summaryrefslogtreecommitdiff
path: root/chromium/third_party/skia/src/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/skia/src/gpu')
-rw-r--r--chromium/third_party/skia/src/gpu/GrAHardwareBufferUtils.cpp1
-rw-r--r--chromium/third_party/skia/src/gpu/GrAppliedClip.h21
-rw-r--r--chromium/third_party/skia/src/gpu/GrBackendSurface.cpp124
-rw-r--r--chromium/third_party/skia/src/gpu/GrBackendSurfaceMutableStateImpl.h58
-rw-r--r--chromium/third_party/skia/src/gpu/GrBackendUtils.h85
-rw-r--r--chromium/third_party/skia/src/gpu/GrBlockAllocator.h2
-rw-r--r--chromium/third_party/skia/src/gpu/GrBlurUtils.cpp35
-rw-r--r--chromium/third_party/skia/src/gpu/GrBlurUtils.h4
-rw-r--r--chromium/third_party/skia/src/gpu/GrCaps.cpp37
-rw-r--r--chromium/third_party/skia/src/gpu/GrCaps.h22
-rw-r--r--chromium/third_party/skia/src/gpu/GrClip.h29
-rw-r--r--chromium/third_party/skia/src/gpu/GrClipStackClip.cpp24
-rw-r--r--chromium/third_party/skia/src/gpu/GrClipStackClip.h19
-rw-r--r--chromium/third_party/skia/src/gpu/GrColorInfo.cpp19
-rw-r--r--chromium/third_party/skia/src/gpu/GrColorInfo.h9
-rw-r--r--chromium/third_party/skia/src/gpu/GrColorSpaceXform.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/GrContext.cpp262
-rw-r--r--chromium/third_party/skia/src/gpu/GrContextPriv.cpp7
-rw-r--r--chromium/third_party/skia/src/gpu/GrContextPriv.h2
-rw-r--r--chromium/third_party/skia/src/gpu/GrContextThreadSafeProxy.cpp69
-rw-r--r--chromium/third_party/skia/src/gpu/GrContextThreadSafeProxyPriv.h24
-rw-r--r--chromium/third_party/skia/src/gpu/GrContext_Base.cpp50
-rw-r--r--chromium/third_party/skia/src/gpu/GrCopyRenderTask.cpp18
-rw-r--r--chromium/third_party/skia/src/gpu/GrCopyRenderTask.h8
-rw-r--r--chromium/third_party/skia/src/gpu/GrDDLContext.cpp25
-rw-r--r--chromium/third_party/skia/src/gpu/GrDataUtils.cpp13
-rw-r--r--chromium/third_party/skia/src/gpu/GrDefaultGeoProcFactory.cpp37
-rw-r--r--chromium/third_party/skia/src/gpu/GrDrawingManager.cpp259
-rw-r--r--chromium/third_party/skia/src/gpu/GrDrawingManager.h64
-rw-r--r--chromium/third_party/skia/src/gpu/GrDynamicAtlas.cpp61
-rw-r--r--chromium/third_party/skia/src/gpu/GrDynamicAtlas.h22
-rw-r--r--chromium/third_party/skia/src/gpu/GrFPArgs.h9
-rw-r--r--chromium/third_party/skia/src/gpu/GrFixedClip.cpp53
-rw-r--r--chromium/third_party/skia/src/gpu/GrFixedClip.h22
-rw-r--r--chromium/third_party/skia/src/gpu/GrFragmentProcessor.cpp130
-rw-r--r--chromium/third_party/skia/src/gpu/GrFragmentProcessor.h67
-rw-r--r--chromium/third_party/skia/src/gpu/GrGpu.cpp64
-rw-r--r--chromium/third_party/skia/src/gpu/GrGpu.h60
-rw-r--r--chromium/third_party/skia/src/gpu/GrHashMapWithCache.h84
-rw-r--r--chromium/third_party/skia/src/gpu/GrImageContext.cpp18
-rw-r--r--chromium/third_party/skia/src/gpu/GrLegacyDirectContext.cpp105
-rw-r--r--chromium/third_party/skia/src/gpu/GrOnFlushResourceProvider.cpp4
-rw-r--r--chromium/third_party/skia/src/gpu/GrOpFlushState.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/GrOpsRenderPass.cpp14
-rw-r--r--chromium/third_party/skia/src/gpu/GrOpsRenderPass.h18
-rw-r--r--chromium/third_party/skia/src/gpu/GrOpsTask.cpp64
-rw-r--r--chromium/third_party/skia/src/gpu/GrOpsTask.h25
-rw-r--r--chromium/third_party/skia/src/gpu/GrPathRenderer.h2
-rw-r--r--chromium/third_party/skia/src/gpu/GrPathRendererChain.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/GrPersistentCacheUtils.h59
-rw-r--r--chromium/third_party/skia/src/gpu/GrPrimitiveProcessor.h17
-rw-r--r--chromium/third_party/skia/src/gpu/GrProcessor.h6
-rw-r--r--chromium/third_party/skia/src/gpu/GrProcessorSet.cpp3
-rw-r--r--chromium/third_party/skia/src/gpu/GrProgramInfo.h1
-rw-r--r--chromium/third_party/skia/src/gpu/GrProxyProvider.cpp83
-rw-r--r--chromium/third_party/skia/src/gpu/GrProxyProvider.h18
-rw-r--r--chromium/third_party/skia/src/gpu/GrRecordingContext.cpp61
-rw-r--r--chromium/third_party/skia/src/gpu/GrRecordingContextPriv.h5
-rw-r--r--chromium/third_party/skia/src/gpu/GrRectanizer.h44
-rw-r--r--chromium/third_party/skia/src/gpu/GrRectanizerPow2.cpp59
-rw-r--r--chromium/third_party/skia/src/gpu/GrRectanizerPow2.h83
-rw-r--r--chromium/third_party/skia/src/gpu/GrRectanizerSkyline.cpp5
-rw-r--r--chromium/third_party/skia/src/gpu/GrRectanizerSkyline.h30
-rw-r--r--chromium/third_party/skia/src/gpu/GrReducedClip.cpp138
-rw-r--r--chromium/third_party/skia/src/gpu/GrReducedClip.h15
-rw-r--r--chromium/third_party/skia/src/gpu/GrRenderTargetContext.cpp565
-rw-r--r--chromium/third_party/skia/src/gpu/GrRenderTargetContext.h105
-rw-r--r--chromium/third_party/skia/src/gpu/GrRenderTargetContextPriv.h21
-rw-r--r--chromium/third_party/skia/src/gpu/GrRenderTargetProxy.h2
-rw-r--r--chromium/third_party/skia/src/gpu/GrRenderTask.cpp77
-rw-r--r--chromium/third_party/skia/src/gpu/GrRenderTask.h44
-rw-r--r--chromium/third_party/skia/src/gpu/GrResourceCache.cpp3
-rw-r--r--chromium/third_party/skia/src/gpu/GrResourceCache.h2
-rw-r--r--chromium/third_party/skia/src/gpu/GrResourceProvider.cpp3
-rw-r--r--chromium/third_party/skia/src/gpu/GrRingBuffer.cpp91
-rw-r--r--chromium/third_party/skia/src/gpu/GrRingBuffer.h72
-rw-r--r--chromium/third_party/skia/src/gpu/GrSWMaskHelper.h1
-rw-r--r--chromium/third_party/skia/src/gpu/GrScissorState.h65
-rw-r--r--chromium/third_party/skia/src/gpu/GrShaderCaps.cpp8
-rw-r--r--chromium/third_party/skia/src/gpu/GrShaderCaps.h14
-rw-r--r--chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp23
-rw-r--r--chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.h8
-rw-r--r--chromium/third_party/skia/src/gpu/GrStencilClip.h24
-rw-r--r--chromium/third_party/skia/src/gpu/GrStencilMaskHelper.cpp15
-rw-r--r--chromium/third_party/skia/src/gpu/GrStencilMaskHelper.h3
-rw-r--r--chromium/third_party/skia/src/gpu/GrSurface.cpp3
-rw-r--r--chromium/third_party/skia/src/gpu/GrSurfaceContext.cpp133
-rw-r--r--chromium/third_party/skia/src/gpu/GrSurfaceContext.h18
-rw-r--r--chromium/third_party/skia/src/gpu/GrSurfaceProxy.cpp20
-rw-r--r--chromium/third_party/skia/src/gpu/GrSurfaceProxy.h14
-rw-r--r--chromium/third_party/skia/src/gpu/GrTextureProxy.cpp21
-rw-r--r--chromium/third_party/skia/src/gpu/GrTextureProxy.h22
-rw-r--r--chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.cpp16
-rw-r--r--chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.h9
-rw-r--r--chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.cpp49
-rw-r--r--chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.h10
-rw-r--r--chromium/third_party/skia/src/gpu/GrTransferFromRenderTask.h2
-rw-r--r--chromium/third_party/skia/src/gpu/GrTriangulator.cpp4
-rw-r--r--chromium/third_party/skia/src/gpu/GrUniformDataManager.cpp319
-rw-r--r--chromium/third_party/skia/src/gpu/GrUniformDataManager.h77
-rw-r--r--chromium/third_party/skia/src/gpu/GrWaitRenderTask.cpp13
-rw-r--r--chromium/third_party/skia/src/gpu/GrWaitRenderTask.h14
-rw-r--r--chromium/third_party/skia/src/gpu/GrYUVProvider.cpp3
-rw-r--r--chromium/third_party/skia/src/gpu/SkGpuDevice.cpp94
-rw-r--r--chromium/third_party/skia/src/gpu/SkGpuDevice.h9
-rw-r--r--chromium/third_party/skia/src/gpu/SkGpuDevice_drawTexture.cpp36
-rw-r--r--chromium/third_party/skia/src/gpu/SkGr.cpp173
-rw-r--r--chromium/third_party/skia/src/gpu/ccpr/GrCCAtlas.cpp8
-rw-r--r--chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.cpp10
-rw-r--r--chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.h11
-rw-r--r--chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.cpp98
-rw-r--r--chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.h9
-rw-r--r--chromium/third_party/skia/src/gpu/ccpr/GrCCFiller.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.cpp17
-rw-r--r--chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.h5
-rw-r--r--chromium/third_party/skia/src/gpu/ccpr/GrCCPerFlushResources.cpp11
-rw-r--r--chromium/third_party/skia/src/gpu/ccpr/GrCCStroker.cpp12
-rw-r--r--chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp20
-rw-r--r--chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.h4
-rw-r--r--chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer_none.cpp4
-rw-r--r--chromium/third_party/skia/src/gpu/ccpr/GrGSCoverageProcessor.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/ccpr/GrVSCoverageProcessor.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DAttachmentViewManager.cpp110
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DAttachmentViewManager.h68
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.cpp41
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.h2
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.cpp25
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.h4
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.cpp220
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.h96
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DConstantRingBuffer.cpp30
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DConstantRingBuffer.h33
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DCpuDescriptorManager.cpp158
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DCpuDescriptorManager.h89
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.cpp13
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.h64
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorTableManager.cpp150
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorTableManager.h123
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.cpp222
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.h24
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.cpp164
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.h33
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.cpp518
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.h96
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp578
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.h13
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateDataManager.cpp41
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateDataManager.h34
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.cpp20
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.h23
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.cpp135
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.h52
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.cpp14
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.h6
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.cpp11
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.h11
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.cpp36
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.h13
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.cpp58
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.h16
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.cpp18
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.h3
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.cpp8
-rw-r--r--chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.h5
-rw-r--r--chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.cpp19
-rw-r--r--chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.h13
-rw-r--r--chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.cpp23
-rw-r--r--chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.h3
-rw-r--r--chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.cpp29
-rw-r--r--chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.h4
-rw-r--r--chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.cpp39
-rw-r--r--chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.h2
-rw-r--r--chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.cpp16
-rw-r--r--chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.h1
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrAARectEffect.fp11
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrAlphaThresholdFragmentProcessor.fp65
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrBezierEffect.cpp260
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrBezierEffect.h49
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.cpp7
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrBitmapTextGeoProc.cpp23
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp4
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrCircleBlurFragmentProcessor.fp66
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrCircleEffect.fp33
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrClampFragmentProcessor.fp20
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrColorMatrixFragmentProcessor.fp23
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrConfigConversionEffect.fp10
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrConstColorProcessor.fp55
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.cpp60
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.h28
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrDeviceSpaceEffect.fp12
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrDistanceFieldGeoProc.cpp81
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrEllipseEffect.fp35
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp71
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h19
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrHSLToRGBFilterEffect.fp13
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrLumaColorFilterEffect.fp13
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrMagnifierEffect.fp38
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.cpp72
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.h48
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.cpp59
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.fp25
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.h (renamed from chromium/third_party/skia/src/gpu/effects/generated/GrMatrixEffect.h)43
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrOvalEffect.cpp17
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrOvalEffect.h5
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrPremulInputFragmentProcessor.fp21
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrRGBToHSLFilterEffect.fp10
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrRRectBlurEffect.fp126
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrRRectEffect.cpp207
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrRRectEffect.h8
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrRectBlurEffect.fp147
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrShadowGeoProc.cpp11
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrSkSLFP.cpp10
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrTextureEffect.cpp261
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrTextureEffect.h29
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrXfermodeFragmentProcessor.cpp12
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp9
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.cpp66
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.h26
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp87
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.h43
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp31
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.h19
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp113
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.h35
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.cpp51
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.h32
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.cpp29
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.h30
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp42
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h33
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.cpp32
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.h10
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.cpp14
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.h14
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.cpp57
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.h64
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.cpp40
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.h18
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.cpp84
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.h38
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp29
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.h26
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp22
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.h26
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.cpp110
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.h21
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrMatrixEffect.cpp69
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.cpp41
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.h10
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp23
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h7
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrPremulInputFragmentProcessor.cpp50
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrPremulInputFragmentProcessor.h41
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp34
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.h26
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.cpp95
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.h67
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.cpp159
-rw-r--r--chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.h50
-rw-r--r--chromium/third_party/skia/src/gpu/geometry/GrPathUtils.cpp3
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLBuffer.cpp63
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLCaps.cpp154
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLCaps.h4
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLDefines.h3
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLGpu.cpp403
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLGpu.h79
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLInterfaceAutogen.cpp48
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.cpp11
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.h5
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLProgram.cpp44
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLProgram.h46
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLUtil.cpp107
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLUtil.h30
-rw-r--r--chromium/third_party/skia/src/gpu/gl/builders/GrGLProgramBuilder.cpp108
-rw-r--r--chromium/third_party/skia/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp25
-rw-r--r--chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.cpp184
-rw-r--r--chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.h85
-rw-r--r--chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.cpp7
-rw-r--r--chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.h10
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/GrGradientShader.cpp8
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/GrTextureGradientColorizer.fp8
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.cpp40
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.h10
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.cpp14
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.h4
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.cpp4
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.h4
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.cpp7
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.h4
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.cpp10
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.h4
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.cpp13
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.h4
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.cpp29
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.h20
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.cpp49
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.h10
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.cpp106
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.h4
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.cpp57
-rw-r--r--chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.h4
-rw-r--r--chromium/third_party/skia/src/gpu/mock/GrMockCaps.h15
-rw-r--r--chromium/third_party/skia/src/gpu/mock/GrMockGpu.cpp3
-rw-r--r--chromium/third_party/skia/src/gpu/mock/GrMockGpu.h5
-rw-r--r--chromium/third_party/skia/src/gpu/mock/GrMockOpsRenderPass.h6
-rw-r--r--chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.h4
-rw-r--r--chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.mm32
-rw-r--r--chromium/third_party/skia/src/gpu/mtl/GrMtlCppUtil.h5
-rw-r--r--chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.h7
-rw-r--r--chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.mm11
-rw-r--r--chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.h5
-rw-r--r--chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.mm11
-rw-r--r--chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.h4
-rw-r--r--chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.mm33
-rw-r--r--chromium/third_party/skia/src/gpu/mtl/GrMtlResourceProvider.h4
-rw-r--r--chromium/third_party/skia/src/gpu/mtl/GrMtlUtil.mm7
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrAAConvexPathRenderer.cpp26
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrAAHairLinePathRenderer.cpp13
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.cpp232
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.h14
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrClearOp.cpp88
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrClearOp.h79
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrClearStencilClipOp.cpp28
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrClearStencilClipOp.h72
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrDashLinePathRenderer.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrDashOp.cpp97
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.cpp12
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.h2
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrDrawVerticesOp.cpp40
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrFillRRectOp.cpp16
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrFillRectOp.cpp4
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrFillRectOp.h2
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrLatticeOp.cpp9
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrMeshDrawOp.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrOvalOpFactory.cpp97
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrQuadPerEdgeAA.cpp18
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrSmallPathRenderer.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp18
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrTextureOp.cpp145
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrTextureOp.h2
-rw-r--r--chromium/third_party/skia/src/gpu/ops/GrTriangulatingPathRenderer.cpp11
-rw-r--r--chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.cpp20
-rw-r--r--chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.h28
-rw-r--r--chromium/third_party/skia/src/gpu/tessellate/GrFillPathShader.cpp7
-rw-r--r--chromium/third_party/skia/src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h52
-rw-r--r--chromium/third_party/skia/src/gpu/tessellate/GrResolveLevelCounter.h73
-rw-r--r--chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.cpp131
-rw-r--r--chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.h120
-rw-r--r--chromium/third_party/skia/src/gpu/tessellate/GrStrokeGeometry.cpp583
-rw-r--r--chromium/third_party/skia/src/gpu/tessellate/GrStrokeGeometry.h177
-rw-r--r--chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.cpp425
-rw-r--r--chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.h85
-rw-r--r--chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.cpp214
-rw-r--r--chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.h35
-rw-r--r--chromium/third_party/skia/src/gpu/tessellate/GrWangsFormula.h42
-rw-r--r--chromium/third_party/skia/src/gpu/text/GrAtlasManager.cpp151
-rw-r--r--chromium/third_party/skia/src/gpu/text/GrAtlasManager.h29
-rw-r--r--chromium/third_party/skia/src/gpu/text/GrSDFTOptions.cpp167
-rw-r--r--chromium/third_party/skia/src/gpu/text/GrSDFTOptions.h38
-rw-r--r--chromium/third_party/skia/src/gpu/text/GrTextBlob.cpp1142
-rw-r--r--chromium/third_party/skia/src/gpu/text/GrTextBlob.h262
-rw-r--r--chromium/third_party/skia/src/gpu/text/GrTextBlobCache.cpp131
-rw-r--r--chromium/third_party/skia/src/gpu/text/GrTextBlobCache.h171
-rw-r--r--chromium/third_party/skia/src/gpu/text/GrTextContext.cpp284
-rw-r--r--chromium/third_party/skia/src/gpu/text/GrTextContext.h101
-rw-r--r--chromium/third_party/skia/src/gpu/text/GrTextTarget.h4
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.cpp42
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.h17
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkCaps.cpp41
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkCaps.h5
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkCommandBuffer.cpp6
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkGpu.cpp326
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkGpu.h57
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkImage.cpp142
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkImage.h62
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkMemory.cpp93
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkMemory.h4
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.cpp76
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.h10
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.cpp66
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.h4
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.cpp307
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.h56
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.h1
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.cpp208
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.h64
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.cpp15
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.h9
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.h4
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkSemaphore.cpp1
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.cpp16
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.h2
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkTexture.cpp44
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkTexture.h11
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.cpp143
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.h27
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkTypesPriv.cpp36
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkUtil.cpp9
-rw-r--r--chromium/third_party/skia/src/gpu/vk/GrVkUtil.h49
401 files changed, 13561 insertions, 8642 deletions
diff --git a/chromium/third_party/skia/src/gpu/GrAHardwareBufferUtils.cpp b/chromium/third_party/skia/src/gpu/GrAHardwareBufferUtils.cpp
index b701dafb3bf..badb8eee5a6 100644
--- a/chromium/third_party/skia/src/gpu/GrAHardwareBufferUtils.cpp
+++ b/chromium/third_party/skia/src/gpu/GrAHardwareBufferUtils.cpp
@@ -486,6 +486,7 @@ static GrBackendTexture make_vk_backend_texture(
// "foreign" device we can leave them as external.
imageInfo.fCurrentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
imageInfo.fYcbcrConversionInfo = *ycbcrConversion;
+ imageInfo.fSharingMode = imageCreateInfo.sharingMode;
*deleteProc = delete_vk_image;
*updateProc = update_vk_image;
diff --git a/chromium/third_party/skia/src/gpu/GrAppliedClip.h b/chromium/third_party/skia/src/gpu/GrAppliedClip.h
index 594a627987d..75e614a659a 100644
--- a/chromium/third_party/skia/src/gpu/GrAppliedClip.h
+++ b/chromium/third_party/skia/src/gpu/GrAppliedClip.h
@@ -22,11 +22,19 @@
class GrAppliedHardClip {
public:
static const GrAppliedHardClip& Disabled() {
- static GrAppliedHardClip kDisabled;
+ // The size doesn't really matter here since it's returned as const& so an actual scissor
+ // will never be set on it, and applied clips are not used to query or bounds test like
+ // the GrClip is.
+ static const GrAppliedHardClip kDisabled({1 << 29, 1 << 29});
return kDisabled;
}
- GrAppliedHardClip() = default;
+ GrAppliedHardClip(const SkISize& rtDims) : fScissorState(rtDims) {}
+ GrAppliedHardClip(const SkISize& logicalRTDims, const SkISize& backingStoreDims)
+ : fScissorState(backingStoreDims) {
+ fScissorState.set(SkIRect::MakeSize(logicalRTDims));
+ }
+
GrAppliedHardClip(GrAppliedHardClip&& that) = default;
GrAppliedHardClip(const GrAppliedHardClip&) = delete;
@@ -81,7 +89,14 @@ private:
*/
class GrAppliedClip {
public:
- GrAppliedClip() = default;
+ static GrAppliedClip Disabled() {
+ return GrAppliedClip({1 << 29, 1 << 29});
+ }
+
+ GrAppliedClip(const SkISize& rtDims) : fHardClip(rtDims) {}
+ GrAppliedClip(const SkISize& logicalRTDims, const SkISize& backingStoreDims)
+ : fHardClip(logicalRTDims, backingStoreDims) {}
+
GrAppliedClip(GrAppliedClip&& that) = default;
GrAppliedClip(const GrAppliedClip&) = delete;
diff --git a/chromium/third_party/skia/src/gpu/GrBackendSurface.cpp b/chromium/third_party/skia/src/gpu/GrBackendSurface.cpp
index 8f07bb1ee22..a1e0203ff46 100644
--- a/chromium/third_party/skia/src/gpu/GrBackendSurface.cpp
+++ b/chromium/third_party/skia/src/gpu/GrBackendSurface.cpp
@@ -7,6 +7,7 @@
#include "include/gpu/GrBackendSurface.h"
+#include "src/gpu/GrBackendSurfaceMutableStateImpl.h"
#include "src/gpu/gl/GrGLUtil.h"
#ifdef SK_DAWN
@@ -386,6 +387,8 @@ SkString GrBackendFormat::toStr() const {
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////
+GrBackendTexture::GrBackendTexture() : fIsValid(false) {}
+
#ifdef SK_DAWN
GrBackendTexture::GrBackendTexture(int width,
int height,
@@ -398,12 +401,24 @@ GrBackendTexture::GrBackendTexture(int width,
, fDawnInfo(dawnInfo) {}
#endif
-GrBackendTexture::GrBackendTexture(int width, int height, const GrVkImageInfo& vkInfo)
#ifdef SK_VULKAN
+GrBackendTexture::GrBackendTexture(int width, int height, const GrVkImageInfo& vkInfo)
: GrBackendTexture(width, height, vkInfo,
- sk_sp<GrVkImageLayout>(new GrVkImageLayout(vkInfo.fImageLayout))) {}
-#else
- : fIsValid(false) {}
+ sk_sp<GrBackendSurfaceMutableStateImpl>(
+ new GrBackendSurfaceMutableStateImpl(
+ vkInfo.fImageLayout, vkInfo.fCurrentQueueFamily))) {}
+
+GrBackendTexture::GrBackendTexture(int width,
+ int height,
+ const GrVkImageInfo& vkInfo,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState)
+ : fIsValid(true)
+ , fWidth(width)
+ , fHeight(height)
+ , fMipMapped(GrMipMapped(vkInfo.fLevelCount > 1))
+ , fBackend(GrBackendApi::kVulkan)
+ , fVkInfo(vkInfo)
+ , fMutableState(std::move(mutableState)) {}
#endif
#ifdef SK_GL
@@ -427,19 +442,6 @@ sk_sp<GrGLTextureParameters> GrBackendTexture::getGLTextureParams() const {
}
#endif
-#ifdef SK_VULKAN
-GrBackendTexture::GrBackendTexture(int width,
- int height,
- const GrVkImageInfo& vkInfo,
- sk_sp<GrVkImageLayout> layout)
- : fIsValid(true)
- , fWidth(width)
- , fHeight(height)
- , fMipMapped(GrMipMapped(vkInfo.fLevelCount > 1))
- , fBackend(GrBackendApi::kVulkan)
- , fVkInfo(vkInfo, layout.release()) {}
-#endif
-
#ifdef SK_METAL
GrBackendTexture::GrBackendTexture(int width,
int height,
@@ -566,10 +568,15 @@ GrBackendTexture& GrBackendTexture::operator=(const GrBackendTexture& that) {
default:
SK_ABORT("Unknown GrBackend");
}
+ fMutableState = that.fMutableState;
fIsValid = true;
return *this;
}
+sk_sp<GrBackendSurfaceMutableStateImpl> GrBackendTexture::getMutableState() const {
+ return fMutableState;
+}
+
#ifdef SK_DAWN
bool GrBackendTexture::getDawnTextureInfo(GrDawnTextureInfo* outInfo) const {
if (this->isValid() && GrBackendApi::kDawn == fBackend) {
@@ -583,7 +590,7 @@ bool GrBackendTexture::getDawnTextureInfo(GrDawnTextureInfo* outInfo) const {
bool GrBackendTexture::getVkImageInfo(GrVkImageInfo* outInfo) const {
#ifdef SK_VULKAN
if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
- *outInfo = fVkInfo.snapImageInfo();
+ *outInfo = fVkInfo.snapImageInfo(fMutableState.get());
return true;
}
#endif
@@ -593,20 +600,11 @@ bool GrBackendTexture::getVkImageInfo(GrVkImageInfo* outInfo) const {
void GrBackendTexture::setVkImageLayout(VkImageLayout layout) {
#ifdef SK_VULKAN
if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
- fVkInfo.setImageLayout(layout);
+ fMutableState->setImageLayout(layout);
}
#endif
}
-#ifdef SK_VULKAN
-sk_sp<GrVkImageLayout> GrBackendTexture::getGrVkImageLayout() const {
- if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
- return fVkInfo.getGrVkImageLayout();
- }
- return nullptr;
-}
-#endif
-
#ifdef SK_METAL
bool GrBackendTexture::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
if (this->isValid() && GrBackendApi::kMetal == fBackend) {
@@ -674,6 +672,10 @@ bool GrBackendTexture::getMockTextureInfo(GrMockTextureInfo* outInfo) const {
return false;
}
+void GrBackendTexture::setMutableState(const GrBackendSurfaceMutableState& state) {
+ fMutableState->set(state);
+}
+
bool GrBackendTexture::isProtected() const {
if (!this->isValid() || this->backend() != GrBackendApi::kVulkan) {
return false;
@@ -695,7 +697,8 @@ bool GrBackendTexture::isSameTexture(const GrBackendTexture& that) {
#endif
#ifdef SK_VULKAN
case GrBackendApi::kVulkan:
- return fVkInfo.snapImageInfo().fImage == that.fVkInfo.snapImageInfo().fImage;
+ return fVkInfo.snapImageInfo(fMutableState.get()).fImage ==
+ that.fVkInfo.snapImageInfo(that.fMutableState.get()).fImage;
#endif
#ifdef SK_METAL
case GrBackendApi::kMetal:
@@ -703,7 +706,13 @@ bool GrBackendTexture::isSameTexture(const GrBackendTexture& that) {
#endif
#ifdef SK_DIRECT3D
case GrBackendApi::kDirect3D:
- return false; //TODO
+ return fD3DInfo.snapTextureResourceInfo().fResource ==
+ that.fD3DInfo.snapTextureResourceInfo().fResource;
+#endif
+#ifdef SK_DAWN
+ case GrBackendApi::kDawn: {
+ return this->fDawnInfo.fTexture.Get() == that.fDawnInfo.fTexture.Get();
+ }
#endif
case GrBackendApi::kMock:
return fMockInfo.id() == that.fMockInfo.id();
@@ -723,7 +732,7 @@ GrBackendFormat GrBackendTexture::getBackendFormat() const {
#endif
#ifdef SK_VULKAN
case GrBackendApi::kVulkan: {
- auto info = fVkInfo.snapImageInfo();
+ auto info = fVkInfo.snapImageInfo(fMutableState.get());
if (info.fYcbcrConversionInfo.isValid()) {
SkASSERT(info.fFormat == info.fYcbcrConversionInfo.fFormat);
return GrBackendFormat::MakeVk(info.fYcbcrConversionInfo);
@@ -769,6 +778,12 @@ bool GrBackendTexture::TestingOnly_Equals(const GrBackendTexture& t0, const GrBa
return false;
}
+ // For our tests when checking equality we are assuming the both backendTexture objects will
+ // be using the same mutable state object.
+ if (t0.fMutableState != t1.fMutableState) {
+ return false;
+ }
+
switch (t0.fBackend) {
#ifdef SK_GL
case GrBackendApi::kOpenGL:
@@ -800,6 +815,9 @@ bool GrBackendTexture::TestingOnly_Equals(const GrBackendTexture& t0, const GrBa
////////////////////////////////////////////////////////////////////////////////////////////////////
+GrBackendRenderTarget::GrBackendRenderTarget() : fIsValid(false) {}
+
+
#ifdef SK_DAWN
GrBackendRenderTarget::GrBackendRenderTarget(int width,
int height,
@@ -816,6 +834,7 @@ GrBackendRenderTarget::GrBackendRenderTarget(int width,
, fDawnInfo(dawnInfo) {}
#endif
+#ifdef SK_VULKAN
GrBackendRenderTarget::GrBackendRenderTarget(int width,
int height,
int sampleCnt,
@@ -830,26 +849,24 @@ GrBackendRenderTarget::GrBackendRenderTarget(int width,
int height,
int sampleCnt,
const GrVkImageInfo& vkInfo)
-#ifdef SK_VULKAN
: GrBackendRenderTarget(width, height, sampleCnt, vkInfo,
- sk_sp<GrVkImageLayout>(new GrVkImageLayout(vkInfo.fImageLayout))) {}
-#else
- : fIsValid(false) {}
-#endif
+ sk_sp<GrBackendSurfaceMutableStateImpl>(
+ new GrBackendSurfaceMutableStateImpl(
+ vkInfo.fImageLayout, vkInfo.fCurrentQueueFamily))) {}
-#ifdef SK_VULKAN
GrBackendRenderTarget::GrBackendRenderTarget(int width,
int height,
int sampleCnt,
const GrVkImageInfo& vkInfo,
- sk_sp<GrVkImageLayout> layout)
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState)
: fIsValid(true)
, fWidth(width)
, fHeight(height)
, fSampleCnt(std::max(1, sampleCnt))
, fStencilBits(0) // We always create stencil buffers internally for vulkan
, fBackend(GrBackendApi::kVulkan)
- , fVkInfo(vkInfo, layout.release()) {}
+ , fVkInfo(vkInfo)
+ , fMutableState(mutableState) {}
#endif
#ifdef SK_METAL
@@ -926,6 +943,11 @@ void GrBackendRenderTarget::cleanup() {
fVkInfo.cleanup();
}
#endif
+#ifdef SK_DIRECT3D
+ if (this->isValid() && GrBackendApi::kDirect3D == fBackend) {
+ fD3DInfo.cleanup();
+ }
+#endif
}
GrBackendRenderTarget::GrBackendRenderTarget(const GrBackendRenderTarget& that) : fIsValid(false) {
@@ -979,10 +1001,15 @@ GrBackendRenderTarget& GrBackendRenderTarget::operator=(const GrBackendRenderTar
default:
SK_ABORT("Unknown GrBackend");
}
+ fMutableState = that.fMutableState;
fIsValid = that.fIsValid;
return *this;
}
+sk_sp<GrBackendSurfaceMutableStateImpl> GrBackendRenderTarget::getMutableState() const {
+ return fMutableState;
+}
+
#ifdef SK_DAWN
bool GrBackendRenderTarget::getDawnRenderTargetInfo(GrDawnRenderTargetInfo* outInfo) const {
if (this->isValid() && GrBackendApi::kDawn == fBackend) {
@@ -996,7 +1023,7 @@ bool GrBackendRenderTarget::getDawnRenderTargetInfo(GrDawnRenderTargetInfo* outI
bool GrBackendRenderTarget::getVkImageInfo(GrVkImageInfo* outInfo) const {
#ifdef SK_VULKAN
if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
- *outInfo = fVkInfo.snapImageInfo();
+ *outInfo = fVkInfo.snapImageInfo(fMutableState.get());
return true;
}
#endif
@@ -1006,20 +1033,11 @@ bool GrBackendRenderTarget::getVkImageInfo(GrVkImageInfo* outInfo) const {
void GrBackendRenderTarget::setVkImageLayout(VkImageLayout layout) {
#ifdef SK_VULKAN
if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
- fVkInfo.setImageLayout(layout);
+ fMutableState->setImageLayout(layout);
}
#endif
}
-#ifdef SK_VULKAN
-sk_sp<GrVkImageLayout> GrBackendRenderTarget::getGrVkImageLayout() const {
- if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
- return fVkInfo.getGrVkImageLayout();
- }
- return nullptr;
-}
-#endif
-
#ifdef SK_METAL
bool GrBackendRenderTarget::getMtlTextureInfo(GrMtlTextureInfo* outInfo) const {
if (this->isValid() && GrBackendApi::kMetal == fBackend) {
@@ -1074,7 +1092,7 @@ GrBackendFormat GrBackendRenderTarget::getBackendFormat() const {
#endif
#ifdef SK_VULKAN
case GrBackendApi::kVulkan: {
- auto info = fVkInfo.snapImageInfo();
+ auto info = fVkInfo.snapImageInfo(fMutableState.get());
if (info.fYcbcrConversionInfo.isValid()) {
SkASSERT(info.fFormat == info.fYcbcrConversionInfo.fFormat);
return GrBackendFormat::MakeVk(info.fYcbcrConversionInfo);
@@ -1117,6 +1135,10 @@ bool GrBackendRenderTarget::getMockRenderTargetInfo(GrMockRenderTargetInfo* outI
return false;
}
+void GrBackendRenderTarget::setMutableState(const GrBackendSurfaceMutableState& state) {
+ fMutableState->set(state);
+}
+
bool GrBackendRenderTarget::isProtected() const {
if (!this->isValid() || this->backend() != GrBackendApi::kVulkan) {
return false;
diff --git a/chromium/third_party/skia/src/gpu/GrBackendSurfaceMutableStateImpl.h b/chromium/third_party/skia/src/gpu/GrBackendSurfaceMutableStateImpl.h
new file mode 100644
index 00000000000..3e3bc92f4e4
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrBackendSurfaceMutableStateImpl.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrBackendSurfaceMutableStateImpl_DEFINED
+#define GrBackendSurfaceMutableStateImpl_DEFINED
+
+#include "include/core/SkRefCnt.h"
+#include "include/gpu/GrBackendSurfaceMutableState.h"
+
+class GrBackendSurfaceMutableStateImpl : public SkRefCnt {
+public:
+#ifdef SK_VULKAN
+ GrBackendSurfaceMutableStateImpl(VkImageLayout layout, uint32_t queueFamilyIndex)
+ : fState(layout, queueFamilyIndex) {}
+
+ GrBackendSurfaceMutableStateImpl(GrVkSharedImageInfo sharedInfo)
+ : fState(sharedInfo.getImageLayout(), sharedInfo.getQueueFamilyIndex()) {}
+#endif
+
+ void set(const GrBackendSurfaceMutableState& state) { fState = state; }
+
+#ifdef SK_VULKAN
+ VkImageLayout getImageLayout() const {
+ SkASSERT(fState.fBackend == GrBackend::kVulkan);
+ return fState.fVkState.getImageLayout();
+ }
+
+ void setImageLayout(VkImageLayout layout) {
+ SkASSERT(fState.fBackend == GrBackend::kVulkan);
+ fState.fVkState.setImageLayout(layout);
+ }
+
+ uint32_t getQueueFamilyIndex() const {
+ SkASSERT(fState.fBackend == GrBackend::kVulkan);
+ return fState.fVkState.getQueueFamilyIndex();
+ }
+
+ void setQueueFamilyIndex(uint32_t queueFamilyIndex) {
+ SkASSERT(fState.fBackend == GrBackend::kVulkan);
+ fState.fVkState.setQueueFamilyIndex(queueFamilyIndex);
+ }
+
+ const GrVkSharedImageInfo& getVkSharedImageInfo() {
+ SkASSERT(fState.fBackend == GrBackend::kVulkan);
+ return fState.fVkState;
+ }
+#endif
+
+
+private:
+ GrBackendSurfaceMutableState fState;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrBackendUtils.h b/chromium/third_party/skia/src/gpu/GrBackendUtils.h
new file mode 100644
index 00000000000..cfbcb0ea302
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrBackendUtils.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrBackendUtils_DEFINED
+#define GrBackendUtils_DEFINED
+
+#include "include/core/SkImage.h"
+
+#include "include/gpu/GrBackendSurface.h"
+
+#ifdef SK_METAL
+#include "src/gpu/mtl/GrMtlCppUtil.h"
+#endif
+
+static SkImage::CompressionType GrBackendFormatToCompressionType(const GrBackendFormat& format) {
+ switch (format.backend()) {
+ case GrBackendApi::kOpenGL: {
+#ifdef SK_GL
+ GrGLFormat glFormat = format.asGLFormat();
+ switch (glFormat) {
+ case GrGLFormat::kCOMPRESSED_ETC1_RGB8:
+ case GrGLFormat::kCOMPRESSED_RGB8_ETC2:
+ return SkImage::CompressionType::kETC2_RGB8_UNORM;
+ case GrGLFormat::kCOMPRESSED_RGB8_BC1:
+ return SkImage::CompressionType::kBC1_RGB8_UNORM;
+ case GrGLFormat::kCOMPRESSED_RGBA8_BC1:
+ return SkImage::CompressionType::kBC1_RGBA8_UNORM;
+ default:
+ return SkImage::CompressionType::kNone;
+ }
+#endif
+ break;
+ }
+ case GrBackendApi::kVulkan: {
+#ifdef SK_VULKAN
+ VkFormat vkFormat;
+ SkAssertResult(format.asVkFormat(&vkFormat));
+ switch (vkFormat) {
+ case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
+ return SkImage::CompressionType::kETC2_RGB8_UNORM;
+ case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
+ return SkImage::CompressionType::kBC1_RGB8_UNORM;
+ case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
+ return SkImage::CompressionType::kBC1_RGBA8_UNORM;
+ default:
+ return SkImage::CompressionType::kNone;
+ }
+#endif
+ break;
+ }
+ case GrBackendApi::kMetal: {
+#ifdef SK_METAL
+ return GrMtlBackendFormatToCompressionType(format);
+#endif
+ break;
+ }
+ case GrBackendApi::kDirect3D: {
+#ifdef SK_DIRECT3D
+ DXGI_FORMAT dxgiFormat;
+ SkAssertResult(format.asDxgiFormat(&dxgiFormat));
+ switch (dxgiFormat) {
+ case DXGI_FORMAT_BC1_UNORM:
+ return SkImage::CompressionType::kBC1_RGBA8_UNORM;
+ default:
+ return SkImage::CompressionType::kNone;
+ }
+#endif
+ break;
+ }
+ case GrBackendApi::kDawn: {
+ return SkImage::CompressionType::kNone;
+ }
+ case GrBackendApi::kMock: {
+ return format.asMockCompressionType();
+ }
+ }
+ return SkImage::CompressionType::kNone;
+}
+
+#endif
+
diff --git a/chromium/third_party/skia/src/gpu/GrBlockAllocator.h b/chromium/third_party/skia/src/gpu/GrBlockAllocator.h
index fae9dabbf20..b683d7825eb 100644
--- a/chromium/third_party/skia/src/gpu/GrBlockAllocator.h
+++ b/chromium/third_party/skia/src/gpu/GrBlockAllocator.h
@@ -436,7 +436,7 @@ GrBlockAllocator::ByteRange GrBlockAllocator::allocate(size_t size) {
<= std::numeric_limits<int32_t>::max());
if (size > kMaxAllocationSize) {
- SK_ABORT("Allocation too large");
+ SK_ABORT("Allocation too large (%zu bytes requested)", size);
}
int iSize = (int) size;
diff --git a/chromium/third_party/skia/src/gpu/GrBlurUtils.cpp b/chromium/third_party/skia/src/gpu/GrBlurUtils.cpp
index 66c145da008..084e8ef8b98 100644
--- a/chromium/third_party/skia/src/gpu/GrBlurUtils.cpp
+++ b/chromium/third_party/skia/src/gpu/GrBlurUtils.cpp
@@ -43,7 +43,7 @@ static GrSurfaceProxyView find_filtered_mask(GrProxyProvider* provider, const Gr
// is already burnt into the mask this boils down to a rect draw.
// Return true if the mask was successfully drawn.
static bool draw_mask(GrRenderTargetContext* renderTargetContext,
- const GrClip& clip,
+ const GrClip* clip,
const SkMatrix& viewMatrix,
const SkIRect& maskRect,
GrPaint&& paint,
@@ -53,7 +53,7 @@ static bool draw_mask(GrRenderTargetContext* renderTargetContext,
return false;
}
- SkMatrix matrix = SkMatrix::MakeTrans(-SkIntToScalar(maskRect.fLeft),
+ SkMatrix matrix = SkMatrix::Translate(-SkIntToScalar(maskRect.fLeft),
-SkIntToScalar(maskRect.fTop));
matrix.preConcat(viewMatrix);
paint.addCoverageFragmentProcessor(
@@ -70,7 +70,7 @@ static void mask_release_proc(void* addr, void* /*context*/) {
static bool sw_draw_with_mask_filter(GrRecordingContext* context,
GrRenderTargetContext* renderTargetContext,
- const GrClip& clipData,
+ const GrClip* clipData,
const SkMatrix& viewMatrix,
const GrStyledShape& shape,
const SkMaskFilter* filter,
@@ -200,14 +200,13 @@ static std::unique_ptr<GrRenderTargetContext> create_mask_GPU(GrRecordingContext
maskPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);
// setup new clip
- const SkIRect clipRect = SkIRect::MakeWH(maskRect.width(), maskRect.height());
- GrFixedClip clip(clipRect);
+ GrFixedClip clip(rtContext->dimensions(), SkIRect::MakeWH(maskRect.width(), maskRect.height()));
// Draw the mask into maskTexture with the path's integerized top-left at the origin using
// maskPaint.
SkMatrix viewMatrix = origViewMatrix;
viewMatrix.postTranslate(-SkIntToScalar(maskRect.fLeft), -SkIntToScalar(maskRect.fTop));
- rtContext->drawShape(clip, std::move(maskPaint), GrAA::kYes, viewMatrix, shape);
+ rtContext->drawShape(&clip, std::move(maskPaint), GrAA::kYes, viewMatrix, shape);
return rtContext;
}
@@ -239,14 +238,15 @@ static bool get_unclipped_shape_dev_bounds(const GrStyledShape& shape, const SkM
// Gets the shape bounds, the clip bounds, and the intersection (if any). Returns false if there
// is no intersection.
static bool get_shape_and_clip_bounds(GrRenderTargetContext* renderTargetContext,
- const GrClip& clip,
+ const GrClip* clip,
const GrStyledShape& shape,
const SkMatrix& matrix,
SkIRect* unclippedDevShapeBounds,
SkIRect* devClipBounds) {
// compute bounds as intersection of rt size, clip, and path
- *devClipBounds = clip.getConservativeBounds(renderTargetContext->width(),
- renderTargetContext->height());
+ *devClipBounds = clip ? clip->getConservativeBounds()
+ : SkIRect::MakeWH(renderTargetContext->width(),
+ renderTargetContext->height());
if (!get_unclipped_shape_dev_bounds(shape, matrix, unclippedDevShapeBounds)) {
*unclippedDevShapeBounds = SkIRect::MakeEmpty();
@@ -258,7 +258,7 @@ static bool get_shape_and_clip_bounds(GrRenderTargetContext* renderTargetContext
static void draw_shape_with_mask_filter(GrRecordingContext* context,
GrRenderTargetContext* renderTargetContext,
- const GrClip& clip,
+ const GrClip* clip,
GrPaint&& paint,
const SkMatrix& viewMatrix,
const SkMaskFilterBase* maskFilter,
@@ -282,12 +282,8 @@ static void draw_shape_with_mask_filter(GrRecordingContext* context,
shape = tmpShape.get();
}
- if (maskFilter->directFilterMaskGPU(context,
- renderTargetContext,
- std::move(paint),
- clip,
- viewMatrix,
- *shape)) {
+ if (maskFilter->directFilterMaskGPU(context, renderTargetContext, std::move(paint), clip,
+ viewMatrix, *shape)) {
// the mask filter was able to draw itself directly, so there's nothing
// left to do.
return;
@@ -301,8 +297,7 @@ static void draw_shape_with_mask_filter(GrRecordingContext* context,
SkIRect unclippedDevShapeBounds, devClipBounds;
if (!get_shape_and_clip_bounds(renderTargetContext, clip, *shape, viewMatrix,
- &unclippedDevShapeBounds,
- &devClipBounds)) {
+ &unclippedDevShapeBounds, &devClipBounds)) {
// TODO: just cons up an opaque mask here
if (!inverseFilled) {
return;
@@ -439,7 +434,7 @@ static void draw_shape_with_mask_filter(GrRecordingContext* context,
void GrBlurUtils::drawShapeWithMaskFilter(GrRecordingContext* context,
GrRenderTargetContext* renderTargetContext,
- const GrClip& clip,
+ const GrClip* clip,
const GrStyledShape& shape,
GrPaint&& paint,
const SkMatrix& viewMatrix,
@@ -450,7 +445,7 @@ void GrBlurUtils::drawShapeWithMaskFilter(GrRecordingContext* context,
void GrBlurUtils::drawShapeWithMaskFilter(GrRecordingContext* context,
GrRenderTargetContext* renderTargetContext,
- const GrClip& clip,
+ const GrClip* clip,
const SkPaint& paint,
const SkMatrixProvider& matrixProvider,
const GrStyledShape& shape) {
diff --git a/chromium/third_party/skia/src/gpu/GrBlurUtils.h b/chromium/third_party/skia/src/gpu/GrBlurUtils.h
index 45ce4efec6f..fa0be4ef52c 100644
--- a/chromium/third_party/skia/src/gpu/GrBlurUtils.h
+++ b/chromium/third_party/skia/src/gpu/GrBlurUtils.h
@@ -36,7 +36,7 @@ namespace GrBlurUtils {
*/
void drawShapeWithMaskFilter(GrRecordingContext*,
GrRenderTargetContext*,
- const GrClip&,
+ const GrClip*,
const SkPaint&,
const SkMatrixProvider&,
const GrStyledShape&);
@@ -47,7 +47,7 @@ namespace GrBlurUtils {
*/
void drawShapeWithMaskFilter(GrRecordingContext*,
GrRenderTargetContext*,
- const GrClip&,
+ const GrClip*,
const GrStyledShape&,
GrPaint&&,
const SkMatrix& viewMatrix,
diff --git a/chromium/third_party/skia/src/gpu/GrCaps.cpp b/chromium/third_party/skia/src/gpu/GrCaps.cpp
index 43b8996170e..9cd3ea381c1 100644
--- a/chromium/third_party/skia/src/gpu/GrCaps.cpp
+++ b/chromium/third_party/skia/src/gpu/GrCaps.cpp
@@ -8,6 +8,7 @@
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrContextOptions.h"
#include "include/private/GrTypesPriv.h"
+#include "src/gpu/GrBackendUtils.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrSurface.h"
#include "src/gpu/GrSurfaceProxy.h"
@@ -358,9 +359,11 @@ GrCaps::SupportedRead GrCaps::supportedReadPixelsColorType(GrColorType srcColorT
// offset alignment is a multiple of 2 but not 4.
case 2:
read.fOffsetAlignmentForTransferBuffer *= 2;
+ break;
// offset alignment is not a multiple of 2.
default:
read.fOffsetAlignmentForTransferBuffer *= 4;
+ break;
}
}
return read;
@@ -388,3 +391,37 @@ GrBackendFormat GrCaps::getDefaultBackendFormat(GrColorType colorType,
}
return format;
}
+
+bool GrCaps::areColorTypeAndFormatCompatible(GrColorType grCT,
+ const GrBackendFormat& format) const {
+ if (GrColorType::kUnknown == grCT) {
+ return false;
+ }
+
+ SkImage::CompressionType compression = GrBackendFormatToCompressionType(format);
+ if (compression != SkImage::CompressionType::kNone) {
+ return grCT == (SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
+ : GrColorType::kRGBA_8888);
+ }
+
+ return this->onAreColorTypeAndFormatCompatible(grCT, format);
+}
+
+GrSwizzle GrCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
+ SkImage::CompressionType compression = GrBackendFormatToCompressionType(format);
+ if (compression != SkImage::CompressionType::kNone) {
+ if (colorType == GrColorType::kRGB_888x || colorType == GrColorType::kRGBA_8888) {
+ return GrSwizzle::RGBA();
+ }
+ SkDEBUGFAILF("Illegal color type (%d) and compressed format (%d) combination.", colorType,
+ compression);
+ return {};
+ }
+
+ return this->onGetReadSwizzle(format, colorType);
+}
+
+bool GrCaps::isFormatCompressed(const GrBackendFormat& format) const {
+ return GrBackendFormatToCompressionType(format) != SkImage::CompressionType::kNone;
+}
+
diff --git a/chromium/third_party/skia/src/gpu/GrCaps.h b/chromium/third_party/skia/src/gpu/GrCaps.h
index 3ef0c61812a..f81ec565e53 100644
--- a/chromium/third_party/skia/src/gpu/GrCaps.h
+++ b/chromium/third_party/skia/src/gpu/GrCaps.h
@@ -13,6 +13,7 @@
#include "include/core/SkString.h"
#include "include/gpu/GrDriverBugWorkarounds.h"
#include "include/private/GrTypesPriv.h"
+#include "src/core/SkCompressedDataUtils.h"
#include "src/gpu/GrBlend.h"
#include "src/gpu/GrSamplerState.h"
#include "src/gpu/GrShaderCaps.h"
@@ -191,12 +192,7 @@ public:
virtual bool isFormatSRGB(const GrBackendFormat&) const = 0;
- // This will return SkImage::CompressionType::kNone if the backend format is not compressed.
- virtual SkImage::CompressionType compressionType(const GrBackendFormat&) const = 0;
-
- bool isFormatCompressed(const GrBackendFormat& format) const {
- return this->compressionType(format) != SkImage::CompressionType::kNone;
- }
+ bool isFormatCompressed(const GrBackendFormat& format) const;
// Can a texture be made with the GrBackendFormat, and then be bound and sampled in a shader.
virtual bool isFormatTexturable(const GrBackendFormat&) const = 0;
@@ -396,14 +392,7 @@ public:
bool validateSurfaceParams(const SkISize&, const GrBackendFormat&, GrRenderable renderable,
int renderTargetSampleCnt, GrMipMapped) const;
- bool areColorTypeAndFormatCompatible(GrColorType grCT,
- const GrBackendFormat& format) const {
- if (GrColorType::kUnknown == grCT) {
- return false;
- }
-
- return this->onAreColorTypeAndFormatCompatible(grCT, format);
- }
+ bool areColorTypeAndFormatCompatible(GrColorType grCT, const GrBackendFormat& format) const;
/** These are used when creating a new texture internally. */
GrBackendFormat getDefaultBackendFormat(GrColorType, GrRenderable) const;
@@ -420,7 +409,7 @@ public:
* Returns the GrSwizzle to use when sampling or reading back from a texture with the passed in
* GrBackendFormat and GrColorType.
*/
- virtual GrSwizzle getReadSwizzle(const GrBackendFormat&, GrColorType) const = 0;
+ GrSwizzle getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const;
/**
* Returns the GrSwizzle to use when writing colors to a surface with the passed in
@@ -557,6 +546,9 @@ private:
const GrBackendFormat& srcFormat,
GrColorType dstColorType) const = 0;
+ virtual GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const = 0;
+
+
bool fSuppressPrints : 1;
bool fWireframeMode : 1;
diff --git a/chromium/third_party/skia/src/gpu/GrClip.h b/chromium/third_party/skia/src/gpu/GrClip.h
index d85338b3756..ee6935d1d28 100644
--- a/chromium/third_party/skia/src/gpu/GrClip.h
+++ b/chromium/third_party/skia/src/gpu/GrClip.h
@@ -21,6 +21,8 @@ class GrContext;
*/
class GrClip {
public:
+ virtual ~GrClip() {}
+
virtual bool quickContains(const SkRect&) const = 0;
virtual bool quickContains(const SkRRect& rrect) const {
return this->quickContains(rrect.getBounds());
@@ -30,9 +32,7 @@ public:
* The returned bounds represent the limits of pixels that can be drawn; anything outside of the
* bounds will be entirely clipped out.
*/
- virtual SkIRect getConservativeBounds(int width, int height) const {
- return SkIRect::MakeWH(width, height);
- }
+ virtual SkIRect getConservativeBounds() const = 0;
/**
* This computes a GrAppliedClip from the clip which in turn can be used to build a GrPipeline.
@@ -45,22 +45,18 @@ public:
virtual bool apply(GrRecordingContext*, GrRenderTargetContext*, bool useHWAA,
bool hasUserStencilSettings, GrAppliedClip*, SkRect* bounds) const = 0;
- virtual ~GrClip() {}
-
/**
* This method quickly and conservatively determines whether the entire clip is equivalent to
- * intersection with a rrect. This will only return true if the rrect does not fully contain
- * the render target bounds. Moreover, the returned rrect need not be contained by the render
+ * intersection with a rrect. Moreover, the returned rrect need not be contained by the render
* target bounds. We assume all draws will be implicitly clipped by the render target bounds.
*
- * @param rtBounds The bounds of the render target that the clip will be applied to.
* @param rrect If return is true rrect will contain the rrect equivalent to the clip within
* rtBounds.
* @param aa If return is true aa will indicate whether the rrect clip is antialiased.
* @return true if the clip is equivalent to a single rrect, false otherwise.
*
*/
- virtual bool isRRect(const SkRect& rtBounds, SkRRect* rrect, GrAA* aa) const = 0;
+ virtual bool isRRect(SkRRect* rrect, GrAA* aa) const = 0;
/**
* This is the maximum distance that a draw may extend beyond a clip's boundary and still count
@@ -151,24 +147,13 @@ public:
* return 'bounds' has been intersected with a conservative bounds of the clip. A return value
* of false indicates that the draw can be skipped as it is fully clipped out.
*/
- virtual bool apply(int rtWidth, int rtHeight, GrAppliedHardClip* out, SkRect* bounds) const = 0;
+ virtual bool apply(GrAppliedHardClip* out, SkRect* bounds) const = 0;
private:
bool apply(GrRecordingContext*, GrRenderTargetContext* rtc, bool useHWAA,
bool hasUserStencilSettings, GrAppliedClip* out, SkRect* bounds) const final {
- return this->apply(rtc->width(), rtc->height(), &out->hardClip(), bounds);
+ return this->apply(&out->hardClip(), bounds);
}
};
-/**
- * Specialized implementation for no clip.
- */
-class GrNoClip final : public GrHardClip {
-private:
- bool quickContains(const SkRect&) const final { return true; }
- bool quickContains(const SkRRect&) const final { return true; }
- bool apply(int rtWidth, int rtHeight, GrAppliedHardClip*, SkRect*) const final { return true; }
- bool isRRect(const SkRect&, SkRRect*, GrAA*) const override { return false; }
-};
-
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrClipStackClip.cpp b/chromium/third_party/skia/src/gpu/GrClipStackClip.cpp
index 37121fd858b..65532389342 100644
--- a/chromium/third_party/skia/src/gpu/GrClipStackClip.cpp
+++ b/chromium/third_party/skia/src/gpu/GrClipStackClip.cpp
@@ -15,7 +15,6 @@
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrDeferredProxyUploader.h"
#include "src/gpu/GrDrawingManager.h"
-#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrGpuResourcePriv.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
@@ -24,7 +23,6 @@
#include "src/gpu/GrStencilAttachment.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/GrTextureProxy.h"
-#include "src/gpu/effects/GrConvexPolyEffect.h"
#include "src/gpu/effects/GrRRectEffect.h"
#include "src/gpu/effects/generated/GrDeviceSpaceEffect.h"
#include "src/gpu/geometry/GrStyledShape.h"
@@ -49,26 +47,27 @@ bool GrClipStackClip::quickContains(const SkRRect& rrect) const {
return fStack->quickContains(rrect);
}
-bool GrClipStackClip::isRRect(const SkRect& origRTBounds, SkRRect* rr, GrAA* aa) const {
+bool GrClipStackClip::isRRect(SkRRect* rr, GrAA* aa) const {
if (!fStack) {
return false;
}
- const SkRect* rtBounds = &origRTBounds;
+
+ SkRect rtBounds = SkRect::MakeIWH(fDeviceSize.fWidth, fDeviceSize.fHeight);
bool isAA;
- if (fStack->isRRect(*rtBounds, rr, &isAA)) {
+ if (fStack->isRRect(rtBounds, rr, &isAA)) {
*aa = GrAA(isAA);
return true;
}
return false;
}
-SkIRect GrClipStackClip::getConservativeBounds(int width, int height) const {
+SkIRect GrClipStackClip::getConservativeBounds() const {
if (fStack) {
SkRect devBounds;
- fStack->getConservativeBounds(0, 0, width, height, &devBounds);
+ fStack->getConservativeBounds(0, 0, fDeviceSize.fWidth, fDeviceSize.fHeight, &devBounds);
return devBounds.roundOut();
} else {
- return this->GrClip::getConservativeBounds(width, height);
+ return SkIRect::MakeSize(fDeviceSize);
}
}
@@ -79,7 +78,7 @@ static std::unique_ptr<GrFragmentProcessor> create_fp_for_mask(GrSurfaceProxyVie
const GrCaps& caps) {
GrSamplerState samplerState(GrSamplerState::WrapMode::kClampToBorder,
GrSamplerState::Filter::kNearest);
- auto m = SkMatrix::MakeTrans(-devBound.fLeft, -devBound.fTop);
+ auto m = SkMatrix::Translate(-devBound.fLeft, -devBound.fTop);
auto subset = SkRect::Make(devBound.size());
// We scissor to devBounds. The mask's texel centers are aligned to device space
// pixel centers. Hence this domain of texture coordinates.
@@ -200,7 +199,9 @@ bool GrClipStackClip::UseSWOnlyPath(GrRecordingContext* context,
bool GrClipStackClip::apply(GrRecordingContext* context, GrRenderTargetContext* renderTargetContext,
bool useHWAA, bool hasUserStencilSettings, GrAppliedClip* out,
SkRect* bounds) const {
- SkRect devBounds = SkRect::MakeIWH(renderTargetContext->width(), renderTargetContext->height());
+ SkASSERT(renderTargetContext->width() == fDeviceSize.fWidth &&
+ renderTargetContext->height() == fDeviceSize.fHeight);
+ SkRect devBounds = SkRect::MakeIWH(fDeviceSize.fWidth, fDeviceSize.fHeight);
if (!devBounds.intersect(*bounds)) {
return false;
}
@@ -253,7 +254,8 @@ bool GrClipStackClip::apply(GrRecordingContext* context, GrRenderTargetContext*
// The opsTask ID must not be looked up until AFTER producing the clip mask (if any). That step
// can cause a flush or otherwise change which opstask our draw is going into.
uint32_t opsTaskID = renderTargetContext->getOpsTask()->uniqueID();
- if (auto clipFPs = reducedClip.finishAndDetachAnalyticFPs(ccpr, opsTaskID)) {
+ if (auto clipFPs = reducedClip.finishAndDetachAnalyticFPs(context, *fMatrixProvider, ccpr,
+ opsTaskID)) {
out->addCoverageFP(std::move(clipFPs));
}
diff --git a/chromium/third_party/skia/src/gpu/GrClipStackClip.h b/chromium/third_party/skia/src/gpu/GrClipStackClip.h
index 90ca8676fc8..ffbd0017cc3 100644
--- a/chromium/third_party/skia/src/gpu/GrClipStackClip.h
+++ b/chromium/third_party/skia/src/gpu/GrClipStackClip.h
@@ -20,17 +20,20 @@ class GrTextureProxy;
*/
class GrClipStackClip final : public GrClip {
public:
- GrClipStackClip(const SkClipStack* stack = nullptr) { this->reset(stack); }
-
- void reset(const SkClipStack* stack) { fStack = stack; }
+ GrClipStackClip(const SkISize& dimensions,
+ const SkClipStack* stack = nullptr,
+ const SkMatrixProvider* matrixProvider = nullptr)
+ : fDeviceSize(dimensions)
+ , fStack(stack)
+ , fMatrixProvider(matrixProvider) {}
bool quickContains(const SkRect&) const final;
bool quickContains(const SkRRect&) const final;
- SkIRect getConservativeBounds(int width, int height) const final;
+ SkIRect getConservativeBounds() const final;
bool apply(GrRecordingContext*, GrRenderTargetContext*, bool useHWAA,
bool hasUserStencilSettings, GrAppliedClip* out, SkRect* bounds) const final;
- bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA* aa) const override;
+ bool isRRect(SkRRect* rr, GrAA* aa) const override;
sk_sp<GrTextureProxy> testingOnly_createClipMask(GrContext*) const;
static const char kMaskTestTag[];
@@ -61,7 +64,11 @@ private:
const GrRenderTargetContext*,
const GrReducedClip&);
- const SkClipStack* fStack;
+ // SkClipStack does not track device bounds explicitly, but it will refine these device bounds
+ // as clip elements are added to the stack.
+ SkISize fDeviceSize;
+ const SkClipStack* fStack;
+ const SkMatrixProvider* fMatrixProvider; // for applying clip shaders
};
#endif // GrClipStackClip_DEFINED
diff --git a/chromium/third_party/skia/src/gpu/GrColorInfo.cpp b/chromium/third_party/skia/src/gpu/GrColorInfo.cpp
index ada27da5a64..22bdc98678c 100644
--- a/chromium/third_party/skia/src/gpu/GrColorInfo.cpp
+++ b/chromium/third_party/skia/src/gpu/GrColorInfo.cpp
@@ -11,7 +11,11 @@
GrColorInfo::GrColorInfo(
GrColorType colorType, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace)
- : fColorSpace(std::move(colorSpace)), fColorType(colorType), fAlphaType(alphaType) {}
+ : fColorSpace(std::move(colorSpace)), fColorType(colorType), fAlphaType(alphaType) {
+ // sRGB sources are very common (SkColor, etc...), so we cache that transformation
+ fColorXformFromSRGB = GrColorSpaceXform::Make(sk_srgb_singleton(), kUnpremul_SkAlphaType,
+ fColorSpace.get(), kUnpremul_SkAlphaType);
+}
GrColorInfo::GrColorInfo(const SkColorInfo& ci)
: GrColorInfo(SkColorTypeToGrColorType(ci.colorType()),
@@ -20,16 +24,3 @@ GrColorInfo::GrColorInfo(const SkColorInfo& ci)
GrColorInfo::GrColorInfo(const GrColorInfo&) = default;
GrColorInfo& GrColorInfo::operator=(const GrColorInfo&) = default;
-
-GrColorSpaceXform* GrColorInfo::colorSpaceXformFromSRGB() const {
- // TODO: Make this atomic if we start accessing this on multiple threads.
- if (!fInitializedColorSpaceXformFromSRGB) {
- // sRGB sources are very common (SkColor, etc...), so we cache that transformation
- fColorXformFromSRGB = GrColorSpaceXform::Make(sk_srgb_singleton(), kUnpremul_SkAlphaType,
- fColorSpace.get(), kUnpremul_SkAlphaType);
- fInitializedColorSpaceXformFromSRGB = true;
- }
- // You can't be color-space aware in legacy mode
- SkASSERT(fColorSpace || !fColorXformFromSRGB);
- return fColorXformFromSRGB.get();
-}
diff --git a/chromium/third_party/skia/src/gpu/GrColorInfo.h b/chromium/third_party/skia/src/gpu/GrColorInfo.h
index 578575a5d6c..0af549a8ee5 100644
--- a/chromium/third_party/skia/src/gpu/GrColorInfo.h
+++ b/chromium/third_party/skia/src/gpu/GrColorInfo.h
@@ -29,10 +29,8 @@ public:
SkColorSpace* colorSpace() const { return fColorSpace.get(); }
sk_sp<SkColorSpace> refColorSpace() const { return fColorSpace; }
- GrColorSpaceXform* colorSpaceXformFromSRGB() const;
- sk_sp<GrColorSpaceXform> refColorSpaceXformFromSRGB() const {
- return sk_ref_sp(this->colorSpaceXformFromSRGB());
- }
+ GrColorSpaceXform* colorSpaceXformFromSRGB() const { return fColorXformFromSRGB.get(); }
+ sk_sp<GrColorSpaceXform> refColorSpaceXformFromSRGB() const { return fColorXformFromSRGB; }
GrColorType colorType() const { return fColorType; }
SkAlphaType alphaType() const { return fAlphaType; }
@@ -43,10 +41,9 @@ public:
private:
sk_sp<SkColorSpace> fColorSpace;
- mutable sk_sp<GrColorSpaceXform> fColorXformFromSRGB;
+ sk_sp<GrColorSpaceXform> fColorXformFromSRGB;
GrColorType fColorType = GrColorType::kUnknown;
SkAlphaType fAlphaType = kUnknown_SkAlphaType;
- mutable bool fInitializedColorSpaceXformFromSRGB = false;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrColorSpaceXform.cpp b/chromium/third_party/skia/src/gpu/GrColorSpaceXform.cpp
index 0f97d21f9ef..b602b32ea4b 100644
--- a/chromium/third_party/skia/src/gpu/GrColorSpaceXform.cpp
+++ b/chromium/third_party/skia/src/gpu/GrColorSpaceXform.cpp
@@ -97,7 +97,7 @@ GrColorSpaceXformEffect::GrColorSpaceXformEffect(std::unique_ptr<GrFragmentProce
: INHERITED(kGrColorSpaceXformEffect_ClassID, OptFlags(child.get()))
, fColorXform(std::move(colorXform)) {
if (child) {
- this->registerChildProcessor(std::move(child));
+ this->registerChild(std::move(child));
}
}
diff --git a/chromium/third_party/skia/src/gpu/GrContext.cpp b/chromium/third_party/skia/src/gpu/GrContext.cpp
index 291c4348e7a..cc951f52643 100644
--- a/chromium/third_party/skia/src/gpu/GrContext.cpp
+++ b/chromium/third_party/skia/src/gpu/GrContext.cpp
@@ -30,9 +30,9 @@
#include "src/gpu/SkGr.h"
#include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h"
#include "src/gpu/effects/GrSkSLFP.h"
+#include "src/gpu/text/GrSDFTOptions.h"
#include "src/gpu/text/GrStrikeCache.h"
#include "src/gpu/text/GrTextBlobCache.h"
-#include "src/gpu/text/GrTextContext.h"
#include "src/image/SkImage_GpuBase.h"
#include "src/image/SkSurface_Gpu.h"
#include <atomic>
@@ -41,16 +41,14 @@
SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == this)
#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
-#define ASSERT_SINGLE_OWNER \
- SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
+#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(this->singleOwner())
#define RETURN_IF_ABANDONED if (this->abandoned()) { return; }
#define RETURN_FALSE_IF_ABANDONED if (this->abandoned()) { return false; }
#define RETURN_NULL_IF_ABANDONED if (this->abandoned()) { return nullptr; }
////////////////////////////////////////////////////////////////////////////////
-GrContext::GrContext(GrBackendApi backend, const GrContextOptions& options, int32_t contextID)
- : INHERITED(backend, options, contextID) {
+GrContext::GrContext(sk_sp<GrContextThreadSafeProxy> proxy) : INHERITED(std::move(proxy)) {
fResourceCache = nullptr;
fResourceProvider = nullptr;
}
@@ -61,20 +59,19 @@ GrContext::~GrContext() {
if (this->drawingManager()) {
this->drawingManager()->cleanup();
}
+ fMappedBufferManager.reset();
delete fResourceProvider;
delete fResourceCache;
}
-bool GrContext::init(sk_sp<const GrCaps> caps) {
+bool GrContext::init() {
ASSERT_SINGLE_OWNER
- SkASSERT(fThreadSafeProxy); // needs to have been initialized by derived classes
SkASSERT(this->proxyProvider());
- if (!INHERITED::init(std::move(caps))) {
+ if (!INHERITED::init()) {
return false;
}
- SkASSERT(this->caps());
SkASSERT(this->getTextBlobCache());
if (fGpu) {
@@ -106,7 +103,7 @@ bool GrContext::init(sk_sp<const GrCaps> caps) {
}
sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() {
- return fThreadSafeProxy;
+ return INHERITED::threadSafeProxy();
}
//////////////////////////////////////////////////////////////////////////////
@@ -170,6 +167,8 @@ bool GrContext::abandoned() {
return false;
}
+bool GrContext::oomed() { return fGpu ? fGpu->checkAndResetOOMed() : false; }
+
void GrContext::resetGLTextureBindings() {
if (this->abandoned() || this->backend() != GrBackendApi::kOpenGL) {
return;
@@ -305,35 +304,49 @@ bool GrContext::wait(int numSemaphores, const GrBackendSemaphore waitSemaphores[
std::unique_ptr<GrSemaphore> sema = fResourceProvider->wrapBackendSemaphore(
waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait,
kAdopt_GrWrapOwnership);
- fGpu->waitSemaphore(sema.get());
+ // If we failed to wrap the semaphore it means the client didn't give us a valid semaphore
+ // to begin with. Therefore, it is fine to not wait on it.
+ if (sema) {
+ fGpu->waitSemaphore(sema.get());
+ }
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
-GrSemaphoresSubmitted GrContext::flush(const GrFlushInfo& info,
- const GrPrepareForExternalIORequests& externalRequests) {
+GrSemaphoresSubmitted GrContext::flush(const GrFlushInfo& info) {
ASSERT_SINGLE_OWNER
if (this->abandoned()) {
+ if (info.fFinishedProc) {
+ info.fFinishedProc(info.fFinishedContext);
+ }
+ if (info.fSubmittedProc) {
+ info.fSubmittedProc(info.fSubmittedContext, false);
+ }
return GrSemaphoresSubmitted::kNo;
}
- bool submitted = false;
- if (this->drawingManager()->flush(nullptr, 0, SkSurface::BackendSurfaceAccess::kNoAccess,
- info, externalRequests)) {
- bool forceSync = SkToBool(info.fFlags & kSyncCpu_GrFlushFlag);
- submitted = this->drawingManager()->submitToGpu(forceSync);
- }
+ bool flushed = this->drawingManager()->flush(
+ nullptr, 0, SkSurface::BackendSurfaceAccess::kNoAccess, info, nullptr);
- if (!submitted || (!this->priv().caps()->semaphoreSupport() && info.fNumSemaphores)) {
+ if (!flushed || (!this->priv().caps()->semaphoreSupport() && info.fNumSemaphores)) {
return GrSemaphoresSubmitted::kNo;
}
return GrSemaphoresSubmitted::kYes;
}
-bool GrContext::submit(bool syncToCpu) {
- return true;
+bool GrContext::submit(bool syncCpu) {
+ ASSERT_SINGLE_OWNER
+ if (this->abandoned()) {
+ return false;
+ }
+
+ if (!fGpu) {
+ return false;
+ }
+
+ return fGpu->submitToGpu(syncCpu);
}
////////////////////////////////////////////////////////////////////////////////
@@ -461,71 +474,71 @@ GrBackendTexture GrContext::createBackendTexture(const SkSurfaceCharacterization
return result;
}
+static GrBackendTexture create_and_update_backend_texture(
+ GrContext* context,
+ SkISize dimensions,
+ const GrBackendFormat& backendFormat,
+ GrMipMapped mipMapped,
+ GrRenderable renderable,
+ GrProtected isProtected,
+ sk_sp<GrRefCntedCallback> finishedCallback,
+ const GrGpu::BackendTextureData* data) {
+ GrGpu* gpu = context->priv().getGpu();
+
+ GrBackendTexture beTex = gpu->createBackendTexture(dimensions, backendFormat, renderable,
+ mipMapped, isProtected);
+ if (!beTex.isValid()) {
+ return {};
+ }
+
+ if (!context->priv().getGpu()->updateBackendTexture(beTex, std::move(finishedCallback), data)) {
+ context->deleteBackendTexture(beTex);
+ return {};
+ }
+ return beTex;
+}
+
+
GrBackendTexture GrContext::createBackendTexture(const SkSurfaceCharacterization& c,
const SkColor4f& color,
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) {
+ sk_sp<GrRefCntedCallback> finishedCallback;
+ if (finishedProc) {
+ finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
+ }
+
if (!this->asDirectContext() || !c.isValid()) {
- finishedProc(finishedContext);
return {};
}
if (this->abandoned()) {
- finishedProc(finishedContext);
return {};
}
if (c.usesGLFBO0()) {
- finishedProc(finishedContext);
// If we are making the surface we will never use FBO0.
return {};
}
if (c.vulkanSecondaryCBCompatible()) {
- finishedProc(finishedContext);
return {};
}
const GrBackendFormat format = this->defaultBackendFormat(c.colorType(), GrRenderable::kYes);
if (!format.isValid()) {
- finishedProc(finishedContext);
return {};
}
- GrBackendTexture result = this->createBackendTexture(c.width(), c.height(), format, color,
- GrMipMapped(c.isMipMapped()),
- GrRenderable::kYes,
- c.isProtected(), finishedProc,
- finishedContext);
+ GrGpu::BackendTextureData data(color);
+ GrBackendTexture result = create_and_update_backend_texture(
+ this, {c.width(), c.height()}, format, GrMipMapped(c.isMipMapped()), GrRenderable::kYes,
+ c.isProtected(), std::move(finishedCallback), &data);
+
SkASSERT(c.isCompatible(result));
return result;
}
-static GrBackendTexture create_and_update_backend_texture(GrContext* context,
- SkISize dimensions,
- const GrBackendFormat& backendFormat,
- GrMipMapped mipMapped,
- GrRenderable renderable,
- GrProtected isProtected,
- GrGpuFinishedProc finishedProc,
- GrGpuFinishedContext finishedContext,
- const GrGpu::BackendTextureData* data) {
- GrGpu* gpu = context->priv().getGpu();
-
- GrBackendTexture beTex = gpu->createBackendTexture(dimensions, backendFormat, renderable,
- mipMapped, isProtected);
- if (!beTex.isValid()) {
- return {};
- }
-
- if (!context->priv().getGpu()->updateBackendTexture(beTex, finishedProc, finishedContext,
- data)) {
- context->deleteBackendTexture(beTex);
- return {};
- }
- return beTex;
-}
-
GrBackendTexture GrContext::createBackendTexture(int width, int height,
const GrBackendFormat& backendFormat,
const SkColor4f& color,
@@ -534,20 +547,23 @@ GrBackendTexture GrContext::createBackendTexture(int width, int height,
GrProtected isProtected,
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) {
+ sk_sp<GrRefCntedCallback> finishedCallback;
+ if (finishedProc) {
+ finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
+ }
+
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
if (!this->asDirectContext()) {
- finishedProc(finishedContext);
return {};
}
if (this->abandoned()) {
- finishedProc(finishedContext);
return {};
}
GrGpu::BackendTextureData data(color);
return create_and_update_backend_texture(this, {width, height}, backendFormat, mipMapped,
- renderable, isProtected, finishedProc, finishedContext,
+ renderable, isProtected, std::move(finishedCallback),
&data);
}
@@ -559,27 +575,31 @@ GrBackendTexture GrContext::createBackendTexture(int width, int height,
GrProtected isProtected,
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) {
+ sk_sp<GrRefCntedCallback> finishedCallback;
+ if (finishedProc) {
+ finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
+ }
+
if (!this->asDirectContext()) {
- finishedProc(finishedContext);
return {};
}
if (this->abandoned()) {
- finishedProc(finishedContext);
return {};
}
GrBackendFormat format = this->defaultBackendFormat(skColorType, renderable);
if (!format.isValid()) {
- finishedProc(finishedContext);
return {};
}
GrColorType grColorType = SkColorTypeToGrColorType(skColorType);
SkColor4f swizzledColor = this->caps()->getWriteSwizzle(format, grColorType).applyTo(color);
- return this->createBackendTexture(width, height, format, swizzledColor, mipMapped, renderable,
- isProtected, finishedProc, finishedContext);
+ GrGpu::BackendTextureData data(swizzledColor);
+ return create_and_update_backend_texture(this, {width, height}, format, mipMapped,
+ renderable, isProtected, std::move(finishedCallback),
+ &data);
}
GrBackendTexture GrContext::createBackendTexture(const SkPixmap srcData[], int numProvidedLevels,
@@ -588,18 +608,20 @@ GrBackendTexture GrContext::createBackendTexture(const SkPixmap srcData[], int n
GrGpuFinishedContext finishedContext) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
+ sk_sp<GrRefCntedCallback> finishedCallback;
+ if (finishedProc) {
+ finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
+ }
+
if (!this->asDirectContext()) {
- finishedProc(finishedContext);
return {};
}
if (this->abandoned()) {
- finishedProc(finishedContext);
return {};
}
if (!srcData || numProvidedLevels <= 0) {
- finishedProc(finishedContext);
return {};
}
@@ -615,7 +637,6 @@ GrBackendTexture GrContext::createBackendTexture(const SkPixmap srcData[], int n
}
if (numProvidedLevels != numExpectedLevels) {
- finishedProc(finishedContext);
return {};
}
@@ -623,26 +644,29 @@ GrBackendTexture GrContext::createBackendTexture(const SkPixmap srcData[], int n
GrGpu::BackendTextureData data(srcData);
return create_and_update_backend_texture(this, {baseWidth, baseHeight}, backendFormat,
- mipMapped, renderable, isProtected, finishedProc,
- finishedContext, &data);
+ mipMapped, renderable, isProtected,
+ std::move(finishedCallback), &data);
}
bool GrContext::updateBackendTexture(const GrBackendTexture& backendTexture,
const SkColor4f& color,
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) {
+ sk_sp<GrRefCntedCallback> finishedCallback;
+ if (finishedProc) {
+ finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
+ }
+
if (!this->asDirectContext()) {
- finishedProc(finishedContext);
return false;
}
if (this->abandoned()) {
- finishedProc(finishedContext);
return false;
}
GrGpu::BackendTextureData data(color);
- return fGpu->updateBackendTexture(backendTexture, finishedProc, finishedContext, &data);
+ return fGpu->updateBackendTexture(backendTexture, std::move(finishedCallback), &data);
}
bool GrContext::updateBackendTexture(const GrBackendTexture& backendTexture,
@@ -650,18 +674,20 @@ bool GrContext::updateBackendTexture(const GrBackendTexture& backendTexture,
int numLevels,
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) {
+ sk_sp<GrRefCntedCallback> finishedCallback;
+ if (finishedProc) {
+ finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
+ }
+
if (!this->asDirectContext()) {
- finishedProc(finishedContext);
return false;
}
if (this->abandoned()) {
- finishedProc(finishedContext);
return false;
}
if (!srcData || numLevels <= 0) {
- finishedProc(finishedContext);
return false;
}
@@ -671,12 +697,11 @@ bool GrContext::updateBackendTexture(const GrBackendTexture& backendTexture,
backendTexture.height()) + 1;
}
if (numLevels != numExpectedLevels) {
- finishedProc(finishedContext);
return false;
}
GrGpu::BackendTextureData data(srcData);
- return fGpu->updateBackendTexture(backendTexture, finishedProc, finishedContext, &data);
+ return fGpu->updateBackendTexture(backendTexture, std::move(finishedCallback), &data);
}
//////////////////////////////////////////////////////////////////////////////
@@ -689,20 +714,23 @@ GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
+ sk_sp<GrRefCntedCallback> finishedCallback;
+ if (finishedProc) {
+ finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
+ }
+
if (!this->asDirectContext()) {
- finishedProc(finishedContext);
return {};
}
if (this->abandoned()) {
- finishedProc(finishedContext);
return {};
}
GrGpu::BackendTextureData data(color);
return fGpu->createCompressedBackendTexture({width, height}, backendFormat,
- mipMapped, isProtected, finishedProc,
- finishedContext, &data);
+ mipMapped, isProtected, std::move(finishedCallback),
+ &data);
}
GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height,
@@ -713,16 +741,6 @@ GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
- if (!this->asDirectContext()) {
- finishedProc(finishedContext);
- return {};
- }
-
- if (this->abandoned()) {
- finishedProc(finishedContext);
- return {};
- }
-
GrBackendFormat format = this->compressedBackendFormat(compression);
return this->createCompressedBackendTexture(width, height, format, color,
mipMapped, isProtected, finishedProc,
@@ -738,20 +756,23 @@ GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
+ sk_sp<GrRefCntedCallback> finishedCallback;
+ if (finishedProc) {
+ finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
+ }
+
if (!this->asDirectContext()) {
- finishedProc(finishedContext);
return {};
}
if (this->abandoned()) {
- finishedProc(finishedContext);
return {};
}
GrGpu::BackendTextureData data(compressedData, dataSize);
return fGpu->createCompressedBackendTexture({width, height}, backendFormat,
- mipMapped, isProtected, finishedProc,
- finishedContext, &data);
+ mipMapped, isProtected, std::move(finishedCallback),
+ &data);
}
GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height,
@@ -762,20 +783,49 @@ GrBackendTexture GrContext::createCompressedBackendTexture(int width, int height
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
+ GrBackendFormat format = this->compressedBackendFormat(compression);
+ return this->createCompressedBackendTexture(width, height, format, data, dataSize, mipMapped,
+ isProtected, finishedProc, finishedContext);
+}
+
+bool GrContext::setBackendTextureState(const GrBackendTexture& backendTexture,
+ const GrBackendSurfaceMutableState& state,
+ GrGpuFinishedProc finishedProc,
+ GrGpuFinishedContext finishedContext) {
+ sk_sp<GrRefCntedCallback> callback;
+ if (finishedProc) {
+ callback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
+ }
+
if (!this->asDirectContext()) {
- finishedProc(finishedContext);
- return {};
+ return false;
}
if (this->abandoned()) {
- finishedProc(finishedContext);
- return {};
+ return false;
}
- GrBackendFormat format = this->compressedBackendFormat(compression);
- return this->createCompressedBackendTexture(width, height, format, data, dataSize,
- mipMapped, isProtected, finishedProc,
- finishedContext);
+ return fGpu->setBackendTextureState(backendTexture, state, std::move(callback));
+}
+
+bool GrContext::setBackendRenderTargetState(const GrBackendRenderTarget& backendRenderTarget,
+ const GrBackendSurfaceMutableState& state,
+ GrGpuFinishedProc finishedProc,
+ GrGpuFinishedContext finishedContext) {
+ sk_sp<GrRefCntedCallback> callback;
+ if (finishedProc) {
+ callback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
+ }
+
+ if (!this->asDirectContext()) {
+ return false;
+ }
+
+ if (this->abandoned()) {
+ return false;
+ }
+
+ return fGpu->setBackendRenderTargetState(backendRenderTarget, state, std::move(callback));
}
void GrContext::deleteBackendTexture(GrBackendTexture backendTex) {
@@ -789,6 +839,8 @@ void GrContext::deleteBackendTexture(GrBackendTexture backendTex) {
fGpu->deleteBackendTexture(backendTex);
}
+//////////////////////////////////////////////////////////////////////////////
+
bool GrContext::precompileShader(const SkData& key, const SkData& data) {
return fGpu->precompileShader(key, data);
}
diff --git a/chromium/third_party/skia/src/gpu/GrContextPriv.cpp b/chromium/third_party/skia/src/gpu/GrContextPriv.cpp
index 702d82dbd94..3c014b13500 100644
--- a/chromium/third_party/skia/src/gpu/GrContextPriv.cpp
+++ b/chromium/third_party/skia/src/gpu/GrContextPriv.cpp
@@ -28,8 +28,7 @@
#define ASSERT_OWNED_PROXY(P) \
SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == fContext)
-#define ASSERT_SINGLE_OWNER \
- SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->singleOwner());)
+#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fContext->singleOwner())
#define RETURN_VALUE_IF_ABANDONED(value) if (fContext->abandoned()) { return (value); }
#define RETURN_IF_ABANDONED RETURN_VALUE_IF_ABANDONED(void)
@@ -53,7 +52,7 @@ GrSemaphoresSubmitted GrContextPriv::flushSurfaces(GrSurfaceProxy* proxies[], in
ASSERT_OWNED_PROXY(proxies[i]);
}
return fContext->drawingManager()->flushSurfaces(
- proxies, numProxies, SkSurface::BackendSurfaceAccess::kNoAccess, info);
+ proxies, numProxies, SkSurface::BackendSurfaceAccess::kNoAccess, info, nullptr);
}
void GrContextPriv::flushSurface(GrSurfaceProxy* proxy) {
@@ -182,7 +181,7 @@ void GrContextPriv::testingOnly_purgeAllUnlockedResources() {
}
void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
- fContext->flush();
+ fContext->flushAndSubmit();
fContext->drawingManager()->testingOnly_removeOnFlushCallbackObject(cb);
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrContextPriv.h b/chromium/third_party/skia/src/gpu/GrContextPriv.h
index d97f7adca6d..c5d3f72021e 100644
--- a/chromium/third_party/skia/src/gpu/GrContextPriv.h
+++ b/chromium/third_party/skia/src/gpu/GrContextPriv.h
@@ -74,7 +74,7 @@ public:
/**
* Create a GrContext without a resource cache
*/
- static sk_sp<GrContext> MakeDDL(const sk_sp<GrContextThreadSafeProxy>&);
+ static sk_sp<GrContext> MakeDDL(sk_sp<GrContextThreadSafeProxy>);
/**
* Finalizes all pending reads and writes to the surfaces and also performs an MSAA resolves
diff --git a/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxy.cpp b/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxy.cpp
index fb27ba1822c..6fd86bd1a9f 100644
--- a/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxy.cpp
+++ b/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxy.cpp
@@ -19,16 +19,24 @@
#include "src/gpu/vk/GrVkCaps.h"
#endif
+static int32_t next_id() {
+ static std::atomic<int32_t> nextID{1};
+ int32_t id;
+ do {
+ id = nextID++;
+ } while (id == SK_InvalidGenID);
+ return id;
+}
+
GrContextThreadSafeProxy::GrContextThreadSafeProxy(GrBackendApi backend,
- const GrContextOptions& options,
- uint32_t contextID)
- : INHERITED(backend, options, contextID) {
+ const GrContextOptions& options)
+ : fBackend(backend), fOptions(options), fContextID(next_id()) {
}
GrContextThreadSafeProxy::~GrContextThreadSafeProxy() = default;
-bool GrContextThreadSafeProxy::init(sk_sp<const GrCaps> caps) {
- return INHERITED::init(std::move(caps));
+void GrContextThreadSafeProxy::init(sk_sp<const GrCaps> caps) {
+ fCaps = std::move(caps);
}
SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization(
@@ -38,6 +46,7 @@ SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization(
const SkSurfaceProps& surfaceProps,
bool isMipMapped, bool willUseGLFBO0, bool isTextureable,
GrProtected isProtected) {
+ SkASSERT(fCaps);
if (!backendFormat.isValid()) {
return SkSurfaceCharacterization(); // return an invalid characterization
}
@@ -49,39 +58,39 @@ SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization(
return SkSurfaceCharacterization(); // return an invalid characterization
}
- if (!this->caps()->mipMapSupport()) {
+ if (!fCaps->mipMapSupport()) {
isMipMapped = false;
}
GrColorType grColorType = SkColorTypeToGrColorType(ii.colorType());
- if (!this->caps()->areColorTypeAndFormatCompatible(grColorType, backendFormat)) {
+ if (!fCaps->areColorTypeAndFormatCompatible(grColorType, backendFormat)) {
return SkSurfaceCharacterization(); // return an invalid characterization
}
- if (!this->caps()->isFormatAsColorTypeRenderable(grColorType, backendFormat, sampleCnt)) {
+ if (!fCaps->isFormatAsColorTypeRenderable(grColorType, backendFormat, sampleCnt)) {
return SkSurfaceCharacterization(); // return an invalid characterization
}
- sampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, backendFormat);
+ sampleCnt = fCaps->getRenderTargetSampleCount(sampleCnt, backendFormat);
SkASSERT(sampleCnt);
if (willUseGLFBO0 && isTextureable) {
return SkSurfaceCharacterization(); // return an invalid characterization
}
- if (isTextureable && !this->caps()->isFormatTexturable(backendFormat)) {
+ if (isTextureable && !fCaps->isFormatTexturable(backendFormat)) {
// Skia doesn't agree that this is textureable.
return SkSurfaceCharacterization(); // return an invalid characterization
}
if (GrBackendApi::kVulkan == backendFormat.backend()) {
- if (GrBackendApi::kVulkan != this->backend()) {
+ if (GrBackendApi::kVulkan != fBackend) {
return SkSurfaceCharacterization(); // return an invalid characterization
}
#ifdef SK_VULKAN
- const GrVkCaps* vkCaps = (const GrVkCaps*) this->caps();
+ const GrVkCaps* vkCaps = (const GrVkCaps*) fCaps.get();
// The protection status of the characterization and the context need to match
if (isProtected != GrProtected(vkCaps->supportsProtectedMemory())) {
@@ -101,18 +110,34 @@ SkSurfaceCharacterization GrContextThreadSafeProxy::createCharacterization(
surfaceProps);
}
+GrBackendFormat GrContextThreadSafeProxy::defaultBackendFormat(SkColorType skColorType,
+ GrRenderable renderable) const {
+ SkASSERT(fCaps);
+ GrColorType grColorType = SkColorTypeToGrColorType(skColorType);
+
+ GrBackendFormat format = fCaps->getDefaultBackendFormat(grColorType, renderable);
+ if (!format.isValid()) {
+ return GrBackendFormat();
+ }
+
+ SkASSERT(renderable == GrRenderable::kNo ||
+ fCaps->isFormatAsColorTypeRenderable(grColorType, format));
+
+ return format;
+}
+
+void GrContextThreadSafeProxy::abandonContext() {
+ fAbandoned.store(true, std::memory_order_relaxed);
+}
+
+bool GrContextThreadSafeProxy::abandoned() const {
+ return fAbandoned.load(std::memory_order_relaxed);
+}
+
////////////////////////////////////////////////////////////////////////////////
sk_sp<GrContextThreadSafeProxy> GrContextThreadSafeProxyPriv::Make(
GrBackendApi backend,
- const GrContextOptions& options,
- uint32_t contextID,
- sk_sp<const GrCaps> caps) {
- sk_sp<GrContextThreadSafeProxy> proxy(new GrContextThreadSafeProxy(backend, options,
- contextID));
-
- if (!proxy->init(std::move(caps))) {
- return nullptr;
- }
- return proxy;
+ const GrContextOptions& options) {
+ return sk_sp<GrContextThreadSafeProxy>(new GrContextThreadSafeProxy(backend, options));
}
diff --git a/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxyPriv.h b/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxyPriv.h
index 0efb995a357..c4873bb9847 100644
--- a/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxyPriv.h
+++ b/chromium/third_party/skia/src/gpu/GrContextThreadSafeProxyPriv.h
@@ -9,6 +9,7 @@
#define GrContextThreadSafeProxyPriv_DEFINED
#include "include/gpu/GrContextThreadSafeProxy.h"
+#include "include/private/GrContext_Base.h"
#include "src/gpu/GrCaps.h"
@@ -19,21 +20,24 @@
*/
class GrContextThreadSafeProxyPriv {
public:
- // from GrContext_Base
- uint32_t contextID() const { return fProxy->contextID(); }
+ void init(sk_sp<const GrCaps> caps) const { fProxy->init(std::move(caps)); }
- bool matches(GrContext_Base* candidate) const { return fProxy->matches(candidate); }
+ bool matches(GrContext_Base* candidate) const {
+ return fProxy == candidate->threadSafeProxy().get();
+ }
- const GrContextOptions& options() const { return fProxy->options(); }
+ GrBackend backend() const { return fProxy->fBackend; }
+ const GrContextOptions& options() const { return fProxy->fOptions; }
+ uint32_t contextID() const { return fProxy->fContextID; }
- const GrCaps* caps() const { return fProxy->caps(); }
- sk_sp<const GrCaps> refCaps() const { return fProxy->refCaps(); }
+ const GrCaps* caps() const { return fProxy->fCaps.get(); }
+ sk_sp<const GrCaps> refCaps() const { return fProxy->fCaps; }
+
+ void abandonContext() { fProxy->abandonContext(); }
+ bool abandoned() const { return fProxy->abandoned(); }
// GrContextThreadSafeProxyPriv
- static sk_sp<GrContextThreadSafeProxy> Make(GrBackendApi,
- const GrContextOptions&,
- uint32_t contextID,
- sk_sp<const GrCaps>);
+ static sk_sp<GrContextThreadSafeProxy> Make(GrBackendApi, const GrContextOptions&);
private:
explicit GrContextThreadSafeProxyPriv(GrContextThreadSafeProxy* proxy) : fProxy(proxy) {}
diff --git a/chromium/third_party/skia/src/gpu/GrContext_Base.cpp b/chromium/third_party/skia/src/gpu/GrContext_Base.cpp
index 034d0234875..34262997f02 100644
--- a/chromium/third_party/skia/src/gpu/GrContext_Base.cpp
+++ b/chromium/third_party/skia/src/gpu/GrContext_Base.cpp
@@ -9,53 +9,35 @@
#include "src/gpu/GrBaseContextPriv.h"
#include "src/gpu/GrCaps.h"
+#include "src/gpu/GrContextThreadSafeProxyPriv.h"
#include "src/gpu/GrShaderUtils.h"
#include "src/gpu/effects/GrSkSLFP.h"
-static int32_t next_id() {
- static std::atomic<int32_t> nextID{1};
- int32_t id;
- do {
- id = nextID++;
- } while (id == SK_InvalidGenID);
- return id;
-}
-
-GrContext_Base::GrContext_Base(GrBackendApi backend,
- const GrContextOptions& options,
- uint32_t contextID)
- : fBackend(backend)
- , fOptions(options)
- , fContextID(SK_InvalidGenID == contextID ? next_id() : contextID) {
+GrContext_Base::GrContext_Base(sk_sp<GrContextThreadSafeProxy> proxy)
+ : fThreadSafeProxy(std::move(proxy)) {
}
GrContext_Base::~GrContext_Base() { }
-bool GrContext_Base::init(sk_sp<const GrCaps> caps) {
- SkASSERT(caps);
+bool GrContext_Base::init() {
+ SkASSERT(fThreadSafeProxy->isValid());
- fCaps = caps;
return true;
}
-const GrCaps* GrContext_Base::caps() const { return fCaps.get(); }
-sk_sp<const GrCaps> GrContext_Base::refCaps() const { return fCaps; }
-
-GrBackendFormat GrContext_Base::defaultBackendFormat(SkColorType skColorType,
- GrRenderable renderable) const {
- const GrCaps* caps = this->caps();
-
- GrColorType grColorType = SkColorTypeToGrColorType(skColorType);
+uint32_t GrContext_Base::contextID() const { return fThreadSafeProxy->priv().contextID(); }
+GrBackendApi GrContext_Base::backend() const { return fThreadSafeProxy->priv().backend(); }
- GrBackendFormat format = caps->getDefaultBackendFormat(grColorType, renderable);
- if (!format.isValid()) {
- return GrBackendFormat();
- }
+const GrContextOptions& GrContext_Base::options() const {
+ return fThreadSafeProxy->priv().options();
+}
- SkASSERT(renderable == GrRenderable::kNo ||
- caps->isFormatAsColorTypeRenderable(grColorType, format));
+const GrCaps* GrContext_Base::caps() const { return fThreadSafeProxy->priv().caps(); }
+sk_sp<const GrCaps> GrContext_Base::refCaps() const { return fThreadSafeProxy->priv().refCaps(); }
- return format;
+GrBackendFormat GrContext_Base::defaultBackendFormat(SkColorType skColorType,
+ GrRenderable renderable) const {
+ return fThreadSafeProxy->defaultBackendFormat(skColorType, renderable);
}
GrBackendFormat GrContext_Base::compressedBackendFormat(SkImage::CompressionType c) const {
@@ -67,6 +49,8 @@ GrBackendFormat GrContext_Base::compressedBackendFormat(SkImage::CompressionType
return format;
}
+sk_sp<GrContextThreadSafeProxy> GrContext_Base::threadSafeProxy() { return fThreadSafeProxy; }
+
///////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<const GrCaps> GrBaseContextPriv::refCaps() const {
return fContext->refCaps();
diff --git a/chromium/third_party/skia/src/gpu/GrCopyRenderTask.cpp b/chromium/third_party/skia/src/gpu/GrCopyRenderTask.cpp
index 0f46e69efcb..a578451b1a7 100644
--- a/chromium/third_party/skia/src/gpu/GrCopyRenderTask.cpp
+++ b/chromium/third_party/skia/src/gpu/GrCopyRenderTask.cpp
@@ -11,7 +11,8 @@
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrResourceAllocator.h"
-sk_sp<GrRenderTask> GrCopyRenderTask::Make(GrSurfaceProxyView srcView,
+sk_sp<GrRenderTask> GrCopyRenderTask::Make(GrDrawingManager* drawingMgr,
+ GrSurfaceProxyView srcView,
const SkIRect& srcRect,
GrSurfaceProxyView dstView,
const SkIPoint& dstPoint,
@@ -41,34 +42,35 @@ sk_sp<GrRenderTask> GrCopyRenderTask::Make(GrSurfaceProxyView srcView,
}
sk_sp<GrCopyRenderTask> task(new GrCopyRenderTask(
- std::move(srcView), clippedSrcRect, std::move(dstView), clippedDstPoint));
+ drawingMgr, std::move(srcView), clippedSrcRect, std::move(dstView), clippedDstPoint));
return std::move(task);
}
-GrCopyRenderTask::GrCopyRenderTask(GrSurfaceProxyView srcView,
+GrCopyRenderTask::GrCopyRenderTask(GrDrawingManager* drawingMgr,
+ GrSurfaceProxyView srcView,
const SkIRect& srcRect,
GrSurfaceProxyView dstView,
const SkIPoint& dstPoint)
- : GrRenderTask(std::move(dstView))
+ : GrRenderTask()
, fSrcView(std::move(srcView))
, fSrcRect(srcRect)
, fDstPoint(dstPoint) {
- fTargetView.proxy()->setLastRenderTask(this);
+ this->addTarget(drawingMgr, dstView);
}
void GrCopyRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
// This renderTask doesn't have "normal" ops. In this case we still need to add an interval (so
// fEndOfOpsTaskOpIndices will remain in sync), so we create a fake op# to capture the fact that
- // we read fSrcView and copy to fTargetView.
+ // we read fSrcView and copy to target view.
alloc->addInterval(fSrcView.proxy(), alloc->curOp(), alloc->curOp(),
GrResourceAllocator::ActualUse::kYes);
- alloc->addInterval(fTargetView.proxy(), alloc->curOp(), alloc->curOp(),
+ alloc->addInterval(this->target(0).proxy(), alloc->curOp(), alloc->curOp(),
GrResourceAllocator::ActualUse::kYes);
alloc->incOps();
}
bool GrCopyRenderTask::onExecute(GrOpFlushState* flushState) {
- GrSurfaceProxy* dstProxy = fTargetView.proxy();
+ GrSurfaceProxy* dstProxy = this->target(0).proxy();
GrSurfaceProxy* srcProxy = fSrcView.proxy();
if (!srcProxy->isInstantiated() || !dstProxy->isInstantiated()) {
return false;
diff --git a/chromium/third_party/skia/src/gpu/GrCopyRenderTask.h b/chromium/third_party/skia/src/gpu/GrCopyRenderTask.h
index a9c79ea43c7..4ecd3c7f1dc 100644
--- a/chromium/third_party/skia/src/gpu/GrCopyRenderTask.h
+++ b/chromium/third_party/skia/src/gpu/GrCopyRenderTask.h
@@ -12,21 +12,21 @@
class GrCopyRenderTask final : public GrRenderTask {
public:
- static sk_sp<GrRenderTask> Make(GrSurfaceProxyView srcView,
+ static sk_sp<GrRenderTask> Make(GrDrawingManager*,
+ GrSurfaceProxyView srcView,
const SkIRect& srcRect,
GrSurfaceProxyView dstView,
const SkIPoint& dstPoint,
const GrCaps*);
private:
- GrCopyRenderTask(GrSurfaceProxyView srcView,
+ GrCopyRenderTask(GrDrawingManager*,
+ GrSurfaceProxyView srcView,
const SkIRect& srcRect,
GrSurfaceProxyView dstView,
const SkIPoint& dstPoint);
bool onIsUsed(GrSurfaceProxy* proxy) const override {
- // This case should be handled by GrRenderTask.
- SkASSERT(proxy != fTargetView.proxy());
return proxy == fSrcView.proxy();
}
// If instantiation failed, at flush time we simply will skip doing the copy.
diff --git a/chromium/third_party/skia/src/gpu/GrDDLContext.cpp b/chromium/third_party/skia/src/gpu/GrDDLContext.cpp
index 1f77417a208..ee77eaf8044 100644
--- a/chromium/third_party/skia/src/gpu/GrDDLContext.cpp
+++ b/chromium/third_party/skia/src/gpu/GrDDLContext.cpp
@@ -21,8 +21,7 @@
class GrDDLContext final : public GrContext {
public:
GrDDLContext(sk_sp<GrContextThreadSafeProxy> proxy)
- : INHERITED(proxy->backend(), proxy->priv().options(), proxy->priv().contextID()) {
- fThreadSafeProxy = std::move(proxy);
+ : INHERITED(std::move(proxy)) {
}
~GrDDLContext() override {}
@@ -38,8 +37,8 @@ public:
}
void freeGpuResources() override {
- SkASSERT(0); // freeing resources in a DDL Recorder doesn't make a whole lot of sense
- INHERITED::freeGpuResources();
+ // freeing resources in a DDL Recorder doesn't make a whole lot of sense but some of
+ // our tests do it anyways
}
private:
@@ -47,11 +46,8 @@ private:
// GrRecordingContext!
GrContext* asDirectContext() override { return nullptr; }
- bool init(sk_sp<const GrCaps> caps) override {
- SkASSERT(caps);
- SkASSERT(fThreadSafeProxy); // should've been set in the ctor
-
- if (!INHERITED::init(std::move(caps))) {
+ bool init() override {
+ if (!INHERITED::init()) {
return false;
}
@@ -59,8 +55,6 @@ private:
// splitting.
this->setupDrawingManager(true, true);
- SkASSERT(this->caps());
-
return true;
}
@@ -79,8 +73,9 @@ private:
if (this->backend() == GrBackendApi::kVulkan ||
this->backend() == GrBackendApi::kMetal ||
+ this->backend() == GrBackendApi::kDirect3D ||
this->backend() == GrBackendApi::kDawn) {
- // Currently, Vulkan, Metal and Dawn require a live renderTarget to
+ // Currently Vulkan, Metal, Direct3D, and Dawn require a live renderTarget to
// compute the key
return;
}
@@ -153,10 +148,10 @@ private:
typedef GrContext INHERITED;
};
-sk_sp<GrContext> GrContextPriv::MakeDDL(const sk_sp<GrContextThreadSafeProxy>& proxy) {
- sk_sp<GrContext> context(new GrDDLContext(proxy));
+sk_sp<GrContext> GrContextPriv::MakeDDL(sk_sp<GrContextThreadSafeProxy> proxy) {
+ sk_sp<GrContext> context(new GrDDLContext(std::move(proxy)));
- if (!context->init(proxy->priv().refCaps())) {
+ if (!context->init()) {
return nullptr;
}
return context;
diff --git a/chromium/third_party/skia/src/gpu/GrDataUtils.cpp b/chromium/third_party/skia/src/gpu/GrDataUtils.cpp
index a6102fd24ca..7e6a6c734eb 100644
--- a/chromium/third_party/skia/src/gpu/GrDataUtils.cpp
+++ b/chromium/third_party/skia/src/gpu/GrDataUtils.cpp
@@ -7,6 +7,7 @@
#include "src/gpu/GrDataUtils.h"
+#include "include/third_party/skcms/skcms.h"
#include "src/core/SkColorSpaceXformSteps.h"
#include "src/core/SkCompressedDataUtils.h"
#include "src/core/SkConvertPixels.h"
@@ -595,10 +596,10 @@ bool GrConvertPixels(const GrImageInfo& dstInfo, void* dst, size_t dstRB,
if (hasConversion) {
loadSwizzle.apply(&pipeline);
if (srcIsSRGB) {
- pipeline.append(SkRasterPipeline::from_srgb);
+ pipeline.append_transfer_function(*skcms_sRGB_TransferFunction());
}
if (alphaOrCSConversion) {
- steps->apply(&pipeline, srcIsNormalized);
+ steps->apply(&pipeline);
}
if (clampGamut) {
append_clamp_gamut(&pipeline);
@@ -606,14 +607,14 @@ bool GrConvertPixels(const GrImageInfo& dstInfo, void* dst, size_t dstRB,
if (doLumToAlpha) {
pipeline.append(SkRasterPipeline::StockStage::bt709_luminance_or_luma_to_alpha);
// If we ever needed to convert from linear-encoded gray to sRGB-encoded
- // gray we'd have a problem here because the subsequent to_srgb stage
+ // gray we'd have a problem here because the subsequent transfer function stage
// ignores the alpha channel (where we just stashed the gray). There are
// several ways that could be fixed but given our current set of color types
// this should never happen.
SkASSERT(!dstIsSRGB);
}
if (dstIsSRGB) {
- pipeline.append(SkRasterPipeline::to_srgb);
+ pipeline.append_transfer_function(*skcms_sRGB_Inverse_TransferFunction());
}
storeSwizzle.apply(&pipeline);
} else {
@@ -664,14 +665,14 @@ bool GrClearImage(const GrImageInfo& dstInfo, void* dst, size_t dstRB, SkColor4f
if (doLumToAlpha) {
pipeline.append(SkRasterPipeline::StockStage::bt709_luminance_or_luma_to_alpha);
// If we ever needed to convert from linear-encoded gray to sRGB-encoded
- // gray we'd have a problem here because the subsequent to_srgb stage
+ // gray we'd have a problem here because the subsequent transfer function stage
// ignores the alpha channel (where we just stashed the gray). There are
// several ways that could be fixed but given our current set of color types
// this should never happen.
SkASSERT(!dstIsSRGB);
}
if (dstIsSRGB) {
- pipeline.append(SkRasterPipeline::to_srgb);
+ pipeline.append_transfer_function(*skcms_sRGB_Inverse_TransferFunction());
}
storeSwizzle.apply(&pipeline);
SkRasterPipeline_MemoryCtx dstCtx{dst, SkToInt(dstRB/dstInfo.bpp())};
diff --git a/chromium/third_party/skia/src/gpu/GrDefaultGeoProcFactory.cpp b/chromium/third_party/skia/src/gpu/GrDefaultGeoProcFactory.cpp
index 4f93238d1ae..94ba1846cbd 100644
--- a/chromium/third_party/skia/src/gpu/GrDefaultGeoProcFactory.cpp
+++ b/chromium/third_party/skia/src/gpu/GrDefaultGeoProcFactory.cpp
@@ -57,6 +57,7 @@ public:
public:
GLSLProcessor()
: fViewMatrix(SkMatrix::InvalidMatrix())
+ , fLocalMatrix(SkMatrix::InvalidMatrix())
, fColor(SK_PMColor4fILLEGAL)
, fCoverage(0xff) {}
@@ -111,14 +112,14 @@ public:
&fViewMatrixUniform);
// emit transforms using either explicit local coords or positions
- const auto& coordsAttr = gp.fInLocalCoords.isInitialized() ? gp.fInLocalCoords
- : gp.fInPosition;
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- coordsAttr.asShaderVar(),
- gp.localMatrix(),
- args.fFPCoordTransformHandler);
+ if (gp.fInLocalCoords.isInitialized()) {
+ SkASSERT(gp.localMatrix().isIdentity());
+ gpArgs->fLocalCoordVar = gp.fInLocalCoords.asShaderVar();
+ } else if (gp.fLocalCoordsWillBeRead) {
+ this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
+ gp.fInPosition.asShaderVar(), gp.localMatrix(),
+ &fLocalMatrixUniform);
+ }
// Setup coverage as pass through
if (gp.hasVertexCoverage() && !tweakAlpha) {
@@ -144,8 +145,12 @@ public:
const DefaultGeoProc& def = gp.cast<DefaultGeoProc>();
uint32_t key = def.fFlags;
key |= (def.coverage() == 0xff) ? 0x80 : 0;
- key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x100 : 0;
- key |= ComputePosKey(def.viewMatrix()) << 20;
+ key |= def.localCoordsWillBeRead() ? 0x100 : 0;
+
+ bool usesLocalMatrix = def.localCoordsWillBeRead() &&
+ !def.fInLocalCoords.isInitialized();
+ key = AddMatrixKeys(key, def.viewMatrix(),
+ usesLocalMatrix ? def.localMatrix() : SkMatrix::I());
b->add32(key);
}
@@ -154,12 +159,9 @@ public:
const CoordTransformRange& transformRange) override {
const DefaultGeoProc& dgp = gp.cast<DefaultGeoProc>();
- if (!dgp.viewMatrix().isIdentity() &&
- !SkMatrixPriv::CheapEqual(fViewMatrix, dgp.viewMatrix()))
- {
- fViewMatrix = dgp.viewMatrix();
- pdman.setSkMatrix(fViewMatrixUniform, fViewMatrix);
- }
+ this->setTransform(pdman, fViewMatrixUniform, dgp.viewMatrix(), &fViewMatrix);
+ this->setTransform(pdman, fLocalMatrixUniform, dgp.localMatrix(), &fLocalMatrix);
+ this->setTransformDataHelper(pdman, transformRange);
if (!dgp.hasVertexColor() && dgp.color() != fColor) {
pdman.set4fv(fColorUniform, 1, dgp.color().vec());
@@ -170,14 +172,15 @@ public:
pdman.set1f(fCoverageUniform, GrNormalizeByteToFloat(dgp.coverage()));
fCoverage = dgp.coverage();
}
- this->setTransformDataHelper(dgp.fLocalMatrix, pdman, transformRange);
}
private:
SkMatrix fViewMatrix;
+ SkMatrix fLocalMatrix;
SkPMColor4f fColor;
uint8_t fCoverage;
UniformHandle fViewMatrixUniform;
+ UniformHandle fLocalMatrixUniform;
UniformHandle fColorUniform;
UniformHandle fCoverageUniform;
diff --git a/chromium/third_party/skia/src/gpu/GrDrawingManager.cpp b/chromium/third_party/skia/src/gpu/GrDrawingManager.cpp
index 83af6b41c7d..5ae2684c582 100644
--- a/chromium/third_party/skia/src/gpu/GrDrawingManager.cpp
+++ b/chromium/third_party/skia/src/gpu/GrDrawingManager.cpp
@@ -10,6 +10,7 @@
#include "include/core/SkDeferredDisplayList.h"
#include "include/gpu/GrBackendSemaphore.h"
#include "include/private/GrRecordingContext.h"
+#include "src/core/SkDeferredDisplayListPriv.h"
#include "src/core/SkTTopoSort.h"
#include "src/gpu/GrAuditTrail.h"
#include "src/gpu/GrClientMappedBufferManager.h"
@@ -36,7 +37,7 @@
#include "src/gpu/GrTransferFromRenderTask.h"
#include "src/gpu/GrWaitRenderTask.h"
#include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h"
-#include "src/gpu/text/GrTextContext.h"
+#include "src/gpu/text/GrSDFTOptions.h"
#include "src/image/SkSurface_Gpu.h"
GrDrawingManager::RenderTaskDAG::RenderTaskDAG(bool sortRenderTasks)
@@ -57,27 +58,15 @@ void GrDrawingManager::RenderTaskDAG::reset() {
fRenderTasks.reset();
}
-void GrDrawingManager::RenderTaskDAG::removeRenderTask(int index) {
- if (!fRenderTasks[index]->unique()) {
- // TODO: Eventually this should be guaranteed unique: http://skbug.com/7111
- fRenderTasks[index]->endFlush();
- }
-
- fRenderTasks[index] = nullptr;
-}
-
void GrDrawingManager::RenderTaskDAG::removeRenderTasks(int startIndex, int stopIndex) {
for (int i = startIndex; i < stopIndex; ++i) {
- if (!fRenderTasks[i]) {
- continue;
- }
- this->removeRenderTask(i);
+ fRenderTasks[i] = nullptr;
}
}
bool GrDrawingManager::RenderTaskDAG::isUsed(GrSurfaceProxy* proxy) const {
- for (int i = 0; i < fRenderTasks.count(); ++i) {
- if (fRenderTasks[i] && fRenderTasks[i]->isUsed(proxy)) {
+ for (const auto& task : fRenderTasks) {
+ if (task && task->isUsed(proxy)) {
return true;
}
}
@@ -134,7 +123,7 @@ void GrDrawingManager::RenderTaskDAG::prepForFlush() {
GrOpsTask* curOpsTask = fRenderTasks[i]->asOpsTask();
if (prevOpsTask && curOpsTask) {
- SkASSERT(prevOpsTask->fTargetView != curOpsTask->fTargetView);
+ SkASSERT(prevOpsTask->target(0).proxy() != curOpsTask->target(0).proxy());
}
prevOpsTask = curOpsTask;
@@ -151,7 +140,7 @@ void GrDrawingManager::RenderTaskDAG::closeAll(const GrCaps* caps) {
}
}
-void GrDrawingManager::RenderTaskDAG::cleanup(const GrCaps* caps) {
+void GrDrawingManager::RenderTaskDAG::cleanup(GrDrawingManager* drawingMgr, const GrCaps* caps) {
for (int i = 0; i < fRenderTasks.count(); ++i) {
if (!fRenderTasks[i]) {
continue;
@@ -160,13 +149,15 @@ void GrDrawingManager::RenderTaskDAG::cleanup(const GrCaps* caps) {
// no renderTask should receive a dependency
fRenderTasks[i]->makeClosed(*caps);
+ fRenderTasks[i]->disown(drawingMgr);
+
// We shouldn't need to do this, but it turns out some clients still hold onto opsTasks
// after a cleanup.
// MDB TODO: is this still true?
if (!fRenderTasks[i]->unique()) {
// TODO: Eventually this should be guaranteed unique.
// https://bugs.chromium.org/p/skia/issues/detail?id=7111
- fRenderTasks[i]->endFlush();
+ fRenderTasks[i]->endFlush(drawingMgr);
}
}
@@ -176,22 +167,18 @@ void GrDrawingManager::RenderTaskDAG::cleanup(const GrCaps* caps) {
///////////////////////////////////////////////////////////////////////////////////////////////////
GrDrawingManager::GrDrawingManager(GrRecordingContext* context,
const GrPathRendererChain::Options& optionsForPathRendererChain,
- const GrTextContext::Options& optionsForTextContext,
bool sortRenderTasks,
bool reduceOpsTaskSplitting)
: fContext(context)
, fOptionsForPathRendererChain(optionsForPathRendererChain)
- , fOptionsForTextContext(optionsForTextContext)
, fDAG(sortRenderTasks)
- , fTextContext(nullptr)
, fPathRendererChain(nullptr)
, fSoftwarePathRenderer(nullptr)
, fFlushing(false)
- , fReduceOpsTaskSplitting(reduceOpsTaskSplitting) {
-}
+ , fReduceOpsTaskSplitting(reduceOpsTaskSplitting) { }
void GrDrawingManager::cleanup() {
- fDAG.cleanup(fContext->priv().caps());
+ fDAG.cleanup(this, fContext->priv().caps());
fPathRendererChain = nullptr;
fSoftwarePathRenderer = nullptr;
@@ -221,14 +208,20 @@ void GrDrawingManager::freeGpuResources() {
}
// MDB TODO: make use of the 'proxy' parameter.
-bool GrDrawingManager::flush(GrSurfaceProxy* proxies[], int numProxies,
- SkSurface::BackendSurfaceAccess access, const GrFlushInfo& info,
- const GrPrepareForExternalIORequests& externalRequests) {
+bool GrDrawingManager::flush(
+ GrSurfaceProxy* proxies[],
+ int numProxies,
+ SkSurface::BackendSurfaceAccess access,
+ const GrFlushInfo& info,
+ const GrBackendSurfaceMutableState* newState) {
SkASSERT(numProxies >= 0);
SkASSERT(!numProxies || proxies);
GR_CREATE_TRACE_MARKER_CONTEXT("GrDrawingManager", "flush", fContext);
if (fFlushing || this->wasAbandoned()) {
+ if (info.fSubmittedProc) {
+ info.fSubmittedProc(info.fSubmittedContext, false);
+ }
if (info.fFinishedProc) {
info.fFinishedProc(info.fFinishedContext);
}
@@ -238,18 +231,24 @@ bool GrDrawingManager::flush(GrSurfaceProxy* proxies[], int numProxies,
SkDEBUGCODE(this->validate());
if (kNone_GrFlushFlags == info.fFlags && !info.fNumSemaphores && !info.fFinishedProc &&
- !externalRequests.hasRequests()) {
+ access == SkSurface::BackendSurfaceAccess::kNoAccess && !newState) {
bool canSkip = numProxies > 0;
for (int i = 0; i < numProxies && canSkip; ++i) {
canSkip = !fDAG.isUsed(proxies[i]) && !this->isDDLTarget(proxies[i]);
}
if (canSkip) {
+ if (info.fSubmittedProc) {
+ info.fSubmittedProc(info.fSubmittedContext, true);
+ }
return false;
}
}
auto direct = fContext->priv().asDirectContext();
if (!direct) {
+ if (info.fSubmittedProc) {
+ info.fSubmittedProc(info.fSubmittedContext, false);
+ }
if (info.fFinishedProc) {
info.fFinishedProc(info.fFinishedContext);
}
@@ -258,12 +257,8 @@ bool GrDrawingManager::flush(GrSurfaceProxy* proxies[], int numProxies,
direct->priv().clientMappedBufferManager()->process();
GrGpu* gpu = direct->priv().getGpu();
- if (!gpu) {
- if (info.fFinishedProc) {
- info.fFinishedProc(info.fFinishedContext);
- }
- return false; // Can't flush while DDL recording
- }
+ // We have a non abandoned and direct GrContext. It must have a GrGpu.
+ SkASSERT(gpu);
fFlushing = true;
@@ -382,6 +377,7 @@ bool GrDrawingManager::flush(GrSurfaceProxy* proxies[], int numProxies,
SkASSERT(!fDAG.renderTask(i) || fDAG.renderTask(i)->unique());
}
#endif
+ fLastRenderTasks.reset();
fDAG.reset();
this->clearDDLTargets();
@@ -394,7 +390,7 @@ bool GrDrawingManager::flush(GrSurfaceProxy* proxies[], int numProxies,
opMemoryPool->isEmpty();
#endif
- gpu->executeFlushInfo(proxies, numProxies, access, info, externalRequests);
+ gpu->executeFlushInfo(proxies, numProxies, access, info, newState);
// Give the cache a chance to purge resources that become purgeable due to flushing.
if (flushed) {
@@ -471,6 +467,7 @@ bool GrDrawingManager::executeRenderTasks(int startIndex, int stopIndex, GrOpFlu
SkDebugf("WARNING: onFlushRenderTask failed to execute.\n");
}
SkASSERT(onFlushRenderTask->unique());
+ onFlushRenderTask->disown(this);
onFlushRenderTask = nullptr;
(*numRenderTasksExecuted)++;
if (*numRenderTasksExecuted >= kMaxRenderTasksBeforeFlush) {
@@ -505,15 +502,70 @@ bool GrDrawingManager::executeRenderTasks(int startIndex, int stopIndex, GrOpFlu
// resources are the last to be purged by the resource cache.
flushState->reset();
- fDAG.removeRenderTasks(startIndex, stopIndex);
+ this->removeRenderTasks(startIndex, stopIndex);
return anyRenderTasksExecuted;
}
-GrSemaphoresSubmitted GrDrawingManager::flushSurfaces(GrSurfaceProxy* proxies[], int numProxies,
- SkSurface::BackendSurfaceAccess access,
- const GrFlushInfo& info) {
+void GrDrawingManager::removeRenderTasks(int startIndex, int stopIndex) {
+ for (int i = startIndex; i < stopIndex; ++i) {
+ GrRenderTask* task = fDAG.renderTask(i);
+ if (!task) {
+ continue;
+ }
+ if (!task->unique()) {
+ // TODO: Eventually this should be guaranteed unique: http://skbug.com/7111
+ task->endFlush(this);
+ }
+ task->disown(this);
+ }
+ fDAG.removeRenderTasks(startIndex, stopIndex);
+}
+
+static void resolve_and_mipmap(GrGpu* gpu, GrSurfaceProxy* proxy) {
+ if (!proxy->isInstantiated()) {
+ return;
+ }
+
+ // In the flushSurfaces case, we need to resolve MSAA immediately after flush. This is
+ // because clients expect the flushed surface's backing texture to be fully resolved
+ // upon return.
+ if (proxy->requiresManualMSAAResolve()) {
+ auto* rtProxy = proxy->asRenderTargetProxy();
+ SkASSERT(rtProxy);
+ if (rtProxy->isMSAADirty()) {
+ SkASSERT(rtProxy->peekRenderTarget());
+ gpu->resolveRenderTarget(rtProxy->peekRenderTarget(), rtProxy->msaaDirtyRect(),
+ GrGpu::ForExternalIO::kYes);
+ rtProxy->markMSAAResolved();
+ }
+ }
+ // If, after a flush, any of the proxies of interest have dirty mipmaps, regenerate them in
+ // case their backend textures are being stolen.
+ // (This special case is exercised by the ReimportImageTextureWithMipLevels test.)
+ // FIXME: It may be more ideal to plumb down a "we're going to steal the backends" flag.
+ if (auto* textureProxy = proxy->asTextureProxy()) {
+ if (textureProxy->mipMapsAreDirty()) {
+ SkASSERT(textureProxy->peekTexture());
+ gpu->regenerateMipMapLevels(textureProxy->peekTexture());
+ textureProxy->markMipMapsClean();
+ }
+ }
+}
+
+GrSemaphoresSubmitted GrDrawingManager::flushSurfaces(
+ GrSurfaceProxy* proxies[],
+ int numProxies,
+ SkSurface::BackendSurfaceAccess access,
+ const GrFlushInfo& info,
+ const GrBackendSurfaceMutableState* newState) {
if (this->wasAbandoned()) {
+ if (info.fSubmittedProc) {
+ info.fSubmittedProc(info.fSubmittedContext, false);
+ }
+ if (info.fFinishedProc) {
+ info.fFinishedProc(info.fFinishedContext);
+ }
return GrSemaphoresSubmitted::kNo;
}
SkDEBUGCODE(this->validate());
@@ -522,59 +574,30 @@ GrSemaphoresSubmitted GrDrawingManager::flushSurfaces(GrSurfaceProxy* proxies[],
auto direct = fContext->priv().asDirectContext();
if (!direct) {
+ if (info.fSubmittedProc) {
+ info.fSubmittedProc(info.fSubmittedContext, false);
+ }
+ if (info.fFinishedProc) {
+ info.fFinishedProc(info.fFinishedContext);
+ }
return GrSemaphoresSubmitted::kNo; // Can't flush while DDL recording
}
GrGpu* gpu = direct->priv().getGpu();
- if (!gpu) {
- return GrSemaphoresSubmitted::kNo; // Can't flush while DDL recording
- }
+ // We have a non abandoned and direct GrContext. It must have a GrGpu.
+ SkASSERT(gpu);
// TODO: It is important to upgrade the drawingmanager to just flushing the
// portion of the DAG required by 'proxies' in order to restore some of the
// semantics of this method.
- bool didFlush = this->flush(proxies, numProxies, access, info,
- GrPrepareForExternalIORequests());
+ bool didFlush = this->flush(proxies, numProxies, access, info, newState);
for (int i = 0; i < numProxies; ++i) {
- GrSurfaceProxy* proxy = proxies[i];
- if (!proxy->isInstantiated()) {
- continue;
- }
- // In the flushSurfaces case, we need to resolve MSAA immediately after flush. This is
- // because the client will call through to this method when drawing into a target created by
- // wrapBackendTextureAsRenderTarget, and will expect the original texture to be fully
- // resolved upon return.
- if (proxy->requiresManualMSAAResolve()) {
- auto* rtProxy = proxy->asRenderTargetProxy();
- SkASSERT(rtProxy);
- if (rtProxy->isMSAADirty()) {
- SkASSERT(rtProxy->peekRenderTarget());
- gpu->resolveRenderTarget(rtProxy->peekRenderTarget(), rtProxy->msaaDirtyRect(),
- GrGpu::ForExternalIO::kYes);
- rtProxy->markMSAAResolved();
- }
- }
- // If, after a flush, any of the proxies of interest have dirty mipmaps, regenerate them in
- // case their backend textures are being stolen.
- // (This special case is exercised by the ReimportImageTextureWithMipLevels test.)
- // FIXME: It may be more ideal to plumb down a "we're going to steal the backends" flag.
- if (auto* textureProxy = proxy->asTextureProxy()) {
- if (textureProxy->mipMapsAreDirty()) {
- SkASSERT(textureProxy->peekTexture());
- gpu->regenerateMipMapLevels(textureProxy->peekTexture());
- textureProxy->markMipMapsClean();
- }
- }
+ resolve_and_mipmap(gpu, proxies[i]);
}
SkDEBUGCODE(this->validate());
- bool submitted = false;
- if (didFlush) {
- submitted = this->submitToGpu(SkToBool(info.fFlags & kSyncCpu_GrFlushFlag));
- }
-
- if (!submitted || (!direct->priv().caps()->semaphoreSupport() && info.fNumSemaphores)) {
+ if (!didFlush || (!direct->priv().caps()->semaphoreSupport() && info.fNumSemaphores)) {
return GrSemaphoresSubmitted::kNo;
}
return GrSemaphoresSubmitted::kYes;
@@ -593,6 +616,31 @@ void GrDrawingManager::testingOnly_removeOnFlushCallbackObject(GrOnFlushCallback
}
#endif
+void GrDrawingManager::setLastRenderTask(const GrSurfaceProxy* proxy, GrRenderTask* task) {
+#ifdef SK_DEBUG
+ if (GrRenderTask* prior = this->getLastRenderTask(proxy)) {
+ SkASSERT(prior->isClosed());
+ }
+#endif
+ uint32_t key = proxy->uniqueID().asUInt();
+ if (task) {
+ fLastRenderTasks.set(key, task);
+ } else if (fLastRenderTasks.find(key)) {
+ fLastRenderTasks.remove(key);
+ }
+}
+
+GrRenderTask* GrDrawingManager::getLastRenderTask(const GrSurfaceProxy* proxy) const {
+ auto entry = fLastRenderTasks.find(proxy->uniqueID().asUInt());
+ return entry ? *entry : nullptr;
+}
+
+GrOpsTask* GrDrawingManager::getLastOpsTask(const GrSurfaceProxy* proxy) const {
+ GrRenderTask* task = this->getLastRenderTask(proxy);
+ return task ? task->asOpsTask() : nullptr;
+}
+
+
void GrDrawingManager::moveRenderTasksToDDL(SkDeferredDisplayList* ddl) {
SkDEBUGCODE(this->validate());
@@ -604,6 +652,7 @@ void GrDrawingManager::moveRenderTasksToDDL(SkDeferredDisplayList* ddl) {
SkASSERT(!fDAG.numRenderTasks());
for (auto& renderTask : ddl->fRenderTasks) {
+ renderTask->disown(this);
renderTask->prePrepare(fContext);
}
@@ -633,7 +682,17 @@ void GrDrawingManager::copyRenderTasksFromDDL(const SkDeferredDisplayList* ddl,
fActiveOpsTask = nullptr;
}
- this->addDDLTarget(newDest);
+ // Propagate the DDL proxy's state information to the replaying DDL.
+ if (ddl->priv().targetProxy()->isMSAADirty()) {
+ newDest->markMSAADirty(ddl->priv().targetProxy()->msaaDirtyRect(),
+ ddl->characterization().origin());
+ }
+ GrTextureProxy* newTextureProxy = newDest->asTextureProxy();
+ if (newTextureProxy && GrMipMapped::kYes == newTextureProxy->mipMapped()) {
+ newTextureProxy->markMipMapsDirty();
+ }
+
+ this->addDDLTarget(newDest, ddl->priv().targetProxy());
// Here we jam the proxy that backs the current replay SkSurface into the LazyProxyData.
// The lazy proxy that references it (in the copied opsTasks) will steal its GrTexture.
@@ -685,7 +744,7 @@ void GrDrawingManager::closeRenderTasksForNewRenderTask(GrSurfaceProxy* target)
// split in case they use both the old and new content. (This is a bit of an overkill: they
// really only need to be split if they ever reference proxy's contents again but that is
// hard to predict/handle).
- if (GrRenderTask* lastRenderTask = target->getLastRenderTask()) {
+ if (GrRenderTask* lastRenderTask = this->getLastRenderTask(target)) {
lastRenderTask->closeThoseWhoDependOnMe(*fContext->priv().caps());
}
} else if (fActiveOpsTask) {
@@ -706,10 +765,10 @@ sk_sp<GrOpsTask> GrDrawingManager::newOpsTask(GrSurfaceProxyView surfaceView,
GrSurfaceProxy* proxy = surfaceView.proxy();
this->closeRenderTasksForNewRenderTask(proxy);
- sk_sp<GrOpsTask> opsTask(new GrOpsTask(fContext->priv().arenas(),
+ sk_sp<GrOpsTask> opsTask(new GrOpsTask(this, fContext->priv().arenas(),
std::move(surfaceView),
fContext->priv().auditTrail()));
- SkASSERT(proxy->getLastRenderTask() == opsTask.get());
+ SkASSERT(this->getLastRenderTask(proxy) == opsTask.get());
if (managedOpsTask) {
fDAG.add(opsTask);
@@ -749,7 +808,7 @@ void GrDrawingManager::newWaitRenderTask(sk_sp<GrSurfaceProxy> proxy,
std::move(semaphores),
numSemaphores);
if (fReduceOpsTaskSplitting) {
- GrRenderTask* lastTask = proxy->getLastRenderTask();
+ GrRenderTask* lastTask = this->getLastRenderTask(proxy.get());
if (lastTask && !lastTask->isClosed()) {
// We directly make the currently open renderTask depend on waitTask instead of using
// the proxy version of addDependency. The waitTask will never need to trigger any
@@ -773,12 +832,12 @@ void GrDrawingManager::newWaitRenderTask(sk_sp<GrSurfaceProxy> proxy,
if (lastTask) {
waitTask->addDependency(lastTask);
}
- proxy->setLastRenderTask(waitTask.get());
+ this->setLastRenderTask(proxy.get(), waitTask.get());
}
fDAG.add(waitTask);
} else {
- if (fActiveOpsTask && (fActiveOpsTask->fTargetView.proxy() == proxy.get())) {
- SkASSERT(proxy->getLastRenderTask() == fActiveOpsTask);
+ if (fActiveOpsTask && (fActiveOpsTask->target(0).proxy() == proxy.get())) {
+ SkASSERT(this->getLastRenderTask(proxy.get()) == fActiveOpsTask);
fDAG.addBeforeLast(waitTask);
// In this case we keep the current renderTask open but just insert the new waitTask
// before it in the list. The waitTask will never need to trigger any resolves or mip
@@ -800,10 +859,10 @@ void GrDrawingManager::newWaitRenderTask(sk_sp<GrSurfaceProxy> proxy,
// there is a lastTask on the proxy we make waitTask depend on that task. This
// dependency isn't strictly needed but it does keep the DAG from reordering the
// waitTask earlier and blocking more tasks.
- if (GrRenderTask* lastTask = proxy->getLastRenderTask()) {
+ if (GrRenderTask* lastTask = this->getLastRenderTask(proxy.get())) {
waitTask->addDependency(lastTask);
}
- proxy->setLastRenderTask(waitTask.get());
+ this->setLastRenderTask(proxy.get(), waitTask.get());
this->closeRenderTasksForNewRenderTask(proxy.get());
fDAG.add(waitTask);
}
@@ -825,13 +884,15 @@ void GrDrawingManager::newTransferFromRenderTask(sk_sp<GrSurfaceProxy> srcProxy,
this->closeRenderTasksForNewRenderTask(nullptr);
GrRenderTask* task = fDAG.add(sk_make_sp<GrTransferFromRenderTask>(
- srcProxy, srcRect, surfaceColorType, dstColorType, std::move(dstBuffer), dstOffset));
+ srcProxy, srcRect, surfaceColorType, dstColorType,
+ std::move(dstBuffer), dstOffset));
const GrCaps& caps = *fContext->priv().caps();
// We always say GrMipMapped::kNo here since we are always just copying from the base layer. We
// don't need to make sure the whole mip map chain is valid.
- task->addDependency(srcProxy.get(), GrMipMapped::kNo, GrTextureResolveManager(this), caps);
+ task->addDependency(this, srcProxy.get(), GrMipMapped::kNo,
+ GrTextureResolveManager(this), caps);
task->makeClosed(caps);
// We have closed the previous active oplist but since a new oplist isn't being added there
@@ -853,7 +914,7 @@ bool GrDrawingManager::newCopyRenderTask(GrSurfaceProxyView srcView,
GrSurfaceProxy* srcProxy = srcView.proxy();
GrRenderTask* task =
- fDAG.add(GrCopyRenderTask::Make(std::move(srcView), srcRect, std::move(dstView),
+ fDAG.add(GrCopyRenderTask::Make(this, std::move(srcView), srcRect, std::move(dstView),
dstPoint, &caps));
if (!task) {
return false;
@@ -861,7 +922,7 @@ bool GrDrawingManager::newCopyRenderTask(GrSurfaceProxyView srcView,
// We always say GrMipMapped::kNo here since we are always just copying from the base layer to
// another base layer. We don't need to make sure the whole mip map chain is valid.
- task->addDependency(srcProxy, GrMipMapped::kNo, GrTextureResolveManager(this), caps);
+ task->addDependency(this, srcProxy, GrMipMapped::kNo, GrTextureResolveManager(this), caps);
task->makeClosed(caps);
// We have closed the previous active oplist but since a new oplist isn't being added there
@@ -871,14 +932,6 @@ bool GrDrawingManager::newCopyRenderTask(GrSurfaceProxyView srcView,
return true;
}
-GrTextContext* GrDrawingManager::getTextContext() {
- if (!fTextContext) {
- fTextContext = GrTextContext::Make(fOptionsForTextContext);
- }
-
- return fTextContext.get();
-}
-
/*
* This method finds a path renderer that can draw the specified path on
* the provided target.
@@ -936,7 +989,7 @@ void GrDrawingManager::flushIfNecessary() {
auto resourceCache = direct->priv().getResourceCache();
if (resourceCache && resourceCache->requestsFlush()) {
if (this->flush(nullptr, 0, SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo(),
- GrPrepareForExternalIORequests())) {
+ nullptr)) {
this->submitToGpu(false);
}
resourceCache->purgeAsNeeded();
diff --git a/chromium/third_party/skia/src/gpu/GrDrawingManager.h b/chromium/third_party/skia/src/gpu/GrDrawingManager.h
index fcb5466e18f..77c1dd95ce5 100644
--- a/chromium/third_party/skia/src/gpu/GrDrawingManager.h
+++ b/chromium/third_party/skia/src/gpu/GrDrawingManager.h
@@ -8,26 +8,30 @@
#ifndef GrDrawingManager_DEFINED
#define GrDrawingManager_DEFINED
-#include <set>
#include "include/core/SkSurface.h"
#include "include/private/SkTArray.h"
+#include "include/private/SkTHash.h"
#include "src/gpu/GrBufferAllocPool.h"
#include "src/gpu/GrDeferredUpload.h"
+#include "src/gpu/GrHashMapWithCache.h"
#include "src/gpu/GrPathRenderer.h"
#include "src/gpu/GrPathRendererChain.h"
#include "src/gpu/GrResourceCache.h"
-#include "src/gpu/text/GrTextContext.h"
+#include "src/gpu/GrSurfaceProxy.h"
// Enabling this will print out which path renderers are being chosen
#define GR_PATH_RENDERER_SPEW 0
class GrCoverageCountingPathRenderer;
+class GrGpuBuffer;
class GrOnFlushCallbackObject;
class GrOpFlushState;
class GrOpsTask;
class GrRecordingContext;
class GrRenderTargetContext;
class GrRenderTargetProxy;
+class GrRenderTask;
+class GrSemaphore;
class GrSoftwarePathRenderer;
class GrSurfaceContext;
class GrSurfaceProxyView;
@@ -78,8 +82,6 @@ public:
GrRecordingContext* getContext() { return fContext; }
- GrTextContext* getTextContext();
-
GrPathRenderer* getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
bool allowSW,
GrPathRendererChain::DrawType drawType,
@@ -98,11 +100,13 @@ public:
GrSemaphoresSubmitted flushSurfaces(GrSurfaceProxy* proxies[],
int cnt,
SkSurface::BackendSurfaceAccess access,
- const GrFlushInfo& info);
+ const GrFlushInfo& info,
+ const GrBackendSurfaceMutableState* newState);
GrSemaphoresSubmitted flushSurface(GrSurfaceProxy* proxy,
SkSurface::BackendSurfaceAccess access,
- const GrFlushInfo& info) {
- return this->flushSurfaces(&proxy, 1, access, info);
+ const GrFlushInfo& info,
+ const GrBackendSurfaceMutableState* newState) {
+ return this->flushSurfaces(&proxy, 1, access, info, newState);
}
void addOnFlushCallbackObject(GrOnFlushCallbackObject*);
@@ -111,6 +115,10 @@ public:
void testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject*);
#endif
+ GrRenderTask* getLastRenderTask(const GrSurfaceProxy*) const;
+ GrOpsTask* getLastOpsTask(const GrSurfaceProxy*) const;
+ void setLastRenderTask(const GrSurfaceProxy*, GrRenderTask*);
+
void moveRenderTasksToDDL(SkDeferredDisplayList* ddl);
void copyRenderTasksFromDDL(const SkDeferredDisplayList*, GrRenderTargetProxy* newDest);
@@ -130,7 +138,7 @@ private:
void closeAll(const GrCaps* caps);
// A yucky combination of closeAll and reset
- void cleanup(const GrCaps* caps);
+ void cleanup(GrDrawingManager*, const GrCaps* caps);
void gatherIDs(SkSTArray<8, uint32_t, true>* idArray) const;
@@ -167,8 +175,8 @@ private:
bool fSortRenderTasks;
};
- GrDrawingManager(GrRecordingContext*, const GrPathRendererChain::Options&,
- const GrTextContext::Options&,
+ GrDrawingManager(GrRecordingContext*,
+ const GrPathRendererChain::Options&,
bool sortRenderTasks,
bool reduceOpsTaskSplitting);
@@ -185,11 +193,13 @@ private:
bool executeRenderTasks(int startIndex, int stopIndex, GrOpFlushState*,
int* numRenderTasksExecuted);
+ void removeRenderTasks(int startIndex, int stopIndex);
+
bool flush(GrSurfaceProxy* proxies[],
int numProxies,
SkSurface::BackendSurfaceAccess access,
const GrFlushInfo&,
- const GrPrepareForExternalIORequests&);
+ const GrBackendSurfaceMutableState* newState);
bool submitToGpu(bool syncToCpu);
@@ -206,7 +216,7 @@ private:
GrRecordingContext* fContext;
GrPathRendererChain::Options fOptionsForPathRendererChain;
- GrTextContext::Options fOptionsForTextContext;
+
// This cache is used by both the vertex and index pools. It reuses memory across multiple
// flushes.
sk_sp<GrBufferAllocPool::CpuBufferCache> fCpuBufferCache;
@@ -218,8 +228,6 @@ private:
// These are the new renderTasks generated by the onFlush CBs
SkSTArray<4, sk_sp<GrRenderTask>> fOnFlushRenderTasks;
- std::unique_ptr<GrTextContext> fTextContext;
-
std::unique_ptr<GrPathRendererChain> fPathRendererChain;
sk_sp<GrSoftwarePathRenderer> fSoftwarePathRenderer;
@@ -229,15 +237,31 @@ private:
SkTArray<GrOnFlushCallbackObject*> fOnFlushCBObjects;
- void addDDLTarget(GrSurfaceProxy* proxy) { fDDLTargets.insert(proxy); }
- bool isDDLTarget(GrSurfaceProxy* proxy) { return fDDLTargets.find(proxy) != fDDLTargets.end(); }
- void clearDDLTargets() { fDDLTargets.clear(); }
+ void addDDLTarget(GrSurfaceProxy* newTarget, GrRenderTargetProxy* ddlTarget) {
+ fDDLTargets.set(newTarget->uniqueID().asUInt(), ddlTarget);
+ }
+ bool isDDLTarget(GrSurfaceProxy* newTarget) {
+ return SkToBool(fDDLTargets.find(newTarget->uniqueID().asUInt()));
+ }
+ GrRenderTargetProxy* getDDLTarget(GrSurfaceProxy* newTarget) {
+ auto entry = fDDLTargets.find(newTarget->uniqueID().asUInt());
+ return entry ? *entry : nullptr;
+ }
+ void clearDDLTargets() { fDDLTargets.reset(); }
// We play a trick with lazy proxies to retarget the base target of a DDL to the SkSurface
- // it is replayed on. Because of this remapping we need to explicitly store the targets of
- // DDL replaying.
+ // it is replayed on. 'fDDLTargets' stores this mapping from SkSurface unique proxy ID
+ // to the DDL's lazy proxy.
// Note: we do not expect a whole lot of these per flush
- std::set<GrSurfaceProxy*> fDDLTargets;
+ SkTHashMap<uint32_t, GrRenderTargetProxy*> fDDLTargets;
+
+ struct SurfaceIDKeyTraits {
+ static uint32_t GetInvalidKey() {
+ return GrSurfaceProxy::UniqueID::InvalidID().asUInt();
+ }
+ };
+
+ GrHashMapWithCache<uint32_t, GrRenderTask*, SurfaceIDKeyTraits, GrCheapHash> fLastRenderTasks;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrDynamicAtlas.cpp b/chromium/third_party/skia/src/gpu/GrDynamicAtlas.cpp
index 00d0947728d..2bc309b7736 100644
--- a/chromium/third_party/skia/src/gpu/GrDynamicAtlas.cpp
+++ b/chromium/third_party/skia/src/gpu/GrDynamicAtlas.cpp
@@ -7,31 +7,33 @@
#include "src/gpu/GrDynamicAtlas.h"
+#include "src/core/SkIPoint16.h"
#include "src/gpu/GrOnFlushResourceProvider.h"
#include "src/gpu/GrProxyProvider.h"
+#include "src/gpu/GrRectanizerPow2.h"
#include "src/gpu/GrRectanizerSkyline.h"
#include "src/gpu/GrRenderTarget.h"
-#include "src/gpu/GrRenderTargetContext.h"
+#include "src/gpu/GrRenderTargetContextPriv.h"
// Each Node covers a sub-rectangle of the final atlas. When a GrDynamicAtlas runs out of room, we
// create a new Node the same size as all combined nodes in the atlas as-is, and then place the new
// Node immediately below or beside the others (thereby doubling the size of the GyDynamicAtlas).
class GrDynamicAtlas::Node {
public:
- Node(std::unique_ptr<Node> previous, int l, int t, int r, int b)
- : fPrevious(std::move(previous)), fX(l), fY(t), fRectanizer(r - l, b - t) {}
+ Node(Node* previous, GrRectanizer* rectanizer, int x, int y)
+ : fPrevious(previous), fRectanizer(rectanizer), fX(x), fY(y) {}
- Node* previous() const { return fPrevious.get(); }
+ Node* previous() const { return fPrevious; }
bool addRect(int w, int h, SkIPoint16* loc) {
// Pad all paths except those that are expected to take up an entire physical texture.
- if (w < fRectanizer.width()) {
- w = std::min(w + kPadding, fRectanizer.width());
+ if (w < fRectanizer->width()) {
+ w = std::min(w + kPadding, fRectanizer->width());
}
- if (h < fRectanizer.height()) {
- h = std::min(h + kPadding, fRectanizer.height());
+ if (h < fRectanizer->height()) {
+ h = std::min(h + kPadding, fRectanizer->height());
}
- if (!fRectanizer.addRect(w, h, loc)) {
+ if (!fRectanizer->addRect(w, h, loc)) {
return false;
}
loc->fX += fX;
@@ -40,9 +42,9 @@ public:
}
private:
- const std::unique_ptr<Node> fPrevious;
+ Node* const fPrevious;
+ GrRectanizer* const fRectanizer;
const int fX, fY;
- GrRectanizerSkyline fRectanizer;
};
sk_sp<GrTextureProxy> GrDynamicAtlas::MakeLazyAtlasProxy(
@@ -66,10 +68,12 @@ sk_sp<GrTextureProxy> GrDynamicAtlas::MakeLazyAtlasProxy(
}
GrDynamicAtlas::GrDynamicAtlas(GrColorType colorType, InternalMultisample internalMultisample,
- SkISize initialSize, int maxAtlasSize, const GrCaps& caps)
+ SkISize initialSize, int maxAtlasSize, const GrCaps& caps,
+ RectanizerAlgorithm algorithm)
: fColorType(colorType)
, fInternalMultisample(internalMultisample)
- , fMaxAtlasSize(maxAtlasSize) {
+ , fMaxAtlasSize(maxAtlasSize)
+ , fRectanizerAlgorithm(algorithm) {
SkASSERT(fMaxAtlasSize <= caps.maxTextureSize());
this->reset(initialSize, caps);
}
@@ -78,6 +82,7 @@ GrDynamicAtlas::~GrDynamicAtlas() {
}
void GrDynamicAtlas::reset(SkISize initialSize, const GrCaps& caps) {
+ fNodeAllocator.reset();
fWidth = std::min(SkNextPow2(initialSize.width()), fMaxAtlasSize);
fHeight = std::min(SkNextPow2(initialSize.height()), fMaxAtlasSize);
fTopNode = nullptr;
@@ -95,18 +100,25 @@ void GrDynamicAtlas::reset(SkISize initialSize, const GrCaps& caps) {
fBackingTexture = nullptr;
}
-bool GrDynamicAtlas::addRect(const SkIRect& devIBounds, SkIVector* offset) {
+GrDynamicAtlas::Node* GrDynamicAtlas::makeNode(Node* previous, int l, int t, int r, int b) {
+ int width = r - l;
+ int height = b - t;
+ GrRectanizer* rectanizer = (fRectanizerAlgorithm == RectanizerAlgorithm::kSkyline)
+ ? (GrRectanizer*)fNodeAllocator.make<GrRectanizerSkyline>(width, height)
+ : fNodeAllocator.make<GrRectanizerPow2>(width, height);
+ return fNodeAllocator.make<Node>(previous, rectanizer, l, t);
+}
+
+bool GrDynamicAtlas::addRect(int width, int height, SkIPoint16* location) {
// This can't be called anymore once instantiate() has been called.
SkASSERT(!this->isInstantiated());
- SkIPoint16 location;
- if (!this->internalPlaceRect(devIBounds.width(), devIBounds.height(), &location)) {
+ if (!this->internalPlaceRect(width, height, location)) {
return false;
}
- offset->set(location.x() - devIBounds.left(), location.y() - devIBounds.top());
- fDrawBounds.fWidth = std::max(fDrawBounds.width(), location.x() + devIBounds.width());
- fDrawBounds.fHeight = std::max(fDrawBounds.height(), location.y() + devIBounds.height());
+ fDrawBounds.fWidth = std::max(fDrawBounds.width(), location->x() + width);
+ fDrawBounds.fHeight = std::max(fDrawBounds.height(), location->y() + height);
return true;
}
@@ -126,10 +138,10 @@ bool GrDynamicAtlas::internalPlaceRect(int w, int h, SkIPoint16* loc) {
if (h > fHeight) {
fHeight = std::min(SkNextPow2(h), fMaxAtlasSize);
}
- fTopNode = std::make_unique<Node>(nullptr, 0, 0, fWidth, fHeight);
+ fTopNode = this->makeNode(nullptr, 0, 0, fWidth, fHeight);
}
- for (Node* node = fTopNode.get(); node; node = node->previous()) {
+ for (Node* node = fTopNode; node; node = node->previous()) {
if (node->addRect(w, h, loc)) {
return true;
}
@@ -143,11 +155,11 @@ bool GrDynamicAtlas::internalPlaceRect(int w, int h, SkIPoint16* loc) {
if (fHeight <= fWidth) {
int top = fHeight;
fHeight = std::min(fHeight * 2, fMaxAtlasSize);
- fTopNode = std::make_unique<Node>(std::move(fTopNode), 0, top, fWidth, fHeight);
+ fTopNode = this->makeNode(fTopNode, 0, top, fWidth, fHeight);
} else {
int left = fWidth;
fWidth = std::min(fWidth * 2, fMaxAtlasSize);
- fTopNode = std::make_unique<Node>(std::move(fTopNode), left, 0, fWidth, fHeight);
+ fTopNode = this->makeNode(fTopNode, left, 0, fWidth, fHeight);
}
} while (!fTopNode->addRect(w, h, loc));
@@ -187,7 +199,6 @@ std::unique_ptr<GrRenderTargetContext> GrDynamicAtlas::instantiate(
}
SkIRect clearRect = SkIRect::MakeSize(fDrawBounds);
- rtc->clear(&clearRect, SK_PMColor4fTRANSPARENT,
- GrRenderTargetContext::CanClearFullscreen::kYes);
+ rtc->priv().clearAtLeast(clearRect, SK_PMColor4fTRANSPARENT);
return rtc;
}
diff --git a/chromium/third_party/skia/src/gpu/GrDynamicAtlas.h b/chromium/third_party/skia/src/gpu/GrDynamicAtlas.h
index 7a7780cc8c8..e96ffe8f590 100644
--- a/chromium/third_party/skia/src/gpu/GrDynamicAtlas.h
+++ b/chromium/third_party/skia/src/gpu/GrDynamicAtlas.h
@@ -8,6 +8,7 @@
#ifndef GrDynamicAtlas_DEFINED
#define GrDynamicAtlas_DEFINED
+#include "src/core/SkArenaAlloc.h"
#include "src/gpu/GrTextureProxy.h"
class GrOnFlushResourceProvider;
@@ -41,20 +42,27 @@ public:
const GrCaps&,
GrSurfaceProxy::UseAllocator);
+ enum class RectanizerAlgorithm {
+ kSkyline,
+ kPow2
+ };
+
GrDynamicAtlas(GrColorType colorType, InternalMultisample, SkISize initialSize,
- int maxAtlasSize, const GrCaps&);
+ int maxAtlasSize, const GrCaps&,
+ RectanizerAlgorithm = RectanizerAlgorithm::kSkyline);
virtual ~GrDynamicAtlas();
void reset(SkISize initialSize, const GrCaps& desc);
+ int maxAtlasSize() const { return fMaxAtlasSize; }
GrTextureProxy* textureProxy() const { return fTextureProxy.get(); }
bool isInstantiated() const { return fTextureProxy->isInstantiated(); }
int currentWidth() const { return fWidth; }
int currentHeight() const { return fHeight; }
- // Attempts to add a rect to the atlas. If successful, returns the integer offset from
- // device-space pixels where the path will be drawn, to atlas pixels where its mask resides.
- bool addRect(const SkIRect& devIBounds, SkIVector* atlasOffset);
+ // Attempts to add a rect to the atlas. Returns true if successful, along with the rect's
+ // top-left location in the atlas.
+ bool addRect(int width, int height, SkIPoint16* location);
const SkISize& drawBounds() { return fDrawBounds; }
// Instantiates our texture proxy for the atlas and returns a pre-cleared GrRenderTargetContext
@@ -70,16 +78,20 @@ public:
private:
class Node;
+ Node* makeNode(Node* previous, int l, int t, int r, int b);
bool internalPlaceRect(int w, int h, SkIPoint16* loc);
const GrColorType fColorType;
const InternalMultisample fInternalMultisample;
const int fMaxAtlasSize;
+ const RectanizerAlgorithm fRectanizerAlgorithm;
int fWidth;
int fHeight;
- std::unique_ptr<Node> fTopNode;
SkISize fDrawBounds;
+ SkSTArenaAlloc<512> fNodeAllocator;
+ Node* fTopNode = nullptr;
+
sk_sp<GrTextureProxy> fTextureProxy;
sk_sp<GrTexture> fBackingTexture;
};
diff --git a/chromium/third_party/skia/src/gpu/GrFPArgs.h b/chromium/third_party/skia/src/gpu/GrFPArgs.h
index 3058f8681de..6b21e32602c 100644
--- a/chromium/third_party/skia/src/gpu/GrFPArgs.h
+++ b/chromium/third_party/skia/src/gpu/GrFPArgs.h
@@ -28,7 +28,13 @@ struct GrFPArgs {
}
class WithPreLocalMatrix;
- class WithPostLocalMatrix;
+
+ GrFPArgs withNewMatrixProvider(const SkMatrixProvider& provider) const {
+ GrFPArgs newArgs(fContext, provider, fFilterQuality, fDstColorInfo);
+ newArgs.fInputColorIsOpaque = fInputColorIsOpaque;
+ newArgs.fPreLocalMatrix = fPreLocalMatrix;
+ return newArgs;
+ }
GrRecordingContext* fContext;
const SkMatrixProvider& fMatrixProvider;
@@ -65,4 +71,3 @@ private:
};
#endif
-
diff --git a/chromium/third_party/skia/src/gpu/GrFixedClip.cpp b/chromium/third_party/skia/src/gpu/GrFixedClip.cpp
index 51f2f9d7bda..2f75bc9a4bf 100644
--- a/chromium/third_party/skia/src/gpu/GrFixedClip.cpp
+++ b/chromium/third_party/skia/src/gpu/GrFixedClip.cpp
@@ -14,47 +14,33 @@ bool GrFixedClip::quickContains(const SkRect& rect) const {
if (fWindowRectsState.enabled()) {
return false;
}
+
return !fScissorState.enabled() || GrClip::IsInsideClip(fScissorState.rect(), rect);
}
-SkIRect GrFixedClip::getConservativeBounds(int w, int h) const {
- SkIRect devResult = this->GrClip::getConservativeBounds(w, h);
- if (fScissorState.enabled()) {
- if (!devResult.intersect(fScissorState.rect())) {
- devResult.setEmpty();
- }
- }
- return devResult;
+SkIRect GrFixedClip::getConservativeBounds() const {
+ return fScissorState.rect();
}
-bool GrFixedClip::isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA* aa) const {
+bool GrFixedClip::isRRect(SkRRect* rr, GrAA* aa) const {
if (fWindowRectsState.enabled()) {
return false;
}
- if (fScissorState.enabled()) {
- SkRect rect = SkRect::Make(fScissorState.rect());
- if (!rect.intersects(rtBounds)) {
- return false;
- }
- rr->setRect(rect);
- *aa = GrAA::kNo;
- return true;
- }
- return false;
+ // Whether or not the scissor test is enabled, the remaining clip is a rectangle described
+ // by scissorState.rect() (either the scissor or the rt bounds).
+ rr->setRect(SkRect::Make(fScissorState.rect()));
+ *aa = GrAA::kNo;
+ return true;
};
-bool GrFixedClip::apply(int rtWidth, int rtHeight, GrAppliedHardClip* out, SkRect* bounds) const {
- if (fScissorState.enabled()) {
- SkIRect tightScissor = SkIRect::MakeWH(rtWidth, rtHeight);
- if (!tightScissor.intersect(fScissorState.rect())) {
- return false;
- }
- if (IsOutsideClip(tightScissor, *bounds)) {
- return false;
- }
- if (!IsInsideClip(fScissorState.rect(), *bounds)) {
- out->addScissor(tightScissor, bounds);
- }
+bool GrFixedClip::apply(GrAppliedHardClip* out, SkRect* bounds) const {
+ if (IsOutsideClip(fScissorState.rect(), *bounds)) {
+ return false;
+ }
+ if (!IsInsideClip(fScissorState.rect(), *bounds)) {
+ SkIRect tightScissor = bounds->roundOut();
+ SkAssertResult(tightScissor.intersect(fScissorState.rect()));
+ out->addScissor(tightScissor, bounds);
}
if (fWindowRectsState.enabled()) {
@@ -63,8 +49,3 @@ bool GrFixedClip::apply(int rtWidth, int rtHeight, GrAppliedHardClip* out, SkRec
return true;
}
-
-const GrFixedClip& GrFixedClip::Disabled() {
- static const GrFixedClip disabled = GrFixedClip();
- return disabled;
-}
diff --git a/chromium/third_party/skia/src/gpu/GrFixedClip.h b/chromium/third_party/skia/src/gpu/GrFixedClip.h
index 1f175f83bee..5abc3102c2f 100644
--- a/chromium/third_party/skia/src/gpu/GrFixedClip.h
+++ b/chromium/third_party/skia/src/gpu/GrFixedClip.h
@@ -17,17 +17,21 @@
*/
class GrFixedClip final : public GrHardClip {
public:
- GrFixedClip() = default;
- explicit GrFixedClip(const SkIRect& scissorRect) : fScissorState(scissorRect) {}
+ explicit GrFixedClip(const SkISize& rtDims) : fScissorState(rtDims) {}
+ GrFixedClip(const SkISize& rtDims, const SkIRect& scissorRect)
+ : GrFixedClip(rtDims) {
+ SkAssertResult(fScissorState.set(scissorRect));
+ }
const GrScissorState& scissorState() const { return fScissorState; }
bool scissorEnabled() const { return fScissorState.enabled(); }
- const SkIRect& scissorRect() const { SkASSERT(scissorEnabled()); return fScissorState.rect(); }
+ // Returns the scissor rect or rt bounds if the scissor test is not enabled.
+ const SkIRect& scissorRect() const { return fScissorState.rect(); }
void disableScissor() { fScissorState.setDisabled(); }
- void setScissor(const SkIRect& irect) {
- fScissorState.set(irect);
+ bool SK_WARN_UNUSED_RESULT setScissor(const SkIRect& irect) {
+ return fScissorState.set(irect);
}
bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& irect) {
return fScissorState.intersect(irect);
@@ -43,11 +47,9 @@ public:
}
bool quickContains(const SkRect&) const override;
- SkIRect getConservativeBounds(int w, int h) const override;
- bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const override;
- bool apply(int rtWidth, int rtHeight, GrAppliedHardClip*, SkRect*) const override;
-
- static const GrFixedClip& Disabled();
+ SkIRect getConservativeBounds() const override;
+ bool isRRect(SkRRect* rr, GrAA*) const override;
+ bool apply(GrAppliedHardClip*, SkRect*) const override;
private:
GrScissorState fScissorState;
diff --git a/chromium/third_party/skia/src/gpu/GrFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/GrFragmentProcessor.cpp
index e4b18c89fcf..9c668d3aed4 100644
--- a/chromium/third_party/skia/src/gpu/GrFragmentProcessor.cpp
+++ b/chromium/third_party/skia/src/gpu/GrFragmentProcessor.cpp
@@ -13,7 +13,6 @@
#include "src/gpu/effects/generated/GrClampFragmentProcessor.h"
#include "src/gpu/effects/generated/GrConstColorProcessor.h"
#include "src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h"
-#include "src/gpu/effects/generated/GrPremulInputFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
@@ -74,25 +73,47 @@ void GrFragmentProcessor::addCoordTransform(GrCoordTransform* transform) {
fFlags |= kHasCoordTransforms_Flag;
}
-void GrFragmentProcessor::setSampleMatrix(SkSL::SampleMatrix matrix) {
- if (matrix == fMatrix) {
+void GrFragmentProcessor::setSampleMatrix(SkSL::SampleMatrix newMatrix) {
+ if (newMatrix == fMatrix) {
return;
}
+ SkASSERT(newMatrix.fKind != SkSL::SampleMatrix::Kind::kNone);
SkASSERT(fMatrix.fKind != SkSL::SampleMatrix::Kind::kVariable);
+ if (this->numCoordTransforms() == 0 &&
+ (newMatrix.fKind == SkSL::SampleMatrix::Kind::kConstantOrUniform ||
+ newMatrix.fKind == SkSL::SampleMatrix::Kind::kMixed)) {
+ // as things stand, matrices only work when there's a coord transform, so we need to add
+ // an identity transform to keep the downstream code happy
+ static GrCoordTransform identity;
+ this->addCoordTransform(&identity);
+ }
if (fMatrix.fKind == SkSL::SampleMatrix::Kind::kConstantOrUniform) {
- SkASSERT(matrix.fKind == SkSL::SampleMatrix::Kind::kVariable ||
- (matrix.fKind == SkSL::SampleMatrix::Kind::kMixed &&
- matrix.fExpression == fMatrix.fExpression));
- fMatrix = SkSL::SampleMatrix(SkSL::SampleMatrix::Kind::kMixed, fMatrix.fOwner,
- fMatrix.fExpression);
+ if (newMatrix.fKind == SkSL::SampleMatrix::Kind::kConstantOrUniform) {
+ // need to base this transform on the one that happened in our parent
+ // If we're already based on something, then we have to assume that parent is now
+ // based on yet another transform, so don't update our base pointer (or we'll skip
+ // the intermediate transform).
+ if (!fMatrix.fBase) {
+ fMatrix.fBase = newMatrix.fOwner;
+ }
+ } else {
+ SkASSERT(newMatrix.fKind == SkSL::SampleMatrix::Kind::kVariable);
+ fMatrix.fKind = SkSL::SampleMatrix::Kind::kMixed;
+ fMatrix.fBase = nullptr;
+ }
} else {
SkASSERT(fMatrix.fKind == SkSL::SampleMatrix::Kind::kNone);
- fMatrix = matrix;
+ fMatrix = newMatrix;
}
- if (matrix.fKind == SkSL::SampleMatrix::Kind::kVariable) {
- for (auto& child : fChildProcessors) {
- child->setSampleMatrix(matrix);
- }
+ for (auto& child : fChildProcessors) {
+ child->setSampleMatrix(newMatrix);
+ }
+}
+
+void GrFragmentProcessor::setSampledWithExplicitCoords() {
+ fFlags |= kSampledWithExplicitCoords;
+ for (auto& child : fChildProcessors) {
+ child->setSampledWithExplicitCoords();
}
}
@@ -114,7 +135,26 @@ bool GrFragmentProcessor::isInstantiated() const {
}
#endif
-int GrFragmentProcessor::registerChildProcessor(std::unique_ptr<GrFragmentProcessor> child) {
+int GrFragmentProcessor::registerChild(std::unique_ptr<GrFragmentProcessor> child,
+ SkSL::SampleMatrix sampleMatrix,
+ bool explicitlySampled) {
+ // Configure child's sampling state first
+ if (explicitlySampled) {
+ child->setSampledWithExplicitCoords();
+ }
+ if (sampleMatrix.fKind != SkSL::SampleMatrix::Kind::kNone) {
+ // FIXME(michaelludwig) - Temporary hack. Owner tracking will be moved off of SampleMatrix
+ // and into FP. Currently, coord transform compilation fails on sample_matrix GMs if the
+ // child isn't the owner. But the matrix effect (and expected behavior) require the owner
+ // to be 'this' FP.
+ if (this->classID() == kGrMatrixEffect_ClassID) {
+ sampleMatrix.fOwner = this;
+ } else {
+ sampleMatrix.fOwner = child.get();
+ }
+ child->setSampleMatrix(sampleMatrix);
+ }
+
if (child->fFlags & kHasCoordTransforms_Flag) {
fFlags |= kHasCoordTransforms_Flag;
}
@@ -127,6 +167,18 @@ int GrFragmentProcessor::registerChildProcessor(std::unique_ptr<GrFragmentProces
return index;
}
+int GrFragmentProcessor::cloneAndRegisterChildProcessor(const GrFragmentProcessor& fp) {
+ std::unique_ptr<GrFragmentProcessor> clone = fp.clone();
+ return this->registerChild(std::move(clone), fp.sampleMatrix(),
+ fp.isSampledWithExplicitCoords());
+}
+
+void GrFragmentProcessor::cloneAndRegisterAllChildProcessors(const GrFragmentProcessor& src) {
+ for (int i = 0; i < src.numChildProcessors(); ++i) {
+ this->cloneAndRegisterChildProcessor(src.childProcessor(i));
+ }
+}
+
bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
if (this->numCoordTransforms() != that.numCoordTransforms()) {
return false;
@@ -156,56 +208,50 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MulInputByChildAlpha(
return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp), SkBlendMode::kSrcIn);
}
-std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::PremulInput(
- std::unique_ptr<GrFragmentProcessor> fp) {
- if (!fp) {
- return nullptr;
- }
- std::unique_ptr<GrFragmentProcessor> fpPipeline[] = { GrPremulInputFragmentProcessor::Make(),
- std::move(fp) };
- return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
-}
-
std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::ClampPremulOutput(
std::unique_ptr<GrFragmentProcessor> fp) {
if (!fp) {
return nullptr;
}
- std::unique_ptr<GrFragmentProcessor> fpPipeline[] = {
- std::move(fp),
- GrClampFragmentProcessor::Make(true)
- };
- return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
+ return GrClampFragmentProcessor::Make(std::move(fp), /*clampToPremul=*/true);
}
std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::SwizzleOutput(
std::unique_ptr<GrFragmentProcessor> fp, const GrSwizzle& swizzle) {
class SwizzleFragmentProcessor : public GrFragmentProcessor {
public:
- static std::unique_ptr<GrFragmentProcessor> Make(const GrSwizzle& swizzle) {
- return std::unique_ptr<GrFragmentProcessor>(new SwizzleFragmentProcessor(swizzle));
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp,
+ const GrSwizzle& swizzle) {
+ return std::unique_ptr<GrFragmentProcessor>(
+ new SwizzleFragmentProcessor(std::move(fp), swizzle));
}
const char* name() const override { return "Swizzle"; }
const GrSwizzle& swizzle() const { return fSwizzle; }
- std::unique_ptr<GrFragmentProcessor> clone() const override { return Make(fSwizzle); }
+ std::unique_ptr<GrFragmentProcessor> clone() const override {
+ return Make(this->childProcessor(0).clone(), fSwizzle);
+ }
private:
- SwizzleFragmentProcessor(const GrSwizzle& swizzle)
- : INHERITED(kSwizzleFragmentProcessor_ClassID, kAll_OptimizationFlags)
- , fSwizzle(swizzle) {}
+ SwizzleFragmentProcessor(std::unique_ptr<GrFragmentProcessor> fp, const GrSwizzle& swizzle)
+ : INHERITED(kSwizzleFragmentProcessor_ClassID, ProcessorOptimizationFlags(fp.get()))
+ , fSwizzle(swizzle) {
+ this->registerChild(std::move(fp));
+ }
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
class GLFP : public GrGLSLFragmentProcessor {
public:
void emitCode(EmitArgs& args) override {
+ SkString childColor = this->invokeChild(0, args.fInputColor, args);
+
const SwizzleFragmentProcessor& sfp = args.fFp.cast<SwizzleFragmentProcessor>();
const GrSwizzle& swizzle = sfp.swizzle();
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
fragBuilder->codeAppendf("%s = %s.%s;",
- args.fOutputColor, args.fInputColor, swizzle.asString().c_str());
+ args.fOutputColor, childColor.c_str(), swizzle.asString().c_str());
}
};
return new GLFP;
@@ -235,9 +281,7 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::SwizzleOutput(
if (GrSwizzle::RGBA() == swizzle) {
return fp;
}
- std::unique_ptr<GrFragmentProcessor> fpPipeline[] = { std::move(fp),
- SwizzleFragmentProcessor::Make(swizzle) };
- return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
+ return SwizzleFragmentProcessor::Make(std::move(fp), swizzle);
}
std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulByOutput(
@@ -259,7 +303,7 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulB
private:
PremulFragmentProcessor(std::unique_ptr<GrFragmentProcessor> processor)
: INHERITED(kPremulFragmentProcessor_ClassID, OptFlags(processor.get())) {
- this->registerChildProcessor(std::move(processor));
+ this->registerChild(std::move(processor));
}
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
@@ -359,7 +403,7 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(
: INHERITED(kSeriesFragmentProcessor_ClassID, OptFlags(children, cnt)) {
SkASSERT(cnt > 1);
for (int i = 0; i < cnt; ++i) {
- this->registerChildProcessor(std::move(children[i]));
+ this->registerChild(std::move(children[i]));
}
}
@@ -400,8 +444,8 @@ std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(
SkPMColor4f knownColor;
int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor);
if (leadingFPsToEliminate) {
- std::unique_ptr<GrFragmentProcessor> colorFP(
- GrConstColorProcessor::Make(knownColor, GrConstColorProcessor::InputMode::kIgnore));
+ std::unique_ptr<GrFragmentProcessor> colorFP = GrConstColorProcessor::Make(
+ /*inputFP=*/nullptr, knownColor, GrConstColorProcessor::InputMode::kIgnore);
if (leadingFPsToEliminate == cnt) {
return colorFP;
}
diff --git a/chromium/third_party/skia/src/gpu/GrFragmentProcessor.h b/chromium/third_party/skia/src/gpu/GrFragmentProcessor.h
index efc4c9ac78b..a0f540eea0e 100644
--- a/chromium/third_party/skia/src/gpu/GrFragmentProcessor.h
+++ b/chromium/third_party/skia/src/gpu/GrFragmentProcessor.h
@@ -8,6 +8,8 @@
#ifndef GrFragmentProcessor_DEFINED
#define GrFragmentProcessor_DEFINED
+#include <tuple>
+
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrProcessor.h"
#include "src/gpu/ops/GrOp.h"
@@ -146,19 +148,10 @@ public:
return SkToBool(fFlags & kSampledWithExplicitCoords);
}
- void setSampledWithExplicitCoords() {
- fFlags |= kSampledWithExplicitCoords;
- for (auto& child : fChildProcessors) {
- child->setSampledWithExplicitCoords();
- }
- }
-
SkSL::SampleMatrix sampleMatrix() const {
return fMatrix;
}
- void setSampleMatrix(SkSL::SampleMatrix matrix);
-
/**
* A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
* output under the following scenario:
@@ -316,6 +309,13 @@ public:
// Sentinel type for range-for using FPItemIter.
class FPItemEndIter {};
+ // FIXME This should be private, but SkGr needs to mark the dither effect as sampled explicitly
+ // even though it's not added to another FP. Once varying generation doesn't add a redundant
+ // varying for it, this can be fully private.
+ void temporary_SetExplicitlySampled() {
+ this->setSampledWithExplicitCoords();
+ }
+
protected:
enum OptimizationFlags : uint32_t {
kNone_OptimizationFlags,
@@ -408,8 +408,37 @@ protected:
* colors will be combined somehow to produce its output color. Registering these child
* processors will allow the ProgramBuilder to automatically handle their transformed coords and
* texture accesses and mangle their uniform and output color names.
+ *
+ * Depending on the 2nd and 3rd parameters, this corresponds to the following SkSL sample calls:
+ * - sample(child): Keep default arguments
+ * - sample(child, matrix): Provide approprate SampleMatrix matching SkSL
+ * - sample(child, float2): SampleMatrix() and 'true', or use 'registerExplicitlySampledChild'
+ * - sample(child, matrix)+sample(child, float2): Appropriate SampleMatrix and 'true'
*/
- int registerChildProcessor(std::unique_ptr<GrFragmentProcessor> child);
+ int registerChild(std::unique_ptr<GrFragmentProcessor> child,
+ SkSL::SampleMatrix sampleMatrix = SkSL::SampleMatrix(),
+ bool explicitlySampled = false);
+
+ /**
+ * A helper for use when the child is only invoked with sample(float2), and not sample()
+ * or sample(matrix).
+ */
+ int registerExplicitlySampledChild(std::unique_ptr<GrFragmentProcessor> child) {
+ return this->registerChild(std::move(child), SkSL::SampleMatrix(), true);
+ }
+
+ /**
+ * This method takes an existing fragment processor, clones it, registers it as a child of this
+ * fragment processor, and returns its child index. It also takes care of any boilerplate in the
+ * cloning process.
+ */
+ int cloneAndRegisterChildProcessor(const GrFragmentProcessor& fp);
+
+ /**
+ * This method takes an existing fragment processor, clones all of its children, and registers
+ * the clones as children of this fragment processor.
+ */
+ void cloneAndRegisterAllChildProcessors(const GrFragmentProcessor& src);
void setTextureSamplerCnt(int cnt) {
SkASSERT(cnt >= 0);
@@ -455,6 +484,10 @@ private:
bool hasSameTransforms(const GrFragmentProcessor&) const;
+ void setSampledWithExplicitCoords();
+
+ void setSampleMatrix(SkSL::SampleMatrix matrix);
+
enum PrivateFlags {
kFirstPrivateFlag = kAll_OptimizationFlags + 1,
kHasCoordTransforms_Flag = kFirstPrivateFlag,
@@ -658,4 +691,18 @@ private:
Src& fSrc;
};
+/**
+ * Some fragment-processor creation methods have preconditions that might not be satisfied by the
+ * calling code. Those methods can return a `GrFPResult` from their factory methods. If creation
+ * succeeds, the new fragment processor is created and `success` is true. If a precondition is not
+ * met, `success` is set to false and the input FP is returned unchanged.
+ */
+using GrFPResult = std::tuple<bool /*success*/, std::unique_ptr<GrFragmentProcessor>>;
+static inline GrFPResult GrFPFailure(std::unique_ptr<GrFragmentProcessor> fp) {
+ return {false, std::move(fp)};
+}
+static inline GrFPResult GrFPSuccess(std::unique_ptr<GrFragmentProcessor> fp) {
+ return {true, std::move(fp)};
+}
+
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrGpu.cpp b/chromium/third_party/skia/src/gpu/GrGpu.cpp
index 5bc99f00354..195d22e03c0 100644
--- a/chromium/third_party/skia/src/gpu/GrGpu.cpp
+++ b/chromium/third_party/skia/src/gpu/GrGpu.cpp
@@ -15,6 +15,7 @@
#include "src/core/SkMathPriv.h"
#include "src/core/SkMipMap.h"
#include "src/gpu/GrAuditTrail.h"
+#include "src/gpu/GrBackendUtils.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrDataUtils.h"
@@ -42,6 +43,7 @@ static const size_t kMinStagingBufferSize = 32 * 1024;
GrGpu::GrGpu(GrContext* context) : fResetBits(kAll_GrBackendState), fContext(context) {}
GrGpu::~GrGpu() {
+ this->callSubmittedProcs(false);
SkASSERT(fBusyStagingBuffers.isEmpty());
}
@@ -261,7 +263,7 @@ sk_sp<GrTexture> GrGpu::createCompressedTexture(SkISize dimensions,
}
// TODO: expand CompressedDataIsCorrect to work here too
- SkImage::CompressionType compressionType = this->caps()->compressionType(format);
+ SkImage::CompressionType compressionType = GrBackendFormatToCompressionType(format);
if (dataSize < SkCompressedDataSize(compressionType, dimensions, nullptr,
mipMapped == GrMipMapped::kYes)) {
@@ -657,7 +659,7 @@ void GrGpu::executeFlushInfo(GrSurfaceProxy* proxies[],
int numProxies,
SkSurface::BackendSurfaceAccess access,
const GrFlushInfo& info,
- const GrPrepareForExternalIORequests& externalRequests) {
+ const GrBackendSurfaceMutableState* newState) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
GrResourceProvider* resourceProvider = fContext->priv().resourceProvider();
@@ -671,7 +673,11 @@ void GrGpu::executeFlushInfo(GrSurfaceProxy* proxies[],
info.fSignalSemaphores[i],
GrResourceProvider::SemaphoreWrapType::kWillSignal,
kBorrow_GrWrapOwnership);
- this->insertSemaphore(semaphores[i].get());
+ // If we failed to wrap the semaphore it means the client didn't give us a valid
+ // semaphore to begin with. Therefore, it is fine to not signal it.
+ if (semaphores[i]) {
+ this->insertSemaphore(semaphores[i].get());
+ }
} else {
semaphores[i] = resourceProvider->makeSemaphore(false);
if (semaphores[i]) {
@@ -685,8 +691,17 @@ void GrGpu::executeFlushInfo(GrSurfaceProxy* proxies[],
if (info.fFinishedProc) {
this->addFinishedProc(info.fFinishedProc, info.fFinishedContext);
}
- this->prepareSurfacesForBackendAccessAndExternalIO(proxies, numProxies, access,
- externalRequests);
+
+ if (info.fSubmittedProc) {
+ fSubmittedProcs.emplace_back(info.fSubmittedProc, info.fSubmittedContext);
+ }
+
+ // We currently don't support passing in new surface state for multiple proxies here. The only
+ // time we have multiple proxies is if we are flushing a yuv SkImage which won't have state
+ // updates anyways.
+ SkASSERT(!newState || numProxies == 1);
+ SkASSERT(!newState || access == SkSurface::BackendSurfaceAccess::kNoAccess);
+ this->prepareSurfacesForBackendAccessAndStateUpdates(proxies, numProxies, access, newState);
}
bool GrGpu::submitToGpu(bool syncCpu) {
@@ -699,9 +714,26 @@ bool GrGpu::submitToGpu(bool syncCpu) {
bool submitted = this->onSubmitToGpu(syncCpu);
+ this->callSubmittedProcs(submitted);
+
return submitted;
}
+bool GrGpu::checkAndResetOOMed() {
+ if (fOOMed) {
+ fOOMed = false;
+ return true;
+ }
+ return false;
+}
+
+void GrGpu::callSubmittedProcs(bool success) {
+ for (int i = 0; i < fSubmittedProcs.count(); ++i) {
+ fSubmittedProcs[i].fProc(fSubmittedProcs[i].fContext, success);
+ }
+ fSubmittedProcs.reset();
+}
+
#ifdef SK_ENABLE_DUMP_GPU
void GrGpu::dumpJSON(SkJSONWriter* writer) const {
writer->beginObject();
@@ -870,17 +902,11 @@ GrBackendTexture GrGpu::createBackendTexture(SkISize dimensions,
}
bool GrGpu::updateBackendTexture(const GrBackendTexture& backendTexture,
- GrGpuFinishedProc finishedProc,
- GrGpuFinishedContext finishedContext,
+ sk_sp<GrRefCntedCallback> finishedCallback,
const BackendTextureData* data) {
SkASSERT(data);
const GrCaps* caps = this->caps();
- sk_sp<GrRefCntedCallback> callback;
- if (finishedProc) {
- callback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
- }
-
if (!backendTexture.isValid()) {
return false;
}
@@ -901,28 +927,22 @@ bool GrGpu::updateBackendTexture(const GrBackendTexture& backendTexture,
return false;
}
- return this->onUpdateBackendTexture(backendTexture, std::move(callback), data);
+ return this->onUpdateBackendTexture(backendTexture, std::move(finishedCallback), data);
}
GrBackendTexture GrGpu::createCompressedBackendTexture(SkISize dimensions,
const GrBackendFormat& format,
GrMipMapped mipMapped,
GrProtected isProtected,
- GrGpuFinishedProc finishedProc,
- GrGpuFinishedContext finishedContext,
+ sk_sp<GrRefCntedCallback> finishedCallback,
const BackendTextureData* data) {
- sk_sp<GrRefCntedCallback> callback;
- if (finishedProc) {
- callback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
- }
-
const GrCaps* caps = this->caps();
if (!format.isValid()) {
return {};
}
- SkImage::CompressionType compressionType = caps->compressionType(format);
+ SkImage::CompressionType compressionType = GrBackendFormatToCompressionType(format);
if (compressionType == SkImage::CompressionType::kNone) {
// Uncompressed formats must go through the createBackendTexture API
return {};
@@ -943,7 +963,7 @@ GrBackendTexture GrGpu::createCompressedBackendTexture(SkISize dimensions,
}
return this->onCreateCompressedBackendTexture(dimensions, format, mipMapped,
- isProtected, std::move(callback), data);
+ isProtected, std::move(finishedCallback), data);
}
GrStagingBuffer* GrGpu::findStagingBuffer(size_t size) {
diff --git a/chromium/third_party/skia/src/gpu/GrGpu.h b/chromium/third_party/skia/src/gpu/GrGpu.h
index 58723df5a05..d93c47fcfc4 100644
--- a/chromium/third_party/skia/src/gpu/GrGpu.h
+++ b/chromium/third_party/skia/src/gpu/GrGpu.h
@@ -350,8 +350,14 @@ public:
// Returns a GrOpsRenderPass which GrOpsTasks send draw commands to instead of directly
// to the Gpu object. The 'bounds' rect is the content rect of the renderTarget.
+ // If a 'stencil' is provided it will be the one bound to 'renderTarget'. If one is not
+ // provided but 'renderTarget' has a stencil buffer then that is a signal that the
+ // render target's stencil buffer should be ignored.
virtual GrOpsRenderPass* getOpsRenderPass(
- GrRenderTarget* renderTarget, GrSurfaceOrigin, const SkIRect& bounds,
+ GrRenderTarget* renderTarget,
+ GrStencilAttachment* stencil,
+ GrSurfaceOrigin,
+ const SkIRect& bounds,
const GrOpsRenderPass::LoadAndStoreInfo&,
const GrOpsRenderPass::StencilLoadAndStoreInfo&,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies) = 0;
@@ -361,8 +367,9 @@ public:
// insert any numSemaphore semaphores on the gpu and set the backendSemaphores to match the
// inserted semaphores.
void executeFlushInfo(GrSurfaceProxy*[], int numProxies,
- SkSurface::BackendSurfaceAccess access, const GrFlushInfo&,
- const GrPrepareForExternalIORequests&);
+ SkSurface::BackendSurfaceAccess access,
+ const GrFlushInfo&,
+ const GrBackendSurfaceMutableState* newState);
bool submitToGpu(bool syncCpu);
@@ -382,6 +389,12 @@ public:
virtual void checkFinishProcs() = 0;
/**
+ * Checks if we detected an OOM from the underlying 3D API and if so returns true and resets
+ * the internal OOM state to false. Otherwise, returns false.
+ */
+ bool checkAndResetOOMed();
+
+ /**
* Put this texture in a safe and known state for use across multiple GrContexts. Depending on
* the backend, this may return a GrSemaphore. If so, other contexts should wait on that
* semaphore before using this texture.
@@ -600,8 +613,7 @@ public:
GrProtected);
bool updateBackendTexture(const GrBackendTexture&,
- GrGpuFinishedProc finishedProc,
- GrGpuFinishedContext finishedContext,
+ sk_sp<GrRefCntedCallback> finishedCallback,
const BackendTextureData*);
/**
@@ -612,10 +624,21 @@ public:
const GrBackendFormat&,
GrMipMapped,
GrProtected,
- GrGpuFinishedProc finishedProc,
- GrGpuFinishedContext finishedContext,
+ sk_sp<GrRefCntedCallback> finishedCallback,
const BackendTextureData*);
+ virtual bool setBackendTextureState(const GrBackendTexture&,
+ const GrBackendSurfaceMutableState&,
+ sk_sp<GrRefCntedCallback> finishedCallback) {
+ return false;
+ }
+
+ virtual bool setBackendRenderTargetState(const GrBackendRenderTarget&,
+ const GrBackendSurfaceMutableState&,
+ sk_sp<GrRefCntedCallback> finishedCallback) {
+ return false;
+ }
+
/**
* Frees a texture created by createBackendTexture(). If ownership of the backend
* texture has been transferred to a GrContext using adopt semantics this should not be called.
@@ -704,6 +727,8 @@ protected:
void didWriteToSurface(GrSurface* surface, GrSurfaceOrigin origin, const SkIRect* bounds,
uint32_t mipLevels = 1) const;
+ void setOOMed() { fOOMed = true; }
+
typedef SkTInternalLList<GrStagingBuffer> StagingBufferList;
const StagingBufferList& availableStagingBuffers() { return fAvailableStagingBuffers; }
const StagingBufferList& activeStagingBuffers() { return fActiveStagingBuffers; }
@@ -815,9 +840,11 @@ private:
virtual void addFinishedProc(GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) = 0;
- virtual void prepareSurfacesForBackendAccessAndExternalIO(
- GrSurfaceProxy* proxies[], int numProxies, SkSurface::BackendSurfaceAccess access,
- const GrPrepareForExternalIORequests& externalRequests) {}
+ virtual void prepareSurfacesForBackendAccessAndStateUpdates(
+ GrSurfaceProxy* proxies[],
+ int numProxies,
+ SkSurface::BackendSurfaceAccess access,
+ const GrBackendSurfaceMutableState* newState) {}
virtual bool onSubmitToGpu(bool syncCpu) = 0;
@@ -843,6 +870,8 @@ private:
void validateStagingBuffers() const;
#endif
+ void callSubmittedProcs(bool success);
+
uint32_t fResetBits;
// The context owns us, not vice-versa, so this ptr is not ref'ed by Gpu.
GrContext* fContext;
@@ -854,6 +883,17 @@ private:
StagingBufferList fActiveStagingBuffers;
StagingBufferList fBusyStagingBuffers;
+ struct SubmittedProc {
+ SubmittedProc(GrGpuSubmittedProc proc, GrGpuSubmittedContext context)
+ : fProc(proc), fContext(context) {}
+
+ GrGpuSubmittedProc fProc;
+ GrGpuSubmittedContext fContext;
+ };
+ SkSTArray<4, SubmittedProc> fSubmittedProcs;
+
+ bool fOOMed = false;
+
friend class GrPathRendering;
typedef SkRefCnt INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/GrHashMapWithCache.h b/chromium/third_party/skia/src/gpu/GrHashMapWithCache.h
new file mode 100644
index 00000000000..8a24ecc525c
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrHashMapWithCache.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrHashMapWithCache_DEFINED
+#define GrHashMapWithCache_DEFINED
+
+#include "include/private/SkChecksum.h"
+#include "include/private/SkNoncopyable.h"
+#include "include/private/SkTHash.h"
+
+// Cheaper than SkGoodHash and good enough for UniqueID tables.
+struct GrCheapHash {
+ uint32_t operator()(uint32_t val) {
+ return SkChecksum::CheapMix(val);
+ }
+};
+
+/** A hash map that caches the most recently accessed entry.
+ The API is a subset of SkHashMap, and you must provide a
+ sentinel key that will never be present, such as SK_InvalidUniqueID.
+
+ KeyTraits must have:
+ - static K GetInvalidKey()
+*/
+template <typename K, typename V, typename KeyTraits, typename HashT = SkGoodHash>
+class GrHashMapWithCache : public SkNoncopyable {
+public:
+ // How many key/value pairs are in the table?
+ int count() const { return fMap.count(); }
+
+ // Approximately how many bytes of memory do we use beyond sizeof(*this)?
+ size_t approxBytesUsed() const { return fMap.approxBytesUsed(); }
+
+ // N.B. The pointers returned by set() and find() are valid only until the next call to set().
+
+ // If there is key/value entry in the table with this key, return a pointer to the value.
+ // If not, return null.
+ const V* find(const K& key) const {
+ if (key != fLastKey) {
+ fLastKey = key;
+ fLastValue = fMap.find(key);
+ }
+ return fLastValue;
+ }
+
+ // Set key to val in the map, replacing any previous value with the same key.
+ // We copy both key and val, and return a pointer to the value copy now in the map.
+ const V* set(K key, V val) {
+ if (fLastValue && key == fLastKey) {
+ *fLastValue = std::move(val);
+ } else {
+ fLastKey = key;
+ fLastValue = fMap.set(std::move(key), std::move(val));
+ }
+ return fLastValue;
+ }
+
+ // Remove the key/value entry in the table with this key.
+ void remove(K key) {
+ // Match SkTHashMap requirement. The caller can find() if they're unsure.
+ SkASSERT(fMap.find(fLastKey));
+ fLastKey = std::move(key);
+ fLastValue = nullptr;
+ fMap.remove(fLastKey);
+ }
+
+ // Clear the map.
+ void reset() {
+ fLastKey = KeyTraits::GetInvalidKey();
+ fLastValue = nullptr;
+ fMap.reset();
+ }
+
+private:
+ SkTHashMap<K, V, HashT> fMap;
+ mutable K fLastKey = KeyTraits::GetInvalidKey();
+ mutable V* fLastValue = nullptr;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrImageContext.cpp b/chromium/third_party/skia/src/gpu/GrImageContext.cpp
index 3f22c1e3ce7..8993a3831bd 100644
--- a/chromium/third_party/skia/src/gpu/GrImageContext.cpp
+++ b/chromium/third_party/skia/src/gpu/GrImageContext.cpp
@@ -8,33 +8,25 @@
#include "include/private/GrImageContext.h"
#include "src/gpu/GrCaps.h"
+#include "src/gpu/GrContextThreadSafeProxyPriv.h"
#include "src/gpu/GrImageContextPriv.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/effects/GrSkSLFP.h"
-#define ASSERT_SINGLE_OWNER \
- SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
-
///////////////////////////////////////////////////////////////////////////////////////////////////
-GrImageContext::GrImageContext(GrBackendApi backend,
- const GrContextOptions& options,
- uint32_t contextID)
- : INHERITED(backend, options, contextID) {
+GrImageContext::GrImageContext(sk_sp<GrContextThreadSafeProxy> proxy)
+ : INHERITED(std::move(proxy)) {
fProxyProvider.reset(new GrProxyProvider(this));
}
GrImageContext::~GrImageContext() {}
void GrImageContext::abandonContext() {
- ASSERT_SINGLE_OWNER
-
- fAbandoned = true;
+ fThreadSafeProxy->priv().abandonContext();
}
bool GrImageContext::abandoned() {
- ASSERT_SINGLE_OWNER
-
- return fAbandoned;
+ return fThreadSafeProxy->priv().abandoned();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/src/gpu/GrLegacyDirectContext.cpp b/chromium/third_party/skia/src/gpu/GrLegacyDirectContext.cpp
index f7cae12c15a..4b027eaf3fe 100644
--- a/chromium/third_party/skia/src/gpu/GrLegacyDirectContext.cpp
+++ b/chromium/third_party/skia/src/gpu/GrLegacyDirectContext.cpp
@@ -31,6 +31,13 @@
#include "src/gpu/dawn/GrDawnGpu.h"
#endif
+#if GR_TEST_UTILS
+# include "include/utils/SkRandom.h"
+# if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
+# include <sanitizer/lsan_interface.h>
+# endif
+#endif
+
#ifdef SK_DISABLE_REDUCE_OPLIST_SPLITTING
static const bool kDefaultReduceOpsTaskSplitting = false;
#else
@@ -40,7 +47,7 @@ static const bool kDefaultReduceOpsTaskSplitting = false;
class GrLegacyDirectContext : public GrContext {
public:
GrLegacyDirectContext(GrBackendApi backend, const GrContextOptions& options)
- : INHERITED(backend, options)
+ : INHERITED(GrContextThreadSafeProxyPriv::Make(backend, options))
, fAtlasManager(nullptr) {
}
@@ -48,7 +55,7 @@ public:
// this if-test protects against the case where the context is being destroyed
// before having been fully created
if (this->priv().getGpu()) {
- this->flush();
+ this->flushAndSubmit();
}
delete fAtlasManager;
@@ -65,23 +72,21 @@ public:
}
void freeGpuResources() override {
- this->flush();
+ this->flushAndSubmit();
fAtlasManager->freeAll();
INHERITED::freeGpuResources();
}
protected:
- bool init(sk_sp<const GrCaps> caps) override {
- SkASSERT(caps);
- SkASSERT(!fThreadSafeProxy);
-
- fThreadSafeProxy = GrContextThreadSafeProxyPriv::Make(this->backend(),
- this->options(),
- this->contextID(),
- caps);
+ bool init() override {
+ const GrGpu* gpu = this->priv().getGpu();
+ if (!gpu) {
+ return false;
+ }
- if (!INHERITED::init(std::move(caps))) {
+ fThreadSafeProxy->priv().init(gpu->refCaps());
+ if (!INHERITED::init()) {
return false;
}
@@ -94,8 +99,6 @@ protected:
this->setupDrawingManager(true, reduceOpsTaskSplitting);
- SkASSERT(this->caps());
-
GrDrawOpAtlas::AllowMultitexturing allowMultitexturing;
if (GrContextOptions::Enable::kNo == this->options().fAllowMultipleGlyphCacheTextures ||
// multitexturing supported only if range can represent the index + texcoords fully
@@ -139,16 +142,52 @@ sk_sp<GrContext> GrContext::MakeGL() {
return MakeGL(nullptr, defaultOptions);
}
+#if GR_TEST_UTILS
+GrGLFunction<GrGLGetErrorFn> make_get_error_with_random_oom(GrGLFunction<GrGLGetErrorFn> original) {
+ // A SkRandom and a GrGLFunction<GrGLGetErrorFn> are too big to be captured by a
+ // GrGLFunction<GrGLGetError> (surprise, surprise). So we make a context object and
+ // capture that by pointer. However, GrGLFunction doesn't support calling a destructor
+ // on the thing it captures. So we leak the context.
+ struct GetErrorContext {
+ SkRandom fRandom;
+ GrGLFunction<GrGLGetErrorFn> fGetError;
+ };
+
+ auto errorContext = new GetErrorContext;
+
+#if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
+ __lsan_ignore_object(errorContext);
+#endif
+
+ errorContext->fGetError = original;
+
+ return GrGLFunction<GrGLGetErrorFn>([errorContext]() {
+ GrGLenum error = errorContext->fGetError();
+ if (error == GR_GL_NO_ERROR && (errorContext->fRandom.nextU() % 300) == 0) {
+ error = GR_GL_OUT_OF_MEMORY;
+ }
+ return error;
+ });
+}
+#endif
+
sk_sp<GrContext> GrContext::MakeGL(sk_sp<const GrGLInterface> glInterface,
const GrContextOptions& options) {
sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kOpenGL, options));
-
- context->fGpu = GrGLGpu::Make(std::move(glInterface), options, context.get());
- if (!context->fGpu) {
- return nullptr;
+#if GR_TEST_UTILS
+ if (options.fRandomGLOOM) {
+ auto copy = sk_make_sp<GrGLInterface>(*glInterface);
+ copy->fFunctions.fGetError =
+ make_get_error_with_random_oom(glInterface->fFunctions.fGetError);
+#if GR_GL_CHECK_ERROR
+ // Suppress logging GL errors since we'll be synthetically generating them.
+ copy->suppressErrorLogging();
+#endif
+ glInterface = std::move(copy);
}
-
- if (!context->init(context->fGpu->refCaps())) {
+#endif
+ context->fGpu = GrGLGpu::Make(std::move(glInterface), options, context.get());
+ if (!context->init()) {
return nullptr;
}
return context;
@@ -165,11 +204,7 @@ sk_sp<GrContext> GrContext::MakeMock(const GrMockOptions* mockOptions,
sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kMock, options));
context->fGpu = GrMockGpu::Make(mockOptions, options, context.get());
- if (!context->fGpu) {
- return nullptr;
- }
-
- if (!context->init(context->fGpu->refCaps())) {
+ if (!context->init()) {
return nullptr;
}
@@ -191,13 +226,10 @@ sk_sp<GrContext> GrContext::MakeVulkan(const GrVkBackendContext& backendContext,
sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kVulkan, options));
context->fGpu = GrVkGpu::Make(backendContext, options, context.get());
- if (!context->fGpu) {
+ if (!context->init()) {
return nullptr;
}
- if (!context->init(context->fGpu->refCaps())) {
- return nullptr;
- }
return context;
#else
return nullptr;
@@ -214,13 +246,10 @@ sk_sp<GrContext> GrContext::MakeMetal(void* device, void* queue, const GrContext
sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kMetal, options));
context->fGpu = GrMtlTrampoline::MakeGpu(context.get(), options, device, queue);
- if (!context->fGpu) {
+ if (!context->init()) {
return nullptr;
}
- if (!context->init(context->fGpu->refCaps())) {
- return nullptr;
- }
return context;
}
#endif
@@ -236,13 +265,10 @@ sk_sp<GrContext> GrContext::MakeDirect3D(const GrD3DBackendContext& backendConte
sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kDirect3D, options));
context->fGpu = GrD3DGpu::Make(backendContext, options, context.get());
- if (!context->fGpu) {
+ if (!context->init()) {
return nullptr;
}
- if (!context->init(context->fGpu->refCaps())) {
- return nullptr;
- }
return context;
}
#endif
@@ -257,13 +283,10 @@ sk_sp<GrContext> GrContext::MakeDawn(const wgpu::Device& device, const GrContext
sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kDawn, options));
context->fGpu = GrDawnGpu::Make(device, options, context.get());
- if (!context->fGpu) {
+ if (!context->init()) {
return nullptr;
}
- if (!context->init(context->fGpu->refCaps())) {
- return nullptr;
- }
return context;
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrOnFlushResourceProvider.cpp b/chromium/third_party/skia/src/gpu/GrOnFlushResourceProvider.cpp
index 0ca9f13ef47..93bf9dbe0df 100644
--- a/chromium/third_party/skia/src/gpu/GrOnFlushResourceProvider.cpp
+++ b/chromium/third_party/skia/src/gpu/GrOnFlushResourceProvider.cpp
@@ -52,12 +52,12 @@ void GrOnFlushResourceProvider::addTextureResolveTask(sk_sp<GrTextureProxy> text
// Since we are bypassing normal DAG operation, we need to ensure the textureProxy's last render
// task gets closed before making a texture resolve task. makeClosed is what will mark msaa and
// mipmaps dirty.
- if (GrRenderTask* renderTask = textureProxy->getLastRenderTask()) {
+ if (GrRenderTask* renderTask = fDrawingMgr->getLastRenderTask(textureProxy.get())) {
renderTask->makeClosed(*this->caps());
}
auto task = static_cast<GrTextureResolveRenderTask*>(fDrawingMgr->fOnFlushRenderTasks.push_back(
sk_make_sp<GrTextureResolveRenderTask>()).get());
- task->addProxy(std::move(textureProxy), resolveFlags, *this->caps());
+ task->addProxy(fDrawingMgr, std::move(textureProxy), resolveFlags, *this->caps());
task->makeClosed(*this->caps());
}
diff --git a/chromium/third_party/skia/src/gpu/GrOpFlushState.cpp b/chromium/third_party/skia/src/gpu/GrOpFlushState.cpp
index dfaa9d6e73c..8bc88f0d091 100644
--- a/chromium/third_party/skia/src/gpu/GrOpFlushState.cpp
+++ b/chromium/third_party/skia/src/gpu/GrOpFlushState.cpp
@@ -194,7 +194,7 @@ void GrOpFlushState::putBackVertices(int vertices, size_t vertexStride) {
}
GrAppliedClip GrOpFlushState::detachAppliedClip() {
- return fOpArgs->appliedClip() ? std::move(*fOpArgs->appliedClip()) : GrAppliedClip();
+ return fOpArgs->appliedClip() ? std::move(*fOpArgs->appliedClip()) : GrAppliedClip::Disabled();
}
GrStrikeCache* GrOpFlushState::strikeCache() const {
diff --git a/chromium/third_party/skia/src/gpu/GrOpsRenderPass.cpp b/chromium/third_party/skia/src/gpu/GrOpsRenderPass.cpp
index 66e346b82fe..07b4eeebe3a 100644
--- a/chromium/third_party/skia/src/gpu/GrOpsRenderPass.cpp
+++ b/chromium/third_party/skia/src/gpu/GrOpsRenderPass.cpp
@@ -11,12 +11,13 @@
#include "include/gpu/GrContext.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrContextPriv.h"
-#include "src/gpu/GrFixedClip.h"
+#include "src/gpu/GrCpuBuffer.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrPrimitiveProcessor.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrRenderTarget.h"
#include "src/gpu/GrRenderTargetPriv.h"
+#include "src/gpu/GrScissorState.h"
#include "src/gpu/GrSimpleMesh.h"
#include "src/gpu/GrTexturePriv.h"
@@ -37,21 +38,22 @@ void GrOpsRenderPass::end() {
this->resetActiveBuffers();
}
-void GrOpsRenderPass::clear(const GrFixedClip& clip, const SkPMColor4f& color) {
+void GrOpsRenderPass::clear(const GrScissorState& scissor, const SkPMColor4f& color) {
SkASSERT(fRenderTarget);
// A clear at this level will always be a true clear, so make sure clears were not supposed to
// be redirected to draws instead
SkASSERT(!this->gpu()->caps()->performColorClearsAsDraws());
- SkASSERT(!clip.scissorEnabled() || !this->gpu()->caps()->performPartialClearsAsDraws());
+ SkASSERT(!scissor.enabled() || !this->gpu()->caps()->performPartialClearsAsDraws());
fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured;
- this->onClear(clip, color);
+ this->onClear(scissor, color);
}
-void GrOpsRenderPass::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
+void GrOpsRenderPass::clearStencilClip(const GrScissorState& scissor, bool insideStencilMask) {
// As above, make sure the stencil clear wasn't supposed to be a draw rect with stencil settings
SkASSERT(!this->gpu()->caps()->performStencilClearsAsDraws());
+ SkASSERT(!scissor.enabled() || !this->gpu()->caps()->performPartialClearsAsDraws());
fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured;
- this->onClearStencilClip(clip, insideStencilMask);
+ this->onClearStencilClip(scissor, insideStencilMask);
}
void GrOpsRenderPass::executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable) {
diff --git a/chromium/third_party/skia/src/gpu/GrOpsRenderPass.h b/chromium/third_party/skia/src/gpu/GrOpsRenderPass.h
index 959d1a222f6..ec7960f366c 100644
--- a/chromium/third_party/skia/src/gpu/GrOpsRenderPass.h
+++ b/chromium/third_party/skia/src/gpu/GrOpsRenderPass.h
@@ -13,12 +13,12 @@
#include "src/gpu/ops/GrDrawOp.h"
class GrOpFlushState;
-class GrFixedClip;
class GrGpu;
class GrPipeline;
class GrPrimitiveProcessor;
class GrProgramInfo;
class GrRenderTarget;
+class GrScissorState;
class GrSemaphore;
struct SkIRect;
struct SkRect;
@@ -120,11 +120,17 @@ public:
virtual void inlineUpload(GrOpFlushState*, GrDeferredTextureUploadFn&) = 0;
/**
- * Clear the owned render target. Ignores the draw state and clip.
+ * Clear the owned render target. Clears the full target if 'scissor' is disabled, otherwise it
+ * is restricted to 'scissor'. Must check caps.performPartialClearsAsDraws() before using an
+ * enabled scissor test; must check caps.performColorClearsAsDraws() before using this at all.
*/
- void clear(const GrFixedClip&, const SkPMColor4f&);
+ void clear(const GrScissorState& scissor, const SkPMColor4f&);
- void clearStencilClip(const GrFixedClip&, bool insideStencilMask);
+ /**
+ * Same as clear() but modifies the stencil; check caps.performStencilClearsAsDraws() and
+ * caps.performPartialClearsAsDraws().
+ */
+ void clearStencilClip(const GrScissorState& scissor, bool insideStencilMask);
/**
* Executes the SkDrawable object for the underlying backend.
@@ -189,8 +195,8 @@ private:
virtual void onDrawIndexedIndirect(const GrBuffer*, size_t offset, int drawCount) {
SK_ABORT("Not implemented."); // Only called if caps.nativeDrawIndirectSupport().
}
- virtual void onClear(const GrFixedClip&, const SkPMColor4f&) = 0;
- virtual void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) = 0;
+ virtual void onClear(const GrScissorState&, const SkPMColor4f&) = 0;
+ virtual void onClearStencilClip(const GrScissorState&, bool insideStencilMask) = 0;
virtual void onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) {}
enum class DrawPipelineStatus {
diff --git a/chromium/third_party/skia/src/gpu/GrOpsTask.cpp b/chromium/third_party/skia/src/gpu/GrOpsTask.cpp
index c811883d774..1f0a55f747d 100644
--- a/chromium/third_party/skia/src/gpu/GrOpsTask.cpp
+++ b/chromium/third_party/skia/src/gpu/GrOpsTask.cpp
@@ -357,14 +357,14 @@ inline void GrOpsTask::OpChain::validate() const {
////////////////////////////////////////////////////////////////////////////////
-GrOpsTask::GrOpsTask(GrRecordingContext::Arenas arenas,
+GrOpsTask::GrOpsTask(GrDrawingManager* drawingMgr, GrRecordingContext::Arenas arenas,
GrSurfaceProxyView view,
GrAuditTrail* auditTrail)
- : GrRenderTask(std::move(view))
+ : GrRenderTask()
, fArenas(arenas)
, fAuditTrail(auditTrail)
SkDEBUGCODE(, fNumClips(0)) {
- fTargetView.proxy()->setLastRenderTask(this);
+ this->addTarget(drawingMgr, std::move(view));
}
void GrOpsTask::deleteOps() {
@@ -388,20 +388,16 @@ void GrOpsTask::removeClosedObserver(GrOpsTaskClosedObserver* observer) {
}
}
-void GrOpsTask::endFlush() {
+void GrOpsTask::endFlush(GrDrawingManager* drawingMgr) {
fLastClipStackGenID = SK_InvalidUniqueID;
this->deleteOps();
fClipAllocator.reset();
- GrSurfaceProxy* proxy = fTargetView.proxy();
- if (proxy && this == proxy->getLastRenderTask()) {
- proxy->setLastRenderTask(nullptr);
- }
-
- fTargetView.reset();
fDeferredProxies.reset();
fSampledProxies.reset();
fAuditTrail = nullptr;
+
+ GrRenderTask::endFlush(drawingMgr);
}
void GrOpsTask::onPrePrepare(GrRecordingContext* context) {
@@ -420,7 +416,7 @@ void GrOpsTask::onPrePrepare(GrRecordingContext* context) {
for (const auto& chain : fOpChains) {
if (chain.shouldExecute()) {
chain.head()->prePrepare(context,
- &fTargetView,
+ &fTargets[0],
chain.appliedClip(),
chain.dstProxyView());
}
@@ -428,7 +424,7 @@ void GrOpsTask::onPrePrepare(GrRecordingContext* context) {
}
void GrOpsTask::onPrepare(GrOpFlushState* flushState) {
- SkASSERT(fTargetView.proxy()->peekRenderTarget());
+ SkASSERT(this->target(0).proxy()->peekRenderTarget());
SkASSERT(this->isClosed());
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
@@ -449,7 +445,7 @@ void GrOpsTask::onPrepare(GrOpFlushState* flushState) {
TRACE_EVENT0("skia.gpu", chain.head()->name());
#endif
GrOpFlushState::OpArgs opArgs(chain.head(),
- &fTargetView,
+ &fTargets[0],
chain.appliedClip(),
chain.dstProxyView());
@@ -457,7 +453,7 @@ void GrOpsTask::onPrepare(GrOpFlushState* flushState) {
// Temporary debugging helper: for debugging prePrepare w/o going through DDLs
// Delete once most of the GrOps have an onPrePrepare.
- // chain.head()->prePrepare(flushState->gpu()->getContext(), &fTargetView,
+ // chain.head()->prePrepare(flushState->gpu()->getContext(), &this->target(0),
// chain.appliedClip());
// GrOp::prePrepare may or may not have been called at this point
@@ -469,9 +465,10 @@ void GrOpsTask::onPrepare(GrOpFlushState* flushState) {
}
static GrOpsRenderPass* create_render_pass(
- GrGpu* gpu, GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
- GrLoadOp colorLoadOp, const SkPMColor4f& loadClearColor, GrLoadOp stencilLoadOp,
- GrStoreOp stencilStoreOp, const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
+ GrGpu* gpu, GrRenderTarget* rt, GrStencilAttachment* stencil, GrSurfaceOrigin origin,
+ const SkIRect& bounds, GrLoadOp colorLoadOp, const SkPMColor4f& loadClearColor,
+ GrLoadOp stencilLoadOp, GrStoreOp stencilStoreOp,
+ const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
const GrOpsRenderPass::LoadAndStoreInfo kColorLoadStoreInfo {
colorLoadOp,
GrStoreOp::kStore,
@@ -488,8 +485,8 @@ static GrOpsRenderPass* create_render_pass(
stencilStoreOp,
};
- return gpu->getOpsRenderPass(rt, origin, bounds, kColorLoadStoreInfo, stencilLoadAndStoreInfo,
- sampledProxies);
+ return gpu->getOpsRenderPass(rt, stencil, origin, bounds,
+ kColorLoadStoreInfo, stencilLoadAndStoreInfo, sampledProxies);
}
// TODO: this is where GrOp::renderTarget is used (which is fine since it
@@ -504,8 +501,8 @@ bool GrOpsTask::onExecute(GrOpFlushState* flushState) {
return false;
}
- SkASSERT(fTargetView.proxy());
- GrRenderTargetProxy* proxy = fTargetView.proxy()->asRenderTargetProxy();
+ SkASSERT(this->numTargets() == 1);
+ GrRenderTargetProxy* proxy = this->target(0).proxy()->asRenderTargetProxy();
SkASSERT(proxy);
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
@@ -553,6 +550,7 @@ bool GrOpsTask::onExecute(GrOpFlushState* flushState) {
// once finished, meaning the stencil values will always remain cleared after the
// initial clear. Just fall through to reloading the existing (cleared) stencil values
// from memory.
+ [[fallthrough]];
case StencilContent::kPreserved:
SkASSERT(stencil);
stencilLoadOp = GrLoadOp::kLoad;
@@ -571,7 +569,7 @@ bool GrOpsTask::onExecute(GrOpFlushState* flushState) {
: GrStoreOp::kStore;
GrOpsRenderPass* renderPass = create_render_pass(
- flushState->gpu(), proxy->peekRenderTarget(), fTargetView.origin(),
+ flushState->gpu(), proxy->peekRenderTarget(), stencil, this->target(0).origin(),
fClippedContentBounds, fColorLoadOp, fLoadClearColor, stencilLoadOp, stencilStoreOp,
fSampledProxies);
if (!renderPass) {
@@ -590,7 +588,7 @@ bool GrOpsTask::onExecute(GrOpFlushState* flushState) {
#endif
GrOpFlushState::OpArgs opArgs(chain.head(),
- &fTargetView,
+ &fTargets[0],
chain.appliedClip(),
chain.dstProxyView());
@@ -610,9 +608,9 @@ void GrOpsTask::setColorLoadOp(GrLoadOp op, const SkPMColor4f& color) {
fColorLoadOp = op;
fLoadClearColor = color;
if (GrLoadOp::kClear == fColorLoadOp) {
- GrSurfaceProxy* proxy = fTargetView.proxy();
+ GrSurfaceProxy* proxy = this->target(0).proxy();
SkASSERT(proxy);
- fTotalBounds = proxy->getBoundsRect();
+ fTotalBounds = proxy->backingStoreBoundsRect();
}
}
@@ -631,7 +629,7 @@ bool GrOpsTask::resetForFullscreenClear(CanDiscardPreviousOps canDiscardPrevious
// If the opsTask is using a render target which wraps a vulkan command buffer, we can't do
// a clear load since we cannot change the render pass that we are using. Thus we fall back
// to making a clear op in this case.
- return !fTargetView.asRenderTargetProxy()->wrapsVkSecondaryCB();
+ return !this->target(0).asRenderTargetProxy()->wrapsVkSecondaryCB();
}
// Could not empty the task, so an op must be added to handle the clear
@@ -757,7 +755,7 @@ void GrOpsTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
alloc->addInterval(fDeferredProxies[i], 0, 0, GrResourceAllocator::ActualUse::kNo);
}
- GrSurfaceProxy* targetProxy = fTargetView.proxy();
+ GrSurfaceProxy* targetProxy = this->target(0).proxy();
// Add the interval for all the writes to this GrOpsTasks's target
if (fOpChains.count()) {
@@ -776,7 +774,7 @@ void GrOpsTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
auto gather = [ alloc SkDEBUGCODE(, this) ] (GrSurfaceProxy* p, GrMipMapped) {
alloc->addInterval(p, alloc->curOp(), alloc->curOp(), GrResourceAllocator::ActualUse::kYes
- SkDEBUGCODE(, fTargetView.proxy() == p));
+ SkDEBUGCODE(, this->target(0).proxy() == p));
};
for (const OpChain& recordedOp : fOpChains) {
recordedOp.visitProxies(gather);
@@ -792,7 +790,7 @@ void GrOpsTask::recordOp(
const DstProxyView* dstProxyView, const GrCaps& caps) {
SkDEBUGCODE(op->validate();)
SkASSERT(processorAnalysis.requiresDstTexture() == (dstProxyView && dstProxyView->proxy()));
- GrSurfaceProxy* proxy = fTargetView.proxy();
+ GrSurfaceProxy* proxy = this->target(0).proxy();
SkASSERT(proxy);
// A closed GrOpsTask should never receive new/more ops
@@ -892,9 +890,11 @@ GrRenderTask::ExpectedOutcome GrOpsTask::onMakeClosed(
fClosedObservers.reset();
});
if (!this->isNoOp()) {
- GrSurfaceProxy* proxy = fTargetView.proxy();
- SkRect clippedContentBounds = proxy->getBoundsRect();
- // TODO: If we can fix up GLPrograms test to always intersect the fTargetView proxy bounds
+ GrSurfaceProxy* proxy = this->target(0).proxy();
+ // Use the entire backing store bounds since the GPU doesn't clip automatically to the
+ // logical dimensions.
+ SkRect clippedContentBounds = proxy->backingStoreBoundsRect();
+ // TODO: If we can fix up GLPrograms test to always intersect the target proxy bounds
// then we can simply assert here that the bounds intersect.
if (clippedContentBounds.intersect(fTotalBounds)) {
clippedContentBounds.roundOut(&fClippedContentBounds);
diff --git a/chromium/third_party/skia/src/gpu/GrOpsTask.h b/chromium/third_party/skia/src/gpu/GrOpsTask.h
index 0baf847e282..a40a51a9edd 100644
--- a/chromium/third_party/skia/src/gpu/GrOpsTask.h
+++ b/chromium/third_party/skia/src/gpu/GrOpsTask.h
@@ -51,7 +51,7 @@ private:
public:
// The Arenas must outlive the GrOpsTask, either by preserving the context that owns
// the pool, or by moving the pool to the DDL that takes over the GrOpsTask.
- GrOpsTask(GrRecordingContext::Arenas, GrSurfaceProxyView, GrAuditTrail*);
+ GrOpsTask(GrDrawingManager*, GrRecordingContext::Arenas, GrSurfaceProxyView, GrAuditTrail*);
~GrOpsTask() override;
GrOpsTask* asOpsTask() override { return this; }
@@ -68,7 +68,7 @@ public:
/**
* Empties the draw buffer of any queued up draws.
*/
- void endFlush() override;
+ void endFlush(GrDrawingManager*) override;
void onPrePrepare(GrRecordingContext*) override;
/**
@@ -88,11 +88,11 @@ public:
fSampledProxies.push_back(proxy);
}
- void addOp(std::unique_ptr<GrOp> op, GrTextureResolveManager textureResolveManager,
- const GrCaps& caps) {
- auto addDependency = [ textureResolveManager, &caps, this ] (
+ void addOp(GrDrawingManager* drawingMgr, std::unique_ptr<GrOp> op,
+ GrTextureResolveManager textureResolveManager, const GrCaps& caps) {
+ auto addDependency = [ drawingMgr, textureResolveManager, &caps, this ] (
GrSurfaceProxy* p, GrMipMapped mipmapped) {
- this->addDependency(p, mipmapped, textureResolveManager, caps);
+ this->addDependency(drawingMgr, p, mipmapped, textureResolveManager, caps);
};
op->visitProxies(addDependency);
@@ -100,19 +100,20 @@ public:
this->recordOp(std::move(op), GrProcessorSet::EmptySetAnalysis(), nullptr, nullptr, caps);
}
- void addWaitOp(std::unique_ptr<GrOp> op, GrTextureResolveManager textureResolveManager,
- const GrCaps& caps) {
+ void addWaitOp(GrDrawingManager* drawingMgr, std::unique_ptr<GrOp> op,
+ GrTextureResolveManager textureResolveManager, const GrCaps& caps) {
fHasWaitOp = true;
- this->addOp(std::move(op), textureResolveManager, caps);
+ this->addOp(drawingMgr, std::move(op), textureResolveManager, caps);
}
- void addDrawOp(std::unique_ptr<GrDrawOp> op, const GrProcessorSet::Analysis& processorAnalysis,
+ void addDrawOp(GrDrawingManager* drawingMgr, std::unique_ptr<GrDrawOp> op,
+ const GrProcessorSet::Analysis& processorAnalysis,
GrAppliedClip&& clip, const DstProxyView& dstProxyView,
GrTextureResolveManager textureResolveManager, const GrCaps& caps) {
- auto addDependency = [ textureResolveManager, &caps, this ] (
+ auto addDependency = [ drawingMgr, textureResolveManager, &caps, this ] (
GrSurfaceProxy* p, GrMipMapped mipmapped) {
this->addSampledTexture(p);
- this->addDependency(p, mipmapped, textureResolveManager, caps);
+ this->addDependency(drawingMgr, p, mipmapped, textureResolveManager, caps);
};
op->visitProxies(addDependency);
diff --git a/chromium/third_party/skia/src/gpu/GrPathRenderer.h b/chromium/third_party/skia/src/gpu/GrPathRenderer.h
index 47e65362c11..0866e0106c4 100644
--- a/chromium/third_party/skia/src/gpu/GrPathRenderer.h
+++ b/chromium/third_party/skia/src/gpu/GrPathRenderer.h
@@ -14,7 +14,6 @@
class GrCaps;
class GrClip;
-class GrFixedClip;
class GrHardClip;
class GrPaint;
class GrRecordingContext;
@@ -127,7 +126,6 @@ public:
SkASSERT(fContext);
SkASSERT(fUserStencilSettings);
SkASSERT(fRenderTargetContext);
- SkASSERT(fClip);
SkASSERT(fClipConservativeBounds);
SkASSERT(fViewMatrix);
SkASSERT(fShape);
diff --git a/chromium/third_party/skia/src/gpu/GrPathRendererChain.cpp b/chromium/third_party/skia/src/gpu/GrPathRendererChain.cpp
index ca2d7e4c867..cf7e271f306 100644
--- a/chromium/third_party/skia/src/gpu/GrPathRendererChain.cpp
+++ b/chromium/third_party/skia/src/gpu/GrPathRendererChain.cpp
@@ -32,7 +32,7 @@ GrPathRendererChain::GrPathRendererChain(GrRecordingContext* context, const Opti
fChain.push_back(sk_make_sp<GrDashLinePathRenderer>());
}
if (options.fGpuPathRenderers & GpuPathRenderers::kTessellation) {
- if (caps.shaderCaps()->tessellationSupport() && caps.drawInstancedSupport()) {
+ if (caps.drawInstancedSupport()) {
auto tess = sk_make_sp<GrTessellationPathRenderer>(caps);
context->priv().addOnFlushCallbackObject(tess.get());
fChain.push_back(std::move(tess));
diff --git a/chromium/third_party/skia/src/gpu/GrPersistentCacheUtils.h b/chromium/third_party/skia/src/gpu/GrPersistentCacheUtils.h
index fe932c26194..d6a15e73280 100644
--- a/chromium/third_party/skia/src/gpu/GrPersistentCacheUtils.h
+++ b/chromium/third_party/skia/src/gpu/GrPersistentCacheUtils.h
@@ -10,8 +10,8 @@
#include "include/core/SkData.h"
#include "include/private/GrTypesPriv.h"
-#include "src/core/SkReader32.h"
-#include "src/core/SkWriter32.h"
+#include "src/core/SkReadBuffer.h"
+#include "src/core/SkWriteBuffer.h"
#include "src/sksl/SkSLString.h"
#include "src/sksl/ir/SkSLProgram.h"
@@ -28,7 +28,7 @@ struct ShaderMetadata {
};
// Increment this whenever the serialization format of cached shaders changes
-static constexpr int kCurrentVersion = 1;
+static constexpr int kCurrentVersion = 2;
static inline sk_sp<SkData> PackCachedShaders(SkFourByteTag shaderType,
const SkSL::String shaders[],
@@ -39,12 +39,12 @@ static inline sk_sp<SkData> PackCachedShaders(SkFourByteTag shaderType,
// kGrShaderTypeCount inputs. If the backend gives us fewer, we just replicate the last one.
SkASSERT(numInputs >= 1 && numInputs <= kGrShaderTypeCount);
- SkWriter32 writer;
- writer.write32(kCurrentVersion);
- writer.write32(shaderType);
+ SkBinaryWriteBuffer writer;
+ writer.writeInt(kCurrentVersion);
+ writer.writeUInt(shaderType);
for (int i = 0; i < kGrShaderTypeCount; ++i) {
- writer.writeString(shaders[i].c_str(), shaders[i].size());
- writer.writePad(&inputs[std::min(i, numInputs - 1)], sizeof(SkSL::Program::Inputs));
+ writer.writeByteArray(shaders[i].c_str(), shaders[i].size());
+ writer.writePad32(&inputs[std::min(i, numInputs - 1)], sizeof(SkSL::Program::Inputs));
}
writer.writeBool(SkToBool(meta));
if (meta) {
@@ -57,7 +57,7 @@ static inline sk_sp<SkData> PackCachedShaders(SkFourByteTag shaderType,
writer.writeInt(meta->fAttributeNames.count());
for (const auto& attr : meta->fAttributeNames) {
- writer.writeString(attr.c_str(), attr.size());
+ writer.writeByteArray(attr.c_str(), attr.size());
}
writer.writeBool(meta->fHasCustomColorOutput);
@@ -66,30 +66,28 @@ static inline sk_sp<SkData> PackCachedShaders(SkFourByteTag shaderType,
return writer.snapshotAsData();
}
-static SkFourByteTag GetType(SkReader32* reader) {
+static SkFourByteTag GetType(SkReadBuffer* reader) {
constexpr SkFourByteTag kInvalidTag = ~0;
- if (!reader->isAvailable(2 * sizeof(int))) {
- return kInvalidTag;
- }
- if (reader->readInt() != kCurrentVersion) {
- return kInvalidTag;
- }
- return reader->readU32();
+ int version = reader->readInt();
+ SkFourByteTag typeTag = reader->readUInt();
+ return reader->validate(version == kCurrentVersion) ? typeTag : kInvalidTag;
}
-static inline void UnpackCachedShaders(SkReader32* reader,
+static inline bool UnpackCachedShaders(SkReadBuffer* reader,
SkSL::String shaders[],
SkSL::Program::Inputs inputs[],
int numInputs,
ShaderMetadata* meta = nullptr) {
for (int i = 0; i < kGrShaderTypeCount; ++i) {
- size_t stringLen = 0;
- const char* string = reader->readString(&stringLen);
- shaders[i] = SkSL::String(string, stringLen);
+ size_t shaderLen = 0;
+ const char* shaderBuf = static_cast<const char*>(reader->skipByteArray(&shaderLen));
+ if (shaderBuf) {
+ shaders[i].assign(shaderBuf, shaderLen);
+ }
// GL, for example, only wants one set of Inputs
if (i < numInputs) {
- reader->read(&inputs[i], sizeof(inputs[i]));
+ reader->readPad32(&inputs[i], sizeof(inputs[i]));
} else {
reader->skip(sizeof(SkSL::Program::Inputs));
}
@@ -104,15 +102,24 @@ static inline void UnpackCachedShaders(SkReader32* reader,
}
meta->fAttributeNames.resize(reader->readInt());
- for (int i = 0; i < meta->fAttributeNames.count(); ++i) {
- size_t stringLen = 0;
- const char* string = reader->readString(&stringLen);
- meta->fAttributeNames[i] = SkSL::String(string, stringLen);
+ for (auto& attr : meta->fAttributeNames) {
+ size_t attrLen = 0;
+ const char* attrName = static_cast<const char*>(reader->skipByteArray(&attrLen));
+ if (attrName) {
+ attr.assign(attrName, attrLen);
+ }
}
meta->fHasCustomColorOutput = reader->readBool();
meta->fHasSecondaryColorOutput = reader->readBool();
}
+
+ if (!reader->isValid()) {
+ for (int i = 0; i < kGrShaderTypeCount; ++i) {
+ shaders[i].clear();
+ }
+ }
+ return reader->isValid();
}
}
diff --git a/chromium/third_party/skia/src/gpu/GrPrimitiveProcessor.h b/chromium/third_party/skia/src/gpu/GrPrimitiveProcessor.h
index 40d4c93d586..c7741833f55 100644
--- a/chromium/third_party/skia/src/gpu/GrPrimitiveProcessor.h
+++ b/chromium/third_party/skia/src/gpu/GrPrimitiveProcessor.h
@@ -36,6 +36,7 @@ class GrCoordTransform;
*/
class GrGLSLPrimitiveProcessor;
+class GrGLSLUniformHandler;
/**
* GrPrimitiveProcessor defines an interface which all subclasses must implement. All
@@ -56,12 +57,14 @@ public:
constexpr Attribute(const char* name,
GrVertexAttribType cpuType,
GrSLType gpuType)
- : fName(name), fCPUType(cpuType), fGPUType(gpuType) {}
+ : fName(name), fCPUType(cpuType), fGPUType(gpuType) {
+ SkASSERT(name && gpuType != kVoid_GrSLType);
+ }
constexpr Attribute(const Attribute&) = default;
Attribute& operator=(const Attribute&) = default;
- constexpr bool isInitialized() const { return SkToBool(fName); }
+ constexpr bool isInitialized() const { return fGPUType != kVoid_GrSLType; }
constexpr const char* name() const { return fName; }
constexpr GrVertexAttribType cpuType() const { return fCPUType; }
@@ -77,7 +80,7 @@ public:
private:
const char* fName = nullptr;
GrVertexAttribType fCPUType = kFloat_GrVertexAttribType;
- GrSLType fGPUType = kFloat_GrSLType;
+ GrSLType fGPUType = kVoid_GrSLType;
};
class Iter {
@@ -213,11 +216,15 @@ public:
// We use these methods as a temporary back door to inject OpenGL tessellation code. Once
// tessellation is supported by SkSL we can remove these.
- virtual SkString getTessControlShaderGLSL(const char* versionAndExtensionDecls,
+ virtual SkString getTessControlShaderGLSL(const GrGLSLPrimitiveProcessor*,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
const GrShaderCaps&) const {
SK_ABORT("Not implemented.");
}
- virtual SkString getTessEvaluationShaderGLSL(const char* versionAndExtensionDecls,
+ virtual SkString getTessEvaluationShaderGLSL(const GrGLSLPrimitiveProcessor*,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
const GrShaderCaps&) const {
SK_ABORT("Not implemented.");
}
diff --git a/chromium/third_party/skia/src/gpu/GrProcessor.h b/chromium/third_party/skia/src/gpu/GrProcessor.h
index cb4711c6960..80ec7e390a1 100644
--- a/chromium/third_party/skia/src/gpu/GrProcessor.h
+++ b/chromium/third_party/skia/src/gpu/GrProcessor.h
@@ -125,7 +125,6 @@ public:
kGrPathProcessor_ClassID,
kGrPerlinNoise2Effect_ClassID,
kGrPipelineDynamicStateTestProcessor_ClassID,
- kGrPremulInputFragmentProcessor_ClassID,
kGrQuadEffect_ClassID,
kGrRadialGradientLayout_ClassID,
kGrRectBlurEffect_ClassID,
@@ -162,9 +161,10 @@ public:
kTessellate_GrFillBoundingBoxShader_ClassID,
kTessellate_GrFillCubicHullShader_ClassID,
kTessellate_GrFillTriangleShader_ClassID,
- kTessellate_GrStencilCubicShader_ClassID,
+ kTessellate_GrMiddleOutCubicShader_ClassID,
kTessellate_GrStencilTriangleShader_ClassID,
- kTessellate_GrStencilWedgeShader_ClassID,
+ kTessellate_GrTessellateCubicShader_ClassID,
+ kTessellate_GrTessellateWedgeShader_ClassID,
kTestFP_ClassID,
kTestRectOp_ClassID,
kFlatNormalsFP_ClassID,
diff --git a/chromium/third_party/skia/src/gpu/GrProcessorSet.cpp b/chromium/third_party/skia/src/gpu/GrProcessorSet.cpp
index fe64cb9233d..b8a0aef92cc 100644
--- a/chromium/third_party/skia/src/gpu/GrProcessorSet.cpp
+++ b/chromium/third_party/skia/src/gpu/GrProcessorSet.cpp
@@ -69,8 +69,9 @@ GrProcessorSet::GrProcessorSet(GrProcessorSet&& that)
fFragmentProcessors[i] =
std::move(that.fFragmentProcessors[i + that.fFragmentProcessorOffset]);
}
- that.fColorFragmentProcessorCnt = 0;
that.fFragmentProcessors.reset(0);
+ that.fColorFragmentProcessorCnt = 0;
+ that.fFragmentProcessorOffset = 0;
}
GrProcessorSet::~GrProcessorSet() {
diff --git a/chromium/third_party/skia/src/gpu/GrProgramInfo.h b/chromium/third_party/skia/src/gpu/GrProgramInfo.h
index 373b3bbafdb..f8ce3fc7011 100644
--- a/chromium/third_party/skia/src/gpu/GrProgramInfo.h
+++ b/chromium/third_party/skia/src/gpu/GrProgramInfo.h
@@ -49,6 +49,7 @@ public:
int numSamples() const { return fNumSamples; }
int numStencilSamples() const { return fNumStencilSamples; }
+ bool isStencilEnabled() const { return fPipeline->isStencilEnabled(); }
int numRasterSamples() const {
return fPipeline->isStencilEnabled() ? fNumStencilSamples : fNumSamples;
diff --git a/chromium/third_party/skia/src/gpu/GrProxyProvider.cpp b/chromium/third_party/skia/src/gpu/GrProxyProvider.cpp
index cf20dd1d715..e2bfd767ff0 100644
--- a/chromium/third_party/skia/src/gpu/GrProxyProvider.cpp
+++ b/chromium/third_party/skia/src/gpu/GrProxyProvider.cpp
@@ -33,8 +33,7 @@
#include "src/gpu/SkGr.h"
#include "src/image/SkImage_Base.h"
-#define ASSERT_SINGLE_OWNER \
- SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fImageContext->priv().singleOwner());)
+#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fImageContext->priv().singleOwner())
GrProxyProvider::GrProxyProvider(GrImageContext* imageContext) : fImageContext(imageContext) {}
@@ -54,6 +53,9 @@ bool GrProxyProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTexturePr
return false;
}
+ // Only the proxyProvider that created a proxy should be assigning unique keys to it.
+ SkASSERT(this->isDDLProvider() == proxy->creatingProvider());
+
#ifdef SK_DEBUG
{
GrContext* direct = fImageContext->priv().asDirectContext();
@@ -189,9 +191,11 @@ sk_sp<GrTextureProxy> GrProxyProvider::createWrapped(sk_sp<GrTexture> tex,
#endif
if (tex->asRenderTarget()) {
- return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), useAllocator));
+ return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), useAllocator,
+ this->isDDLProvider()));
} else {
- return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), useAllocator));
+ return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), useAllocator,
+ this->isDDLProvider()));
}
}
@@ -424,19 +428,18 @@ sk_sp<GrTextureProxy> GrProxyProvider::createProxy(const GrBackendFormat& format
? GrMipMapsStatus::kDirty
: GrMipMapsStatus::kNotAllocated;
if (renderable == GrRenderable::kYes) {
- renderTargetSampleCnt =
- caps->getRenderTargetSampleCount(renderTargetSampleCnt, format);
+ renderTargetSampleCnt = caps->getRenderTargetSampleCount(renderTargetSampleCnt, format);
SkASSERT(renderTargetSampleCnt);
// We know anything we instantiate later from this deferred path will be
// both texturable and renderable
return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(
*caps, format, dimensions, renderTargetSampleCnt, mipMapped, mipMapsStatus, fit,
- budgeted, isProtected, surfaceFlags, useAllocator));
+ budgeted, isProtected, surfaceFlags, useAllocator, this->isDDLProvider()));
}
return sk_sp<GrTextureProxy>(new GrTextureProxy(format, dimensions, mipMapped, mipMapsStatus,
fit, budgeted, isProtected, surfaceFlags,
- useAllocator));
+ useAllocator, this->isDDLProvider()));
}
sk_sp<GrTextureProxy> GrProxyProvider::createCompressedTextureProxy(
@@ -487,9 +490,9 @@ sk_sp<GrTextureProxy> GrProxyProvider::wrapBackendTexture(const GrBackendTexture
GrWrapOwnership ownership,
GrWrapCacheable cacheable,
GrIOType ioType,
- ReleaseProc releaseProc,
- ReleaseContext releaseCtx) {
+ sk_sp<GrRefCntedCallback> releaseHelper) {
SkASSERT(ioType != kWrite_GrIOType);
+
if (this->isAbandoned()) {
return nullptr;
}
@@ -508,22 +511,23 @@ sk_sp<GrTextureProxy> GrProxyProvider::wrapBackendTexture(const GrBackendTexture
return nullptr;
}
- if (releaseProc) {
- tex->setRelease(releaseProc, releaseCtx);
+ if (releaseHelper) {
+ tex->setRelease(std::move(releaseHelper));
}
SkASSERT(!tex->asRenderTarget()); // Strictly a GrTexture
// Make sure we match how we created the proxy with SkBudgeted::kNo
SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
- return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), UseAllocator::kNo));
+ return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), UseAllocator::kNo,
+ this->isDDLProvider()));
}
-sk_sp<GrTextureProxy> GrProxyProvider::wrapCompressedBackendTexture(const GrBackendTexture& beTex,
- GrWrapOwnership ownership,
- GrWrapCacheable cacheable,
- ReleaseProc releaseProc,
- ReleaseContext releaseCtx) {
+sk_sp<GrTextureProxy> GrProxyProvider::wrapCompressedBackendTexture(
+ const GrBackendTexture& beTex,
+ GrWrapOwnership ownership,
+ GrWrapCacheable cacheable,
+ sk_sp<GrRefCntedCallback> releaseHelper) {
if (this->isAbandoned()) {
return nullptr;
}
@@ -542,15 +546,16 @@ sk_sp<GrTextureProxy> GrProxyProvider::wrapCompressedBackendTexture(const GrBack
return nullptr;
}
- if (releaseProc) {
- tex->setRelease(releaseProc, releaseCtx);
+ if (releaseHelper) {
+ tex->setRelease(std::move(releaseHelper));
}
SkASSERT(!tex->asRenderTarget()); // Strictly a GrTexture
// Make sure we match how we created the proxy with SkBudgeted::kNo
SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
- return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), UseAllocator::kNo));
+ return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex), UseAllocator::kNo,
+ this->isDDLProvider()));
}
sk_sp<GrTextureProxy> GrProxyProvider::wrapRenderableBackendTexture(
@@ -558,8 +563,7 @@ sk_sp<GrTextureProxy> GrProxyProvider::wrapRenderableBackendTexture(
int sampleCnt,
GrWrapOwnership ownership,
GrWrapCacheable cacheable,
- ReleaseProc releaseProc,
- ReleaseContext releaseCtx) {
+ sk_sp<GrRefCntedCallback> releaseHelper) {
if (this->isAbandoned()) {
return nullptr;
}
@@ -583,21 +587,21 @@ sk_sp<GrTextureProxy> GrProxyProvider::wrapRenderableBackendTexture(
return nullptr;
}
- if (releaseProc) {
- tex->setRelease(releaseProc, releaseCtx);
+ if (releaseHelper) {
+ tex->setRelease(std::move(releaseHelper));
}
SkASSERT(tex->asRenderTarget()); // A GrTextureRenderTarget
// Make sure we match how we created the proxy with SkBudgeted::kNo
SkASSERT(GrBudgetedType::kBudgeted != tex->resourcePriv().budgetedType());
- return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), UseAllocator::kNo));
+ return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex), UseAllocator::kNo,
+ this->isDDLProvider()));
}
sk_sp<GrSurfaceProxy> GrProxyProvider::wrapBackendRenderTarget(
const GrBackendRenderTarget& backendRT,
- ReleaseProc releaseProc,
- ReleaseContext releaseCtx) {
+ sk_sp<GrRefCntedCallback> releaseHelper) {
if (this->isAbandoned()) {
return nullptr;
}
@@ -615,8 +619,8 @@ sk_sp<GrSurfaceProxy> GrProxyProvider::wrapBackendRenderTarget(
return nullptr;
}
- if (releaseProc) {
- rt->setRelease(releaseProc, releaseCtx);
+ if (releaseHelper) {
+ rt->setRelease(std::move(releaseHelper));
}
SkASSERT(!rt->asTexture()); // A GrRenderTarget that's not textureable
@@ -730,7 +734,8 @@ sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&&
budgeted,
isProtected,
surfaceFlags,
- useAllocator));
+ useAllocator,
+ this->isDDLProvider()));
} else {
return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(callback),
format,
@@ -741,7 +746,8 @@ sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&&
budgeted,
isProtected,
surfaceFlags,
- useAllocator));
+ useAllocator,
+ this->isDDLProvider()));
}
}
@@ -777,7 +783,7 @@ sk_sp<GrRenderTargetProxy> GrProxyProvider::createLazyRenderTargetProxy(
return sk_sp<GrRenderTargetProxy>(new GrTextureRenderTargetProxy(
*this->caps(), std::move(callback), format, dimensions, sampleCnt,
textureInfo->fMipMapped, mipMapsStatus, fit, budgeted, isProtected, surfaceFlags,
- useAllocator));
+ useAllocator, this->isDDLProvider()));
}
GrRenderTargetProxy::WrapsVkSecondaryCB vkSCB =
@@ -803,17 +809,20 @@ sk_sp<GrTextureProxy> GrProxyProvider::MakeFullyLazyProxy(LazyInstantiateCallbac
SkASSERT(renderTargetSampleCnt == 1 || renderable == GrRenderable::kYes);
GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone;
+ // MakeFullyLazyProxy is only called at flush time so we know these texture proxies are
+ // not being created by a DDL provider.
static constexpr SkISize kLazyDims = {-1, -1};
if (GrRenderable::kYes == renderable) {
return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(
caps, std::move(callback), format, kLazyDims, renderTargetSampleCnt,
GrMipMapped::kNo, GrMipMapsStatus::kNotAllocated, SkBackingFit::kApprox,
- SkBudgeted::kYes, isProtected, surfaceFlags, useAllocator));
+ SkBudgeted::kYes, isProtected, surfaceFlags, useAllocator, GrDDLProvider::kNo));
} else {
return sk_sp<GrTextureProxy>(
new GrTextureProxy(std::move(callback), format, kLazyDims, GrMipMapped::kNo,
GrMipMapsStatus::kNotAllocated, SkBackingFit::kApprox,
- SkBudgeted::kYes, isProtected, surfaceFlags, useAllocator));
+ SkBudgeted::kYes, isProtected, surfaceFlags, useAllocator,
+ GrDDLProvider::kNo));
}
}
@@ -858,6 +867,10 @@ void GrProxyProvider::processInvalidUniqueKeyImpl(const GrUniqueKey& key, GrText
}
}
+GrDDLProvider GrProxyProvider::isDDLProvider() const {
+ return fImageContext->priv().asDirectContext() ? GrDDLProvider::kNo : GrDDLProvider::kYes;
+}
+
uint32_t GrProxyProvider::contextID() const {
return fImageContext->priv().contextID();
}
diff --git a/chromium/third_party/skia/src/gpu/GrProxyProvider.h b/chromium/third_party/skia/src/gpu/GrProxyProvider.h
index a275f297940..e1f681f04b6 100644
--- a/chromium/third_party/skia/src/gpu/GrProxyProvider.h
+++ b/chromium/third_party/skia/src/gpu/GrProxyProvider.h
@@ -115,12 +115,12 @@ public:
GrWrapOwnership,
GrWrapCacheable,
GrIOType,
- ReleaseProc = nullptr,
- ReleaseContext = nullptr);
+ sk_sp<GrRefCntedCallback> = nullptr);
- sk_sp<GrTextureProxy> wrapCompressedBackendTexture(const GrBackendTexture&, GrWrapOwnership,
- GrWrapCacheable, ReleaseProc = nullptr,
- ReleaseContext = nullptr);
+ sk_sp<GrTextureProxy> wrapCompressedBackendTexture(const GrBackendTexture&,
+ GrWrapOwnership,
+ GrWrapCacheable,
+ sk_sp<GrRefCntedCallback> releaseHelper);
/*
* Create a texture proxy that wraps a backend texture and is both texture-able and renderable
@@ -129,15 +129,13 @@ public:
int sampleCnt,
GrWrapOwnership,
GrWrapCacheable,
- ReleaseProc = nullptr,
- ReleaseContext = nullptr);
+ sk_sp<GrRefCntedCallback> releaseHelper);
/*
* Create a render target proxy that wraps a backend render target
*/
sk_sp<GrSurfaceProxy> wrapBackendRenderTarget(const GrBackendRenderTarget&,
- ReleaseProc = nullptr,
- ReleaseContext = nullptr);
+ sk_sp<GrRefCntedCallback> releaseHelper);
/*
* Create a render target proxy that wraps a backend texture
@@ -223,6 +221,8 @@ public:
*/
void processInvalidUniqueKey(const GrUniqueKey&, GrTextureProxy*, InvalidateGPUResource);
+ GrDDLProvider isDDLProvider() const;
+
// TODO: remove these entry points - it is a bit sloppy to be getting context info from here
uint32_t contextID() const;
const GrCaps* caps() const;
diff --git a/chromium/third_party/skia/src/gpu/GrRecordingContext.cpp b/chromium/third_party/skia/src/gpu/GrRecordingContext.cpp
index 2c7c64d5730..9173931e4f1 100644
--- a/chromium/third_party/skia/src/gpu/GrRecordingContext.cpp
+++ b/chromium/third_party/skia/src/gpu/GrRecordingContext.cpp
@@ -8,6 +8,7 @@
#include "include/private/GrRecordingContext.h"
#include "include/gpu/GrContext.h"
+#include "include/gpu/GrContextThreadSafeProxy.h"
#include "src/core/SkArenaAlloc.h"
#include "src/gpu/GrAuditTrail.h"
#include "src/gpu/GrCaps.h"
@@ -22,9 +23,6 @@
#include "src/gpu/effects/GrSkSLFP.h"
#include "src/gpu/text/GrTextBlobCache.h"
-#define ASSERT_SINGLE_OWNER_PRIV \
- SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
-
GrRecordingContext::ProgramData::ProgramData(std::unique_ptr<const GrProgramDesc> desc,
const GrProgramInfo* info)
: fDesc(std::move(desc))
@@ -36,44 +34,34 @@ GrRecordingContext::ProgramData::ProgramData(ProgramData&& other)
, fInfo(other.fInfo) {
}
-GrRecordingContext::ProgramData::~ProgramData() {}
+GrRecordingContext::ProgramData::~ProgramData() = default;
-GrRecordingContext::GrRecordingContext(GrBackendApi backend,
- const GrContextOptions& options,
- uint32_t contextID)
- : INHERITED(backend, options, contextID)
+GrRecordingContext::GrRecordingContext(sk_sp<GrContextThreadSafeProxy> proxy)
+ : INHERITED(std::move(proxy))
, fAuditTrail(new GrAuditTrail()) {
}
-GrRecordingContext::~GrRecordingContext() { }
+GrRecordingContext::~GrRecordingContext() = default;
-/**
- * TODO: move textblob draw calls below context (see comment below)
- */
-static void textblobcache_overbudget_CB(void* data) {
- SkASSERT(data);
- GrRecordingContext* context = reinterpret_cast<GrRecordingContext*>(data);
+bool GrRecordingContext::init() {
- GrContext* direct = context->priv().asDirectContext();
- if (!direct) {
- return;
+ if (!INHERITED::init()) {
+ return false;
}
- // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on
- // GrRenderTargetContext to perform a necessary flush. The solution is to move drawText calls
- // to below the GrContext level, but this is not trivial because they call drawPath on
- // SkGpuDevice.
- direct->flush();
-}
-
-bool GrRecordingContext::init(sk_sp<const GrCaps> caps) {
+ auto overBudget = [this]() {
+ if (GrContext* direct = this->priv().asDirectContext(); direct != nullptr) {
- if (!INHERITED::init(std::move(caps))) {
- return false;
- }
+ // TODO: move text blob draw calls below context
+ // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on
+ // GrRenderTargetContext to perform a necessary flush. The solution is to move drawText
+ // calls to below the GrContext level, but this is not trivial because they call
+ // drawPath on SkGpuDevice.
+ direct->flushAndSubmit();
+ }
+ };
- fTextBlobCache.reset(new GrTextBlobCache(textblobcache_overbudget_CB, this,
- this->contextID()));
+ fTextBlobCache.reset(new GrTextBlobCache(overBudget, this->contextID()));
return true;
}
@@ -99,19 +87,8 @@ void GrRecordingContext::setupDrawingManager(bool sortOpsTasks, bool reduceOpsTa
prcOptions.fGpuPathRenderers &= ~GpuPathRenderers::kSmall;
}
- GrTextContext::Options textContextOptions;
- textContextOptions.fMaxDistanceFieldFontSize = this->options().fGlyphsAsPathsFontSize;
- textContextOptions.fMinDistanceFieldFontSize = this->options().fMinDistanceFieldFontSize;
- textContextOptions.fDistanceFieldVerticesAlwaysHaveW = false;
-#if SK_SUPPORT_ATLAS_TEXT
- if (GrContextOptions::Enable::kYes == this->options().fDistanceFieldGlyphVerticesAlwaysHaveW) {
- textContextOptions.fDistanceFieldVerticesAlwaysHaveW = true;
- }
-#endif
-
fDrawingManager.reset(new GrDrawingManager(this,
prcOptions,
- textContextOptions,
sortOpsTasks,
reduceOpsTaskSplitting));
}
diff --git a/chromium/third_party/skia/src/gpu/GrRecordingContextPriv.h b/chromium/third_party/skia/src/gpu/GrRecordingContextPriv.h
index 4337d3f3c4b..4e3e9a7a3da 100644
--- a/chromium/third_party/skia/src/gpu/GrRecordingContextPriv.h
+++ b/chromium/third_party/skia/src/gpu/GrRecordingContextPriv.h
@@ -9,6 +9,7 @@
#define GrRecordingContextPriv_DEFINED
#include "include/private/GrRecordingContext.h"
+#include "src/gpu/text/GrSDFTOptions.h"
/** Class that exposes methods to GrRecordingContext that are only intended for use internal to
Skia. This class is purely a privileged window into GrRecordingContext. It should never have
@@ -102,6 +103,10 @@ public:
return &fContext->fStats;
}
+ GrSDFTOptions SDFTOptions() const {
+ return {this->options().fMinDistanceFieldFontSize, this->options().fGlyphsAsPathsFontSize};
+ }
+
private:
explicit GrRecordingContextPriv(GrRecordingContext* context) : fContext(context) {}
GrRecordingContextPriv(const GrRecordingContextPriv&); // unimpl
diff --git a/chromium/third_party/skia/src/gpu/GrRectanizer.h b/chromium/third_party/skia/src/gpu/GrRectanizer.h
new file mode 100644
index 00000000000..0b1fff53348
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrRectanizer.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrRectanizer_DEFINED
+#define GrRectanizer_DEFINED
+
+#include "include/gpu/GrTypes.h"
+
+struct SkIPoint16;
+
+class GrRectanizer {
+public:
+ GrRectanizer(int width, int height) : fWidth(width), fHeight(height) {
+ SkASSERT(width >= 0);
+ SkASSERT(height >= 0);
+ }
+
+ virtual ~GrRectanizer() {}
+
+ virtual void reset() = 0;
+
+ int width() const { return fWidth; }
+ int height() const { return fHeight; }
+
+ // Attempt to add a rect. Return true on success; false on failure. If
+ // successful the position in the atlas is returned in 'loc'.
+ virtual bool addRect(int width, int height, SkIPoint16* loc) = 0;
+ virtual float percentFull() const = 0;
+
+ /**
+ * Our factory, which returns the subclass du jour
+ */
+ static GrRectanizer* Factory(int width, int height);
+
+private:
+ const int fWidth;
+ const int fHeight;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrRectanizerPow2.cpp b/chromium/third_party/skia/src/gpu/GrRectanizerPow2.cpp
new file mode 100644
index 00000000000..9a35bf298d2
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrRectanizerPow2.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/GrRectanizerPow2.h"
+
+bool GrRectanizerPow2::addRect(int width, int height, SkIPoint16* loc) {
+ if ((unsigned)width > (unsigned)this->width() ||
+ (unsigned)height > (unsigned)this->height()) {
+ return false;
+ }
+
+ int32_t area = width * height; // computed here since height will be modified
+
+ height = GrNextPow2(height);
+ if (height < kMIN_HEIGHT_POW2) {
+ height = kMIN_HEIGHT_POW2;
+ }
+
+ Row* row = &fRows[HeightToRowIndex(height)];
+ SkASSERT(row->fRowHeight == 0 || row->fRowHeight == height);
+
+ if (0 == row->fRowHeight) {
+ if (!this->canAddStrip(height)) {
+ return false;
+ }
+ this->initRow(row, height);
+ } else {
+ if (!row->canAddWidth(width, this->width())) {
+ if (!this->canAddStrip(height)) {
+ return false;
+ }
+ // that row is now "full", so retarget our Row record for
+ // another one
+ this->initRow(row, height);
+ }
+ }
+
+ SkASSERT(row->fRowHeight == height);
+ SkASSERT(row->canAddWidth(width, this->width()));
+ *loc = row->fLoc;
+ row->fLoc.fX += width;
+
+ SkASSERT(row->fLoc.fX <= this->width());
+ SkASSERT(row->fLoc.fY <= this->height());
+ SkASSERT(fNextStripY <= this->height());
+ fAreaSoFar += area;
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// factory is now in GrRectanizer_skyline.cpp
+//GrRectanizer* GrRectanizer::Factory(int width, int height) {
+// return new GrRectanizerPow2 (width, height);
+//}
diff --git a/chromium/third_party/skia/src/gpu/GrRectanizerPow2.h b/chromium/third_party/skia/src/gpu/GrRectanizerPow2.h
new file mode 100644
index 00000000000..c96c9725b16
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrRectanizerPow2.h
@@ -0,0 +1,83 @@
+/*
+* Copyright 2014 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#ifndef GrRectanizerPow2_DEFINED
+#define GrRectanizerPow2_DEFINED
+
+#include "include/private/SkMalloc.h"
+#include "src/core/SkIPoint16.h"
+#include "src/core/SkMathPriv.h"
+#include "src/gpu/GrRectanizer.h"
+
+// This Rectanizer quantizes the incoming rects to powers of 2. Each power
+// of two can have, at most, one active row/shelf. Once a row/shelf for
+// a particular power of two gets full its fRows entry is recycled to point
+// to a new row.
+// The skyline algorithm almost always provides a better packing.
+//
+// Mark this class final in an effort to avoid the vtable when this subclass is used explicitly.
+class GrRectanizerPow2 final : public GrRectanizer {
+public:
+ GrRectanizerPow2(int w, int h) : INHERITED(w, h) {
+ this->reset();
+ }
+
+ ~GrRectanizerPow2() final {}
+
+ void reset() final {
+ fNextStripY = 0;
+ fAreaSoFar = 0;
+ sk_bzero(fRows, sizeof(fRows));
+ }
+
+ bool addRect(int w, int h, SkIPoint16* loc) final;
+
+ float percentFull() const final {
+ return fAreaSoFar / ((float)this->width() * this->height());
+ }
+
+private:
+ static const int kMIN_HEIGHT_POW2 = 2;
+ static const int kMaxExponent = 16;
+
+ struct Row {
+ SkIPoint16 fLoc;
+ // fRowHeight is actually known by this struct's position in fRows
+ // but it is used to signal if there exists an open row of this height
+ int fRowHeight;
+
+ bool canAddWidth(int width, int containerWidth) const {
+ return fLoc.fX + width <= containerWidth;
+ }
+ };
+
+ Row fRows[kMaxExponent]; // 0-th entry will be unused
+
+ int fNextStripY;
+ int32_t fAreaSoFar;
+
+ static int HeightToRowIndex(int height) {
+ SkASSERT(height >= kMIN_HEIGHT_POW2);
+ int index = 32 - SkCLZ(height - 1);
+ SkASSERT(index < kMaxExponent);
+ return index;
+ }
+
+ bool canAddStrip(int height) const {
+ return fNextStripY + height <= this->height();
+ }
+
+ void initRow(Row* row, int rowHeight) {
+ row->fLoc.set(0, fNextStripY);
+ row->fRowHeight = rowHeight;
+ fNextStripY += rowHeight;
+ }
+
+ typedef GrRectanizer INHERITED;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.cpp b/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.cpp
index 42aff7a657f..f36b733d1dc 100644
--- a/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.cpp
+++ b/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.cpp
@@ -116,3 +116,8 @@ void GrRectanizerSkyline::addSkylineLevel(int skylineIndex, int x, int y, int wi
}
}
+///////////////////////////////////////////////////////////////////////////////
+
+GrRectanizer* GrRectanizer::Factory(int width, int height) {
+ return new GrRectanizerSkyline(width, height);
+}
diff --git a/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.h b/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.h
index 36af34db618..40e5c1cc163 100644
--- a/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.h
+++ b/chromium/third_party/skia/src/gpu/GrRectanizerSkyline.h
@@ -9,17 +9,21 @@
#define GrRectanizerSkyline_DEFINED
#include "include/private/SkTDArray.h"
-#include "src/core/SkIPoint16.h"
+#include "src/gpu/GrRectanizer.h"
// Pack rectangles and track the current silhouette
// Based, in part, on Jukka Jylanki's work at http://clb.demon.fi
-class GrRectanizerSkyline {
+//
+// Mark this class final in an effort to avoid the vtable when this subclass is used explicitly.
+class GrRectanizerSkyline final : public GrRectanizer {
public:
- GrRectanizerSkyline(int w, int h) : fWidth{w}, fHeight{h} {
+ GrRectanizerSkyline(int w, int h) : INHERITED(w, h) {
this->reset();
}
- void reset() {
+ ~GrRectanizerSkyline() final { }
+
+ void reset() final {
fAreaSoFar = 0;
fSkyline.reset();
SkylineSegment* seg = fSkyline.append(1);
@@ -28,10 +32,11 @@ public:
seg->fWidth = this->width();
}
- bool addRect(int w, int h, SkIPoint16* loc);
+ bool addRect(int w, int h, SkIPoint16* loc) final;
- int width() const { return fWidth; }
- int height() const { return fHeight; }
+ float percentFull() const final {
+ return fAreaSoFar / ((float)this->width() * this->height());
+ }
private:
struct SkylineSegment {
@@ -40,6 +45,10 @@ private:
int fWidth;
};
+ SkTDArray<SkylineSegment> fSkyline;
+
+ int32_t fAreaSoFar;
+
// Can a width x height rectangle fit in the free space represented by
// the skyline segments >= 'skylineIndex'? If so, return true and fill in
// 'y' with the y-location at which it fits (the x location is pulled from
@@ -49,10 +58,7 @@ private:
// at x,y.
void addSkylineLevel(int skylineIndex, int x, int y, int width, int height);
- const int fWidth;
- const int fHeight;
- SkTDArray<SkylineSegment> fSkyline;
- int32_t fAreaSoFar;
+ typedef GrRectanizer INHERITED;
};
-#endif // GrRectanizerSkyline_DEFINED
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrReducedClip.cpp b/chromium/third_party/skia/src/gpu/GrReducedClip.cpp
index 469b7f94e48..533132edc7c 100644
--- a/chromium/third_party/skia/src/gpu/GrReducedClip.cpp
+++ b/chromium/third_party/skia/src/gpu/GrReducedClip.cpp
@@ -25,7 +25,9 @@
#include "src/gpu/effects/GrConvexPolyEffect.h"
#include "src/gpu/effects/GrRRectEffect.h"
#include "src/gpu/effects/generated/GrAARectEffect.h"
+#include "src/gpu/effects/generated/GrDeviceSpaceEffect.h"
#include "src/gpu/geometry/GrStyledShape.h"
+#include "src/shaders/SkShaderBase.h"
/**
* There are plenty of optimizations that could be added here. Maybe flips could be folded into
@@ -115,6 +117,13 @@ GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds
// Now that we have determined the bounds to use and filtered out the trivial cases, call
// the helper that actually walks the stack.
this->walkStack(stack, tighterQuery);
+
+ if (fInitialState == InitialState::kAllOut && fMaskElements.isEmpty()) {
+ // The clip starts with no coverage and there are no elements to add coverage with
+ // expanding ops. We ignore the AAClipRectGenID since it is an implied intersection.
+ this->makeEmpty();
+ return;
+ }
}
if (SK_InvalidGenID != fAAClipRectGenID && // Is there an AA clip rect?
@@ -173,6 +182,18 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
break;
}
+ if (element->getDeviceSpaceType() == Element::DeviceSpaceType::kShader) {
+ if (fShader) {
+ // Combine multiple shaders together with src-in blending. This works because all
+ // shaders are effectively intersections (difference ops have been modified to be
+ // 1 - alpha already).
+ fShader = SkShaders::Blend(SkBlendMode::kSrcIn, element->refShader(), fShader);
+ } else {
+ fShader = element->refShader();
+ }
+ continue;
+ }
+
bool skippable = false;
bool isFlip = false; // does this op just flip the in/out state of every point in the bounds
@@ -480,6 +501,8 @@ void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBound
}
GrReducedClip::ClipResult GrReducedClip::clipInsideElement(const Element* element) {
+ SkASSERT(element->getDeviceSpaceType() != Element::DeviceSpaceType::kShader);
+
SkIRect elementIBounds;
if (!element->isAA()) {
element->getBounds().round(&elementIBounds);
@@ -523,12 +546,17 @@ GrReducedClip::ClipResult GrReducedClip::clipInsideElement(const Element* elemen
case Element::DeviceSpaceType::kPath:
return this->addAnalyticFP(element->getDeviceSpacePath(),
Invert(element->isInverseFilled()), GrAA(element->isAA()));
+
+ case Element::DeviceSpaceType::kShader:
+ SkUNREACHABLE;
}
SK_ABORT("Unexpected DeviceSpaceType");
}
GrReducedClip::ClipResult GrReducedClip::clipOutsideElement(const Element* element) {
+ SkASSERT(element->getDeviceSpaceType() != Element::DeviceSpaceType::kShader);
+
switch (element->getDeviceSpaceType()) {
case Element::DeviceSpaceType::kEmpty:
return ClipResult::kMadeEmpty;
@@ -589,6 +617,9 @@ GrReducedClip::ClipResult GrReducedClip::clipOutsideElement(const Element* eleme
case Element::DeviceSpaceType::kPath:
return this->addAnalyticFP(element->getDeviceSpacePath(),
Invert(!element->isInverseFilled()), GrAA(element->isAA()));
+
+ case Element::DeviceSpaceType::kShader:
+ SkUNREACHABLE;
}
SK_ABORT("Unexpected DeviceSpaceType");
@@ -620,9 +651,10 @@ GrReducedClip::ClipResult GrReducedClip::addAnalyticFP(const SkRect& deviceSpace
return ClipResult::kNotClipped;
}
- fAnalyticFPs.push_back(GrAARectEffect::Make(GetClipEdgeType(invert, aa), deviceSpaceRect));
- SkASSERT(fAnalyticFPs.back());
+ fAnalyticFP = GrAARectEffect::Make(std::move(fAnalyticFP), GetClipEdgeType(invert, aa),
+ deviceSpaceRect);
+ SkASSERT(fAnalyticFP != nullptr);
return ClipResult::kClipped;
}
@@ -632,9 +664,12 @@ GrReducedClip::ClipResult GrReducedClip::addAnalyticFP(const SkRRect& deviceSpac
return ClipResult::kNotClipped;
}
- if (auto fp = GrRRectEffect::Make(GetClipEdgeType(invert, aa), deviceSpaceRRect,
- *fCaps->shaderCaps())) {
- fAnalyticFPs.push_back(std::move(fp));
+ // Combine this analytic effect with the previous effect in the stack.
+ bool success;
+ std::tie(success, fAnalyticFP) = GrRRectEffect::Make(std::move(fAnalyticFP),
+ GetClipEdgeType(invert, aa),
+ deviceSpaceRRect, *fCaps->shaderCaps());
+ if (success) {
return ClipResult::kClipped;
}
@@ -650,8 +685,12 @@ GrReducedClip::ClipResult GrReducedClip::addAnalyticFP(const SkPath& deviceSpace
return ClipResult::kNotClipped;
}
- if (auto fp = GrConvexPolyEffect::Make(GetClipEdgeType(invert, aa), deviceSpacePath)) {
- fAnalyticFPs.push_back(std::move(fp));
+ // Combine this analytic effect with the previous effect in the stack.
+ bool success;
+ std::tie(success, fAnalyticFP) = GrConvexPolyEffect::Make(std::move(fAnalyticFP),
+ GetClipEdgeType(invert, aa),
+ deviceSpacePath);
+ if (success) {
return ClipResult::kClipped;
}
@@ -673,6 +712,7 @@ void GrReducedClip::makeEmpty() {
fAAClipRectGenID = SK_InvalidGenID;
fWindowRects.reset();
fMaskElements.reset();
+ fShader.reset();
fInitialState = InitialState::kAllOut;
}
@@ -693,7 +733,7 @@ static bool stencil_element(GrRenderTargetContext* rtc,
GrPaint paint;
paint.setCoverageSetOpXPFactory((SkRegion::Op)element->getOp(),
element->isInverseFilled());
- rtc->priv().stencilRect(clip, ss, std::move(paint), aa, viewMatrix,
+ rtc->priv().stencilRect(&clip, ss, std::move(paint), aa, viewMatrix,
element->getDeviceSpaceRect());
return true;
}
@@ -704,7 +744,7 @@ static bool stencil_element(GrRenderTargetContext* rtc,
path.toggleInverseFillType();
}
- return rtc->priv().drawAndStencilPath(clip, ss, (SkRegion::Op)element->getOp(),
+ return rtc->priv().drawAndStencilPath(&clip, ss, (SkRegion::Op)element->getOp(),
element->isInverseFilled(), aa, viewMatrix, path);
}
}
@@ -724,7 +764,7 @@ static void draw_element(GrRenderTargetContext* rtc,
SkDEBUGFAIL("Should never get here with an empty element.");
break;
case SkClipStack::Element::DeviceSpaceType::kRect:
- rtc->drawRect(clip, std::move(paint), aa, viewMatrix, element->getDeviceSpaceRect());
+ rtc->drawRect(&clip, std::move(paint), aa, viewMatrix, element->getDeviceSpaceRect());
break;
default: {
SkPath path;
@@ -733,7 +773,7 @@ static void draw_element(GrRenderTargetContext* rtc,
path.toggleInverseFillType();
}
- rtc->drawPath(clip, std::move(paint), aa, viewMatrix, path, GrStyle::SimpleFill());
+ rtc->drawPath(&clip, std::move(paint), aa, viewMatrix, path, GrStyle::SimpleFill());
break;
}
}
@@ -742,7 +782,7 @@ static void draw_element(GrRenderTargetContext* rtc,
bool GrReducedClip::drawAlphaClipMask(GrRenderTargetContext* rtc) const {
// The texture may be larger than necessary, this rect represents the part of the texture
// we populate with a rasterization of the clip.
- GrFixedClip clip(SkIRect::MakeWH(fScissor.width(), fScissor.height()));
+ GrFixedClip clip(rtc->dimensions(), SkIRect::MakeWH(fScissor.width(), fScissor.height()));
if (!fWindowRects.empty()) {
clip.setWindowRectangles(fWindowRects.makeOffset(-fScissor.left(), -fScissor.top()),
@@ -753,7 +793,15 @@ bool GrReducedClip::drawAlphaClipMask(GrRenderTargetContext* rtc) const {
// clear the part that we care about.
SkPMColor4f initialCoverage =
InitialState::kAllIn == this->initialState() ? SK_PMColor4fWHITE : SK_PMColor4fTRANSPARENT;
- rtc->priv().clear(clip, initialCoverage, GrRenderTargetContext::CanClearFullscreen::kYes);
+ if (clip.hasWindowRectangles()) {
+ GrPaint paint;
+ paint.setColor4f(initialCoverage);
+ paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
+ rtc->drawRect(&clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
+ SkRect::Make(clip.scissorRect()));
+ } else {
+ rtc->priv().clearAtLeast(clip.scissorRect(), initialCoverage);
+ }
// Set the matrix so that rendered clip elements are transformed to mask space from clip space.
SkMatrix translate;
@@ -794,7 +842,7 @@ bool GrReducedClip::drawAlphaClipMask(GrRenderTargetContext* rtc) const {
GrPaint paint;
paint.setCoverageSetOpXPFactory(op, !invert);
- rtc->priv().stencilRect(clip, &kDrawOutsideElement, std::move(paint), GrAA::kNo,
+ rtc->priv().stencilRect(&clip, &kDrawOutsideElement, std::move(paint), GrAA::kNo,
translate, SkRect::Make(fScissor));
} else {
// all the remaining ops can just be directly draw into the accumulation buffer
@@ -842,21 +890,59 @@ bool GrReducedClip::drawStencilClipMask(GrRecordingContext* context,
return true;
}
+static int count_fp_recursive(GrFragmentProcessor* fp) {
+ int count = 0;
+ if (fp != nullptr) {
+ count += 1; // count self
+ for (int index=0; index < fp->numChildProcessors(); ++index) {
+ count += count_fp_recursive(&fp->childProcessor(index)); // count children
+ }
+ }
+ return count;
+}
+
+int GrReducedClip::numAnalyticFPs() const {
+ return fCCPRClipPaths.size() + count_fp_recursive(fAnalyticFP.get());
+}
+
std::unique_ptr<GrFragmentProcessor> GrReducedClip::finishAndDetachAnalyticFPs(
+ GrRecordingContext* context, const SkMatrixProvider& matrixProvider,
GrCoverageCountingPathRenderer* ccpr, uint32_t opsTaskID) {
- // Make sure finishAndDetachAnalyticFPs hasn't been called already.
- SkDEBUGCODE(for (const auto& fp : fAnalyticFPs) { SkASSERT(fp); })
-
- if (!fCCPRClipPaths.empty()) {
- fAnalyticFPs.reserve(fAnalyticFPs.count() + fCCPRClipPaths.count());
- for (const SkPath& ccprClipPath : fCCPRClipPaths) {
- SkASSERT(ccpr);
- SkASSERT(fHasScissor);
- auto fp = ccpr->makeClipProcessor(opsTaskID, ccprClipPath, fScissor, *fCaps);
- fAnalyticFPs.push_back(std::move(fp));
+ // Combine the analytic FP with any CCPR clip processors.
+ std::unique_ptr<GrFragmentProcessor> clipFP = std::move(fAnalyticFP);
+
+ for (const SkPath& ccprClipPath : fCCPRClipPaths) {
+ SkASSERT(ccpr);
+ SkASSERT(fHasScissor);
+ clipFP = ccpr->makeClipProcessor(std::move(clipFP), opsTaskID, ccprClipPath,
+ fScissor, *fCaps);
+ }
+ fCCPRClipPaths.reset();
+
+ // Create the shader.
+ std::unique_ptr<GrFragmentProcessor> shaderFP;
+ if (fShader != nullptr) {
+ static const GrColorInfo kCoverageColorInfo{GrColorType::kUnknown, kPremul_SkAlphaType,
+ nullptr};
+ GrFPArgs args(context, matrixProvider, kNone_SkFilterQuality, &kCoverageColorInfo);
+ shaderFP = as_SB(fShader)->asFragmentProcessor(args);
+ if (shaderFP != nullptr) {
+ shaderFP = GrFragmentProcessor::SwizzleOutput(std::move(shaderFP), GrSwizzle::AAAA());
}
- fCCPRClipPaths.reset();
}
- return GrFragmentProcessor::RunInSeries(fAnalyticFPs.begin(), fAnalyticFPs.count());
+ // Combine the clip and shader FPs using RunInSeries. (RunInSeries will automatically return the
+ // input as-is if we only have one.)
+ SkSTArray<2, std::unique_ptr<GrFragmentProcessor>> seriesFPs;
+ if (clipFP != nullptr) {
+ seriesFPs.push_back(std::move(clipFP));
+ }
+ if (shaderFP != nullptr) {
+ seriesFPs.push_back(std::move(shaderFP));
+ }
+
+ return seriesFPs.empty()
+ ? nullptr
+ : GrFragmentProcessor::RunInSeries(&seriesFPs.front(), seriesFPs.size());
}
+
diff --git a/chromium/third_party/skia/src/gpu/GrReducedClip.h b/chromium/third_party/skia/src/gpu/GrReducedClip.h
index ca95bd09949..bcc45a0702e 100644
--- a/chromium/third_party/skia/src/gpu/GrReducedClip.h
+++ b/chromium/third_party/skia/src/gpu/GrReducedClip.h
@@ -53,6 +53,13 @@ public:
bool hasScissor() const { return fHasScissor; }
/**
+ * Indicates if there is a clip shader, representing the merge of all shader elements of the
+ * original stack.
+ */
+ bool hasShader() const { return SkToBool(fShader); }
+ sk_sp<SkShader> shader() const { SkASSERT(fShader); return fShader; }
+
+ /**
* If nonempty, the clip mask is not valid inside these windows and the caller must clip them
* out using the window rectangles GPU extension.
*/
@@ -85,7 +92,7 @@ public:
bool drawAlphaClipMask(GrRenderTargetContext*) const;
bool drawStencilClipMask(GrRecordingContext*, GrRenderTargetContext*) const;
- int numAnalyticFPs() const { return fAnalyticFPs.count() + fCCPRClipPaths.count(); }
+ int numAnalyticFPs() const;
/**
* Called once the client knows the ID of the opsTask that the clip FPs will operate in. This
@@ -97,6 +104,7 @@ public:
* may cause flushes or otherwise change which opsTask the actual draw is going into.
*/
std::unique_ptr<GrFragmentProcessor> finishAndDetachAnalyticFPs(
+ GrRecordingContext*, const SkMatrixProvider& matrixProvider,
GrCoverageCountingPathRenderer*, uint32_t opsTaskID);
private:
@@ -144,8 +152,11 @@ private:
ElementList fMaskElements;
uint32_t fMaskGenID;
bool fMaskRequiresAA;
- SkSTArray<4, std::unique_ptr<GrFragmentProcessor>> fAnalyticFPs;
+ std::unique_ptr<GrFragmentProcessor> fAnalyticFP;
SkSTArray<4, SkPath> fCCPRClipPaths; // Will convert to FPs once we have an opsTask ID for CCPR.
+ // Will be the combination of all kShader elements or null if there's no clip shader.
+ // Does not count against the analytic FP limit.
+ sk_sp<SkShader> fShader;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrRenderTargetContext.cpp b/chromium/third_party/skia/src/gpu/GrRenderTargetContext.cpp
index 7a53e76afb4..b4617c8ba3d 100644
--- a/chromium/third_party/skia/src/gpu/GrRenderTargetContext.cpp
+++ b/chromium/third_party/skia/src/gpu/GrRenderTargetContext.cpp
@@ -20,6 +20,7 @@
#include "src/core/SkGlyphRunPainter.h"
#include "src/core/SkLatticeIter.h"
#include "src/core/SkMatrixPriv.h"
+#include "src/core/SkMatrixProvider.h"
#include "src/core/SkRRectPriv.h"
#include "src/core/SkSurfacePriv.h"
#include "src/core/SkYUVMath.h"
@@ -28,11 +29,11 @@
#include "src/gpu/GrBlurUtils.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrClientMappedBufferManager.h"
+#include "src/gpu/GrClip.h"
#include "src/gpu/GrColor.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrDataUtils.h"
#include "src/gpu/GrDrawingManager.h"
-#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrGpuResourcePriv.h"
#include "src/gpu/GrImageContextPriv.h"
#include "src/gpu/GrImageInfo.h"
@@ -55,7 +56,6 @@
#include "src/gpu/geometry/GrStyledShape.h"
#include "src/gpu/ops/GrAtlasTextOp.h"
#include "src/gpu/ops/GrClearOp.h"
-#include "src/gpu/ops/GrClearStencilClipOp.h"
#include "src/gpu/ops/GrDrawAtlasOp.h"
#include "src/gpu/ops/GrDrawOp.h"
#include "src/gpu/ops/GrDrawVerticesOp.h"
@@ -70,7 +70,8 @@
#include "src/gpu/ops/GrStencilPathOp.h"
#include "src/gpu/ops/GrStrokeRectOp.h"
#include "src/gpu/ops/GrTextureOp.h"
-#include "src/gpu/text/GrTextContext.h"
+#include "src/gpu/text/GrSDFTOptions.h"
+#include "src/gpu/text/GrTextBlobCache.h"
#include "src/gpu/text/GrTextTarget.h"
class GrRenderTargetContext::TextTarget : public GrTextTarget {
@@ -78,14 +79,13 @@ public:
TextTarget(GrRenderTargetContext* renderTargetContext)
: GrTextTarget(renderTargetContext->width(), renderTargetContext->height(),
renderTargetContext->colorInfo())
- , fRenderTargetContext(renderTargetContext)
- , fGlyphPainter{*renderTargetContext} {}
+ , fRenderTargetContext(renderTargetContext) {}
- void addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) override {
+ void addDrawOp(const GrClip* clip, std::unique_ptr<GrAtlasTextOp> op) override {
fRenderTargetContext->addDrawOp(clip, std::move(op));
}
- void drawShape(const GrClip& clip,
+ void drawShape(const GrClip* clip,
const SkPaint& paint,
const SkMatrixProvider& matrixProvider,
const GrStyledShape& shape) override {
@@ -112,20 +112,16 @@ public:
}
SkGlyphRunListPainter* glyphPainter() override {
- return &fGlyphPainter;
+ return fRenderTargetContext->glyphPainter();
}
private:
GrRenderTargetContext* fRenderTargetContext;
- SkGlyphRunListPainter fGlyphPainter;
-
};
#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
-#define ASSERT_SINGLE_OWNER \
- SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
-#define ASSERT_SINGLE_OWNER_PRIV \
- SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());)
+#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(this->singleOwner())
+#define ASSERT_SINGLE_OWNER_PRIV GR_ASSERT_SINGLE_OWNER(fRenderTargetContext->singleOwner())
#define RETURN_IF_ABANDONED if (fContext->priv().abandoned()) { return; }
#define RETURN_IF_ABANDONED_PRIV if (fRenderTargetContext->fContext->priv().abandoned()) { return; }
#define RETURN_FALSE_IF_ABANDONED if (fContext->priv().abandoned()) { return false; }
@@ -296,12 +292,11 @@ std::unique_ptr<GrRenderTargetContext> GrRenderTargetContext::MakeFromBackendTex
int sampleCnt,
GrSurfaceOrigin origin,
const SkSurfaceProps* surfaceProps,
- ReleaseProc releaseProc,
- ReleaseContext releaseCtx) {
+ sk_sp<GrRefCntedCallback> releaseHelper) {
SkASSERT(sampleCnt > 0);
sk_sp<GrTextureProxy> proxy(context->priv().proxyProvider()->wrapRenderableBackendTexture(
- tex, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, releaseProc,
- releaseCtx));
+ tex, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
+ std::move(releaseHelper)));
if (!proxy) {
return nullptr;
}
@@ -338,8 +333,13 @@ std::unique_ptr<GrRenderTargetContext> GrRenderTargetContext::MakeFromBackendRen
const SkSurfaceProps* surfaceProps,
ReleaseProc releaseProc,
ReleaseContext releaseCtx) {
+ sk_sp<GrRefCntedCallback> releaseHelper;
+ if (releaseProc) {
+ releaseHelper.reset(new GrRefCntedCallback(releaseProc, releaseCtx));
+ }
+
sk_sp<GrSurfaceProxy> proxy(
- context->priv().proxyProvider()->wrapBackendRenderTarget(rt, releaseProc, releaseCtx));
+ context->priv().proxyProvider()->wrapBackendRenderTarget(rt, std::move(releaseHelper)));
if (!proxy) {
return nullptr;
}
@@ -379,9 +379,10 @@ GrRenderTargetContext::GrRenderTargetContext(GrRecordingContext* context,
: GrSurfaceContext(context, std::move(readView), colorType, kPremul_SkAlphaType,
std::move(colorSpace))
, fWriteView(std::move(writeView))
- , fOpsTask(sk_ref_sp(this->asSurfaceProxy()->getLastOpsTask()))
, fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
- , fManagedOpsTask(managedOpsTask) {
+ , fManagedOpsTask(managedOpsTask)
+ , fGlyphPainter(*this) {
+ fOpsTask = sk_ref_sp(context->priv().drawingManager()->getLastOpsTask(this->asSurfaceProxy()));
if (fOpsTask) {
fOpsTask->addClosedObserver(this);
}
@@ -395,7 +396,7 @@ GrRenderTargetContext::GrRenderTargetContext(GrRecordingContext* context,
#ifdef SK_DEBUG
void GrRenderTargetContext::onValidate() const {
if (fOpsTask && !fOpsTask->isClosed()) {
- SkASSERT(fWriteView.proxy()->getLastRenderTask() == fOpsTask.get());
+ SkASSERT(this->drawingManager()->getLastRenderTask(fWriteView.proxy()) == fOpsTask.get());
}
}
#endif
@@ -448,9 +449,34 @@ GrOpsTask* GrRenderTargetContext::getOpsTask() {
return fOpsTask.get();
}
-void GrRenderTargetContext::drawGlyphRunList(const GrClip& clip,
+static SkColor compute_canonical_color(const SkPaint& paint, bool lcd) {
+ SkColor canonicalColor = SkPaintPriv::ComputeLuminanceColor(paint);
+ if (lcd) {
+ // This is the correct computation for canonicalColor, but there are tons of cases where LCD
+ // can be modified. For now we just regenerate if any run in a textblob has LCD.
+ // TODO figure out where all of these modifications are and see if we can incorporate that
+ // logic at a higher level *OR* use sRGB
+ //canonicalColor = SkMaskGamma::CanonicalColor(canonicalColor);
+
+ // TODO we want to figure out a way to be able to use the canonical color on LCD text,
+ // see the note above. We pick a dummy value for LCD text to ensure we always match the
+ // same key
+ return SK_ColorTRANSPARENT;
+ } else {
+ // A8, though can have mixed BMP text but it shouldn't matter because BMP text won't have
+ // gamma corrected masks anyways, nor color
+ U8CPU lum = SkComputeLuminance(SkColorGetR(canonicalColor),
+ SkColorGetG(canonicalColor),
+ SkColorGetB(canonicalColor));
+ // reduce to our finite number of bits
+ canonicalColor = SkMaskGamma::CanonicalColor(SkColorSetRGB(lum, lum, lum));
+ }
+ return canonicalColor;
+}
+
+void GrRenderTargetContext::drawGlyphRunList(const GrClip* clip,
const SkMatrixProvider& matrixProvider,
- const SkGlyphRunList& blob) {
+ const SkGlyphRunList& glyphRunList) {
ASSERT_SINGLE_OWNER
RETURN_IF_ABANDONED
SkDEBUGCODE(this->validate();)
@@ -463,46 +489,83 @@ void GrRenderTargetContext::drawGlyphRunList(const GrClip& clip,
return;
}
- GrTextContext* atlasTextContext = this->drawingManager()->getTextContext();
- atlasTextContext->drawGlyphRunList(fContext, fTextTarget.get(), clip, matrixProvider,
- fSurfaceProps, blob);
-}
+ GrSDFTOptions options = fContext->priv().SDFTOptions();
+ GrTextBlobCache* textBlobCache = fContext->priv().getTextBlobCache();
-void GrRenderTargetContext::discard() {
- ASSERT_SINGLE_OWNER
- RETURN_IF_ABANDONED
- SkDEBUGCODE(this->validate();)
- GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "discard", fContext);
+ // Get the first paint to use as the key paint.
+ const SkPaint& blobPaint = glyphRunList.paint();
- AutoCheckFlush acf(this->drawingManager());
+ SkPoint drawOrigin = glyphRunList.origin();
- this->getOpsTask()->discard();
+ SkMaskFilterBase::BlurRec blurRec;
+ // It might be worth caching these things, but its not clear at this time
+ // TODO for animated mask filters, this will fill up our cache. We need a safeguard here
+ const SkMaskFilter* mf = blobPaint.getMaskFilter();
+ bool canCache = glyphRunList.canCache() &&
+ !(blobPaint.getPathEffect() || (mf && !as_MFB(mf)->asABlur(&blurRec)));
+
+ // If we're doing linear blending, then we can disable the gamma hacks.
+ // Otherwise, leave them on. In either case, we still want the contrast boost:
+ // TODO: Can we be even smarter about mask gamma based on the dest transfer function?
+ SkScalerContextFlags scalerContextFlags = this->colorInfo().isLinearlyBlended()
+ ? SkScalerContextFlags::kBoostContrast
+ : SkScalerContextFlags::kFakeGammaAndBoostContrast;
+
+ sk_sp<GrTextBlob> blob;
+ GrTextBlob::Key key;
+ if (canCache) {
+ bool hasLCD = glyphRunList.anyRunsLCD();
+
+ // We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry
+ SkPixelGeometry pixelGeometry =
+ hasLCD ? fSurfaceProps.pixelGeometry() : kUnknown_SkPixelGeometry;
+
+ GrColor canonicalColor = compute_canonical_color(blobPaint, hasLCD);
+
+ key.fPixelGeometry = pixelGeometry;
+ key.fUniqueID = glyphRunList.uniqueID();
+ key.fStyle = blobPaint.getStyle();
+ key.fHasBlur = SkToBool(mf);
+ key.fCanonicalColor = canonicalColor;
+ key.fScalerContextFlags = scalerContextFlags;
+ blob = textBlobCache->find(key);
+ }
+
+ const SkMatrix& drawMatrix(matrixProvider.localToDevice());
+ if (blob != nullptr && blob->canReuse(blobPaint, blurRec, drawMatrix, drawOrigin)) {
+ // Reusing the blob. Move it to the front of LRU cache.
+ textBlobCache->makeMRU(blob.get());
+ } else {
+ // Build or Rebuild the GrTextBlob
+ if (blob != nullptr) {
+ // We have to remake the blob because changes may invalidate our masks.
+ // TODO we could probably get away with reuse most of the time if the pointer is unique,
+ // but we'd have to clear the SubRun information
+ textBlobCache->remove(blob.get());
+ }
+ if (canCache) {
+ blob = textBlobCache->makeCachedBlob(glyphRunList, key, blurRec, drawMatrix);
+ } else {
+ blob = GrTextBlob::Make(glyphRunList, drawMatrix);
+ }
+ bool supportsSDFT = fContext->priv().caps()->shaderCaps()->supportsDistanceFieldText();
+ fGlyphPainter.processGlyphRunList(
+ glyphRunList, drawMatrix, fSurfaceProps, supportsSDFT, options, blob.get());
+ }
+
+ blob->insertOpsIntoTarget(
+ fTextTarget.get(), fSurfaceProps, blobPaint, clip, matrixProvider, drawOrigin);
}
-void GrRenderTargetContext::clear(const SkIRect* rect,
- const SkPMColor4f& color,
- CanClearFullscreen canClearFullscreen) {
+void GrRenderTargetContext::discard() {
ASSERT_SINGLE_OWNER
RETURN_IF_ABANDONED
SkDEBUGCODE(this->validate();)
- GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "clear", fContext);
+ GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "discard", fContext);
AutoCheckFlush acf(this->drawingManager());
- this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color,
- canClearFullscreen);
-}
-void GrRenderTargetContextPriv::clear(const GrFixedClip& clip,
- const SkPMColor4f& color,
- CanClearFullscreen canClearFullscreen) {
- ASSERT_SINGLE_OWNER_PRIV
- RETURN_IF_ABANDONED_PRIV
- SkDEBUGCODE(fRenderTargetContext->validate();)
- GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clear",
- fRenderTargetContext->fContext);
-
- AutoCheckFlush acf(fRenderTargetContext->drawingManager());
- fRenderTargetContext->internalClear(clip, color, canClearFullscreen);
+ this->getOpsTask()->discard();
}
static void clear_to_grpaint(const SkPMColor4f& color, GrPaint* paint) {
@@ -517,21 +580,46 @@ static void clear_to_grpaint(const SkPMColor4f& color, GrPaint* paint) {
}
}
-void GrRenderTargetContext::internalClear(const GrFixedClip& clip,
+// NOTE: We currently pass the premul color unmodified to the gpu, since we assume the GrRTC has a
+// premul alpha type. If we ever support different alpha type render targets, this function should
+// transform the color as appropriate.
+void GrRenderTargetContext::internalClear(const SkIRect* scissor,
const SkPMColor4f& color,
- CanClearFullscreen canClearFullscreen) {
- bool isFull = false;
- if (!clip.hasWindowRectangles()) {
- // TODO: wrt the shouldInitializeTextures path, it would be more performant to
- // only clear the entire target if we knew it had not been cleared before. As
- // is this could end up doing a lot of redundant clears.
- isFull = !clip.scissorEnabled() ||
- (CanClearFullscreen::kYes == canClearFullscreen &&
- (this->caps()->preferFullscreenClears() || this->caps()->shouldInitializeTextures())) ||
- clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
- }
-
- if (isFull) {
+ bool upgradePartialToFull) {
+ ASSERT_SINGLE_OWNER
+ RETURN_IF_ABANDONED
+ SkDEBUGCODE(this->validate();)
+ GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "clear", fContext);
+
+ // There are three ways clears are handled: load ops, native clears, and draws. Load ops are
+ // only for fullscreen clears; native clears can be fullscreen or with scissors if the backend
+ // supports then. Drawing an axis-aligned rect is the fallback path.
+ GrScissorState scissorState(this->asSurfaceProxy()->backingStoreDimensions());
+ if (scissor && !scissorState.set(*scissor)) {
+ // The clear is offscreen, so skip it (normally this would be handled by addDrawOp,
+ // except clear ops are not draw ops).
+ return;
+ }
+
+ // If we have a scissor but it's okay to clear beyond it for performance reasons, then disable
+ // the test. We only do this when the clear would be handled by a load op or natively.
+ if (scissorState.enabled() && !this->caps()->performColorClearsAsDraws()) {
+ if (upgradePartialToFull && (this->caps()->preferFullscreenClears() ||
+ this->caps()->shouldInitializeTextures())) {
+ // TODO: wrt the shouldInitializeTextures path, it would be more performant to
+ // only clear the entire target if we knew it had not been cleared before. As
+ // is this could end up doing a lot of redundant clears.
+ scissorState.setDisabled();
+ } else {
+ // Unlike with stencil clears, we also allow clears up to the logical dimensions of the
+ // render target to overflow into any approx-fit padding of the backing store dimensions
+ scissorState.relaxTest(this->dimensions());
+ }
+ }
+
+ if (!scissorState.enabled()) {
+ // This is a fullscreen clear, so could be handled as a load op. Regardless, we can also
+ // discard all prior ops in the current task since the color buffer will be overwritten.
GrOpsTask* opsTask = this->getOpsTask();
if (opsTask->resetForFullscreenClear(this->canDiscardPreviousOpsOnFullClear()) &&
!this->caps()->performColorClearsAsDraws()) {
@@ -543,43 +631,24 @@ void GrRenderTargetContext::internalClear(const GrFixedClip& clip,
// blow away the color buffer contents
opsTask->setColorLoadOp(GrLoadOp::kDiscard);
}
+ }
- // Must add an op to the list (either because we couldn't use a load op, or because the
- // clear load op isn't supported)
- if (this->caps()->performColorClearsAsDraws()) {
- SkRect rtRect = SkRect::MakeWH(this->width(), this->height());
- GrPaint paint;
- clear_to_grpaint(color, &paint);
- this->addDrawOp(GrFixedClip::Disabled(),
- GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
- rtRect));
- } else {
- this->addOp(GrClearOp::Make(
- fContext, SkIRect::MakeEmpty(), color, /* fullscreen */ true));
- }
+ // At this point we are either a partial clear or a fullscreen clear that couldn't be applied
+ // as a load op.
+ bool clearAsDraw = this->caps()->performColorClearsAsDraws() ||
+ (scissorState.enabled() && this->caps()->performPartialClearsAsDraws());
+ if (clearAsDraw) {
+ GrPaint paint;
+ clear_to_grpaint(color, &paint);
+ this->addDrawOp(nullptr,
+ GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
+ SkRect::Make(scissorState.rect())));
} else {
- if (this->caps()->performPartialClearsAsDraws()) {
- // performPartialClearsAsDraws() also returns true if any clear has to be a draw.
- GrPaint paint;
- clear_to_grpaint(color, &paint);
-
- this->addDrawOp(clip,
- GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
- SkRect::Make(clip.scissorRect())));
- } else {
- std::unique_ptr<GrOp> op(GrClearOp::Make(fContext, clip, color,
- this->asSurfaceProxy()));
- // This version of the clear op factory can return null if the clip doesn't intersect
- // with the surface proxy's boundary
- if (!op) {
- return;
- }
- this->addOp(std::move(op));
- }
+ this->addOp(GrClearOp::MakeColor(fContext, scissorState, color));
}
}
-void GrRenderTargetContext::drawPaint(const GrClip& clip,
+void GrRenderTargetContext::drawPaint(const GrClip* clip,
GrPaint&& paint,
const SkMatrix& viewMatrix) {
// Start with the render target, since that is the maximum content we could possibly fill.
@@ -630,8 +699,12 @@ static bool make_vertex_finite(float* value) {
return true;
}
+static SkIRect get_clip_bounds(const GrRenderTargetContext* rtc, const GrClip* clip) {
+ return clip ? clip->getConservativeBounds() : SkIRect::MakeWH(rtc->width(), rtc->height());
+}
+
GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimization(
- const GrClip& clip, const SkPMColor4f* constColor,
+ const GrClip* clip, const SkPMColor4f* constColor,
const GrUserStencilSettings* stencilSettings, GrAA* aa, DrawQuad* quad) {
// Optimization requirements:
// 1. kDiscard applies when clip bounds and quad bounds do not intersect
@@ -645,16 +718,9 @@ GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimi
// better to just keep the old flags instead of introducing mixed edge flags.
GrQuadAAFlags oldFlags = quad->fEdgeFlags;
- SkRect rtRect;
- if (stencilSettings) {
- // Must use size at which the rendertarget will ultimately be allocated so that stencil
- // buffer updates on approximately sized render targets don't get corrupted.
- rtRect = this->asSurfaceProxy()->backingStoreBoundsRect();
- } else {
- // Use the logical size of the render target, which allows for "fullscreen" clears even if
- // the render target has an approximate backing fit
- rtRect = SkRect::MakeWH(this->width(), this->height());
- }
+ // Use the logical size of the render target, which allows for "fullscreen" clears even if
+ // the render target has an approximate backing fit
+ SkRect rtRect = this->asSurfaceProxy()->getBoundsRect();
SkRect drawBounds = quad->fDevice.bounds();
if (constColor) {
@@ -692,8 +758,8 @@ GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimi
// regular draws so that if we fully cover the render target, that can stop being anti-aliased.
GrAA clipAA = stencilSettings ? *aa : GrAA::kNo;
bool axisAlignedClip = true;
- if (!clip.quickContains(rtRect)) {
- if (!clip.isRRect(rtRect, &clipRRect, &clipAA)) {
+ if (clip && !clip->quickContains(rtRect)) {
+ if (!clip->isRRect(&clipRRect, &clipAA)) {
axisAlignedClip = false;
}
}
@@ -717,14 +783,14 @@ GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimi
drawBounds = quad->fDevice.bounds();
if (drawBounds.contains(rtRect)) {
// Fullscreen clear
- this->clear(nullptr, *constColor, CanClearFullscreen::kYes);
+ this->clear(*constColor);
return QuadOptimization::kSubmitted;
} else if (GrClip::IsPixelAligned(drawBounds) &&
drawBounds.width() > 256 && drawBounds.height() > 256) {
// Scissor + clear (round shouldn't do anything since we are pixel aligned)
SkIRect scissorRect;
drawBounds.round(&scissorRect);
- this->clear(&scissorRect, *constColor, CanClearFullscreen::kNo);
+ this->clear(scissorRect, *constColor);
return QuadOptimization::kSubmitted;
}
}
@@ -759,7 +825,7 @@ GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimi
// we can draw the rrect directly and ignore the edge flags
GrPaint paint;
clear_to_grpaint(*constColor, &paint);
- this->drawRRect(GrFixedClip::Disabled(), std::move(paint), clipAA, SkMatrix::I(),
+ this->drawRRect(nullptr, std::move(paint), clipAA, SkMatrix::I(),
clipRRect, GrStyle::SimpleFill());
return QuadOptimization::kSubmitted;
} else {
@@ -771,7 +837,7 @@ GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimi
}
// Crop the quad to the conservative bounds of the clip.
- SkRect clipBounds = SkRect::Make(clip.getConservativeBounds(rtRect.width(), rtRect.height()));
+ SkRect clipBounds = SkRect::Make(get_clip_bounds(this, clip));
// One final check for discarding, since we may have gone here directly due to a complex clip
if (!clipBounds.intersects(drawBounds)) {
@@ -786,7 +852,7 @@ GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimi
return QuadOptimization::kCropped;
}
-void GrRenderTargetContext::drawFilledQuad(const GrClip& clip,
+void GrRenderTargetContext::drawFilledQuad(const GrClip* clip,
GrPaint&& paint,
GrAA aa,
DrawQuad* quad,
@@ -809,8 +875,7 @@ void GrRenderTargetContext::drawFilledQuad(const GrClip& clip,
QuadOptimization opt = this->attemptQuadOptimization(clip, constColor, ss, &aa, quad);
if (opt >= QuadOptimization::kClipApplied) {
// These optimizations require caller to add an op themselves
- const GrClip& finalClip = opt == QuadOptimization::kClipApplied ? GrFixedClip::Disabled()
- : clip;
+ const GrClip* finalClip = opt == QuadOptimization::kClipApplied ? nullptr : clip;
GrAAType aaType = ss ? (aa == GrAA::kYes ? GrAAType::kMSAA : GrAAType::kNone)
: this->chooseAAType(aa);
this->addDrawOp(finalClip, GrFillRectOp::Make(fContext, std::move(paint), aaType,
@@ -819,7 +884,7 @@ void GrRenderTargetContext::drawFilledQuad(const GrClip& clip,
// All other optimization levels were completely handled inside attempt(), so no extra op needed
}
-void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip,
+void GrRenderTargetContext::drawTexturedQuad(const GrClip* clip,
GrSurfaceProxyView proxyView,
SkAlphaType srcAlphaType,
sk_sp<GrColorSpaceXform> textureXform,
@@ -844,8 +909,7 @@ void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip,
SkASSERT(opt != QuadOptimization::kSubmitted);
if (opt != QuadOptimization::kDiscarded) {
// And the texture op if not discarded
- const GrClip& finalClip = opt == QuadOptimization::kClipApplied ? GrFixedClip::Disabled()
- : clip;
+ const GrClip* finalClip = opt == QuadOptimization::kClipApplied ? nullptr : clip;
GrAAType aaType = this->chooseAAType(aa);
auto clampType = GrColorTypeClampType(this->colorInfo().colorType());
auto saturate = clampType == GrClampType::kManual ? GrTextureOp::Saturate::kYes
@@ -859,7 +923,7 @@ void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip,
}
}
-void GrRenderTargetContext::drawRect(const GrClip& clip,
+void GrRenderTargetContext::drawRect(const GrClip* clip,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
@@ -904,7 +968,7 @@ void GrRenderTargetContext::drawRect(const GrClip& clip,
GrStyledShape(rect, *style));
}
-void GrRenderTargetContext::drawQuadSet(const GrClip& clip, GrPaint&& paint, GrAA aa,
+void GrRenderTargetContext::drawQuadSet(const GrClip* clip, GrPaint&& paint, GrAA aa,
const SkMatrix& viewMatrix, const QuadSetEntry quads[],
int cnt) {
GrAAType aaType = this->chooseAAType(aa);
@@ -956,7 +1020,7 @@ void GrRenderTargetContext::setNeedsStencil(bool useMixedSamplesIfNotMSAA) {
if (this->caps()->performStencilClearsAsDraws()) {
// There is a driver bug with clearing stencil. We must use an op to manually clear the
// stencil buffer before the op that required 'setNeedsStencil'.
- this->internalStencilClear(GrFixedClip::Disabled(), /* inside mask */ false);
+ this->internalStencilClear(nullptr, /* inside mask */ false);
} else {
this->getOpsTask()->setInitialStencilContent(
GrOpsTask::StencilContent::kUserBitsCleared);
@@ -964,41 +1028,32 @@ void GrRenderTargetContext::setNeedsStencil(bool useMixedSamplesIfNotMSAA) {
}
}
-void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
- ASSERT_SINGLE_OWNER_PRIV
- RETURN_IF_ABANDONED_PRIV
- SkDEBUGCODE(fRenderTargetContext->validate();)
- GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clearStencilClip",
- fRenderTargetContext->fContext);
-
- AutoCheckFlush acf(fRenderTargetContext->drawingManager());
-
- fRenderTargetContext->internalStencilClear(clip, insideStencilMask);
-}
-
-void GrRenderTargetContext::internalStencilClear(const GrFixedClip& clip, bool insideStencilMask) {
+void GrRenderTargetContext::internalStencilClear(const SkIRect* scissor, bool insideStencilMask) {
this->setNeedsStencil(/* useMixedSamplesIfNotMSAA = */ false);
- if (this->caps()->performStencilClearsAsDraws()) {
+ GrScissorState scissorState(this->asSurfaceProxy()->backingStoreDimensions());
+ if (scissor && !scissorState.set(*scissor)) {
+ // The requested clear region is off screen, so nothing to do.
+ return;
+ }
+
+ bool clearWithDraw = this->caps()->performStencilClearsAsDraws() ||
+ (scissorState.enabled() && this->caps()->performPartialClearsAsDraws());
+ if (clearWithDraw) {
const GrUserStencilSettings* ss = GrStencilSettings::SetClipBitSettings(insideStencilMask);
- SkRect rtRect = SkRect::MakeWH(this->width(), this->height());
// Configure the paint to have no impact on the color buffer
GrPaint paint;
paint.setXPFactory(GrDisableColorXPFactory::Get());
- this->addDrawOp(clip, GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
- rtRect, ss));
+ this->addDrawOp(nullptr,
+ GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
+ SkRect::Make(scissorState.rect()), ss));
} else {
- std::unique_ptr<GrOp> op(GrClearStencilClipOp::Make(fContext, clip, insideStencilMask,
- this->asRenderTargetProxy()));
- if (!op) {
- return;
- }
- this->addOp(std::move(op));
+ this->addOp(GrClearOp::MakeStencilClip(fContext, scissorState, insideStencilMask));
}
}
-void GrRenderTargetContextPriv::stencilPath(const GrHardClip& clip,
+void GrRenderTargetContextPriv::stencilPath(const GrHardClip* clip,
GrAA doStencilMSAA,
const SkMatrix& viewMatrix,
sk_sp<const GrPath> path) {
@@ -1016,12 +1071,18 @@ void GrRenderTargetContextPriv::stencilPath(const GrHardClip& clip,
// https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
- // Setup clip
- GrAppliedHardClip appliedClip;
- if (!clip.apply(fRenderTargetContext->width(), fRenderTargetContext->height(), &appliedClip,
- &bounds)) {
+ // Setup clip and reject offscreen paths; we do this explicitly instead of relying on addDrawOp
+ // because GrStencilPathOp is not a draw op as its state depends directly on the choices made
+ // during this clip application.
+ GrAppliedHardClip appliedClip(fRenderTargetContext->dimensions(),
+ fRenderTargetContext->asSurfaceProxy()->backingStoreDimensions());
+
+ if (clip && !clip->apply(&appliedClip, &bounds)) {
return;
}
+ // else see FIXME above; we'd normally want to check path bounds with render target bounds,
+ // but as it is, we're just using the full render target so intersecting the two bounds would
+ // do nothing.
std::unique_ptr<GrOp> op = GrStencilPathOp::Make(fRenderTargetContext->fContext,
viewMatrix,
@@ -1038,7 +1099,7 @@ void GrRenderTargetContextPriv::stencilPath(const GrHardClip& clip,
fRenderTargetContext->addOp(std::move(op));
}
-void GrRenderTargetContext::drawTextureSet(const GrClip& clip, TextureSetEntry set[],
+void GrRenderTargetContext::drawTextureSet(const GrClip* clip, TextureSetEntry set[],
int cnt, int proxyRunCnt,
GrSamplerState::Filter filter, SkBlendMode mode,
GrAA aa, SkCanvas::SrcRectConstraint constraint,
@@ -1060,7 +1121,7 @@ void GrRenderTargetContext::drawTextureSet(const GrClip& clip, TextureSetEntry s
mode, aaType, constraint, viewMatrix, std::move(texXform));
}
-void GrRenderTargetContext::drawVertices(const GrClip& clip,
+void GrRenderTargetContext::drawVertices(const GrClip* clip,
GrPaint&& paint,
const SkMatrixProvider& matrixProvider,
sk_sp<SkVertices> vertices,
@@ -1084,7 +1145,7 @@ void GrRenderTargetContext::drawVertices(const GrClip& clip,
///////////////////////////////////////////////////////////////////////////////
-void GrRenderTargetContext::drawAtlas(const GrClip& clip,
+void GrRenderTargetContext::drawAtlas(const GrClip* clip,
GrPaint&& paint,
const SkMatrix& viewMatrix,
int spriteCount,
@@ -1106,7 +1167,7 @@ void GrRenderTargetContext::drawAtlas(const GrClip& clip,
///////////////////////////////////////////////////////////////////////////////
-void GrRenderTargetContext::drawRRect(const GrClip& origClip,
+void GrRenderTargetContext::drawRRect(const GrClip* origClip,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
@@ -1122,8 +1183,7 @@ void GrRenderTargetContext::drawRRect(const GrClip& origClip,
return;
}
- GrNoClip noclip;
- const GrClip* clip = &origClip;
+ const GrClip* clip = origClip;
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
// The Android framework frequently clips rrects to themselves where the clip is non-aa and the
// draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it
@@ -1132,9 +1192,9 @@ void GrRenderTargetContext::drawRRect(const GrClip& origClip,
// can be ignored. We'd prefer to fix this in the framework by removing the clips calls. This
// only works for filled rrects since the stroke width outsets beyond the rrect itself.
SkRRect devRRect;
- if (stroke.getStyle() == SkStrokeRec::kFill_Style && rrect.transform(viewMatrix, &devRRect) &&
- clip->quickContains(devRRect)) {
- clip = &noclip;
+ if (clip && stroke.getStyle() == SkStrokeRec::kFill_Style &&
+ rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
+ clip = nullptr;
}
#endif
SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
@@ -1163,12 +1223,12 @@ void GrRenderTargetContext::drawRRect(const GrClip& origClip,
fContext, std::move(paint), viewMatrix, rrect, stroke, this->caps()->shaderCaps());
}
if (op) {
- this->addDrawOp(*clip, std::move(op));
+ this->addDrawOp(clip, std::move(op));
return;
}
assert_alive(paint);
- this->drawShapeUsingPathRenderer(*clip, std::move(paint), aa, viewMatrix,
+ this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix,
GrStyledShape(rrect, style));
}
@@ -1181,7 +1241,7 @@ static SkPoint3 map(const SkMatrix& m, const SkPoint3& pt) {
return result;
}
-bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
+bool GrRenderTargetContext::drawFastShadow(const GrClip* clip,
const SkMatrix& viewMatrix,
const SkPath& path,
const SkDrawShadowRec& rec) {
@@ -1376,7 +1436,7 @@ bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
///////////////////////////////////////////////////////////////////////////////
-bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
+bool GrRenderTargetContext::drawFilledDRRect(const GrClip* clip,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
@@ -1442,18 +1502,17 @@ bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
const auto& caps = *this->caps()->shaderCaps();
// TODO these need to be a geometry processors
- auto innerEffect = GrRRectEffect::Make(innerEdgeType, *inner, caps);
- if (!innerEffect) {
+ auto [success, fp] = GrRRectEffect::Make(/*inputFP=*/nullptr, innerEdgeType, *inner, caps);
+ if (!success) {
return false;
}
- auto outerEffect = GrRRectEffect::Make(outerEdgeType, *outer, caps);
- if (!outerEffect) {
+ std::tie(success, fp) = GrRRectEffect::Make(std::move(fp), outerEdgeType, *outer, caps);
+ if (!success) {
return false;
}
- paint.addCoverageFragmentProcessor(std::move(innerEffect));
- paint.addCoverageFragmentProcessor(std::move(outerEffect));
+ paint.addCoverageFragmentProcessor(std::move(fp));
SkRect bounds = outer->getBounds();
if (GrAAType::kCoverage == aaType) {
@@ -1465,7 +1524,7 @@ bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
return true;
}
-void GrRenderTargetContext::drawDRRect(const GrClip& clip,
+void GrRenderTargetContext::drawDRRect(const GrClip* clip,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
@@ -1496,7 +1555,7 @@ void GrRenderTargetContext::drawDRRect(const GrClip& clip,
///////////////////////////////////////////////////////////////////////////////
-void GrRenderTargetContext::drawRegion(const GrClip& clip,
+void GrRenderTargetContext::drawRegion(const GrClip* clip,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
@@ -1532,7 +1591,7 @@ void GrRenderTargetContext::drawRegion(const GrClip& clip,
this->addDrawOp(clip, std::move(op));
}
-void GrRenderTargetContext::drawOval(const GrClip& clip,
+void GrRenderTargetContext::drawOval(const GrClip* clip,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
@@ -1593,7 +1652,7 @@ void GrRenderTargetContext::drawOval(const GrClip& clip,
GrStyledShape(SkRRect::MakeOval(oval), SkPathDirection::kCW, 2, false, style));
}
-void GrRenderTargetContext::drawArc(const GrClip& clip,
+void GrRenderTargetContext::drawArc(const GrClip* clip,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
@@ -1632,7 +1691,7 @@ void GrRenderTargetContext::drawArc(const GrClip& clip,
GrStyledShape::MakeArc(oval, startAngle, sweepAngle, useCenter, style));
}
-void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
+void GrRenderTargetContext::drawImageLattice(const GrClip* clip,
GrPaint&& paint,
const SkMatrix& viewMatrix,
GrSurfaceProxyView view,
@@ -1711,7 +1770,8 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels(
int x = srcRect.fLeft;
int y = srcRect.fTop;
if (needsRescale) {
- tempRTC = this->rescale(info, srcRect, rescaleGamma, rescaleQuality);
+ tempRTC = this->rescale(info, kTopLeft_GrSurfaceOrigin, srcRect, rescaleGamma,
+ rescaleQuality);
if (!tempRTC) {
callback(context, nullptr);
return;
@@ -1754,7 +1814,7 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels(
callback(context, nullptr);
return;
}
- tempRTC->drawTexture(GrNoClip(), std::move(texProxyView), this->colorInfo().alphaType(),
+ tempRTC->drawTexture(nullptr, std::move(texProxyView), this->colorInfo().alphaType(),
GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
SK_PMColor4fWHITE, srcRectToDraw,
SkRect::MakeWH(srcRect.width(), srcRect.height()), GrAA::kNo,
@@ -1899,7 +1959,7 @@ void GrRenderTargetContext::asyncReadPixels(const SkIRect& rect, SkColorType col
GrFlushInfo flushInfo;
flushInfo.fFinishedContext = finishContext;
flushInfo.fFinishedProc = finishCallback;
- this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
+ this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo, nullptr);
}
void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
@@ -1941,7 +2001,8 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC
auto info = SkImageInfo::Make(dstSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType,
dstColorSpace);
// TODO: Incorporate the YUV conversion into last pass of rescaling.
- auto tempRTC = this->rescale(info, srcRect, rescaleGamma, rescaleQuality);
+ auto tempRTC = this->rescale(info, kTopLeft_GrSurfaceOrigin, srcRect, rescaleGamma,
+ rescaleQuality);
if (!tempRTC) {
callback(context, nullptr);
return;
@@ -1976,7 +2037,7 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC
callback(context, nullptr);
return;
}
- tempRTC->drawTexture(GrNoClip(), std::move(srcView), this->colorInfo().alphaType(),
+ tempRTC->drawTexture(nullptr, std::move(srcView), this->colorInfo().alphaType(),
GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
SK_PMColor4fWHITE, srcRectToDraw, SkRect::Make(srcRect.size()),
GrAA::kNo, GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint,
@@ -2008,7 +2069,7 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC
// TODO: Use one transfer buffer for all three planes to reduce map/unmap cost?
- auto texMatrix = SkMatrix::MakeTrans(x, y);
+ auto texMatrix = SkMatrix::Translate(x, y);
SkRect dstRectY = SkRect::Make(dstSize);
SkRect dstRectUV = SkRect::MakeWH(halfW, halfH);
@@ -2021,12 +2082,14 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC
std::fill_n(yM, 15, 0.f);
std::copy_n(baseM + 0, 5, yM + 15);
GrPaint yPaint;
- yPaint.addColorFragmentProcessor(
- GrTextureEffect::Make(srcView, this->colorInfo().alphaType(), texMatrix));
- auto yFP = GrColorMatrixFragmentProcessor::Make(yM, false, true, false);
- yPaint.addColorFragmentProcessor(std::move(yFP));
+ auto yTexFP = GrTextureEffect::Make(srcView, this->colorInfo().alphaType(), texMatrix);
+ auto yColFP = GrColorMatrixFragmentProcessor::Make(std::move(yTexFP), yM,
+ /*unpremulInput=*/false,
+ /*clampRGBOutput=*/true,
+ /*premulOutput=*/false);
+ yPaint.addColorFragmentProcessor(std::move(yColFP));
yPaint.setPorterDuffXPFactory(SkBlendMode::kSrc);
- yRTC->fillRectToRect(GrNoClip(), std::move(yPaint), GrAA::kNo, SkMatrix::I(),
+ yRTC->fillRectToRect(nullptr, std::move(yPaint), GrAA::kNo, SkMatrix::I(),
dstRectY, dstRectY);
if (!doSynchronousRead) {
yTransfer = yRTC->transferPixels(GrColorType::kAlpha_8,
@@ -2043,12 +2106,15 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC
std::fill_n(uM, 15, 0.f);
std::copy_n(baseM + 5, 5, uM + 15);
GrPaint uPaint;
- uPaint.addColorFragmentProcessor(GrTextureEffect::Make(
- srcView, this->colorInfo().alphaType(), texMatrix, GrSamplerState::Filter::kBilerp));
- auto uFP = GrColorMatrixFragmentProcessor::Make(uM, false, true, false);
- uPaint.addColorFragmentProcessor(std::move(uFP));
+ auto uTexFP = GrTextureEffect::Make(srcView, this->colorInfo().alphaType(), texMatrix,
+ GrSamplerState::Filter::kBilerp);
+ auto uColFP = GrColorMatrixFragmentProcessor::Make(std::move(uTexFP), uM,
+ /*unpremulInput=*/false,
+ /*clampRGBOutput=*/true,
+ /*premulOutput=*/false);
+ uPaint.addColorFragmentProcessor(std::move(uColFP));
uPaint.setPorterDuffXPFactory(SkBlendMode::kSrc);
- uRTC->fillRectToRect(GrNoClip(), std::move(uPaint), GrAA::kNo, SkMatrix::I(),
+ uRTC->fillRectToRect(nullptr, std::move(uPaint), GrAA::kNo, SkMatrix::I(),
dstRectUV, dstRectUV);
if (!doSynchronousRead) {
uTransfer = uRTC->transferPixels(GrColorType::kAlpha_8,
@@ -2064,13 +2130,15 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC
std::fill_n(vM, 15, 0.f);
std::copy_n(baseM + 10, 5, vM + 15);
GrPaint vPaint;
- vPaint.addColorFragmentProcessor(GrTextureEffect::Make(std::move(srcView),
- this->colorInfo().alphaType(), texMatrix,
- GrSamplerState::Filter::kBilerp));
- auto vFP = GrColorMatrixFragmentProcessor::Make(vM, false, true, false);
- vPaint.addColorFragmentProcessor(std::move(vFP));
+ auto vTexFP = GrTextureEffect::Make(std::move(srcView), this->colorInfo().alphaType(),
+ texMatrix, GrSamplerState::Filter::kBilerp);
+ auto vColFP = GrColorMatrixFragmentProcessor::Make(std::move(vTexFP), vM,
+ /*unpremulInput=*/false,
+ /*clampRGBOutput=*/true,
+ /*premulOutput=*/false);
+ vPaint.addColorFragmentProcessor(std::move(vColFP));
vPaint.setPorterDuffXPFactory(SkBlendMode::kSrc);
- vRTC->fillRectToRect(GrNoClip(), std::move(vPaint), GrAA::kNo, SkMatrix::I(),
+ vRTC->fillRectToRect(nullptr, std::move(vPaint), GrAA::kNo, SkMatrix::I(),
dstRectUV, dstRectUV);
if (!doSynchronousRead) {
vTransfer = vRTC->transferPixels(GrColorType::kAlpha_8,
@@ -2150,19 +2218,26 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC
GrFlushInfo flushInfo;
flushInfo.fFinishedContext = finishContext;
flushInfo.fFinishedProc = finishCallback;
- this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
+ this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo, nullptr);
}
GrSemaphoresSubmitted GrRenderTargetContext::flush(SkSurface::BackendSurfaceAccess access,
- const GrFlushInfo& info) {
+ const GrFlushInfo& info,
+ const GrBackendSurfaceMutableState* newState) {
ASSERT_SINGLE_OWNER
if (fContext->priv().abandoned()) {
+ if (info.fSubmittedProc) {
+ info.fSubmittedProc(info.fSubmittedContext, false);
+ }
+ if (info.fFinishedProc) {
+ info.fFinishedProc(info.fFinishedContext);
+ }
return GrSemaphoresSubmitted::kNo;
}
SkDEBUGCODE(this->validate();)
GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "flush", fContext);
- return this->drawingManager()->flushSurface(this->asSurfaceProxy(), access, info);
+ return this->drawingManager()->flushSurface(this->asSurfaceProxy(), access, info, newState);
}
bool GrRenderTargetContext::waitOnSemaphores(int numSemaphores,
@@ -2197,7 +2272,7 @@ bool GrRenderTargetContext::waitOnSemaphores(int numSemaphores,
return true;
}
-void GrRenderTargetContext::drawPath(const GrClip& clip,
+void GrRenderTargetContext::drawPath(const GrClip* clip,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
@@ -2213,7 +2288,7 @@ void GrRenderTargetContext::drawPath(const GrClip& clip,
this->drawShape(clip, std::move(paint), aa, viewMatrix, shape);
}
-void GrRenderTargetContext::drawShape(const GrClip& clip,
+void GrRenderTargetContext::drawShape(const GrClip* clip,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
@@ -2271,7 +2346,7 @@ void GrRenderTargetContext::drawShape(const GrClip& clip,
/* attempt fallback */ false);
}
-bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip,
+bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip* clip,
const GrUserStencilSettings* ss,
SkRegion::Op op,
bool invert,
@@ -2302,8 +2377,7 @@ bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip,
GrAAType aaType = fRenderTargetContext->chooseAAType(aa);
bool hasUserStencilSettings = !ss->isUnused();
- SkIRect clipConservativeBounds = clip.getConservativeBounds(fRenderTargetContext->width(),
- fRenderTargetContext->height());
+ SkIRect clipConservativeBounds = get_clip_bounds(fRenderTargetContext, clip);
GrPaint paint;
paint.setCoverageSetOpXPFactory(op, invert);
@@ -2332,7 +2406,7 @@ bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip,
std::move(paint),
ss,
fRenderTargetContext,
- &clip,
+ clip,
&clipConservativeBounds,
&viewMatrix,
&shape,
@@ -2354,7 +2428,7 @@ SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
return fRenderTargetContext->asSurfaceProxy()->isBudgeted();
}
-void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip& clip,
+void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip* clip,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
@@ -2376,7 +2450,7 @@ void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip& clip,
return;
}
- SkIRect clipConservativeBounds = clip.getConservativeBounds(this->width(), this->height());
+ SkIRect clipConservativeBounds = get_clip_bounds(this, clip);
GrStyledShape tempShape;
GrAAType aaType = this->chooseAAType(aa);
@@ -2441,7 +2515,7 @@ void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip& clip,
std::move(paint),
&GrUserStencilSettings::kUnused,
this,
- &clip,
+ clip,
&clipConservativeBounds,
&viewMatrix,
canDrawArgs.fShape,
@@ -2477,11 +2551,12 @@ static void op_bounds(SkRect* bounds, const GrOp* op) {
}
void GrRenderTargetContext::addOp(std::unique_ptr<GrOp> op) {
- this->getOpsTask()->addOp(
- std::move(op), GrTextureResolveManager(this->drawingManager()), *this->caps());
+ GrDrawingManager* drawingMgr = this->drawingManager();
+ this->getOpsTask()->addOp(drawingMgr,
+ std::move(op), GrTextureResolveManager(drawingMgr), *this->caps());
}
-void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op,
+void GrRenderTargetContext::addDrawOp(const GrClip* clip, std::unique_ptr<GrDrawOp> op,
const std::function<WillAddOpFn>& willAddFn) {
ASSERT_SINGLE_OWNER
if (fContext->priv().abandoned()) {
@@ -2495,7 +2570,7 @@ void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDraw
// Setup clip
SkRect bounds;
op_bounds(&bounds, op.get());
- GrAppliedClip appliedClip;
+ GrAppliedClip appliedClip(this->dimensions(), this->asSurfaceProxy()->backingStoreDimensions());
GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags();
bool usesHWAA = fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA;
bool usesUserStencilBits = fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil;
@@ -2504,7 +2579,20 @@ void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDraw
this->setNeedsStencil(usesHWAA);
}
- if (!clip.apply(fContext, this, usesHWAA, usesUserStencilBits, &appliedClip, &bounds)) {
+ bool skipDraw = false;
+ if (clip) {
+ // Have a complex clip, so defer to its early clip culling
+ if (!clip->apply(fContext, this, usesHWAA, usesUserStencilBits, &appliedClip, &bounds)) {
+ skipDraw = true;
+ }
+ } else {
+ // No clipping, so just clip the bounds against the logical render target dimensions
+ if (!bounds.intersect(this->asSurfaceProxy()->getBoundsRect())) {
+ skipDraw = true;
+ }
+ }
+
+ if (skipDraw) {
fContext->priv().opMemoryPool()->release(std::move(op));
return;
}
@@ -2524,24 +2612,26 @@ void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDraw
GrProcessorSet::Analysis analysis = op->finalize(
*this->caps(), &appliedClip, hasMixedSampledCoverage, clampType);
+ // Must be called before setDstProxyView so that it sees the final bounds of the op.
+ op->setClippedBounds(bounds);
+
GrXferProcessor::DstProxyView dstProxyView;
if (analysis.requiresDstTexture()) {
- if (!this->setupDstProxyView(clip, *op, &dstProxyView)) {
+ if (!this->setupDstProxyView(*op, &dstProxyView)) {
fContext->priv().opMemoryPool()->release(std::move(op));
return;
}
}
- op->setClippedBounds(bounds);
auto opsTask = this->getOpsTask();
if (willAddFn) {
willAddFn(op.get(), opsTask->uniqueID());
}
- opsTask->addDrawOp(std::move(op), analysis, std::move(appliedClip), dstProxyView,
- GrTextureResolveManager(this->drawingManager()), *this->caps());
+ opsTask->addDrawOp(this->drawingManager(), std::move(op), analysis, std::move(appliedClip),
+ dstProxyView,GrTextureResolveManager(this->drawingManager()), *this->caps());
}
-bool GrRenderTargetContext::setupDstProxyView(const GrClip& clip, const GrOp& op,
+bool GrRenderTargetContext::setupDstProxyView(const GrOp& op,
GrXferProcessor::DstProxyView* dstProxyView) {
// If we are wrapping a vulkan secondary command buffer, we can't make a dst copy because we
// don't actually have a VkImage to make a copy of. Additionally we don't have the power to
@@ -2561,37 +2651,20 @@ bool GrRenderTargetContext::setupDstProxyView(const GrClip& clip, const GrOp& op
}
}
- SkIRect copyRect = SkIRect::MakeSize(this->asSurfaceProxy()->dimensions());
-
- SkIRect clippedRect = clip.getConservativeBounds(this->width(), this->height());
- SkRect opBounds = op.bounds();
- // If the op has aa bloating or is a infinitely thin geometry (hairline) outset the bounds by
- // 0.5 pixels.
- if (op.hasAABloat() || op.hasZeroArea()) {
- opBounds.outset(0.5f, 0.5f);
- // An antialiased/hairline draw can sometimes bleed outside of the clips bounds. For
- // performance we may ignore the clip when the draw is entirely inside the clip is float
- // space but will hit pixels just outside the clip when actually rasterizing.
- clippedRect.outset(1, 1);
- clippedRect.intersect(SkIRect::MakeSize(this->asSurfaceProxy()->dimensions()));
- }
- SkIRect opIBounds;
- opBounds.roundOut(&opIBounds);
- if (!clippedRect.intersect(opIBounds)) {
-#ifdef SK_DEBUG
- GrCapsDebugf(this->caps(), "setupDstTexture: Missed an early reject bailing on draw.");
-#endif
- return false;
- }
-
GrColorType colorType = this->colorInfo().colorType();
// MSAA consideration: When there is support for reading MSAA samples in the shader we could
// have per-sample dst values by making the copy multisampled.
GrCaps::DstCopyRestrictions restrictions = this->caps()->getDstCopyRestrictions(
this->asRenderTargetProxy(), colorType);
+ SkIRect copyRect = SkIRect::MakeSize(this->asSurfaceProxy()->backingStoreDimensions());
if (!restrictions.fMustCopyWholeSrc) {
- copyRect = clippedRect;
+ // If we don't need the whole source, restrict to the op's bounds. We add an extra pixel
+ // of padding to account for AA bloat and the unpredictable rounding of coords near pixel
+ // centers during rasterization.
+ SkIRect conservativeDrawBounds = op.bounds().roundOut();
+ conservativeDrawBounds.outset(1, 1);
+ SkAssertResult(copyRect.intersect(conservativeDrawBounds));
}
SkIPoint dstOffset;
@@ -2633,7 +2706,7 @@ bool GrRenderTargetContext::blitTexture(GrSurfaceProxyView view, const SkIRect&
paint.addColorFragmentProcessor(std::move(fp));
this->fillRectToRect(
- GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+ nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
SkRect::MakeXYWH(clippedDstPoint.fX, clippedDstPoint.fY, clippedSrcRect.width(),
clippedSrcRect.height()),
SkRect::Make(clippedSrcRect));
diff --git a/chromium/third_party/skia/src/gpu/GrRenderTargetContext.h b/chromium/third_party/skia/src/gpu/GrRenderTargetContext.h
index ca0ac266de0..350461b081a 100644
--- a/chromium/third_party/skia/src/gpu/GrRenderTargetContext.h
+++ b/chromium/third_party/skia/src/gpu/GrRenderTargetContext.h
@@ -14,6 +14,7 @@
#include "include/core/SkSurface.h"
#include "include/core/SkSurfaceProps.h"
#include "include/private/GrTypesPriv.h"
+#include "src/core/SkGlyphRunPainter.h"
#include "src/gpu/GrOpsTask.h"
#include "src/gpu/GrPaint.h"
#include "src/gpu/GrRenderTargetProxy.h"
@@ -28,7 +29,6 @@ class GrClip;
class GrColorSpaceXform;
class GrCoverageCountingPathRenderer;
class GrDrawOp;
-class GrFixedClip;
class GrOp;
class GrRenderTarget;
class GrRenderTargetContextPriv;
@@ -118,8 +118,8 @@ public:
// Creates a GrRenderTargetContext that wraps the passed in GrBackendTexture.
static std::unique_ptr<GrRenderTargetContext> MakeFromBackendTexture(
GrRecordingContext*, GrColorType, sk_sp<SkColorSpace>, const GrBackendTexture&,
- int sampleCnt, GrSurfaceOrigin, const SkSurfaceProps*, ReleaseProc releaseProc,
- ReleaseContext releaseCtx);
+ int sampleCnt, GrSurfaceOrigin, const SkSurfaceProps*,
+ sk_sp<GrRefCntedCallback> releaseHelper);
static std::unique_ptr<GrRenderTargetContext> MakeFromBackendTextureAsRenderTarget(
GrRecordingContext*, GrColorType, sk_sp<SkColorSpace>, const GrBackendTexture&,
@@ -140,7 +140,7 @@ public:
~GrRenderTargetContext() override;
- virtual void drawGlyphRunList(const GrClip&, const SkMatrixProvider&, const SkGlyphRunList&);
+ virtual void drawGlyphRunList(const GrClip*, const SkMatrixProvider&, const SkGlyphRunList&);
/**
* Provides a perfomance hint that the render target's contents are allowed
@@ -148,28 +148,23 @@ public:
*/
void discard();
- enum class CanClearFullscreen : bool {
- kNo = false,
- kYes = true
- };
-
/**
- * Clear the entire or rect of the render target, ignoring any clips.
- * @param rect the rect to clear or the whole thing if rect is NULL.
+ * Clear the rect of the render target to the given color.
+ * @param rect the rect to clear to
* @param color the color to clear to.
- * @param CanClearFullscreen allows partial clears to be converted to fullscreen clears on
- * tiling platforms where that is an optimization.
*/
- void clear(const SkIRect* rect, const SkPMColor4f& color, CanClearFullscreen);
-
+ void clear(const SkIRect& rect, const SkPMColor4f& color) {
+ this->internalClear(&rect, color);
+ }
+ // Clears the entire render target to the color.
void clear(const SkPMColor4f& color) {
- return this->clear(nullptr, color, CanClearFullscreen::kYes);
+ this->internalClear(nullptr, color);
}
/**
* Draw everywhere (respecting the clip) with the paint.
*/
- void drawPaint(const GrClip&, GrPaint&&, const SkMatrix& viewMatrix);
+ void drawPaint(const GrClip*, GrPaint&&, const SkMatrix& viewMatrix);
/**
* Draw the rect using a paint.
@@ -180,7 +175,7 @@ public:
* allowed.
* The rects coords are used to access the paint (through texture matrix)
*/
- void drawRect(const GrClip&,
+ void drawRect(const GrClip*,
GrPaint&& paint,
GrAA,
const SkMatrix& viewMatrix,
@@ -196,7 +191,7 @@ public:
* @param rectToDraw the rectangle to draw
* @param localRect the rectangle of shader coordinates applied to rectToDraw
*/
- void fillRectToRect(const GrClip& clip,
+ void fillRectToRect(const GrClip* clip,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
@@ -210,7 +205,7 @@ public:
/**
* Fills a rect with a paint and a localMatrix.
*/
- void fillRectWithLocalMatrix(const GrClip& clip,
+ void fillRectWithLocalMatrix(const GrClip* clip,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
@@ -228,7 +223,7 @@ public:
* This is a specialized version of fillQuadWithEdgeAA, but is kept separate since knowing
* the geometry is a rectangle affords more optimizations.
*/
- void fillRectWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrAA aa, GrQuadAAFlags edgeAA,
+ void fillRectWithEdgeAA(const GrClip* clip, GrPaint&& paint, GrAA aa, GrQuadAAFlags edgeAA,
const SkMatrix& viewMatrix, const SkRect& rect,
const SkRect* optionalLocalRect = nullptr) {
const SkRect& localRect = optionalLocalRect ? *optionalLocalRect : rect;
@@ -248,7 +243,7 @@ public:
* The last argument, 'optionalLocalQuad', can be null if no separate local coordinates are
* necessary.
*/
- void fillQuadWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrAA aa, GrQuadAAFlags edgeAA,
+ void fillQuadWithEdgeAA(const GrClip* clip, GrPaint&& paint, GrAA aa, GrQuadAAFlags edgeAA,
const SkMatrix& viewMatrix, const SkPoint points[4],
const SkPoint optionalLocalPoints[4]) {
const SkPoint* localPoints = optionalLocalPoints ? optionalLocalPoints : points;
@@ -266,7 +261,7 @@ public:
};
// TODO(michaelludwig) - remove if the bulk API is not useful for SkiaRenderer
- void drawQuadSet(const GrClip& clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix,
+ void drawQuadSet(const GrClip* clip, GrPaint&& paint, GrAA aa, const SkMatrix& viewMatrix,
const QuadSetEntry[], int cnt);
/**
@@ -275,7 +270,7 @@ public:
* specifies the rectangle to draw in local coords which will be transformed by 'viewMatrix' to
* device space.
*/
- void drawTexture(const GrClip& clip, GrSurfaceProxyView view, SkAlphaType srcAlphaType,
+ void drawTexture(const GrClip* clip, GrSurfaceProxyView view, SkAlphaType srcAlphaType,
GrSamplerState::Filter filter, SkBlendMode mode, const SkPMColor4f& color,
const SkRect& srcRect, const SkRect& dstRect, GrAA aa, GrQuadAAFlags edgeAA,
SkCanvas::SrcRectConstraint constraint, const SkMatrix& viewMatrix,
@@ -294,7 +289,7 @@ public:
* 'subset' is null, it's equivalent to using the fast src rect constraint. If 'subset' is
* provided, the strict src rect constraint is applied using 'subset'.
*/
- void drawTextureQuad(const GrClip& clip, GrSurfaceProxyView view, GrColorType srcColorType,
+ void drawTextureQuad(const GrClip* clip, GrSurfaceProxyView view, GrColorType srcColorType,
SkAlphaType srcAlphaType, GrSamplerState::Filter filter, SkBlendMode mode,
const SkPMColor4f& color, const SkPoint srcQuad[4],
const SkPoint dstQuad[4], GrAA aa, GrQuadAAFlags edgeAA,
@@ -314,7 +309,7 @@ public:
SkRect fDstRect;
const SkPoint* fDstClipQuad; // Must be null, or point to an array of 4 points
const SkMatrix* fPreViewMatrix; // If not null, entry's CTM is 'viewMatrix' * fPreViewMatrix
- float fAlpha;
+ SkPMColor4f fColor; // {a,a,a,a} for rgb textures, {r,g,b,a} for alpha-only textures
GrQuadAAFlags fAAFlags;
};
/**
@@ -328,7 +323,7 @@ public:
* can be inferred from the array within this function, but the information is already known
* by SkGpuDevice, so no need to incur another iteration over the array.
*/
- void drawTextureSet(const GrClip&, TextureSetEntry[], int cnt, int proxyRunCnt,
+ void drawTextureSet(const GrClip*, TextureSetEntry[], int cnt, int proxyRunCnt,
GrSamplerState::Filter, SkBlendMode mode, GrAA aa,
SkCanvas::SrcRectConstraint, const SkMatrix& viewMatrix,
sk_sp<GrColorSpaceXform> texXform);
@@ -342,7 +337,7 @@ public:
* @param rrect the roundrect to draw
* @param style style to apply to the rrect. Currently path effects are not allowed.
*/
- void drawRRect(const GrClip&,
+ void drawRRect(const GrClip*,
GrPaint&&,
GrAA,
const SkMatrix& viewMatrix,
@@ -357,7 +352,7 @@ public:
* @param path the path to shadow
* @param rec parameters for shadow rendering
*/
- bool drawFastShadow(const GrClip&,
+ bool drawFastShadow(const GrClip*,
const SkMatrix& viewMatrix,
const SkPath& path,
const SkDrawShadowRec& rec);
@@ -372,7 +367,7 @@ public:
* @param outer the outer roundrect
* @param inner the inner roundrect
*/
- void drawDRRect(const GrClip&,
+ void drawDRRect(const GrClip*,
GrPaint&&,
GrAA,
const SkMatrix& viewMatrix,
@@ -388,7 +383,7 @@ public:
* @param path the path to draw
* @param style style to apply to the path.
*/
- void drawPath(const GrClip&,
+ void drawPath(const GrClip*,
GrPaint&&,
GrAA,
const SkMatrix& viewMatrix,
@@ -403,7 +398,7 @@ public:
* @param viewMatrix transformation matrix
* @param shape the shape to draw
*/
- void drawShape(const GrClip&,
+ void drawShape(const GrClip*,
GrPaint&&,
GrAA,
const SkMatrix& viewMatrix,
@@ -419,7 +414,7 @@ public:
* @param overridePrimType primitive type to draw. If NULL, derive prim type from vertices.
* @param effect runtime effect that will handle custom vertex attributes.
*/
- void drawVertices(const GrClip&,
+ void drawVertices(const GrClip*,
GrPaint&& paint,
const SkMatrixProvider& matrixProvider,
sk_sp<SkVertices> vertices,
@@ -438,7 +433,7 @@ public:
* @param colors optional array of per-sprite colors, supercedes
* the paint's color field.
*/
- void drawAtlas(const GrClip&,
+ void drawAtlas(const GrClip*,
GrPaint&& paint,
const SkMatrix& viewMatrix,
int spriteCount,
@@ -455,7 +450,7 @@ public:
* @param region the region to be drawn
* @param style style to apply to the region
*/
- void drawRegion(const GrClip&,
+ void drawRegion(const GrClip*,
GrPaint&& paint,
GrAA aa,
const SkMatrix& viewMatrix,
@@ -472,7 +467,7 @@ public:
* @param oval the bounding rect of the oval.
* @param style style to apply to the oval. Currently path effects are not allowed.
*/
- void drawOval(const GrClip&,
+ void drawOval(const GrClip*,
GrPaint&& paint,
GrAA,
const SkMatrix& viewMatrix,
@@ -493,7 +488,7 @@ public:
* omitted.
* @param style style to apply to the oval.
*/
- void drawArc(const GrClip&,
+ void drawArc(const GrClip*,
GrPaint&& paint,
GrAA,
const SkMatrix& viewMatrix,
@@ -506,7 +501,7 @@ public:
/**
* Draw the image as a set of rects, specified by |iter|.
*/
- void drawImageLattice(const GrClip&,
+ void drawImageLattice(const GrClip*,
GrPaint&&,
const SkMatrix& viewMatrix,
GrSurfaceProxyView,
@@ -551,7 +546,8 @@ public:
* After this returns any pending surface IO will be issued to the backend 3D API and
* if the surface has MSAA it will be resolved.
*/
- GrSemaphoresSubmitted flush(SkSurface::BackendSurfaceAccess access, const GrFlushInfo&);
+ GrSemaphoresSubmitted flush(SkSurface::BackendSurfaceAccess access, const GrFlushInfo&,
+ const GrBackendSurfaceMutableState*);
/**
* The next time this GrRenderTargetContext is flushed, the gpu will wait on the passed in
@@ -594,13 +590,12 @@ private:
GrAAType chooseAAType(GrAA);
- friend class GrAtlasTextBlob; // for access to add[Mesh]DrawOp
friend class GrClipStackClip; // for access to getOpsTask
friend class GrOnFlushResourceProvider; // for access to getOpsTask (http://skbug.com/9357)
friend class GrRenderTargetContextPriv;
- // All the path renderers currently make their own ops
+ // All the path and text renderers/ops currently make their own ops
friend class GrSoftwarePathRenderer; // for access to add[Mesh]DrawOp
friend class GrAAConvexPathRenderer; // for access to add[Mesh]DrawOp
friend class GrDashLinePathRenderer; // for access to add[Mesh]DrawOp
@@ -615,6 +610,7 @@ private:
friend class GrFillRectOp; // for access to addDrawOp
friend class GrTessellationPathRenderer; // for access to addDrawOp
friend class GrTextureOp; // for access to addDrawOp
+ friend class GrAtlasTextOp; // for access to addDrawOp
SkDEBUGCODE(void onValidate() const override;)
@@ -622,11 +618,12 @@ private:
GrOpsTask::CanDiscardPreviousOps canDiscardPreviousOpsOnFullClear() const;
void setNeedsStencil(bool useMixedSamplesIfNotMSAA);
- void internalClear(const GrFixedClip&, const SkPMColor4f&, CanClearFullscreen);
- void internalStencilClear(const GrFixedClip&, bool insideStencilMask);
+ void internalClear(const SkIRect* scissor, const SkPMColor4f&,
+ bool upgradePartialToFull = false);
+ void internalStencilClear(const SkIRect* scissor, bool insideStencilMask);
// Only consumes the GrPaint if successful.
- bool drawFilledDRRect(const GrClip& clip,
+ bool drawFilledDRRect(const GrClip* clip,
GrPaint&& paint,
GrAA,
const SkMatrix& viewMatrix,
@@ -642,7 +639,7 @@ private:
//
// 'stencilSettings' are provided merely for decision making purposes; When non-null,
// optimization strategies that submit special ops are avoided.
- QuadOptimization attemptQuadOptimization(const GrClip& clip,
+ QuadOptimization attemptQuadOptimization(const GrClip* clip,
const SkPMColor4f* constColor,
const GrUserStencilSettings* stencilSettings,
GrAA* aa,
@@ -652,7 +649,7 @@ private:
// can choose between coverage, MSAA as per chooseAAType(). This will always attempt to apply
// quad optimizations, so all quad/rect public APIs should rely on this function for consistent
// clipping behavior. 'quad' will be modified in place to reflect final rendered geometry.
- void drawFilledQuad(const GrClip& clip,
+ void drawFilledQuad(const GrClip* clip,
GrPaint&& paint,
GrAA aa,
DrawQuad* quad,
@@ -660,7 +657,7 @@ private:
// Like drawFilledQuad but does not require using a GrPaint or FP for texturing.
// 'quad' may be modified in place to reflect final geometry.
- void drawTexturedQuad(const GrClip& clip,
+ void drawTexturedQuad(const GrClip* clip,
GrSurfaceProxyView proxyView,
SkAlphaType alphaType,
sk_sp<GrColorSpaceXform> textureXform,
@@ -673,7 +670,7 @@ private:
// If 'attemptShapeFallback' is true, and the original shape had been simplfied, this
// will re-route through drawShape() to see if we can avoid path rendering one more time.
- void drawShapeUsingPathRenderer(const GrClip&, GrPaint&&, GrAA, const SkMatrix&,
+ void drawShapeUsingPathRenderer(const GrClip*, GrPaint&&, GrAA, const SkMatrix&,
const GrStyledShape&, bool attemptShapeFallback = true);
void addOp(std::unique_ptr<GrOp>);
@@ -684,13 +681,17 @@ private:
// op list. Before adding the op to an op list the WillAddOpFn is called. Note that it
// will not be called in the event that the op is discarded. Moreover, the op may merge into
// another op after the function is called (either before addDrawOp returns or some time later).
- void addDrawOp(const GrClip&, std::unique_ptr<GrDrawOp>,
+ //
+ // If the clip pointer is null, no clipping will be performed.
+ void addDrawOp(const GrClip*, std::unique_ptr<GrDrawOp>,
const std::function<WillAddOpFn>& = std::function<WillAddOpFn>());
// Makes a copy of the proxy if it is necessary for the draw and places the texture that should
// be used by GrXferProcessor to access the destination color in 'result'. If the return
// value is false then a texture copy could not be made.
- bool SK_WARN_UNUSED_RESULT setupDstProxyView(const GrClip&, const GrOp& op,
+ //
+ // The op should have already had setClippedBounds called on it.
+ bool SK_WARN_UNUSED_RESULT setupDstProxyView(const GrOp& op,
GrXferProcessor::DstProxyView* result);
class AsyncReadResult;
@@ -701,6 +702,8 @@ private:
GrOpsTask* getOpsTask();
+ SkGlyphRunListPainter* glyphPainter() { return &fGlyphPainter; }
+
std::unique_ptr<GrTextTarget> fTextTarget;
GrSurfaceProxyView fWriteView;
@@ -716,7 +719,7 @@ private:
#if GR_TEST_UTILS
bool fPreserveOpsOnFullClear_TestingOnly = false;
#endif
-
+ SkGlyphRunListPainter fGlyphPainter;
typedef GrSurfaceContext INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/GrRenderTargetContextPriv.h b/chromium/third_party/skia/src/gpu/GrRenderTargetContextPriv.h
index 188d251002d..4e1e227fbc9 100644
--- a/chromium/third_party/skia/src/gpu/GrRenderTargetContextPriv.h
+++ b/chromium/third_party/skia/src/gpu/GrRenderTargetContextPriv.h
@@ -12,7 +12,6 @@
#include "src/gpu/GrPathRendering.h"
#include "src/gpu/GrRenderTargetContext.h"
-class GrFixedClip;
class GrHardClip;
class GrPath;
class GrRenderTargetPriv;
@@ -43,17 +42,21 @@ public:
opsTask->fLastClipNumAnalyticFPs != numClipAnalyticFPs;
}
- using CanClearFullscreen = GrRenderTargetContext::CanClearFullscreen;
-
- void clear(const GrFixedClip&, const SkPMColor4f&, CanClearFullscreen);
+ // Clear at minimum the pixels within 'scissor', but is allowed to clear the full render target
+ // if that is the more performant option.
+ void clearAtLeast(const SkIRect& scissor, const SkPMColor4f& color) {
+ fRenderTargetContext->internalClear(&scissor, color, /* upgrade to full */ true);
+ }
- void clearStencilClip(const GrFixedClip&, bool insideStencilMask);
+ void clearStencilClip(const SkIRect& scissor, bool insideStencilMask) {
+ fRenderTargetContext->internalStencilClear(&scissor, insideStencilMask);
+ }
// While this can take a general clip, since GrReducedClip relies on this function, it must take
// care to only provide hard clips or we could get stuck in a loop. The general clip is needed
// so that path renderers can use this function.
void stencilRect(
- const GrClip& clip, const GrUserStencilSettings* ss, GrPaint&& paint,
+ const GrClip* clip, const GrUserStencilSettings* ss, GrPaint&& paint,
GrAA doStencilMSAA, const SkMatrix& viewMatrix, const SkRect& rect,
const SkMatrix* localMatrix = nullptr) {
// Since this provides stencil settings to drawFilledQuad, it performs a different AA type
@@ -65,13 +68,13 @@ public:
}
void stencilPath(
- const GrHardClip&, GrAA doStencilMSAA, const SkMatrix& viewMatrix, sk_sp<const GrPath>);
+ const GrHardClip*, GrAA doStencilMSAA, const SkMatrix& viewMatrix, sk_sp<const GrPath>);
/**
* Draws a path, either AA or not, and touches the stencil buffer with the user stencil settings
* for each color sample written.
*/
- bool drawAndStencilPath(const GrHardClip&,
+ bool drawAndStencilPath(const GrHardClip*,
const GrUserStencilSettings*,
SkRegion::Op op,
bool invert,
@@ -95,7 +98,7 @@ public:
using WillAddOpFn = GrRenderTargetContext::WillAddOpFn;
void testingOnly_addDrawOp(std::unique_ptr<GrDrawOp>);
- void testingOnly_addDrawOp(const GrClip&, std::unique_ptr<GrDrawOp>,
+ void testingOnly_addDrawOp(const GrClip*, std::unique_ptr<GrDrawOp>,
const std::function<WillAddOpFn>& = std::function<WillAddOpFn>());
bool refsWrappedObjects() const {
diff --git a/chromium/third_party/skia/src/gpu/GrRenderTargetProxy.h b/chromium/third_party/skia/src/gpu/GrRenderTargetProxy.h
index de21acc23cb..31193ae184b 100644
--- a/chromium/third_party/skia/src/gpu/GrRenderTargetProxy.h
+++ b/chromium/third_party/skia/src/gpu/GrRenderTargetProxy.h
@@ -60,7 +60,7 @@ public:
bool wrapsVkSecondaryCB() const { return fWrapsVkSecondaryCB == WrapsVkSecondaryCB::kYes; }
void markMSAADirty(const SkIRect& dirtyRect, GrSurfaceOrigin origin) {
- SkASSERT(SkIRect::MakeSize(this->dimensions()).contains(dirtyRect));
+ SkASSERT(SkIRect::MakeSize(this->backingStoreDimensions()).contains(dirtyRect));
SkASSERT(this->requiresManualMSAAResolve());
auto nativeRect = GrNativeRect::MakeRelativeTo(
origin, this->backingStoreDimensions().height(), dirtyRect);
diff --git a/chromium/third_party/skia/src/gpu/GrRenderTask.cpp b/chromium/third_party/skia/src/gpu/GrRenderTask.cpp
index 7dc434b8276..fece63f45b2 100644
--- a/chromium/third_party/skia/src/gpu/GrRenderTask.cpp
+++ b/chromium/third_party/skia/src/gpu/GrRenderTask.cpp
@@ -26,21 +26,24 @@ GrRenderTask::GrRenderTask()
, fFlags(0) {
}
-GrRenderTask::GrRenderTask(GrSurfaceProxyView targetView)
- : fTargetView(std::move(targetView))
- , fUniqueID(CreateUniqueID())
- , fFlags(0) {
-}
+void GrRenderTask::disown(GrDrawingManager* drawingMgr) {
+ if (this->isSetFlag(kDisowned_Flag)) {
+ return;
+ }
+ this->setFlag(kDisowned_Flag);
-GrRenderTask::~GrRenderTask() {
- GrSurfaceProxy* proxy = fTargetView.proxy();
- if (proxy && this == proxy->getLastRenderTask()) {
- // Ensure the target proxy doesn't keep hold of a dangling back pointer.
- proxy->setLastRenderTask(nullptr);
+ for (const GrSurfaceProxyView& target : fTargets) {
+ if (this == drawingMgr->getLastRenderTask(target.proxy())) {
+ drawingMgr->setLastRenderTask(target.proxy(), nullptr);
+ }
}
}
#ifdef SK_DEBUG
+GrRenderTask::~GrRenderTask() {
+ SkASSERT(this->isSetFlag(kDisowned_Flag));
+}
+
bool GrRenderTask::deferredProxiesAreInstantiated() const {
for (int i = 0; i < fDeferredProxies.count(); ++i) {
if (!fDeferredProxies[i]->isInstantiated()) {
@@ -59,13 +62,13 @@ void GrRenderTask::makeClosed(const GrCaps& caps) {
SkIRect targetUpdateBounds;
if (ExpectedOutcome::kTargetDirty == this->onMakeClosed(caps, &targetUpdateBounds)) {
- GrSurfaceProxy* proxy = fTargetView.proxy();
+ GrSurfaceProxy* proxy = this->target(0).proxy();
if (proxy->requiresManualMSAAResolve()) {
- SkASSERT(fTargetView.asRenderTargetProxy());
- fTargetView.asRenderTargetProxy()->markMSAADirty(targetUpdateBounds,
- fTargetView.origin());
+ SkASSERT(this->target(0).asRenderTargetProxy());
+ this->target(0).asRenderTargetProxy()->markMSAADirty(targetUpdateBounds,
+ this->target(0).origin());
}
- GrTextureProxy* textureProxy = fTargetView.asTextureProxy();
+ GrTextureProxy* textureProxy = this->target(0).asTextureProxy();
if (textureProxy && GrMipMapped::kYes == textureProxy->mipMapped()) {
textureProxy->markMipMapsDirty();
}
@@ -111,13 +114,14 @@ void GrRenderTask::addDependenciesFromOtherTask(GrRenderTask* otherTask) {
}
// Convert from a GrSurface-based dependency to a GrRenderTask one
-void GrRenderTask::addDependency(GrSurfaceProxy* dependedOn, GrMipMapped mipMapped,
+void GrRenderTask::addDependency(GrDrawingManager* drawingMgr, GrSurfaceProxy* dependedOn,
+ GrMipMapped mipMapped,
GrTextureResolveManager textureResolveManager,
const GrCaps& caps) {
// If it is still receiving dependencies, this GrRenderTask shouldn't be closed
SkASSERT(!this->isClosed());
- GrRenderTask* dependedOnTask = dependedOn->getLastRenderTask();
+ GrRenderTask* dependedOnTask = drawingMgr->getLastRenderTask(dependedOn);
if (dependedOnTask == this) {
// self-read - presumably for dst reads. We don't need to do anything in this case. The
@@ -168,11 +172,11 @@ void GrRenderTask::addDependency(GrSurfaceProxy* dependedOn, GrMipMapped mipMapp
if (!fTextureResolveTask) {
fTextureResolveTask = textureResolveManager.newTextureResolveRenderTask(caps);
}
- fTextureResolveTask->addProxy(sk_ref_sp(dependedOn), resolveFlags, caps);
+ fTextureResolveTask->addProxy(drawingMgr, sk_ref_sp(dependedOn), resolveFlags, caps);
// addProxy() should have closed the texture proxy's previous task.
SkASSERT(!dependedOnTask || dependedOnTask->isClosed());
- SkASSERT(dependedOn->getLastRenderTask() == fTextureResolveTask);
+ SkASSERT(drawingMgr->getLastRenderTask(dependedOn) == fTextureResolveTask);
#ifdef SK_DEBUG
// addProxy() should have called addDependency (in this instance, recursively) on
@@ -192,7 +196,7 @@ void GrRenderTask::addDependency(GrSurfaceProxy* dependedOn, GrMipMapped mipMapp
if (textureProxy) {
SkASSERT(!textureProxy->mipMapsAreDirty());
}
- SkASSERT(dependedOn->getLastRenderTask() == fTextureResolveTask);
+ SkASSERT(drawingMgr->getLastRenderTask(dependedOn) == fTextureResolveTask);
#endif
return;
}
@@ -250,11 +254,11 @@ void GrRenderTask::closeThoseWhoDependOnMe(const GrCaps& caps) {
}
bool GrRenderTask::isInstantiated() const {
- // Some renderTasks (e.g. GrTransferFromRenderTask) don't have a target.
- GrSurfaceProxy* proxy = fTargetView.proxy();
- if (!proxy) {
+ // Some renderTasks (e.g. GrTransferFromRenderTask) don't have any targets.
+ if (0 == this->numTargets()) {
return true;
}
+ GrSurfaceProxy* proxy = this->target(0).proxy();
if (!proxy->isInstantiated()) {
return false;
@@ -268,16 +272,29 @@ bool GrRenderTask::isInstantiated() const {
return true;
}
+void GrRenderTask::addTarget(GrDrawingManager* drawingMgr, GrSurfaceProxyView view) {
+ SkASSERT(view);
+ drawingMgr->setLastRenderTask(view.proxy(), this);
+ fTargets.push_back(std::move(view));
+}
+
#ifdef SK_DEBUG
void GrRenderTask::dump(bool printDependencies) const {
SkDebugf("--------------------------------------------------------------\n");
- GrSurfaceProxy* proxy = fTargetView.proxy();
- SkDebugf("%s - renderTaskID: %d - proxyID: %d - surfaceID: %d\n",
- this->name(), fUniqueID,
- proxy ? proxy->uniqueID().asUInt() : -1,
- proxy && proxy->peekSurface()
- ? proxy->peekSurface()->uniqueID().asUInt()
- : -1);
+ SkDebugf("%s - renderTaskID: %d\n", this->name(), fUniqueID);
+
+ if (!fTargets.empty()) {
+ SkDebugf("Targets: \n");
+ for (int i = 0; i < fTargets.count(); ++i) {
+ GrSurfaceProxy* proxy = fTargets[i].proxy();
+ SkDebugf("[%d]: proxyID: %d - surfaceID: %d\n",
+ i,
+ proxy ? proxy->uniqueID().asUInt() : -1,
+ proxy && proxy->peekSurface()
+ ? proxy->peekSurface()->uniqueID().asUInt()
+ : -1);
+ }
+ }
if (printDependencies) {
SkDebugf("I rely On (%d): ", fDependencies.count());
diff --git a/chromium/third_party/skia/src/gpu/GrRenderTask.h b/chromium/third_party/skia/src/gpu/GrRenderTask.h
index 83f17d90243..64431a18fea 100644
--- a/chromium/third_party/skia/src/gpu/GrRenderTask.h
+++ b/chromium/third_party/skia/src/gpu/GrRenderTask.h
@@ -14,6 +14,7 @@
#include "src/gpu/GrSurfaceProxyView.h"
#include "src/gpu/GrTextureProxy.h"
#include "src/gpu/GrTextureResolveManager.h"
+#include "src/gpu/ops/GrOp.h"
class GrOpFlushState;
class GrOpsTask;
@@ -26,8 +27,7 @@ class GrTextureResolveRenderTask;
class GrRenderTask : public SkRefCnt {
public:
GrRenderTask();
- GrRenderTask(GrSurfaceProxyView);
- ~GrRenderTask() override;
+ SkDEBUGCODE(~GrRenderTask() override);
void makeClosed(const GrCaps&);
@@ -40,15 +40,20 @@ public:
// Called when this class will survive a flush and needs to truncate its ops and start over.
// TODO: ultimately it should be invalid for an op list to survive a flush.
// https://bugs.chromium.org/p/skia/issues/detail?id=7111
- virtual void endFlush() {}
+ virtual void endFlush(GrDrawingManager*) {}
+
+ // This method "disowns" all the GrSurfaceProxies this RenderTask modifies. In
+ // practice this just means telling the drawingManager to forget the relevant
+ // mappings from surface proxy to last modifying rendertask.
+ virtual void disown(GrDrawingManager*);
bool isClosed() const { return this->isSetFlag(kClosed_Flag); }
/*
* Notify this GrRenderTask that it relies on the contents of 'dependedOn'
*/
- void addDependency(GrSurfaceProxy* dependedOn, GrMipMapped, GrTextureResolveManager,
- const GrCaps& caps);
+ void addDependency(GrDrawingManager*, GrSurfaceProxy* dependedOn, GrMipMapped,
+ GrTextureResolveManager, const GrCaps& caps);
/*
* Notify this GrRenderTask that it relies on the contents of all GrRenderTasks which otherTask
@@ -62,6 +67,8 @@ public:
bool dependsOn(const GrRenderTask* dependedOn) const;
uint32_t uniqueID() const { return fUniqueID; }
+ int numTargets() const { return fTargets.count(); }
+ const GrSurfaceProxyView& target(int i) const { return fTargets[i]; }
/*
* Safely cast this GrRenderTask to a GrOpsTask (if possible).
@@ -81,8 +88,8 @@ public:
void visitTargetAndSrcProxies_debugOnly(const GrOp::VisitProxyFunc& fn) const {
this->visitProxies_debugOnly(fn);
- if (fTargetView.proxy()) {
- fn(fTargetView.proxy(), GrMipMapped::kNo);
+ for (int i = 0; i < this->numTargets(); ++i) {
+ fn(this->target(i).proxy(), GrMipMapped::kNo);
}
}
#endif
@@ -94,6 +101,10 @@ protected:
SkDEBUGCODE(bool deferredProxiesAreInstantiated() const;)
+ // Add a target surface proxy to the list of targets for this task.
+ // This also informs the drawing manager to update the lastRenderTask association.
+ void addTarget(GrDrawingManager*, GrSurfaceProxyView);
+
enum class ExpectedOutcome : bool {
kTargetUnchanged,
kTargetDirty,
@@ -106,7 +117,7 @@ protected:
// targetUpdateBounds must not extend beyond the proxy bounds.
virtual ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect* targetUpdateBounds) = 0;
- GrSurfaceProxyView fTargetView;
+ SkSTArray<1, GrSurfaceProxyView> fTargets;
// List of texture proxies whose contents are being prepared on a worker thread
// TODO: this list exists so we can fire off the proper upload when an renderTask begins
@@ -118,15 +129,19 @@ private:
friend class GrDrawingManager;
// Drops any pending operations that reference proxies that are not instantiated.
- // NOTE: Derived classes don't need to check fTargetView. That is handled when the
+ // NOTE: Derived classes don't need to check targets. That is handled when the
// drawingManager calls isInstantiated.
virtual void handleInternalAllocationFailure() = 0;
+ // Derived classes can override to indicate usage of proxies _other than target proxies_.
+ // GrRenderTask itself will handle checking the target proxies.
virtual bool onIsUsed(GrSurfaceProxy*) const = 0;
bool isUsed(GrSurfaceProxy* proxy) const {
- if (proxy == fTargetView.proxy()) {
- return true;
+ for (const GrSurfaceProxyView& target : fTargets) {
+ if (target.proxy() == proxy) {
+ return true;
+ }
}
return this->onIsUsed(proxy);
@@ -144,10 +159,11 @@ private:
static uint32_t CreateUniqueID();
enum Flags {
- kClosed_Flag = 0x01, //!< This GrRenderTask can't accept any more dependencies.
+ kClosed_Flag = 0x01, //!< This task can't accept any more dependencies.
+ kDisowned_Flag = 0x02, //!< This task is disowned by its creating GrDrawingManager.
- kWasOutput_Flag = 0x02, //!< Flag for topological sorting
- kTempMark_Flag = 0x04, //!< Flag for topological sorting
+ kWasOutput_Flag = 0x04, //!< Flag for topological sorting
+ kTempMark_Flag = 0x08, //!< Flag for topological sorting
};
void setFlag(uint32_t flag) {
diff --git a/chromium/third_party/skia/src/gpu/GrResourceCache.cpp b/chromium/third_party/skia/src/gpu/GrResourceCache.cpp
index cdc0e21f24b..b3166acf1a6 100644
--- a/chromium/third_party/skia/src/gpu/GrResourceCache.cpp
+++ b/chromium/third_party/skia/src/gpu/GrResourceCache.cpp
@@ -28,8 +28,7 @@ DECLARE_SKMESSAGEBUS_MESSAGE(GrUniqueKeyInvalidatedMessage);
DECLARE_SKMESSAGEBUS_MESSAGE(GrTextureFreedMessage);
-#define ASSERT_SINGLE_OWNER \
- SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
+#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fSingleOwner)
//////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/src/gpu/GrResourceCache.h b/chromium/third_party/skia/src/gpu/GrResourceCache.h
index 4db77e21867..23639dc3890 100644
--- a/chromium/third_party/skia/src/gpu/GrResourceCache.h
+++ b/chromium/third_party/skia/src/gpu/GrResourceCache.h
@@ -61,7 +61,7 @@ public:
~GrResourceCache();
// Default maximum number of bytes of gpu memory of budgeted resources in the cache.
- static const size_t kDefaultMaxSize = 96 * (1 << 20);
+ static const size_t kDefaultMaxSize = 256 * (1 << 20);
/** Used to access functionality needed by GrGpuResource for lifetime management. */
class ResourceAccess;
diff --git a/chromium/third_party/skia/src/gpu/GrResourceProvider.cpp b/chromium/third_party/skia/src/gpu/GrResourceProvider.cpp
index f079c7d9df2..2c9d9b145bb 100644
--- a/chromium/third_party/skia/src/gpu/GrResourceProvider.cpp
+++ b/chromium/third_party/skia/src/gpu/GrResourceProvider.cpp
@@ -31,8 +31,7 @@
const int GrResourceProvider::kMinScratchTextureSize = 16;
-#define ASSERT_SINGLE_OWNER \
- SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
+#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fSingleOwner)
GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* owner)
: fCache(cache)
diff --git a/chromium/third_party/skia/src/gpu/GrRingBuffer.cpp b/chromium/third_party/skia/src/gpu/GrRingBuffer.cpp
new file mode 100644
index 00000000000..145c88a72df
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrRingBuffer.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/GrRingBuffer.h"
+
+// Get offset into buffer that has enough space for size
+// Returns fTotalSize if no space
+size_t GrRingBuffer::getAllocationOffset(size_t size) {
+ // capture current state locally (because fTail could be overwritten by the completion handler)
+ size_t head, tail;
+ SkAutoSpinlock lock(fMutex);
+ head = fHead;
+ tail = fTail;
+
+ // The head and tail indices increment without bound, wrapping with overflow,
+ // so we need to mod them down to the actual bounds of the allocation to determine
+ // which blocks are available.
+ size_t modHead = head & (fTotalSize - 1);
+ size_t modTail = tail & (fTotalSize - 1);
+
+ bool full = (head != tail && modHead == modTail);
+
+ if (full) {
+ return fTotalSize;
+ }
+
+ // case 1: free space lies at the beginning and/or the end of the buffer
+ if (modHead >= modTail) {
+ // check for room at the end
+ if (fTotalSize - modHead < size) {
+ // no room at the end, check the beginning
+ if (modTail < size) {
+ // no room at the beginning
+ return fTotalSize;
+ }
+ // we are going to allocate from the beginning, adjust head to '0' position
+ head += fTotalSize - modHead;
+ modHead = 0;
+ }
+ // case 2: free space lies in the middle of the buffer, check for room there
+ } else if (modTail - modHead < size) {
+ // no room in the middle
+ return fTotalSize;
+ }
+
+ fHead = GrAlignTo(head + size, fAlignment);
+ return modHead;
+}
+
+GrRingBuffer::Slice GrRingBuffer::suballocate(size_t size) {
+ size_t offset = this->getAllocationOffset(size);
+ if (offset < fTotalSize) {
+ return { fBuffer, offset };
+ }
+
+ // Try to grow allocation (old allocation will age out).
+ fTotalSize *= 2;
+ fBuffer = this->createBuffer(fTotalSize);
+ SkASSERT(fBuffer);
+ {
+ SkAutoSpinlock lock(fMutex);
+ fHead = 0;
+ fTail = 0;
+ fGenID++;
+ }
+ offset = this->getAllocationOffset(size);
+ SkASSERT(offset < fTotalSize);
+ return { fBuffer, offset };
+}
+
+// used when current command buffer/command list is submitted
+GrRingBuffer::SubmitData GrRingBuffer::startSubmit() {
+ SubmitData submitData;
+ SkAutoSpinlock lock(fMutex);
+ submitData.fBuffer = fBuffer;
+ submitData.fLastHead = fHead;
+ submitData.fGenID = fGenID;
+ return submitData;
+}
+
+// used when current command buffer/command list is completed
+void GrRingBuffer::finishSubmit(const GrRingBuffer::SubmitData& submitData) {
+ SkAutoSpinlock lock(fMutex);
+ if (submitData.fGenID == fGenID) {
+ fTail = submitData.fLastHead;
+ }
+}
diff --git a/chromium/third_party/skia/src/gpu/GrRingBuffer.h b/chromium/third_party/skia/src/gpu/GrRingBuffer.h
new file mode 100644
index 00000000000..2498c0d9cfb
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrRingBuffer.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrRingBuffer_DEFINED
+#define GrRingBuffer_DEFINED
+
+#include "src/gpu/GrGpuBuffer.h"
+
+#include "include/private/SkSpinlock.h"
+
+/**
+ * A wrapper for a GPU buffer that allocates slices in a continuous ring.
+ *
+ * It's assumed that suballocate and startSubmit are always called in the same thread,
+ * and that finishSubmit could be called in a separate thread.
+ */
+class GrRingBuffer : public SkRefCnt {
+public:
+ GrRingBuffer(sk_sp<GrGpuBuffer> buffer, size_t size, size_t alignment)
+ : fBuffer(std::move(buffer))
+ , fTotalSize(size)
+ , fAlignment(alignment)
+ , fHead(0)
+ , fTail(0)
+ , fGenID(0) {
+ // We increment fHead and fTail without bound and let overflow handle any wrapping.
+ // Because of this, size needs to be a power of two.
+ SkASSERT(SkIsPow2(size));
+ }
+ virtual ~GrRingBuffer() = default;
+
+ struct Slice {
+ sk_sp<GrGpuBuffer> fBuffer;
+ size_t fOffset;
+ };
+
+ Slice suballocate(size_t size);
+
+ class SubmitData {
+ public:
+ GrGpuBuffer* buffer() const { return fBuffer.get(); }
+ private:
+ friend class GrRingBuffer;
+ sk_sp<GrGpuBuffer> fBuffer;
+ size_t fLastHead;
+ size_t fGenID;
+ };
+ // Backends should call startSubmit() at submit time, and finishSubmit() when the
+ // command buffer/list finishes.
+ SubmitData startSubmit();
+ void finishSubmit(const SubmitData&);
+
+ size_t size() const { return fTotalSize; }
+
+private:
+ virtual sk_sp<GrGpuBuffer> createBuffer(size_t size) = 0;
+ size_t getAllocationOffset(size_t size);
+
+ sk_sp<GrGpuBuffer> fBuffer;
+ size_t fTotalSize;
+ size_t fAlignment;
+ size_t fHead SK_GUARDED_BY(fMutex); // where we start allocating
+ size_t fTail SK_GUARDED_BY(fMutex); // where we start deallocating
+ uint64_t fGenID SK_GUARDED_BY(fMutex); // incremented when createBuffer is called
+ SkSpinlock fMutex;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrSWMaskHelper.h b/chromium/third_party/skia/src/gpu/GrSWMaskHelper.h
index 5ca23f70d61..5982bcffb35 100644
--- a/chromium/third_party/skia/src/gpu/GrSWMaskHelper.h
+++ b/chromium/third_party/skia/src/gpu/GrSWMaskHelper.h
@@ -15,6 +15,7 @@
#include "src/core/SkAutoPixmapStorage.h"
#include "src/core/SkDraw.h"
#include "src/core/SkRasterClip.h"
+#include "src/gpu/GrSurfaceProxyView.h"
class GrShape;
class GrStyledShape;
diff --git a/chromium/third_party/skia/src/gpu/GrScissorState.h b/chromium/third_party/skia/src/gpu/GrScissorState.h
index dac735b023d..cc1cea25781 100644
--- a/chromium/third_party/skia/src/gpu/GrScissorState.h
+++ b/chromium/third_party/skia/src/gpu/GrScissorState.h
@@ -10,33 +10,74 @@
#include "include/core/SkRect.h"
+/**
+ * The scissor state is stored as the scissor rectangle and the backing store bounds of the render
+ * target that the scissor will apply to. If the render target is approximate fit and the padded
+ * content should not be modified, the clip should apply the render target context's logical bounds
+ * as part of the scissor (e.g. when stenciling). This puts the onus on the render target context
+ * to intentionally discard the scissor at its logical bounds when drawing into the padded content
+ * is acceptable (e.g. color-only updates).
+ */
class GrScissorState {
public:
- GrScissorState() : fEnabled(false) {}
- GrScissorState(const SkIRect& rect) : fEnabled(true), fRect(rect) {}
- void setDisabled() { fEnabled = false; }
- void set(const SkIRect& rect) { fRect = rect; fEnabled = true; }
+ // The disabled scissor state for a render target of the given size.
+ explicit GrScissorState(const SkISize& rtDims)
+ : fRTSize(rtDims)
+ , fRect(SkIRect::MakeSize(rtDims)) {}
+
+ void setDisabled() { fRect = SkIRect::MakeSize(fRTSize); }
+ bool set(const SkIRect& rect) {
+ this->setDisabled();
+ return this->intersect(rect);
+ }
+
bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& rect) {
- if (!fEnabled) {
- this->set(rect);
+ if (!fRect.intersect(rect)) {
+ fRect.setEmpty();
+ return false;
+ } else {
return true;
}
- return fRect.intersect(rect);
}
+
+ // If the scissor was configured for the backing store dimensions and it's acceptable to
+ // draw outside the logical dimensions of the target, this will discard the scissor test if
+ // the test wouldn't modify the logical dimensions.
+ bool relaxTest(const SkISize& logicalDimensions) {
+ SkASSERT(logicalDimensions.fWidth <= fRTSize.fWidth &&
+ logicalDimensions.fHeight <= fRTSize.fHeight);
+ if (fRect.fLeft == 0 && fRect.fTop == 0 && fRect.fRight >= logicalDimensions.fWidth &&
+ fRect.fBottom >= logicalDimensions.fHeight) {
+ this->setDisabled();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
bool operator==(const GrScissorState& other) const {
- return fEnabled == other.fEnabled &&
- (false == fEnabled || fRect == other.fRect);
+ return fRTSize == other.fRTSize && fRect == other.fRect;
}
bool operator!=(const GrScissorState& other) const { return !(*this == other); }
- bool enabled() const { return fEnabled; }
+ bool enabled() const {
+ SkASSERT(fRect.isEmpty() || SkIRect::MakeSize(fRTSize).contains(fRect));
+ // This is equivalent to a strict contains check on SkIRect::MakeSize(rtSize) w/o creating
+ // the render target bounding rectangle.
+ return fRect.fLeft > 0 || fRect.fTop > 0 ||
+ fRect.fRight < fRTSize.fWidth || fRect.fBottom < fRTSize.fHeight;
+ }
+
+ // Will always be equal to or contained in the rt bounds, or empty if scissor rectangles were
+ // added that did not intersect with the render target or prior scissor.
const SkIRect& rect() const {
- SkASSERT(fEnabled);
+ SkASSERT(fRect.isEmpty() || SkIRect::MakeSize(fRTSize).contains(fRect));
return fRect;
}
private:
- bool fEnabled;
+ // The scissor is considered enabled if the rectangle does not cover the render target
+ SkISize fRTSize;
SkIRect fRect;
};
diff --git a/chromium/third_party/skia/src/gpu/GrShaderCaps.cpp b/chromium/third_party/skia/src/gpu/GrShaderCaps.cpp
index faafc94c79b..a629085a099 100644
--- a/chromium/third_party/skia/src/gpu/GrShaderCaps.cpp
+++ b/chromium/third_party/skia/src/gpu/GrShaderCaps.cpp
@@ -49,7 +49,6 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fPreferFlatInterpolation = false;
fNoPerspectiveInterpolationSupport = false;
fSampleMaskSupport = false;
- fTessellationSupport = false;
fExternalTextureSupport = false;
fVertexIDSupport = false;
fFPManipulationSupport = false;
@@ -61,6 +60,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
// GL_ARB_texture_swizzle).
fTextureSwizzleAppliedInShader = true;
fBuiltinFMASupport = false;
+ fCanUseDoLoops = true;
fVersionDeclString = nullptr;
fShaderDerivativeExtensionString = nullptr;
@@ -76,6 +76,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fFBFetchColorName = nullptr;
fFBFetchExtensionString = nullptr;
fMaxFragmentSamplers = 0;
+ fMaxTessellationSegments = 0;
fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction;
}
@@ -132,7 +133,6 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
writer->appendBool("Prefer flat interpolation", fPreferFlatInterpolation);
writer->appendBool("No perspective interpolation support", fNoPerspectiveInterpolationSupport);
writer->appendBool("Sample mask support", fSampleMaskSupport);
- writer->appendBool("Tessellation Support", fTessellationSupport);
writer->appendBool("External texture support", fExternalTextureSupport);
writer->appendBool("sk_VertexID support", fVertexIDSupport);
writer->appendBool("Floating point manipulation support", fFPManipulationSupport);
@@ -142,8 +142,10 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
writer->appendBool("Color space math needs float", fColorSpaceMathNeedsFloat);
writer->appendBool("Texture swizzle applied in shader", fTextureSwizzleAppliedInShader);
writer->appendBool("Builtin fma() support", fBuiltinFMASupport);
+ writer->appendBool("Can use do-while loops", fCanUseDoLoops);
writer->appendS32("Max FS Samplers", fMaxFragmentSamplers);
+ writer->appendS32("Max Tessellation Segments", fMaxTessellationSegments);
writer->appendString("Advanced blend equation interaction",
kAdvBlendEqInteractionStr[fAdvBlendEqInteraction]);
@@ -183,7 +185,7 @@ void GrShaderCaps::applyOptionsOverrides(const GrContextOptions& options) {
fGeometryShaderSupport = false;
}
if (options.fSuppressTessellationShaders) {
- fTessellationSupport = false;
+ fMaxTessellationSegments = 0;
}
#endif
}
diff --git a/chromium/third_party/skia/src/gpu/GrShaderCaps.h b/chromium/third_party/skia/src/gpu/GrShaderCaps.h
index b6a3cc023c1..3b3e1bf9b5f 100644
--- a/chromium/third_party/skia/src/gpu/GrShaderCaps.h
+++ b/chromium/third_party/skia/src/gpu/GrShaderCaps.h
@@ -72,8 +72,6 @@ public:
bool sampleMaskSupport() const { return fSampleMaskSupport; }
- bool tessellationSupport() const { return fTessellationSupport; }
-
bool externalTextureSupport() const { return fExternalTextureSupport; }
bool vertexIDSupport() const { return fVertexIDSupport; }
@@ -175,6 +173,10 @@ public:
// http://skbug.com/8921
bool canOnlyUseSampleMaskWithStencil() const { return fCanOnlyUseSampleMaskWithStencil; }
+ // ANGLE disallows do loops altogether, and we're seeing crashes on Tegra3 with do loops in at
+ // least some cases.
+ bool canUseDoLoops() const { return fCanUseDoLoops; }
+
// Returns the string of an extension that must be enabled in the shader to support
// derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
// this function, the caller should check that shaderDerivativeSupport exists.
@@ -244,6 +246,11 @@ public:
int maxFragmentSamplers() const { return fMaxFragmentSamplers; }
+ // Maximum number of segments a tessellation edge can be divided into.
+ int maxTessellationSegments() const { return fMaxTessellationSegments; }
+
+ bool tessellationSupport() const { return SkToBool(fMaxTessellationSegments);}
+
bool textureSwizzleAppliedInShader() const { return fTextureSwizzleAppliedInShader; }
GrGLSLGeneration generation() const { return fGLSLGeneration; }
@@ -267,7 +274,6 @@ private:
bool fPreferFlatInterpolation : 1;
bool fNoPerspectiveInterpolationSupport : 1;
bool fSampleMaskSupport : 1;
- bool fTessellationSupport : 1;
bool fExternalTextureSupport : 1;
bool fVertexIDSupport : 1;
bool fFPManipulationSupport : 1;
@@ -301,6 +307,7 @@ private:
bool fNoDefaultPrecisionForExternalSamplers : 1;
bool fCanOnlyUseSampleMaskWithStencil : 1;
bool fColorSpaceMathNeedsFloat : 1;
+ bool fCanUseDoLoops : 1;
const char* fVersionDeclString;
@@ -319,6 +326,7 @@ private:
const char* fFBFetchExtensionString;
int fMaxFragmentSamplers;
+ int fMaxTessellationSegments;
AdvBlendEqInteraction fAdvBlendEqInteraction;
diff --git a/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp b/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp
index 6646caeadb9..95ab059800f 100644
--- a/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp
@@ -68,15 +68,16 @@ static bool get_unclipped_shape_dev_bounds(const GrStyledShape& shape, const SkM
// Gets the shape bounds, the clip bounds, and the intersection (if any). Returns false if there
// is no intersection.
bool GrSoftwarePathRenderer::GetShapeAndClipBounds(GrRenderTargetContext* renderTargetContext,
- const GrClip& clip,
+ const GrClip* clip,
const GrStyledShape& shape,
const SkMatrix& matrix,
SkIRect* unclippedDevShapeBounds,
SkIRect* clippedDevShapeBounds,
SkIRect* devClipBounds) {
// compute bounds as intersection of rt size, clip, and path
- *devClipBounds = clip.getConservativeBounds(renderTargetContext->width(),
- renderTargetContext->height());
+ *devClipBounds = clip ? clip->getConservativeBounds()
+ : SkIRect::MakeWH(renderTargetContext->width(),
+ renderTargetContext->height());
if (!get_unclipped_shape_dev_bounds(shape, matrix, unclippedDevShapeBounds)) {
*unclippedDevShapeBounds = SkIRect::MakeEmpty();
@@ -95,7 +96,7 @@ bool GrSoftwarePathRenderer::GetShapeAndClipBounds(GrRenderTargetContext* render
void GrSoftwarePathRenderer::DrawNonAARect(GrRenderTargetContext* renderTargetContext,
GrPaint&& paint,
const GrUserStencilSettings& userStencilSettings,
- const GrClip& clip,
+ const GrClip* clip,
const SkMatrix& viewMatrix,
const SkRect& rect,
const SkMatrix& localMatrix) {
@@ -106,7 +107,7 @@ void GrSoftwarePathRenderer::DrawNonAARect(GrRenderTargetContext* renderTargetCo
void GrSoftwarePathRenderer::DrawAroundInvPath(GrRenderTargetContext* renderTargetContext,
GrPaint&& paint,
const GrUserStencilSettings& userStencilSettings,
- const GrClip& clip,
+ const GrClip* clip,
const SkMatrix& viewMatrix,
const SkIRect& devClipBounds,
const SkIRect& devPathBounds) {
@@ -147,7 +148,7 @@ void GrSoftwarePathRenderer::DrawToTargetWithShapeMask(
GrRenderTargetContext* renderTargetContext,
GrPaint&& paint,
const GrUserStencilSettings& userStencilSettings,
- const GrClip& clip,
+ const GrClip* clip,
const SkMatrix& viewMatrix,
const SkIPoint& textureOriginInDeviceSpace,
const SkIRect& deviceSpaceRectToDraw) {
@@ -161,7 +162,7 @@ void GrSoftwarePathRenderer::DrawToTargetWithShapeMask(
// We use device coords to compute the texture coordinates. We take the device coords and apply
// a translation so that the top-left of the device bounds maps to 0,0, and then a scaling
// matrix to normalized coords.
- SkMatrix maskMatrix = SkMatrix::MakeTrans(SkIntToScalar(-textureOriginInDeviceSpace.fX),
+ SkMatrix maskMatrix = SkMatrix::Translate(SkIntToScalar(-textureOriginInDeviceSpace.fX),
SkIntToScalar(-textureOriginInDeviceSpace.fY));
maskMatrix.preConcat(viewMatrix);
@@ -241,13 +242,13 @@ bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) {
args.fShape->hasUnstyledKey() && (GrAAType::kCoverage == args.fAAType);
if (!GetShapeAndClipBounds(args.fRenderTargetContext,
- *args.fClip, *args.fShape,
+ args.fClip, *args.fShape,
*args.fViewMatrix, &unclippedDevShapeBounds,
&clippedDevShapeBounds,
&devClipBounds)) {
if (inverseFilled) {
DrawAroundInvPath(args.fRenderTargetContext, std::move(args.fPaint),
- *args.fUserStencilSettings, *args.fClip, *args.fViewMatrix,
+ *args.fUserStencilSettings, args.fClip, *args.fViewMatrix,
devClipBounds, unclippedDevShapeBounds);
}
return true;
@@ -382,11 +383,11 @@ bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) {
SkASSERT(view);
if (inverseFilled) {
DrawAroundInvPath(args.fRenderTargetContext, GrPaint::Clone(args.fPaint),
- *args.fUserStencilSettings, *args.fClip, *args.fViewMatrix, devClipBounds,
+ *args.fUserStencilSettings, args.fClip, *args.fViewMatrix, devClipBounds,
unclippedDevShapeBounds);
}
DrawToTargetWithShapeMask(std::move(view), args.fRenderTargetContext, std::move(args.fPaint),
- *args.fUserStencilSettings, *args.fClip, *args.fViewMatrix,
+ *args.fUserStencilSettings, args.fClip, *args.fViewMatrix,
SkIPoint{boundsForMask->fLeft, boundsForMask->fTop}, *boundsForMask);
return true;
diff --git a/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.h b/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.h
index d24d48adbe4..7b931662240 100644
--- a/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.h
+++ b/chromium/third_party/skia/src/gpu/GrSoftwarePathRenderer.h
@@ -27,7 +27,7 @@ public:
}
static bool GetShapeAndClipBounds(GrRenderTargetContext*,
- const GrClip& clip,
+ const GrClip* clip,
const GrStyledShape& shape,
const SkMatrix& matrix,
SkIRect* unclippedDevShapeBounds,
@@ -38,14 +38,14 @@ private:
static void DrawNonAARect(GrRenderTargetContext* renderTargetContext,
GrPaint&& paint,
const GrUserStencilSettings& userStencilSettings,
- const GrClip& clip,
+ const GrClip* clip,
const SkMatrix& viewMatrix,
const SkRect& rect,
const SkMatrix& localMatrix);
static void DrawAroundInvPath(GrRenderTargetContext* renderTargetContext,
GrPaint&& paint,
const GrUserStencilSettings& userStencilSettings,
- const GrClip& clip,
+ const GrClip* clip,
const SkMatrix& viewMatrix,
const SkIRect& devClipBounds,
const SkIRect& devPathBounds);
@@ -57,7 +57,7 @@ private:
GrRenderTargetContext* renderTargetContext,
GrPaint&& paint,
const GrUserStencilSettings& userStencilSettings,
- const GrClip& clip,
+ const GrClip* clip,
const SkMatrix& viewMatrix,
const SkIPoint& textureOriginInDeviceSpace,
const SkIRect& deviceSpaceRectToDraw);
diff --git a/chromium/third_party/skia/src/gpu/GrStencilClip.h b/chromium/third_party/skia/src/gpu/GrStencilClip.h
index 854ba1ce510..4ab8a82e080 100644
--- a/chromium/third_party/skia/src/gpu/GrStencilClip.h
+++ b/chromium/third_party/skia/src/gpu/GrStencilClip.h
@@ -16,12 +16,14 @@
*/
class GrStencilClip final : public GrHardClip {
public:
- GrStencilClip(uint32_t stencilStackID = SK_InvalidGenID) : fStencilStackID(stencilStackID) {}
+ explicit GrStencilClip(const SkISize& rtDims, uint32_t stencilStackID = SK_InvalidGenID)
+ : fFixedClip(rtDims)
+ , fStencilStackID(stencilStackID) {}
- explicit GrStencilClip(const SkIRect& scissorRect, uint32_t stencilStackID = SK_InvalidGenID)
- : fFixedClip(scissorRect)
- , fStencilStackID(stencilStackID) {
- }
+ GrStencilClip(const SkISize& rtDims, const SkIRect& scissorRect,
+ uint32_t stencilStackID = SK_InvalidGenID)
+ : fFixedClip(rtDims, scissorRect)
+ , fStencilStackID(stencilStackID) {}
const GrFixedClip& fixedClip() const { return fFixedClip; }
GrFixedClip& fixedClip() { return fFixedClip; }
@@ -33,14 +35,14 @@ public:
bool quickContains(const SkRect& rect) const override {
return !this->hasStencilClip() && fFixedClip.quickContains(rect);
}
- SkIRect getConservativeBounds(int width, int height) const override {
- return fFixedClip.getConservativeBounds(width, height);
+ SkIRect getConservativeBounds() const override {
+ return fFixedClip.getConservativeBounds();
}
- bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA* aa) const override {
- return !this->hasStencilClip() && fFixedClip.isRRect(rtBounds, rr, aa);
+ bool isRRect(SkRRect* rr, GrAA* aa) const override {
+ return !this->hasStencilClip() && fFixedClip.isRRect(rr, aa);
}
- bool apply(int rtWidth, int rtHeight, GrAppliedHardClip* out, SkRect* bounds) const override {
- if (!fFixedClip.apply(rtWidth, rtHeight, out, bounds)) {
+ bool apply(GrAppliedHardClip* out, SkRect* bounds) const override {
+ if (!fFixedClip.apply(out, bounds)) {
return false;
}
if (this->hasStencilClip()) {
diff --git a/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.cpp b/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.cpp
index f9870f41af1..f261e265e92 100644
--- a/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.cpp
+++ b/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.cpp
@@ -278,7 +278,7 @@ static void draw_stencil_rect(GrRenderTargetContext* rtc, const GrHardClip& clip
const SkRect& rect, GrAA aa) {
GrPaint paint;
paint.setXPFactory(GrDisableColorXPFactory::Get());
- rtc->priv().stencilRect(clip, ss, std::move(paint), aa, matrix, rect);
+ rtc->priv().stencilRect(&clip, ss, std::move(paint), aa, matrix, rect);
}
static void draw_path(GrRecordingContext* context, GrRenderTargetContext* rtc,
@@ -334,7 +334,8 @@ bool GrStencilMaskHelper::init(const SkIRect& bounds, uint32_t genID,
}
fClip.setStencilClip(genID);
- fClip.fixedClip().setScissor(bounds);
+ // Should have caught bounds not intersecting the render target much earlier in clip application
+ SkAssertResult(fClip.fixedClip().setScissor(bounds));
if (!windowRects.empty()) {
fClip.fixedClip().setWindowRectangles(
windowRects, GrWindowRectsState::Mode::kExclusive);
@@ -462,7 +463,15 @@ bool GrStencilMaskHelper::drawShape(const GrShape& shape,
}
void GrStencilMaskHelper::clear(bool insideStencil) {
- fRTC->priv().clearStencilClip(fClip.fixedClip(), insideStencil);
+ if (fClip.fixedClip().hasWindowRectangles()) {
+ // Use a draw to benefit from window rectangles when resetting the stencil buffer; for
+ // large buffers with MSAA this can be significant.
+ draw_stencil_rect(fRTC, fClip.fixedClip(),
+ GrStencilSettings::SetClipBitSettings(insideStencil), SkMatrix::I(),
+ SkRect::Make(fClip.fixedClip().scissorRect()), GrAA::kNo);
+ } else {
+ fRTC->priv().clearStencilClip(fClip.fixedClip().scissorRect(), insideStencil);
+ }
}
void GrStencilMaskHelper::finish() {
diff --git a/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.h b/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.h
index 547bee2d934..f6cd2b90aa2 100644
--- a/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.h
+++ b/chromium/third_party/skia/src/gpu/GrStencilMaskHelper.h
@@ -39,7 +39,8 @@ public:
// of which must outlive the helper.
GrStencilMaskHelper(GrRecordingContext* context, GrRenderTargetContext* rtc)
: fContext(context)
- , fRTC(rtc) {}
+ , fRTC(rtc)
+ , fClip(rtc->dimensions()) {}
// Returns true if the stencil mask must be redrawn
bool init(const SkIRect& maskBounds, uint32_t genID,
diff --git a/chromium/third_party/skia/src/gpu/GrSurface.cpp b/chromium/third_party/skia/src/gpu/GrSurface.cpp
index 03f46166116..1aa4444482f 100644
--- a/chromium/third_party/skia/src/gpu/GrSurface.cpp
+++ b/chromium/third_party/skia/src/gpu/GrSurface.cpp
@@ -7,6 +7,7 @@
#include "include/gpu/GrContext.h"
#include "src/core/SkCompressedDataUtils.h"
+#include "src/gpu/GrBackendUtils.h"
#include "src/gpu/GrRenderTarget.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrSurface.h"
@@ -34,7 +35,7 @@ size_t GrSurface::ComputeSize(const GrCaps& caps,
dimensions = GrResourceProvider::MakeApprox(dimensions);
}
- SkImage::CompressionType compressionType = caps.compressionType(format);
+ SkImage::CompressionType compressionType = GrBackendFormatToCompressionType(format);
if (compressionType != SkImage::CompressionType::kNone) {
colorSize = SkCompressedFormatDataSize(compressionType, dimensions,
mipMapped == GrMipMapped::kYes);
diff --git a/chromium/third_party/skia/src/gpu/GrSurfaceContext.cpp b/chromium/third_party/skia/src/gpu/GrSurfaceContext.cpp
index 4e0e5c4b6ba..b7c667f04b9 100644
--- a/chromium/third_party/skia/src/gpu/GrSurfaceContext.cpp
+++ b/chromium/third_party/skia/src/gpu/GrSurfaceContext.cpp
@@ -10,7 +10,6 @@
#include "include/private/GrRecordingContext.h"
#include "src/core/SkAutoPixmapStorage.h"
#include "src/gpu/GrAuditTrail.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrDataUtils.h"
#include "src/gpu/GrDrawingManager.h"
@@ -24,8 +23,7 @@
#include "src/gpu/SkGr.h"
#include "src/gpu/effects/GrBicubicEffect.h"
-#define ASSERT_SINGLE_OWNER \
- SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
+#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(this->singleOwner())
#define RETURN_FALSE_IF_ABANDONED if (this->fContext->priv().abandoned()) { return false; }
std::unique_ptr<GrSurfaceContext> GrSurfaceContext::Make(GrRecordingContext* context,
@@ -240,7 +238,7 @@ bool GrSurfaceContext::readPixels(const GrImageInfo& origDstInfo, void* dst, siz
paint.addColorFragmentProcessor(std::move(fp));
tempCtx->asRenderTargetContext()->fillRectToRect(
- GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+ nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
SkRect::MakeWH(dstInfo.width(), dstInfo.height()),
SkRect::MakeXYWH(pt.fX, pt.fY, dstInfo.width(), dstInfo.height()));
@@ -275,7 +273,7 @@ bool GrSurfaceContext::readPixels(const GrImageInfo& origDstInfo, void* dst, siz
}
direct->priv().flushSurface(srcProxy);
-
+ direct->submit();
if (!direct->priv().getGpu()->readPixels(srcSurface, pt.fX, pt.fY, dstInfo.width(),
dstInfo.height(), this->colorInfo().colorType(),
supportedRead.fColorType, readDst, readRB)) {
@@ -426,7 +424,7 @@ bool GrSurfaceContext::writePixels(const GrImageInfo& origSrcInfo, const void* s
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
paint.addColorFragmentProcessor(std::move(fp));
this->asRenderTargetContext()->fillRectToRect(
- GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+ nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
SkRect::MakeXYWH(pt.fX, pt.fY, srcInfo.width(), srcInfo.height()),
SkRect::MakeWH(srcInfo.width(), srcInfo.height()));
} else {
@@ -502,14 +500,11 @@ bool GrSurfaceContext::copy(GrSurfaceProxy* src, const SkIRect& srcRect, const S
}
std::unique_ptr<GrRenderTargetContext> GrSurfaceContext::rescale(
- const SkImageInfo& info,
- const SkIRect& srcRect,
+ const GrImageInfo& info,
+ GrSurfaceOrigin origin,
+ SkIRect srcRect,
SkSurface::RescaleGamma rescaleGamma,
SkFilterQuality rescaleQuality) {
- auto direct = fContext->priv().asDirectContext();
- if (!direct) {
- return nullptr;
- }
auto rtProxy = this->asRenderTargetProxy();
if (rtProxy && rtProxy->wrapsVkSecondaryCB()) {
return nullptr;
@@ -524,12 +519,7 @@ std::unique_ptr<GrRenderTargetContext> GrSurfaceContext::rescale(
return nullptr;
}
- int srcW = srcRect.width();
- int srcH = srcRect.height();
- int srcX = srcRect.fLeft;
- int srcY = srcRect.fTop;
GrSurfaceProxyView texView = this->readSurfaceView();
- SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint;
SkAlphaType srcAlphaType = this->colorInfo().alphaType();
if (!texView.asTextureProxy()) {
texView = GrSurfaceProxyView::Copy(fContext, std::move(texView), GrMipMapped::kNo, srcRect,
@@ -538,25 +528,8 @@ std::unique_ptr<GrRenderTargetContext> GrSurfaceContext::rescale(
return nullptr;
}
SkASSERT(texView.asTextureProxy());
- srcX = 0;
- srcY = 0;
- constraint = SkCanvas::kFast_SrcRectConstraint;
- }
-
- float sx = (float)info.width() / srcW;
- float sy = (float)info.height() / srcH;
-
- // How many bilerp/bicubic steps to do in X and Y. + means upscaling, - means downscaling.
- int stepsX;
- int stepsY;
- if (rescaleQuality > kNone_SkFilterQuality) {
- stepsX = static_cast<int>((sx > 1.f) ? ceil(log2f(sx)) : floor(log2f(sx)));
- stepsY = static_cast<int>((sy > 1.f) ? ceil(log2f(sy)) : floor(log2f(sy)));
- } else {
- stepsX = sx != 1.f;
- stepsY = sy != 1.f;
+ srcRect = SkIRect::MakeSize(srcRect.size());
}
- SkASSERT(stepsX || stepsY);
// Within a rescaling pass A is the input (if not null) and B is the output. At the end of the
// pass B is moved to A. If 'this' is the input on the first pass then tempA is null.
@@ -572,100 +545,95 @@ std::unique_ptr<GrRenderTargetContext> GrSurfaceContext::rescale(
kPremul_SkAlphaType);
// We'll fall back to kRGBA_8888 if half float not supported.
auto linearRTC = GrRenderTargetContext::MakeWithFallback(
- fContext, GrColorType::kRGBA_F16, cs, SkBackingFit::kExact, {srcW, srcH}, 1,
- GrMipMapped::kNo, GrProtected::kNo, kTopLeft_GrSurfaceOrigin);
+ fContext, GrColorType::kRGBA_F16, cs, SkBackingFit::kApprox, srcRect.size(), 1,
+ GrMipMapped::kNo, GrProtected::kNo, origin);
if (!linearRTC) {
return nullptr;
}
- linearRTC->drawTexture(GrNoClip(), std::move(texView), srcAlphaType,
+ // 1-to-1 draw can always be kFast.
+ linearRTC->drawTexture(nullptr, std::move(texView), srcAlphaType,
GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
- SK_PMColor4fWHITE, SkRect::Make(srcRect), SkRect::MakeWH(srcW, srcH),
- GrAA::kNo, GrQuadAAFlags::kNone, constraint, SkMatrix::I(),
- std::move(xform));
+ SK_PMColor4fWHITE, SkRect::Make(srcRect),
+ SkRect::Make(srcRect.size()), GrAA::kNo, GrQuadAAFlags::kNone,
+ SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), std::move(xform));
texView = linearRTC->readSurfaceView();
SkASSERT(texView.asTextureProxy());
tempA = std::move(linearRTC);
- srcX = 0;
- srcY = 0;
- constraint = SkCanvas::kFast_SrcRectConstraint;
- }
- while (stepsX || stepsY) {
- int nextW = info.width();
- int nextH = info.height();
- if (stepsX < 0) {
- nextW = info.width() << (-stepsX - 1);
- stepsX++;
- } else if (stepsX != 0) {
- if (stepsX > 1) {
- nextW = srcW * 2;
+ srcRect = SkIRect::MakeSize(srcRect.size());
+ }
+
+ while (srcRect.size() != info.dimensions()) {
+ SkISize nextDims = info.dimensions();
+ if (rescaleQuality != kNone_SkFilterQuality) {
+ if (srcRect.width() > info.width()) {
+ nextDims.fWidth = std::max((srcRect.width() + 1)/2, info.width());
+ } else if (srcRect.width() < info.width()) {
+ nextDims.fWidth = std::min(srcRect.width()*2, info.width());
}
- --stepsX;
- }
- if (stepsY < 0) {
- nextH = info.height() << (-stepsY - 1);
- stepsY++;
- } else if (stepsY != 0) {
- if (stepsY > 1) {
- nextH = srcH * 2;
+ if (srcRect.height() > info.height()) {
+ nextDims.fHeight = std::max((srcRect.height() + 1)/2, info.height());
+ } else if (srcRect.height() < info.height()) {
+ nextDims.fHeight = std::min(srcRect.height()*2, info.height());
}
- --stepsY;
}
auto input = tempA ? tempA.get() : this;
GrColorType colorType = input->colorInfo().colorType();
auto cs = input->colorInfo().refColorSpace();
sk_sp<GrColorSpaceXform> xform;
auto prevAlphaType = input->colorInfo().alphaType();
- if (!stepsX && !stepsY) {
+ if (nextDims == info.dimensions()) {
// Might as well fold conversion to final info in the last step.
cs = info.refColorSpace();
- colorType = SkColorTypeToGrColorType(info.colorType());
xform = GrColorSpaceXform::Make(input->colorInfo().colorSpace(),
input->colorInfo().alphaType(), cs.get(),
info.alphaType());
}
- tempB = GrRenderTargetContext::MakeWithFallback(
- fContext, colorType, std::move(cs), SkBackingFit::kExact, {nextW, nextH}, 1,
- GrMipMapped::kNo, GrProtected::kNo, kTopLeft_GrSurfaceOrigin);
+ tempB = GrRenderTargetContext::MakeWithFallback(fContext, colorType, std::move(cs),
+ SkBackingFit::kApprox, nextDims, 1,
+ GrMipMapped::kNo, GrProtected::kNo, origin);
if (!tempB) {
return nullptr;
}
- auto dstRect = SkRect::MakeWH(nextW, nextH);
+ auto dstRect = SkRect::Make(nextDims);
if (rescaleQuality == kHigh_SkFilterQuality) {
SkMatrix matrix;
- matrix.setScaleTranslate((float)srcW / nextW, (float)srcH / nextH, srcX, srcY);
+ matrix.setScaleTranslate((float)srcRect.width()/nextDims.width(),
+ (float)srcRect.height()/nextDims.height(),
+ srcRect.x(),
+ srcRect.y());
std::unique_ptr<GrFragmentProcessor> fp;
auto dir = GrBicubicEffect::Direction::kXY;
- if (nextW == srcW) {
+ if (nextDims.width() == srcRect.width()) {
dir = GrBicubicEffect::Direction::kY;
- } else if (nextH == srcH) {
+ } else if (nextDims.height() == srcRect.height()) {
dir = GrBicubicEffect::Direction::kX;
}
static constexpr GrSamplerState::WrapMode kWM = GrSamplerState::WrapMode::kClamp;
- auto subset = SkRect::MakeXYWH(srcX, srcY, srcW, srcH);
fp = GrBicubicEffect::MakeSubset(std::move(texView), prevAlphaType, matrix, kWM, kWM,
- subset, dir, *this->caps());
+ SkRect::Make(srcRect), dir, *this->caps());
if (xform) {
fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(xform));
}
GrPaint paint;
paint.addColorFragmentProcessor(std::move(fp));
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
- tempB->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
+ tempB->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
dstRect);
} else {
auto filter = rescaleQuality == kNone_SkFilterQuality ? GrSamplerState::Filter::kNearest
: GrSamplerState::Filter::kBilerp;
- auto srcSubset = SkRect::MakeXYWH(srcX, srcY, srcW, srcH);
- tempB->drawTexture(GrNoClip(), std::move(texView), srcAlphaType, filter,
- SkBlendMode::kSrc, SK_PMColor4fWHITE, srcSubset, dstRect, GrAA::kNo,
+ // Minimizing draw with integer coord src and dev rects can always be kFast.
+ auto constraint = SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint;
+ if (nextDims.width() <= srcRect.width() && nextDims.height() <= srcRect.height()) {
+ constraint = SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint;
+ }
+ tempB->drawTexture(nullptr, std::move(texView), srcAlphaType, filter, SkBlendMode::kSrc,
+ SK_PMColor4fWHITE, SkRect::Make(srcRect), dstRect, GrAA::kNo,
GrQuadAAFlags::kNone, constraint, SkMatrix::I(), std::move(xform));
}
texView = tempB->readSurfaceView();
tempA = std::move(tempB);
- srcX = srcY = 0;
- srcW = nextW;
- srcH = nextH;
- constraint = SkCanvas::kFast_SrcRectConstraint;
+ srcRect = SkIRect::MakeSize(nextDims);
}
SkASSERT(tempA);
return tempA;
@@ -744,4 +712,3 @@ void GrSurfaceContext::validate() const {
this->onValidate();
}
#endif
-
diff --git a/chromium/third_party/skia/src/gpu/GrSurfaceContext.h b/chromium/third_party/skia/src/gpu/GrSurfaceContext.h
index 028cc52a94d..8e3394ce1a0 100644
--- a/chromium/third_party/skia/src/gpu/GrSurfaceContext.h
+++ b/chromium/third_party/skia/src/gpu/GrSurfaceContext.h
@@ -114,6 +114,19 @@ public:
virtual GrRenderTargetContext* asRenderTargetContext() { return nullptr; }
+ /**
+ * Rescales the contents of srcRect. The gamma in which the rescaling occurs is controlled by
+ * RescaleGamma. It is always in the original gamut. The result is converted to the color type
+ * and color space of info after rescaling. Note: this currently requires that the info have a
+ * different size than srcRect. Though, it could be relaxed to allow non-scaling color
+ * conversions.
+ */
+ std::unique_ptr<GrRenderTargetContext> rescale(const GrImageInfo& info,
+ GrSurfaceOrigin,
+ SkIRect srcRect,
+ SkSurface::RescaleGamma,
+ SkFilterQuality);
+
GrAuditTrail* auditTrail();
// Provides access to functions that aren't part of the public API.
@@ -144,11 +157,6 @@ protected:
GrSurfaceProxyView fReadView;
- // The rescaling step of asyncRescaleAndReadPixels[YUV420]().
- std::unique_ptr<GrRenderTargetContext> rescale(const SkImageInfo& info, const SkIRect& srcRect,
- SkSurface::RescaleGamma rescaleGamma,
- SkFilterQuality rescaleQuality);
-
// Inserts a transfer, part of the implementation of asyncReadPixels and
// asyncRescaleAndReadPixelsYUV420().
struct PixelTransferResult {
diff --git a/chromium/third_party/skia/src/gpu/GrSurfaceProxy.cpp b/chromium/third_party/skia/src/gpu/GrSurfaceProxy.cpp
index 4df6c3302db..23580b2a5e4 100644
--- a/chromium/third_party/skia/src/gpu/GrSurfaceProxy.cpp
+++ b/chromium/third_party/skia/src/gpu/GrSurfaceProxy.cpp
@@ -106,9 +106,6 @@ GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface,
}
GrSurfaceProxy::~GrSurfaceProxy() {
- // For this to be deleted the opsTask that held a ref on it (if there was one) must have been
- // deleted. Which would have cleared out this back pointer.
- SkASSERT(!fLastRenderTask);
}
sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider,
@@ -219,21 +216,6 @@ void GrSurfaceProxy::computeScratchKey(const GrCaps& caps, GrScratchKey* key) co
renderable, sampleCount, mipMapped, fIsProtected, key);
}
-void GrSurfaceProxy::setLastRenderTask(GrRenderTask* renderTask) {
-#ifdef SK_DEBUG
- if (fLastRenderTask) {
- SkASSERT(fLastRenderTask->isClosed());
- }
-#endif
-
- // Un-reffed
- fLastRenderTask = renderTask;
-}
-
-GrOpsTask* GrSurfaceProxy::getLastOpsTask() {
- return fLastRenderTask ? fLastRenderTask->asOpsTask() : nullptr;
-}
-
SkISize GrSurfaceProxy::backingStoreDimensions() const {
SkASSERT(!this->isFullyLazy());
if (fTarget) {
@@ -259,7 +241,7 @@ bool GrSurfaceProxy::isFormatCompressed(const GrCaps* caps) const {
#ifdef SK_DEBUG
void GrSurfaceProxy::validate(GrContext_Base* context) const {
if (fTarget) {
- SkASSERT(fTarget->getContext() == context);
+ SkASSERT(fTarget->getContext()->priv().matches(context));
}
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrSurfaceProxy.h b/chromium/third_party/skia/src/gpu/GrSurfaceProxy.h
index 0bbd936127b..f30e21d10d4 100644
--- a/chromium/third_party/skia/src/gpu/GrSurfaceProxy.h
+++ b/chromium/third_party/skia/src/gpu/GrSurfaceProxy.h
@@ -268,11 +268,6 @@ public:
return fSurfaceFlags & GrInternalSurfaceFlags::kRequiresManualMSAAResolve;
}
- void setLastRenderTask(GrRenderTask*);
- GrRenderTask* getLastRenderTask() { return fLastRenderTask; }
-
- GrOpsTask* getLastOpsTask();
-
/**
* Retrieves the amount of GPU memory that will be or currently is used by this resource
* in bytes. It is approximate since we aren't aware of additional padding or copies made
@@ -436,15 +431,6 @@ private:
// If the proxy computes its own answer that answer is checked (in debug mode) in
// the instantiation method.
mutable size_t fGpuMemorySize;
-
- // The last GrRenderTask that wrote to or is currently going to write to this surface
- // The GrRenderTask can be closed (e.g., no surface context is currently bound
- // to this proxy).
- // This back-pointer is required so that we can add a dependancy between
- // the GrRenderTask used to create the current contents of this surface
- // and the GrRenderTask of a destination surface to which this one is being drawn or copied.
- // This pointer is unreffed. GrRenderTasks own a ref on their surface proxies.
- GrRenderTask* fLastRenderTask = nullptr;
};
GR_MAKE_BITFIELD_CLASS_OPS(GrSurfaceProxy::ResolveFlags)
diff --git a/chromium/third_party/skia/src/gpu/GrTextureProxy.cpp b/chromium/third_party/skia/src/gpu/GrTextureProxy.cpp
index fa7e064fa9a..d955712d209 100644
--- a/chromium/third_party/skia/src/gpu/GrTextureProxy.cpp
+++ b/chromium/third_party/skia/src/gpu/GrTextureProxy.cpp
@@ -24,10 +24,13 @@ GrTextureProxy::GrTextureProxy(const GrBackendFormat& format,
SkBudgeted budgeted,
GrProtected isProtected,
GrInternalSurfaceFlags surfaceFlags,
- UseAllocator useAllocator)
+ UseAllocator useAllocator,
+ GrDDLProvider creatingProvider)
: INHERITED(format, dimensions, fit, budgeted, isProtected, surfaceFlags, useAllocator)
, fMipMapped(mipMapped)
- , fMipMapsStatus(mipMapsStatus) SkDEBUGCODE(, fInitialMipMapsStatus(fMipMapsStatus))
+ , fMipMapsStatus(mipMapsStatus)
+ SkDEBUGCODE(, fInitialMipMapsStatus(fMipMapsStatus))
+ , fCreatingProvider(creatingProvider)
, fProxyProvider(nullptr)
, fDeferredUploader(nullptr) {
SkASSERT(!(fSurfaceFlags & GrInternalSurfaceFlags::kFramebufferOnly));
@@ -43,22 +46,28 @@ GrTextureProxy::GrTextureProxy(LazyInstantiateCallback&& callback,
SkBudgeted budgeted,
GrProtected isProtected,
GrInternalSurfaceFlags surfaceFlags,
- UseAllocator useAllocator)
+ UseAllocator useAllocator,
+ GrDDLProvider creatingProvider)
: INHERITED(std::move(callback), format, dimensions, fit, budgeted, isProtected,
surfaceFlags, useAllocator)
, fMipMapped(mipMapped)
- , fMipMapsStatus(mipMapsStatus) SkDEBUGCODE(, fInitialMipMapsStatus(fMipMapsStatus))
+ , fMipMapsStatus(mipMapsStatus)
+ SkDEBUGCODE(, fInitialMipMapsStatus(fMipMapsStatus))
+ , fCreatingProvider(creatingProvider)
, fProxyProvider(nullptr)
, fDeferredUploader(nullptr) {
SkASSERT(!(fSurfaceFlags & GrInternalSurfaceFlags::kFramebufferOnly));
}
// Wrapped version
-GrTextureProxy::GrTextureProxy(sk_sp<GrSurface> surf, UseAllocator useAllocator)
+GrTextureProxy::GrTextureProxy(sk_sp<GrSurface> surf,
+ UseAllocator useAllocator,
+ GrDDLProvider creatingProvider)
: INHERITED(std::move(surf), SkBackingFit::kExact, useAllocator)
, fMipMapped(fTarget->asTexture()->texturePriv().mipMapped())
, fMipMapsStatus(fTarget->asTexture()->texturePriv().mipMapsStatus())
- SkDEBUGCODE(, fInitialMipMapsStatus(fMipMapsStatus))
+ SkDEBUGCODE(, fInitialMipMapsStatus(fMipMapsStatus))
+ , fCreatingProvider(creatingProvider)
, fProxyProvider(nullptr)
, fDeferredUploader(nullptr) {
if (fTarget->getUniqueKey().isValid()) {
diff --git a/chromium/third_party/skia/src/gpu/GrTextureProxy.h b/chromium/third_party/skia/src/gpu/GrTextureProxy.h
index 06afa9a08ce..7781cc2309f 100644
--- a/chromium/third_party/skia/src/gpu/GrTextureProxy.h
+++ b/chromium/third_party/skia/src/gpu/GrTextureProxy.h
@@ -73,7 +73,8 @@ public:
*/
const GrUniqueKey& getUniqueKey() const {
#ifdef SK_DEBUG
- if (this->isInstantiated() && fUniqueKey.isValid() && fSyncTargetKey) {
+ if (this->isInstantiated() && fUniqueKey.isValid() && fSyncTargetKey &&
+ fCreatingProvider == GrDDLProvider::kNo) {
GrSurface* surface = this->peekSurface();
SkASSERT(surface);
@@ -100,6 +101,8 @@ public:
GrTextureProxyPriv texPriv();
const GrTextureProxyPriv texPriv() const;
+ SkDEBUGCODE(GrDDLProvider creatingProvider() const { return fCreatingProvider; })
+
protected:
// DDL TODO: rm the GrSurfaceProxy friending
friend class GrSurfaceProxy; // for ctors
@@ -116,7 +119,8 @@ protected:
SkBudgeted,
GrProtected,
GrInternalSurfaceFlags,
- UseAllocator);
+ UseAllocator,
+ GrDDLProvider creatingProvider);
// Lazy-callback version
// There are two main use cases for lazily-instantiated proxies:
@@ -137,15 +141,19 @@ protected:
SkBudgeted,
GrProtected,
GrInternalSurfaceFlags,
- UseAllocator);
+ UseAllocator,
+ GrDDLProvider creatingProvider);
// Wrapped version
- GrTextureProxy(sk_sp<GrSurface>, UseAllocator);
+ GrTextureProxy(sk_sp<GrSurface>, UseAllocator, GrDDLProvider creatingProvider);
~GrTextureProxy() override;
sk_sp<GrSurface> createSurface(GrResourceProvider*) const override;
+ // By default uniqueKeys are propagated from a textureProxy to its backing GrTexture.
+ // Setting syncTargetKey to false disables this behavior and only keeps the unique key
+ // on the proxy.
void setTargetKeySync(bool sync) { fSyncTargetKey = sync; }
private:
@@ -173,6 +181,12 @@ private:
bool fSyncTargetKey = true; // Should target's unique key be sync'ed with ours.
+ // For GrTextureProxies created in a DDL recording thread it is possible for the uniqueKey
+ // to be cleared on the backing GrTexture while the uniqueKey remains on the proxy.
+ // A fCreatingProvider of DDLProvider::kYes loosens up asserts that the key of an instantiated
+ // uniquely-keyed textureProxy is also always set on the backing GrTexture.
+ GrDDLProvider fCreatingProvider = GrDDLProvider::kNo;
+
GrUniqueKey fUniqueKey;
GrProxyProvider* fProxyProvider; // only set when fUniqueKey is valid
diff --git a/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.cpp b/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.cpp
index e7b6e186691..7dbd304e7dd 100644
--- a/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.cpp
+++ b/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.cpp
@@ -30,13 +30,14 @@ GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(const GrCaps& caps,
SkBudgeted budgeted,
GrProtected isProtected,
GrInternalSurfaceFlags surfaceFlags,
- UseAllocator useAllocator)
+ UseAllocator useAllocator,
+ GrDDLProvider creatingProvider)
: GrSurfaceProxy(format, dimensions, fit, budgeted, isProtected, surfaceFlags, useAllocator)
// for now textures w/ data are always wrapped
, GrRenderTargetProxy(caps, format, dimensions, sampleCnt, fit, budgeted, isProtected,
surfaceFlags, useAllocator)
, GrTextureProxy(format, dimensions, mipMapped, mipMapsStatus, fit, budgeted, isProtected,
- surfaceFlags, useAllocator) {
+ surfaceFlags, useAllocator, creatingProvider) {
this->initSurfaceFlags(caps);
}
@@ -52,7 +53,8 @@ GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(const GrCaps& caps,
SkBudgeted budgeted,
GrProtected isProtected,
GrInternalSurfaceFlags surfaceFlags,
- UseAllocator useAllocator)
+ UseAllocator useAllocator,
+ GrDDLProvider creatingProvider)
: GrSurfaceProxy(std::move(callback), format, dimensions, fit, budgeted, isProtected,
surfaceFlags, useAllocator)
// Since we have virtual inheritance, we initialize GrSurfaceProxy directly. Send null
@@ -61,7 +63,8 @@ GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(const GrCaps& caps,
budgeted, isProtected, surfaceFlags, useAllocator,
WrapsVkSecondaryCB::kNo)
, GrTextureProxy(LazyInstantiateCallback(), format, dimensions, mipMapped, mipMapsStatus,
- fit, budgeted, isProtected, surfaceFlags, useAllocator) {
+ fit, budgeted, isProtected, surfaceFlags, useAllocator,
+ creatingProvider) {
this->initSurfaceFlags(caps);
}
@@ -69,10 +72,11 @@ GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(const GrCaps& caps,
// This class is virtually derived from GrSurfaceProxy (via both GrTextureProxy and
// GrRenderTargetProxy) so its constructor must be explicitly called.
GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(sk_sp<GrSurface> surf,
- UseAllocator useAllocator)
+ UseAllocator useAllocator,
+ GrDDLProvider creatingProvider)
: GrSurfaceProxy(surf, SkBackingFit::kExact, useAllocator)
, GrRenderTargetProxy(surf, useAllocator)
- , GrTextureProxy(surf, useAllocator) {
+ , GrTextureProxy(surf, useAllocator, creatingProvider) {
SkASSERT(surf->asTexture());
SkASSERT(surf->asRenderTarget());
SkASSERT(fSurfaceFlags == fTarget->surfacePriv().flags());
diff --git a/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.h b/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.h
index 585f60c63d9..4eb81f25f89 100644
--- a/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.h
+++ b/chromium/third_party/skia/src/gpu/GrTextureRenderTargetProxy.h
@@ -38,7 +38,8 @@ private:
SkBudgeted,
GrProtected,
GrInternalSurfaceFlags,
- UseAllocator);
+ UseAllocator,
+ GrDDLProvider creatingProvider);
// Lazy-callback version
GrTextureRenderTargetProxy(const GrCaps&,
@@ -52,11 +53,13 @@ private:
SkBudgeted,
GrProtected,
GrInternalSurfaceFlags,
- UseAllocator);
+ UseAllocator,
+ GrDDLProvider creatingProvider);
// Wrapped version
GrTextureRenderTargetProxy(sk_sp<GrSurface>,
- UseAllocator);
+ UseAllocator,
+ GrDDLProvider creatingProvider);
void initSurfaceFlags(const GrCaps&);
diff --git a/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.cpp b/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.cpp
index 8d67c035321..1a915bad9db 100644
--- a/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.cpp
+++ b/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.cpp
@@ -14,28 +14,24 @@
#include "src/gpu/GrResourceAllocator.h"
#include "src/gpu/GrTexturePriv.h"
-GrTextureResolveRenderTask::~GrTextureResolveRenderTask() {
- for (const auto& resolve : fResolves) {
- // Ensure the proxy doesn't keep hold of a dangling back pointer.
- resolve.fProxy->setLastRenderTask(nullptr);
- }
-}
-
-void GrTextureResolveRenderTask::addProxy(
- sk_sp<GrSurfaceProxy> proxyRef, GrSurfaceProxy::ResolveFlags flags, const GrCaps& caps) {
- fResolves.emplace_back(std::move(proxyRef), flags);
- GrSurfaceProxy* proxy = fResolves.back().fProxy.get();
+void GrTextureResolveRenderTask::addProxy(GrDrawingManager* drawingMgr,
+ sk_sp<GrSurfaceProxy> proxyRef,
+ GrSurfaceProxy::ResolveFlags flags,
+ const GrCaps& caps) {
+ Resolve& resolve = fResolves.emplace_back(flags);
+ GrSurfaceProxy* proxy = proxyRef.get();
// Ensure the last render task that operated on the proxy is closed. That's where msaa and
// mipmaps should have been marked dirty.
- SkASSERT(!proxy->getLastRenderTask() || proxy->getLastRenderTask()->isClosed());
+ SkASSERT(!drawingMgr->getLastRenderTask(proxy)
+ || drawingMgr->getLastRenderTask(proxy)->isClosed());
SkASSERT(GrSurfaceProxy::ResolveFlags::kNone != flags);
if (GrSurfaceProxy::ResolveFlags::kMSAA & flags) {
GrRenderTargetProxy* renderTargetProxy = proxy->asRenderTargetProxy();
SkASSERT(renderTargetProxy);
SkASSERT(renderTargetProxy->isMSAADirty());
- fResolves.back().fMSAAResolveRect = renderTargetProxy->msaaDirtyRect();
+ resolve.fMSAAResolveRect = renderTargetProxy->msaaDirtyRect();
renderTargetProxy->markMSAAResolved();
}
@@ -48,8 +44,9 @@ void GrTextureResolveRenderTask::addProxy(
// Add the proxy as a dependency: We will read the existing contents of this texture while
// generating mipmap levels and/or resolving MSAA.
- this->addDependency(proxy, GrMipMapped::kNo, GrTextureResolveManager(nullptr), caps);
- proxy->setLastRenderTask(this);
+ this->addDependency(drawingMgr, proxy, GrMipMapped::kNo,
+ GrTextureResolveManager(nullptr), caps);
+ this->addTarget(drawingMgr, GrSurfaceProxyView(std::move(proxyRef)));
}
void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
@@ -57,8 +54,9 @@ void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc
// fEndOfOpsTaskOpIndices will remain in sync. We create fake op#'s to capture the fact that we
// manipulate the resolve proxies.
auto fakeOp = alloc->curOp();
- for (const auto& resolve : fResolves) {
- alloc->addInterval(resolve.fProxy.get(), fakeOp, fakeOp,
+ SkASSERT(fResolves.count() == this->numTargets());
+ for (const GrSurfaceProxyView& target : fTargets) {
+ alloc->addInterval(target.proxy(), fakeOp, fakeOp,
GrResourceAllocator::ActualUse::kYes);
}
alloc->incOps();
@@ -66,9 +64,11 @@ void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc
bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) {
// Resolve all msaa back-to-back, before regenerating mipmaps.
- for (const auto& resolve : fResolves) {
+ SkASSERT(fResolves.count() == this->numTargets());
+ for (int i = 0; i < fResolves.count(); ++i) {
+ const Resolve& resolve = fResolves[i];
if (GrSurfaceProxy::ResolveFlags::kMSAA & resolve.fFlags) {
- GrSurfaceProxy* proxy = resolve.fProxy.get();
+ GrSurfaceProxy* proxy = this->target(i).proxy();
// peekRenderTarget might be null if there was an instantiation error.
if (GrRenderTarget* renderTarget = proxy->peekRenderTarget()) {
flushState->gpu()->resolveRenderTarget(renderTarget, resolve.fMSAAResolveRect,
@@ -77,10 +77,11 @@ bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) {
}
}
// Regenerate all mipmaps back-to-back.
- for (const auto& resolve : fResolves) {
+ for (int i = 0; i < fResolves.count(); ++i) {
+ const Resolve& resolve = fResolves[i];
if (GrSurfaceProxy::ResolveFlags::kMipMaps & resolve.fFlags) {
// peekTexture might be null if there was an instantiation error.
- GrTexture* texture = resolve.fProxy->peekTexture();
+ GrTexture* texture = this->target(i).proxy()->peekTexture();
if (texture && texture->texturePriv().mipMapsAreDirty()) {
flushState->gpu()->regenerateMipMapLevels(texture);
SkASSERT(!texture->texturePriv().mipMapsAreDirty());
@@ -92,9 +93,5 @@ bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) {
}
#ifdef SK_DEBUG
-void GrTextureResolveRenderTask::visitProxies_debugOnly(const GrOp::VisitProxyFunc& fn) const {
- for (const auto& resolve : fResolves) {
- fn(resolve.fProxy.get(), GrMipMapped::kNo);
- }
-}
+void GrTextureResolveRenderTask::visitProxies_debugOnly(const GrOp::VisitProxyFunc& fn) const {}
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.h b/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.h
index e9ce954ca5c..379aa4b3453 100644
--- a/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.h
+++ b/chromium/third_party/skia/src/gpu/GrTextureResolveRenderTask.h
@@ -13,14 +13,12 @@
class GrTextureResolveRenderTask final : public GrRenderTask {
public:
GrTextureResolveRenderTask() : GrRenderTask() {}
- ~GrTextureResolveRenderTask() override;
- void addProxy(sk_sp<GrSurfaceProxy> proxy, GrSurfaceProxy::ResolveFlags, const GrCaps&);
+ void addProxy(GrDrawingManager*, sk_sp<GrSurfaceProxy> proxy,
+ GrSurfaceProxy::ResolveFlags, const GrCaps&);
private:
bool onIsUsed(GrSurfaceProxy* proxy) const override {
- // This case should be handled by GrRenderTask.
- SkASSERT(proxy != fTargetView.proxy());
return false;
}
void handleInternalAllocationFailure() override {
@@ -40,9 +38,7 @@ private:
#endif
struct Resolve {
- Resolve(sk_sp<GrSurfaceProxy> proxy, GrSurfaceProxy::ResolveFlags flags)
- : fProxy(std::move(proxy)), fFlags(flags) {}
- sk_sp<GrSurfaceProxy> fProxy;
+ Resolve(GrSurfaceProxy::ResolveFlags flags) : fFlags(flags) {}
GrSurfaceProxy::ResolveFlags fFlags;
SkIRect fMSAAResolveRect;
};
diff --git a/chromium/third_party/skia/src/gpu/GrTransferFromRenderTask.h b/chromium/third_party/skia/src/gpu/GrTransferFromRenderTask.h
index 2126ae81a86..93a0f7aad31 100644
--- a/chromium/third_party/skia/src/gpu/GrTransferFromRenderTask.h
+++ b/chromium/third_party/skia/src/gpu/GrTransferFromRenderTask.h
@@ -28,7 +28,7 @@ public:
private:
bool onIsUsed(GrSurfaceProxy* proxy) const override {
- SkASSERT(!fTargetView.proxy());
+ SkASSERT(0 == this->numTargets());
return proxy == fSrcProxy.get();
}
// If fSrcProxy is uninstantiated at flush time we simply will skip doing the transfer.
diff --git a/chromium/third_party/skia/src/gpu/GrTriangulator.cpp b/chromium/third_party/skia/src/gpu/GrTriangulator.cpp
index b2b2af31add..f695d6ee2dc 100644
--- a/chromium/third_party/skia/src/gpu/GrTriangulator.cpp
+++ b/chromium/third_party/skia/src/gpu/GrTriangulator.cpp
@@ -2400,13 +2400,13 @@ int get_contour_count(const SkPath& path, SkScalar tolerance) {
if (!first) {
++contourCnt;
}
- // fallthru.
+ [[fallthrough]];
case SkPath::kLine_Verb:
case SkPath::kConic_Verb:
case SkPath::kQuad_Verb:
case SkPath::kCubic_Verb:
hasPoints = true;
- // fallthru to break.
+ break;
default:
break;
}
diff --git a/chromium/third_party/skia/src/gpu/GrUniformDataManager.cpp b/chromium/third_party/skia/src/gpu/GrUniformDataManager.cpp
new file mode 100644
index 00000000000..549057a3d5a
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrUniformDataManager.cpp
@@ -0,0 +1,319 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/GrUniformDataManager.h"
+
+#include "src/gpu/GrShaderVar.h"
+
+GrUniformDataManager::GrUniformDataManager(uint32_t uniformCount, uint32_t uniformSize)
+ : fUniformSize(uniformSize)
+ , fUniformsDirty(false) {
+ fUniformData.reset(uniformSize);
+ fUniforms.push_back_n(uniformCount);
+ // subclasses fill in the uniforms in their constructor
+}
+
+void* GrUniformDataManager::getBufferPtrAndMarkDirty(const Uniform& uni) const {
+ fUniformsDirty = true;
+ return static_cast<char*>(fUniformData.get())+uni.fOffset;
+}
+
+void GrUniformDataManager::set1i(UniformHandle u, int32_t i) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
+ SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ memcpy(buffer, &i, sizeof(int32_t));
+}
+
+void GrUniformDataManager::set1iv(UniformHandle u,
+ int arrayCount,
+ const int32_t v[]) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
+ SkASSERT(arrayCount > 0);
+ SkASSERT(arrayCount <= uni.fArrayCount ||
+ (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
+
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ SkASSERT(sizeof(int32_t) == 4);
+ for (int i = 0; i < arrayCount; ++i) {
+ const int32_t* curVec = &v[i];
+ memcpy(buffer, curVec, sizeof(int32_t));
+ buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t);
+ }
+}
+
+void GrUniformDataManager::set1f(UniformHandle u, float v0) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kFloat_GrSLType || uni.fType == kHalf_GrSLType);
+ SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ SkASSERT(sizeof(float) == 4);
+ memcpy(buffer, &v0, sizeof(float));
+}
+
+void GrUniformDataManager::set1fv(UniformHandle u,
+ int arrayCount,
+ const float v[]) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kFloat_GrSLType || uni.fType == kHalf_GrSLType);
+ SkASSERT(arrayCount > 0);
+ SkASSERT(arrayCount <= uni.fArrayCount ||
+ (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
+
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ SkASSERT(sizeof(float) == 4);
+ for (int i = 0; i < arrayCount; ++i) {
+ const float* curVec = &v[i];
+ memcpy(buffer, curVec, sizeof(float));
+ buffer = static_cast<char*>(buffer) + 4*sizeof(float);
+ }
+}
+
+void GrUniformDataManager::set2i(UniformHandle u, int32_t i0, int32_t i1) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kInt2_GrSLType || uni.fType == kShort2_GrSLType);
+ SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ int32_t v[2] = { i0, i1 };
+ memcpy(buffer, v, 2 * sizeof(int32_t));
+}
+
+void GrUniformDataManager::set2iv(UniformHandle u,
+ int arrayCount,
+ const int32_t v[]) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kInt2_GrSLType || uni.fType == kShort2_GrSLType);
+ SkASSERT(arrayCount > 0);
+ SkASSERT(arrayCount <= uni.fArrayCount ||
+ (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
+
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ SkASSERT(sizeof(int32_t) == 4);
+ for (int i = 0; i < arrayCount; ++i) {
+ const int32_t* curVec = &v[2 * i];
+ memcpy(buffer, curVec, 2 * sizeof(int32_t));
+ buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t);
+ }
+}
+
+void GrUniformDataManager::set2f(UniformHandle u, float v0, float v1) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
+ SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ SkASSERT(sizeof(float) == 4);
+ float v[2] = { v0, v1 };
+ memcpy(buffer, v, 2 * sizeof(float));
+}
+
+void GrUniformDataManager::set2fv(UniformHandle u,
+ int arrayCount,
+ const float v[]) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
+ SkASSERT(arrayCount > 0);
+ SkASSERT(arrayCount <= uni.fArrayCount ||
+ (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
+
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ SkASSERT(sizeof(float) == 4);
+ for (int i = 0; i < arrayCount; ++i) {
+ const float* curVec = &v[2 * i];
+ memcpy(buffer, curVec, 2 * sizeof(float));
+ buffer = static_cast<char*>(buffer) + 4*sizeof(float);
+ }
+}
+
+void GrUniformDataManager::set3i(UniformHandle u,
+ int32_t i0,
+ int32_t i1,
+ int32_t i2) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kInt3_GrSLType || uni.fType == kShort3_GrSLType);
+ SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ int32_t v[3] = { i0, i1, i2 };
+ memcpy(buffer, v, 3 * sizeof(int32_t));
+}
+
+void GrUniformDataManager::set3iv(UniformHandle u,
+ int arrayCount,
+ const int32_t v[]) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kInt3_GrSLType || uni.fType == kShort3_GrSLType);
+ SkASSERT(arrayCount > 0);
+ SkASSERT(arrayCount <= uni.fArrayCount ||
+ (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
+
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ SkASSERT(sizeof(int32_t) == 4);
+ for (int i = 0; i < arrayCount; ++i) {
+ const int32_t* curVec = &v[3 * i];
+ memcpy(buffer, curVec, 3 * sizeof(int32_t));
+ buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t);
+ }
+}
+
+void GrUniformDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
+ SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ SkASSERT(sizeof(float) == 4);
+ float v[3] = { v0, v1, v2 };
+ memcpy(buffer, v, 3 * sizeof(float));
+}
+
+void GrUniformDataManager::set3fv(UniformHandle u,
+ int arrayCount,
+ const float v[]) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
+ SkASSERT(arrayCount > 0);
+ SkASSERT(arrayCount <= uni.fArrayCount ||
+ (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
+
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ SkASSERT(sizeof(float) == 4);
+ for (int i = 0; i < arrayCount; ++i) {
+ const float* curVec = &v[3 * i];
+ memcpy(buffer, curVec, 3 * sizeof(float));
+ buffer = static_cast<char*>(buffer) + 4*sizeof(float);
+ }
+}
+
+void GrUniformDataManager::set4i(UniformHandle u,
+ int32_t i0,
+ int32_t i1,
+ int32_t i2,
+ int32_t i3) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kInt4_GrSLType || uni.fType == kShort4_GrSLType);
+ SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ int32_t v[4] = { i0, i1, i2, i3 };
+ memcpy(buffer, v, 4 * sizeof(int32_t));
+}
+
+void GrUniformDataManager::set4iv(UniformHandle u,
+ int arrayCount,
+ const int32_t v[]) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kInt4_GrSLType || uni.fType == kShort4_GrSLType);
+ SkASSERT(arrayCount > 0);
+ SkASSERT(arrayCount <= uni.fArrayCount ||
+ (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
+
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ SkASSERT(sizeof(int32_t) == 4);
+ for (int i = 0; i < arrayCount; ++i) {
+ const int32_t* curVec = &v[4 * i];
+ memcpy(buffer, curVec, 4 * sizeof(int32_t));
+ buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t);
+ }
+}
+
+void GrUniformDataManager::set4f(UniformHandle u,
+ float v0,
+ float v1,
+ float v2,
+ float v3) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
+ SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ SkASSERT(sizeof(float) == 4);
+ float v[4] = { v0, v1, v2, v3 };
+ memcpy(buffer, v, 4 * sizeof(float));
+}
+
+void GrUniformDataManager::set4fv(UniformHandle u,
+ int arrayCount,
+ const float v[]) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
+ SkASSERT(arrayCount > 0);
+ SkASSERT(arrayCount <= uni.fArrayCount ||
+ (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
+
+ void* buffer = this->getBufferPtrAndMarkDirty(uni);
+ SkASSERT(sizeof(float) == 4);
+ memcpy(buffer, v, arrayCount * 4 * sizeof(float));
+}
+
+void GrUniformDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const {
+ this->setMatrices<2>(u, 1, matrix);
+}
+
+void GrUniformDataManager::setMatrix2fv(UniformHandle u,
+ int arrayCount,
+ const float m[]) const {
+ this->setMatrices<2>(u, arrayCount, m);
+}
+
+void GrUniformDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const {
+ this->setMatrices<3>(u, 1, matrix);
+}
+
+void GrUniformDataManager::setMatrix3fv(UniformHandle u,
+ int arrayCount,
+ const float m[]) const {
+ this->setMatrices<3>(u, arrayCount, m);
+}
+
+void GrUniformDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const {
+ this->setMatrices<4>(u, 1, matrix);
+}
+
+void GrUniformDataManager::setMatrix4fv(UniformHandle u,
+ int arrayCount,
+ const float m[]) const {
+ this->setMatrices<4>(u, arrayCount, m);
+}
+
+template<int N> struct set_uniform_matrix;
+
+template<int N> inline void GrUniformDataManager::setMatrices(UniformHandle u,
+ int arrayCount,
+ const float matrices[]) const {
+ const Uniform& uni = fUniforms[u.toIndex()];
+ SkASSERT(uni.fType == kFloat2x2_GrSLType + (N - 2) ||
+ uni.fType == kHalf2x2_GrSLType + (N - 2));
+ SkASSERT(arrayCount > 0);
+ SkASSERT(arrayCount <= uni.fArrayCount ||
+ (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
+
+ void* buffer = fUniformData.get();
+ fUniformsDirty = true;
+
+ set_uniform_matrix<N>::set(buffer, uni.fOffset, arrayCount, matrices);
+}
+
+template<int N> struct set_uniform_matrix {
+ inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) {
+ static_assert(sizeof(float) == 4);
+ buffer = static_cast<char*>(buffer) + uniformOffset;
+ for (int i = 0; i < count; ++i) {
+ const float* matrix = &matrices[N * N * i];
+ for (int j = 0; j < N; ++j) {
+ memcpy(buffer, &matrix[j * N], N * sizeof(float));
+ buffer = static_cast<char*>(buffer) + 4 * sizeof(float);
+ }
+ }
+ }
+};
+
+template<> struct set_uniform_matrix<4> {
+ inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) {
+ static_assert(sizeof(float) == 4);
+ buffer = static_cast<char*>(buffer) + uniformOffset;
+ memcpy(buffer, matrices, count * 16 * sizeof(float));
+ }
+};
+
diff --git a/chromium/third_party/skia/src/gpu/GrUniformDataManager.h b/chromium/third_party/skia/src/gpu/GrUniformDataManager.h
new file mode 100644
index 00000000000..dc08bcf0d2b
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrUniformDataManager.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrUniformDataManager_DEFINED
+#define GrUniformDataManager_DEFINED
+
+#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
+
+#include "include/private/GrTypesPriv.h"
+#include "include/private/SkTArray.h"
+#include "src/core/SkAutoMalloc.h"
+
+class GrUniformDataManager : public GrGLSLProgramDataManager {
+public:
+ GrUniformDataManager(uint32_t uniformCount, uint32_t uniformSize);
+
+ void set1i(UniformHandle, int32_t) const override;
+ void set1iv(UniformHandle, int arrayCount, const int32_t v[]) const override;
+ void set1f(UniformHandle, float v0) const override;
+ void set1fv(UniformHandle, int arrayCount, const float v[]) const override;
+ void set2i(UniformHandle, int32_t, int32_t) const override;
+ void set2iv(UniformHandle, int arrayCount, const int32_t v[]) const override;
+ void set2f(UniformHandle, float, float) const override;
+ void set2fv(UniformHandle, int arrayCount, const float v[]) const override;
+ void set3i(UniformHandle, int32_t, int32_t, int32_t) const override;
+ void set3iv(UniformHandle, int arrayCount, const int32_t v[]) const override;
+ void set3f(UniformHandle, float, float, float) const override;
+ void set3fv(UniformHandle, int arrayCount, const float v[]) const override;
+ void set4i(UniformHandle, int32_t, int32_t, int32_t, int32_t) const override;
+ void set4iv(UniformHandle, int arrayCount, const int32_t v[]) const override;
+ void set4f(UniformHandle, float, float, float, float) const override;
+ void set4fv(UniformHandle, int arrayCount, const float v[]) const override;
+ // matrices are column-major, the first two upload a single matrix, the latter two upload
+ // arrayCount matrices into a uniform array.
+ void setMatrix2f(UniformHandle, const float matrix[]) const override;
+ void setMatrix3f(UniformHandle, const float matrix[]) const override;
+ void setMatrix4f(UniformHandle, const float matrix[]) const override;
+ void setMatrix2fv(UniformHandle, int arrayCount, const float matrices[]) const override;
+ void setMatrix3fv(UniformHandle, int arrayCount, const float matrices[]) const override;
+ void setMatrix4fv(UniformHandle, int arrayCount, const float matrices[]) const override;
+
+ // for nvpr only
+ void setPathFragmentInputTransform(VaryingHandle u, int components,
+ const SkMatrix& matrix) const override {
+ SK_ABORT("Only supported in NVPR, which is only available in GL");
+ }
+
+ // For the uniform data to be dirty so that we will reupload on the next use.
+ void markDirty() { fUniformsDirty = true; }
+
+protected:
+ struct Uniform {
+ uint32_t fOffset;
+ SkDEBUGCODE(
+ GrSLType fType;
+ int fArrayCount;
+ );
+ };
+
+ template<int N> inline void setMatrices(UniformHandle, int arrayCount,
+ const float matrices[]) const;
+
+ void* getBufferPtrAndMarkDirty(const Uniform& uni) const;
+
+ uint32_t fUniformSize;
+
+ SkTArray<Uniform, true> fUniforms;
+
+ mutable SkAutoMalloc fUniformData;
+ mutable bool fUniformsDirty;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrWaitRenderTask.cpp b/chromium/third_party/skia/src/gpu/GrWaitRenderTask.cpp
index d7b2a7cc081..d9740301760 100644
--- a/chromium/third_party/skia/src/gpu/GrWaitRenderTask.cpp
+++ b/chromium/third_party/skia/src/gpu/GrWaitRenderTask.cpp
@@ -14,15 +14,22 @@
void GrWaitRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
// This renderTask doesn't have "normal" ops. In this case we still need to add an interval (so
// fEndOfOpsTaskOpIndices will remain in sync), so we create a fake op# to capture the fact that
- // we manipulate fTargetView's proxy.
- alloc->addInterval(fTargetView.proxy(), alloc->curOp(), alloc->curOp(),
+ // we manipulate our target's proxy.
+ SkASSERT(0 == this->numTargets());
+ auto fakeOp = alloc->curOp();
+ alloc->addInterval(fWaitedOn.proxy(), fakeOp, fakeOp,
GrResourceAllocator::ActualUse::kYes);
alloc->incOps();
}
bool GrWaitRenderTask::onExecute(GrOpFlushState* flushState) {
for (int i = 0; i < fNumSemaphores; ++i) {
- flushState->gpu()->waitSemaphore(fSemaphores[i].get());
+ // If we don't have a semaphore here it means we failed to wrap it. That happens if the
+ // client didn't give us a valid semaphore to begin with. Therefore, it is fine to not wait
+ // on it.
+ if (fSemaphores[i].get()) {
+ flushState->gpu()->waitSemaphore(fSemaphores[i].get());
+ }
}
return true;
}
diff --git a/chromium/third_party/skia/src/gpu/GrWaitRenderTask.h b/chromium/third_party/skia/src/gpu/GrWaitRenderTask.h
index 18e715755c8..4681f76209f 100644
--- a/chromium/third_party/skia/src/gpu/GrWaitRenderTask.h
+++ b/chromium/third_party/skia/src/gpu/GrWaitRenderTask.h
@@ -16,15 +16,14 @@ public:
GrWaitRenderTask(GrSurfaceProxyView surfaceView,
std::unique_ptr<std::unique_ptr<GrSemaphore>[]> semaphores,
int numSemaphores)
- : GrRenderTask(std::move(surfaceView))
+ : GrRenderTask()
, fSemaphores(std::move(semaphores))
- , fNumSemaphores(numSemaphores) {}
+ , fNumSemaphores(numSemaphores)
+ , fWaitedOn(std::move(surfaceView)) {}
private:
bool onIsUsed(GrSurfaceProxy* proxy) const override {
- // This case should be handled by GrRenderTask.
- SkASSERT(proxy != fTargetView.proxy());
- return false;
+ return proxy == fWaitedOn.proxy();
}
void handleInternalAllocationFailure() override {}
void gatherProxyIntervals(GrResourceAllocator*) const override;
@@ -42,6 +41,11 @@ private:
#endif
std::unique_ptr<std::unique_ptr<GrSemaphore>[]> fSemaphores;
int fNumSemaphores;
+
+ // This field is separate from the main "targets" field on GrRenderTask because this task
+ // does not actually write to the surface and so should not participate in the normal
+ // lastRenderTask tracking that written-to targets do.
+ GrSurfaceProxyView fWaitedOn;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrYUVProvider.cpp b/chromium/third_party/skia/src/gpu/GrYUVProvider.cpp
index 6a25a79562b..3d5668c6f30 100644
--- a/chromium/third_party/skia/src/gpu/GrYUVProvider.cpp
+++ b/chromium/third_party/skia/src/gpu/GrYUVProvider.cpp
@@ -16,7 +16,6 @@
#include "src/core/SkYUVPlanesCache.h"
#include "src/gpu/GrBitmapTextureMaker.h"
#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrColorSpaceXform.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
@@ -191,7 +190,7 @@ GrSurfaceProxyView GrYUVProvider::refAsTextureProxyView(GrRecordingContext* ctx,
yuvSizeInfo.fSizes[0].fHeight);
SkMatrix m = SkEncodedOriginToMatrix(yuvSizeInfo.fOrigin, r.width(), r.height());
- renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, m, r);
+ renderTargetContext->drawRect(nullptr, std::move(paint), GrAA::kNo, m, r);
SkASSERT(renderTargetContext->asTextureProxy());
return renderTargetContext->readSurfaceView();
diff --git a/chromium/third_party/skia/src/gpu/SkGpuDevice.cpp b/chromium/third_party/skia/src/gpu/SkGpuDevice.cpp
index fcd15fa7aad..aa949a3acc3 100644
--- a/chromium/third_party/skia/src/gpu/SkGpuDevice.cpp
+++ b/chromium/third_party/skia/src/gpu/SkGpuDevice.cpp
@@ -48,8 +48,7 @@
#include "src/image/SkSurface_Gpu.h"
#include "src/utils/SkUTF.h"
-#define ASSERT_SINGLE_OWNER \
-SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->priv().singleOwner());)
+#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fContext->priv().singleOwner())
///////////////////////////////////////////////////////////////////////////////
@@ -125,7 +124,8 @@ SkGpuDevice::SkGpuDevice(GrContext* context,
: INHERITED(make_info(renderTargetContext.get(), SkToBool(flags & kIsOpaque_Flag)),
renderTargetContext->surfaceProps())
, fContext(SkRef(context))
- , fRenderTargetContext(std::move(renderTargetContext)) {
+ , fRenderTargetContext(std::move(renderTargetContext))
+ , fClip(fRenderTargetContext->dimensions(), &this->cs(), &this->asMatrixProvider()) {
if (flags & kNeedClear_Flag) {
this->clearAll();
}
@@ -209,8 +209,7 @@ void SkGpuDevice::clearAll() {
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "clearAll", fContext.get());
SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
- fRenderTargetContext->clear(&rect, SK_PMColor4fTRANSPARENT,
- GrRenderTargetContext::CanClearFullscreen::kYes);
+ fRenderTargetContext->priv().clearAtLeast(rect, SK_PMColor4fTRANSPARENT);
}
void SkGpuDevice::replaceRenderTargetContext(std::unique_ptr<GrRenderTargetContext> rtc,
@@ -325,13 +324,12 @@ void SkGpuDevice::drawPoints(SkCanvas::PointMode mode,
const SkMatrixProvider* matrixProvider = this;
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
- SkTLazy<SkPostConcatMatrixProvider> postConcatMatrixProvider;
+ SkTLazy<SkPostTranslateMatrixProvider> postTranslateMatrixProvider;
// This offsetting in device space matches the expectations of the Android framework for non-AA
// points and lines.
if (GrIsPrimTypeLines(primitiveType) || GrPrimitiveType::kPoints == primitiveType) {
static const SkScalar kOffset = 0.063f; // Just greater than 1/16.
- matrixProvider = postConcatMatrixProvider.init(*matrixProvider,
- SkMatrix::MakeTrans(kOffset, kOffset));
+ matrixProvider = postTranslateMatrixProvider.init(*matrixProvider, kOffset, kOffset);
}
#endif
@@ -630,8 +628,7 @@ void SkGpuDevice::drawPath(const SkPath& origSrcPath, const SkPaint& paint, bool
paint, this->asMatrixProvider(), shape);
}
-void SkGpuDevice::drawSpecial(SkSpecialImage* special, int left, int top, const SkPaint& paint,
- SkImage* clipImage, const SkMatrix& clipMatrix) {
+void SkGpuDevice::drawSpecial(SkSpecialImage* special, int left, int top, const SkPaint& paint) {
SkASSERT(!paint.getMaskFilter());
ASSERT_SINGLE_OWNER
@@ -687,55 +684,7 @@ void SkGpuDevice::drawSpecial(SkSpecialImage* special, int left, int top, const
const SkIRect& subset = result->subset();
SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(left, top, subset.width(), subset.height()));
SkRect srcRect = SkRect::Make(subset);
- if (clipImage) {
- // Add the image as a simple texture effect applied to coverage. Accessing content outside
- // of the clip image should behave as if it were a decal (i.e. zero coverage). However, to
- // limit pixels touched and hardware checks, we draw the clip image geometry to get the
- // decal effect.
- auto filter = paint.getFilterQuality() > kNone_SkFilterQuality
- ? GrSamplerState::Filter::kBilerp
- : GrSamplerState::Filter::kNearest;
- GrSurfaceProxyView clipView = as_IB(clipImage)->refView(this->context(), GrMipMapped::kNo);
- // Fold clip matrix into ctm
- ctm.preConcat(clipMatrix);
- SkMatrix inverseClipMatrix;
-
- std::unique_ptr<GrFragmentProcessor> cfp;
- if (clipView && ctm.invert(&inverseClipMatrix)) {
- GrColorType srcColorType = SkColorTypeToGrColorType(clipImage->colorType());
-
- cfp = GrTextureEffect::Make(std::move(clipView), clipImage->alphaType(),
- inverseClipMatrix, filter);
- if (srcColorType != GrColorType::kAlpha_8) {
- cfp = GrFragmentProcessor::SwizzleOutput(std::move(cfp), GrSwizzle::AAAA());
- }
- }
- if (cfp) {
- // If the grPaint already has coverage, this adds an additional stage that multiples
- // the image's alpha channel with the prior coverage.
- grPaint.addCoverageFragmentProcessor(std::move(cfp));
-
- // Undo the offset that was needed for shader coord transforms to get the transform for
- // the actual drawn geometry.
- ctm.postTranslate(SkIntToScalar(left), SkIntToScalar(top));
- inverseClipMatrix.preTranslate(-SkIntToScalar(left), -SkIntToScalar(top));
- SkRect clipGeometry = SkRect::MakeWH(clipImage->width(), clipImage->height());
- if (!clipGeometry.contains(inverseClipMatrix.mapRect(dstRect))) {
- // Draw the clip geometry since it is smaller, using dstRect as an extra scissor
- SkClipStack clip(this->cs());
- clip.clipDevRect(SkIRect::MakeXYWH(left, top, subset.width(), subset.height()),
- SkClipOp::kIntersect);
- SkMatrix local = SkMatrix::Concat(SkMatrix::MakeRectToRect(
- dstRect, srcRect, SkMatrix::kFill_ScaleToFit), ctm);
- fRenderTargetContext->fillRectWithLocalMatrix(GrClipStackClip(&clip),
- std::move(grPaint), GrAA(paint.isAntiAlias()), ctm, clipGeometry, local);
- return;
- }
- // Else fall through and draw the subset since that is contained in the clip geometry
- }
- // Else some issue configuring the coverage FP, so just draw without the clip mask image
- }
// Draw directly in screen space, possibly with an extra coverage processor
fRenderTargetContext->fillRectToRect(this->clip(), std::move(grPaint),
GrAA(paint.isAntiAlias()), SkMatrix::I(), dstRect, srcRect);
@@ -844,7 +793,7 @@ void SkGpuDevice::drawDevice(SkBaseDevice* device,
return;
}
- this->drawSpecial(srcImg.get(), left, top, paint, nullptr, SkMatrix::I());
+ this->drawSpecial(srcImg.get(), left, top, paint);
}
void SkGpuDevice::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
@@ -941,12 +890,11 @@ static bool init_vertices_paint(GrContext* context,
const SkPaint& skPaint,
const SkMatrixProvider& matrixProvider,
SkBlendMode bmode,
- bool hasTexs,
bool hasColors,
GrPaint* grPaint) {
- if (hasTexs && skPaint.getShader()) {
+ if (skPaint.getShader()) {
if (hasColors) {
- // When there are texs and colors the shader and colors are combined using bmode.
+ // When there are colors and a shader, the shader and colors are combined using bmode.
return SkPaintToGrPaintWithXfermode(context, colorInfo, skPaint, matrixProvider, bmode,
grPaint);
} else {
@@ -955,12 +903,11 @@ static bool init_vertices_paint(GrContext* context,
}
} else {
if (hasColors) {
- // We have colors, but either have no shader or no texture coords (which implies that
- // we should ignore the shader).
+ // We have colors, but no shader.
return SkPaintToGrPaintWithPrimitiveColor(context, colorInfo, skPaint, matrixProvider,
grPaint);
} else {
- // No colors and no shaders. Just draw with the paint color.
+ // No colors and no shader. Just draw with the paint color.
return SkPaintToGrPaintNoShader(context, colorInfo, skPaint, matrixProvider, grPaint);
}
}
@@ -976,13 +923,9 @@ void SkGpuDevice::drawVertices(const SkVertices* vertices, SkBlendMode mode, con
const SkRuntimeEffect* effect =
paint.getShader() ? as_SB(paint.getShader())->asRuntimeEffect() : nullptr;
- // Pretend that we have tex coords when using custom per-vertex data. The shader is going to
- // use those (rather than local coords), but our paint conversion remains the same.
GrPaint grPaint;
- bool hasColors = info.hasColors();
- bool hasTexs = info.hasTexCoords() || info.hasCustomData();
if (!init_vertices_paint(fContext.get(), fRenderTargetContext->colorInfo(), paint,
- this->asMatrixProvider(), mode, hasTexs, hasColors, &grPaint)) {
+ this->asMatrixProvider(), mode, info.hasColors(), &grPaint)) {
return;
}
fRenderTargetContext->drawVertices(this->clip(), std::move(grPaint), this->asMatrixProvider(),
@@ -1067,14 +1010,16 @@ void SkGpuDevice::drawDrawable(SkDrawable* drawable, const SkMatrix* matrix, SkC
///////////////////////////////////////////////////////////////////////////////
void SkGpuDevice::flush() {
- this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo());
+ this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo(), nullptr);
+ this->context()->submit();
}
GrSemaphoresSubmitted SkGpuDevice::flush(SkSurface::BackendSurfaceAccess access,
- const GrFlushInfo& info) {
+ const GrFlushInfo& info,
+ const GrBackendSurfaceMutableState* newState) {
ASSERT_SINGLE_OWNER
- return fRenderTargetContext->flush(access, info);
+ return fRenderTargetContext->flush(access, info, newState);
}
bool SkGpuDevice::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
@@ -1143,7 +1088,6 @@ bool SkGpuDevice::android_utils_clipWithStencil() {
}
GrPaint grPaint;
grPaint.setXPFactory(GrDisableColorXPFactory::Get());
- GrNoClip noClip;
static constexpr GrUserStencilSettings kDrawToStencil(
GrUserStencilSettings::StaticInit<
0x1,
@@ -1153,7 +1097,7 @@ bool SkGpuDevice::android_utils_clipWithStencil() {
GrUserStencilOp::kReplace,
0x1>()
);
- rtc->drawRegion(noClip, std::move(grPaint), GrAA::kNo, SkMatrix::I(), clipRegion,
+ rtc->drawRegion(nullptr, std::move(grPaint), GrAA::kNo, SkMatrix::I(), clipRegion,
GrStyle::SimpleFill(), &kDrawToStencil);
return true;
}
diff --git a/chromium/third_party/skia/src/gpu/SkGpuDevice.h b/chromium/third_party/skia/src/gpu/SkGpuDevice.h
index 664aaf0b5c9..75aa82db57b 100644
--- a/chromium/third_party/skia/src/gpu/SkGpuDevice.h
+++ b/chromium/third_party/skia/src/gpu/SkGpuDevice.h
@@ -101,8 +101,7 @@ public:
void drawDevice(SkBaseDevice*, int x, int y, const SkPaint&) override;
- void drawSpecial(SkSpecialImage*, int left, int top, const SkPaint& paint,
- SkImage*, const SkMatrix&) override;
+ void drawSpecial(SkSpecialImage*, int left, int top, const SkPaint&) override;
void drawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], SkCanvas::QuadAAFlags aaFlags,
const SkColor4f& color, SkBlendMode mode) override;
@@ -114,7 +113,8 @@ public:
sk_sp<SkSpecialImage> snapSpecial(const SkIRect&, bool = false) override;
void flush() override;
- GrSemaphoresSubmitted flush(SkSurface::BackendSurfaceAccess access, const GrFlushInfo&);
+ GrSemaphoresSubmitted flush(SkSurface::BackendSurfaceAccess access, const GrFlushInfo&,
+ const GrBackendSurfaceMutableState*);
bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores);
bool onAccessPixels(SkPixmap*) override;
@@ -129,6 +129,7 @@ private:
// We want these unreffed in RenderTargetContext, GrContext order.
sk_sp<GrContext> fContext;
std::unique_ptr<GrRenderTargetContext> fRenderTargetContext;
+ GrClipStackClip fClip;
enum Flags {
kNeedClear_Flag = 1 << 0, //!< Surface requires an initial clear
@@ -148,7 +149,7 @@ private:
bool forceConservativeRasterClip() const override { return true; }
- GrClipStackClip clip() const { return GrClipStackClip(&this->cs()); }
+ const GrClip* clip() const { return &fClip; }
sk_sp<SkSpecialImage> filterTexture(SkSpecialImage*,
int left, int top,
diff --git a/chromium/third_party/skia/src/gpu/SkGpuDevice_drawTexture.cpp b/chromium/third_party/skia/src/gpu/SkGpuDevice_drawTexture.cpp
index 3534b6cd844..4ef4d653950 100644
--- a/chromium/third_party/skia/src/gpu/SkGpuDevice_drawTexture.cpp
+++ b/chromium/third_party/skia/src/gpu/SkGpuDevice_drawTexture.cpp
@@ -125,12 +125,13 @@ static int determine_tile_size(const SkIRect& src, int maxTileSize) {
// Given a bitmap, an optional src rect, and a context with a clip and matrix determine what
// pixels from the bitmap are necessary.
static SkIRect determine_clipped_src_rect(int width, int height,
- const GrClip& clip,
+ const GrClip* clip,
const SkMatrix& viewMatrix,
const SkMatrix& srcToDstRect,
const SkISize& imageDimensions,
const SkRect* srcRectPtr) {
- SkIRect clippedSrcIRect = clip.getConservativeBounds(width, height);
+ SkIRect clippedSrcIRect = clip ? clip->getConservativeBounds()
+ : SkIRect::MakeWH(width, height);
SkMatrix inv = SkMatrix::Concat(viewMatrix, srcToDstRect);
if (!inv.invert(&inv)) {
return SkIRect::MakeEmpty();
@@ -154,7 +155,7 @@ static SkIRect determine_clipped_src_rect(int width, int height,
// tileSize and clippedSubset are valid if true is returned
static bool should_tile_image_id(GrContext* context,
SkISize rtSize,
- const GrClip& clip,
+ const GrClip* clip,
uint32_t imageID,
const SkISize& imageSize,
const SkMatrix& ctm,
@@ -318,8 +319,19 @@ static bool can_use_draw_texture(const SkPaint& paint) {
!paint.getImageFilter() && paint.getFilterQuality() < kMedium_SkFilterQuality);
}
+static SkPMColor4f texture_color(SkColor4f paintColor, float entryAlpha, GrColorType srcColorType,
+ const GrColorInfo& dstColorInfo) {
+ paintColor.fA *= entryAlpha;
+ if (GrColorTypeIsAlphaOnly(srcColorType)) {
+ return SkColor4fPrepForDst(paintColor, dstColorInfo).premul();
+ } else {
+ float paintAlpha = SkTPin(paintColor.fA, 0.f, 1.f);
+ return { paintAlpha, paintAlpha, paintAlpha, paintAlpha };
+ }
+}
+
// Assumes srcRect and dstRect have already been optimized to fit the proxy
-static void draw_texture(GrRenderTargetContext* rtc, const GrClip& clip, const SkMatrix& ctm,
+static void draw_texture(GrRenderTargetContext* rtc, const GrClip* clip, const SkMatrix& ctm,
const SkPaint& paint, const SkRect& srcRect, const SkRect& dstRect,
const SkPoint dstClip[4], GrAA aa, GrQuadAAFlags aaFlags,
SkCanvas::SrcRectConstraint constraint, GrSurfaceProxyView view,
@@ -354,14 +366,8 @@ static void draw_texture(GrRenderTargetContext* rtc, const GrClip& clip, const S
constraint = SkCanvas::kStrict_SrcRectConstraint;
}
}
- SkPMColor4f color;
- if (GrColorTypeIsAlphaOnly(srcColorInfo.colorType())) {
- color = SkColor4fPrepForDst(paint.getColor4f(), dstInfo).premul();
- } else {
- float paintAlpha = paint.getColor4f().fA;
- color = { paintAlpha, paintAlpha, paintAlpha, paintAlpha };
- }
+ SkPMColor4f color = texture_color(paint.getColor4f(), 1.f, srcColorInfo.colorType(), dstInfo);
if (dstClip) {
// Get source coords corresponding to dstClip
SkPoint srcQuad[4];
@@ -382,7 +388,7 @@ static void draw_texture(GrRenderTargetContext* rtc, const GrClip& clip, const S
// Assumes srcRect and dstRect have already been optimized to fit the proxy.
static void draw_texture_producer(GrContext* context,
GrRenderTargetContext* rtc,
- const GrClip& clip,
+ const GrClip* clip,
const SkMatrixProvider& matrixProvider,
const SkPaint& paint,
GrTextureProducer* producer,
@@ -510,7 +516,7 @@ static void draw_texture_producer(GrContext* context,
void draw_tiled_bitmap(GrContext* context,
GrRenderTargetContext* rtc,
- const GrClip& clip,
+ const GrClip* clip,
const SkBitmap& bitmap,
int tileSize,
const SkMatrixProvider& matrixProvider,
@@ -844,7 +850,9 @@ void SkGpuDevice::drawEdgeAAImageSet(const SkCanvas::ImageSetEntry set[], int co
textures[i].fDstClipQuad = clip;
textures[i].fPreViewMatrix =
set[i].fMatrixIndex < 0 ? nullptr : preViewMatrices + set[i].fMatrixIndex;
- textures[i].fAlpha = set[i].fAlpha * paint.getAlphaf();
+ textures[i].fColor = texture_color(paint.getColor4f(), set[i].fAlpha,
+ SkColorTypeToGrColorType(image->colorType()),
+ fRenderTargetContext->colorInfo());
textures[i].fAAFlags = SkToGrQuadAAFlags(set[i].fAAFlags);
if (n > 0 &&
diff --git a/chromium/third_party/skia/src/gpu/SkGr.cpp b/chromium/third_party/skia/src/gpu/SkGr.cpp
index 9c66d396ce7..9b77a281fc5 100644
--- a/chromium/third_party/skia/src/gpu/SkGr.cpp
+++ b/chromium/third_party/skia/src/gpu/SkGr.cpp
@@ -20,6 +20,7 @@
#include "include/private/SkTemplates.h"
#include "src/core/SkAutoMalloc.h"
#include "src/core/SkBlendModePriv.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkImagePriv.h"
#include "src/core/SkMaskFilterBase.h"
@@ -48,38 +49,39 @@
#include "src/shaders/SkShaderBase.h"
GR_FP_SRC_STRING SKSL_DITHER_SRC = R"(
-// This controls the range of values added to color channels
-in int rangeType;
+// This controls the range of values added to color channels and is based on the destination color
+// type; as such it doesn't really affect our program cache to have a variant per-range.
+in half range;
-void main(float2 p, inout half4 color) {
+void main(inout half4 color) {
half value;
- half range;
- @switch (rangeType) {
- case 0:
- range = 1.0 / 255.0;
- break;
- case 1:
- range = 1.0 / 63.0;
- break;
- default:
- // Experimentally this looks better than the expected value of 1/15.
- range = 1.0 / 15.0;
- break;
- }
- @if (sk_Caps.integerSupport) {
+ @if (sk_Caps.integerSupport)
+ {
// This ordered-dither code is lifted from the cpu backend.
- uint x = uint(p.x);
- uint y = uint(p.y);
+ uint x = uint(sk_FragCoord.x);
+ uint y = uint(sk_FragCoord.y) ^ x;
uint m = (y & 1) << 5 | (x & 1) << 4 |
(y & 2) << 2 | (x & 2) << 1 |
(y & 4) >> 1 | (x & 4) >> 2;
value = half(m) * 1.0 / 64.0 - 63.0 / 128.0;
} else {
- // Simulate the integer effect used above using step/mod. For speed, simulates a 4x4
- // dither pattern rather than an 8x8 one.
- half4 modValues = mod(half4(half(p.x), half(p.y), half(p.x), half(p.y)), half4(2.0, 2.0, 4.0, 4.0));
- half4 stepValues = step(modValues, half4(1.0, 1.0, 2.0, 2.0));
- value = dot(stepValues, half4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0;
+ // Simulate the integer effect used above using step/mod/abs. For speed, simulates a 4x4
+ // dither pattern rather than an 8x8 one. Since it's 4x4, this is effectively computing:
+ // uint m = (y & 1) << 3 | (x & 1) << 2 |
+ // (y & 2) << 0 | (x & 2) >> 1;
+ // where 'y' has already been XOR'ed with 'x' as in the integer-supported case.
+
+ // To get the low bit of p.x and p.y, we compute mod 2.0; for the high bit, we mod 4.0
+ half4 bits = mod(half4(sk_FragCoord.yxyx), half4(2.0, 2.0, 4.0, 4.0));
+ // Use step to convert the 0-3 value in bits.zw into a 0|1 value. bits.xy is already 0|1.
+ bits.zw = step(2.0, bits.zw);
+ // bits was constructed such that the p.x bits were already in the right place for
+ // interleaving (in bits.yw). We just need to update the other bits from p.y to (p.x ^ p.y).
+ // These are in bits.xz. Since the values are 0|1, we can simulate ^ as abs(y - x).
+ bits.xz = abs(bits.xz - bits.yw);
+
+ // Manual binary sum, divide by N^2, and offset
+ value = dot(bits, half4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0;
}
// For each color channel, add the random offset to the channel value and then clamp
// between 0 and alpha to keep the color premultiplied.
@@ -198,39 +200,50 @@ static inline bool blend_requires_shader(const SkBlendMode mode) {
}
#ifndef SK_IGNORE_GPU_DITHER
-static inline int32_t dither_range_type_for_config(GrColorType dstColorType) {
+static inline float dither_range_for_config(GrColorType dstColorType) {
+ // We use 1 / (2^bitdepth-1) as the range since each channel can hold 2^bitdepth values
switch (dstColorType) {
+ // 4 bit
+ case GrColorType::kABGR_4444:
+ return 1 / 15.f;
+ // 6 bit
+ case GrColorType::kBGR_565:
+ return 1 / 63.f;
+ // 8 bit
case GrColorType::kUnknown:
+ case GrColorType::kAlpha_8:
+ case GrColorType::kAlpha_8xxx:
case GrColorType::kGray_8:
- case GrColorType::kRGBA_8888:
- case GrColorType::kRGB_888x:
+ case GrColorType::kGray_8xxx:
+ case GrColorType::kR_8:
case GrColorType::kRG_88:
- case GrColorType::kBGRA_8888:
- case GrColorType::kRG_1616:
- case GrColorType::kRGBA_16161616:
- case GrColorType::kRG_F16:
+ case GrColorType::kRGB_888:
+ case GrColorType::kRGB_888x:
+ case GrColorType::kRGBA_8888:
case GrColorType::kRGBA_8888_SRGB:
+ case GrColorType::kBGRA_8888:
+ return 1 / 255.f;
+ // 10 bit
case GrColorType::kRGBA_1010102:
case GrColorType::kBGRA_1010102:
+ return 1 / 1023.f;
+ // 16 bit
+ case GrColorType::kAlpha_16:
+ case GrColorType::kR_16:
+ case GrColorType::kRG_1616:
+ case GrColorType::kRGBA_16161616:
+ return 1 / 32767.f;
+ // Half
case GrColorType::kAlpha_F16:
- case GrColorType::kRGBA_F32:
+ case GrColorType::kGray_F16:
+ case GrColorType::kR_F16:
+ case GrColorType::kRG_F16:
case GrColorType::kRGBA_F16:
case GrColorType::kRGBA_F16_Clamped:
- case GrColorType::kAlpha_8:
- case GrColorType::kAlpha_8xxx:
- case GrColorType::kAlpha_16:
+ // Float
case GrColorType::kAlpha_F32xxx:
- case GrColorType::kGray_8xxx:
- case GrColorType::kRGB_888:
- case GrColorType::kR_8:
- case GrColorType::kR_16:
- case GrColorType::kR_F16:
- case GrColorType::kGray_F16:
- return 0;
- case GrColorType::kBGR_565:
- return 1;
- case GrColorType::kABGR_4444:
- return 2;
+ case GrColorType::kRGBA_F32:
+ return 0.f; // no dithering
}
SkUNREACHABLE;
}
@@ -250,15 +263,17 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
// Setup the initial color considering the shader, the SkPaint color, and the presence or not
// of per-vertex colors.
- std::unique_ptr<GrFragmentProcessor> shaderFP;
+ std::unique_ptr<GrFragmentProcessor> paintFP;
if (!primColorMode || blend_requires_shader(*primColorMode)) {
fpArgs.fInputColorIsOpaque = origColor.isOpaque();
if (shaderProcessor) {
- shaderFP = std::move(*shaderProcessor);
- } else if (const auto* shader = as_SB(skPaint.getShader())) {
- shaderFP = shader->asFragmentProcessor(fpArgs);
- if (!shaderFP) {
- return false;
+ paintFP = std::move(*shaderProcessor);
+ } else {
+ if (const SkShaderBase* shader = as_SB(skPaint.getShader())) {
+ paintFP = shader->asFragmentProcessor(fpArgs);
+ if (paintFP == nullptr) {
+ return false;
+ }
}
}
}
@@ -267,7 +282,7 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
// a known constant value. In that case we can simply apply a color filter during this
// conversion without converting the color filter to a GrFragmentProcessor.
bool applyColorFilterToPaintColor = false;
- if (shaderFP) {
+ if (paintFP) {
if (primColorMode) {
// There is a blend between the primitive color and the shader color. The shader sees
// the opaque paint color. The shader's output is blended using the provided mode by
@@ -277,43 +292,33 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
// the GrPaint color will be ignored.
SkPMColor4f shaderInput = origColor.makeOpaque().premul();
- shaderFP = GrFragmentProcessor::OverrideInput(std::move(shaderFP), shaderInput);
- shaderFP = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(shaderFP),
- *primColorMode);
-
- // The above may return null if compose results in a pass through of the prim color.
- if (shaderFP) {
- grPaint->addColorFragmentProcessor(std::move(shaderFP));
- }
+ paintFP = GrFragmentProcessor::OverrideInput(std::move(paintFP), shaderInput);
+ paintFP = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(paintFP),
+ *primColorMode);
// We can ignore origColor here - alpha is unchanged by gamma
float paintAlpha = skPaint.getColor4f().fA;
if (1.0f != paintAlpha) {
// No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
// color channels. It's value should be treated as the same in ANY color space.
- grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
- { paintAlpha, paintAlpha, paintAlpha, paintAlpha },
- GrConstColorProcessor::InputMode::kModulateRGBA));
+ paintFP = GrConstColorProcessor::Make(
+ std::move(paintFP), { paintAlpha, paintAlpha, paintAlpha, paintAlpha },
+ GrConstColorProcessor::InputMode::kModulateRGBA);
}
} else {
// The shader's FP sees the paint *unpremul* color
SkPMColor4f origColorAsPM = { origColor.fR, origColor.fG, origColor.fB, origColor.fA };
grPaint->setColor4f(origColorAsPM);
- grPaint->addColorFragmentProcessor(std::move(shaderFP));
}
} else {
if (primColorMode) {
// There is a blend between the primitive color and the paint color. The blend considers
// the opaque paint color. The paint's alpha is applied to the post-blended color.
SkPMColor4f opaqueColor = origColor.makeOpaque().premul();
- auto processor = GrConstColorProcessor::Make(opaqueColor,
- GrConstColorProcessor::InputMode::kIgnore);
- processor = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(processor),
- *primColorMode);
- if (processor) {
- grPaint->addColorFragmentProcessor(std::move(processor));
- }
-
+ paintFP = GrConstColorProcessor::Make(/*inputFP=*/nullptr, opaqueColor,
+ GrConstColorProcessor::InputMode::kIgnore);
+ paintFP = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(paintFP),
+ *primColorMode);
grPaint->setColor4f(opaqueColor);
// We can ignore origColor here - alpha is unchanged by gamma
@@ -321,9 +326,9 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
if (1.0f != paintAlpha) {
// No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
// color channels. It's value should be treated as the same in ANY color space.
- grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
- { paintAlpha, paintAlpha, paintAlpha, paintAlpha },
- GrConstColorProcessor::InputMode::kModulateRGBA));
+ paintFP = GrConstColorProcessor::Make(
+ std::move(paintFP), { paintAlpha, paintAlpha, paintAlpha, paintAlpha },
+ GrConstColorProcessor::InputMode::kModulateRGBA);
}
} else {
// No shader, no primitive color.
@@ -332,13 +337,17 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
}
}
+ if (paintFP) {
+ grPaint->addColorFragmentProcessor(std::move(paintFP));
+ }
+
SkColorFilter* colorFilter = skPaint.getColorFilter();
if (colorFilter) {
if (applyColorFilterToPaintColor) {
SkColorSpace* dstCS = dstColorInfo.colorSpace();
grPaint->setColor4f(colorFilter->filterColor4f(origColor, dstCS, dstCS).premul());
} else {
- auto cfFP = colorFilter->asFragmentProcessor(context, dstColorInfo);
+ auto cfFP = as_CFB(colorFilter)->asFragmentProcessor(context, dstColorInfo);
if (cfFP) {
grPaint->addColorFragmentProcessor(std::move(cfFP));
} else {
@@ -367,12 +376,15 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
GrColorType ct = dstColorInfo.colorType();
if (SkPaintPriv::ShouldDither(skPaint, GrColorTypeToSkColorType(ct)) &&
grPaint->numColorFragmentProcessors() > 0) {
- int32_t ditherRange = dither_range_type_for_config(ct);
- if (ditherRange >= 0) {
+ float ditherRange = dither_range_for_config(ct);
+ if (ditherRange > 0.f) {
static auto effect = std::get<0>(SkRuntimeEffect::Make(SkString(SKSL_DITHER_SRC)));
auto ditherFP = GrSkSLFP::Make(context, effect, "Dither",
SkData::MakeWithCopy(&ditherRange, sizeof(ditherRange)));
if (ditherFP) {
+ // The dither shader doesn't actually use input coordinates, but if we don't set
+ // this flag, the generated shader includes an extra local coord varying.
+ ditherFP->temporary_SetExplicitlySampled();
grPaint->addColorFragmentProcessor(std::move(ditherFP));
}
}
@@ -380,7 +392,8 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
#endif
if (GrColorTypeClampType(dstColorInfo.colorType()) == GrClampType::kManual) {
if (grPaint->numColorFragmentProcessors()) {
- grPaint->addColorFragmentProcessor(GrClampFragmentProcessor::Make(false));
+ grPaint->addColorFragmentProcessor(
+ GrClampFragmentProcessor::Make(/*inputFP=*/nullptr, /*clampToPremul=*/false));
} else {
auto color = grPaint->getColor4f();
grPaint->setColor4f({SkTPin(color.fR, 0.f, 1.f),
diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCAtlas.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCCAtlas.cpp
index a980f688841..8cf105e6740 100644
--- a/chromium/third_party/skia/src/gpu/ccpr/GrCCAtlas.cpp
+++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCAtlas.cpp
@@ -7,6 +7,7 @@
#include "src/gpu/ccpr/GrCCAtlas.h"
+#include "src/core/SkIPoint16.h"
#include "src/gpu/GrOnFlushResourceProvider.h"
#include "src/gpu/ccpr/GrCCPathCache.h"
@@ -84,13 +85,16 @@ sk_sp<GrCCCachedAtlas> GrCCAtlas::refOrMakeCachedAtlas(GrOnFlushResourceProvider
GrCCAtlas* GrCCAtlasStack::addRect(const SkIRect& devIBounds, SkIVector* devToAtlasOffset) {
GrCCAtlas* retiredAtlas = nullptr;
- if (fAtlases.empty() || !fAtlases.back().addRect(devIBounds, devToAtlasOffset)) {
+ SkIPoint16 location;
+ if (fAtlases.empty() ||
+ !fAtlases.back().addRect(devIBounds.width(), devIBounds.height(), &location)) {
// The retired atlas is out of room and can't grow any bigger.
retiredAtlas = !fAtlases.empty() ? &fAtlases.back() : nullptr;
fAtlases.emplace_back(fCoverageType, fSpecs, *fCaps);
SkASSERT(devIBounds.width() <= fSpecs.fMinWidth);
SkASSERT(devIBounds.height() <= fSpecs.fMinHeight);
- SkAssertResult(fAtlases.back().addRect(devIBounds, devToAtlasOffset));
+ SkAssertResult(fAtlases.back().addRect(devIBounds.width(), devIBounds.height(), &location));
}
+ devToAtlasOffset->set(location.x() - devIBounds.left(), location.y() - devIBounds.top());
return retiredAtlas;
}
diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.cpp
index b2a2c07f833..36ba5f8383e 100644
--- a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.cpp
+++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.cpp
@@ -21,23 +21,19 @@ void GrCCClipPath::init(
fAtlasLazyProxy = GrCCAtlas::MakeLazyAtlasProxy(
[this](GrResourceProvider* resourceProvider, const GrCCAtlas::LazyAtlasDesc& desc) {
SkASSERT(fHasAtlas);
- SkASSERT(!fHasAtlasTransform);
+ SkASSERT(!fHasAtlasTranslate);
GrTextureProxy* textureProxy = fAtlas ? fAtlas->textureProxy() : nullptr;
if (!textureProxy || !textureProxy->instantiate(resourceProvider)) {
- fAtlasScale = fAtlasTranslate = {0, 0};
- SkDEBUGCODE(fHasAtlasTransform = true);
+ SkDEBUGCODE(fHasAtlasTranslate = true);
return GrSurfaceProxy::LazyCallbackResult();
}
sk_sp<GrTexture> texture = sk_ref_sp(textureProxy->peekTexture());
SkASSERT(texture);
- fAtlasScale = {1.f / texture->width(), 1.f / texture->height()};
- fAtlasTranslate.set(fDevToAtlasOffset.fX * fAtlasScale.x(),
- fDevToAtlasOffset.fY * fAtlasScale.y());
- SkDEBUGCODE(fHasAtlasTransform = true);
+ SkDEBUGCODE(fHasAtlasTranslate = true);
// We use LazyInstantiationKeyMode::kUnsynced here because CCPR clip masks are never
// cached, and the clip FP proxies need to ignore any unique keys that atlas
diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.h b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.h
index 0f3fef20583..c0ec06c47b1 100644
--- a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.h
+++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipPath.h
@@ -62,8 +62,10 @@ public:
void accountForOwnPath(GrCCPerFlushResourceSpecs*) const;
void renderPathInAtlas(GrCCPerFlushResources*, GrOnFlushResourceProvider*);
- const SkVector& atlasScale() const { SkASSERT(fHasAtlasTransform); return fAtlasScale; }
- const SkVector& atlasTranslate() const { SkASSERT(fHasAtlasTransform); return fAtlasTranslate; }
+ const SkIVector& atlasTranslate() const {
+ SkASSERT(fHasAtlasTranslate);
+ return fDevToAtlasOffset;
+ }
private:
sk_sp<GrTextureProxy> fAtlasLazyProxy;
@@ -74,10 +76,7 @@ private:
const GrCCAtlas* fAtlas = nullptr;
SkIVector fDevToAtlasOffset; // Translation from device space to location in atlas.
SkDEBUGCODE(bool fHasAtlas = false;)
-
- SkVector fAtlasScale;
- SkVector fAtlasTranslate;
- SkDEBUGCODE(bool fHasAtlasTransform = false;)
+ SkDEBUGCODE(bool fHasAtlasTranslate = false;)
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.cpp
index 9eed783219f..718985ac5fb 100644
--- a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.cpp
+++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.cpp
@@ -7,9 +7,8 @@
#include "src/gpu/ccpr/GrCCClipProcessor.h"
-#include "src/gpu/GrTexture.h"
-#include "src/gpu/GrTextureProxy.h"
#include "src/gpu/ccpr/GrCCClipPath.h"
+#include "src/gpu/effects/GrTextureEffect.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
@@ -20,30 +19,34 @@ static GrSurfaceProxyView make_view(const GrCaps& caps, GrSurfaceProxy* proxy,
return { sk_ref_sp(proxy), GrCCAtlas::kTextureOrigin, swizzle };
}
-GrCCClipProcessor::GrCCClipProcessor(GrSurfaceProxyView view, const GrCCClipPath* clipPath,
+GrCCClipProcessor::GrCCClipProcessor(std::unique_ptr<GrFragmentProcessor> inputFP,
+ const GrCaps& caps,
+ const GrCCClipPath* clipPath,
IsCoverageCount isCoverageCount,
MustCheckBounds mustCheckBounds)
: INHERITED(kGrCCClipProcessor_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, fClipPath(clipPath)
, fIsCoverageCount(IsCoverageCount::kYes == isCoverageCount)
- , fMustCheckBounds(MustCheckBounds::kYes == mustCheckBounds)
- , fAtlasAccess(std::move(view)) {
- SkASSERT(fAtlasAccess.view());
- this->setTextureSamplerCnt(1);
+ , fMustCheckBounds(MustCheckBounds::kYes == mustCheckBounds) {
+ auto view = make_view(caps, clipPath->atlasLazyProxy(), fIsCoverageCount);
+ auto texEffect = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
+ this->registerExplicitlySampledChild(std::move(texEffect));
+
+ if (inputFP != nullptr) {
+ this->registerChild(std::move(inputFP));
+ }
}
-GrCCClipProcessor::GrCCClipProcessor(const GrCaps& caps, const GrCCClipPath* clipPath,
- IsCoverageCount isCoverageCount,
- MustCheckBounds mustCheckBounds)
- : GrCCClipProcessor(make_view(caps, clipPath->atlasLazyProxy(),
- IsCoverageCount::kYes == isCoverageCount),
- clipPath, isCoverageCount, mustCheckBounds) {
+GrCCClipProcessor::GrCCClipProcessor(const GrCCClipProcessor& that)
+ : INHERITED(kGrCCClipProcessor_ClassID, that.optimizationFlags())
+ , fClipPath(that.fClipPath)
+ , fIsCoverageCount(that.fIsCoverageCount)
+ , fMustCheckBounds(that.fMustCheckBounds) {
+ this->cloneAndRegisterAllChildProcessors(that);
}
std::unique_ptr<GrFragmentProcessor> GrCCClipProcessor::clone() const {
- return std::make_unique<GrCCClipProcessor>(
- fAtlasAccess.view(), fClipPath, IsCoverageCount(fIsCoverageCount),
- MustCheckBounds(fMustCheckBounds));
+ return std::unique_ptr<GrFragmentProcessor>(new GrCCClipProcessor(*this));
}
void GrCCClipProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
@@ -56,15 +59,19 @@ void GrCCClipProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKe
bool GrCCClipProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
const GrCCClipProcessor& that = fp.cast<GrCCClipProcessor>();
- // Each ClipPath path has a unique atlas proxy, so hasSameSamplersAndAccesses should have
- // already weeded out FPs with different ClipPaths.
- SkASSERT(that.fClipPath->deviceSpacePath().getGenerationID() ==
- fClipPath->deviceSpacePath().getGenerationID());
- return that.fClipPath->deviceSpacePath().getFillType() ==
+ return that.fClipPath->deviceSpacePath().getGenerationID() ==
+ fClipPath->deviceSpacePath().getGenerationID() &&
+ that.fClipPath->deviceSpacePath().getFillType() ==
fClipPath->deviceSpacePath().getFillType() &&
that.fIsCoverageCount == fIsCoverageCount && that.fMustCheckBounds == fMustCheckBounds;
}
+bool GrCCClipProcessor::hasInputFP() const {
+ // We always have a `texEffect`, and this accounts for one child.
+ // The second child will be the input FP, if we have one.
+ return this->numChildProcessors() > 1;
+}
+
class GrCCClipProcessor::Impl : public GrGLSLFragmentProcessor {
public:
void emitCode(EmitArgs& args) override {
@@ -72,7 +79,7 @@ public:
GrGLSLUniformHandler* uniHandler = args.fUniformHandler;
GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
- f->codeAppend ("half coverage;");
+ f->codeAppend("half coverage;");
if (proc.fMustCheckBounds) {
const char* pathIBounds;
@@ -84,39 +91,43 @@ public:
pathIBounds, pathIBounds);
}
- const char* atlasTransform;
- fAtlasTransformUniform = uniHandler->addUniform(&proc, kFragment_GrShaderFlag,
- kFloat4_GrSLType, "atlas_transform",
- &atlasTransform);
- f->codeAppendf("float2 texcoord = sk_FragCoord.xy * %s.xy + %s.zw;",
- atlasTransform, atlasTransform);
-
- f->codeAppend ("coverage = ");
- f->appendTextureLookup(args.fTexSamplers[0], "texcoord");
- f->codeAppend (".a;");
+ const char* atlasTranslate;
+ fAtlasTranslateUniform = uniHandler->addUniform(&proc, kFragment_GrShaderFlag,
+ kFloat2_GrSLType, "atlas_translate",
+ &atlasTranslate);
+ SkString coord;
+ coord.printf("sk_FragCoord.xy + %s.xy", atlasTranslate);
+ constexpr int kTexEffectFPIndex = 0;
+ SkString sample = this->invokeChild(kTexEffectFPIndex, args, coord.c_str());
+ f->codeAppendf("coverage = %s.a;", sample.c_str());
if (proc.fIsCoverageCount) {
auto fillRule = GrFillRuleForSkPath(proc.fClipPath->deviceSpacePath());
if (GrFillRule::kEvenOdd == fillRule) {
- f->codeAppend ("half t = mod(abs(coverage), 2);");
- f->codeAppend ("coverage = 1 - abs(t - 1);");
+ f->codeAppend("half t = mod(abs(coverage), 2);");
+ f->codeAppend("coverage = 1 - abs(t - 1);");
} else {
SkASSERT(GrFillRule::kNonzero == fillRule);
- f->codeAppend ("coverage = min(abs(coverage), 1);");
+ f->codeAppend("coverage = min(abs(coverage), 1);");
}
}
if (proc.fMustCheckBounds) {
- f->codeAppend ("} else {");
- f->codeAppend ( "coverage = 0;");
- f->codeAppend ("}");
+ f->codeAppend("} else {");
+ f->codeAppend( "coverage = 0;");
+ f->codeAppend("}");
}
if (proc.fClipPath->deviceSpacePath().isInverseFillType()) {
- f->codeAppend ("coverage = 1 - coverage;");
+ f->codeAppend("coverage = 1 - coverage;");
}
- f->codeAppendf("%s = %s * coverage;", args.fOutputColor, args.fInputColor);
+ constexpr int kInputFPIndex = 1;
+ SkString inputColor = proc.hasInputFP()
+ ? this->invokeChild(kInputFPIndex, args.fInputColor, args)
+ : SkString(args.fInputColor);
+
+ f->codeAppendf("%s = %s * coverage;", args.fOutputColor, inputColor.c_str());
}
void onSetData(const GrGLSLProgramDataManager& pdman,
@@ -127,14 +138,13 @@ public:
pdman.set4f(fPathIBoundsUniform, pathIBounds.left(), pathIBounds.top(),
pathIBounds.right(), pathIBounds.bottom());
}
- const SkVector& scale = proc.fClipPath->atlasScale();
- const SkVector& trans = proc.fClipPath->atlasTranslate();
- pdman.set4f(fAtlasTransformUniform, scale.x(), scale.y(), trans.x(), trans.y());
+ const SkIVector& trans = proc.fClipPath->atlasTranslate();
+ pdman.set2f(fAtlasTranslateUniform, trans.x(), trans.y());
}
private:
UniformHandle fPathIBoundsUniform;
- UniformHandle fAtlasTransformUniform;
+ UniformHandle fAtlasTranslateUniform;
};
GrGLSLFragmentProcessor* GrCCClipProcessor::onCreateGLSLInstance() const {
diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.h b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.h
index d7eae5e5bc1..536bb8ed214 100644
--- a/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.h
+++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCClipProcessor.h
@@ -24,21 +24,22 @@ public:
kYes = true
};
- GrCCClipProcessor(GrSurfaceProxyView, const GrCCClipPath*, IsCoverageCount, MustCheckBounds);
- GrCCClipProcessor(const GrCaps&, const GrCCClipPath*, IsCoverageCount, MustCheckBounds);
+ GrCCClipProcessor(std::unique_ptr<GrFragmentProcessor>, const GrCaps&, const GrCCClipPath*,
+ IsCoverageCount, MustCheckBounds);
const char* name() const override { return "GrCCClipProcessor"; }
std::unique_ptr<GrFragmentProcessor> clone() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
- const TextureSampler& onTextureSampler(int) const override { return fAtlasAccess; }
+ bool hasInputFP() const;
private:
+ explicit GrCCClipProcessor(const GrCCClipProcessor&);
+
const GrCCClipPath* const fClipPath;
const bool fIsCoverageCount;
const bool fMustCheckBounds;
- const TextureSampler fAtlasAccess;
class Impl;
diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCFiller.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCCFiller.cpp
index ee9520f83be..9b30a708cd5 100644
--- a/chromium/third_party/skia/src/gpu/ccpr/GrCCFiller.cpp
+++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCFiller.cpp
@@ -433,7 +433,7 @@ bool GrCCFiller::prepareToDraw(GrOnFlushResourceProvider* onFlushRP) {
SkASSERT(!currFan.empty());
currFan.pop_back();
}
- // fallthru.
+ [[fallthrough]];
case Verb::kEndOpenContour: // endPt != startPt.
SkASSERT(!currFanIsTessellated || currFan.empty());
if (!currFanIsTessellated && currFan.count() >= 3) {
diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.cpp
index d4c1d8be466..e5c99c01a78 100644
--- a/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.cpp
+++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.cpp
@@ -103,6 +103,10 @@ class GrCCPathProcessor::Impl : public GrGLSLGeometryProcessor {
public:
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override;
+ static void GenKey(const GrCCPathProcessor& cc, GrProcessorKeyBuilder* b) {
+ b->add32(AddMatrixKeys((uint32_t) cc.fCoverageMode, SkMatrix::I(), cc.fLocalMatrix));
+ }
+
private:
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
const CoordTransformRange& transformRange) override {
@@ -110,14 +114,21 @@ private:
pdman.set2f(fAtlasAdjustUniform,
1.0f / proc.fAtlasDimensions.fWidth,
1.0f / proc.fAtlasDimensions.fHeight);
- this->setTransformDataHelper(proc.fLocalMatrix, pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
+ this->setTransform(pdman, fLocalMatrixUni, proc.fLocalMatrix, &fLocalMatrix);
}
GrGLSLUniformHandler::UniformHandle fAtlasAdjustUniform;
+ GrGLSLUniformHandler::UniformHandle fLocalMatrixUni;
+ SkMatrix fLocalMatrix = SkMatrix::InvalidMatrix();
typedef GrGLSLGeometryProcessor INHERITED;
};
+void GrCCPathProcessor::getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
+ GrCCPathProcessor::Impl::GenKey(*this, b);
+}
+
GrGLSLPrimitiveProcessor* GrCCPathProcessor::createGLSLInstance(const GrShaderCaps&) const {
return new Impl();
}
@@ -218,8 +229,8 @@ void GrCCPathProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
}
gpArgs->fPositionVar.set(kFloat2_GrSLType, "octocoord");
- this->emitTransforms(v, varyingHandler, uniHandler, gpArgs->fPositionVar, proc.fLocalMatrix,
- args.fFPCoordTransformHandler);
+ this->writeLocalCoord(v, args.fUniformHandler, gpArgs, gpArgs->fPositionVar, proc.fLocalMatrix,
+ &fLocalMatrixUni);
// Fragment shader.
GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.h b/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.h
index cb5f22770ef..789ac2e3ff6 100644
--- a/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.h
+++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCPathProcessor.h
@@ -64,9 +64,8 @@ public:
const SkMatrix& viewMatrixIfUsingLocalCoords = SkMatrix::I());
const char* name() const override { return "GrCCPathProcessor"; }
- void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
- b->add32((uint32_t)fCoverageMode);
- }
+ void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override;
+
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
void drawPaths(GrOpFlushState*, const GrPipeline&, const GrSurfaceProxy& atlasProxy,
diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCPerFlushResources.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCCPerFlushResources.cpp
index 9101b1d84c4..d13a52a28f6 100644
--- a/chromium/third_party/skia/src/gpu/ccpr/GrCCPerFlushResources.cpp
+++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCPerFlushResources.cpp
@@ -8,7 +8,6 @@
#include "src/gpu/ccpr/GrCCPerFlushResources.h"
#include "include/private/GrRecordingContext.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrMemoryPool.h"
#include "src/gpu/GrOnFlushResourceProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
@@ -97,8 +96,10 @@ public:
GrCCPathProcessor pathProc(coverageMode, fSrcProxy->peekTexture(), swizzle,
GrCCAtlas::kTextureOrigin);
- GrPipeline pipeline(GrScissorTest::kDisabled, SkBlendMode::kSrc,
- flushState->drawOpArgs().writeSwizzle());
+ bool hasScissor = flushState->appliedClip() &&
+ flushState->appliedClip()->scissorState().enabled();
+ GrPipeline pipeline(hasScissor ? GrScissorTest::kEnabled : GrScissorTest::kDisabled,
+ SkBlendMode::kSrc, flushState->drawOpArgs().writeSwizzle());
pathProc.drawPaths(flushState, pipeline, *fSrcProxy, *fResources, fBaseInstance,
fEndInstance, this->bounds());
@@ -541,7 +542,7 @@ bool GrCCPerFlushResources::finalize(GrOnFlushResourceProvider* onFlushRP) {
auto op = CopyAtlasOp::Make(
rtc->surfPriv().getContext(), sk_ref_sp(this), copyRange.fSrcProxy,
baseCopyInstance, endCopyInstance, atlas.drawBounds());
- rtc->addDrawOp(GrNoClip(), std::move(op));
+ rtc->addDrawOp(nullptr, std::move(op));
}
baseCopyInstance = endCopyInstance;
}
@@ -580,7 +581,7 @@ bool GrCCPerFlushResources::finalize(GrOnFlushResourceProvider* onFlushRP) {
rtc->surfPriv().getContext(), sk_ref_sp(this), atlas.getFillBatchID(),
atlas.getStrokeBatchID(), atlas.drawBounds());
}
- rtc->addDrawOp(GrNoClip(), std::move(op));
+ rtc->addDrawOp(nullptr, std::move(op));
if (rtc->asSurfaceProxy()->requiresManualMSAAResolve()) {
onFlushRP->addTextureResolveTask(sk_ref_sp(rtc->asTextureProxy()),
GrSurfaceProxy::ResolveFlags::kMSAA);
diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCCStroker.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCCStroker.cpp
index 44f3db3362f..bb09fe4c612 100644
--- a/chromium/third_party/skia/src/gpu/ccpr/GrCCStroker.cpp
+++ b/chromium/third_party/skia/src/gpu/ccpr/GrCCStroker.cpp
@@ -103,7 +103,6 @@ private:
void LinearStrokeProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
- GrGLSLUniformHandler* uniHandler = args.fUniformHandler;
varyingHandler->emitAttributes(args.fGP.cast<LinearStrokeProcessor>());
@@ -137,8 +136,7 @@ void LinearStrokeProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
edgeDistances.vsOut(), edgeDistances.vsOut(), edgeDistances.vsOut());
gpArgs->fPositionVar.set(kFloat2_GrSLType, "position");
- this->emitTransforms(v, varyingHandler, uniHandler, GrShaderVar("position", kFloat2_GrSLType),
- SkMatrix::I(), args.fFPCoordTransformHandler);
+ // Leave fLocalCoordVar uninitialized; this GP is not combined with frag processors
// Use the 4 edge distances to calculate coverage in the fragment shader.
GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
@@ -194,7 +192,6 @@ private:
void CubicStrokeProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
- GrGLSLUniformHandler* uniHandler = args.fUniformHandler;
varyingHandler->emitAttributes(args.fGP.cast<CubicStrokeProcessor>());
@@ -259,8 +256,7 @@ void CubicStrokeProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
coverages.vsOut());
gpArgs->fPositionVar.set(kFloat2_GrSLType, "position");
- this->emitTransforms(v, varyingHandler, uniHandler, GrShaderVar("position", kFloat2_GrSLType),
- SkMatrix::I(), args.fFPCoordTransformHandler);
+ // Leave fLocalCoordVar uninitialized; this GP is not combined with frag processors
// Use the 2 edge distances and interpolated butt cap AA to calculate fragment coverage.
GrGLSLFPFragmentBuilder* f = args.fFragBuilder;
@@ -649,10 +645,10 @@ bool GrCCStroker::prepareToDraw(GrOnFlushResourceProvider* onFlushRP) {
case Verb::kRoundJoin:
case Verb::kInternalRoundJoin:
conicWeight = params[paramsIdx++].fConicWeight;
- // fallthru
+ [[fallthrough]];
case Verb::kMiterJoin:
miterCapHeightOverWidth = params[paramsIdx++].fMiterCapHeightOverWidth;
- // fallthru
+ [[fallthrough]];
case Verb::kBevelJoin:
case Verb::kInternalBevelJoin:
builder.appendJoin(verb, pts[ptsIdx], normals[normalsIdx], normals[normalsIdx + 1],
diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
index bc56c5de6e4..5f66c6e442e 100644
--- a/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp
@@ -9,8 +9,8 @@
#include "include/pathops/SkPathOps.h"
#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrProxyProvider.h"
+#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/ccpr/GrCCClipProcessor.h"
#include "src/gpu/ccpr/GrCCDrawPathsOp.h"
#include "src/gpu/ccpr/GrCCPathCache.h"
@@ -136,7 +136,7 @@ GrPathRenderer::CanDrawPath GrCoverageCountingPathRenderer::onCanDrawPath(
// defined relative to device space.
return CanDrawPath::kNo;
}
- // fallthru
+ [[fallthrough]];
case SkStrokeRec::kHairline_Style: {
if (CoverageType::kFP16_CoverageCount != fCoverageType) {
// Stroking is not yet supported in MSAA atlas mode.
@@ -167,11 +167,8 @@ GrPathRenderer::CanDrawPath GrCoverageCountingPathRenderer::onCanDrawPath(
bool GrCoverageCountingPathRenderer::onDrawPath(const DrawPathArgs& args) {
SkASSERT(!fFlushing);
- GrRenderTargetContext* rtc = args.fRenderTargetContext;
- SkIRect clipIBounds = args.fClip->getConservativeBounds(rtc->width(), rtc->height());
-
- auto op = GrCCDrawPathsOp::Make(args.fContext, clipIBounds, *args.fViewMatrix, *args.fShape,
- std::move(args.fPaint));
+ auto op = GrCCDrawPathsOp::Make(args.fContext, *args.fClipConservativeBounds, *args.fViewMatrix,
+ *args.fShape, std::move(args.fPaint));
this->recordOp(std::move(op), args);
return true;
}
@@ -183,14 +180,14 @@ void GrCoverageCountingPathRenderer::recordOp(std::unique_ptr<GrCCDrawPathsOp> o
op->cast<GrCCDrawPathsOp>()->addToOwningPerOpsTaskPaths(
sk_ref_sp(this->lookupPendingPaths(opsTaskID)));
};
- args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op),
+ args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op),
addToOwningPerOpsTaskPaths);
}
}
std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor(
- uint32_t opsTaskID, const SkPath& deviceSpacePath, const SkIRect& accessRect,
- const GrCaps& caps) {
+ std::unique_ptr<GrFragmentProcessor> inputFP, uint32_t opsTaskID,
+ const SkPath& deviceSpacePath, const SkIRect& accessRect, const GrCaps& caps) {
SkASSERT(!fFlushing);
uint32_t key = deviceSpacePath.getGenerationID();
@@ -221,7 +218,8 @@ std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipPro
CoverageType::kFP16_CoverageCount == fCoverageType);
auto mustCheckBounds = GrCCClipProcessor::MustCheckBounds(
!clipPath.pathDevIBounds().contains(accessRect));
- return std::make_unique<GrCCClipProcessor>(caps, &clipPath, isCoverageCount, mustCheckBounds);
+ return std::make_unique<GrCCClipProcessor>(
+ std::move(inputFP), caps, &clipPath, isCoverageCount, mustCheckBounds);
}
void GrCoverageCountingPathRenderer::preFlush(
diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.h b/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.h
index a3107057b44..e5e09472f00 100644
--- a/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.h
+++ b/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer.h
@@ -63,8 +63,8 @@ public:
}
std::unique_ptr<GrFragmentProcessor> makeClipProcessor(
- uint32_t oplistID, const SkPath& deviceSpacePath, const SkIRect& accessRect,
- const GrCaps&);
+ std::unique_ptr<GrFragmentProcessor> inputFP, uint32_t opsTaskID,
+ const SkPath& deviceSpacePath, const SkIRect& accessRect, const GrCaps& caps);
// GrOnFlushCallbackObject overrides.
void preFlush(GrOnFlushResourceProvider*, const uint32_t* opsTaskIDs,
diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer_none.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer_none.cpp
index 1b2a55e0e70..72d443c6949 100644
--- a/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer_none.cpp
+++ b/chromium/third_party/skia/src/gpu/ccpr/GrCoverageCountingPathRenderer_none.cpp
@@ -17,7 +17,7 @@ sk_sp<GrCoverageCountingPathRenderer> GrCoverageCountingPathRenderer::CreateIfSu
}
std::unique_ptr<GrFragmentProcessor> GrCoverageCountingPathRenderer::makeClipProcessor(
- uint32_t opsTaskID, const SkPath& deviceSpacePath, const SkIRect& accessRect,
- const GrCaps& caps) {
+ std::unique_ptr<GrFragmentProcessor> inputFP, uint32_t opsTaskID,
+ const SkPath& deviceSpacePath, const SkIRect& accessRect, const GrCaps& caps) {
return nullptr;
}
diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrGSCoverageProcessor.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrGSCoverageProcessor.cpp
index feaac1a1439..44e2def7264 100644
--- a/chromium/third_party/skia/src/gpu/ccpr/GrGSCoverageProcessor.cpp
+++ b/chromium/third_party/skia/src/gpu/ccpr/GrGSCoverageProcessor.cpp
@@ -25,7 +25,7 @@ protected:
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
const CoordTransformRange& transformRange) final {
- this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
}
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
diff --git a/chromium/third_party/skia/src/gpu/ccpr/GrVSCoverageProcessor.cpp b/chromium/third_party/skia/src/gpu/ccpr/GrVSCoverageProcessor.cpp
index ee3ce647edb..0270cbf89af 100644
--- a/chromium/third_party/skia/src/gpu/ccpr/GrVSCoverageProcessor.cpp
+++ b/chromium/third_party/skia/src/gpu/ccpr/GrVSCoverageProcessor.cpp
@@ -20,7 +20,7 @@ public:
private:
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
const CoordTransformRange& transformRange) final {
- this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
}
void onEmitCode(EmitArgs&, GrGPArgs*) override;
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DAttachmentViewManager.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DAttachmentViewManager.cpp
deleted file mode 100644
index 7536f590918..00000000000
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DAttachmentViewManager.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2020 Google LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "src/gpu/d3d/GrD3DAttachmentViewManager.h"
-
-#include "src/gpu/d3d/GrD3DGpu.h"
-
-GrD3DAttachmentViewManager::GrD3DAttachmentViewManager(GrD3DGpu* gpu)
- : fRTVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_RTV)
- , fDSVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_DSV) {}
-
-D3D12_CPU_DESCRIPTOR_HANDLE GrD3DAttachmentViewManager::createRenderTargetView(
- GrD3DGpu* gpu, ID3D12Resource* textureResource) {
- D3D12_CPU_DESCRIPTOR_HANDLE descriptor = fRTVDescriptorPool.allocateHandle(gpu);
- gpu->device()->CreateRenderTargetView(textureResource, nullptr, descriptor);
- return descriptor;
-}
-
-void GrD3DAttachmentViewManager::recycleRenderTargetView(
- D3D12_CPU_DESCRIPTOR_HANDLE* rtvDescriptor) {
- fRTVDescriptorPool.releaseHandle(rtvDescriptor);
-}
-
-D3D12_CPU_DESCRIPTOR_HANDLE GrD3DAttachmentViewManager::createDepthStencilView(
- GrD3DGpu* gpu, ID3D12Resource* textureResource) {
- D3D12_CPU_DESCRIPTOR_HANDLE descriptor = fDSVDescriptorPool.allocateHandle(gpu);
- gpu->device()->CreateDepthStencilView(textureResource, nullptr, descriptor);
- return descriptor;
-}
-
-void GrD3DAttachmentViewManager::recycleDepthStencilView(
- D3D12_CPU_DESCRIPTOR_HANDLE* dsvDescriptor) {
- fDSVDescriptorPool.releaseHandle(dsvDescriptor);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-
-std::unique_ptr<GrD3DAttachmentViewManager::Heap> GrD3DAttachmentViewManager::Heap::Make(
- GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, unsigned int numDescriptors) {
- std::unique_ptr<GrD3DDescriptorHeap> heap =
- GrD3DDescriptorHeap::Make(gpu, type, numDescriptors, D3D12_DESCRIPTOR_HEAP_FLAG_NONE);
- if (!heap) {
- return nullptr;
- }
-
- return std::unique_ptr<Heap>(new Heap(heap, numDescriptors));
-
-}
-
-D3D12_CPU_DESCRIPTOR_HANDLE GrD3DAttachmentViewManager::Heap::allocateCPUHandle() {
- SkBitSet::OptionalIndex freeBlock = fFreeBlocks.findFirst();
- SkASSERT(freeBlock);
- fFreeBlocks.reset(*freeBlock);
- --fFreeCount;
- return fHeap->getCPUHandle(*freeBlock);
-}
-
-bool GrD3DAttachmentViewManager::Heap::freeCPUHandle(D3D12_CPU_DESCRIPTOR_HANDLE* handle) {
- size_t index;
- if (!fHeap->getIndex(*handle, &index)) {
- return false;
- }
- fFreeBlocks.set(index);
- ++fFreeCount;
- handle->ptr = 0;
- return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-
-GrD3DAttachmentViewManager::HeapPool::HeapPool(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE heapType)
- : fMaxAvailableDescriptors(32)
- , fHeapType(heapType) {
- std::unique_ptr<GrD3DAttachmentViewManager::Heap> heap =
- GrD3DAttachmentViewManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors);
- fDescriptorHeaps.push_back(std::move(heap));
-}
-
-D3D12_CPU_DESCRIPTOR_HANDLE GrD3DAttachmentViewManager::HeapPool::allocateHandle(GrD3DGpu* gpu) {
- for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) {
- if (fDescriptorHeaps[i]->canAllocate()) {
- D3D12_CPU_DESCRIPTOR_HANDLE handle = fDescriptorHeaps[i]->allocateCPUHandle();
- return handle;
- }
- }
-
- // need to allocate more space
- std::unique_ptr<GrD3DAttachmentViewManager::Heap> heap =
- GrD3DAttachmentViewManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors);
-
- fDescriptorHeaps.push_back(std::move(heap));
- fMaxAvailableDescriptors *= 2;
- D3D12_CPU_DESCRIPTOR_HANDLE handle =
- fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateCPUHandle();
- return handle;
-}
-
-void GrD3DAttachmentViewManager::HeapPool::releaseHandle(
- D3D12_CPU_DESCRIPTOR_HANDLE* dsvDescriptor) {
- for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) {
- if (fDescriptorHeaps[i]->freeCPUHandle(dsvDescriptor)) {
- return;
- }
- }
- SkASSERT(false);
-}
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DAttachmentViewManager.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DAttachmentViewManager.h
deleted file mode 100644
index 3424ba39f94..00000000000
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DAttachmentViewManager.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2020 Google LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrD3DAttachmentViewManager_DEFINED
-#define GrD3DAttachmentViewManager_DEFINED
-
-#include "src/gpu/d3d/GrD3DDescriptorHeap.h"
-
-class GrD3DGpu;
-
-class GrD3DAttachmentViewManager {
-public:
- GrD3DAttachmentViewManager(GrD3DGpu*);
-
- D3D12_CPU_DESCRIPTOR_HANDLE createRenderTargetView(GrD3DGpu*, ID3D12Resource* textureResource);
- void recycleRenderTargetView(D3D12_CPU_DESCRIPTOR_HANDLE*);
-
- D3D12_CPU_DESCRIPTOR_HANDLE createDepthStencilView(GrD3DGpu*, ID3D12Resource* textureResource);
- void recycleDepthStencilView(D3D12_CPU_DESCRIPTOR_HANDLE*);
-
-private:
- class Heap {
- public:
- static std::unique_ptr<Heap> Make(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type,
- unsigned int numDescriptors);
-
- D3D12_CPU_DESCRIPTOR_HANDLE allocateCPUHandle();
- bool freeCPUHandle(D3D12_CPU_DESCRIPTOR_HANDLE*);
-
- bool canAllocate() { return fFreeCount > 0; }
-
- private:
- Heap(std::unique_ptr<GrD3DDescriptorHeap>& heap, unsigned int numDescriptors)
- : fHeap(std::move(heap))
- , fFreeBlocks(numDescriptors)
- , fFreeCount(numDescriptors) {
- for (unsigned int i = 0; i < numDescriptors; ++i) {
- fFreeBlocks.set(i);
- }
- }
-
- std::unique_ptr<GrD3DDescriptorHeap> fHeap;
- SkBitSet fFreeBlocks;
- unsigned int fFreeCount;
- };
-
- class HeapPool {
- public:
- HeapPool(GrD3DGpu*, D3D12_DESCRIPTOR_HEAP_TYPE);
-
- D3D12_CPU_DESCRIPTOR_HANDLE allocateHandle(GrD3DGpu*);
- void releaseHandle(D3D12_CPU_DESCRIPTOR_HANDLE*);
-
- private:
- std::vector<std::unique_ptr<Heap>> fDescriptorHeaps;
- int fMaxAvailableDescriptors;
- D3D12_DESCRIPTOR_HEAP_TYPE fHeapType;
- };
-
- HeapPool fRTVDescriptorPool;
- HeapPool fDSVDescriptorPool;
-};
-
-#endif
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.cpp
index 7462feb392d..108e9d11571 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.cpp
@@ -24,8 +24,8 @@ sk_sp<GrD3DBuffer::Resource> GrD3DBuffer::Resource::Make(GrD3DGpu* gpu, size_t s
SkASSERT(intendedType != GrGpuBufferType::kXferCpuToGpu &&
intendedType != GrGpuBufferType::kXferGpuToCpu);
heapType = D3D12_HEAP_TYPE_DEFAULT;
- // Can be transitioned to different states
- *resourceState = D3D12_RESOURCE_STATE_COMMON;
+ // Needs to be transitioned to appropriate state to be read in shader
+ *resourceState = D3D12_RESOURCE_STATE_COPY_DEST;
} else {
if (intendedType == GrGpuBufferType::kXferGpuToCpu) {
heapType = D3D12_HEAP_TYPE_READBACK;
@@ -101,6 +101,26 @@ GrD3DBuffer::GrD3DBuffer(GrD3DGpu* gpu, size_t size, GrGpuBufferType intendedTyp
VALIDATE();
}
+void GrD3DBuffer::setResourceState(const GrD3DGpu* gpu,
+ D3D12_RESOURCE_STATES newResourceState) {
+ if (newResourceState == fResourceState ||
+ // GENERIC_READ encapsulates a lot of different read states
+ (fResourceState == D3D12_RESOURCE_STATE_GENERIC_READ &&
+ SkToBool(newResourceState | fResourceState))) {
+ return;
+ }
+
+ D3D12_RESOURCE_TRANSITION_BARRIER barrier = {};
+ barrier.pResource = this->d3dResource();
+ barrier.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ barrier.StateBefore = fResourceState;
+ barrier.StateAfter = newResourceState;
+
+ gpu->addResourceBarriers(this->resource(), 1, &barrier);
+
+ fResourceState = newResourceState;
+}
+
void GrD3DBuffer::onRelease() {
if (!this->wasDestroyed()) {
VALIDATE();
@@ -169,10 +189,6 @@ void GrD3DBuffer::internalMap(size_t size) {
VALIDATE();
if (this->accessPattern() == kStatic_GrAccessPattern) {
-#ifdef SK_BUILD_FOR_MAC
- // Mac requires 4-byte alignment for copies so we pad this out
- sizeInBytes = SkAlign4(sizeInBytes);
-#endif
// TODO: should use a slice of a previously allocated UPLOAD buffer
D3D12_RESOURCE_STATES resourceState; // not used, just to pass to make
fMappedResource = Resource::Make(this->getD3DGpu(), size, GrGpuBufferType::kXferCpuToGpu,
@@ -215,15 +231,10 @@ void GrD3DBuffer::internalUnmap(size_t size) {
range.Begin = 0;
range.End = size;
fMappedResource->fD3DResource->Unmap(0, &range);
- // TODO
- // let the D3DGpu make this decision?
- //if (size == this->size()) {
- // this->getD3DGpu()->copyResource(this->d3dResource(), fMappedResource->fD3DResource);
-
- //} else {
- // this->getD3DGpu()->copyBufferRegion(this->d3dResource(), 0,
- // fMappedResource->fD3DResource, 0, size);
- //}
+ this->setResourceState(this->getD3DGpu(), D3D12_RESOURCE_STATE_COPY_DEST);
+ this->getD3DGpu()->currentCommandList()->copyBufferToBuffer(
+ fResource, fResource->fD3DResource.get(), 0,
+ fMappedResource, fMappedResource->fD3DResource.get(), 0, size);
} else {
D3D12_RANGE range;
range.Begin = 0;
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.h
index e2d1efc55de..00611728fc6 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DBuffer.h
@@ -37,6 +37,8 @@ public:
return fResource;
}
+ void setResourceState(const GrD3DGpu* gpu, D3D12_RESOURCE_STATES newResourceState);
+
protected:
GrD3DBuffer(GrD3DGpu*, size_t size, GrGpuBufferType, GrAccessPattern, const sk_sp<Resource>&,
D3D12_RESOURCE_STATES);
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.cpp
index df17463d607..e6b00dc73b5 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.cpp
@@ -10,6 +10,7 @@
#include "include/gpu/d3d/GrD3DTypes.h"
#include "src/core/SkCompressedDataUtils.h"
+#include "src/gpu/GrBackendUtils.h"
#include "src/gpu/GrProgramDesc.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrShaderCaps.h"
@@ -773,20 +774,6 @@ bool GrD3DCaps::isFormatSRGB(const GrBackendFormat& format) const {
}
}
-SkImage::CompressionType GrD3DCaps::compressionType(const GrBackendFormat& format) const {
- DXGI_FORMAT dxgiFormat;
- if (!format.asDxgiFormat(&dxgiFormat)) {
- return SkImage::CompressionType::kNone;
- }
-
- switch (dxgiFormat) {
- case DXGI_FORMAT_BC1_UNORM: return SkImage::CompressionType::kBC1_RGBA8_UNORM;
- default: return SkImage::CompressionType::kNone;
- }
-
- SkUNREACHABLE;
-}
-
bool GrD3DCaps::isFormatTexturable(const GrBackendFormat& format) const {
DXGI_FORMAT dxgiFormat;
if (!format.asDxgiFormat(&dxgiFormat)) {
@@ -944,12 +931,6 @@ bool GrD3DCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
return false;
}
- SkImage::CompressionType compression = GrDxgiFormatToCompressionType(dxgiFormat);
- if (compression != SkImage::CompressionType::kNone) {
- return ct == (SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
- : GrColorType::kRGBA_8888);
- }
-
const auto& info = this->getFormatInfo(dxgiFormat);
for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
if (info.fColorTypeInfos[i].fColorType == ct) {
@@ -982,7 +963,7 @@ GrBackendFormat GrD3DCaps::getBackendFormatFromCompressionType(
SkUNREACHABLE;
}
-GrSwizzle GrD3DCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
+GrSwizzle GrD3DCaps::onGetReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
DXGI_FORMAT dxgiFormat;
SkAssertResult(format.asDxgiFormat(&dxgiFormat));
const auto& info = this->getFormatInfo(dxgiFormat);
@@ -1025,7 +1006,7 @@ GrCaps::SupportedRead GrD3DCaps::onSupportedReadPixelsColorType(
return { GrColorType::kUnknown, 0 };
}
- SkImage::CompressionType compression = GrDxgiFormatToCompressionType(dxgiFormat);
+ SkImage::CompressionType compression = GrBackendFormatToCompressionType(srcBackendFormat);
if (compression != SkImage::CompressionType::kNone) {
return { SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
: GrColorType::kRGBA_8888, 0 };
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.h
index 1c4fefb52db..2e05f117b52 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DCaps.h
@@ -29,7 +29,6 @@ public:
GrD3DCaps(const GrContextOptions& contextOptions, IDXGIAdapter1*, ID3D12Device*);
bool isFormatSRGB(const GrBackendFormat&) const override;
- SkImage::CompressionType compressionType(const GrBackendFormat&) const override;
bool isFormatTexturable(const GrBackendFormat&) const override;
bool isFormatTexturable(DXGI_FORMAT) const;
@@ -93,7 +92,6 @@ public:
return fColorTypeToFormatTable[idx];
}
- GrSwizzle getReadSwizzle(const GrBackendFormat&, GrColorType) const override;
GrSwizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override;
uint64_t computeFormatKey(const GrBackendFormat&) const override;
@@ -139,6 +137,8 @@ private:
SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&,
GrColorType) const override;
+ GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override;
+
// ColorTypeInfo for a specific format
struct ColorTypeInfo {
GrColorType fColorType = GrColorType::kUnknown;
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.cpp
index 1216b93f17b..a422622116d 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.cpp
@@ -7,10 +7,13 @@
#include "src/gpu/d3d/GrD3DCommandList.h"
+#include "src/gpu/GrScissorState.h"
#include "src/gpu/d3d/GrD3DBuffer.h"
#include "src/gpu/d3d/GrD3DGpu.h"
#include "src/gpu/d3d/GrD3DPipelineState.h"
#include "src/gpu/d3d/GrD3DRenderTarget.h"
+#include "src/gpu/d3d/GrD3DStencilAttachment.h"
+#include "src/gpu/d3d/GrD3DTexture.h"
#include "src/gpu/d3d/GrD3DTextureResource.h"
GrD3DCommandList::GrD3DCommandList(gr_cp<ID3D12CommandAllocator> allocator,
@@ -30,6 +33,7 @@ bool GrD3DCommandList::close() {
GrD3DCommandList::SubmitResult GrD3DCommandList::submit(ID3D12CommandQueue* queue) {
SkASSERT(fIsActive);
if (!this->hasWork()) {
+ this->callFinishedCallbacks();
return SubmitResult::kNoWork;
}
@@ -49,6 +53,7 @@ void GrD3DCommandList::reset() {
SkASSERT(SUCCEEDED(hr));
SkDEBUGCODE(hr = ) fCommandList->Reset(fAllocator.get(), nullptr);
SkASSERT(SUCCEEDED(hr));
+ this->onReset();
this->releaseResources();
@@ -73,6 +78,12 @@ void GrD3DCommandList::releaseResources() {
fTrackedResources.reset();
fTrackedRecycledResources.reset();
+
+ this->callFinishedCallbacks();
+}
+
+void GrD3DCommandList::addFinishedCallback(sk_sp<GrRefCntedCallback> callback) {
+ fFinishedCallbacks.push_back(std::move(callback));
}
////////////////////////////////////////////////////////////////////////////////
@@ -81,7 +92,7 @@ void GrD3DCommandList::releaseResources() {
void GrD3DCommandList::resourceBarrier(sk_sp<GrManagedResource> resource,
int numBarriers,
- D3D12_RESOURCE_TRANSITION_BARRIER* barriers) {
+ const D3D12_RESOURCE_TRANSITION_BARRIER* barriers) {
SkASSERT(fIsActive);
SkASSERT(barriers);
for (int i = 0; i < numBarriers; ++i) {
@@ -108,8 +119,8 @@ void GrD3DCommandList::submitResourceBarriers() {
SkASSERT(!fResourceBarriers.count());
}
-void GrD3DCommandList::copyBufferToTexture(GrD3DBuffer* srcBuffer,
- GrD3DTextureResource* dstTexture,
+void GrD3DCommandList::copyBufferToTexture(const GrD3DBuffer* srcBuffer,
+ const GrD3DTextureResource* dstTexture,
uint32_t subresourceCount,
D3D12_PLACED_SUBRESOURCE_FOOTPRINT* bufferFootprints,
int left, int top) {
@@ -148,14 +159,23 @@ void GrD3DCommandList::copyTextureRegion(sk_sp<GrManagedResource> dst,
fCommandList->CopyTextureRegion(dstLocation, dstX, dstY, 0, srcLocation, srcBox);
}
-void GrD3DCommandList::clearRenderTargetView(GrD3DRenderTarget* renderTarget,
- const SkPMColor4f& color,
- const GrFixedClip& clip) {
+void GrD3DCommandList::copyBufferToBuffer(sk_sp<GrManagedResource> dst,
+ ID3D12Resource* dstBuffer, uint64_t dstOffset,
+ sk_sp<GrManagedResource> src,
+ ID3D12Resource* srcBuffer, uint64_t srcOffset,
+ uint64_t numBytes) {
+ SkASSERT(fIsActive);
+
this->addingWork();
- this->addResource(renderTarget->resource());
- fCommandList->ClearRenderTargetView(renderTarget->colorRenderTargetView(),
- color.vec(),
- 0, NULL); // no cliprects for now
+ this->addResource(dst);
+ this->addResource(src);
+ uint64_t dstSize = dstBuffer->GetDesc().Width;
+ uint64_t srcSize = srcBuffer->GetDesc().Width;
+ if (dstSize == srcSize && srcSize == numBytes) {
+ fCommandList->CopyResource(dstBuffer, srcBuffer);
+ } else {
+ fCommandList->CopyBufferRegion(dstBuffer, dstOffset, srcBuffer, srcOffset, numBytes);
+ }
}
void GrD3DCommandList::addingWork() {
@@ -183,7 +203,31 @@ std::unique_ptr<GrD3DDirectCommandList> GrD3DDirectCommandList::Make(ID3D12Devic
GrD3DDirectCommandList::GrD3DDirectCommandList(gr_cp<ID3D12CommandAllocator> allocator,
gr_cp<ID3D12GraphicsCommandList> commandList)
- : GrD3DCommandList(std::move(allocator), std::move(commandList)) {
+ : GrD3DCommandList(std::move(allocator), std::move(commandList))
+ , fCurrentRootSignature(nullptr)
+ , fCurrentVertexBuffer(nullptr)
+ , fCurrentVertexStride(0)
+ , fCurrentInstanceBuffer(nullptr)
+ , fCurrentInstanceStride(0)
+ , fCurrentIndexBuffer(nullptr)
+ , fCurrentConstantRingBuffer(nullptr)
+ , fCurrentSRVCRVDescriptorHeap(nullptr)
+ , fCurrentSamplerDescriptorHeap(nullptr) {
+}
+
+void GrD3DDirectCommandList::onReset() {
+ fCurrentRootSignature = nullptr;
+ fCurrentVertexBuffer = nullptr;
+ fCurrentVertexStride = 0;
+ fCurrentInstanceBuffer = nullptr;
+ fCurrentInstanceStride = 0;
+ fCurrentIndexBuffer = nullptr;
+ if (fCurrentConstantRingBuffer) {
+ fCurrentConstantRingBuffer->finishSubmit(fConstantRingBufferSubmitData);
+ fCurrentConstantRingBuffer = nullptr;
+ }
+ fCurrentSRVCRVDescriptorHeap = nullptr;
+ fCurrentSamplerDescriptorHeap = nullptr;
}
void GrD3DDirectCommandList::setPipelineState(sk_sp<GrD3DPipelineState> pipelineState) {
@@ -192,6 +236,16 @@ void GrD3DDirectCommandList::setPipelineState(sk_sp<GrD3DPipelineState> pipeline
this->addResource(std::move(pipelineState));
}
+void GrD3DDirectCommandList::setCurrentConstantBuffer(
+ const sk_sp<GrD3DConstantRingBuffer>& constantBuffer) {
+ fCurrentConstantRingBuffer = constantBuffer.get();
+ if (fCurrentConstantRingBuffer) {
+ fConstantRingBufferSubmitData = constantBuffer->startSubmit();
+ this->addResource(
+ static_cast<GrD3DBuffer*>(fConstantRingBufferSubmitData.buffer())->resource());
+ }
+}
+
void GrD3DDirectCommandList::setStencilRef(unsigned int stencilRef) {
SkASSERT(fIsActive);
fCommandList->OMSetStencilRef(stencilRef);
@@ -218,6 +272,150 @@ void GrD3DDirectCommandList::setViewports(unsigned int numViewports,
fCommandList->RSSetViewports(numViewports, viewports);
}
+void GrD3DDirectCommandList::setGraphicsRootSignature(const sk_sp<GrD3DRootSignature>& rootSig) {
+ SkASSERT(fIsActive);
+ if (fCurrentRootSignature != rootSig.get()) {
+ fCommandList->SetGraphicsRootSignature(rootSig->rootSignature());
+ this->addResource(rootSig);
+ fCurrentRootSignature = rootSig.get();
+ }
+}
+
+void GrD3DDirectCommandList::setVertexBuffers(unsigned int startSlot,
+ const GrD3DBuffer* vertexBuffer,
+ size_t vertexStride,
+ const GrD3DBuffer* instanceBuffer,
+ size_t instanceStride) {
+ if (fCurrentVertexBuffer != vertexBuffer || fCurrentVertexStride != vertexStride ||
+ fCurrentInstanceBuffer != instanceBuffer || fCurrentInstanceStride != instanceStride) {
+ this->addResource(vertexBuffer->resource());
+
+ D3D12_VERTEX_BUFFER_VIEW views[2];
+ int numViews = 0;
+ views[numViews].BufferLocation = vertexBuffer->d3dResource()->GetGPUVirtualAddress();
+ views[numViews].SizeInBytes = vertexBuffer->size();
+ views[numViews++].StrideInBytes = vertexStride;
+ if (instanceBuffer) {
+ this->addResource(instanceBuffer->resource());
+ views[numViews].BufferLocation = instanceBuffer->d3dResource()->GetGPUVirtualAddress();
+ views[numViews].SizeInBytes = instanceBuffer->size();
+ views[numViews++].StrideInBytes = instanceStride;
+ }
+ fCommandList->IASetVertexBuffers(startSlot, numViews, views);
+
+ fCurrentVertexBuffer = vertexBuffer;
+ fCurrentVertexStride = vertexStride;
+ fCurrentInstanceBuffer = instanceBuffer;
+ fCurrentInstanceStride = instanceStride;
+ }
+}
+
+void GrD3DDirectCommandList::setIndexBuffer(const GrD3DBuffer* indexBuffer) {
+ if (fCurrentIndexBuffer != indexBuffer) {
+ this->addResource(indexBuffer->resource());
+
+ D3D12_INDEX_BUFFER_VIEW view = {};
+ view.BufferLocation = indexBuffer->d3dResource()->GetGPUVirtualAddress();
+ view.SizeInBytes = indexBuffer->size();
+ view.Format = DXGI_FORMAT_R16_UINT;
+ fCommandList->IASetIndexBuffer(&view);
+ }
+}
+
+void GrD3DDirectCommandList::drawInstanced(unsigned int vertexCount, unsigned int instanceCount,
+ unsigned int startVertex, unsigned int startInstance) {
+ SkASSERT(fIsActive);
+ this->addingWork();
+ fCommandList->DrawInstanced(vertexCount, instanceCount, startVertex, startInstance);
+}
+
+void GrD3DDirectCommandList::drawIndexedInstanced(unsigned int indexCount,
+ unsigned int instanceCount,
+ unsigned int startIndex,
+ unsigned int baseVertex,
+ unsigned int startInstance) {
+ SkASSERT(fIsActive);
+ this->addingWork();
+ fCommandList->DrawIndexedInstanced(indexCount, instanceCount, startIndex, baseVertex,
+ startInstance);
+}
+
+void GrD3DDirectCommandList::clearRenderTargetView(const GrD3DRenderTarget* renderTarget,
+ const SkPMColor4f& color,
+ const D3D12_RECT* rect) {
+ this->addingWork();
+ this->addResource(renderTarget->resource());
+ if (renderTarget->numSamples() > 1) {
+ this->addResource(renderTarget->msaaTextureResource()->resource());
+ }
+ unsigned int numRects = rect ? 1 : 0;
+ fCommandList->ClearRenderTargetView(renderTarget->colorRenderTargetView(),
+ color.vec(), numRects, rect);
+}
+
+void GrD3DDirectCommandList::clearDepthStencilView(const GrD3DStencilAttachment* stencil,
+ uint8_t stencilClearValue,
+ const D3D12_RECT* rect) {
+ this->addingWork();
+ this->addResource(stencil->resource());
+ unsigned int numRects = rect ? 1 : 0;
+ fCommandList->ClearDepthStencilView(stencil->view(), D3D12_CLEAR_FLAG_STENCIL, 0,
+ stencilClearValue, numRects, rect);
+}
+
+void GrD3DDirectCommandList::setRenderTarget(const GrD3DRenderTarget* renderTarget) {
+ this->addingWork();
+ this->addResource(renderTarget->resource());
+ if (renderTarget->numSamples() > 1) {
+ this->addResource(renderTarget->msaaTextureResource()->resource());
+ }
+ D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = renderTarget->colorRenderTargetView();
+
+ D3D12_CPU_DESCRIPTOR_HANDLE dsDescriptor;
+ D3D12_CPU_DESCRIPTOR_HANDLE* dsDescriptorPtr = nullptr;
+ if (auto stencil = renderTarget->renderTargetPriv().getStencilAttachment()) {
+ GrD3DStencilAttachment* d3dStencil = static_cast<GrD3DStencilAttachment*>(stencil);
+ this->addResource(d3dStencil->resource());
+ dsDescriptor = d3dStencil->view();
+ dsDescriptorPtr = &dsDescriptor;
+ }
+
+ fCommandList->OMSetRenderTargets(1, &rtvDescriptor, false, dsDescriptorPtr);
+}
+
+void GrD3DDirectCommandList::setGraphicsRootConstantBufferView(
+ unsigned int rootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS bufferLocation) {
+ fCommandList->SetGraphicsRootConstantBufferView(rootParameterIndex, bufferLocation);
+}
+
+void GrD3DDirectCommandList::setGraphicsRootDescriptorTable(
+ unsigned int rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor) {
+ fCommandList->SetGraphicsRootDescriptorTable(rootParameterIndex, baseDescriptor);
+}
+
+void GrD3DDirectCommandList::setDescriptorHeaps(sk_sp<GrRecycledResource> srvCrvHeapResource,
+ ID3D12DescriptorHeap* srvCrvDescriptorHeap,
+ sk_sp<GrRecycledResource> samplerHeapResource,
+ ID3D12DescriptorHeap* samplerDescriptorHeap) {
+ if (srvCrvDescriptorHeap != fCurrentSRVCRVDescriptorHeap ||
+ samplerDescriptorHeap != fCurrentSamplerDescriptorHeap) {
+ ID3D12DescriptorHeap* heaps[2] = {
+ srvCrvDescriptorHeap,
+ samplerDescriptorHeap
+ };
+
+ fCommandList->SetDescriptorHeaps(2, heaps);
+ this->addRecycledResource(std::move(srvCrvHeapResource));
+ this->addRecycledResource(std::move(samplerHeapResource));
+ fCurrentSRVCRVDescriptorHeap = srvCrvDescriptorHeap;
+ fCurrentSamplerDescriptorHeap = samplerDescriptorHeap;
+ }
+}
+
+void GrD3DDirectCommandList::addSampledTextureRef(GrD3DTexture* texture) {
+ this->addResource(texture->resource());
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////
std::unique_ptr<GrD3DCopyCommandList> GrD3DCopyCommandList::Make(ID3D12Device* device) {
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.h
index 781f8f7c52d..4bea28bad1e 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DCommandList.h
@@ -12,20 +12,25 @@
#include "include/gpu/d3d/GrD3DTypes.h"
#include "include/private/SkColorData.h"
#include "src/gpu/GrManagedResource.h"
+#include "src/gpu/d3d/GrD3DConstantRingBuffer.h"
#include <memory>
class GrD3DGpu;
class GrD3DBuffer;
+class GrD3DConstantRingBuffer;
class GrD3DPipelineState;
class GrD3DRenderTarget;
+class GrD3DRootSignature;
+class GrD3DStencilAttachment;
+class GrD3DTexture;
class GrD3DTextureResource;
-class GrFixedClip;
+class GrScissorState;
class GrD3DCommandList {
public:
- ~GrD3DCommandList() {
+ virtual ~GrD3DCommandList() {
this->releaseResources();
}
@@ -47,11 +52,11 @@ public:
// All barriers should reference subresources of managedResource
void resourceBarrier(sk_sp<GrManagedResource> managedResource,
int numBarriers,
- D3D12_RESOURCE_TRANSITION_BARRIER* barriers);
+ const D3D12_RESOURCE_TRANSITION_BARRIER* barriers);
// Helper method that calls copyTextureRegion multiple times, once for each subresource
- void copyBufferToTexture(GrD3DBuffer* srcBuffer,
- GrD3DTextureResource* dstTexture,
+ void copyBufferToTexture(const GrD3DBuffer* srcBuffer,
+ const GrD3DTextureResource* dstTexture,
uint32_t subresourceCount,
D3D12_PLACED_SUBRESOURCE_FOOTPRINT* bufferFootprints,
int left, int top);
@@ -61,9 +66,24 @@ public:
sk_sp<GrManagedResource> src,
const D3D12_TEXTURE_COPY_LOCATION* srcLocation,
const D3D12_BOX* srcBox);
+ void copyBufferToBuffer(sk_sp<GrManagedResource> dst,
+ ID3D12Resource* dstBuffer, uint64_t dstOffset,
+ sk_sp<GrManagedResource> src,
+ ID3D12Resource* srcBuffer, uint64_t srcOffset,
+ uint64_t numBytes);
- void clearRenderTargetView(GrD3DRenderTarget* renderTarget, const SkPMColor4f& color,
- const GrFixedClip& clip);
+ void releaseResources();
+
+ bool hasWork() const { return fHasWork; }
+
+ void addFinishedCallback(sk_sp<GrRefCntedCallback> callback);
+
+private:
+ static const int kInitialTrackedResourcesCount = 32;
+
+protected:
+ GrD3DCommandList(gr_cp<ID3D12CommandAllocator> allocator,
+ gr_cp<ID3D12GraphicsCommandList> commandList);
// Add ref-counted resource that will be tracked and released when this command buffer finishes
// execution
@@ -80,18 +100,8 @@ public:
fTrackedRecycledResources.push_back(std::move(resource));
}
- void releaseResources();
-
- bool hasWork() const { return fHasWork; }
-
-private:
- static const int kInitialTrackedResourcesCount = 32;
-
-protected:
- GrD3DCommandList(gr_cp<ID3D12CommandAllocator> allocator,
- gr_cp<ID3D12GraphicsCommandList> commandList);
-
void addingWork();
+ virtual void onReset() {}
void submitResourceBarriers();
@@ -105,26 +115,76 @@ protected:
bool fHasWork = false;
private:
+ void callFinishedCallbacks() { fFinishedCallbacks.reset(); }
+
gr_cp<ID3D12CommandAllocator> fAllocator;
SkSTArray<4, D3D12_RESOURCE_BARRIER> fResourceBarriers;
+
+ SkTArray<sk_sp<GrRefCntedCallback>> fFinishedCallbacks;
};
class GrD3DDirectCommandList : public GrD3DCommandList {
public:
static std::unique_ptr<GrD3DDirectCommandList> Make(ID3D12Device* device);
+ ~GrD3DDirectCommandList() override = default;
+
void setPipelineState(sk_sp<GrD3DPipelineState> pipelineState);
+ void setCurrentConstantBuffer(const sk_sp<GrD3DConstantRingBuffer>& constantBuffer);
+
void setStencilRef(unsigned int stencilRef);
void setBlendFactor(const float blendFactor[4]);
void setPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY primitiveTopology);
void setScissorRects(unsigned int numRects, const D3D12_RECT* rects);
void setViewports(unsigned int numViewports, const D3D12_VIEWPORT* viewports);
+ void setGraphicsRootSignature(const sk_sp<GrD3DRootSignature>& rootSignature);
+ void setVertexBuffers(unsigned int startSlot,
+ const GrD3DBuffer* vertexBuffer, size_t vertexStride,
+ const GrD3DBuffer* instanceBuffer, size_t instanceStride);
+ void setIndexBuffer(const GrD3DBuffer* indexBuffer);
+ void drawInstanced(unsigned int vertexCount, unsigned int instanceCount,
+ unsigned int startVertex, unsigned int startInstance);
+ void drawIndexedInstanced(unsigned int indexCount, unsigned int instanceCount,
+ unsigned int startIndex, unsigned int baseVertex,
+ unsigned int startInstance);
+
+ void clearRenderTargetView(const GrD3DRenderTarget* renderTarget, const SkPMColor4f& color,
+ const D3D12_RECT* rect);
+ void clearDepthStencilView(const GrD3DStencilAttachment*, uint8_t stencilClearValue,
+ const D3D12_RECT* rect);
+ void setRenderTarget(const GrD3DRenderTarget* renderTarget);
+
+ void setGraphicsRootConstantBufferView(unsigned int rootParameterIndex,
+ D3D12_GPU_VIRTUAL_ADDRESS bufferLocation);
+ void setGraphicsRootDescriptorTable(unsigned int rootParameterIndex,
+ D3D12_GPU_DESCRIPTOR_HANDLE bufferLocation);
+ void setDescriptorHeaps(sk_sp<GrRecycledResource> srvCrvHeapResource,
+ ID3D12DescriptorHeap* srvDescriptorHeap,
+ sk_sp<GrRecycledResource> samplerHeapResource,
+ ID3D12DescriptorHeap* samplerDescriptorHeap);
+
+ void addSampledTextureRef(GrD3DTexture*);
private:
GrD3DDirectCommandList(gr_cp<ID3D12CommandAllocator> allocator,
gr_cp<ID3D12GraphicsCommandList> commandList);
+
+ void onReset() override;
+
+ const GrD3DRootSignature* fCurrentRootSignature;
+ const GrD3DBuffer* fCurrentVertexBuffer;
+ size_t fCurrentVertexStride;
+ const GrD3DBuffer* fCurrentInstanceBuffer;
+ size_t fCurrentInstanceStride;
+ const GrD3DBuffer* fCurrentIndexBuffer;
+
+ GrD3DConstantRingBuffer* fCurrentConstantRingBuffer;
+ GrD3DConstantRingBuffer::SubmitData fConstantRingBufferSubmitData;
+
+ const ID3D12DescriptorHeap* fCurrentSRVCRVDescriptorHeap;
+ const ID3D12DescriptorHeap* fCurrentSamplerDescriptorHeap;
};
class GrD3DCopyCommandList : public GrD3DCommandList {
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DConstantRingBuffer.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DConstantRingBuffer.cpp
new file mode 100644
index 00000000000..cf719c7745b
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DConstantRingBuffer.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/d3d/GrD3DConstantRingBuffer.h"
+
+#include "src/gpu/d3d/GrD3DBuffer.h"
+#include "src/gpu/d3d/GrD3DGpu.h"
+
+sk_sp<GrD3DConstantRingBuffer> GrD3DConstantRingBuffer::Make(GrD3DGpu* gpu, size_t size,
+ size_t alignment) {
+ sk_sp<GrGpuBuffer> buffer = GrD3DBuffer::Make(gpu, size, GrGpuBufferType::kVertex,
+ kDynamic_GrAccessPattern);
+ if (!buffer) {
+ return nullptr;
+ }
+
+ return sk_sp<GrD3DConstantRingBuffer>(new GrD3DConstantRingBuffer(std::move(buffer), size,
+ alignment, gpu));
+}
+
+sk_sp<GrGpuBuffer> GrD3DConstantRingBuffer::createBuffer(size_t size) {
+ // Make sure the old buffer is added to the current command list
+ fGpu->resourceProvider().prepForSubmit();
+
+ return GrD3DBuffer::Make(fGpu, size, GrGpuBufferType::kVertex, kDynamic_GrAccessPattern);
+}
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DConstantRingBuffer.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DConstantRingBuffer.h
new file mode 100644
index 00000000000..0a4bbf60675
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DConstantRingBuffer.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrD3DConstantRingBuffer_DEFINED
+
+#define GrD3DConstantRingBuffer_DEFINED
+
+#include "src/gpu/GrRingBuffer.h"
+
+class GrD3DGpu;
+
+class GrD3DConstantRingBuffer : public GrRingBuffer {
+public:
+ static sk_sp<GrD3DConstantRingBuffer> Make(GrD3DGpu* gpu, size_t size, size_t alignment);
+
+private:
+ GrD3DConstantRingBuffer(sk_sp<GrGpuBuffer> buffer, size_t size, size_t alignment, GrD3DGpu* gpu)
+ : INHERITED(std::move(buffer), size, alignment)
+ , fGpu(gpu) {}
+ ~GrD3DConstantRingBuffer() override = default;
+
+ sk_sp<GrGpuBuffer> createBuffer(size_t size) override;
+
+ GrD3DGpu* fGpu;
+
+ typedef GrRingBuffer INHERITED;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DCpuDescriptorManager.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DCpuDescriptorManager.cpp
new file mode 100644
index 00000000000..3ad33c388ea
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DCpuDescriptorManager.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/d3d/GrD3DCpuDescriptorManager.h"
+
+#include "src/gpu/d3d/GrD3DGpu.h"
+
+GrD3DCpuDescriptorManager::GrD3DCpuDescriptorManager(GrD3DGpu* gpu)
+ : fRTVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_RTV)
+ , fDSVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_DSV)
+ , fCBVSRVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
+ , fSamplerDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) {}
+
+GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createRenderTargetView(
+ GrD3DGpu* gpu, ID3D12Resource* textureResource) {
+ const GrD3DDescriptorHeap::CPUHandle& descriptor = fRTVDescriptorPool.allocateHandle(gpu);
+ gpu->device()->CreateRenderTargetView(textureResource, nullptr, descriptor.fHandle);
+ return descriptor;
+}
+
+void GrD3DCpuDescriptorManager::recycleRenderTargetView(
+ const GrD3DDescriptorHeap::CPUHandle& rtvDescriptor) {
+ fRTVDescriptorPool.releaseHandle(rtvDescriptor);
+}
+
+GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createDepthStencilView(
+ GrD3DGpu* gpu, ID3D12Resource* textureResource) {
+ const GrD3DDescriptorHeap::CPUHandle& descriptor = fDSVDescriptorPool.allocateHandle(gpu);
+ gpu->device()->CreateDepthStencilView(textureResource, nullptr, descriptor.fHandle);
+ return descriptor;
+}
+
+void GrD3DCpuDescriptorManager::recycleDepthStencilView(
+ const GrD3DDescriptorHeap::CPUHandle& dsvDescriptor) {
+ fDSVDescriptorPool.releaseHandle(dsvDescriptor);
+}
+
+GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createConstantBufferView(
+ GrD3DGpu* gpu, ID3D12Resource* bufferResource, size_t offset, size_t size) {
+ const GrD3DDescriptorHeap::CPUHandle& descriptor = fCBVSRVDescriptorPool.allocateHandle(gpu);
+ D3D12_CONSTANT_BUFFER_VIEW_DESC desc = {};
+ desc.BufferLocation = bufferResource->GetGPUVirtualAddress() + offset;
+ desc.SizeInBytes = size;
+ gpu->device()->CreateConstantBufferView(&desc, descriptor.fHandle);
+ return descriptor;
+}
+
+GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createShaderResourceView(
+ GrD3DGpu* gpu, ID3D12Resource* resource) {
+ const GrD3DDescriptorHeap::CPUHandle& descriptor = fCBVSRVDescriptorPool.allocateHandle(gpu);
+ // TODO: for 4:2:0 YUV formats we'll need to map two different views, one for Y and one for UV.
+ // For now map the entire resource.
+ gpu->device()->CreateShaderResourceView(resource, nullptr, descriptor.fHandle);
+ return descriptor;
+}
+
+void GrD3DCpuDescriptorManager::recycleConstantOrShaderView(
+ const GrD3DDescriptorHeap::CPUHandle& view) {
+ fCBVSRVDescriptorPool.releaseHandle(view);
+}
+
+GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createSampler(
+ GrD3DGpu* gpu, D3D12_FILTER filter, D3D12_TEXTURE_ADDRESS_MODE addressModeU,
+ D3D12_TEXTURE_ADDRESS_MODE addressModeV) {
+ const GrD3DDescriptorHeap::CPUHandle& descriptor = fSamplerDescriptorPool.allocateHandle(gpu);
+ D3D12_SAMPLER_DESC desc = {};
+ desc.Filter = filter;
+ desc.AddressU = addressModeU;
+ desc.AddressV = addressModeV;
+ desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+ desc.MipLODBias = 0;
+ desc.MaxAnisotropy = 1;
+ desc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
+ // desc.BorderColor initialized to { 0, 0, 0, 0 } by default initializer, above.
+ desc.MinLOD = 0;
+ desc.MaxLOD = SK_ScalarMax;
+
+ gpu->device()->CreateSampler(&desc, descriptor.fHandle);
+ return descriptor;
+}
+
+void GrD3DCpuDescriptorManager::recycleSampler(
+ const GrD3DDescriptorHeap::CPUHandle& samplerDescriptor) {
+ fSamplerDescriptorPool.releaseHandle(samplerDescriptor);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+std::unique_ptr<GrD3DCpuDescriptorManager::Heap> GrD3DCpuDescriptorManager::Heap::Make(
+ GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, unsigned int numDescriptors) {
+ std::unique_ptr<GrD3DDescriptorHeap> heap =
+ GrD3DDescriptorHeap::Make(gpu, type, numDescriptors, D3D12_DESCRIPTOR_HEAP_FLAG_NONE);
+ if (!heap) {
+ return nullptr;
+ }
+
+ return std::unique_ptr<Heap>(new Heap(heap, numDescriptors));
+}
+
+GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::Heap::allocateCPUHandle() {
+ SkBitSet::OptionalIndex freeBlock = fFreeBlocks.findFirst();
+ SkASSERT(freeBlock);
+ fFreeBlocks.reset(*freeBlock);
+ --fFreeCount;
+ return fHeap->getCPUHandle(*freeBlock);
+}
+
+void GrD3DCpuDescriptorManager::Heap::freeCPUHandle(const GrD3DDescriptorHeap::CPUHandle& handle) {
+ SkASSERT(this->ownsHandle(handle));
+ size_t index = fHeap->getIndex(handle);
+ fFreeBlocks.set(index);
+ ++fFreeCount;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+GrD3DCpuDescriptorManager::HeapPool::HeapPool(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE heapType)
+ : fMaxAvailableDescriptors(32)
+ , fHeapType(heapType) {
+ std::unique_ptr<GrD3DCpuDescriptorManager::Heap> heap =
+ GrD3DCpuDescriptorManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors);
+ fDescriptorHeaps.push_back(std::move(heap));
+}
+
+GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::HeapPool::allocateHandle(
+ GrD3DGpu* gpu) {
+ for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) {
+ if (fDescriptorHeaps[i]->canAllocate()) {
+ GrD3DDescriptorHeap::CPUHandle handle = fDescriptorHeaps[i]->allocateCPUHandle();
+ return handle;
+ }
+ }
+
+ // need to allocate more space
+ std::unique_ptr<GrD3DCpuDescriptorManager::Heap> heap =
+ GrD3DCpuDescriptorManager::Heap::Make(gpu, fHeapType, fMaxAvailableDescriptors);
+
+ fDescriptorHeaps.push_back(std::move(heap));
+ fMaxAvailableDescriptors *= 2;
+ GrD3DDescriptorHeap::CPUHandle handle =
+ fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateCPUHandle();
+ return handle;
+}
+
+void GrD3DCpuDescriptorManager::HeapPool::releaseHandle(
+ const GrD3DDescriptorHeap::CPUHandle& dsvDescriptor) {
+ for (unsigned int i = 0; i < fDescriptorHeaps.size(); ++i) {
+ if (fDescriptorHeaps[i]->ownsHandle(dsvDescriptor)) {
+ fDescriptorHeaps[i]->freeCPUHandle(dsvDescriptor);
+ return;
+ }
+ }
+ SkASSERT(false);
+}
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DCpuDescriptorManager.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DCpuDescriptorManager.h
new file mode 100644
index 00000000000..056c6968738
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DCpuDescriptorManager.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrD3DCpuDescriptorManager_DEFINED
+#define GrD3DCpuDescriptorManager_DEFINED
+
+#include "src/gpu/d3d/GrD3DDescriptorHeap.h"
+
+class GrD3DGpu;
+
+class GrD3DCpuDescriptorManager {
+public:
+ GrD3DCpuDescriptorManager(GrD3DGpu*);
+
+ GrD3DDescriptorHeap::CPUHandle createRenderTargetView(GrD3DGpu*,
+ ID3D12Resource* textureResource);
+ void recycleRenderTargetView(const GrD3DDescriptorHeap::CPUHandle&);
+
+ GrD3DDescriptorHeap::CPUHandle createDepthStencilView(GrD3DGpu*,
+ ID3D12Resource* textureResource);
+ void recycleDepthStencilView(const GrD3DDescriptorHeap::CPUHandle&);
+
+ GrD3DDescriptorHeap::CPUHandle createConstantBufferView(GrD3DGpu*,
+ ID3D12Resource* bufferResource,
+ size_t offset,
+ size_t size);
+ GrD3DDescriptorHeap::CPUHandle createShaderResourceView(GrD3DGpu*,
+ ID3D12Resource* resource);
+ void recycleConstantOrShaderView(const GrD3DDescriptorHeap::CPUHandle&);
+
+ GrD3DDescriptorHeap::CPUHandle createSampler(GrD3DGpu*,
+ D3D12_FILTER filter,
+ D3D12_TEXTURE_ADDRESS_MODE addressModeU,
+ D3D12_TEXTURE_ADDRESS_MODE addressModeV);
+ void recycleSampler(const GrD3DDescriptorHeap::CPUHandle&);
+
+private:
+ class Heap {
+ public:
+ static std::unique_ptr<Heap> Make(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type,
+ unsigned int numDescriptors);
+
+ GrD3DDescriptorHeap::CPUHandle allocateCPUHandle();
+ void freeCPUHandle(const GrD3DDescriptorHeap::CPUHandle&);
+ bool ownsHandle(const GrD3DDescriptorHeap::CPUHandle& handle) {
+ return handle.fHeapID == fHeap->uniqueID();
+ }
+
+ bool canAllocate() { return fFreeCount > 0; }
+
+ private:
+ Heap(std::unique_ptr<GrD3DDescriptorHeap>& heap, unsigned int numDescriptors)
+ : fHeap(std::move(heap))
+ , fFreeBlocks(numDescriptors)
+ , fFreeCount(numDescriptors) {
+ for (unsigned int i = 0; i < numDescriptors; ++i) {
+ fFreeBlocks.set(i);
+ }
+ }
+
+ std::unique_ptr<GrD3DDescriptorHeap> fHeap;
+ SkBitSet fFreeBlocks;
+ unsigned int fFreeCount;
+ };
+
+ class HeapPool {
+ public:
+ HeapPool(GrD3DGpu*, D3D12_DESCRIPTOR_HEAP_TYPE);
+
+ GrD3DDescriptorHeap::CPUHandle allocateHandle(GrD3DGpu*);
+ void releaseHandle(const GrD3DDescriptorHeap::CPUHandle&);
+
+ private:
+ std::vector<std::unique_ptr<Heap>> fDescriptorHeaps;
+ int fMaxAvailableDescriptors;
+ D3D12_DESCRIPTOR_HEAP_TYPE fHeapType;
+ };
+
+ HeapPool fRTVDescriptorPool;
+ HeapPool fDSVDescriptorPool;
+ HeapPool fCBVSRVDescriptorPool;
+ HeapPool fSamplerDescriptorPool;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.cpp
index b3ae3cc330e..8d2569783bf 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.cpp
@@ -28,25 +28,24 @@ std::unique_ptr<GrD3DDescriptorHeap> GrD3DDescriptorHeap::Make(GrD3DGpu* gpu,
GrD3DDescriptorHeap::GrD3DDescriptorHeap(const gr_cp<ID3D12DescriptorHeap>& heap,
unsigned int handleIncrementSize)
: fHeap(heap)
- , fHandleIncrementSize(handleIncrementSize) {
+ , fHandleIncrementSize(handleIncrementSize)
+ , fUniqueID(GenID()) {
fCPUHeapStart = fHeap->GetCPUDescriptorHandleForHeapStart();
fGPUHeapStart = fHeap->GetGPUDescriptorHandleForHeapStart();
}
-D3D12_CPU_DESCRIPTOR_HANDLE GrD3DDescriptorHeap::getCPUHandle(unsigned int index) {
- // valid only for non-shader-visible heaps
- SkASSERT(!SkToBool(fHeap->GetDesc().Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE));
+GrD3DDescriptorHeap::CPUHandle GrD3DDescriptorHeap::getCPUHandle(unsigned int index) {
SkASSERT(index < fHeap->GetDesc().NumDescriptors);
D3D12_CPU_DESCRIPTOR_HANDLE handle = fCPUHeapStart;
handle.ptr += index * fHandleIncrementSize;
- return handle;
+ return {handle, fUniqueID};
}
-D3D12_GPU_DESCRIPTOR_HANDLE GrD3DDescriptorHeap::getGPUHandle(unsigned int index) {
+GrD3DDescriptorHeap::GPUHandle GrD3DDescriptorHeap::getGPUHandle(unsigned int index) {
SkASSERT(index < fHeap->GetDesc().NumDescriptors);
D3D12_GPU_DESCRIPTOR_HANDLE handle = fGPUHeapStart;
handle.ptr += index * fHandleIncrementSize;
- return handle;
+ return {handle, fUniqueID};
}
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.h
index 19e2745011c..30fdc1358eb 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorHeap.h
@@ -22,42 +22,56 @@ public:
~GrD3DDescriptorHeap() = default;
- D3D12_CPU_DESCRIPTOR_HANDLE getCPUHandle(unsigned int index); // only if non-shader-visible
- D3D12_GPU_DESCRIPTOR_HANDLE getGPUHandle(unsigned int index);
-
- bool getIndex(D3D12_CPU_DESCRIPTOR_HANDLE handle, size_t* indexPtr) {
- if (handle.ptr < fCPUHeapStart.ptr) {
- return false;
- }
- size_t index = (handle.ptr - fCPUHeapStart.ptr) / fHandleIncrementSize;
- if (index >= fHeap->GetDesc().NumDescriptors) {
- return false;
- }
- SkASSERT(handle.ptr == fCPUHeapStart.ptr + index * fHandleIncrementSize);
- *indexPtr = index;
- return true;
+ uint32_t uniqueID() const { return fUniqueID; }
+
+ struct CPUHandle {
+ D3D12_CPU_DESCRIPTOR_HANDLE fHandle;
+ uint32_t fHeapID;
+ };
+
+ struct GPUHandle {
+ D3D12_GPU_DESCRIPTOR_HANDLE fHandle;
+ uint32_t fHeapID;
+ };
+
+ CPUHandle getCPUHandle(unsigned int index); // write-only if shader-visible
+ GPUHandle getGPUHandle(unsigned int index);
+ ID3D12DescriptorHeap* descriptorHeap() const { return fHeap.get(); }
+ size_t handleIncrementSize() { return fHandleIncrementSize; }
+
+ size_t getIndex(const CPUHandle& handle) {
+ SkASSERT(handle.fHeapID == fUniqueID);
+ size_t index = (handle.fHandle.ptr - fCPUHeapStart.ptr) / fHandleIncrementSize;
+ SkASSERT(index < fHeap->GetDesc().NumDescriptors);
+ SkASSERT(handle.fHandle.ptr == fCPUHeapStart.ptr + index * fHandleIncrementSize);
+ return index;
}
- bool getIndex(D3D12_GPU_DESCRIPTOR_HANDLE handle, size_t* indexPtr) {
- if (handle.ptr < fGPUHeapStart.ptr) {
- return false;
- }
- size_t index = (handle.ptr - fGPUHeapStart.ptr) / fHandleIncrementSize;
- if (index >= fHeap->GetDesc().NumDescriptors) {
- return false;
- }
- SkASSERT(handle.ptr == fGPUHeapStart.ptr + index * fHandleIncrementSize);
- *indexPtr = index;
- return true;
+ size_t getIndex(const GPUHandle& handle) {
+ SkASSERT(handle.fHeapID == fUniqueID);
+ size_t index = (handle.fHandle.ptr - fCPUHeapStart.ptr) / fHandleIncrementSize;
+ SkASSERT(index < fHeap->GetDesc().NumDescriptors);
+ SkASSERT(handle.fHandle.ptr == fCPUHeapStart.ptr + index * fHandleIncrementSize);
+ return index;
}
protected:
GrD3DDescriptorHeap(const gr_cp<ID3D12DescriptorHeap>&, unsigned int handleIncrementSize);
+ static uint32_t GenID() {
+ static std::atomic<uint32_t> nextID{1};
+ uint32_t id;
+ do {
+ id = nextID++;
+ } while (id == SK_InvalidUniqueID);
+ return id;
+ }
+
gr_cp<ID3D12DescriptorHeap> fHeap;
size_t fHandleIncrementSize;
D3D12_CPU_DESCRIPTOR_HANDLE fCPUHeapStart;
D3D12_GPU_DESCRIPTOR_HANDLE fGPUHeapStart;
+ uint32_t fUniqueID;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorTableManager.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorTableManager.cpp
new file mode 100644
index 00000000000..7bbb95f2450
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorTableManager.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/d3d/GrD3DDescriptorTableManager.h"
+
+#include "src/gpu/d3d/GrD3DGpu.h"
+
+GrD3DDescriptorTableManager::GrD3DDescriptorTableManager(GrD3DGpu* gpu)
+ : fCBVSRVDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
+ , fSamplerDescriptorPool(gpu, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) {}
+
+std::unique_ptr<GrD3DDescriptorTable>
+ GrD3DDescriptorTableManager::createShaderOrConstantResourceTable(GrD3DGpu* gpu,
+ unsigned int size) {
+ std::unique_ptr<GrD3DDescriptorTable> table = fCBVSRVDescriptorPool.allocateTable(gpu, size);
+ this->setHeaps(gpu);
+ return table;
+}
+
+std::unique_ptr<GrD3DDescriptorTable> GrD3DDescriptorTableManager::createSamplerTable(
+ GrD3DGpu* gpu, unsigned int size) {
+ std::unique_ptr<GrD3DDescriptorTable> table = fSamplerDescriptorPool.allocateTable(gpu, size);
+ this->setHeaps(gpu);
+ return table;
+}
+
+void GrD3DDescriptorTableManager::setHeaps(GrD3DGpu* gpu) {
+ sk_sp<Heap>& currentCBVSRVHeap = fCBVSRVDescriptorPool.currentDescriptorHeap();
+ sk_sp<Heap>& currentSamplerHeap = fSamplerDescriptorPool.currentDescriptorHeap();
+ GrD3DDirectCommandList* commandList = gpu->currentCommandList();
+ commandList->setDescriptorHeaps(currentCBVSRVHeap,
+ currentCBVSRVHeap->d3dDescriptorHeap(),
+ currentSamplerHeap,
+ currentSamplerHeap->d3dDescriptorHeap());
+}
+
+void GrD3DDescriptorTableManager::prepForSubmit(GrD3DGpu* gpu) {
+ fCBVSRVDescriptorPool.prepForSubmit(gpu);
+ fSamplerDescriptorPool.prepForSubmit(gpu);
+}
+
+void GrD3DDescriptorTableManager::recycle(Heap* heap) {
+ // wrap the heap in an sk_sp and take ownership of it
+ sk_sp<Heap> wrappedHeap(heap);
+
+ SkASSERT(heap);
+ switch (heap->type()) {
+ case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV:
+ fCBVSRVDescriptorPool.recycle(std::move(wrappedHeap));
+ break;
+ case D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER:
+ fSamplerDescriptorPool.recycle(std::move(wrappedHeap));
+ break;
+ default:
+ SkUNREACHABLE;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+sk_sp<GrD3DDescriptorTableManager::Heap> GrD3DDescriptorTableManager::Heap::Make(
+ GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type, unsigned int descriptorCount) {
+ std::unique_ptr<GrD3DDescriptorHeap> heap =
+ GrD3DDescriptorHeap::Make(gpu, type, descriptorCount,
+ D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE);
+ if (!heap) {
+ return nullptr;
+ }
+
+ return sk_sp< GrD3DDescriptorTableManager::Heap>(new Heap(gpu, heap, type, descriptorCount));
+}
+
+std::unique_ptr<GrD3DDescriptorTable> GrD3DDescriptorTableManager::Heap::allocateTable(
+ unsigned int count) {
+ SkASSERT(fDescriptorCount - fNextAvailable >= count);
+ unsigned int startIndex = fNextAvailable;
+ fNextAvailable += count;
+ return std::unique_ptr<GrD3DDescriptorTable>(
+ new GrD3DDescriptorTable(fHeap->getCPUHandle(startIndex).fHandle,
+ fHeap->getGPUHandle(startIndex).fHandle, fType));
+}
+
+void GrD3DDescriptorTableManager::Heap::onRecycle() const {
+ fGpu->resourceProvider().descriptorTableMgr()->recycle(const_cast<Heap*>(this));
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+GrD3DDescriptorTableManager::HeapPool::HeapPool(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE heapType)
+ : fHeapType(heapType)
+ , fCurrentHeapDescriptorCount(kInitialHeapDescriptorCount) {
+ sk_sp<Heap> heap = Heap::Make(gpu, fHeapType, fCurrentHeapDescriptorCount);
+ fDescriptorHeaps.push_back(heap);
+}
+
+std::unique_ptr<GrD3DDescriptorTable> GrD3DDescriptorTableManager::HeapPool::allocateTable(
+ GrD3DGpu* gpu, unsigned int count) {
+ // In back-to-front order, iterate through heaps until we find one we can allocate from.
+ // Any heap we can't allocate from gets removed from the list.
+ // If it was already used, it will have been added to the commandlist,
+ // and then later recycled back to us.
+ while (fDescriptorHeaps.size() > 0) {
+ if (fDescriptorHeaps[fDescriptorHeaps.size() - 1]->canAllocate(count)) {
+ return fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateTable(count);
+ }
+ // No space in current heap, pop off list
+ fDescriptorHeaps.pop_back();
+ }
+
+ // Out of available heaps, need to allocate a new one
+ fCurrentHeapDescriptorCount = std::min(2*fCurrentHeapDescriptorCount, 2048u);
+ sk_sp<GrD3DDescriptorTableManager::Heap> heap =
+ GrD3DDescriptorTableManager::Heap::Make(gpu, fHeapType, fCurrentHeapDescriptorCount);
+ fDescriptorHeaps.push_back(heap);
+ return fDescriptorHeaps[fDescriptorHeaps.size() - 1]->allocateTable(count);
+}
+
+sk_sp<GrD3DDescriptorTableManager::Heap>&
+ GrD3DDescriptorTableManager::HeapPool::currentDescriptorHeap() {
+ SkASSERT(fDescriptorHeaps.size() > 0);
+ return fDescriptorHeaps[fDescriptorHeaps.size() - 1];
+}
+
+void GrD3DDescriptorTableManager::HeapPool::prepForSubmit(GrD3DGpu* gpu) {
+ // Pop off the current descriptor heap
+ if (fDescriptorHeaps[fDescriptorHeaps.size() - 1]->used()) {
+ fDescriptorHeaps.pop_back();
+ }
+
+ if (fDescriptorHeaps.size() == 0) {
+ fCurrentHeapDescriptorCount = std::min(fCurrentHeapDescriptorCount, 2048u);
+ sk_sp<GrD3DDescriptorTableManager::Heap> heap =
+ GrD3DDescriptorTableManager::Heap::Make(gpu, fHeapType, fCurrentHeapDescriptorCount);
+ fDescriptorHeaps.push_back(heap);
+ }
+}
+
+void GrD3DDescriptorTableManager::HeapPool::recycle(sk_sp<Heap> heap) {
+ SkASSERT(heap);
+ // only add heaps back if they match our current size
+ // this purges any smaller heaps we no longer need
+ if (heap->descriptorCount() == fCurrentHeapDescriptorCount) {
+ heap->reset();
+ fDescriptorHeaps.push_back(heap);
+ }
+}
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorTableManager.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorTableManager.h
new file mode 100644
index 00000000000..295b8680afc
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DDescriptorTableManager.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrD3DGpuDescriptorTableManager_DEFINED
+#define GrD3DGpuDescriptorTableManager_DEFINED
+
+#include "src/gpu/d3d/GrD3DDescriptorHeap.h"
+
+class GrD3DCommandList;
+class GrD3DDirectCommandList;
+class GrD3DGpu;
+
+class GrD3DDescriptorTable {
+public:
+ GrD3DDescriptorTable(D3D12_CPU_DESCRIPTOR_HANDLE baseCPU, D3D12_GPU_DESCRIPTOR_HANDLE baseGPU,
+ D3D12_DESCRIPTOR_HEAP_TYPE type)
+ : fDescriptorTableCpuStart(baseCPU)
+ , fDescriptorTableGpuStart(baseGPU)
+ , fType(type) {}
+
+ const D3D12_CPU_DESCRIPTOR_HANDLE* baseCpuDescriptorPtr() {
+ return &fDescriptorTableCpuStart;
+ }
+
+ const D3D12_GPU_DESCRIPTOR_HANDLE baseGpuDescriptor() {
+ return fDescriptorTableGpuStart;
+ }
+
+ D3D12_DESCRIPTOR_HEAP_TYPE type() const { return fType; }
+
+private:
+ D3D12_CPU_DESCRIPTOR_HANDLE fDescriptorTableCpuStart;
+ D3D12_GPU_DESCRIPTOR_HANDLE fDescriptorTableGpuStart;
+ D3D12_DESCRIPTOR_HEAP_TYPE fType;
+};
+
+class GrD3DDescriptorTableManager {
+public:
+ GrD3DDescriptorTableManager(GrD3DGpu*);
+
+ std::unique_ptr<GrD3DDescriptorTable> createShaderOrConstantResourceTable(GrD3DGpu*,
+ unsigned int count);
+ std::unique_ptr<GrD3DDescriptorTable> createSamplerTable(GrD3DGpu*, unsigned int count);
+
+ void prepForSubmit(GrD3DGpu* gpu);
+
+private:
+ class Heap : public GrRecycledResource {
+ public:
+ static sk_sp<Heap> Make(GrD3DGpu* gpu, D3D12_DESCRIPTOR_HEAP_TYPE type,
+ unsigned int numDescriptors);
+
+ std::unique_ptr<GrD3DDescriptorTable> allocateTable(unsigned int count);
+ bool canAllocate(unsigned int count) const {
+ return (fDescriptorCount - fNextAvailable) >= count;
+ }
+ ID3D12DescriptorHeap* d3dDescriptorHeap() const { return fHeap->descriptorHeap(); }
+ D3D12_DESCRIPTOR_HEAP_TYPE type() const { return fType; }
+ unsigned int descriptorCount() { return fDescriptorCount; }
+ bool used() { return fNextAvailable > 0; }
+
+ void reset() {
+ fNextAvailable = 0;
+ }
+
+ private:
+ Heap(GrD3DGpu* gpu, std::unique_ptr<GrD3DDescriptorHeap>& heap,
+ D3D12_DESCRIPTOR_HEAP_TYPE type, unsigned int descriptorCount)
+ : INHERITED()
+ , fGpu(gpu)
+ , fHeap(std::move(heap))
+ , fType(type)
+ , fDescriptorCount(descriptorCount)
+ , fNextAvailable(0) {
+ }
+
+ void freeGPUData() const override {}
+ void onRecycle() const override;
+
+#ifdef SK_TRACE_MANAGED_RESOURCES
+ void dumpInfo() const override {
+ SkDebugf("GrD3DDescriptorTable::Heap: %d (%d refs)\n", fHeap.get(), this->getRefCnt());
+ }
+#endif
+
+ GrD3DGpu* fGpu;
+ std::unique_ptr<GrD3DDescriptorHeap> fHeap;
+ D3D12_DESCRIPTOR_HEAP_TYPE fType;
+ unsigned int fDescriptorCount;
+ unsigned int fNextAvailable;
+
+ typedef GrRecycledResource INHERITED;
+ };
+
+ class HeapPool {
+ public:
+ HeapPool(GrD3DGpu*, D3D12_DESCRIPTOR_HEAP_TYPE);
+
+ std::unique_ptr<GrD3DDescriptorTable> allocateTable(GrD3DGpu*, unsigned int count);
+ void recycle(sk_sp<Heap>);
+ sk_sp<Heap>& currentDescriptorHeap();
+ void prepForSubmit(GrD3DGpu* gpu);
+
+ private:
+ static constexpr int kInitialHeapDescriptorCount = 256;
+
+ std::vector<sk_sp<Heap>> fDescriptorHeaps;
+ D3D12_DESCRIPTOR_HEAP_TYPE fHeapType;
+ unsigned int fCurrentHeapDescriptorCount;
+ };
+
+ void setHeaps(GrD3DGpu*);
+ void recycle(Heap*);
+
+ HeapPool fCBVSRVDescriptorPool;
+ HeapPool fSamplerDescriptorPool;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.cpp
index fb79434c9e1..fbfc3c741bf 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.cpp
@@ -11,6 +11,7 @@
#include "include/gpu/d3d/GrD3DBackendContext.h"
#include "src/core/SkConvertPixels.h"
#include "src/core/SkMipMap.h"
+#include "src/gpu/GrBackendUtils.h"
#include "src/gpu/GrDataUtils.h"
#include "src/gpu/GrTexturePriv.h"
#include "src/gpu/d3d/GrD3DBuffer.h"
@@ -84,16 +85,19 @@ void GrD3DGpu::destroyResources() {
// We used a placement new for each object in fOutstandingCommandLists, so we're responsible
// for calling the destructor on each of them as well.
while (!fOutstandingCommandLists.empty()) {
- OutstandingCommandList* list = (OutstandingCommandList*)fOutstandingCommandLists.back();
+ OutstandingCommandList* list = (OutstandingCommandList*)fOutstandingCommandLists.front();
SkASSERT(list->fFenceValue <= fenceValue);
// No reason to recycle the command lists since we are destroying all resources anyways.
list->~OutstandingCommandList();
- fOutstandingCommandLists.pop_back();
+ fOutstandingCommandLists.pop_front();
}
+
+ fResourceProvider.destroyResources();
}
GrOpsRenderPass* GrD3DGpu::getOpsRenderPass(
- GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
+ GrRenderTarget* rt, GrStencilAttachment*,
+ GrSurfaceOrigin origin, const SkIRect& bounds,
const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
@@ -110,16 +114,23 @@ GrOpsRenderPass* GrD3DGpu::getOpsRenderPass(
bool GrD3DGpu::submitDirectCommandList(SyncQueue sync) {
SkASSERT(fCurrentDirectCommandList);
+ fResourceProvider.prepForSubmit();
+
GrD3DDirectCommandList::SubmitResult result = fCurrentDirectCommandList->submit(fQueue.get());
if (result == GrD3DDirectCommandList::SubmitResult::kFailure) {
return false;
} else if (result == GrD3DDirectCommandList::SubmitResult::kNoWork) {
if (sync == SyncQueue::kForce) {
this->waitForQueueCompletion();
+ this->checkForFinishedCommandLists();
}
return true;
}
+ // We just submitted the command list so make sure all GrD3DPipelineState's mark their cached
+ // uniform data as dirty.
+ fResourceProvider.markPipelineStateUniformsDirty();
+
new (fOutstandingCommandLists.push_back()) OutstandingCommandList(
std::move(fCurrentDirectCommandList), ++fCurrentFenceValue);
@@ -180,6 +191,29 @@ void GrD3DGpu::submit(GrOpsRenderPass* renderPass) {
fCachedOpsRenderPass.reset();
}
+void GrD3DGpu::addFinishedProc(GrGpuFinishedProc finishedProc,
+ GrGpuFinishedContext finishedContext) {
+ SkASSERT(finishedProc);
+ sk_sp<GrRefCntedCallback> finishedCallback(
+ new GrRefCntedCallback(finishedProc, finishedContext));
+ this->addFinishedCallback(std::move(finishedCallback));
+}
+
+void GrD3DGpu::addFinishedCallback(sk_sp<GrRefCntedCallback> finishedCallback) {
+ SkASSERT(finishedCallback);
+ // Besides the current command list, we also add the finishedCallback to the newest outstanding
+ // command list. Our contract for calling the proc is that all previous submitted command lists
+ // have finished when we call it. However, if our current command list has no work when it is
+ // flushed it will drop its ref to the callback immediately. But the previous work may not have
+ // finished. It is safe to only add the proc to the newest outstanding commandlist cause that
+ // must finish after all previously submitted command lists.
+ OutstandingCommandList* back = (OutstandingCommandList*)fOutstandingCommandLists.back();
+ if (back) {
+ back->fCommandList->addFinishedCallback(finishedCallback);
+ }
+ fCurrentDirectCommandList->addFinishedCallback(std::move(finishedCallback));
+}
+
void GrD3DGpu::querySampleLocations(GrRenderTarget* rt, SkTArray<SkPoint>* sampleLocations) {
// TODO
}
@@ -561,14 +595,6 @@ bool GrD3DGpu::uploadToTexture(GrD3DTexture* tex, int left, int top, int width,
return true;
}
-void GrD3DGpu::clear(const GrFixedClip& clip, const SkPMColor4f& color, GrRenderTarget* rt) {
- GrD3DRenderTarget* d3dRT = static_cast<GrD3DRenderTarget*>(rt);
-
- d3dRT->setResourceState(this, D3D12_RESOURCE_STATE_RENDER_TARGET);
-
- fCurrentDirectCommandList->clearRenderTargetView(d3dRT, color, clip);
-}
-
static bool check_resource_info(const GrD3DTextureResourceInfo& info) {
if (!info.fResource.get()) {
return false;
@@ -884,10 +910,157 @@ GrBackendTexture GrD3DGpu::onCreateBackendTexture(SkISize dimensions,
return GrBackendTexture(dimensions.width(), dimensions.height(), info);
}
+bool copy_src_data(GrD3DGpu* gpu, char* mapPtr, DXGI_FORMAT dxgiFormat,
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT* placedFootprints,
+ const SkPixmap srcData[], int numMipLevels) {
+ SkASSERT(srcData && numMipLevels);
+ SkASSERT(!GrDxgiFormatIsCompressed(dxgiFormat));
+ SkASSERT(mapPtr);
+
+ size_t bytesPerPixel = gpu->d3dCaps().bytesPerPixel(dxgiFormat);
+
+ for (int currentMipLevel = 0; currentMipLevel < numMipLevels; currentMipLevel++) {
+ const size_t trimRowBytes = srcData[currentMipLevel].width() * bytesPerPixel;
+
+ // copy data into the buffer, skipping any trailing bytes
+ char* dst = mapPtr + placedFootprints[currentMipLevel].Offset;
+ SkRectMemcpy(dst, placedFootprints[currentMipLevel].Footprint.RowPitch,
+ srcData[currentMipLevel].addr(), srcData[currentMipLevel].rowBytes(),
+ trimRowBytes, srcData[currentMipLevel].height());
+ }
+
+ return true;
+}
+
+// Used to "clear" a backend texture to a constant color by transferring.
+static GrColorType dxgi_format_to_backend_tex_clear_colortype(DXGI_FORMAT format) {
+ switch (format) {
+ case DXGI_FORMAT_A8_UNORM: return GrColorType::kAlpha_8;
+ case DXGI_FORMAT_R8_UNORM: return GrColorType::kR_8;
+
+ case DXGI_FORMAT_B5G6R5_UNORM: return GrColorType::kBGR_565;
+ case DXGI_FORMAT_B4G4R4A4_UNORM: return GrColorType::kABGR_4444;
+ case DXGI_FORMAT_R8G8B8A8_UNORM: return GrColorType::kRGBA_8888;
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return GrColorType::kRGBA_8888_SRGB;
+
+ case DXGI_FORMAT_R8G8_UNORM: return GrColorType::kRG_88;
+ case DXGI_FORMAT_B8G8R8A8_UNORM: return GrColorType::kBGRA_8888;
+ case DXGI_FORMAT_R10G10B10A2_UNORM: return GrColorType::kRGBA_1010102;
+ case DXGI_FORMAT_R16_FLOAT: return GrColorType::kR_F16;
+ case DXGI_FORMAT_R16G16B16A16_FLOAT: return GrColorType::kRGBA_F16;
+ case DXGI_FORMAT_R16_UNORM: return GrColorType::kR_16;
+ case DXGI_FORMAT_R16G16_UNORM: return GrColorType::kRG_1616;
+ case DXGI_FORMAT_R16G16B16A16_UNORM: return GrColorType::kRGBA_16161616;
+ case DXGI_FORMAT_R16G16_FLOAT: return GrColorType::kRG_F16;
+ default: return GrColorType::kUnknown;
+ }
+
+ SkUNREACHABLE;
+}
+
+
+bool copy_color_data(char* mapPtr, DXGI_FORMAT dxgiFormat, SkISize dimensions,
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT* placedFootprints, SkColor4f color) {
+ auto colorType = dxgi_format_to_backend_tex_clear_colortype(dxgiFormat);
+ if (colorType == GrColorType::kUnknown) {
+ return false;
+ }
+ GrImageInfo ii(colorType, kUnpremul_SkAlphaType, nullptr, dimensions);
+ if (!GrClearImage(ii, mapPtr, placedFootprints[0].Footprint.RowPitch, color)) {
+ return false;
+ }
+
+ return true;
+}
+
bool GrD3DGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
sk_sp<GrRefCntedCallback> finishedCallback,
const BackendTextureData* data) {
- // TODO: handle finishedCallback and data upload
+ GrD3DTextureResourceInfo info;
+ SkAssertResult(backendTexture.getD3DTextureResourceInfo(&info));
+
+ sk_sp<GrD3DResourceState> state = backendTexture.getGrD3DResourceState();
+ SkASSERT(state);
+ sk_sp<GrD3DTexture> texture =
+ GrD3DTexture::MakeWrappedTexture(this, backendTexture.dimensions(),
+ GrWrapCacheable::kNo,
+ kRW_GrIOType, info, std::move(state));
+ if (!texture) {
+ return false;
+ }
+
+ GrD3DDirectCommandList* cmdList = this->currentCommandList();
+ if (!cmdList) {
+ return false;
+ }
+
+ texture->setResourceState(this, D3D12_RESOURCE_STATE_COPY_DEST);
+
+ ID3D12Resource* d3dResource = texture->d3dResource();
+ SkASSERT(d3dResource);
+ D3D12_RESOURCE_DESC desc = d3dResource->GetDesc();
+ unsigned int mipLevelCount = 1;
+ if (backendTexture.fMipMapped == GrMipMapped::kYes) {
+ mipLevelCount = SkMipMap::ComputeLevelCount(backendTexture.dimensions().width(),
+ backendTexture.dimensions().height()) + 1;
+ }
+ SkASSERT(mipLevelCount == info.fLevelCount);
+ SkAutoTMalloc<D3D12_PLACED_SUBRESOURCE_FOOTPRINT> placedFootprints(mipLevelCount);
+ UINT64 combinedBufferSize;
+ fDevice->GetCopyableFootprints(&desc, 0, mipLevelCount, 0, placedFootprints.get(),
+ nullptr, nullptr, &combinedBufferSize);
+ SkASSERT(combinedBufferSize);
+ if (data->type() == BackendTextureData::Type::kColor &&
+ !GrDxgiFormatIsCompressed(info.fFormat) && mipLevelCount > 1) {
+ // For a single uncompressed color, we reuse the same top-level buffer area for all levels.
+ combinedBufferSize =
+ placedFootprints[0].Footprint.RowPitch * placedFootprints[0].Footprint.Height;
+ for (unsigned int i = 1; i < mipLevelCount; ++i) {
+ placedFootprints[i].Offset = 0;
+ placedFootprints[i].Footprint.RowPitch = placedFootprints[0].Footprint.RowPitch;
+ }
+ }
+
+ // TODO: do this until we have slices of buttery buffers
+ sk_sp<GrGpuBuffer> transferBuffer = this->createBuffer(combinedBufferSize,
+ GrGpuBufferType::kXferCpuToGpu,
+ kDynamic_GrAccessPattern);
+ if (!transferBuffer) {
+ return false;
+ }
+ char* bufferData = (char*)transferBuffer->map();
+ SkASSERT(bufferData);
+
+ bool result;
+ if (data->type() == BackendTextureData::Type::kPixmaps) {
+ result = copy_src_data(this, bufferData, info.fFormat, placedFootprints.get(),
+ data->pixmaps(), info.fLevelCount);
+ } else if (data->type() == BackendTextureData::Type::kCompressed) {
+ memcpy(bufferData, data->compressedData(), data->compressedSize());
+ result = true;
+ } else {
+ SkASSERT(data->type() == BackendTextureData::Type::kColor);
+ SkImage::CompressionType compression =
+ GrBackendFormatToCompressionType(backendTexture.getBackendFormat());
+ if (SkImage::CompressionType::kNone == compression) {
+ result = copy_color_data(bufferData, info.fFormat, backendTexture.dimensions(),
+ placedFootprints, data->color());
+ } else {
+ GrFillInCompressedData(compression, backendTexture.dimensions(),
+ backendTexture.fMipMapped, bufferData, data->color());
+ result = true;
+ }
+ }
+ transferBuffer->unmap();
+
+ GrD3DBuffer* d3dBuffer = static_cast<GrD3DBuffer*>(transferBuffer.get());
+ cmdList->copyBufferToTexture(d3dBuffer, texture.get(), mipLevelCount, placedFootprints.get(),
+ 0, 0);
+
+ if (finishedCallback) {
+ this->addFinishedCallback(std::move(finishedCallback));
+ }
+
return true;
}
@@ -1006,6 +1179,31 @@ void GrD3DGpu::addResourceBarriers(sk_sp<GrManagedResource> resource,
fCurrentDirectCommandList->resourceBarrier(std::move(resource), numBarriers, barriers);
}
+void GrD3DGpu::prepareSurfacesForBackendAccessAndStateUpdates(
+ GrSurfaceProxy* proxies[],
+ int numProxies,
+ SkSurface::BackendSurfaceAccess access,
+ const GrBackendSurfaceMutableState* newState) {
+ SkASSERT(numProxies >= 0);
+ SkASSERT(!numProxies || proxies);
+
+ // prepare proxies by transitioning to PRESENT renderState
+ if (numProxies && access == SkSurface::BackendSurfaceAccess::kPresent) {
+ GrD3DTextureResource* resource;
+ for (int i = 0; i < numProxies; ++i) {
+ SkASSERT(proxies[i]->isInstantiated());
+ if (GrTexture* tex = proxies[i]->peekTexture()) {
+ resource = static_cast<GrD3DTexture*>(tex);
+ } else {
+ GrRenderTarget* rt = proxies[i]->peekRenderTarget();
+ SkASSERT(rt);
+ resource = static_cast<GrD3DRenderTarget*>(rt);
+ }
+ resource->prepareForPresent(this);
+ }
+ }
+}
+
bool GrD3DGpu::onSubmitToGpu(bool syncCpu) {
if (syncCpu) {
return this->submitDirectCommandList(SyncQueue::kForce);
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.h
index 3c1c9738a10..ce2488134c4 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DGpu.h
@@ -64,13 +64,18 @@ public:
void testingOnly_startCapture() override;
void testingOnly_endCapture() override;
+
+ void resetShaderCacheForTesting() const override {
+ fResourceProvider.resetShaderCacheForTesting();
+ }
#endif
GrStencilAttachment* createStencilAttachmentForRenderTarget(
const GrRenderTarget*, int width, int height, int numStencilSamples) override;
GrOpsRenderPass* getOpsRenderPass(
- GrRenderTarget*, GrSurfaceOrigin, const SkIRect&,
+ GrRenderTarget*, GrStencilAttachment*,
+ GrSurfaceOrigin, const SkIRect&,
const GrOpsRenderPass::LoadAndStoreInfo&,
const GrOpsRenderPass::StencilLoadAndStoreInfo&,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override;
@@ -98,11 +103,9 @@ public:
return nullptr;
}
- void clear(const GrFixedClip& clip, const SkPMColor4f& color, GrRenderTarget*);
-
void submit(GrOpsRenderPass* renderPass) override;
- void checkFinishProcs() override {}
+ void checkFinishProcs() override { this->checkForFinishedCommandLists(); }
SkSL::Compiler* shaderCompiler() const {
return fCompiler.get();
@@ -184,11 +187,14 @@ private:
void onResolveRenderTarget(GrRenderTarget* target, const SkIRect&, ForExternalIO) override {}
void addFinishedProc(GrGpuFinishedProc finishedProc,
- GrGpuFinishedContext finishedContext) override {
- // TODO: have this actually wait before calling the proc
- SkASSERT(finishedProc);
- finishedProc(finishedContext);
- }
+ GrGpuFinishedContext finishedContext) override;
+ void addFinishedCallback(sk_sp<GrRefCntedCallback> finishedCallback);
+
+ void prepareSurfacesForBackendAccessAndStateUpdates(
+ GrSurfaceProxy* proxies[],
+ int numProxies,
+ SkSurface::BackendSurfaceAccess access,
+ const GrBackendSurfaceMutableState* newState) override;
bool onSubmitToGpu(bool syncCpu) override;
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.cpp
index bd681f9058f..baac3d222f2 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.cpp
@@ -8,13 +8,16 @@
#include "src/gpu/d3d/GrD3DOpsRenderPass.h"
#include "src/gpu/GrContextPriv.h"
-#include "src/gpu/GrFixedClip.h"
+#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrProgramDesc.h"
#include "src/gpu/GrRenderTargetPriv.h"
#include "src/gpu/GrStencilSettings.h"
+#include "src/gpu/d3d/GrD3DBuffer.h"
#include "src/gpu/d3d/GrD3DGpu.h"
#include "src/gpu/d3d/GrD3DPipelineState.h"
#include "src/gpu/d3d/GrD3DPipelineStateBuilder.h"
+#include "src/gpu/d3d/GrD3DRenderTarget.h"
+#include "src/gpu/d3d/GrD3DTexture.h"
GrD3DOpsRenderPass::GrD3DOpsRenderPass(GrD3DGpu* gpu) : fGpu(gpu) {}
@@ -41,11 +44,33 @@ GrD3DOpsRenderPass::~GrD3DOpsRenderPass() {}
GrGpu* GrD3DOpsRenderPass::gpu() { return fGpu; }
+void GrD3DOpsRenderPass::onBegin() {
+ GrD3DRenderTarget* d3dRT = static_cast<GrD3DRenderTarget*>(fRenderTarget);
+ d3dRT->setResourceState(fGpu, D3D12_RESOURCE_STATE_RENDER_TARGET);
+ fGpu->currentCommandList()->setRenderTarget(d3dRT);
+
+ if (GrLoadOp::kClear == fColorLoadOp) {
+ // Passing in nullptr for the rect clears the entire d3d RT. Is this correct? Does the load
+ // op respect the logical bounds of a RT?
+ fGpu->currentCommandList()->clearRenderTargetView(d3dRT, fClearColor, nullptr);
+ }
+
+ if (auto stencil = d3dRT->renderTargetPriv().getStencilAttachment()) {
+ GrD3DStencilAttachment* d3dStencil = static_cast<GrD3DStencilAttachment*>(stencil);
+ d3dStencil->setResourceState(fGpu, D3D12_RESOURCE_STATE_DEPTH_WRITE);
+ if (fStencilLoadOp == GrLoadOp::kClear) {
+ fGpu->currentCommandList()->clearDepthStencilView(d3dStencil, 0, nullptr);
+ }
+ }
+}
+
void set_stencil_ref(GrD3DGpu* gpu, const GrProgramInfo& info) {
GrStencilSettings stencilSettings = info.nonGLStencilSettings();
if (!stencilSettings.isDisabled()) {
unsigned int stencilRef = 0;
if (stencilSettings.isTwoSided()) {
+ SkASSERT(stencilSettings.postOriginCCWFace(info.origin()).fRef ==
+ stencilSettings.postOriginCWFace(info.origin()).fRef);
stencilRef = stencilSettings.postOriginCCWFace(info.origin()).fRef;
} else {
stencilRef = stencilSettings.singleSidedFace().fRef;
@@ -97,6 +122,7 @@ void set_primitive_topology(GrD3DGpu* gpu, const GrProgramInfo& info) {
default:
SkUNREACHABLE;
}
+ gpu->currentCommandList()->setPrimitiveTopology(topology);
}
void set_scissor_rects(GrD3DGpu* gpu, const GrRenderTarget* renderTarget, GrSurfaceOrigin rtOrigin,
@@ -139,13 +165,16 @@ bool GrD3DOpsRenderPass::onBindPipeline(const GrProgramInfo& info, const SkRect&
fCurrentPipelineBounds.setEmpty();
}
- sk_sp<GrD3DPipelineState> pipelineState =
+ fCurrentPipelineState =
fGpu->resourceProvider().findOrCreateCompatiblePipelineState(fRenderTarget, info);
- if (!pipelineState) {
+ if (!fCurrentPipelineState) {
return false;
}
- fGpu->currentCommandList()->setPipelineState(std::move(pipelineState));
+ fGpu->currentCommandList()->setGraphicsRootSignature(fCurrentPipelineState->rootSignature());
+ fGpu->currentCommandList()->setPipelineState(fCurrentPipelineState);
+
+ fCurrentPipelineState->setAndBindConstants(fGpu, fRenderTarget, info);
set_stencil_ref(fGpu, info);
set_blend_factor(fGpu, info);
@@ -159,13 +188,128 @@ bool GrD3DOpsRenderPass::onBindPipeline(const GrProgramInfo& info, const SkRect&
return true;
}
-void GrD3DOpsRenderPass::onBegin() {
- if (GrLoadOp::kClear == fColorLoadOp) {
- GrFixedClip clip;
- fGpu->clear(clip, fClearColor, fRenderTarget);
+void GrD3DOpsRenderPass::onSetScissorRect(const SkIRect& scissor) {
+ SkIRect combinedScissorRect;
+ if (!combinedScissorRect.intersect(fCurrentPipelineBounds, scissor)) {
+ combinedScissorRect = SkIRect::MakeEmpty();
+ }
+
+ set_scissor_rects(fGpu, fRenderTarget, fOrigin, combinedScissorRect);
+}
+
+void update_resource_state(GrTexture* tex, GrRenderTarget* rt, GrD3DGpu* gpu) {
+ SkASSERT(!tex->isProtected() || (rt->isProtected() && gpu->protectedContext()));
+ GrD3DTexture* d3dTex = static_cast<GrD3DTexture*>(tex);
+ SkASSERT(d3dTex);
+ d3dTex->setResourceState(gpu, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
+}
+
+bool GrD3DOpsRenderPass::onBindTextures(const GrPrimitiveProcessor& primProc,
+ const GrSurfaceProxy* const primProcTextures[],
+ const GrPipeline& pipeline) {
+ SkASSERT(fCurrentPipelineState);
+
+ // update textures to sampled resource state
+ for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
+ update_resource_state(primProcTextures[i]->peekTexture(), fRenderTarget, fGpu);
+ }
+ GrFragmentProcessor::PipelineTextureSamplerRange textureSamplerRange(pipeline);
+ for (auto [sampler, fp] : textureSamplerRange) {
+ update_resource_state(sampler.peekTexture(), fRenderTarget, fGpu);
+ }
+ if (GrTexture* dstTexture = pipeline.peekDstTexture()) {
+ update_resource_state(dstTexture, fRenderTarget, fGpu);
+ }
+
+ // TODO: possibly check for success once we start binding properly
+ fCurrentPipelineState->setAndBindTextures(fGpu, primProc, primProcTextures, pipeline);
+
+ return true;
+}
+
+void GrD3DOpsRenderPass::onBindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
+ const GrBuffer* vertexBuffer,
+ GrPrimitiveRestart primRestart) {
+ SkASSERT(GrPrimitiveRestart::kNo == primRestart);
+ SkASSERT(fCurrentPipelineState);
+ SkASSERT(!fGpu->caps()->usePrimitiveRestart()); // Ignore primitiveRestart parameter.
+
+ GrD3DDirectCommandList* currCmdList = fGpu->currentCommandList();
+ SkASSERT(currCmdList);
+
+ // TODO: do we need a memory barrier here?
+
+ fCurrentPipelineState->bindBuffers(fGpu, indexBuffer, instanceBuffer, vertexBuffer,
+ currCmdList);
+}
+
+void GrD3DOpsRenderPass::onDrawInstanced(int instanceCount, int baseInstance, int vertexCount,
+ int baseVertex) {
+ SkASSERT(fCurrentPipelineState);
+ fGpu->currentCommandList()->drawInstanced(vertexCount, instanceCount, baseVertex, baseInstance);
+ fGpu->stats()->incNumDraws();
+}
+
+void GrD3DOpsRenderPass::onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount,
+ int baseInstance, int baseVertex) {
+ SkASSERT(fCurrentPipelineState);
+ fGpu->currentCommandList()->drawIndexedInstanced(indexCount, instanceCount, baseIndex,
+ baseVertex, baseInstance);
+ fGpu->stats()->incNumDraws();
+}
+
+static D3D12_RECT scissor_to_d3d_clear_rect(const GrScissorState& scissor,
+ const GrSurface* surface,
+ GrSurfaceOrigin origin) {
+ D3D12_RECT clearRect;
+ // Flip rect if necessary
+ SkIRect d3dRect;
+ if (!scissor.enabled()) {
+ d3dRect.setXYWH(0, 0, surface->width(), surface->height());
+ } else if (kBottomLeft_GrSurfaceOrigin != origin) {
+ d3dRect = scissor.rect();
+ } else {
+ d3dRect.setLTRB(scissor.rect().fLeft, surface->height() - scissor.rect().fBottom,
+ scissor.rect().fRight, surface->height() - scissor.rect().fTop);
}
+ clearRect.left = d3dRect.fLeft;
+ clearRect.right = d3dRect.fRight;
+ clearRect.top = d3dRect.fTop;
+ clearRect.bottom = d3dRect.fBottom;
+ return clearRect;
+}
+
+void GrD3DOpsRenderPass::onClear(const GrScissorState& scissor, const SkPMColor4f& color) {
+ D3D12_RECT clearRect = scissor_to_d3d_clear_rect(scissor, fRenderTarget, fOrigin);
+ auto d3dRT = static_cast<GrD3DRenderTarget*>(fRenderTarget);
+ SkASSERT(d3dRT->grD3DResourceState()->getResourceState() == D3D12_RESOURCE_STATE_RENDER_TARGET);
+ fGpu->currentCommandList()->clearRenderTargetView(d3dRT, color, &clearRect);
+}
+
+void GrD3DOpsRenderPass::onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) {
+ GrStencilAttachment* sb = fRenderTarget->renderTargetPriv().getStencilAttachment();
+ // this should only be called internally when we know we have a
+ // stencil buffer.
+ SkASSERT(sb);
+ int stencilBitCount = sb->bits();
+
+ // The contract with the callers does not guarantee that we preserve all bits in the stencil
+ // during this clear. Thus we will clear the entire stencil to the desired value.
+
+ uint8_t stencilColor = 0;
+ if (insideStencilMask) {
+ stencilColor = (1 << (stencilBitCount - 1));
+ }
+
+ D3D12_RECT clearRect = scissor_to_d3d_clear_rect(scissor, fRenderTarget, fOrigin);
+
+ auto d3dStencil = static_cast<GrD3DStencilAttachment*>(sb);
+ fGpu->currentCommandList()->clearDepthStencilView(d3dStencil, stencilColor, &clearRect);
}
-void GrD3DOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& color) {
- fGpu->clear(clip, color, fRenderTarget);
+void GrD3DOpsRenderPass::inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) {
+ // If we ever start using copy command lists for doing uploads, then we'll need to make sure
+ // we submit our main command list before doing the copy here and then start a new main command
+ // list.
+ state->doUpload(upload);
}
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.h
index 058d046422d..ed540bd7ed2 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DOpsRenderPass.h
@@ -14,6 +14,7 @@
#include "include/private/GrTypesPriv.h"
class GrD3DGpu;
+class GrD3DPipelineState;
class GrD3DOpsRenderPass : public GrOpsRenderPass {
public:
@@ -21,7 +22,7 @@ public:
~GrD3DOpsRenderPass() override;
- void inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) override {}
+ void inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) override;
void onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) override {}
@@ -36,31 +37,39 @@ private:
void onBegin() override;
bool onBindPipeline(const GrProgramInfo&, const SkRect& drawBounds) override;
- void onSetScissorRect(const SkIRect&) override {}
+ void onSetScissorRect(const SkIRect&) override;
bool onBindTextures(const GrPrimitiveProcessor&, const GrSurfaceProxy* const primProcTextures[],
- const GrPipeline&) override {
- return true;
- }
+ const GrPipeline&) override;
void onBindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
- const GrBuffer* vertexBuffer, GrPrimitiveRestart) override {}
- void onDraw(int vertexCount, int baseVertex) override {}
+ const GrBuffer* vertexBuffer, GrPrimitiveRestart) override;
+ void onDraw(int vertexCount, int baseVertex) override {
+ this->onDrawInstanced(1, 0, vertexCount, baseVertex);
+ }
void onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
- uint16_t maxIndexValue, int baseVertex) override {}
+ uint16_t maxIndexValue, int baseVertex) override {
+ this->onDrawIndexedInstanced(indexCount, baseIndex, 1, 0, baseVertex);
+ }
void onDrawInstanced(int instanceCount, int baseInstance, int vertexCount,
- int baseVertex) override {}
+ int baseVertex) override;
void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance,
- int baseVertex) override {}
+ int baseVertex) override;
+ void onDrawIndirect(const GrBuffer*, size_t offset, int drawCount) override {}
+ void onDrawIndexedIndirect(const GrBuffer*, size_t offset, int drawCount) override {}
- void onClear(const GrFixedClip&, const SkPMColor4f& color) override;
+ void onClear(const GrScissorState& scissor, const SkPMColor4f& color) override;
- void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) override {}
+ void onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) override;
GrD3DGpu* fGpu;
+
+ sk_sp<GrD3DPipelineState> fCurrentPipelineState;
+
SkIRect fBounds;
SkIRect fCurrentPipelineBounds;
GrLoadOp fColorLoadOp;
SkPMColor4f fClearColor;
+ GrLoadOp fStencilLoadOp;
typedef GrOpsRenderPass INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.cpp
index 21351763373..f7e3d6e26a4 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.cpp
@@ -10,393 +10,183 @@
#include "include/private/SkTemplates.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrStencilSettings.h"
+#include "src/gpu/d3d/GrD3DBuffer.h"
#include "src/gpu/d3d/GrD3DGpu.h"
#include "src/gpu/d3d/GrD3DRootSignature.h"
-
-static DXGI_FORMAT attrib_type_to_format(GrVertexAttribType type) {
- switch (type) {
- case kFloat_GrVertexAttribType:
- return DXGI_FORMAT_R32_FLOAT;
- case kFloat2_GrVertexAttribType:
- return DXGI_FORMAT_R32G32_FLOAT;
- case kFloat3_GrVertexAttribType:
- return DXGI_FORMAT_R32G32B32_FLOAT;
- case kFloat4_GrVertexAttribType:
- return DXGI_FORMAT_R32G32B32A32_FLOAT;
- case kHalf_GrVertexAttribType:
- return DXGI_FORMAT_R16_FLOAT;
- case kHalf2_GrVertexAttribType:
- return DXGI_FORMAT_R16G16_FLOAT;
- case kHalf4_GrVertexAttribType:
- return DXGI_FORMAT_R16G16B16A16_FLOAT;
- case kInt2_GrVertexAttribType:
- return DXGI_FORMAT_R32G32_SINT;
- case kInt3_GrVertexAttribType:
- return DXGI_FORMAT_R32G32B32_SINT;
- case kInt4_GrVertexAttribType:
- return DXGI_FORMAT_R32G32B32A32_SINT;
- case kByte_GrVertexAttribType:
- return DXGI_FORMAT_R8_SINT;
- case kByte2_GrVertexAttribType:
- return DXGI_FORMAT_R8G8_SINT;
- case kByte4_GrVertexAttribType:
- return DXGI_FORMAT_R8G8B8A8_SINT;
- case kUByte_GrVertexAttribType:
- return DXGI_FORMAT_R8_UINT;
- case kUByte2_GrVertexAttribType:
- return DXGI_FORMAT_R8G8_UINT;
- case kUByte4_GrVertexAttribType:
- return DXGI_FORMAT_R8G8B8A8_UINT;
- case kUByte_norm_GrVertexAttribType:
- return DXGI_FORMAT_R8_UNORM;
- case kUByte4_norm_GrVertexAttribType:
- return DXGI_FORMAT_R8G8B8A8_UNORM;
- case kShort2_GrVertexAttribType:
- return DXGI_FORMAT_R16G16_SINT;
- case kShort4_GrVertexAttribType:
- return DXGI_FORMAT_R16G16B16A16_SINT;
- case kUShort2_GrVertexAttribType:
- return DXGI_FORMAT_R16G16_UINT;
- case kUShort2_norm_GrVertexAttribType:
- return DXGI_FORMAT_R16G16_UNORM;
- case kInt_GrVertexAttribType:
- return DXGI_FORMAT_R32_SINT;
- case kUint_GrVertexAttribType:
- return DXGI_FORMAT_R32_UINT;
- case kUShort_norm_GrVertexAttribType:
- return DXGI_FORMAT_R16_UNORM;
- case kUShort4_norm_GrVertexAttribType:
- return DXGI_FORMAT_R16G16B16A16_UNORM;
+#include "src/gpu/d3d/GrD3DTexture.h"
+#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
+#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
+#include "src/gpu/glsl/GrGLSLXferProcessor.h"
+
+GrD3DPipelineState::GrD3DPipelineState(
+ gr_cp<ID3D12PipelineState> pipelineState,
+ sk_sp<GrD3DRootSignature> rootSignature,
+ const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
+ const UniformInfoArray& uniforms, uint32_t uniformSize,
+ uint32_t numSamplers,
+ std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
+ std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
+ std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,
+ int fragmentProcessorCnt,
+ size_t vertexStride,
+ size_t instanceStride)
+ : fPipelineState(std::move(pipelineState))
+ , fRootSignature(std::move(rootSignature))
+ , fBuiltinUniformHandles(builtinUniformHandles)
+ , fGeometryProcessor(std::move(geometryProcessor))
+ , fXferProcessor(std::move(xferProcessor))
+ , fFragmentProcessors(std::move(fragmentProcessors))
+ , fFragmentProcessorCnt(fragmentProcessorCnt)
+ , fDataManager(uniforms, uniformSize)
+ , fNumSamplers(numSamplers)
+ , fVertexStride(vertexStride)
+ , fInstanceStride(instanceStride) {}
+
+void GrD3DPipelineState::setAndBindConstants(GrD3DGpu* gpu,
+ const GrRenderTarget* renderTarget,
+ const GrProgramInfo& programInfo) {
+ this->setRenderTargetState(renderTarget, programInfo.origin());
+
+ GrFragmentProcessor::PipelineCoordTransformRange transformRange(programInfo.pipeline());
+ fGeometryProcessor->setData(fDataManager, programInfo.primProc(), transformRange);
+ GrFragmentProcessor::CIter fpIter(programInfo.pipeline());
+ GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
+ for (; fpIter && glslIter; ++fpIter, ++glslIter) {
+ glslIter->setData(fDataManager, *fpIter);
}
- SK_ABORT("Unknown vertex attrib type");
-}
+ SkASSERT(!fpIter && !glslIter);
-static void setup_vertex_input_layout(const GrPrimitiveProcessor& primProc,
- D3D12_INPUT_ELEMENT_DESC* inputElements) {
- unsigned int slotNumber = 0;
- unsigned int vertexSlot = 0;
- unsigned int instanceSlot = 0;
- if (primProc.hasVertexAttributes()) {
- vertexSlot = slotNumber++;
- }
- if (primProc.hasInstanceAttributes()) {
- instanceSlot = slotNumber++;
- }
+ {
+ SkIPoint offset;
+ GrTexture* dstTexture = programInfo.pipeline().peekDstTexture(&offset);
- unsigned int currentAttrib = 0;
- unsigned int vertexAttributeOffset = 0;
-
- for (const auto& attrib : primProc.vertexAttributes()) {
- // When using SPIRV-Cross it converts the location modifier in SPIRV to be
- // TEXCOORD<N> where N is the location value for eveery vertext attribute
- inputElements[currentAttrib] = {"TEXCOORD", currentAttrib,
- attrib_type_to_format(attrib.cpuType()),
- vertexSlot, vertexAttributeOffset,
- D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0};
- vertexAttributeOffset += attrib.sizeAlign4();
- currentAttrib++;
+ fXferProcessor->setData(fDataManager, programInfo.pipeline().getXferProcessor(),
+ dstTexture, offset);
}
- SkASSERT(vertexAttributeOffset == primProc.vertexStride());
- unsigned int instanceAttributeOffset = 0;
- for (const auto& attrib : primProc.instanceAttributes()) {
- // When using SPIRV-Cross it converts the location modifier in SPIRV to be
- // TEXCOORD<N> where N is the location value for eveery vertext attribute
- inputElements[currentAttrib] = {"TEXCOORD", currentAttrib,
- attrib_type_to_format(attrib.cpuType()),
- instanceSlot, instanceAttributeOffset,
- D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0};
- instanceAttributeOffset += attrib.sizeAlign4();
- currentAttrib++;
- }
- SkASSERT(instanceAttributeOffset == primProc.instanceStride());
+ D3D12_GPU_VIRTUAL_ADDRESS constantsAddress = fDataManager.uploadConstants(gpu);
+ gpu->currentCommandList()->setGraphicsRootConstantBufferView(
+ (unsigned int)(GrD3DRootSignature::ParamIndex::kConstantBufferView),
+ constantsAddress);
}
-static D3D12_BLEND blend_coeff_to_d3d_blend(GrBlendCoeff coeff) {
- switch (coeff) {
- case kZero_GrBlendCoeff:
- return D3D12_BLEND_ZERO;
- case kOne_GrBlendCoeff:
- return D3D12_BLEND_ONE;
- case kSC_GrBlendCoeff:
- return D3D12_BLEND_SRC_COLOR;
- case kISC_GrBlendCoeff:
- return D3D12_BLEND_INV_SRC_COLOR;
- case kDC_GrBlendCoeff:
- return D3D12_BLEND_DEST_COLOR;
- case kIDC_GrBlendCoeff:
- return D3D12_BLEND_INV_DEST_COLOR;
- case kSA_GrBlendCoeff:
- return D3D12_BLEND_SRC_ALPHA;
- case kISA_GrBlendCoeff:
- return D3D12_BLEND_INV_SRC_ALPHA;
- case kDA_GrBlendCoeff:
- return D3D12_BLEND_DEST_ALPHA;
- case kIDA_GrBlendCoeff:
- return D3D12_BLEND_INV_DEST_ALPHA;
- case kConstC_GrBlendCoeff:
- return D3D12_BLEND_BLEND_FACTOR;
- case kIConstC_GrBlendCoeff:
- return D3D12_BLEND_INV_BLEND_FACTOR;
- case kS2C_GrBlendCoeff:
- return D3D12_BLEND_SRC1_COLOR;
- case kIS2C_GrBlendCoeff:
- return D3D12_BLEND_INV_SRC1_COLOR;
- case kS2A_GrBlendCoeff:
- return D3D12_BLEND_SRC1_ALPHA;
- case kIS2A_GrBlendCoeff:
- return D3D12_BLEND_INV_SRC1_ALPHA;
- case kIllegal_GrBlendCoeff:
- return D3D12_BLEND_ZERO;
+void GrD3DPipelineState::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin) {
+ // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
+ if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
+ fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
+ fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height()));
}
- SkUNREACHABLE;
-}
-static D3D12_BLEND blend_coeff_to_d3d_blend_for_alpha(GrBlendCoeff coeff) {
- switch (coeff) {
- // Force all srcColor used in alpha slot to alpha version.
- case kSC_GrBlendCoeff:
- return D3D12_BLEND_SRC_ALPHA;
- case kISC_GrBlendCoeff:
- return D3D12_BLEND_INV_SRC_ALPHA;
- case kDC_GrBlendCoeff:
- return D3D12_BLEND_DEST_ALPHA;
- case kIDC_GrBlendCoeff:
- return D3D12_BLEND_INV_DEST_ALPHA;
- case kS2C_GrBlendCoeff:
- return D3D12_BLEND_SRC1_ALPHA;
- case kIS2C_GrBlendCoeff:
- return D3D12_BLEND_INV_SRC1_ALPHA;
-
- default:
- return blend_coeff_to_d3d_blend(coeff);
- }
-}
-
-
-static D3D12_BLEND_OP blend_equation_to_d3d_op(GrBlendEquation equation) {
- switch (equation) {
- case kAdd_GrBlendEquation:
- return D3D12_BLEND_OP_ADD;
- case kSubtract_GrBlendEquation:
- return D3D12_BLEND_OP_SUBTRACT;
- case kReverseSubtract_GrBlendEquation:
- return D3D12_BLEND_OP_REV_SUBTRACT;
- default:
- SkUNREACHABLE;
+ // set RT adjustment
+ SkISize dimensions = rt->dimensions();
+ SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
+ if (fRenderTargetState.fRenderTargetOrigin != origin ||
+ fRenderTargetState.fRenderTargetSize != dimensions) {
+ fRenderTargetState.fRenderTargetSize = dimensions;
+ fRenderTargetState.fRenderTargetOrigin = origin;
+
+ float rtAdjustmentVec[4];
+ fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
+ fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
}
}
-static void fill_in_blend_state(const GrPipeline& pipeline, D3D12_BLEND_DESC* blendDesc) {
- blendDesc->AlphaToCoverageEnable = false;
- blendDesc->IndependentBlendEnable = false;
-
- const GrXferProcessor::BlendInfo& blendInfo = pipeline.getXferProcessor().getBlendInfo();
-
- GrBlendEquation equation = blendInfo.fEquation;
- GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
- GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
- bool blendOff = GrBlendShouldDisable(equation, srcCoeff, dstCoeff);
-
- auto& rtBlend = blendDesc->RenderTarget[0];
- rtBlend.BlendEnable = !blendOff;
- if (!blendOff) {
- rtBlend.SrcBlend = blend_coeff_to_d3d_blend(srcCoeff);
- rtBlend.DestBlend = blend_coeff_to_d3d_blend(dstCoeff);
- rtBlend.BlendOp = blend_equation_to_d3d_op(equation);
- rtBlend.SrcBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(srcCoeff);
- rtBlend.DestBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(dstCoeff);
- rtBlend.BlendOpAlpha = blend_equation_to_d3d_op(equation);
+void GrD3DPipelineState::setAndBindTextures(GrD3DGpu* gpu, const GrPrimitiveProcessor& primProc,
+ const GrSurfaceProxy* const primProcTextures[],
+ const GrPipeline& pipeline) {
+ SkASSERT(primProcTextures || !primProc.numTextureSamplers());
+
+ SkAutoSTMalloc<8, D3D12_CPU_DESCRIPTOR_HANDLE> shaderResourceViews(fNumSamplers);
+ SkAutoSTMalloc<8, D3D12_CPU_DESCRIPTOR_HANDLE> samplers(fNumSamplers);
+ SkAutoSTMalloc<8, unsigned int> rangeSizes(fNumSamplers);
+ unsigned int currTextureBinding = 0;
+
+ for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
+ SkASSERT(primProcTextures[i]->asTextureProxy());
+ const auto& sampler = primProc.textureSampler(i);
+ auto texture = static_cast<GrD3DTexture*>(primProcTextures[i]->peekTexture());
+ shaderResourceViews[currTextureBinding] = texture->shaderResourceView();
+ samplers[currTextureBinding] =
+ gpu->resourceProvider().findOrCreateCompatibleSampler(sampler.samplerState());
+ gpu->currentCommandList()->addSampledTextureRef(texture);
+ rangeSizes[currTextureBinding++] = 1;
}
- if (!blendInfo.fWriteColor) {
- rtBlend.RenderTargetWriteMask = 0;
- } else {
- rtBlend.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
+ GrFragmentProcessor::CIter fpIter(pipeline);
+ GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
+ for (; fpIter && glslIter; ++fpIter, ++glslIter) {
+ for (int i = 0; i < fpIter->numTextureSamplers(); ++i) {
+ const auto& sampler = fpIter->textureSampler(i);
+ auto texture = static_cast<GrD3DTexture*>(sampler.peekTexture());
+ shaderResourceViews[currTextureBinding] = texture->shaderResourceView();
+ samplers[currTextureBinding] =
+ gpu->resourceProvider().findOrCreateCompatibleSampler(sampler.samplerState());
+ gpu->currentCommandList()->addSampledTextureRef(texture);
+ rangeSizes[currTextureBinding++] = 1;
+ }
}
-}
-
-static void fill_in_rasterizer_state(const GrPipeline& pipeline, const GrCaps* caps,
- D3D12_RASTERIZER_DESC* rasterizer) {
- rasterizer->FillMode = (caps->wireframeMode() || pipeline.isWireframe()) ?
- D3D12_FILL_MODE_WIREFRAME : D3D12_FILL_MODE_SOLID;
- rasterizer->CullMode = D3D12_CULL_MODE_NONE;
- rasterizer->FrontCounterClockwise = true;
- rasterizer->DepthBias = 0;
- rasterizer->DepthBiasClamp = 0.0f;
- rasterizer->SlopeScaledDepthBias = 0.0f;
- rasterizer->DepthClipEnable = false;
- rasterizer->MultisampleEnable = pipeline.isHWAntialiasState();
- rasterizer->AntialiasedLineEnable = false;
- rasterizer->ForcedSampleCount = 0;
- rasterizer->ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
-}
-
-static D3D12_STENCIL_OP stencil_op_to_d3d_op(GrStencilOp op) {
- switch (op) {
- case GrStencilOp::kKeep:
- return D3D12_STENCIL_OP_KEEP;
- case GrStencilOp::kZero:
- return D3D12_STENCIL_OP_ZERO;
- case GrStencilOp::kReplace:
- return D3D12_STENCIL_OP_REPLACE;
- case GrStencilOp::kInvert:
- return D3D12_STENCIL_OP_INVERT;
- case GrStencilOp::kIncWrap:
- return D3D12_STENCIL_OP_INCR;
- case GrStencilOp::kDecWrap:
- return D3D12_STENCIL_OP_DECR;
- case GrStencilOp::kIncClamp:
- return D3D12_STENCIL_OP_INCR_SAT;
- case GrStencilOp::kDecClamp:
- return D3D12_STENCIL_OP_DECR_SAT;
+ SkASSERT(!fpIter && !glslIter);
+
+ if (GrTexture* dstTexture = pipeline.peekDstTexture()) {
+ auto texture = static_cast<GrD3DTexture*>(dstTexture);
+ shaderResourceViews[currTextureBinding] = texture->shaderResourceView();
+ samplers[currTextureBinding] = gpu->resourceProvider().findOrCreateCompatibleSampler(
+ GrSamplerState::Filter::kNearest);
+ gpu->currentCommandList()->addSampledTextureRef(texture);
+ rangeSizes[currTextureBinding++] = 1;
}
- SkUNREACHABLE;
-}
-static D3D12_COMPARISON_FUNC stencil_test_to_d3d_func(GrStencilTest test) {
- switch (test) {
- case GrStencilTest::kAlways:
- return D3D12_COMPARISON_FUNC_ALWAYS;
- case GrStencilTest::kNever:
- return D3D12_COMPARISON_FUNC_NEVER;
- case GrStencilTest::kGreater:
- return D3D12_COMPARISON_FUNC_GREATER;
- case GrStencilTest::kGEqual:
- return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
- case GrStencilTest::kLess:
- return D3D12_COMPARISON_FUNC_LESS;
- case GrStencilTest::kLEqual:
- return D3D12_COMPARISON_FUNC_LESS_EQUAL;
- case GrStencilTest::kEqual:
- return D3D12_COMPARISON_FUNC_EQUAL;
- case GrStencilTest::kNotEqual:
- return D3D12_COMPARISON_FUNC_NOT_EQUAL;
+ SkASSERT(fNumSamplers == currTextureBinding);
+
+ // fill in descriptor tables and bind to root signature
+ if (fNumSamplers > 0) {
+ // set up and bind shader resource view table
+ std::unique_ptr<GrD3DDescriptorTable> srvTable =
+ gpu->resourceProvider().createShaderOrConstantResourceTable(fNumSamplers);
+ gpu->device()->CopyDescriptors(1, srvTable->baseCpuDescriptorPtr(), &fNumSamplers,
+ fNumSamplers, shaderResourceViews.get(), rangeSizes.get(),
+ srvTable->type());
+ gpu->currentCommandList()->setGraphicsRootDescriptorTable(
+ static_cast<unsigned int>(GrD3DRootSignature::ParamIndex::kTextureDescriptorTable),
+ srvTable->baseGpuDescriptor());
+
+ // set up and bind sampler table
+ std::unique_ptr<GrD3DDescriptorTable> samplerTable =
+ gpu->resourceProvider().createSamplerTable(fNumSamplers);
+ gpu->device()->CopyDescriptors(1, samplerTable->baseCpuDescriptorPtr(), &fNumSamplers,
+ fNumSamplers, samplers.get(), rangeSizes.get(),
+ samplerTable->type());
+ gpu->currentCommandList()->setGraphicsRootDescriptorTable(
+ static_cast<unsigned int>(GrD3DRootSignature::ParamIndex::kSamplerDescriptorTable),
+ samplerTable->baseGpuDescriptor());
}
- SkUNREACHABLE;
-}
-
-static void setup_stencilop_desc(D3D12_DEPTH_STENCILOP_DESC* desc,
- const GrStencilSettings::Face& stencilFace) {
- desc->StencilFailOp = stencil_op_to_d3d_op(stencilFace.fFailOp);
- desc->StencilDepthFailOp = desc->StencilFailOp;
- desc->StencilPassOp = stencil_op_to_d3d_op(stencilFace.fPassOp);
- desc->StencilFunc = stencil_test_to_d3d_func(stencilFace.fTest);
}
-static void fill_in_depth_stencil_state(const GrProgramInfo& programInfo,
- D3D12_DEPTH_STENCIL_DESC* dsDesc) {
- GrStencilSettings stencilSettings = programInfo.nonGLStencilSettings();
- GrSurfaceOrigin origin = programInfo.origin();
-
- dsDesc->DepthEnable = false;
- dsDesc->DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
- dsDesc->DepthFunc = D3D12_COMPARISON_FUNC_NEVER;
- dsDesc->StencilEnable = !stencilSettings.isDisabled();
- if (!stencilSettings.isDisabled()) {
- if (stencilSettings.isTwoSided()) {
- const auto& frontFace = stencilSettings.postOriginCCWFace(origin);
- const auto& backFace = stencilSettings.postOriginCCWFace(origin);
-
- SkASSERT(frontFace.fTestMask == backFace.fTestMask);
- SkASSERT(frontFace.fWriteMask == backFace.fWriteMask);
- dsDesc->StencilReadMask = frontFace.fTestMask;
- dsDesc->StencilWriteMask = frontFace.fWriteMask;
-
- setup_stencilop_desc(&dsDesc->FrontFace, frontFace);
- setup_stencilop_desc(&dsDesc->BackFace, backFace);
- } else {
- dsDesc->StencilReadMask = stencilSettings.singleSidedFace().fTestMask;
- dsDesc->StencilWriteMask = stencilSettings.singleSidedFace().fTestMask;
- setup_stencilop_desc(&dsDesc->FrontFace, stencilSettings.singleSidedFace());
- dsDesc->BackFace = dsDesc->FrontFace;
+void GrD3DPipelineState::bindBuffers(GrD3DGpu* gpu, const GrBuffer* indexBuffer,
+ const GrBuffer* instanceBuffer, const GrBuffer* vertexBuffer,
+ GrD3DDirectCommandList* commandList) {
+ // Here our vertex and instance inputs need to match the same 0-based bindings they were
+ // assigned in the PipelineState. That is, vertex first (if any) followed by instance.
+ if (auto* d3dVertexBuffer = static_cast<const GrD3DBuffer*>(vertexBuffer)) {
+ SkASSERT(!d3dVertexBuffer->isCpuBuffer());
+ SkASSERT(!d3dVertexBuffer->isMapped());
+ const_cast<GrD3DBuffer*>(d3dVertexBuffer)->setResourceState(
+ gpu, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
+ auto* d3dInstanceBuffer = static_cast<const GrD3DBuffer*>(instanceBuffer);
+ if (d3dInstanceBuffer) {
+ SkASSERT(!d3dInstanceBuffer->isCpuBuffer());
+ SkASSERT(!d3dInstanceBuffer->isMapped());
+ const_cast<GrD3DBuffer*>(d3dInstanceBuffer)->setResourceState(
+ gpu, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
}
+ commandList->setVertexBuffers(0, d3dVertexBuffer, fVertexStride,
+ d3dInstanceBuffer, fInstanceStride);
}
-}
-
-static D3D12_PRIMITIVE_TOPOLOGY_TYPE gr_primitive_type_to_d3d(GrPrimitiveType primitiveType) {
- switch (primitiveType) {
- case GrPrimitiveType::kTriangles:
- case GrPrimitiveType::kTriangleStrip: //fall through
- return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
- case GrPrimitiveType::kPoints:
- return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
- case GrPrimitiveType::kLines: // fall through
- case GrPrimitiveType::kLineStrip:
- return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
- case GrPrimitiveType::kPatches: // fall through, unsupported
- case GrPrimitiveType::kPath: // fall through, unsupported
- default:
- SkUNREACHABLE;
+ if (auto* d3dIndexBuffer = static_cast<const GrD3DBuffer*>(indexBuffer)) {
+ SkASSERT(!d3dIndexBuffer->isCpuBuffer());
+ SkASSERT(!d3dIndexBuffer->isMapped());
+ const_cast<GrD3DBuffer*>(d3dIndexBuffer)->setResourceState(
+ gpu, D3D12_RESOURCE_STATE_INDEX_BUFFER);
+ commandList->setIndexBuffer(d3dIndexBuffer);
}
}
-
-sk_sp<GrD3DPipelineState> GrD3DPipelineState::Make(GrD3DGpu* gpu,
- const GrProgramInfo& programInfo,
- sk_sp<GrD3DRootSignature> rootSig,
- gr_cp<ID3DBlob> vertexShader,
- gr_cp<ID3DBlob> geometryShader,
- gr_cp<ID3DBlob> pixelShader,
- DXGI_FORMAT renderTargetFormat,
- DXGI_FORMAT depthStencilFormat,
- unsigned int sampleQualityLevel) {
- D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
-
- psoDesc.pRootSignature = rootSig->rootSignature();
-
- psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()),
- vertexShader->GetBufferSize() };
- psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()),
- pixelShader->GetBufferSize() };
-
- if (geometryShader.get()) {
- psoDesc.GS = { reinterpret_cast<UINT8*>(geometryShader->GetBufferPointer()),
- geometryShader->GetBufferSize() };
- }
-
- psoDesc.StreamOutput = {nullptr, 0, nullptr, 0, 0};
-
- fill_in_blend_state(programInfo.pipeline(), &psoDesc.BlendState);
- psoDesc.SampleMask = UINT_MAX;
-
- fill_in_rasterizer_state(programInfo.pipeline(), gpu->caps(), &psoDesc.RasterizerState);
-
- fill_in_depth_stencil_state(programInfo, &psoDesc.DepthStencilState);
-
- unsigned int totalAttributeCnt = programInfo.primProc().numVertexAttributes() +
- programInfo.primProc().numInstanceAttributes();
- SkAutoSTArray<4, D3D12_INPUT_ELEMENT_DESC> inputElements(totalAttributeCnt);
- setup_vertex_input_layout(programInfo.primProc(), inputElements.get());
-
- psoDesc.InputLayout = { inputElements.get(), totalAttributeCnt };
-
- psoDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
-
- // This is for geometry or hull shader primitives
- psoDesc.PrimitiveTopologyType = gr_primitive_type_to_d3d(programInfo.primitiveType());
-
- psoDesc.NumRenderTargets = 1;
-
- psoDesc.RTVFormats[0] = renderTargetFormat;
-
- psoDesc.DSVFormat = depthStencilFormat;
-
- unsigned int numRasterSamples = programInfo.numRasterSamples();
- psoDesc.SampleDesc = {numRasterSamples, sampleQualityLevel};
-
- // Only used for multi-adapter systems.
- psoDesc.NodeMask = 0;
-
- psoDesc.CachedPSO = {nullptr, 0};
- psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
-
- gr_cp<ID3D12PipelineState> pipelineState;
- SkDEBUGCODE(HRESULT hr = )gpu->device()->CreateGraphicsPipelineState(
- &psoDesc, IID_PPV_ARGS(&pipelineState));
- SkASSERT(SUCCEEDED(hr));
-
- return sk_sp<GrD3DPipelineState>(new GrD3DPipelineState(std::move(pipelineState)));
-}
-
-GrD3DPipelineState::GrD3DPipelineState(gr_cp<ID3D12PipelineState> pipelineState)
- : fPipelineState(std::move(pipelineState)) {}
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.h
index b6eb50a8d24..0925571d950 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineState.h
@@ -12,21 +12,30 @@
#include "include/gpu/GrTypes.h"
#include "include/gpu/d3d/GrD3DTypes.h"
#include "src/gpu/GrManagedResource.h"
+#include "src/gpu/d3d/GrD3DPipelineStateDataManager.h"
+#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
+class GrD3DDirectCommandList;
class GrD3DGpu;
class GrD3DRootSignature;
class GrProgramInfo;
class GrD3DPipelineState : public GrManagedResource {
public:
- static sk_sp<GrD3DPipelineState> Make(GrD3DGpu* gpu, const GrProgramInfo&,
- sk_sp<GrD3DRootSignature> rootSig,
- gr_cp<ID3DBlob> vertexShader,
- gr_cp<ID3DBlob> geometryShader,
- gr_cp<ID3DBlob> pixelShader,
- DXGI_FORMAT renderTargetFormat,
- DXGI_FORMAT depthStencilFormat,
- unsigned int sampleQualityLevel);
+ using UniformInfoArray = GrD3DPipelineStateDataManager::UniformInfoArray;
+
+ GrD3DPipelineState(gr_cp<ID3D12PipelineState> pipelineState,
+ sk_sp<GrD3DRootSignature> rootSignature,
+ const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
+ const UniformInfoArray& uniforms,
+ uint32_t uniformSize,
+ uint32_t numSamplers,
+ std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
+ std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
+ std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragProcessors,
+ int fragmentProcessorCnt,
+ size_t vertexStride,
+ size_t instanceStride);
#ifdef SK_TRACE_MANAGED_RESOURCES
/** Output a human-readable dump of this resource's information
@@ -41,12 +50,81 @@ public:
void freeGPUData() const override {}
ID3D12PipelineState* pipelineState() const { return fPipelineState.get(); }
+ const sk_sp<GrD3DRootSignature>& rootSignature() const { return fRootSignature; }
+
+ void setAndBindConstants(GrD3DGpu*, const GrRenderTarget*, const GrProgramInfo&);
+
+ void setAndBindTextures(GrD3DGpu*, const GrPrimitiveProcessor& primProc,
+ const GrSurfaceProxy* const primProcTextures[],
+ const GrPipeline& pipeline);
+
+ void bindBuffers(GrD3DGpu*, const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
+ const GrBuffer* vertexBuffer, GrD3DDirectCommandList* commandList);
+
+ // We can only cache non dirty uniform values until we submit a command list. After that, the
+ // next frame will get a completely different uniform buffer and/or offset into the buffer. Thus
+ // we need a way to mark them all as dirty during submit.
+ void markUniformsDirty() { fDataManager.markDirty(); }
private:
- GrD3DPipelineState(gr_cp<ID3D12PipelineState> pipelineState);
+ /**
+ * We use the RT's size and origin to adjust from Skia device space to d3d normalized device
+ * space and to make device space positions have the correct origin for processors that require
+ * them.
+ */
+ struct RenderTargetState {
+ SkISize fRenderTargetSize;
+ GrSurfaceOrigin fRenderTargetOrigin;
+
+ RenderTargetState() { this->invalidate(); }
+ void invalidate() {
+ fRenderTargetSize.fWidth = -1;
+ fRenderTargetSize.fHeight = -1;
+ fRenderTargetOrigin = (GrSurfaceOrigin)-1;
+ }
+
+ /**
+ * Gets a float4 that adjusts the position from Skia device coords to D3D's normalized device
+ * coords. Assuming the transformed position, pos, is a homogeneous float3, the vec, v, is
+ * applied as such:
+ * pos.x = dot(v.xy, pos.xz)
+ * pos.y = dot(v.zw, pos.yz)
+ */
+ void getRTAdjustmentVec(float* destVec) {
+ destVec[0] = 2.f / fRenderTargetSize.fWidth;
+ destVec[1] = -1.f;
+ // D3D's NDC space is flipped from Vulkan and Metal
+ if (kTopLeft_GrSurfaceOrigin == fRenderTargetOrigin) {
+ destVec[2] = -2.f / fRenderTargetSize.fHeight;
+ destVec[3] = 1.f;
+ } else {
+ destVec[2] = 2.f / fRenderTargetSize.fHeight;
+ destVec[3] = -1.f;
+ }
+ }
+ };
+
+ // Helper for setData() that sets the view matrix and loads the render target height uniform
+ void setRenderTargetState(const GrRenderTarget*, GrSurfaceOrigin);
gr_cp<ID3D12PipelineState> fPipelineState;
+ sk_sp<GrD3DRootSignature> fRootSignature;
+
+ // Tracks the current render target uniforms stored in the vertex buffer.
+ RenderTargetState fRenderTargetState;
+ GrGLSLBuiltinUniformHandles fBuiltinUniformHandles;
+
+ // Processors in the GrD3DPipelineState
+ std::unique_ptr<GrGLSLPrimitiveProcessor> fGeometryProcessor;
+ std::unique_ptr<GrGLSLXferProcessor> fXferProcessor;
+ std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fFragmentProcessors;
+ int fFragmentProcessorCnt;
+
+ GrD3DPipelineStateDataManager fDataManager;
+ unsigned int fNumSamplers;
+ size_t fVertexStride;
+ size_t fInstanceStride;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp
index f03858ec832..5c2b91f509d 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp
@@ -14,6 +14,7 @@
#include "src/core/SkTraceEvent.h"
#include "src/gpu/GrAutoLocaleSetter.h"
#include "src/gpu/GrContextPriv.h"
+#include "src/gpu/GrPersistentCacheUtils.h"
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/GrShaderUtils.h"
#include "src/gpu/GrStencilSettings.h"
@@ -24,8 +25,6 @@
#include <d3dcompiler.h>
-typedef size_t shader_size;
-
sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::MakePipelineState(
GrD3DGpu* gpu,
GrRenderTarget* renderTarget,
@@ -66,27 +65,9 @@ void GrD3DPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outp
outputColor.addLayoutQualifier("location = 0, index = 1");
}
-void GrD3DPipelineStateBuilder::compileD3DProgram(SkSL::Program::Kind kind,
- const SkSL::String& sksl,
- const SkSL::Program::Settings& settings,
- ID3DBlob** shader,
- SkSL::Program::Inputs* outInputs) {
- auto errorHandler = fGpu->getContext()->priv().getShaderErrorHandler();
- std::unique_ptr<SkSL::Program> program = fGpu->shaderCompiler()->convertProgram(
- kind, sksl, settings);
- if (!program) {
- errorHandler->compileError(sksl.c_str(),
- fGpu->shaderCompiler()->errorText().c_str());
- return;
- }
- *outInputs = program->fInputs;
- SkSL::String outHLSL;
- if (!fGpu->shaderCompiler()->toHLSL(*program, &outHLSL)) {
- errorHandler->compileError(sksl.c_str(),
- fGpu->shaderCompiler()->errorText().c_str());
- return;
- }
-
+static gr_cp<ID3DBlob> GrCompileHLSLShader(GrD3DGpu* gpu,
+ const SkSL::String& hlsl,
+ SkSL::Program::Kind kind) {
const char* compileTarget = nullptr;
switch (kind) {
case SkSL::Program::kVertex_Kind:
@@ -110,16 +91,452 @@ void GrD3DPipelineStateBuilder::compileD3DProgram(SkSL::Program::Kind kind,
// SPRIV-cross does matrix multiplication expecting row major matrices
compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
- // TODO: D3D Static Function
+ gr_cp<ID3DBlob> shader;
gr_cp<ID3DBlob> errors;
- HRESULT hr = D3DCompile(outHLSL.c_str(), outHLSL.length(), nullptr, nullptr, nullptr, "main",
- compileTarget, compileFlags, 0, shader, &errors);
+ HRESULT hr = D3DCompile(hlsl.c_str(), hlsl.length(), nullptr, nullptr, nullptr, "main",
+ compileTarget, compileFlags, 0, &shader, &errors);
if (!SUCCEEDED(hr)) {
- errorHandler->compileError(outHLSL.c_str(),
- reinterpret_cast<char*>(errors->GetBufferPointer()));
+ gpu->getContext()->priv().getShaderErrorHandler()->compileError(
+ hlsl.c_str(), reinterpret_cast<char*>(errors->GetBufferPointer()));
+ }
+ return shader;
+}
+
+bool GrD3DPipelineStateBuilder::loadHLSLFromCache(SkReadBuffer* reader, gr_cp<ID3DBlob> shaders[]) {
+
+ SkSL::String hlsl[kGrShaderTypeCount];
+ SkSL::Program::Inputs inputs[kGrShaderTypeCount];
+
+ if (!GrPersistentCacheUtils::UnpackCachedShaders(reader, hlsl, inputs, kGrShaderTypeCount)) {
+ return false;
}
+
+ auto compile = [&](SkSL::Program::Kind kind, GrShaderType shaderType) {
+ if (inputs[shaderType].fRTHeight) {
+ this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
+ }
+ shaders[shaderType] = GrCompileHLSLShader(fGpu, hlsl[shaderType], kind);
+ return shaders[shaderType].get();
+ };
+
+ return compile(SkSL::Program::kVertex_Kind, kVertex_GrShaderType) &&
+ compile(SkSL::Program::kFragment_Kind, kFragment_GrShaderType) &&
+ (hlsl[kGeometry_GrShaderType].empty() ||
+ compile(SkSL::Program::kGeometry_Kind, kGeometry_GrShaderType));
}
+gr_cp<ID3DBlob> GrD3DPipelineStateBuilder::compileD3DProgram(
+ SkSL::Program::Kind kind,
+ const SkSL::String& sksl,
+ const SkSL::Program::Settings& settings,
+ SkSL::Program::Inputs* outInputs,
+ SkSL::String* outHLSL) {
+ auto errorHandler = fGpu->getContext()->priv().getShaderErrorHandler();
+ std::unique_ptr<SkSL::Program> program = fGpu->shaderCompiler()->convertProgram(
+ kind, sksl, settings);
+ if (!program) {
+ errorHandler->compileError(sksl.c_str(),
+ fGpu->shaderCompiler()->errorText().c_str());
+ return gr_cp<ID3DBlob>();
+ }
+ *outInputs = program->fInputs;
+ if (!fGpu->shaderCompiler()->toHLSL(*program, outHLSL)) {
+ errorHandler->compileError(sksl.c_str(),
+ fGpu->shaderCompiler()->errorText().c_str());
+ return gr_cp<ID3DBlob>();
+ }
+
+ if (program->fInputs.fRTHeight) {
+ this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
+ }
+
+ return GrCompileHLSLShader(fGpu, *outHLSL, kind);
+}
+
+static DXGI_FORMAT attrib_type_to_format(GrVertexAttribType type) {
+ switch (type) {
+ case kFloat_GrVertexAttribType:
+ return DXGI_FORMAT_R32_FLOAT;
+ case kFloat2_GrVertexAttribType:
+ return DXGI_FORMAT_R32G32_FLOAT;
+ case kFloat3_GrVertexAttribType:
+ return DXGI_FORMAT_R32G32B32_FLOAT;
+ case kFloat4_GrVertexAttribType:
+ return DXGI_FORMAT_R32G32B32A32_FLOAT;
+ case kHalf_GrVertexAttribType:
+ return DXGI_FORMAT_R16_FLOAT;
+ case kHalf2_GrVertexAttribType:
+ return DXGI_FORMAT_R16G16_FLOAT;
+ case kHalf4_GrVertexAttribType:
+ return DXGI_FORMAT_R16G16B16A16_FLOAT;
+ case kInt2_GrVertexAttribType:
+ return DXGI_FORMAT_R32G32_SINT;
+ case kInt3_GrVertexAttribType:
+ return DXGI_FORMAT_R32G32B32_SINT;
+ case kInt4_GrVertexAttribType:
+ return DXGI_FORMAT_R32G32B32A32_SINT;
+ case kByte_GrVertexAttribType:
+ return DXGI_FORMAT_R8_SINT;
+ case kByte2_GrVertexAttribType:
+ return DXGI_FORMAT_R8G8_SINT;
+ case kByte4_GrVertexAttribType:
+ return DXGI_FORMAT_R8G8B8A8_SINT;
+ case kUByte_GrVertexAttribType:
+ return DXGI_FORMAT_R8_UINT;
+ case kUByte2_GrVertexAttribType:
+ return DXGI_FORMAT_R8G8_UINT;
+ case kUByte4_GrVertexAttribType:
+ return DXGI_FORMAT_R8G8B8A8_UINT;
+ case kUByte_norm_GrVertexAttribType:
+ return DXGI_FORMAT_R8_UNORM;
+ case kUByte4_norm_GrVertexAttribType:
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+ case kShort2_GrVertexAttribType:
+ return DXGI_FORMAT_R16G16_SINT;
+ case kShort4_GrVertexAttribType:
+ return DXGI_FORMAT_R16G16B16A16_SINT;
+ case kUShort2_GrVertexAttribType:
+ return DXGI_FORMAT_R16G16_UINT;
+ case kUShort2_norm_GrVertexAttribType:
+ return DXGI_FORMAT_R16G16_UNORM;
+ case kInt_GrVertexAttribType:
+ return DXGI_FORMAT_R32_SINT;
+ case kUint_GrVertexAttribType:
+ return DXGI_FORMAT_R32_UINT;
+ case kUShort_norm_GrVertexAttribType:
+ return DXGI_FORMAT_R16_UNORM;
+ case kUShort4_norm_GrVertexAttribType:
+ return DXGI_FORMAT_R16G16B16A16_UNORM;
+ }
+ SK_ABORT("Unknown vertex attrib type");
+}
+
+static void setup_vertex_input_layout(const GrPrimitiveProcessor& primProc,
+ D3D12_INPUT_ELEMENT_DESC* inputElements) {
+ unsigned int slotNumber = 0;
+ unsigned int vertexSlot = 0;
+ unsigned int instanceSlot = 0;
+ if (primProc.hasVertexAttributes()) {
+ vertexSlot = slotNumber++;
+ }
+ if (primProc.hasInstanceAttributes()) {
+ instanceSlot = slotNumber++;
+ }
+
+ unsigned int currentAttrib = 0;
+ unsigned int vertexAttributeOffset = 0;
+
+ for (const auto& attrib : primProc.vertexAttributes()) {
+ // When using SPIRV-Cross it converts the location modifier in SPIRV to be
+ // TEXCOORD<N> where N is the location value for eveery vertext attribute
+ inputElements[currentAttrib] = { "TEXCOORD", currentAttrib,
+ attrib_type_to_format(attrib.cpuType()),
+ vertexSlot, vertexAttributeOffset,
+ D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 };
+ vertexAttributeOffset += attrib.sizeAlign4();
+ currentAttrib++;
+ }
+ SkASSERT(vertexAttributeOffset == primProc.vertexStride());
+
+ unsigned int instanceAttributeOffset = 0;
+ for (const auto& attrib : primProc.instanceAttributes()) {
+ // When using SPIRV-Cross it converts the location modifier in SPIRV to be
+ // TEXCOORD<N> where N is the location value for eveery vertext attribute
+ inputElements[currentAttrib] = { "TEXCOORD", currentAttrib,
+ attrib_type_to_format(attrib.cpuType()),
+ instanceSlot, instanceAttributeOffset,
+ D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA, 1 };
+ instanceAttributeOffset += attrib.sizeAlign4();
+ currentAttrib++;
+ }
+ SkASSERT(instanceAttributeOffset == primProc.instanceStride());
+}
+
+static D3D12_BLEND blend_coeff_to_d3d_blend(GrBlendCoeff coeff) {
+ switch (coeff) {
+ case kZero_GrBlendCoeff:
+ return D3D12_BLEND_ZERO;
+ case kOne_GrBlendCoeff:
+ return D3D12_BLEND_ONE;
+ case kSC_GrBlendCoeff:
+ return D3D12_BLEND_SRC_COLOR;
+ case kISC_GrBlendCoeff:
+ return D3D12_BLEND_INV_SRC_COLOR;
+ case kDC_GrBlendCoeff:
+ return D3D12_BLEND_DEST_COLOR;
+ case kIDC_GrBlendCoeff:
+ return D3D12_BLEND_INV_DEST_COLOR;
+ case kSA_GrBlendCoeff:
+ return D3D12_BLEND_SRC_ALPHA;
+ case kISA_GrBlendCoeff:
+ return D3D12_BLEND_INV_SRC_ALPHA;
+ case kDA_GrBlendCoeff:
+ return D3D12_BLEND_DEST_ALPHA;
+ case kIDA_GrBlendCoeff:
+ return D3D12_BLEND_INV_DEST_ALPHA;
+ case kConstC_GrBlendCoeff:
+ return D3D12_BLEND_BLEND_FACTOR;
+ case kIConstC_GrBlendCoeff:
+ return D3D12_BLEND_INV_BLEND_FACTOR;
+ case kS2C_GrBlendCoeff:
+ return D3D12_BLEND_SRC1_COLOR;
+ case kIS2C_GrBlendCoeff:
+ return D3D12_BLEND_INV_SRC1_COLOR;
+ case kS2A_GrBlendCoeff:
+ return D3D12_BLEND_SRC1_ALPHA;
+ case kIS2A_GrBlendCoeff:
+ return D3D12_BLEND_INV_SRC1_ALPHA;
+ case kIllegal_GrBlendCoeff:
+ return D3D12_BLEND_ZERO;
+ }
+ SkUNREACHABLE;
+}
+
+static D3D12_BLEND blend_coeff_to_d3d_blend_for_alpha(GrBlendCoeff coeff) {
+ switch (coeff) {
+ // Force all srcColor used in alpha slot to alpha version.
+ case kSC_GrBlendCoeff:
+ return D3D12_BLEND_SRC_ALPHA;
+ case kISC_GrBlendCoeff:
+ return D3D12_BLEND_INV_SRC_ALPHA;
+ case kDC_GrBlendCoeff:
+ return D3D12_BLEND_DEST_ALPHA;
+ case kIDC_GrBlendCoeff:
+ return D3D12_BLEND_INV_DEST_ALPHA;
+ case kS2C_GrBlendCoeff:
+ return D3D12_BLEND_SRC1_ALPHA;
+ case kIS2C_GrBlendCoeff:
+ return D3D12_BLEND_INV_SRC1_ALPHA;
+
+ default:
+ return blend_coeff_to_d3d_blend(coeff);
+ }
+}
+
+
+static D3D12_BLEND_OP blend_equation_to_d3d_op(GrBlendEquation equation) {
+ switch (equation) {
+ case kAdd_GrBlendEquation:
+ return D3D12_BLEND_OP_ADD;
+ case kSubtract_GrBlendEquation:
+ return D3D12_BLEND_OP_SUBTRACT;
+ case kReverseSubtract_GrBlendEquation:
+ return D3D12_BLEND_OP_REV_SUBTRACT;
+ default:
+ SkUNREACHABLE;
+ }
+}
+
+static void fill_in_blend_state(const GrPipeline& pipeline, D3D12_BLEND_DESC* blendDesc) {
+ blendDesc->AlphaToCoverageEnable = false;
+ blendDesc->IndependentBlendEnable = false;
+
+ const GrXferProcessor::BlendInfo& blendInfo = pipeline.getXferProcessor().getBlendInfo();
+
+ GrBlendEquation equation = blendInfo.fEquation;
+ GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
+ GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
+ bool blendOff = GrBlendShouldDisable(equation, srcCoeff, dstCoeff);
+
+ auto& rtBlend = blendDesc->RenderTarget[0];
+ rtBlend.BlendEnable = !blendOff;
+ if (!blendOff) {
+ rtBlend.SrcBlend = blend_coeff_to_d3d_blend(srcCoeff);
+ rtBlend.DestBlend = blend_coeff_to_d3d_blend(dstCoeff);
+ rtBlend.BlendOp = blend_equation_to_d3d_op(equation);
+ rtBlend.SrcBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(srcCoeff);
+ rtBlend.DestBlendAlpha = blend_coeff_to_d3d_blend_for_alpha(dstCoeff);
+ rtBlend.BlendOpAlpha = blend_equation_to_d3d_op(equation);
+ }
+
+ if (!blendInfo.fWriteColor) {
+ rtBlend.RenderTargetWriteMask = 0;
+ } else {
+ rtBlend.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
+ }
+}
+
+static void fill_in_rasterizer_state(const GrPipeline& pipeline, const GrCaps* caps,
+ D3D12_RASTERIZER_DESC* rasterizer) {
+ rasterizer->FillMode = (caps->wireframeMode() || pipeline.isWireframe()) ?
+ D3D12_FILL_MODE_WIREFRAME : D3D12_FILL_MODE_SOLID;
+ rasterizer->CullMode = D3D12_CULL_MODE_NONE;
+ rasterizer->FrontCounterClockwise = true;
+ rasterizer->DepthBias = 0;
+ rasterizer->DepthBiasClamp = 0.0f;
+ rasterizer->SlopeScaledDepthBias = 0.0f;
+ rasterizer->DepthClipEnable = false;
+ rasterizer->MultisampleEnable = pipeline.isHWAntialiasState();
+ rasterizer->AntialiasedLineEnable = false;
+ rasterizer->ForcedSampleCount = 0;
+ rasterizer->ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
+}
+
+static D3D12_STENCIL_OP stencil_op_to_d3d_op(GrStencilOp op) {
+ switch (op) {
+ case GrStencilOp::kKeep:
+ return D3D12_STENCIL_OP_KEEP;
+ case GrStencilOp::kZero:
+ return D3D12_STENCIL_OP_ZERO;
+ case GrStencilOp::kReplace:
+ return D3D12_STENCIL_OP_REPLACE;
+ case GrStencilOp::kInvert:
+ return D3D12_STENCIL_OP_INVERT;
+ case GrStencilOp::kIncWrap:
+ return D3D12_STENCIL_OP_INCR;
+ case GrStencilOp::kDecWrap:
+ return D3D12_STENCIL_OP_DECR;
+ case GrStencilOp::kIncClamp:
+ return D3D12_STENCIL_OP_INCR_SAT;
+ case GrStencilOp::kDecClamp:
+ return D3D12_STENCIL_OP_DECR_SAT;
+ }
+ SkUNREACHABLE;
+}
+
+static D3D12_COMPARISON_FUNC stencil_test_to_d3d_func(GrStencilTest test) {
+ switch (test) {
+ case GrStencilTest::kAlways:
+ return D3D12_COMPARISON_FUNC_ALWAYS;
+ case GrStencilTest::kNever:
+ return D3D12_COMPARISON_FUNC_NEVER;
+ case GrStencilTest::kGreater:
+ return D3D12_COMPARISON_FUNC_GREATER;
+ case GrStencilTest::kGEqual:
+ return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
+ case GrStencilTest::kLess:
+ return D3D12_COMPARISON_FUNC_LESS;
+ case GrStencilTest::kLEqual:
+ return D3D12_COMPARISON_FUNC_LESS_EQUAL;
+ case GrStencilTest::kEqual:
+ return D3D12_COMPARISON_FUNC_EQUAL;
+ case GrStencilTest::kNotEqual:
+ return D3D12_COMPARISON_FUNC_NOT_EQUAL;
+ }
+ SkUNREACHABLE;
+}
+
+static void setup_stencilop_desc(D3D12_DEPTH_STENCILOP_DESC* desc,
+ const GrStencilSettings::Face& stencilFace) {
+ desc->StencilFailOp = stencil_op_to_d3d_op(stencilFace.fFailOp);
+ desc->StencilDepthFailOp = desc->StencilFailOp;
+ desc->StencilPassOp = stencil_op_to_d3d_op(stencilFace.fPassOp);
+ desc->StencilFunc = stencil_test_to_d3d_func(stencilFace.fTest);
+}
+
+static void fill_in_depth_stencil_state(const GrProgramInfo& programInfo,
+ D3D12_DEPTH_STENCIL_DESC* dsDesc) {
+ GrStencilSettings stencilSettings = programInfo.nonGLStencilSettings();
+ GrSurfaceOrigin origin = programInfo.origin();
+
+ dsDesc->DepthEnable = false;
+ dsDesc->DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
+ dsDesc->DepthFunc = D3D12_COMPARISON_FUNC_NEVER;
+ dsDesc->StencilEnable = !stencilSettings.isDisabled();
+ if (!stencilSettings.isDisabled()) {
+ if (stencilSettings.isTwoSided()) {
+ const auto& frontFace = stencilSettings.postOriginCCWFace(origin);
+ const auto& backFace = stencilSettings.postOriginCWFace(origin);
+
+ SkASSERT(frontFace.fTestMask == backFace.fTestMask);
+ SkASSERT(frontFace.fWriteMask == backFace.fWriteMask);
+ dsDesc->StencilReadMask = frontFace.fTestMask;
+ dsDesc->StencilWriteMask = frontFace.fWriteMask;
+
+ setup_stencilop_desc(&dsDesc->FrontFace, frontFace);
+ setup_stencilop_desc(&dsDesc->BackFace, backFace);
+ } else {
+ dsDesc->StencilReadMask = stencilSettings.singleSidedFace().fTestMask;
+ dsDesc->StencilWriteMask = stencilSettings.singleSidedFace().fWriteMask;
+ setup_stencilop_desc(&dsDesc->FrontFace, stencilSettings.singleSidedFace());
+ dsDesc->BackFace = dsDesc->FrontFace;
+ }
+ }
+}
+
+static D3D12_PRIMITIVE_TOPOLOGY_TYPE gr_primitive_type_to_d3d(GrPrimitiveType primitiveType) {
+ switch (primitiveType) {
+ case GrPrimitiveType::kTriangles:
+ case GrPrimitiveType::kTriangleStrip: //fall through
+ return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
+ case GrPrimitiveType::kPoints:
+ return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
+ case GrPrimitiveType::kLines: // fall through
+ case GrPrimitiveType::kLineStrip:
+ return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
+ case GrPrimitiveType::kPatches: // fall through, unsupported
+ case GrPrimitiveType::kPath: // fall through, unsupported
+ default:
+ SkUNREACHABLE;
+ }
+}
+
+gr_cp<ID3D12PipelineState> create_pipeline_state(
+ GrD3DGpu* gpu, const GrProgramInfo& programInfo, const sk_sp<GrD3DRootSignature>& rootSig,
+ gr_cp<ID3DBlob> vertexShader, gr_cp<ID3DBlob> geometryShader, gr_cp<ID3DBlob> pixelShader,
+ DXGI_FORMAT renderTargetFormat, DXGI_FORMAT depthStencilFormat,
+ unsigned int sampleQualityLevel) {
+ D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
+
+ psoDesc.pRootSignature = rootSig->rootSignature();
+
+ psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()),
+ vertexShader->GetBufferSize() };
+ psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()),
+ pixelShader->GetBufferSize() };
+
+ if (geometryShader.get()) {
+ psoDesc.GS = { reinterpret_cast<UINT8*>(geometryShader->GetBufferPointer()),
+ geometryShader->GetBufferSize() };
+ }
+
+ psoDesc.StreamOutput = { nullptr, 0, nullptr, 0, 0 };
+
+ fill_in_blend_state(programInfo.pipeline(), &psoDesc.BlendState);
+ psoDesc.SampleMask = UINT_MAX;
+
+ fill_in_rasterizer_state(programInfo.pipeline(), gpu->caps(), &psoDesc.RasterizerState);
+
+ fill_in_depth_stencil_state(programInfo, &psoDesc.DepthStencilState);
+
+ unsigned int totalAttributeCnt = programInfo.primProc().numVertexAttributes() +
+ programInfo.primProc().numInstanceAttributes();
+ SkAutoSTArray<4, D3D12_INPUT_ELEMENT_DESC> inputElements(totalAttributeCnt);
+ setup_vertex_input_layout(programInfo.primProc(), inputElements.get());
+
+ psoDesc.InputLayout = { inputElements.get(), totalAttributeCnt };
+
+ psoDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
+
+ // This is for geometry or hull shader primitives
+ psoDesc.PrimitiveTopologyType = gr_primitive_type_to_d3d(programInfo.primitiveType());
+
+ psoDesc.NumRenderTargets = 1;
+
+ psoDesc.RTVFormats[0] = renderTargetFormat;
+
+ psoDesc.DSVFormat = depthStencilFormat;
+
+ unsigned int numRasterSamples = programInfo.numRasterSamples();
+ psoDesc.SampleDesc = { numRasterSamples, sampleQualityLevel };
+
+ // Only used for multi-adapter systems.
+ psoDesc.NodeMask = 0;
+
+ psoDesc.CachedPSO = { nullptr, 0 };
+ psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
+
+ gr_cp<ID3D12PipelineState> pipelineState;
+ SkDEBUGCODE(HRESULT hr = )gpu->device()->CreateGraphicsPipelineState(
+ &psoDesc, IID_PPV_ARGS(&pipelineState));
+ SkASSERT(SUCCEEDED(hr));
+
+ return pipelineState;
+}
+
+static constexpr SkFourByteTag kHLSL_Tag = SkSetFourByteTag('H', 'L', 'S', 'L');
+static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
+
sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
@@ -135,32 +552,86 @@ sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() {
SkSL::Program::Settings settings;
settings.fCaps = this->caps()->shaderCaps();
settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
+ settings.fInverseW = true;
settings.fSharpenTextures =
this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures;
settings.fRTHeightOffset = fUniformHandler.getRTHeightOffset();
settings.fRTHeightBinding = 0;
settings.fRTHeightSet = 0;
- gr_cp<ID3DBlob> vertexShader;
- gr_cp<ID3DBlob> geometryShader;
- gr_cp<ID3DBlob> pixelShader;
- SkSL::Program::Inputs vertInputs, fragInputs, geomInputs;
+ sk_sp<SkData> cached;
+ SkReadBuffer reader;
+ SkFourByteTag shaderType = 0;
+ auto persistentCache = fGpu->getContext()->priv().getPersistentCache();
+ if (persistentCache) {
+ // Shear off the D3D-specific portion of the Desc to get the persistent key. We only cache
+ // shader code, not entire pipelines.
+ sk_sp<SkData> key =
+ SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().initialKeyLength());
+ cached = persistentCache->load(*key);
+ if (cached) {
+ reader.setMemory(cached->data(), cached->size());
+ shaderType = GrPersistentCacheUtils::GetType(&reader);
+ }
+ }
- this->compileD3DProgram(SkSL::Program::kVertex_Kind, fVS.fCompilerString, settings,
- &vertexShader, &vertInputs);
- this->compileD3DProgram(SkSL::Program::kFragment_Kind, fFS.fCompilerString, settings,
- &pixelShader, &fragInputs);
+ const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
+ gr_cp<ID3DBlob> shaders[kGrShaderTypeCount];
- if (!vertexShader.get() || !pixelShader.get()) {
- return nullptr;
- }
+ if (kHLSL_Tag == shaderType && this->loadHLSLFromCache(&reader, shaders)) {
+ // We successfully loaded and compiled HLSL
+ } else {
+ SkSL::Program::Inputs inputs[kGrShaderTypeCount];
+ SkSL::String* sksl[kGrShaderTypeCount] = {
+ &fVS.fCompilerString,
+ &fGS.fCompilerString,
+ &fFS.fCompilerString,
+ };
+ SkSL::String cached_sksl[kGrShaderTypeCount];
+ SkSL::String hlsl[kGrShaderTypeCount];
- if (this->primitiveProcessor().willUseGeoShader()) {
- this->compileD3DProgram(SkSL::Program::kGeometry_Kind, fGS.fCompilerString, settings,
- &geometryShader, &geomInputs);
- if (!geometryShader.get()) {
+ if (kSKSL_Tag == shaderType) {
+ if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, inputs,
+ kGrShaderTypeCount)) {
+ for (int i = 0; i < kGrShaderTypeCount; ++i) {
+ sksl[i] = &cached_sksl[i];
+ }
+ }
+ }
+
+ auto compile = [&](SkSL::Program::Kind kind, GrShaderType shaderType) {
+ shaders[shaderType] = this->compileD3DProgram(kind, *sksl[shaderType], settings,
+ &inputs[shaderType], &hlsl[shaderType]);
+ return shaders[shaderType].get();
+ };
+
+ if (!compile(SkSL::Program::kVertex_Kind, kVertex_GrShaderType) ||
+ !compile(SkSL::Program::kFragment_Kind, kFragment_GrShaderType)) {
return nullptr;
}
+
+ if (primProc.willUseGeoShader()) {
+ if (!compile(SkSL::Program::kGeometry_Kind, kGeometry_GrShaderType)) {
+ return nullptr;
+ }
+ }
+
+ if (persistentCache && !cached) {
+ const bool cacheSkSL = fGpu->getContext()->priv().options().fShaderCacheStrategy ==
+ GrContextOptions::ShaderCacheStrategy::kSkSL;
+ if (cacheSkSL) {
+ // Replace the HLSL with formatted SkSL to be cached. This looks odd, but this is
+ // the last time we're going to use these strings, so it's safe.
+ for (int i = 0; i < kGrShaderTypeCount; ++i) {
+ hlsl[i] = GrShaderUtils::PrettyPrint(*sksl[i]);
+ }
+ }
+ sk_sp<SkData> key =
+ SkData::MakeWithoutCopy(this->desc().asKey(), this->desc().initialKeyLength());
+ sk_sp<SkData> data = GrPersistentCacheUtils::PackCachedShaders(
+ cacheSkSL ? kSKSL_Tag : kHLSL_Tag, hlsl, inputs, kGrShaderTypeCount);
+ persistentCache->store(*key, *data);
+ }
}
sk_sp<GrD3DRootSignature> rootSig =
@@ -170,8 +641,21 @@ sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() {
}
const GrD3DRenderTarget* rt = static_cast<const GrD3DRenderTarget*>(fRenderTarget);
- return GrD3DPipelineState::Make(fGpu, fProgramInfo, std::move(rootSig),
- std::move(vertexShader), std::move(geometryShader),
- std::move(pixelShader), rt->dxgiFormat(),
- rt->stencilDxgiFormat(), rt->sampleQualityLevel());
+ gr_cp<ID3D12PipelineState> pipelineState = create_pipeline_state(
+ fGpu, fProgramInfo, rootSig, std::move(shaders[kVertex_GrShaderType]),
+ std::move(shaders[kGeometry_GrShaderType]), std::move(shaders[kFragment_GrShaderType]),
+ rt->dxgiFormat(), rt->stencilDxgiFormat(), rt->sampleQualityLevel());
+
+ return sk_sp<GrD3DPipelineState>(new GrD3DPipelineState(std::move(pipelineState),
+ std::move(rootSig),
+ fUniformHandles,
+ fUniformHandler.fUniforms,
+ fUniformHandler.fCurrentUBOOffset,
+ fUniformHandler.fSamplers.count(),
+ std::move(fGeometryProcessor),
+ std::move(fXferProcessor),
+ std::move(fFragmentProcessors),
+ fFragmentProcessorCnt,
+ primProc.vertexStride(),
+ primProc.instanceStride()));
}
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.h
index e5fc4171bbd..357c024b0cd 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateBuilder.h
@@ -18,7 +18,6 @@
class GrProgramDesc;
class GrD3DGpu;
class GrVkRenderPass;
-class SkReader32;
class GrD3DPipelineStateBuilder : public GrGLSLProgramBuilder {
public:
@@ -46,11 +45,13 @@ private:
sk_sp<GrD3DPipelineState> finalize();
- void compileD3DProgram(SkSL::Program::Kind kind,
- const SkSL::String& sksl,
- const SkSL::Program::Settings& settings,
- ID3DBlob** shader,
- SkSL::Program::Inputs* outInputs);
+ bool loadHLSLFromCache(SkReadBuffer* reader, gr_cp<ID3DBlob> shaders[]);
+
+ gr_cp<ID3DBlob> compileD3DProgram(SkSL::Program::Kind kind,
+ const SkSL::String& sksl,
+ const SkSL::Program::Settings& settings,
+ SkSL::Program::Inputs* outInputs,
+ SkSL::String* outHLSL);
GrGLSLUniformHandler* uniformHandler() override { return &fUniformHandler; }
const GrGLSLUniformHandler* uniformHandler() const override { return &fUniformHandler; }
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateDataManager.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateDataManager.cpp
new file mode 100644
index 00000000000..a902bddc9a5
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateDataManager.cpp
@@ -0,0 +1,41 @@
+/*
+* Copyright 2016 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#include "src/gpu/d3d/GrD3DPipelineStateDataManager.h"
+
+#include "src/gpu/d3d/GrD3DGpu.h"
+#include "src/gpu/d3d/GrD3DResourceProvider.h"
+
+GrD3DPipelineStateDataManager::GrD3DPipelineStateDataManager(const UniformInfoArray& uniforms,
+ uint32_t uniformSize)
+ : INHERITED(uniforms.count(), uniformSize) {
+ // We must add uniforms in same order as the UniformInfoArray so that UniformHandles already
+ // owned by other objects will still match up here.
+ int i = 0;
+ for (const auto& uniformInfo : uniforms.items()) {
+ Uniform& uniform = fUniforms[i];
+ SkASSERT(GrShaderVar::kNonArray == uniformInfo.fVariable.getArrayCount() ||
+ uniformInfo.fVariable.getArrayCount() > 0);
+ SkDEBUGCODE(
+ uniform.fArrayCount = uniformInfo.fVariable.getArrayCount();
+ uniform.fType = uniformInfo.fVariable.getType();
+ )
+
+ uniform.fOffset = uniformInfo.fUBOOffset;
+ ++i;
+ }
+}
+
+D3D12_GPU_VIRTUAL_ADDRESS GrD3DPipelineStateDataManager::uploadConstants(GrD3DGpu* gpu) {
+ if (fUniformsDirty) {
+ fConstantBufferAddress = gpu->resourceProvider().uploadConstantData(fUniformData.get(),
+ fUniformSize);
+ fUniformsDirty = false;
+ }
+
+ return fConstantBufferAddress;
+}
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateDataManager.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateDataManager.h
new file mode 100644
index 00000000000..15a41abc42f
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DPipelineStateDataManager.h
@@ -0,0 +1,34 @@
+/*
+* Copyright 2020 Google LLC
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#ifndef GrD3DPipelineStateDataManager_DEFINED
+#define GrD3DPipelineStateDataManager_DEFINED
+
+#include "src/gpu/GrUniformDataManager.h"
+
+#include "include/gpu/d3d/GrD3DTypes.h"
+#include "src/gpu/GrSPIRVUniformHandler.h"
+
+class GrD3DConstantRingBuffer;
+class GrD3DGpu;
+
+class GrD3DPipelineStateDataManager : public GrUniformDataManager {
+public:
+ typedef GrSPIRVUniformHandler::UniformInfoArray UniformInfoArray;
+
+ GrD3DPipelineStateDataManager(const UniformInfoArray&,
+ uint32_t uniformSize);
+
+ D3D12_GPU_VIRTUAL_ADDRESS uploadConstants(GrD3DGpu* gpu);
+
+private:
+ D3D12_GPU_VIRTUAL_ADDRESS fConstantBufferAddress;
+
+ typedef GrUniformDataManager INHERITED;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.cpp
index 4dd2e6092ec..b572a6f5c7b 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.cpp
@@ -24,8 +24,8 @@ GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
sk_sp<GrD3DResourceState> state,
const GrD3DTextureResourceInfo& msaaInfo,
sk_sp<GrD3DResourceState> msaaState,
- const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView,
- const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView,
Wrapped)
: GrSurface(gpu, dimensions, info.fProtected)
, GrD3DTextureResource(info, std::move(state))
@@ -48,8 +48,8 @@ GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
sk_sp<GrD3DResourceState> state,
const GrD3DTextureResourceInfo& msaaInfo,
sk_sp<GrD3DResourceState> msaaState,
- const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView,
- const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView)
+ const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView)
: GrSurface(gpu, dimensions, info.fProtected)
, GrD3DTextureResource(info, std::move(state))
// for the moment we only support 1:1 color to stencil
@@ -67,7 +67,7 @@ GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
SkISize dimensions,
const GrD3DTextureResourceInfo& info,
sk_sp<GrD3DResourceState> state,
- const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& renderTargetView,
Wrapped)
: GrSurface(gpu, dimensions, info.fProtected)
, GrD3DTextureResource(info, std::move(state))
@@ -83,7 +83,7 @@ GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
SkISize dimensions,
const GrD3DTextureResourceInfo& info,
sk_sp<GrD3DResourceState> state,
- const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView)
+ const GrD3DDescriptorHeap::CPUHandle& renderTargetView)
: GrSurface(gpu, dimensions, info.fProtected)
, GrD3DTextureResource(info, std::move(state))
, GrRenderTarget(gpu, dimensions, 1, info.fProtected)
@@ -98,7 +98,7 @@ sk_sp<GrD3DRenderTarget> GrD3DRenderTarget::MakeWrappedRenderTarget(
SkASSERT(1 == info.fLevelCount);
DXGI_FORMAT dxgiFormat = info.fFormat;
- D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView =
+ GrD3DDescriptorHeap::CPUHandle renderTargetView =
gpu->resourceProvider().createRenderTargetView(info.fResource.get());
// create msaa surface if necessary
@@ -137,7 +137,7 @@ sk_sp<GrD3DRenderTarget> GrD3DRenderTarget::MakeWrappedRenderTarget(
msState.reset(new GrD3DResourceState(
static_cast<D3D12_RESOURCE_STATES>(msInfo.fResourceState)));
- D3D12_CPU_DESCRIPTOR_HANDLE msaaRenderTargetView =
+ GrD3DDescriptorHeap::CPUHandle msaaRenderTargetView =
gpu->resourceProvider().createRenderTargetView(msInfo.fResource.get());
d3dRT = new GrD3DRenderTarget(gpu, dimensions, sampleCnt, info, std::move(state), msInfo,
@@ -162,10 +162,10 @@ void GrD3DRenderTarget::releaseInternalObjects() {
if (fMSAATextureResource) {
fMSAATextureResource->releaseResource(gpu);
fMSAATextureResource.reset();
- gpu->resourceProvider().recycleRenderTargetView(&fResolveRenderTargetView);
+ gpu->resourceProvider().recycleRenderTargetView(fResolveRenderTargetView);
}
- gpu->resourceProvider().recycleRenderTargetView(&fColorRenderTargetView);
+ gpu->resourceProvider().recycleRenderTargetView(fColorRenderTargetView);
}
void GrD3DRenderTarget::onRelease() {
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.h
index e2829a444ca..c83cf60020e 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DRenderTarget.h
@@ -14,6 +14,7 @@
#include "include/gpu/d3d/GrD3DTypes.h"
#include "src/gpu/GrGpu.h"
+#include "src/gpu/d3d/GrD3DDescriptorHeap.h"
#include "src/gpu/d3d/GrD3DResourceProvider.h"
class GrD3DGpu;
@@ -36,7 +37,7 @@ public:
GrBackendFormat backendFormat() const override { return this->getBackendFormat(); }
- GrD3DTextureResource* msaaTextureResource() { return fMSAATextureResource.get(); }
+ GrD3DTextureResource* msaaTextureResource() const { return fMSAATextureResource.get(); }
bool canAttemptStencilAttachment() const override {
return true;
@@ -44,8 +45,8 @@ public:
GrBackendRenderTarget getBackendRenderTarget() const override;
- D3D12_CPU_DESCRIPTOR_HANDLE colorRenderTargetView() {
- return fColorRenderTargetView;
+ D3D12_CPU_DESCRIPTOR_HANDLE colorRenderTargetView() const {
+ return fColorRenderTargetView.fHandle;
}
DXGI_FORMAT stencilDxgiFormat() const;
@@ -61,14 +62,14 @@ protected:
sk_sp<GrD3DResourceState> state,
const GrD3DTextureResourceInfo& msaaInfo,
sk_sp<GrD3DResourceState> msaaState,
- const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView,
- const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView);
+ const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView);
GrD3DRenderTarget(GrD3DGpu* gpu,
SkISize dimensions,
const GrD3DTextureResourceInfo& info,
sk_sp<GrD3DResourceState> state,
- const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView);
+ const GrD3DDescriptorHeap::CPUHandle& renderTargetView);
void onAbandon() override;
void onRelease() override;
@@ -95,15 +96,15 @@ private:
sk_sp<GrD3DResourceState> state,
const GrD3DTextureResourceInfo& msaaInfo,
sk_sp<GrD3DResourceState> msaaState,
- const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView,
- const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView,
Wrapped);
GrD3DRenderTarget(GrD3DGpu* gpu,
SkISize dimensions,
const GrD3DTextureResourceInfo& info,
sk_sp<GrD3DResourceState> state,
- const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& renderTargetView,
Wrapped);
GrD3DGpu* getD3DGpu() const;
@@ -121,8 +122,8 @@ private:
std::unique_ptr<GrD3DTextureResource> fMSAATextureResource;
- D3D12_CPU_DESCRIPTOR_HANDLE fColorRenderTargetView;
- D3D12_CPU_DESCRIPTOR_HANDLE fResolveRenderTargetView;
+ GrD3DDescriptorHeap::CPUHandle fColorRenderTargetView;
+ GrD3DDescriptorHeap::CPUHandle fResolveRenderTargetView;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.cpp
index f93b36c2687..c933743e358 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.cpp
@@ -9,6 +9,7 @@
#include "include/gpu/GrContextOptions.h"
#include "src/gpu/GrContextPriv.h"
+#include "src/gpu/d3d/GrD3DBuffer.h"
#include "src/gpu/d3d/GrD3DCommandList.h"
#include "src/gpu/d3d/GrD3DGpu.h"
#include "src/gpu/d3d/GrD3DPipelineState.h"
@@ -16,8 +17,14 @@
GrD3DResourceProvider::GrD3DResourceProvider(GrD3DGpu* gpu)
: fGpu(gpu)
- , fAttachmentViewManager(gpu)
- , fPipelineStateCache(new PipelineStateCache(gpu)) {
+ , fCpuDescriptorManager(gpu)
+ , fDescriptorTableManager(gpu)
+ , fPipelineStateCache(new PipelineStateCache(gpu)) {}
+
+void GrD3DResourceProvider::destroyResources() {
+ fSamplers.reset();
+
+ fPipelineStateCache->release();
}
std::unique_ptr<GrD3DDirectCommandList> GrD3DResourceProvider::findOrCreateDirectCommandList() {
@@ -52,22 +59,91 @@ sk_sp<GrD3DRootSignature> GrD3DResourceProvider::findOrCreateRootSignature(int n
}
-D3D12_CPU_DESCRIPTOR_HANDLE GrD3DResourceProvider::createRenderTargetView(
+GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createRenderTargetView(
ID3D12Resource* textureResource) {
- return fAttachmentViewManager.createRenderTargetView(fGpu, textureResource);
+ return fCpuDescriptorManager.createRenderTargetView(fGpu, textureResource);
}
-void GrD3DResourceProvider::recycleRenderTargetView(D3D12_CPU_DESCRIPTOR_HANDLE* rtvDescriptor) {
- fAttachmentViewManager.recycleRenderTargetView(rtvDescriptor);
+void GrD3DResourceProvider::recycleRenderTargetView(
+ const GrD3DDescriptorHeap::CPUHandle& rtvDescriptor) {
+ fCpuDescriptorManager.recycleRenderTargetView(rtvDescriptor);
}
-D3D12_CPU_DESCRIPTOR_HANDLE GrD3DResourceProvider::createDepthStencilView(
+GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createDepthStencilView(
ID3D12Resource* textureResource) {
- return fAttachmentViewManager.createDepthStencilView(fGpu, textureResource);
+ return fCpuDescriptorManager.createDepthStencilView(fGpu, textureResource);
+}
+
+void GrD3DResourceProvider::recycleDepthStencilView(
+ const GrD3DDescriptorHeap::CPUHandle& dsvDescriptor) {
+ fCpuDescriptorManager.recycleDepthStencilView(dsvDescriptor);
+}
+
+GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createConstantBufferView(
+ ID3D12Resource* bufferResource, size_t offset, size_t size) {
+ return fCpuDescriptorManager.createConstantBufferView(fGpu, bufferResource, offset, size);
+}
+
+GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createShaderResourceView(
+ ID3D12Resource* resource) {
+ return fCpuDescriptorManager.createShaderResourceView(fGpu, resource);
+}
+
+void GrD3DResourceProvider::recycleConstantOrShaderView(
+ const GrD3DDescriptorHeap::CPUHandle& view) {
+ fCpuDescriptorManager.recycleConstantOrShaderView(view);
}
-void GrD3DResourceProvider::recycleDepthStencilView(D3D12_CPU_DESCRIPTOR_HANDLE* dsvDescriptor) {
- fAttachmentViewManager.recycleDepthStencilView(dsvDescriptor);
+static D3D12_TEXTURE_ADDRESS_MODE wrap_mode_to_d3d_address_mode(GrSamplerState::WrapMode wrapMode) {
+ switch (wrapMode) {
+ case GrSamplerState::WrapMode::kClamp:
+ return D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+ case GrSamplerState::WrapMode::kRepeat:
+ return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
+ case GrSamplerState::WrapMode::kMirrorRepeat:
+ return D3D12_TEXTURE_ADDRESS_MODE_MIRROR;
+ case GrSamplerState::WrapMode::kClampToBorder:
+ return D3D12_TEXTURE_ADDRESS_MODE_BORDER;
+ }
+ SK_ABORT("Unknown wrap mode.");
+}
+
+D3D12_CPU_DESCRIPTOR_HANDLE GrD3DResourceProvider::findOrCreateCompatibleSampler(
+ const GrSamplerState& params) {
+ uint32_t key = GrSamplerState::GenerateKey(params);
+ D3D12_CPU_DESCRIPTOR_HANDLE* samplerPtr = fSamplers.find(key);
+ if (samplerPtr) {
+ return *samplerPtr;
+ }
+
+ static D3D12_FILTER d3dFilterModes[] = {
+ D3D12_FILTER_MIN_MAG_MIP_POINT,
+ D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT,
+ D3D12_FILTER_MIN_MAG_MIP_LINEAR
+ };
+
+ static_assert((int)GrSamplerState::Filter::kNearest == 0);
+ static_assert((int)GrSamplerState::Filter::kBilerp == 1);
+ static_assert((int)GrSamplerState::Filter::kMipMap == 2);
+
+ D3D12_FILTER filter = d3dFilterModes[static_cast<int>(params.filter())];
+ D3D12_TEXTURE_ADDRESS_MODE addressModeU = wrap_mode_to_d3d_address_mode(params.wrapModeX());
+ D3D12_TEXTURE_ADDRESS_MODE addressModeV = wrap_mode_to_d3d_address_mode(params.wrapModeY());
+
+ D3D12_CPU_DESCRIPTOR_HANDLE sampler =
+ fCpuDescriptorManager.createSampler(
+ fGpu, filter, addressModeU, addressModeV).fHandle;
+ fSamplers.set(key, sampler);
+ return sampler;
+}
+
+std::unique_ptr<GrD3DDescriptorTable> GrD3DResourceProvider::createShaderOrConstantResourceTable(
+ unsigned int size) {
+ return fDescriptorTableManager.createShaderOrConstantResourceTable(fGpu, size);
+}
+
+std::unique_ptr<GrD3DDescriptorTable> GrD3DResourceProvider::createSamplerTable(unsigned int size) {
+ return fDescriptorTableManager.createSamplerTable(fGpu, size);
}
sk_sp<GrD3DPipelineState> GrD3DResourceProvider::findOrCreateCompatiblePipelineState(
@@ -75,6 +151,34 @@ sk_sp<GrD3DPipelineState> GrD3DResourceProvider::findOrCreateCompatiblePipelineS
return fPipelineStateCache->refPipelineState(rt, info);
}
+D3D12_GPU_VIRTUAL_ADDRESS GrD3DResourceProvider::uploadConstantData(void* data, size_t size) {
+ // constant size has to be aligned to 256
+ constexpr int kConstantAlignment = 256;
+
+ // Due to dependency on the resource cache we can't initialize this in the constructor, so
+ // we do so it here.
+ if (!fConstantBuffer) {
+ fConstantBuffer = GrD3DConstantRingBuffer::Make(fGpu, 128 * 1024, kConstantAlignment);
+ SkASSERT(fConstantBuffer);
+ }
+
+ // upload the data
+ size_t paddedSize = GrAlignTo(size, kConstantAlignment);
+ GrRingBuffer::Slice slice = fConstantBuffer->suballocate(paddedSize);
+ char* destPtr = static_cast<char*>(slice.fBuffer->map()) + slice.fOffset;
+ memcpy(destPtr, data, size);
+
+ // create the associated constant buffer view descriptor
+ GrD3DBuffer* d3dBuffer = static_cast<GrD3DBuffer*>(slice.fBuffer.get());
+ D3D12_GPU_VIRTUAL_ADDRESS gpuAddress = d3dBuffer->d3dResource()->GetGPUVirtualAddress();
+ return gpuAddress + slice.fOffset;
+}
+
+void GrD3DResourceProvider::prepForSubmit() {
+ fGpu->currentCommandList()->setCurrentConstantBuffer(fConstantBuffer);
+ fDescriptorTableManager.prepForSubmit(fGpu);
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef GR_PIPELINE_STATE_CACHE_STATS
@@ -114,6 +218,10 @@ GrD3DResourceProvider::PipelineStateCache::~PipelineStateCache() {
#endif
}
+void GrD3DResourceProvider::PipelineStateCache::release() {
+ fMap.reset();
+}
+
sk_sp<GrD3DPipelineState> GrD3DResourceProvider::PipelineStateCache::refPipelineState(
GrRenderTarget* renderTarget, const GrProgramInfo& programInfo) {
#ifdef GR_PIPELINE_STATE_CACHE_STATS
@@ -144,3 +252,10 @@ sk_sp<GrD3DPipelineState> GrD3DResourceProvider::PipelineStateCache::refPipeline
}
return (*entry)->fPipelineState;
}
+
+void GrD3DResourceProvider::PipelineStateCache::markPipelineStateUniformsDirty() {
+ fMap.foreach ([](const GrProgramDesc*, std::unique_ptr<Entry>* entry) {
+ (*entry)->fPipelineState->markUniformsDirty();
+ });
+}
+
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.h
index 4e244cb632f..923342ab79f 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DResourceProvider.h
@@ -10,9 +10,12 @@
#include "include/gpu/d3d/GrD3DTypes.h"
#include "include/private/SkTArray.h"
+#include "include/private/SkTHash.h"
#include "src/core/SkLRUCache.h"
#include "src/gpu/GrProgramDesc.h"
-#include "src/gpu/d3d/GrD3DAttachmentViewManager.h"
+#include "src/gpu/d3d/GrD3DConstantRingBuffer.h"
+#include "src/gpu/d3d/GrD3DCpuDescriptorManager.h"
+#include "src/gpu/d3d/GrD3DDescriptorTableManager.h"
#include "src/gpu/d3d/GrD3DRootSignature.h"
#include <memory>
@@ -20,26 +23,53 @@
class GrD3DDirectCommandList;
class GrD3DGpu;
class GrD3DPipelineState;
+class GrSamplerState;
class GrD3DResourceProvider {
public:
GrD3DResourceProvider(GrD3DGpu*);
+ void destroyResources();
+
std::unique_ptr<GrD3DDirectCommandList> findOrCreateDirectCommandList();
void recycleDirectCommandList(std::unique_ptr<GrD3DDirectCommandList>);
sk_sp<GrD3DRootSignature> findOrCreateRootSignature(int numTextureSamplers);
- D3D12_CPU_DESCRIPTOR_HANDLE createRenderTargetView(ID3D12Resource* textureResource);
- void recycleRenderTargetView(D3D12_CPU_DESCRIPTOR_HANDLE*);
+ GrD3DDescriptorHeap::CPUHandle createRenderTargetView(ID3D12Resource* textureResource);
+ void recycleRenderTargetView(const GrD3DDescriptorHeap::CPUHandle&);
+
+ GrD3DDescriptorHeap::CPUHandle createDepthStencilView(ID3D12Resource* textureResource);
+ void recycleDepthStencilView(const GrD3DDescriptorHeap::CPUHandle&);
+
+ GrD3DDescriptorHeap::CPUHandle createConstantBufferView(ID3D12Resource* bufferResource,
+ size_t offset,
+ size_t size);
+ GrD3DDescriptorHeap::CPUHandle createShaderResourceView(ID3D12Resource* resource);
+ void recycleConstantOrShaderView(const GrD3DDescriptorHeap::CPUHandle&);
- D3D12_CPU_DESCRIPTOR_HANDLE createDepthStencilView(ID3D12Resource* textureResource);
- void recycleDepthStencilView(D3D12_CPU_DESCRIPTOR_HANDLE*);
+ D3D12_CPU_DESCRIPTOR_HANDLE findOrCreateCompatibleSampler(const GrSamplerState& params);
- sk_sp<GrD3DPipelineState> findOrCreateCompatiblePipelineState(GrRenderTarget*,
+
+ std::unique_ptr<GrD3DDescriptorTable> createShaderOrConstantResourceTable(unsigned int size);
+ std::unique_ptr<GrD3DDescriptorTable> createSamplerTable(unsigned int size);
+ GrD3DDescriptorTableManager* descriptorTableMgr() {
+ return &fDescriptorTableManager;
+ }
+
+ sk_sp<GrD3DPipelineState> findOrCreateCompatiblePipelineState(GrRenderTarget*,
const GrProgramInfo&);
+ D3D12_GPU_VIRTUAL_ADDRESS uploadConstantData(void* data, size_t size);
+ void prepForSubmit();
+
+ void markPipelineStateUniformsDirty() { fPipelineStateCache->markPipelineStateUniformsDirty(); }
+
+#if GR_TEST_UTILS
+ void resetShaderCacheForTesting() const { fPipelineStateCache->release(); }
+#endif
+
private:
#ifdef SK_DEBUG
#define GR_PIPELINE_STATE_CACHE_STATS
@@ -50,8 +80,11 @@ private:
PipelineStateCache(GrD3DGpu* gpu);
~PipelineStateCache();
+ void release();
sk_sp<GrD3DPipelineState> refPipelineState(GrRenderTarget*, const GrProgramInfo&);
+ void markPipelineStateUniformsDirty();
+
private:
struct Entry;
@@ -76,9 +109,14 @@ private:
SkSTArray<4, std::unique_ptr<GrD3DDirectCommandList>> fAvailableDirectCommandLists;
SkSTArray<4, sk_sp<GrD3DRootSignature>> fRootSignatures;
- GrD3DAttachmentViewManager fAttachmentViewManager;
+ GrD3DCpuDescriptorManager fCpuDescriptorManager;
+ GrD3DDescriptorTableManager fDescriptorTableManager;
+
+ sk_sp<GrD3DConstantRingBuffer> fConstantBuffer;
std::unique_ptr<PipelineStateCache> fPipelineStateCache;
+
+ SkTHashMap<uint32_t, D3D12_CPU_DESCRIPTOR_HANDLE> fSamplers;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.cpp
index b4f2d8ddc04..e64faa2ba0c 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.cpp
@@ -15,17 +15,9 @@ sk_sp<GrD3DRootSignature> GrD3DRootSignature::Make(GrD3DGpu* gpu, int numTexture
D3D12_ROOT_PARAMETER parameters[3];
// The first will always be our uniforms
- D3D12_DESCRIPTOR_RANGE uniformRange{};
- uniformRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
- uniformRange.NumDescriptors = 1;
- uniformRange.BaseShaderRegister = 0;
- // Spirv-Cross uses the descriptor set as the space in HSLS
- uniformRange.RegisterSpace = GrSPIRVUniformHandler::kUniformDescriptorSet;
- uniformRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
-
- parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- parameters[0].DescriptorTable.NumDescriptorRanges = 1;
- parameters[0].DescriptorTable.pDescriptorRanges = &uniformRange;
+ parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
+ parameters[0].Descriptor.ShaderRegister = 0;
+ parameters[0].Descriptor.RegisterSpace = GrSPIRVUniformHandler::kUniformDescriptorSet;
parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
SkAutoTArray<D3D12_DESCRIPTOR_RANGE> samplerRanges(numTextureSamplers);
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.h
index c133e2e5aca..025ac4d2a8e 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DRootSignature.h
@@ -17,6 +17,12 @@ class GrD3DRootSignature : public GrManagedResource {
public:
static sk_sp<GrD3DRootSignature> Make(GrD3DGpu* gpu, int numTextureSamplers);
+ enum class ParamIndex {
+ kConstantBufferView = 0,
+ kSamplerDescriptorTable = 1,
+ kTextureDescriptorTable = 2
+ };
+
bool isCompatible(int numTextureSamplers) const;
ID3D12RootSignature* rootSignature() const { return fRootSignature.get(); }
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.cpp
index e5dd5bcf339..c8925c1d87f 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.cpp
@@ -13,10 +13,12 @@ GrD3DStencilAttachment::GrD3DStencilAttachment(GrD3DGpu* gpu,
const Format& format,
const D3D12_RESOURCE_DESC& desc,
const GrD3DTextureResourceInfo& info,
- sk_sp<GrD3DResourceState> state)
+ sk_sp<GrD3DResourceState> state,
+ const GrD3DDescriptorHeap::CPUHandle& view)
: GrStencilAttachment(gpu, desc.Width, desc.Height, format.fStencilBits,
desc.SampleDesc.Count)
- , GrD3DTextureResource(info, state) {
+ , GrD3DTextureResource(info, state)
+ , fView(view) {
this->registerWithCache(SkBudgeted::kYes);
}
@@ -51,9 +53,12 @@ GrD3DStencilAttachment* GrD3DStencilAttachment::Make(GrD3DGpu* gpu,
return nullptr;
}
+ GrD3DDescriptorHeap::CPUHandle view =
+ gpu->resourceProvider().createDepthStencilView(info.fResource.get());
+
sk_sp<GrD3DResourceState> state(new GrD3DResourceState(info.fResourceState));
GrD3DStencilAttachment* stencil = new GrD3DStencilAttachment(gpu, format, resourceDesc,
- info, std::move(state));
+ info, std::move(state), view);
return stencil;
}
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.h
index 096626d9053..927637c9e15 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DStencilAttachment.h
@@ -11,11 +11,11 @@
#include "src/gpu/GrStencilAttachment.h"
#include "include/gpu/d3d/GrD3DTypes.h"
+#include "src/gpu/d3d/GrD3DDescriptorHeap.h"
#include "src/gpu/d3d/GrD3DTextureResource.h"
class GrD3DGpu;
-
class GrD3DStencilAttachment : public GrStencilAttachment, public GrD3DTextureResource {
public:
struct Format {
@@ -28,6 +28,10 @@ public:
~GrD3DStencilAttachment() override {}
+ D3D12_CPU_DESCRIPTOR_HANDLE view() const {
+ return fView.fHandle;
+ }
+
protected:
void onRelease() override;
void onAbandon() override;
@@ -39,9 +43,12 @@ private:
const Format& format,
const D3D12_RESOURCE_DESC&,
const GrD3DTextureResourceInfo&,
- sk_sp<GrD3DResourceState>);
+ sk_sp<GrD3DResourceState>,
+ const GrD3DDescriptorHeap::CPUHandle& view);
GrD3DGpu* getD3DGpu() const;
+
+ GrD3DDescriptorHeap::CPUHandle fView;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.cpp
index 458853a3ad6..b59fb4d5f4d 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.cpp
@@ -19,10 +19,12 @@ GrD3DTexture::GrD3DTexture(GrD3DGpu* gpu,
SkISize dimensions,
const GrD3DTextureResourceInfo& info,
sk_sp<GrD3DResourceState> state,
+ const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
GrMipMapsStatus mipMapsStatus)
: GrSurface(gpu, dimensions, info.fProtected)
, GrD3DTextureResource(info, std::move(state))
- , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus) {
+ , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus)
+ , fShaderResourceView(shaderResourceView) {
SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
this->registerWithCache(budgeted);
if (GrDxgiFormatIsCompressed(info.fFormat)) {
@@ -31,11 +33,14 @@ GrD3DTexture::GrD3DTexture(GrD3DGpu* gpu,
}
GrD3DTexture::GrD3DTexture(GrD3DGpu* gpu, SkISize dimensions, const GrD3DTextureResourceInfo& info,
- sk_sp<GrD3DResourceState> state, GrMipMapsStatus mipMapsStatus,
- GrWrapCacheable cacheable, GrIOType ioType)
+ sk_sp<GrD3DResourceState> state,
+ const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
+ GrMipMapsStatus mipMapsStatus, GrWrapCacheable cacheable,
+ GrIOType ioType)
: GrSurface(gpu, dimensions, info.fProtected)
, GrD3DTextureResource(info, std::move(state))
- , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus) {
+ , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus)
+ , fShaderResourceView(shaderResourceView) {
SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
if (ioType == kRead_GrIOType) {
this->setReadOnly();
@@ -48,10 +53,12 @@ GrD3DTexture::GrD3DTexture(GrD3DGpu* gpu,
SkISize dimensions,
const GrD3DTextureResourceInfo& info,
sk_sp<GrD3DResourceState> state,
+ const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
GrMipMapsStatus mipMapsStatus)
: GrSurface(gpu, dimensions, info.fProtected)
, GrD3DTextureResource(info, state)
- , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus) {
+ , INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus)
+ , fShaderResourceView(shaderResourceView) {
SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
}
@@ -70,8 +77,11 @@ sk_sp<GrD3DTexture> GrD3DTexture::MakeNewTexture(GrD3DGpu* gpu, SkBudgeted budge
sk_sp<GrD3DResourceState> state(
new GrD3DResourceState(static_cast<D3D12_RESOURCE_STATES>(info.fResourceState)));
+ GrD3DDescriptorHeap::CPUHandle shaderResourceView =
+ gpu->resourceProvider().createShaderResourceView(info.fResource.get());
+
GrD3DTexture* tex = new GrD3DTexture(gpu, budgeted, dimensions, info, std::move(state),
- mipMapsStatus);
+ shaderResourceView, mipMapsStatus);
return sk_sp<GrD3DTexture>(tex);
}
@@ -90,8 +100,12 @@ sk_sp<GrD3DTexture> GrD3DTexture::MakeWrappedTexture(GrD3DGpu* gpu,
GrMipMapsStatus mipMapsStatus = info.fLevelCount > 1 ? GrMipMapsStatus::kValid
: GrMipMapsStatus::kNotAllocated;
+ GrD3DDescriptorHeap::CPUHandle shaderResourceView =
+ gpu->resourceProvider().createShaderResourceView(info.fResource.get());
+
return sk_sp<GrD3DTexture>(new GrD3DTexture(gpu, dimensions, info, std::move(state),
- mipMapsStatus, cacheable, ioType));
+ shaderResourceView, mipMapsStatus, cacheable,
+ ioType));
}
void GrD3DTexture::onRelease() {
@@ -103,7 +117,9 @@ void GrD3DTexture::onRelease() {
this->removeFinishIdleProcs();
}
- this->releaseResource(this->getD3DGpu());
+ GrD3DGpu* gpu = this->getD3DGpu();
+ gpu->resourceProvider().recycleConstantOrShaderView(fShaderResourceView);
+ this->releaseResource(gpu);
INHERITED::onRelease();
}
@@ -117,7 +133,9 @@ void GrD3DTexture::onAbandon() {
this->removeFinishIdleProcs();
}
- this->releaseResource(this->getD3DGpu());
+ GrD3DGpu* gpu = this->getD3DGpu();
+ gpu->resourceProvider().recycleConstantOrShaderView(fShaderResourceView);
+ this->releaseResource(gpu);
INHERITED::onAbandon();
}
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.h
index 704f1b2146d..e6e9b56a42a 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DTexture.h
@@ -11,6 +11,7 @@
#include "src/core/SkLRUCache.h"
#include "src/gpu/GrSamplerState.h"
#include "src/gpu/GrTexture.h"
+#include "src/gpu/d3d/GrD3DDescriptorHeap.h"
#include "src/gpu/d3d/GrD3DTextureResource.h"
class GrD3DTexture : public GrTexture, public virtual GrD3DTextureResource {
@@ -34,6 +35,7 @@ public:
GrBackendTexture getBackendTexture() const override;
GrBackendFormat backendFormat() const override { return this->getBackendFormat(); }
+ D3D12_CPU_DESCRIPTOR_HANDLE shaderResourceView() { return fShaderResourceView.fHandle; }
void textureParamsModified() override {}
@@ -45,6 +47,7 @@ protected:
SkISize dimensions,
const GrD3DTextureResourceInfo&,
sk_sp<GrD3DResourceState>,
+ const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
GrMipMapsStatus);
GrD3DGpu* getD3DGpu() const;
@@ -60,9 +63,13 @@ protected:
private:
GrD3DTexture(GrD3DGpu*, SkBudgeted, SkISize dimensions, const GrD3DTextureResourceInfo&,
- sk_sp<GrD3DResourceState>, GrMipMapsStatus);
+ sk_sp<GrD3DResourceState>,
+ const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
+ GrMipMapsStatus);
GrD3DTexture(GrD3DGpu*, SkISize dimensions, const GrD3DTextureResourceInfo&,
- sk_sp<GrD3DResourceState>, GrMipMapsStatus, GrWrapCacheable, GrIOType);
+ sk_sp<GrD3DResourceState>,
+ const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
+ GrMipMapsStatus, GrWrapCacheable, GrIOType);
// In D3D we call the release proc after we are finished with the underlying
// GrSurfaceResource::Resource object (which occurs after the GPU has finished all work on it).
@@ -79,6 +86,8 @@ private:
}
};
+ GrD3DDescriptorHeap::CPUHandle fShaderResourceView;
+
typedef GrTexture INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.cpp
index 1aa178b5f61..f352e8d7954 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.cpp
@@ -13,13 +13,14 @@
GrD3DTextureRenderTarget::GrD3DTextureRenderTarget(
GrD3DGpu* gpu, SkBudgeted budgeted, SkISize dimensions, int sampleCnt,
const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state,
+ const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
const GrD3DTextureResourceInfo& msaaInfo, sk_sp<GrD3DResourceState> msaaState,
- const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView,
- const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView,
GrMipMapsStatus mipMapsStatus)
: GrSurface(gpu, dimensions, info.fProtected)
, GrD3DTextureResource(info, state)
- , GrD3DTexture(gpu, dimensions, info, state, mipMapsStatus)
+ , GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipMapsStatus)
, GrD3DRenderTarget(gpu, dimensions, sampleCnt, info, state, msaaInfo,
std::move(msaaState), colorRenderTargetView, resolveRenderTargetView) {
SkASSERT(info.fProtected == msaaInfo.fProtected);
@@ -29,11 +30,12 @@ GrD3DTextureRenderTarget::GrD3DTextureRenderTarget(
GrD3DTextureRenderTarget::GrD3DTextureRenderTarget(
GrD3DGpu* gpu, SkBudgeted budgeted, SkISize dimensions,
const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state,
- const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
+ const GrD3DDescriptorHeap::CPUHandle& renderTargetView,
GrMipMapsStatus mipMapsStatus)
: GrSurface(gpu, dimensions, info.fProtected)
, GrD3DTextureResource(info, state)
- , GrD3DTexture(gpu, dimensions, info, state, mipMapsStatus)
+ , GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipMapsStatus)
, GrD3DRenderTarget(gpu, dimensions, info, state, renderTargetView) {
this->registerWithCache(budgeted);
}
@@ -41,14 +43,15 @@ GrD3DTextureRenderTarget::GrD3DTextureRenderTarget(
GrD3DTextureRenderTarget::GrD3DTextureRenderTarget(
GrD3DGpu* gpu, SkISize dimensions, int sampleCnt,
const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state,
+ const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
const GrD3DTextureResourceInfo& msaaInfo, sk_sp<GrD3DResourceState> msaaState,
- const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView,
- const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView,
GrMipMapsStatus mipMapsStatus,
GrWrapCacheable cacheable)
: GrSurface(gpu, dimensions, info.fProtected)
, GrD3DTextureResource(info, state)
- , GrD3DTexture(gpu, dimensions, info, state, mipMapsStatus)
+ , GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipMapsStatus)
, GrD3DRenderTarget(gpu, dimensions, sampleCnt, info, state, msaaInfo,
std::move(msaaState), colorRenderTargetView, resolveRenderTargetView) {
SkASSERT(info.fProtected == msaaInfo.fProtected);
@@ -58,12 +61,13 @@ GrD3DTextureRenderTarget::GrD3DTextureRenderTarget(
GrD3DTextureRenderTarget::GrD3DTextureRenderTarget(
GrD3DGpu* gpu, SkISize dimensions,
const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state,
- const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
+ const GrD3DDescriptorHeap::CPUHandle& renderTargetView,
GrMipMapsStatus mipMapsStatus,
GrWrapCacheable cacheable)
: GrSurface(gpu, dimensions, info.fProtected)
, GrD3DTextureResource(info, state)
- , GrD3DTexture(gpu, dimensions, info, state, mipMapsStatus)
+ , GrD3DTexture(gpu, dimensions, info, state, shaderResourceView, mipMapsStatus)
, GrD3DRenderTarget(gpu, dimensions, info, state, renderTargetView) {
this->registerWithCacheWrapped(cacheable);
}
@@ -134,8 +138,11 @@ sk_sp<GrD3DTextureRenderTarget> GrD3DTextureRenderTarget::MakeNewTextureRenderTa
sk_sp<GrD3DResourceState> state(new GrD3DResourceState(
static_cast<D3D12_RESOURCE_STATES>(info.fResourceState)));
- const D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView =
- gpu->resourceProvider().createRenderTargetView(info.fResource.get());
+ const GrD3DDescriptorHeap::CPUHandle shaderResourceView =
+ gpu->resourceProvider().createShaderResourceView(info.fResource.get());
+
+ const GrD3DDescriptorHeap::CPUHandle renderTargetView =
+ gpu->resourceProvider().createRenderTargetView(info.fResource.get());
if (sampleCnt > 1) {
GrD3DTextureResourceInfo msInfo;
@@ -143,16 +150,17 @@ sk_sp<GrD3DTextureRenderTarget> GrD3DTextureRenderTarget::MakeNewTextureRenderTa
std::tie(msInfo, msState) = create_msaa_resource(gpu, dimensions, sampleCnt, info);
- const D3D12_CPU_DESCRIPTOR_HANDLE msaaRenderTargetView =
- gpu->resourceProvider().createRenderTargetView(msInfo.fResource.get());
+ const GrD3DDescriptorHeap::CPUHandle msaaRenderTargetView =
+ gpu->resourceProvider().createRenderTargetView(msInfo.fResource.get());
GrD3DTextureRenderTarget* trt = new GrD3DTextureRenderTarget(
- gpu, budgeted, dimensions, sampleCnt, info, std::move(state),
+ gpu, budgeted, dimensions, sampleCnt, info, std::move(state), shaderResourceView,
msInfo, std::move(msState), msaaRenderTargetView, renderTargetView, mipMapsStatus);
return sk_sp<GrD3DTextureRenderTarget>(trt);
} else {
GrD3DTextureRenderTarget* trt = new GrD3DTextureRenderTarget(
- gpu, budgeted, dimensions, info, std::move(state), renderTargetView, mipMapsStatus);
+ gpu, budgeted, dimensions, info, std::move(state), shaderResourceView,
+ renderTargetView, mipMapsStatus);
return sk_sp<GrD3DTextureRenderTarget>(trt);
}
}
@@ -172,25 +180,29 @@ sk_sp<GrD3DTextureRenderTarget> GrD3DTextureRenderTarget::MakeWrappedTextureRend
GrMipMapsStatus mipMapsStatus = info.fLevelCount > 1 ? GrMipMapsStatus::kDirty
: GrMipMapsStatus::kNotAllocated;
- const D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView =
- gpu->resourceProvider().createRenderTargetView(info.fResource.get());
+ const GrD3DDescriptorHeap::CPUHandle shaderResourceView =
+ gpu->resourceProvider().createShaderResourceView(info.fResource.get());
+
+ const GrD3DDescriptorHeap::CPUHandle renderTargetView =
+ gpu->resourceProvider().createRenderTargetView(info.fResource.get());
if (sampleCnt > 1) {
GrD3DTextureResourceInfo msInfo;
sk_sp<GrD3DResourceState> msState;
std::tie(msInfo, msState) = create_msaa_resource(gpu, dimensions, sampleCnt, info);
- const D3D12_CPU_DESCRIPTOR_HANDLE msaaRenderTargetView =
+ const GrD3DDescriptorHeap::CPUHandle msaaRenderTargetView =
gpu->resourceProvider().createRenderTargetView(msInfo.fResource.get());
GrD3DTextureRenderTarget* trt = new GrD3DTextureRenderTarget(
- gpu, dimensions, sampleCnt, info, std::move(state), msInfo, std::move(msState),
- msaaRenderTargetView, renderTargetView, mipMapsStatus, cacheable);
+ gpu, dimensions, sampleCnt, info, std::move(state), shaderResourceView,
+ msInfo, std::move(msState), msaaRenderTargetView, renderTargetView, mipMapsStatus,
+ cacheable);
return sk_sp<GrD3DTextureRenderTarget>(trt);
} else {
return sk_sp<GrD3DTextureRenderTarget>(new GrD3DTextureRenderTarget(
- gpu, dimensions, info, std::move(state), renderTargetView, mipMapsStatus,
- cacheable));
+ gpu, dimensions, info, std::move(state), shaderResourceView, renderTargetView,
+ mipMapsStatus, cacheable));
}
}
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.h
index 75ac076fb07..46d3ca5a3fc 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureRenderTarget.h
@@ -59,10 +59,11 @@ private:
int sampleCnt,
const GrD3DTextureResourceInfo& info,
sk_sp<GrD3DResourceState> state,
+ const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
const GrD3DTextureResourceInfo& msaaInfo,
sk_sp<GrD3DResourceState> msaaState,
- const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView,
- const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView,
GrMipMapsStatus);
// non-MSAA, not-wrapped
@@ -71,7 +72,8 @@ private:
SkISize dimensions,
const GrD3DTextureResourceInfo& info,
sk_sp<GrD3DResourceState> state,
- const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
+ const GrD3DDescriptorHeap::CPUHandle& renderTargetView,
GrMipMapsStatus);
// MSAA, wrapped
@@ -80,10 +82,11 @@ private:
int sampleCnt,
const GrD3DTextureResourceInfo& info,
sk_sp<GrD3DResourceState> state,
+ const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
const GrD3DTextureResourceInfo& msaaInfo,
sk_sp<GrD3DResourceState> msaaState,
- const D3D12_CPU_DESCRIPTOR_HANDLE& colorRenderTargetView,
- const D3D12_CPU_DESCRIPTOR_HANDLE& resolveRenderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView,
GrMipMapsStatus,
GrWrapCacheable);
@@ -92,7 +95,8 @@ private:
SkISize dimensions,
const GrD3DTextureResourceInfo& info,
sk_sp<GrD3DResourceState> state,
- const D3D12_CPU_DESCRIPTOR_HANDLE& renderTargetView,
+ const GrD3DDescriptorHeap::CPUHandle& shaderResourceView,
+ const GrD3DDescriptorHeap::CPUHandle& renderTargetView,
GrMipMapsStatus,
GrWrapCacheable);
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.cpp
index a62f2d8554d..a307d110365 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.cpp
@@ -16,14 +16,12 @@ void GrD3DTextureResource::setResourceState(const GrD3DGpu* gpu,
return;
}
- SkAutoTMalloc<D3D12_RESOURCE_TRANSITION_BARRIER> barriers(fInfo.fLevelCount);
- for (uint32_t mipLevel = 0; mipLevel < fInfo.fLevelCount; ++mipLevel) {
- barriers[mipLevel].pResource = this->d3dResource();
- barriers[mipLevel].Subresource = mipLevel;
- barriers[mipLevel].StateBefore = currentResourceState;
- barriers[mipLevel].StateAfter = newResourceState;
- }
- gpu->addResourceBarriers(this->resource(), fInfo.fLevelCount, barriers.get());
+ D3D12_RESOURCE_TRANSITION_BARRIER barrier;
+ barrier.pResource = this->d3dResource();
+ barrier.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ barrier.StateBefore = currentResourceState;
+ barrier.StateAfter = newResourceState;
+ gpu->addResourceBarriers(this->resource(), 1, &barrier);
this->updateResourceState(newResourceState);
}
@@ -78,6 +76,10 @@ GrD3DTextureResource::~GrD3DTextureResource() {
SkASSERT(!fResource);
}
+void GrD3DTextureResource::prepareForPresent(GrD3DGpu* gpu) {
+ this->setResourceState(gpu, D3D12_RESOURCE_STATE_PRESENT);
+}
+
void GrD3DTextureResource::releaseResource(GrD3DGpu* gpu) {
// TODO: do we need to migrate resource state if we change queues?
if (fResource) {
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.h
index bffb68988f3..6f091ea406b 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DTextureResource.h
@@ -55,6 +55,9 @@ public:
void setResourceState(const GrD3DGpu* gpu, D3D12_RESOURCE_STATES newResourceState);
+ // Changes the layout to present
+ void prepareForPresent(GrD3DGpu* gpu);
+
unsigned int sampleQualityLevel() const { return fInfo.fSampleQualityLevel; }
// This simply updates our tracking of the resourceState and does not actually do any gpu work.
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.cpp b/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.cpp
index 521fd5d684d..dd66b8355be 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.cpp
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.cpp
@@ -21,11 +21,3 @@ bool GrDxgiFormatIsCompressed(DXGI_FORMAT format) {
}
SkUNREACHABLE;
}
-
-SkImage::CompressionType GrDxgiFormatToCompressionType(DXGI_FORMAT format) {
- switch (format) {
- case DXGI_FORMAT_BC1_UNORM: return SkImage::CompressionType::kBC1_RGBA8_UNORM;
- default: return SkImage::CompressionType::kNone;
- }
- SkUNREACHABLE;
-}
diff --git a/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.h b/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.h
index b17f7a5dae8..c5aa209acf3 100644
--- a/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.h
+++ b/chromium/third_party/skia/src/gpu/d3d/GrD3DUtil.h
@@ -18,11 +18,6 @@
*/
bool GrDxgiFormatIsCompressed(DXGI_FORMAT);
-/**
- * Maps a dxgi format into the CompressionType enum if applicable.
- */
-SkImage::CompressionType GrDxgiFormatToCompressionType(DXGI_FORMAT dxgiFormat);
-
static constexpr uint32_t GrDxgiFormatChannels(DXGI_FORMAT vkFormat) {
switch (vkFormat) {
case DXGI_FORMAT_R8G8B8A8_UNORM: return kRGBA_SkColorChannelFlags;
diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.cpp b/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.cpp
index 15c4d8941c7..41b9fd851a4 100644
--- a/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.cpp
+++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.cpp
@@ -38,10 +38,6 @@ bool GrDawnCaps::isFormatSRGB(const GrBackendFormat& format) const {
return false;
}
-SkImage::CompressionType GrDawnCaps::compressionType(const GrBackendFormat& format) const {
- return SkImage::CompressionType::kNone;
-}
-
bool GrDawnCaps::isFormatTexturable(const GrBackendFormat& format) const {
// Currently, all the formats in GrDawnFormatToPixelConfig are texturable.
wgpu::TextureFormat dawnFormat;
@@ -67,6 +63,7 @@ static GrSwizzle get_swizzle(const GrBackendFormat& format, GrColorType colorTyp
if (!forOutput) {
return GrSwizzle::RGB1();
}
+ break;
default:
return GrSwizzle::RGBA();
}
@@ -88,6 +85,18 @@ bool GrDawnCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFo
return isFormatRenderable(format, sampleCount);
}
+GrCaps::SurfaceReadPixelsSupport GrDawnCaps::surfaceSupportsReadPixels(
+ const GrSurface* surface) const {
+ // We currently support readbacks only from Textures and TextureRenderTargets.
+ return surface->asTexture() ? SurfaceReadPixelsSupport::kSupported
+ : SurfaceReadPixelsSupport::kUnsupported;
+}
+
+bool GrDawnCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
+ // We currently support writePixels only to Textures and TextureRenderTargets.
+ return surface->asTexture() != nullptr;
+}
+
size_t GrDawnCaps::bytesPerPixel(const GrBackendFormat& backendFormat) const {
wgpu::TextureFormat dawnFormat;
if (!backendFormat.asDawnFormat(&dawnFormat)) {
@@ -122,7 +131,7 @@ GrBackendFormat GrDawnCaps::getBackendFormatFromCompressionType(SkImage::Compres
return GrBackendFormat();
}
-GrSwizzle GrDawnCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const
+GrSwizzle GrDawnCaps::onGetReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const
{
return get_swizzle(format, colorType, false);
}
diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.h b/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.h
index c6922a9855e..fc2f8b52ed2 100644
--- a/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.h
+++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnCaps.h
@@ -18,7 +18,6 @@ public:
GrDawnCaps(const GrContextOptions& contextOptions);
bool isFormatSRGB(const GrBackendFormat&) const override;
- SkImage::CompressionType compressionType(const GrBackendFormat&) const override;
bool isFormatRenderable(const GrBackendFormat& format,
int sampleCount = 1) const override;
@@ -36,9 +35,7 @@ public:
return {surfaceColorType, GrColorTypeBytesPerPixel(surfaceColorType)};
}
- SurfaceReadPixelsSupport surfaceSupportsReadPixels(const GrSurface*) const override {
- return SurfaceReadPixelsSupport::kSupported;
- }
+ SurfaceReadPixelsSupport surfaceSupportsReadPixels(const GrSurface*) const override;
size_t bytesPerPixel(const GrBackendFormat&) const override;
@@ -49,8 +46,6 @@ public:
GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override;
- GrSwizzle getReadSwizzle(const GrBackendFormat&, GrColorType) const override;
-
GrSwizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override;
uint64_t computeFormatKey(const GrBackendFormat&) const override;
@@ -62,9 +57,7 @@ public:
#endif
private:
- bool onSurfaceSupportsWritePixels(const GrSurface* surface) const override {
- return true;
- }
+ bool onSurfaceSupportsWritePixels(const GrSurface* surface) const override;
bool onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
const SkIRect& srcRect, const SkIPoint& dstPoint) const override {
return true;
@@ -79,6 +72,8 @@ private:
return { srcColorType, GrColorTypeBytesPerPixel(srcColorType) };
}
+ GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override;
+
typedef GrCaps INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.cpp b/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.cpp
index cc0f446134c..f35a2e7e630 100644
--- a/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.cpp
+++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.cpp
@@ -10,6 +10,7 @@
#include "include/gpu/GrBackendSemaphore.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrContextOptions.h"
+#include "src/gpu/GrDataUtils.h"
#include "src/gpu/GrGeometryProcessor.h"
#include "src/gpu/GrGpuResourceCacheAccess.h"
#include "src/gpu/GrPipeline.h"
@@ -92,7 +93,6 @@ static wgpu::AddressMode to_dawn_address_mode(GrSamplerState::WrapMode wrapMode)
}
SkASSERT(!"unsupported address mode");
return wgpu::AddressMode::ClampToEdge;
-
}
sk_sp<GrGpu> GrDawnGpu::Make(const wgpu::Device& device,
@@ -124,20 +124,22 @@ GrDawnGpu::~GrDawnGpu() {
}
}
-
void GrDawnGpu::disconnect(DisconnectType type) {
if (DisconnectType::kCleanup == type) {
while (!this->busyStagingBuffers().isEmpty()) {
fDevice.Tick();
}
}
+ fQueue = nullptr;
+ fDevice = nullptr;
INHERITED::disconnect(type);
}
///////////////////////////////////////////////////////////////////////////////
GrOpsRenderPass* GrDawnGpu::getOpsRenderPass(
- GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
+ GrRenderTarget* rt, GrStencilAttachment*,
+ GrSurfaceOrigin origin, const SkIRect& bounds,
const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
@@ -193,7 +195,10 @@ sk_sp<GrTexture> GrDawnGpu::onCreateTexture(SkISize dimensions,
GrProtected,
int mipLevelCount,
uint32_t levelClearMask) {
- SkASSERT(!levelClearMask);
+ if (levelClearMask) {
+ return nullptr;
+ }
+
wgpu::TextureFormat format;
if (!backendFormat.asDawnFormat(&format)) {
return nullptr;
@@ -353,7 +358,13 @@ bool GrDawnGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
pixels = data->pixmap(0).addr();
} else {
pixels = defaultStorage.get();
- memset(defaultStorage.get(), 0, baseLayerSize);
+ GrColorType colorType;
+ if (!GrDawnFormatToGrColorType(info.fFormat, &colorType)) {
+ return false;
+ }
+ SkISize size{backendTexture.width(), backendTexture.height()};
+ GrImageInfo imageInfo(colorType, kUnpremul_SkAlphaType, nullptr, size);
+ GrClearImage(imageInfo, defaultStorage.get(), bpp * backendTexture.width(), data->color());
}
wgpu::Device device = this->device();
wgpu::CommandEncoder copyEncoder = this->getCopyEncoder();
@@ -530,7 +541,6 @@ bool GrDawnGpu::onReadPixels(GrSurface* surface, int left, int top, int width, i
GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
size_t rowBytes) {
wgpu::Texture tex = get_dawn_texture_from_surface(surface);
- SkASSERT(tex);
if (!tex || 0 == rowBytes) {
return false;
@@ -638,7 +648,6 @@ std::unique_ptr<GrSemaphore> GrDawnGpu::prepareTextureForCrossContextUsage(GrTex
sk_sp<GrDawnProgram> GrDawnGpu::getOrCreateRenderPipeline(
GrRenderTarget* rt,
const GrProgramInfo& programInfo) {
-
GrProgramDesc desc = this->caps()->makeDesc(rt, programInfo);
if (!desc.isValid()) {
return nullptr;
diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.h b/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.h
index ac4f983bb62..fd09f9e5f56 100644
--- a/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.h
+++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnGpu.h
@@ -61,7 +61,8 @@ public:
int numStencilSamples) override;
GrOpsRenderPass* getOpsRenderPass(
- GrRenderTarget*, GrSurfaceOrigin, const SkIRect& bounds,
+ GrRenderTarget*, GrStencilAttachment*,
+ GrSurfaceOrigin, const SkIRect& bounds,
const GrOpsRenderPass::LoadAndStoreInfo&,
const GrOpsRenderPass::StencilLoadAndStoreInfo&,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override;
diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.cpp b/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.cpp
index 8c23a31d973..ba4c73e77ac 100644
--- a/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.cpp
+++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.cpp
@@ -7,7 +7,6 @@
#include "src/gpu/dawn/GrDawnOpsRenderPass.h"
-#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrPipeline.h"
#include "src/gpu/GrRenderTargetPriv.h"
@@ -94,12 +93,15 @@ void GrDawnOpsRenderPass::submit() {
fGpu->appendCommandBuffer(fEncoder.Finish());
}
-void GrDawnOpsRenderPass::onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
+void GrDawnOpsRenderPass::onClearStencilClip(const GrScissorState& scissor,
+ bool insideStencilMask) {
+ SkASSERT(!scissor.enabled());
fPassEncoder.EndPass();
fPassEncoder = beginRenderPass(wgpu::LoadOp::Load, wgpu::LoadOp::Clear);
}
-void GrDawnOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& color) {
+void GrDawnOpsRenderPass::onClear(const GrScissorState& scissor, const SkPMColor4f& color) {
+ SkASSERT(!scissor.enabled());
fPassEncoder.EndPass();
fPassEncoder = beginRenderPass(wgpu::LoadOp::Clear, wgpu::LoadOp::Load);
}
@@ -108,7 +110,8 @@ void GrDawnOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& co
void GrDawnOpsRenderPass::inlineUpload(GrOpFlushState* state,
GrDeferredTextureUploadFn& upload) {
- SkASSERT(!"unimplemented");
+ fGpu->submitToGpu(false);
+ state->doUpload(upload);
}
////////////////////////////////////////////////////////////////////////////////
@@ -144,20 +147,22 @@ bool GrDawnOpsRenderPass::onBindPipeline(const GrProgramInfo& programInfo,
}
void GrDawnOpsRenderPass::onSetScissorRect(const SkIRect& scissor) {
- SkIRect rect;
- SkIRect currentPipelineBounds =
- SkIRect::MakeWH(fRenderTarget->width(), fRenderTarget->height());
- if (!rect.intersect(currentPipelineBounds, scissor)) {
- rect = SkIRect::MakeEmpty();
- }
- fPassEncoder.SetScissorRect(rect.x(), rect.y(), rect.width(), rect.height());
+ // Higher-level GrRenderTargetContext and clips should have already ensured draw bounds are
+ // restricted to the render target. This is a sanity check.
+ SkASSERT(SkIRect::MakeSize(fRenderTarget->dimensions()).contains(scissor));
+ auto nativeScissorRect =
+ GrNativeRect::MakeRelativeTo(fOrigin, fRenderTarget->height(), scissor);
+ fPassEncoder.SetScissorRect(nativeScissorRect.fX, nativeScissorRect.fY,
+ nativeScissorRect.fWidth, nativeScissorRect.fHeight);
}
bool GrDawnOpsRenderPass::onBindTextures(const GrPrimitiveProcessor& primProc,
const GrSurfaceProxy* const primProcTextures[],
const GrPipeline& pipeline) {
auto bindGroup = fCurrentProgram->setTextures(fGpu, primProc, pipeline, primProcTextures);
- fPassEncoder.SetBindGroup(1, bindGroup, 0, nullptr);
+ if (bindGroup) {
+ fPassEncoder.SetBindGroup(1, bindGroup, 0, nullptr);
+ }
return true;
}
diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.h b/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.h
index 8ab0c771445..1f7b70f25ea 100644
--- a/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.h
+++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnOpsRenderPass.h
@@ -51,9 +51,9 @@ private:
void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance,
int baseVertex) override;
- void onClear(const GrFixedClip&, const SkPMColor4f& color) override;
+ void onClear(const GrScissorState& scissor, const SkPMColor4f& color) override;
- void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) override;
+ void onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) override;
struct InlineUploadInfo {
InlineUploadInfo(GrOpFlushState* state, const GrDeferredTextureUploadFn& upload)
diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.cpp b/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.cpp
index 95d85fb7501..1008eac3d0b 100644
--- a/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.cpp
+++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.cpp
@@ -325,29 +325,32 @@ sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu,
if (0 != uniformBufferSize) {
uniformLayoutEntries.push_back({ GrSPIRVUniformHandler::kUniformBinding,
wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment,
- wgpu::BindingType::UniformBuffer});
+ wgpu::BindingType::UniformBuffer });
}
wgpu::BindGroupLayoutDescriptor uniformBindGroupLayoutDesc;
uniformBindGroupLayoutDesc.entryCount = uniformLayoutEntries.size();
uniformBindGroupLayoutDesc.entries = uniformLayoutEntries.data();
- result->fBindGroupLayouts[0] =
- gpu->device().CreateBindGroupLayout(&uniformBindGroupLayoutDesc);
+ result->fBindGroupLayouts.push_back(
+ gpu->device().CreateBindGroupLayout(&uniformBindGroupLayoutDesc));
uint32_t binding = 0;
std::vector<wgpu::BindGroupLayoutEntry> textureLayoutEntries;
- for (int i = 0; i < builder.fUniformHandler.fSamplers.count(); ++i) {
- textureLayoutEntries.push_back({ binding++, wgpu::ShaderStage::Fragment,
- wgpu::BindingType::Sampler});
- textureLayoutEntries.push_back({ binding++, wgpu::ShaderStage::Fragment,
- wgpu::BindingType::SampledTexture});
+ int textureCount = builder.fUniformHandler.fSamplers.count();
+ if (textureCount > 0) {
+ for (int i = 0; i < textureCount; ++i) {
+ textureLayoutEntries.push_back({ binding++, wgpu::ShaderStage::Fragment,
+ wgpu::BindingType::Sampler });
+ textureLayoutEntries.push_back({ binding++, wgpu::ShaderStage::Fragment,
+ wgpu::BindingType::SampledTexture });
+ }
+ wgpu::BindGroupLayoutDescriptor textureBindGroupLayoutDesc;
+ textureBindGroupLayoutDesc.entryCount = textureLayoutEntries.size();
+ textureBindGroupLayoutDesc.entries = textureLayoutEntries.data();
+ result->fBindGroupLayouts.push_back(
+ gpu->device().CreateBindGroupLayout(&textureBindGroupLayoutDesc));
}
- wgpu::BindGroupLayoutDescriptor textureBindGroupLayoutDesc;
- textureBindGroupLayoutDesc.entryCount = textureLayoutEntries.size();
- textureBindGroupLayoutDesc.entries = textureLayoutEntries.data();
- result->fBindGroupLayouts[1] =
- gpu->device().CreateBindGroupLayout(&textureBindGroupLayoutDesc);
wgpu::PipelineLayoutDescriptor pipelineLayoutDesc;
- pipelineLayoutDesc.bindGroupLayoutCount = 2;
- pipelineLayoutDesc.bindGroupLayouts = &result->fBindGroupLayouts[0];
+ pipelineLayoutDesc.bindGroupLayoutCount = result->fBindGroupLayouts.size();
+ pipelineLayoutDesc.bindGroupLayouts = result->fBindGroupLayouts.data();
auto pipelineLayout = gpu->device().CreatePipelineLayout(&pipelineLayoutDesc);
result->fBuiltinUniformHandles = builder.fUniformHandles;
const GrPipeline& pipeline = programInfo.pipeline();
@@ -365,9 +368,9 @@ sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu,
std::vector<wgpu::VertexAttributeDescriptor> vertexAttributes;
const GrPrimitiveProcessor& primProc = programInfo.primProc();
+ int i = 0;
if (primProc.numVertexAttributes() > 0) {
size_t offset = 0;
- int i = 0;
for (const auto& attrib : primProc.vertexAttributes()) {
wgpu::VertexAttributeDescriptor attribute;
attribute.shaderLocation = i;
@@ -387,7 +390,6 @@ sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu,
std::vector<wgpu::VertexAttributeDescriptor> instanceAttributes;
if (primProc.numInstanceAttributes() > 0) {
size_t offset = 0;
- int i = 0;
for (const auto& attrib : primProc.instanceAttributes()) {
wgpu::VertexAttributeDescriptor attribute;
attribute.shaderLocation = i;
@@ -543,6 +545,9 @@ wgpu::BindGroup GrDawnProgram::setTextures(GrDawnGpu* gpu,
const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline,
const GrSurfaceProxy* const primProcTextures[]) {
+ if (fBindGroupLayouts.size() < 2) {
+ return nullptr;
+ }
std::vector<wgpu::BindGroupEntry> bindings;
int binding = 0;
if (primProcTextures) {
diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.h b/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.h
index b4f75d4e058..af707843b65 100644
--- a/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.h
+++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnProgramBuilder.h
@@ -57,7 +57,7 @@ struct GrDawnProgram : public SkRefCnt {
std::unique_ptr<GrGLSLXferProcessor> fXferProcessor;
std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fFragmentProcessors;
int fFragmentProcessorCnt;
- wgpu::BindGroupLayout fBindGroupLayouts[2];
+ std::vector<wgpu::BindGroupLayout> fBindGroupLayouts;
wgpu::RenderPipeline fRenderPipeline;
GrDawnProgramDataManager fDataManager;
RenderTargetState fRenderTargetState;
diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.cpp b/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.cpp
index 9f6daec00cc..91b155d8e76 100644
--- a/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.cpp
+++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.cpp
@@ -45,6 +45,22 @@ bool GrColorTypeToDawnFormat(GrColorType ct, wgpu::TextureFormat* format) {
}
}
+bool GrDawnFormatToGrColorType(wgpu::TextureFormat format, GrColorType* colorType) {
+ switch (format) {
+ case wgpu::TextureFormat::RGBA8Unorm:
+ *colorType = GrColorType::kRGBA_8888;
+ return true;
+ case wgpu::TextureFormat::BGRA8Unorm:
+ *colorType = GrColorType::kBGRA_8888;
+ return true;
+ case wgpu::TextureFormat::R8Unorm:
+ *colorType = GrColorType::kR_8;
+ return true;
+ default:
+ return false;
+ }
+}
+
size_t GrDawnRoundRowBytes(size_t rowBytes) {
// Dawn requires that rowBytes be a multiple of 256. (This is actually imposed by D3D12.)
return (rowBytes + 0xFF) & ~0xFF;
diff --git a/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.h b/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.h
index 7b5ac6c5715..6f090ffe4a1 100644
--- a/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.h
+++ b/chromium/third_party/skia/src/gpu/dawn/GrDawnUtil.h
@@ -14,6 +14,7 @@
size_t GrDawnBytesPerPixel(wgpu::TextureFormat format);
bool GrDawnFormatIsRenderable(wgpu::TextureFormat format);
bool GrColorTypeToDawnFormat(GrColorType colorType, wgpu::TextureFormat* format);
+bool GrDawnFormatToGrColorType(wgpu::TextureFormat format, GrColorType* colorType);
size_t GrDawnRoundRowBytes(size_t rowBytes);
#if GR_TEST_UTILS
const char* GrDawnFormatToStr(wgpu::TextureFormat format);
diff --git a/chromium/third_party/skia/src/gpu/effects/GrAARectEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrAARectEffect.fp
index 856b761a0f5..6a66a69d732 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrAARectEffect.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrAARectEffect.fp
@@ -5,12 +5,16 @@
* found in the LICENSE file.
*/
+in fragmentProcessor? inputFP;
layout(key) in GrClipEdgeType edgeType;
layout(ctype=SkRect) in float4 rect;
layout(ctype=SkRect) float4 prevRect = float4(-1);
uniform float4 rectUniform;
-@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag }
+@optimizationFlags {
+ (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag
+}
void main() {
half alpha;
@@ -37,7 +41,8 @@ void main() {
@if (edgeType == GrClipEdgeType::kInverseFillBW || edgeType == GrClipEdgeType::kInverseFillAA) {
alpha = 1.0 - alpha;
}
- sk_OutColor = sk_InColor * alpha;
+ half4 inputColor = sample(inputFP, sk_InColor);
+ sk_OutColor = inputColor * alpha;
}
@setData(pdman) {
@@ -59,7 +64,7 @@ void main() {
GrClipEdgeType edgeType = static_cast<GrClipEdgeType>(
d->fRandom->nextULessThan(kGrClipEdgeTypeCnt));
- fp = GrAARectEffect::Make(edgeType, rect);
+ fp = GrAARectEffect::Make(/*inputFP=*/nullptr, edgeType, rect);
} while (nullptr == fp);
return fp;
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrAlphaThresholdFragmentProcessor.fp b/chromium/third_party/skia/src/gpu/effects/GrAlphaThresholdFragmentProcessor.fp
index 4eb3a4eeeff..24aaf921c7e 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrAlphaThresholdFragmentProcessor.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrAlphaThresholdFragmentProcessor.fp
@@ -5,47 +5,19 @@
* found in the LICENSE file.
*/
-in uniform sampler2D mask;
+in fragmentProcessor? inputFP;
+in fragmentProcessor maskFP;
in uniform half innerThreshold;
in uniform half outerThreshold;
-@class {
- inline OptimizationFlags optFlags(float outerThreshold);
-}
-
-@constructorParams {
- const SkIRect& bounds
-}
-
-@make {
- static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView mask,
- float innerThreshold,
- float outerThreshold,
- const SkIRect& bounds) {
- return std::unique_ptr<GrFragmentProcessor>(new GrAlphaThresholdFragmentProcessor(
- std::move(mask), innerThreshold, outerThreshold, bounds));
- }
-}
-
-@coordTransform(mask) {
- SkMatrix::MakeTrans(SkIntToScalar(-bounds.x()), SkIntToScalar(-bounds.y()))
-}
-
-@cpp {
- inline GrFragmentProcessor::OptimizationFlags GrAlphaThresholdFragmentProcessor::optFlags(
- float outerThreshold) {
- if (outerThreshold >= 1.0) {
- return kPreservesOpaqueInput_OptimizationFlag |
- kCompatibleWithCoverageAsAlpha_OptimizationFlag;
- } else {
- return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
- }
- }
+@optimizationFlags {
+ (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
+ ((outerThreshold >= 1.0) ? kPreservesOpaqueInput_OptimizationFlag : kNone_OptimizationFlags)
}
void main() {
- half4 color = sk_InColor;
- half4 mask_color = sample(mask, sk_TransformedCoords2D[0]);
+ half4 color = sample(inputFP, sk_InColor);
+ half4 mask_color = sample(maskFP);
if (mask_color.a < 0.5) {
if (color.a > outerThreshold) {
half scale = outerThreshold / color.a;
@@ -61,18 +33,15 @@ void main() {
}
@test(testData) {
- auto [maskView, ct, at] = testData->randomAlphaOnlyView();
- // Make the inner and outer thresholds be in (0, 1) exclusive and be sorted correctly.
- float innerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f;
- float outerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f;
- const int kMaxWidth = 1000;
- const int kMaxHeight = 1000;
- uint32_t width = testData->fRandom->nextULessThan(kMaxWidth);
- uint32_t height = testData->fRandom->nextULessThan(kMaxHeight);
- uint32_t x = testData->fRandom->nextULessThan(kMaxWidth - width);
- uint32_t y = testData->fRandom->nextULessThan(kMaxHeight - height);
- SkIRect bounds = SkIRect::MakeXYWH(x, y, width, height);
+ // Make the inner and outer thresholds be in [0, 1].
+ float outerThresh = testData->fRandom->nextUScalar1();
+ float innerThresh = testData->fRandom->nextUScalar1();
+ std::unique_ptr<GrFragmentProcessor> inputChild, maskChild;
+ if (testData->fRandom->nextBool()) {
+ inputChild = GrProcessorUnitTest::MakeChildFP(testData);
+ }
+ maskChild = GrProcessorUnitTest::MakeChildFP(testData);
- return GrAlphaThresholdFragmentProcessor::Make(std::move(maskView), innerThresh, outerThresh,
- bounds);
+ return GrAlphaThresholdFragmentProcessor::Make(std::move(inputChild), std::move(maskChild),
+ innerThresh, outerThresh);
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.cpp
index 2fc715c70f2..e127ab4a0d3 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.cpp
@@ -28,12 +28,8 @@ public:
const CoordTransformRange& transformRange) override {
const GrConicEffect& ce = primProc.cast<GrConicEffect>();
- if (!ce.viewMatrix().isIdentity() &&
- !SkMatrixPriv::CheapEqual(fViewMatrix, ce.viewMatrix()))
- {
- fViewMatrix = ce.viewMatrix();
- pdman.setSkMatrix(fViewMatrixUniform, fViewMatrix);
- }
+ this->setTransform(pdman, fViewMatrixUniform, ce.viewMatrix(), &fViewMatrix);
+ this->setTransform(pdman, fLocalMatrixUniform, ce.localMatrix(), &fLocalMatrix);
if (ce.color() != fColor) {
pdman.set4fv(fColorUniform, 1, ce.color().vec());
@@ -44,26 +40,27 @@ public:
pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(ce.coverageScale()));
fCoverageScale = ce.coverageScale();
}
- this->setTransformDataHelper(ce.localMatrix(), pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
}
private:
SkMatrix fViewMatrix;
+ SkMatrix fLocalMatrix;
SkPMColor4f fColor;
uint8_t fCoverageScale;
- GrClipEdgeType fEdgeType;
UniformHandle fColorUniform;
UniformHandle fCoverageScaleUniform;
UniformHandle fViewMatrixUniform;
+ UniformHandle fLocalMatrixUniform;
typedef GrGLSLGeometryProcessor INHERITED;
};
GrGLConicEffect::GrGLConicEffect(const GrGeometryProcessor& processor)
- : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(SK_PMColor4fILLEGAL), fCoverageScale(0xff) {
- const GrConicEffect& ce = processor.cast<GrConicEffect>();
- fEdgeType = ce.getEdgeType();
-}
+ : fViewMatrix(SkMatrix::InvalidMatrix())
+ , fLocalMatrix(SkMatrix::InvalidMatrix())
+ , fColor(SK_PMColor4fILLEGAL)
+ , fCoverageScale(0xff) {}
void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
@@ -89,14 +86,10 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
gp.inPosition().name(),
gp.viewMatrix(),
&fViewMatrixUniform);
-
- // emit transforms with position
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- gp.inPosition().asShaderVar(),
- gp.localMatrix(),
- args.fFPCoordTransformHandler);
+ if (gp.usesLocalCoords()) {
+ this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, gp.inPosition().asShaderVar(),
+ gp.localMatrix(), &fLocalMatrixUniform);
+ }
// TODO: we should check on the number of bits float and half provide and use the smallest one
// that suffices. Additionally we should assert that the upstream code only lets us get here if
@@ -120,74 +113,31 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
fragBuilder->declAppend(gFM);
fragBuilder->declAppend(func);
- switch (fEdgeType) {
- case GrClipEdgeType::kHairlineAA: {
- fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
- fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
- fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
- dfdx.c_str(),
- v.fsIn(), dklmdx.c_str(),
- v.fsIn(), dklmdx.c_str(),
- v.fsIn(), dklmdx.c_str());
- fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
- dfdy.c_str(),
- v.fsIn(), dklmdy.c_str(),
- v.fsIn(), dklmdy.c_str(),
- v.fsIn(), dklmdy.c_str());
- fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(),
- dfdy.c_str());
- fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
- gFM.c_str(), gF.c_str(), gF.c_str());
- fragBuilder->codeAppendf("%s = %s.x*%s.x - %s.y*%s.z;",
- func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
- fragBuilder->codeAppendf("%s = abs(%s);", func.c_str(), func.c_str());
- fragBuilder->codeAppendf("%s = half(%s / %s);",
- edgeAlpha.c_str(), func.c_str(), gFM.c_str());
- fragBuilder->codeAppendf("%s = max(1.0 - %s, 0.0);",
- edgeAlpha.c_str(), edgeAlpha.c_str());
- // Add line below for smooth cubic ramp
- // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
- break;
- }
- case GrClipEdgeType::kFillAA: {
- fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
- fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
- fragBuilder->codeAppendf("%s ="
- "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
- dfdx.c_str(),
- v.fsIn(), dklmdx.c_str(),
- v.fsIn(), dklmdx.c_str(),
- v.fsIn(), dklmdx.c_str());
- fragBuilder->codeAppendf("%s ="
- "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
- dfdy.c_str(),
- v.fsIn(), dklmdy.c_str(),
- v.fsIn(), dklmdy.c_str(),
- v.fsIn(), dklmdy.c_str());
- fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(),
- dfdy.c_str());
- fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
- gFM.c_str(), gF.c_str(), gF.c_str());
- fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;",
- func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
- fragBuilder->codeAppendf("%s = half(%s / %s);",
- edgeAlpha.c_str(), func.c_str(), gFM.c_str());
- fragBuilder->codeAppendf("%s = saturate(0.5 - %s);",
- edgeAlpha.c_str(), edgeAlpha.c_str());
- // Add line below for smooth cubic ramp
- // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
- break;
- }
- case GrClipEdgeType::kFillBW: {
- fragBuilder->codeAppendf("%s = half(%s.x * %s.x - %s.y * %s.z);",
- edgeAlpha.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
- fragBuilder->codeAppendf("%s = half(%s < 0.0);",
- edgeAlpha.c_str(), edgeAlpha.c_str());
- break;
- }
- default:
- SK_ABORT("Shouldn't get here");
- }
+ fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
+ fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
+ fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
+ dfdx.c_str(),
+ v.fsIn(), dklmdx.c_str(),
+ v.fsIn(), dklmdx.c_str(),
+ v.fsIn(), dklmdx.c_str());
+ fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
+ dfdy.c_str(),
+ v.fsIn(), dklmdy.c_str(),
+ v.fsIn(), dklmdy.c_str(),
+ v.fsIn(), dklmdy.c_str());
+ fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(),
+ dfdy.c_str());
+ fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
+ gFM.c_str(), gF.c_str(), gF.c_str());
+ fragBuilder->codeAppendf("%s = %s.x*%s.x - %s.y*%s.z;",
+ func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
+ fragBuilder->codeAppendf("%s = abs(%s);", func.c_str(), func.c_str());
+ fragBuilder->codeAppendf("%s = half(%s / %s);",
+ edgeAlpha.c_str(), func.c_str(), gFM.c_str());
+ fragBuilder->codeAppendf("%s = max(1.0 - %s, 0.0);",
+ edgeAlpha.c_str(), edgeAlpha.c_str());
+ // Add line below for smooth cubic ramp
+ // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
// TODO should we really be doing this?
if (gp.coverageScale() != 0xff) {
@@ -210,8 +160,9 @@ void GrGLConicEffect::GenKey(const GrGeometryProcessor& gp,
const GrConicEffect& ce = gp.cast<GrConicEffect>();
uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
key |= 0xff != ce.coverageScale() ? 0x8 : 0x0;
- key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0;
- key |= ComputePosKey(ce.viewMatrix()) << 5;
+ key |= ce.usesLocalCoords() ? 0x10 : 0x0;
+ key = AddMatrixKeys(key, ce.viewMatrix(), ce.usesLocalCoords() ? ce.localMatrix()
+ : SkMatrix::I());
b->add32(key);
}
@@ -231,15 +182,13 @@ GrGLSLPrimitiveProcessor* GrConicEffect::createGLSLInstance(const GrShaderCaps&)
}
GrConicEffect::GrConicEffect(const SkPMColor4f& color, const SkMatrix& viewMatrix, uint8_t coverage,
- GrClipEdgeType edgeType, const SkMatrix& localMatrix,
- bool usesLocalCoords)
+ const SkMatrix& localMatrix, bool usesLocalCoords)
: INHERITED(kGrConicEffect_ClassID)
, fColor(color)
, fViewMatrix(viewMatrix)
, fLocalMatrix(viewMatrix)
, fUsesLocalCoords(usesLocalCoords)
- , fCoverageScale(coverage)
- , fEdgeType(edgeType) {
+ , fCoverageScale(coverage) {
this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes));
}
@@ -249,17 +198,10 @@ GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrConicEffect);
#if GR_TEST_UTILS
GrGeometryProcessor* GrConicEffect::TestCreate(GrProcessorTestData* d) {
- GrGeometryProcessor* gp;
- do {
- GrClipEdgeType edgeType =
- static_cast<GrClipEdgeType>(
- d->fRandom->nextULessThan(kGrClipEdgeTypeCnt));
- gp = GrConicEffect::Make(d->allocator(),
- SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)),
- GrTest::TestMatrix(d->fRandom), edgeType, *d->caps(),
- GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool());
- } while (nullptr == gp);
- return gp;
+ return GrConicEffect::Make(d->allocator(),
+ SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)),
+ GrTest::TestMatrix(d->fRandom), *d->caps(),
+ GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool());
}
#endif
@@ -281,12 +223,8 @@ public:
const CoordTransformRange& transformRange) override {
const GrQuadEffect& qe = primProc.cast<GrQuadEffect>();
- if (!qe.viewMatrix().isIdentity() &&
- !SkMatrixPriv::CheapEqual(fViewMatrix, qe.viewMatrix()))
- {
- fViewMatrix = qe.viewMatrix();
- pdman.setSkMatrix(fViewMatrixUniform, fViewMatrix);
- }
+ this->setTransform(pdman, fViewMatrixUniform, qe.viewMatrix(), &fViewMatrix);
+ this->setTransform(pdman, fLocalMatrixUniform, qe.localMatrix(), &fLocalMatrix);
if (qe.color() != fColor) {
pdman.set4fv(fColorUniform, 1, qe.color().vec());
@@ -297,26 +235,28 @@ public:
pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(qe.coverageScale()));
fCoverageScale = qe.coverageScale();
}
- this->setTransformDataHelper(qe.localMatrix(), pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
}
private:
SkMatrix fViewMatrix;
+ SkMatrix fLocalMatrix;
SkPMColor4f fColor;
uint8_t fCoverageScale;
- GrClipEdgeType fEdgeType;
+
UniformHandle fColorUniform;
UniformHandle fCoverageScaleUniform;
UniformHandle fViewMatrixUniform;
+ UniformHandle fLocalMatrixUniform;
typedef GrGLSLGeometryProcessor INHERITED;
};
GrGLQuadEffect::GrGLQuadEffect(const GrGeometryProcessor& processor)
- : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(SK_PMColor4fILLEGAL), fCoverageScale(0xff) {
- const GrQuadEffect& ce = processor.cast<GrQuadEffect>();
- fEdgeType = ce.getEdgeType();
-}
+ : fViewMatrix(SkMatrix::InvalidMatrix())
+ , fLocalMatrix(SkMatrix::InvalidMatrix())
+ , fColor(SK_PMColor4fILLEGAL)
+ , fCoverageScale(0xff) {}
void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
@@ -342,55 +282,24 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
gp.inPosition().name(),
gp.viewMatrix(),
&fViewMatrixUniform);
-
- // emit transforms with position
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- gp.inPosition().asShaderVar(),
- gp.localMatrix(),
- args.fFPCoordTransformHandler);
+ if (gp.usesLocalCoords()) {
+ this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, gp.inPosition().asShaderVar(),
+ gp.localMatrix(), &fLocalMatrixUniform);
+ }
fragBuilder->codeAppendf("half edgeAlpha;");
- switch (fEdgeType) {
- case GrClipEdgeType::kHairlineAA: {
- fragBuilder->codeAppendf("half2 duvdx = half2(dFdx(%s.xy));", v.fsIn());
- fragBuilder->codeAppendf("half2 duvdy = half2(dFdy(%s.xy));", v.fsIn());
- fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y,"
- " 2.0 * %s.x * duvdy.x - duvdy.y);",
- v.fsIn(), v.fsIn());
- fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);",
- v.fsIn(), v.fsIn(), v.fsIn());
- fragBuilder->codeAppend("edgeAlpha = sqrt(edgeAlpha * edgeAlpha / dot(gF, gF));");
- fragBuilder->codeAppend("edgeAlpha = max(1.0 - edgeAlpha, 0.0);");
- // Add line below for smooth cubic ramp
- // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
- break;
- }
- case GrClipEdgeType::kFillAA: {
- fragBuilder->codeAppendf("half2 duvdx = half2(dFdx(%s.xy));", v.fsIn());
- fragBuilder->codeAppendf("half2 duvdy = half2(dFdy(%s.xy));", v.fsIn());
- fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y,"
- " 2.0 * %s.x * duvdy.x - duvdy.y);",
- v.fsIn(), v.fsIn());
- fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);",
- v.fsIn(), v.fsIn(), v.fsIn());
- fragBuilder->codeAppend("edgeAlpha = edgeAlpha / sqrt(dot(gF, gF));");
- fragBuilder->codeAppend("edgeAlpha = saturate(0.5 - edgeAlpha);");
- // Add line below for smooth cubic ramp
- // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
- break;
- }
- case GrClipEdgeType::kFillBW: {
- fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);",
- v.fsIn(), v.fsIn(), v.fsIn());
- fragBuilder->codeAppend("edgeAlpha = half(edgeAlpha < 0.0);");
- break;
- }
- default:
- SK_ABORT("Shouldn't get here");
- }
+ fragBuilder->codeAppendf("half2 duvdx = half2(dFdx(%s.xy));", v.fsIn());
+ fragBuilder->codeAppendf("half2 duvdy = half2(dFdy(%s.xy));", v.fsIn());
+ fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y,"
+ " 2.0 * %s.x * duvdy.x - duvdy.y);",
+ v.fsIn(), v.fsIn());
+ fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);",
+ v.fsIn(), v.fsIn(), v.fsIn());
+ fragBuilder->codeAppend("edgeAlpha = sqrt(edgeAlpha * edgeAlpha / dot(gF, gF));");
+ fragBuilder->codeAppend("edgeAlpha = max(1.0 - edgeAlpha, 0.0);");
+ // Add line below for smooth cubic ramp
+ // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
if (0xff != gp.coverageScale()) {
const char* coverageScale;
@@ -412,8 +321,9 @@ void GrGLQuadEffect::GenKey(const GrGeometryProcessor& gp,
const GrQuadEffect& ce = gp.cast<GrQuadEffect>();
uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
key |= ce.coverageScale() != 0xff ? 0x8 : 0x0;
- key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0;
- key |= ComputePosKey(ce.viewMatrix()) << 5;
+ key |= ce.usesLocalCoords()? 0x10 : 0x0;
+ key = AddMatrixKeys(key, ce.viewMatrix(), ce.usesLocalCoords() ? ce.localMatrix()
+ : SkMatrix::I());
b->add32(key);
}
@@ -433,15 +343,13 @@ GrGLSLPrimitiveProcessor* GrQuadEffect::createGLSLInstance(const GrShaderCaps&)
}
GrQuadEffect::GrQuadEffect(const SkPMColor4f& color, const SkMatrix& viewMatrix, uint8_t coverage,
- GrClipEdgeType edgeType, const SkMatrix& localMatrix,
- bool usesLocalCoords)
+ const SkMatrix& localMatrix, bool usesLocalCoords)
: INHERITED(kGrQuadEffect_ClassID)
, fColor(color)
, fViewMatrix(viewMatrix)
, fLocalMatrix(localMatrix)
, fUsesLocalCoords(usesLocalCoords)
- , fCoverageScale(coverage)
- , fEdgeType(edgeType) {
+ , fCoverageScale(coverage) {
this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes));
}
@@ -451,15 +359,9 @@ GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrQuadEffect);
#if GR_TEST_UTILS
GrGeometryProcessor* GrQuadEffect::TestCreate(GrProcessorTestData* d) {
- GrGeometryProcessor* gp;
- do {
- GrClipEdgeType edgeType = static_cast<GrClipEdgeType>(
- d->fRandom->nextULessThan(kGrClipEdgeTypeCnt));
- gp = GrQuadEffect::Make(d->allocator(),
- SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)),
- GrTest::TestMatrix(d->fRandom), edgeType, *d->caps(),
- GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool());
- } while (nullptr == gp);
- return gp;
+ return GrQuadEffect::Make(d->allocator(),
+ SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)),
+ GrTest::TestMatrix(d->fRandom), *d->caps(),
+ GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool());
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.h b/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.h
index c59faebc5b3..87d3721a120 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.h
@@ -61,25 +61,15 @@ public:
static GrGeometryProcessor* Make(SkArenaAlloc* arena,
const SkPMColor4f& color,
const SkMatrix& viewMatrix,
- const GrClipEdgeType edgeType,
const GrCaps& caps,
const SkMatrix& localMatrix,
bool usesLocalCoords,
uint8_t coverage = 0xff) {
- switch (edgeType) {
- case GrClipEdgeType::kFillAA: // fall through
- case GrClipEdgeType::kHairlineAA:
- if (!caps.shaderCaps()->shaderDerivativeSupport()) {
- return nullptr;
- }
- break;
- case GrClipEdgeType::kFillBW:
- break;
- default: // kInverseFillBW or kInverseFillAA
- return nullptr;
+ if (!caps.shaderCaps()->shaderDerivativeSupport()) {
+ return nullptr;
}
- return arena->make<GrConicEffect>(color, viewMatrix, coverage, edgeType, localMatrix,
+ return arena->make<GrConicEffect>(color, viewMatrix, coverage, localMatrix,
usesLocalCoords);
}
@@ -89,9 +79,8 @@ public:
inline const Attribute& inPosition() const { return kAttributes[0]; }
inline const Attribute& inConicCoeffs() const { return kAttributes[1]; }
- inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
- inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
- inline GrClipEdgeType getEdgeType() const { return fEdgeType; }
+ inline bool isAntiAliased() const { return true; }
+ inline bool isFilled() const { return false; }
const SkPMColor4f& color() const { return fColor; }
const SkMatrix& viewMatrix() const { return fViewMatrix; }
const SkMatrix& localMatrix() const { return fLocalMatrix; }
@@ -105,7 +94,7 @@ public:
private:
friend class ::SkArenaAlloc; // for access to ctor
- GrConicEffect(const SkPMColor4f&, const SkMatrix& viewMatrix, uint8_t coverage, GrClipEdgeType,
+ GrConicEffect(const SkPMColor4f&, const SkMatrix& viewMatrix, uint8_t coverage,
const SkMatrix& localMatrix, bool usesLocalCoords);
SkPMColor4f fColor;
@@ -113,7 +102,6 @@ private:
SkMatrix fLocalMatrix;
bool fUsesLocalCoords;
uint8_t fCoverageScale;
- GrClipEdgeType fEdgeType;
static constexpr Attribute kAttributes[] = {
{"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType},
{"inConicCoeffs", kFloat4_GrVertexAttribType, kHalf4_GrSLType}
@@ -140,26 +128,15 @@ public:
static GrGeometryProcessor* Make(SkArenaAlloc* arena,
const SkPMColor4f& color,
const SkMatrix& viewMatrix,
- const GrClipEdgeType edgeType,
const GrCaps& caps,
const SkMatrix& localMatrix,
bool usesLocalCoords,
uint8_t coverage = 0xff) {
- switch (edgeType) {
- case GrClipEdgeType::kFillAA: // fall through
- case GrClipEdgeType::kHairlineAA:
- if (!caps.shaderCaps()->shaderDerivativeSupport()) {
- return nullptr;
- }
- break;
- case GrClipEdgeType::kFillBW:
- break;
- default: // kInverseFillBW and kInverseFillAA
- return nullptr;
+ if (!caps.shaderCaps()->shaderDerivativeSupport()) {
+ return nullptr;
}
- return arena->make<GrQuadEffect>(color, viewMatrix, coverage, edgeType,
- localMatrix, usesLocalCoords);
+ return arena->make<GrQuadEffect>(color, viewMatrix, coverage, localMatrix, usesLocalCoords);
}
~GrQuadEffect() override;
@@ -168,9 +145,8 @@ public:
inline const Attribute& inPosition() const { return kAttributes[0]; }
inline const Attribute& inHairQuadEdge() const { return kAttributes[1]; }
- inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
- inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
- inline GrClipEdgeType getEdgeType() const { return fEdgeType; }
+ inline bool isAntiAliased() const { return true; }
+ inline bool isFilled() const { return false; }
const SkPMColor4f& color() const { return fColor; }
const SkMatrix& viewMatrix() const { return fViewMatrix; }
const SkMatrix& localMatrix() const { return fLocalMatrix; }
@@ -184,7 +160,7 @@ public:
private:
friend class ::SkArenaAlloc; // for access to ctor
- GrQuadEffect(const SkPMColor4f&, const SkMatrix& viewMatrix, uint8_t coverage, GrClipEdgeType,
+ GrQuadEffect(const SkPMColor4f&, const SkMatrix& viewMatrix, uint8_t coverage,
const SkMatrix& localMatrix, bool usesLocalCoords);
SkPMColor4f fColor;
@@ -192,7 +168,6 @@ private:
SkMatrix fLocalMatrix;
bool fUsesLocalCoords;
uint8_t fCoverageScale;
- GrClipEdgeType fEdgeType;
static constexpr Attribute kAttributes[] = {
{"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType},
diff --git a/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.cpp
index ef9560e57e8..d575668ba49 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.cpp
@@ -176,9 +176,8 @@ GrBicubicEffect::GrBicubicEffect(std::unique_ptr<GrFragmentProcessor> fp,
, fCoordTransform(matrix)
, fDirection(direction)
, fClamp(clamp) {
- fp->setSampledWithExplicitCoords();
this->addCoordTransform(&fCoordTransform);
- this->registerChildProcessor(std::move(fp));
+ this->registerExplicitlySampledChild(std::move(fp));
}
GrBicubicEffect::GrBicubicEffect(const GrBicubicEffect& that)
@@ -187,9 +186,7 @@ GrBicubicEffect::GrBicubicEffect(const GrBicubicEffect& that)
, fDirection(that.fDirection)
, fClamp(that.fClamp) {
this->addCoordTransform(&fCoordTransform);
- auto child = that.childProcessor(0).clone();
- child->setSampledWithExplicitCoords();
- this->registerChildProcessor(std::move(child));
+ this->cloneAndRegisterAllChildProcessors(that);
}
void GrBicubicEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
diff --git a/chromium/third_party/skia/src/gpu/effects/GrBitmapTextGeoProc.cpp b/chromium/third_party/skia/src/gpu/effects/GrBitmapTextGeoProc.cpp
index 87612127b20..4a9f94e52cd 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrBitmapTextGeoProc.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrBitmapTextGeoProc.cpp
@@ -20,7 +20,10 @@
class GrGLBitmapTextGeoProc : public GrGLSLGeometryProcessor {
public:
- GrGLBitmapTextGeoProc() : fColor(SK_PMColor4fILLEGAL), fAtlasDimensions{0,0} {}
+ GrGLBitmapTextGeoProc()
+ : fColor(SK_PMColor4fILLEGAL)
+ , fAtlasDimensions{0,0}
+ , fLocalMatrix(SkMatrix::InvalidMatrix()) {}
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
const GrBitmapTextGeoProc& btgp = args.fGP.cast<GrBitmapTextGeoProc>();
@@ -53,14 +56,8 @@ public:
// Setup position
gpArgs->fPositionVar = btgp.inPosition().asShaderVar();
-
- // emit transforms
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- btgp.inPosition().asShaderVar(),
- btgp.localMatrix(),
- args.fFPCoordTransformHandler);
+ this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, btgp.inPosition().asShaderVar(),
+ btgp.localMatrix(), &fLocalMatrixUniform);
fragBuilder->codeAppend("half4 texColor;");
append_multitexture_lookup(args, btgp.numTextureSamplers(),
@@ -92,7 +89,9 @@ public:
1.0f / atlasDimensions.fHeight);
fAtlasDimensions = atlasDimensions;
}
- this->setTransformDataHelper(btgp.localMatrix(), pdman, transformRange);
+
+ this->setTransform(pdman, fLocalMatrixUniform, btgp.localMatrix(), &fLocalMatrix);
+ this->setTransformDataHelper(pdman, transformRange);
}
static inline void GenKey(const GrGeometryProcessor& proc,
@@ -102,6 +101,7 @@ public:
uint32_t key = 0;
key |= btgp.usesW() ? 0x1 : 0x0;
key |= btgp.maskFormat() << 1;
+ key |= ComputeMatrixKey(btgp.localMatrix()) << 2;
b->add32(key);
b->add32(btgp.numTextureSamplers());
}
@@ -113,6 +113,9 @@ private:
SkISize fAtlasDimensions;
UniformHandle fAtlasDimensionsInvUniform;
+ SkMatrix fLocalMatrix;
+ UniformHandle fLocalMatrixUniform;
+
typedef GrGLSLGeometryProcessor INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp b/chromium/third_party/skia/src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp
index 6126c7d5f6e..f5fde018544 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp
@@ -10,10 +10,12 @@ enum class Mode {
kSmoothStep = 1
};
+in fragmentProcessor? inputFP;
layout(key) in Mode mode;
void main() {
- half factor = 1.0 - sk_InColor.a;
+ half inputAlpha = sample(inputFP, sk_InColor).a;
+ half factor = 1.0 - inputAlpha;
@switch (mode) {
case Mode::kGaussian:
factor = half(exp(-factor * factor * 4.0) - 0.018);
diff --git a/chromium/third_party/skia/src/gpu/effects/GrCircleBlurFragmentProcessor.fp b/chromium/third_party/skia/src/gpu/effects/GrCircleBlurFragmentProcessor.fp
index 12eaeb6e24a..458431cefc0 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrCircleBlurFragmentProcessor.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrCircleBlurFragmentProcessor.fp
@@ -5,10 +5,15 @@
* found in the LICENSE file.
*/
+in fragmentProcessor? inputFP;
in half4 circleRect;
-in half textureRadius;
in half solidRadius;
-in uniform sampler2D blurProfileSampler;
+in half textureRadius;
+in fragmentProcessor blurProfile;
+
+@header {
+ #include "src/gpu/effects/GrTextureEffect.h"
+};
// The data is formatted as:
// x, y - the center of the circle
@@ -17,12 +22,14 @@ in uniform sampler2D blurProfileSampler;
uniform half4 circleData;
@optimizationFlags {
+ (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
kCompatibleWithCoverageAsAlpha_OptimizationFlag
}
@make {
- static std::unique_ptr<GrFragmentProcessor> Make(GrRecordingContext*,
- const SkRect& circle, float sigma);
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrRecordingContext*, const SkRect& circle,
+ float sigma);
}
@setData(data) {
@@ -188,13 +195,14 @@ uniform half4 circleData;
profile[profileWidth - 1] = 0;
}
- static GrSurfaceProxyView create_profile_texture(GrRecordingContext* context,
+ static std::unique_ptr<GrFragmentProcessor> create_profile_effect(GrRecordingContext* context,
const SkRect& circle,
float sigma,
- float* solidRadius, float* textureRadius) {
+ float* solidRadius,
+ float* textureRadius) {
float circleR = circle.width() / 2.0f;
if (circleR < SK_ScalarNearlyZero) {
- return {};
+ return nullptr;
}
// Profile textures are cached by the ratio of sigma to circle radius and by the size of the
// profile texture (binned by powers of 2).
@@ -224,6 +232,12 @@ uniform half4 circleData;
*textureRadius = circleR + 3 * sigma;
}
+ static constexpr int kProfileTextureWidth = 512;
+ // This would be kProfileTextureWidth/textureRadius if it weren't for the fact that we do
+ // the calculation of the profile coord in a coord space that has already been scaled by
+ // 1 / textureRadius. This is done to avoid overflow in length().
+ SkMatrix texM = SkMatrix::Scale(kProfileTextureWidth, 1.f);
+
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey key;
GrUniqueKey::Builder builder(&key, kDomain, 1, "1-D Circular Blur");
@@ -234,14 +248,14 @@ uniform half4 circleData;
if (sk_sp<GrTextureProxy> blurProfile = proxyProvider->findOrCreateProxyByUniqueKey(key)) {
GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(blurProfile->backendFormat(),
GrColorType::kAlpha_8);
- return {std::move(blurProfile), kTopLeft_GrSurfaceOrigin, swizzle};
+ GrSurfaceProxyView profileView{std::move(blurProfile), kTopLeft_GrSurfaceOrigin,
+ swizzle};
+ return GrTextureEffect::Make(std::move(profileView), kPremul_SkAlphaType, texM);
}
- static constexpr int kProfileTextureWidth = 512;
-
SkBitmap bm;
if (!bm.tryAllocPixels(SkImageInfo::MakeA8(kProfileTextureWidth, 1))) {
- return {};
+ return nullptr;
}
if (useHalfPlaneApprox) {
@@ -256,40 +270,42 @@ uniform half4 circleData;
bm.setImmutable();
GrBitmapTextureMaker maker(context, bm, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
- auto blurView = maker.view(GrMipMapped::kNo);
- if (!blurView) {
- return {};
+ auto profileView = maker.view(GrMipMapped::kNo);
+ if (!profileView) {
+ return nullptr;
}
- proxyProvider->assignUniqueKeyToProxy(key, blurView.asTextureProxy());
- return blurView;
+ proxyProvider->assignUniqueKeyToProxy(key, profileView.asTextureProxy());
+ return GrTextureEffect::Make(std::move(profileView), kPremul_SkAlphaType, texM);
}
std::unique_ptr<GrFragmentProcessor> GrCircleBlurFragmentProcessor::Make(
- GrRecordingContext* context, const SkRect& circle, float sigma) {
+ std::unique_ptr<GrFragmentProcessor> inputFP, GrRecordingContext* context,
+ const SkRect& circle, float sigma) {
float solidRadius;
float textureRadius;
- GrSurfaceProxyView profile = create_profile_texture(context, circle, sigma,
+ std::unique_ptr<GrFragmentProcessor> profile = create_profile_effect(context, circle, sigma,
&solidRadius, &textureRadius);
if (!profile) {
return nullptr;
}
return std::unique_ptr<GrFragmentProcessor>(new GrCircleBlurFragmentProcessor(
- circle, textureRadius, solidRadius, std::move(profile)));
+ std::move(inputFP), circle, solidRadius, textureRadius, std::move(profile)));
}
}
void main() {
// We just want to compute "(length(vec) - circleData.z + 0.5) * circleData.w" but need to
- // rearrange for precision.
- half2 vec = half2(half((sk_FragCoord.x - circleData.x) * circleData.w),
- half((sk_FragCoord.y - circleData.y) * circleData.w));
+ // rearrange to avoid passing large values to length() that would overflow.
+ half2 vec = half2((sk_FragCoord.xy - circleData.xy) * circleData.w);
half dist = length(vec) + (0.5 - circleData.z) * circleData.w;
- sk_OutColor = sk_InColor * sample(blurProfileSampler, half2(dist, 0.5)).a;
+ half4 inputColor = sample(inputFP, sk_InColor);
+ sk_OutColor = inputColor * sample(blurProfile, half2(dist, 0.5)).a;
}
@test(testData) {
SkScalar wh = testData->fRandom->nextRangeScalar(100.f, 1000.f);
- SkScalar sigma = testData->fRandom->nextRangeF(1.f,10.f);
+ SkScalar sigma = testData->fRandom->nextRangeF(1.f, 10.f);
SkRect circle = SkRect::MakeWH(wh, wh);
- return GrCircleBlurFragmentProcessor::Make(testData->context(), circle, sigma);
+ return GrCircleBlurFragmentProcessor::Make(/*inputFP=*/nullptr, testData->context(),
+ circle, sigma);
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrCircleEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrCircleEffect.fp
index ac06c7c47ba..00c6733a713 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrCircleEffect.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrCircleEffect.fp
@@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
+in fragmentProcessor? inputFP;
layout(key) in GrClipEdgeType edgeType;
in float2 center;
in float radius;
@@ -16,18 +17,22 @@ float prevRadius = -1;
uniform float4 circle;
@make {
- static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, SkPoint center,
- float radius) {
+ static GrFPResult Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType, SkPoint center, float radius) {
// A radius below half causes the implicit insetting done by this processor to become
// inverted. We could handle this case by making the processor code more complicated.
if (radius < .5f && GrProcessorEdgeTypeIsInverseFill(edgeType)) {
- return nullptr;
+ return GrFPFailure(std::move(inputFP));
}
- return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(edgeType, center, radius));
+ return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>(
+ new GrCircleEffect(std::move(inputFP), edgeType, center, radius)));
}
}
-@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag }
+@optimizationFlags {
+ (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag
+}
@setData(pdman) {
if (radius != prevRadius || center != prevCenter) {
@@ -57,12 +62,12 @@ void main() {
} else {
d = half((1.0 - length((circle.xy - sk_FragCoord.xy) * circle.w)) * circle.z);
}
+ half4 inputColor = sample(inputFP, sk_InColor);
@if (edgeType == GrClipEdgeType::kFillAA ||
- edgeType == GrClipEdgeType::kInverseFillAA ||
- edgeType == GrClipEdgeType::kHairlineAA) {
- sk_OutColor = sk_InColor * saturate(d);
+ edgeType == GrClipEdgeType::kInverseFillAA) {
+ sk_OutColor = inputColor * saturate(d);
} else {
- sk_OutColor = d > 0.5 ? sk_InColor : half4(0);
+ sk_OutColor = d > 0.5 ? inputColor : half4(0);
}
}
@@ -71,9 +76,11 @@ void main() {
center.fX = testData->fRandom->nextRangeScalar(0.f, 1000.f);
center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f);
SkScalar radius = testData->fRandom->nextRangeF(1.f, 1000.f);
- GrClipEdgeType et;
+ bool success;
+ std::unique_ptr<GrFragmentProcessor> fp;
do {
- et = (GrClipEdgeType) testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
- } while (GrClipEdgeType::kHairlineAA == et);
- return GrCircleEffect::Make(et, center, radius);
+ GrClipEdgeType et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
+ std::tie(success, fp) = GrCircleEffect::Make(/*inputFP=*/nullptr, et, center, radius);
+ } while (!success);
+ return fp;
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrClampFragmentProcessor.fp b/chromium/third_party/skia/src/gpu/effects/GrClampFragmentProcessor.fp
index f81fe08de7e..ed6771cbb5d 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrClampFragmentProcessor.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrClampFragmentProcessor.fp
@@ -5,24 +5,30 @@
* found in the LICENSE file.
*/
+in fragmentProcessor? inputFP;
layout(key) in bool clampToPremul;
@optimizationFlags {
- kConstantOutputForConstantInput_OptimizationFlag |
- kPreservesOpaqueInput_OptimizationFlag
+ (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
+ (kConstantOutputForConstantInput_OptimizationFlag |
+ kPreservesOpaqueInput_OptimizationFlag)
}
void main() {
+ half4 inputColor = sample(inputFP, sk_InColor);
@if (clampToPremul) {
- half alpha = saturate(sk_InColor.a);
- sk_OutColor = half4(clamp(sk_InColor.rgb, 0, alpha), alpha);
+ half alpha = saturate(inputColor.a);
+ sk_OutColor = half4(clamp(inputColor.rgb, 0, alpha), alpha);
} else {
- sk_OutColor = saturate(sk_InColor);
+ sk_OutColor = saturate(inputColor);
}
}
@class {
- SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
+ SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
+ SkPMColor4f input = this->numChildProcessors()
+ ? ConstantOutputForConstantInput(this->childProcessor(0), inColor)
+ : inColor;
float clampedAlpha = SkTPin(input.fA, 0.f, 1.f);
float clampVal = clampToPremul ? clampedAlpha : 1.f;
return {SkTPin(input.fR, 0.f, clampVal),
@@ -33,5 +39,5 @@ void main() {
}
@test(d) {
- return GrClampFragmentProcessor::Make(d->fRandom->nextBool());
+ return GrClampFragmentProcessor::Make(/*inputFP=*/nullptr, d->fRandom->nextBool());
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrColorMatrixFragmentProcessor.fp b/chromium/third_party/skia/src/gpu/effects/GrColorMatrixFragmentProcessor.fp
index ee73b89f035..5e07a148595 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrColorMatrixFragmentProcessor.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrColorMatrixFragmentProcessor.fp
@@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
+in fragmentProcessor? inputFP;
layout(ctype=SkM44, tracked) in uniform half4x4 m;
layout(ctype=SkV4, tracked) in uniform half4 v;
layout(key) in bool unpremulInput;
@@ -12,16 +13,14 @@ layout(key) in bool clampRGBOutput;
layout(key) in bool premulOutput;
@optimizationFlags {
+ (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
kConstantOutputForConstantInput_OptimizationFlag
}
void main() {
- half4 inputColor = sk_InColor;
+ half4 inputColor = sample(inputFP, sk_InColor);
@if (unpremulInput) {
- // The max() is to guard against 0 / 0 during unpremul when the incoming color is
- // transparent black.
- half nonZeroAlpha = max(inputColor.a, 0.0001);
- inputColor = half4(inputColor.rgb / nonZeroAlpha, inputColor.a);
+ inputColor = unpremul(inputColor);
}
sk_OutColor = m * inputColor + v;
@if (clampRGBOutput) {
@@ -35,7 +34,10 @@ void main() {
}
@class {
- SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
+ SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
+ SkPMColor4f input = this->numChildProcessors()
+ ? ConstantOutputForConstantInput(this->childProcessor(0), inColor)
+ : inColor;
SkColor4f color;
if (unpremulInput) {
color = input.unpremul();
@@ -62,7 +64,9 @@ void main() {
}
@make {
- static std::unique_ptr<GrFragmentProcessor> Make(const float matrix[20], bool unpremulInput, bool clampRGBOutput, bool premulOutput) {
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ const float matrix[20], bool unpremulInput,
+ bool clampRGBOutput, bool premulOutput) {
SkM44 m44(
matrix[ 0], matrix[ 1], matrix[ 2], matrix[ 3],
matrix[ 5], matrix[ 6], matrix[ 7], matrix[ 8],
@@ -70,7 +74,8 @@ void main() {
matrix[15], matrix[16], matrix[17], matrix[18]
);
SkV4 v4 = {matrix[4], matrix[9], matrix[14], matrix[19]};
- return std::unique_ptr<GrFragmentProcessor>(new GrColorMatrixFragmentProcessor(m44, v4, unpremulInput, clampRGBOutput, premulOutput));
+ return std::unique_ptr<GrFragmentProcessor>(new GrColorMatrixFragmentProcessor(
+ std::move(inputFP), m44, v4, unpremulInput, clampRGBOutput, premulOutput));
}
}
@@ -82,5 +87,5 @@ void main() {
bool unpremul = d->fRandom->nextBool();
bool clampRGB = d->fRandom->nextBool();
bool premul = d->fRandom->nextBool();
- return Make(m, unpremul, clampRGB, premul);
+ return Make(/*inputFP=*/nullptr, m, unpremul, clampRGB, premul);
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrConfigConversionEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrConfigConversionEffect.fp
index 6e08ad3daea..c66f283801b 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrConfigConversionEffect.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrConfigConversionEffect.fp
@@ -8,7 +8,6 @@
@header {
#include "include/gpu/GrContext.h"
#include "src/gpu/GrBitmapTextureMaker.h"
- #include "src/gpu/GrClip.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrImageInfo.h"
#include "src/gpu/GrRenderTargetContext.h"
@@ -84,8 +83,7 @@
paint1.addColorFragmentProcessor(pmToUPM->clone());
paint1.setPorterDuffXPFactory(SkBlendMode::kSrc);
- readRTC->fillRectToRect(GrNoClip(), std::move(paint1), GrAA::kNo, SkMatrix::I(), kRect,
- kRect);
+ readRTC->fillRectToRect(nullptr, std::move(paint1), GrAA::kNo, SkMatrix::I(), kRect, kRect);
if (!readRTC->readPixels(ii, firstRead, 0, {0, 0})) {
return false;
}
@@ -99,16 +97,14 @@
paint2.addColorFragmentProcessor(std::move(upmToPM));
paint2.setPorterDuffXPFactory(SkBlendMode::kSrc);
- tempRTC->fillRectToRect(GrNoClip(), std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect,
- kRect);
+ tempRTC->fillRectToRect(nullptr, std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect, kRect);
paint3.addColorFragmentProcessor(GrTextureEffect::Make(tempRTC->readSurfaceView(),
kPremul_SkAlphaType));
paint3.addColorFragmentProcessor(std::move(pmToUPM));
paint3.setPorterDuffXPFactory(SkBlendMode::kSrc);
- readRTC->fillRectToRect(GrNoClip(), std::move(paint3), GrAA::kNo, SkMatrix::I(), kRect,
- kRect);
+ readRTC->fillRectToRect(nullptr, std::move(paint3), GrAA::kNo, SkMatrix::I(), kRect, kRect);
if (!readRTC->readPixels(ii, secondRead, 0, {0, 0})) {
return false;
diff --git a/chromium/third_party/skia/src/gpu/effects/GrConstColorProcessor.fp b/chromium/third_party/skia/src/gpu/effects/GrConstColorProcessor.fp
index 18cc91a4b12..950705c4f0a 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrConstColorProcessor.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrConstColorProcessor.fp
@@ -13,51 +13,60 @@ enum class InputMode {
kLast = kModulateA
};
+in fragmentProcessor? inputFP;
layout(ctype=SkPMColor4f, tracked) in uniform half4 color;
layout(key) in InputMode mode;
@optimizationFlags {
- OptFlags(color, mode)
+ (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
+ (kConstantOutputForConstantInput_OptimizationFlag |
+ ((mode != InputMode::kIgnore) ? kCompatibleWithCoverageAsAlpha_OptimizationFlag
+ : kNone_OptimizationFlags) |
+ ((color.isOpaque()) ? kPreservesOpaqueInput_OptimizationFlag
+ : kNone_OptimizationFlags))
}
void main() {
@switch (mode) {
- case InputMode::kIgnore:
+ case InputMode::kIgnore: {
sk_OutColor = color;
break;
- case InputMode::kModulateRGBA:
- sk_OutColor = sk_InColor * color;
+ }
+ case InputMode::kModulateRGBA: {
+ half4 inputColor = sample(inputFP, sk_InColor);
+ sk_OutColor = inputColor * color;
break;
- case InputMode::kModulateA:
- sk_OutColor = sk_InColor.a * color;
+ }
+ case InputMode::kModulateA: {
+ half inputAlpha = sample(inputFP, sk_InColor).a;
+ sk_OutColor = inputAlpha * color;
break;
+ }
}
}
@class {
static const int kInputModeCnt = (int) InputMode::kLast + 1;
- static OptimizationFlags OptFlags(const SkPMColor4f& color, InputMode mode) {
- OptimizationFlags flags = kConstantOutputForConstantInput_OptimizationFlag;
- if (mode != InputMode::kIgnore) {
- flags |= kCompatibleWithCoverageAsAlpha_OptimizationFlag;
- }
- if (color.isOpaque()) {
- flags |= kPreservesOpaqueInput_OptimizationFlag;
- }
- return flags;
- }
-
- SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
+ SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
switch (mode) {
- case InputMode::kIgnore:
+ case InputMode::kIgnore: {
return color;
- case InputMode::kModulateA:
+ }
+ case InputMode::kModulateA: {
+ SkPMColor4f input = this->numChildProcessors()
+ ? ConstantOutputForConstantInput(this->childProcessor(inputFP_index), inColor)
+ : inColor;
return color * input.fA;
- case InputMode::kModulateRGBA:
+ }
+ case InputMode::kModulateRGBA: {
+ SkPMColor4f input = this->numChildProcessors()
+ ? ConstantOutputForConstantInput(this->childProcessor(inputFP_index), inColor)
+ : inColor;
return color * input;
+ }
}
- SK_ABORT("Unexpected mode");
+ SkUNREACHABLE;
}
}
@@ -82,5 +91,5 @@ void main() {
break;
}
InputMode mode = static_cast<InputMode>(d->fRandom->nextULessThan(kInputModeCnt));
- return GrConstColorProcessor::Make(color, mode);
+ return GrConstColorProcessor::Make(/*inputFP=*/nullptr, color, mode);
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.cpp
index 82de90ec6db..70f2fe443f2 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.cpp
@@ -66,7 +66,12 @@ void GrGLConvexPolyEffect::emitCode(EmitArgs& args) {
if (GrProcessorEdgeTypeIsInverseFill(cpe.getEdgeType())) {
fragBuilder->codeAppend("\talpha = 1.0 - alpha;\n");
}
- fragBuilder->codeAppendf("\t%s = %s * alpha;\n", args.fOutputColor, args.fInputColor);
+
+ SkString inputSample = cpe.hasInputFP()
+ ? this->invokeChild(/*childIndex=*/0, args.fInputColor, args)
+ : SkString(args.fInputColor);
+
+ fragBuilder->codeAppendf("\t%s = %s * alpha;\n", args.fOutputColor, inputSample.c_str());
}
void GrGLConvexPolyEffect::onSetData(const GrGLSLProgramDataManager& pdman,
@@ -89,14 +94,10 @@ void GrGLConvexPolyEffect::GenKey(const GrProcessor& processor, const GrShaderCa
//////////////////////////////////////////////////////////////////////////////
-std::unique_ptr<GrFragmentProcessor> GrConvexPolyEffect::Make(GrClipEdgeType type,
- const SkPath& path) {
- if (GrClipEdgeType::kHairlineAA == type) {
- return nullptr;
- }
- if (path.getSegmentMasks() != SkPath::kLine_SegmentMask ||
- !path.isConvex()) {
- return nullptr;
+GrFPResult GrConvexPolyEffect::Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType type, const SkPath& path) {
+ if (path.getSegmentMasks() != SkPath::kLine_SegmentMask || !path.isConvex()) {
+ return GrFPFailure(std::move(inputFP));
}
SkPathPriv::FirstDirection dir;
@@ -105,15 +106,17 @@ std::unique_ptr<GrFragmentProcessor> GrConvexPolyEffect::Make(GrClipEdgeType typ
// skip the draw or omit the clip element.
if (!SkPathPriv::CheapComputeFirstDirection(path, &dir)) {
if (GrProcessorEdgeTypeIsInverseFill(type)) {
- return GrConstColorProcessor::Make(SK_PMColor4fWHITE,
- GrConstColorProcessor::InputMode::kModulateRGBA);
+ return GrFPSuccess(
+ GrConstColorProcessor::Make(std::move(inputFP), SK_PMColor4fWHITE,
+ GrConstColorProcessor::InputMode::kModulateRGBA));
}
// This could use kIgnore instead of kModulateRGBA but it would trigger a debug print
// about a coverage processor not being compatible with the alpha-as-coverage optimization.
// We don't really care about this unlikely case so we just use kModulateRGBA to suppress
// the print.
- return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
- GrConstColorProcessor::InputMode::kModulateRGBA);
+ return GrFPSuccess(
+ GrConstColorProcessor::Make(std::move(inputFP), SK_PMColor4fTRANSPARENT,
+ GrConstColorProcessor::InputMode::kModulateRGBA));
}
SkScalar edges[3 * kMaxEdges];
@@ -130,11 +133,12 @@ std::unique_ptr<GrFragmentProcessor> GrConvexPolyEffect::Make(GrClipEdgeType typ
switch (verb) {
case SkPath::kMove_Verb:
SkASSERT(n == 0);
+ break;
case SkPath::kClose_Verb:
break;
case SkPath::kLine_Verb: {
if (n >= kMaxEdges) {
- return nullptr;
+ return GrFPFailure(std::move(inputFP));
}
if (pts[0] != pts[1]) {
SkVector v = pts[1] - pts[0];
@@ -152,22 +156,20 @@ std::unique_ptr<GrFragmentProcessor> GrConvexPolyEffect::Make(GrClipEdgeType typ
break;
}
default:
- return nullptr;
+ return GrFPFailure(std::move(inputFP));
}
}
if (path.isInverseFillType()) {
type = GrInvertProcessorEdgeType(type);
}
- return Make(type, n, edges);
+ return GrConvexPolyEffect::Make(std::move(inputFP), type, n, edges);
}
-std::unique_ptr<GrFragmentProcessor> GrConvexPolyEffect::Make(GrClipEdgeType edgeType,
- const SkRect& rect) {
- if (GrClipEdgeType::kHairlineAA == edgeType){
- return nullptr;
- }
- return GrAARectEffect::Make(edgeType, rect);
+GrFPResult GrConvexPolyEffect::Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType, const SkRect& rect) {
+ // TODO: Replace calls to this method with calling GrAARectEffect::Make directly
+ return GrFPSuccess(GrAARectEffect::Make(std::move(inputFP), edgeType, rect));
}
GrConvexPolyEffect::~GrConvexPolyEffect() {}
@@ -181,7 +183,8 @@ GrGLSLFragmentProcessor* GrConvexPolyEffect::onCreateGLSLInstance() const {
return new GrGLConvexPolyEffect;
}
-GrConvexPolyEffect::GrConvexPolyEffect(GrClipEdgeType edgeType, int n, const SkScalar edges[])
+GrConvexPolyEffect::GrConvexPolyEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType, int n, const SkScalar edges[])
: INHERITED(kGrConvexPolyEffect_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, fEdgeType(edgeType)
, fEdgeCount(n) {
@@ -193,12 +196,17 @@ GrConvexPolyEffect::GrConvexPolyEffect(GrClipEdgeType edgeType, int n, const SkS
for (int i = 0; i < n; ++i) {
fEdges[3 * i + 2] += SK_ScalarHalf;
}
+
+ if (inputFP != nullptr) {
+ this->registerChild(std::move(inputFP));
+ }
}
GrConvexPolyEffect::GrConvexPolyEffect(const GrConvexPolyEffect& that)
: INHERITED(kGrConvexPolyEffect_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, fEdgeType(that.fEdgeType)
, fEdgeCount(that.fEdgeCount) {
+ this->cloneAndRegisterAllChildProcessors(that);
memcpy(fEdges, that.fEdges, 3 * that.fEdgeCount * sizeof(SkScalar));
}
@@ -229,7 +237,11 @@ std::unique_ptr<GrFragmentProcessor> GrConvexPolyEffect::TestCreate(GrProcessorT
do {
GrClipEdgeType edgeType = static_cast<GrClipEdgeType>(
d->fRandom->nextULessThan(kGrClipEdgeTypeCnt));
- fp = GrConvexPolyEffect::Make(edgeType, count, edges);
+ auto [success, convexPolyFP] = GrConvexPolyEffect::Make(/*inputFP=*/nullptr, edgeType,
+ count, edges);
+ if (success) {
+ fp = std::move(convexPolyFP);
+ }
} while (nullptr == fp);
return fp;
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.h b/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.h
index 2bb33736f81..36fbc73f0e0 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.h
@@ -23,9 +23,7 @@ class SkPath;
*/
class GrConvexPolyEffect : public GrFragmentProcessor {
public:
- enum {
- kMaxEdges = 8,
- };
+ static constexpr int kMaxEdges = 8;
/**
* edges is a set of n edge equations where n is limited to kMaxEdges. It contains 3*n values.
@@ -38,24 +36,26 @@ public:
* have to modify the effect/shaderbuilder interface to make it possible (e.g. give access
* to the view matrix or untransformed positions in the fragment shader).
*/
- static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, int n,
- const SkScalar edges[]) {
- if (n <= 0 || n > kMaxEdges || GrClipEdgeType::kHairlineAA == edgeType) {
- return nullptr;
+ static GrFPResult Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType, int n, const SkScalar edges[]) {
+ if (n <= 0 || n > kMaxEdges) {
+ return GrFPFailure(std::move(inputFP));
}
- return std::unique_ptr<GrFragmentProcessor>(new GrConvexPolyEffect(edgeType, n, edges));
+
+ return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>(
+ new GrConvexPolyEffect(std::move(inputFP), edgeType, n, edges)));
}
/**
* Creates an effect that clips against the path. If the path is not a convex polygon, is
- * inverse filled, or has too many edges, this will return nullptr.
+ * inverse filled, or has too many edges, creation will fail.
*/
- static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkPath&);
+ static GrFPResult Make(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType, const SkPath&);
/**
* Creates an effect that fills inside the rect with AA edges..
*/
- static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRect&);
+ static GrFPResult Make(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType, const SkRect&);
~GrConvexPolyEffect() override;
@@ -69,8 +69,12 @@ public:
const SkScalar* getEdges() const { return fEdges; }
+ bool hasInputFP() const { return numChildProcessors() > 0; }
+
private:
- GrConvexPolyEffect(GrClipEdgeType edgeType, int n, const SkScalar edges[]);
+ GrConvexPolyEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType,
+ int n, const SkScalar edges[]);
GrConvexPolyEffect(const GrConvexPolyEffect&);
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
diff --git a/chromium/third_party/skia/src/gpu/effects/GrDeviceSpaceEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrDeviceSpaceEffect.fp
index 879c7c4d7c3..8dfb2c4dbda 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrDeviceSpaceEffect.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrDeviceSpaceEffect.fp
@@ -7,8 +7,18 @@
in fragmentProcessor fp;
+in uniform float3x3 matrix;
+
void main() {
- sk_OutColor = sample(fp, sk_InColor, sk_FragCoord.xy);
+ float3 p = matrix * (sk_FragCoord.xy1);
+ sk_OutColor = sample(fp, sk_InColor, p.xy / p.z);
+}
+
+@make{
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp,
+ const SkMatrix& matrix = SkMatrix::I()) {
+ return std::unique_ptr<GrFragmentProcessor>(new GrDeviceSpaceEffect(std::move(fp), matrix));
+ }
}
@test(d) {
diff --git a/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldGeoProc.cpp
index 3bf74e11fba..19c75f332f3 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldGeoProc.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldGeoProc.cpp
@@ -57,14 +57,8 @@ public:
// Setup position
gpArgs->fPositionVar = dfTexEffect.inPosition().asShaderVar();
-
- // emit transforms
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- dfTexEffect.inPosition().asShaderVar(),
- dfTexEffect.localMatrix(),
- args.fFPCoordTransformHandler);
+ this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, gpArgs->fPositionVar,
+ dfTexEffect.localMatrix(), &fLocalMatrixUniform);
// add varyings
GrGLSLVarying uv(kFloat2_GrSLType);
@@ -185,7 +179,8 @@ public:
1.0f / atlasDimensions.fHeight);
fAtlasDimensions = atlasDimensions;
}
- this->setTransformDataHelper(dfa8gp.localMatrix(), pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
+ this->setTransform(pdman, fLocalMatrixUniform, dfa8gp.localMatrix(), &fLocalMatrix);
}
static inline void GenKey(const GrGeometryProcessor& gp,
@@ -193,6 +188,7 @@ public:
GrProcessorKeyBuilder* b) {
const GrDistanceFieldA8TextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldA8TextGeoProc>();
uint32_t key = dfTexEffect.getFlags();
+ key |= ComputeMatrixKey(dfTexEffect.localMatrix()) << 16;
b->add32(key);
b->add32(dfTexEffect.numTextureSamplers());
}
@@ -202,9 +198,12 @@ private:
float fDistanceAdjust = -1.f;
UniformHandle fDistanceAdjustUni;
#endif
- SkISize fAtlasDimensions = {0, 0};
+ SkISize fAtlasDimensions = {0, 0};
UniformHandle fAtlasDimensionsInvUniform;
+ SkMatrix fLocalMatrix = SkMatrix::InvalidMatrix();
+ UniformHandle fLocalMatrixUniform;
+
typedef GrGLSLGeometryProcessor INHERITED;
};
@@ -354,31 +353,20 @@ public:
varyingHandler->addPassThroughAttribute(dfPathEffect.inColor(), args.fOutputColor);
if (dfPathEffect.matrix().hasPerspective()) {
- // Setup position
+ // Setup position (output position is transformed, local coords are pass through)
this->writeOutputPosition(vertBuilder,
uniformHandler,
gpArgs,
dfPathEffect.inPosition().name(),
dfPathEffect.matrix(),
&fMatrixUniform);
-
- // emit transforms
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- dfPathEffect.inPosition().asShaderVar(),
- args.fFPCoordTransformHandler);
+ gpArgs->fLocalCoordVar = dfPathEffect.inPosition().asShaderVar();
} else {
- // Setup position
+ // Setup position (output position is pass through, local coords are transformed)
this->writeOutputPosition(vertBuilder, gpArgs, dfPathEffect.inPosition().name());
-
- // emit transforms
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- dfPathEffect.inPosition().asShaderVar(),
- dfPathEffect.matrix(),
- args.fFPCoordTransformHandler);
+ this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
+ dfPathEffect.inPosition().asShaderVar(), dfPathEffect.matrix(),
+ &fMatrixUniform);
}
// Use highp to work around aliasing issues
@@ -463,10 +451,9 @@ public:
const CoordTransformRange& transformRange) override {
const GrDistanceFieldPathGeoProc& dfpgp = proc.cast<GrDistanceFieldPathGeoProc>();
- if (dfpgp.matrix().hasPerspective() && !SkMatrixPriv::CheapEqual(fMatrix, dfpgp.matrix())) {
- fMatrix = dfpgp.matrix();
- pdman.setSkMatrix(fMatrixUniform, fMatrix);
- }
+ // We always set the matrix uniform; it's either used to transform from local to device
+ // for the output position, or from device to local for the local coord variable.
+ this->setTransform(pdman, fMatrixUniform, dfpgp.matrix(), &fMatrix);
const SkISize& atlasDimensions = dfpgp.atlasDimensions();
SkASSERT(SkIsPow2(atlasDimensions.fWidth) && SkIsPow2(atlasDimensions.fHeight));
@@ -477,11 +464,7 @@ public:
fAtlasDimensions = atlasDimensions;
}
- if (dfpgp.matrix().hasPerspective()) {
- this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
- } else {
- this->setTransformDataHelper(dfpgp.matrix(), pdman, transformRange);
- }
+ this->setTransformDataHelper(pdman, transformRange);
}
static inline void GenKey(const GrGeometryProcessor& gp,
@@ -490,7 +473,7 @@ public:
const GrDistanceFieldPathGeoProc& dfTexEffect = gp.cast<GrDistanceFieldPathGeoProc>();
uint32_t key = dfTexEffect.getFlags();
- key |= ComputePosKey(dfTexEffect.matrix()) << 16;
+ key |= ComputeMatrixKey(dfTexEffect.matrix()) << 16;
b->add32(key);
b->add32(dfTexEffect.matrix().hasPerspective());
b->add32(dfTexEffect.numTextureSamplers());
@@ -605,7 +588,9 @@ GrGeometryProcessor* GrDistanceFieldPathGeoProc::TestCreate(GrProcessorTestData*
class GrGLDistanceFieldLCDTextGeoProc : public GrGLSLGeometryProcessor {
public:
- GrGLDistanceFieldLCDTextGeoProc() : fAtlasDimensions({0, 0}) {
+ GrGLDistanceFieldLCDTextGeoProc()
+ : fAtlasDimensions({0, 0})
+ , fLocalMatrix(SkMatrix::InvalidMatrix()) {
fDistanceAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(1.0f, 1.0f, 1.0f);
}
@@ -634,14 +619,9 @@ public:
// Setup position
gpArgs->fPositionVar = dfTexEffect.inPosition().asShaderVar();
-
- // emit transforms
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- dfTexEffect.inPosition().asShaderVar(),
- dfTexEffect.localMatrix(),
- args.fFPCoordTransformHandler);
+ this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
+ dfTexEffect.inPosition().asShaderVar(), dfTexEffect.localMatrix(),
+ &fLocalMatrixUniform);
// set up varyings
GrGLSLVarying uv(kFloat2_GrSLType);
@@ -801,7 +781,8 @@ public:
1.0f / atlasDimensions.fHeight);
fAtlasDimensions = atlasDimensions;
}
- this->setTransformDataHelper(dflcd.localMatrix(), pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
+ this->setTransform(pdman, fLocalMatrixUniform, dflcd.localMatrix(), &fLocalMatrix);
}
static inline void GenKey(const GrGeometryProcessor& gp,
@@ -809,7 +790,8 @@ public:
GrProcessorKeyBuilder* b) {
const GrDistanceFieldLCDTextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldLCDTextGeoProc>();
- uint32_t key = dfTexEffect.getFlags();
+ uint32_t key = (dfTexEffect.getFlags() << 16) |
+ ComputeMatrixKey(dfTexEffect.localMatrix());
b->add32(key);
b->add32(dfTexEffect.numTextureSamplers());
}
@@ -821,6 +803,9 @@ private:
SkISize fAtlasDimensions;
UniformHandle fAtlasDimensionsInvUniform;
+ SkMatrix fLocalMatrix;
+ UniformHandle fLocalMatrixUniform;
+
typedef GrGLSLGeometryProcessor INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/effects/GrEllipseEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrEllipseEffect.fp
index 8e8c766d0f2..918dcbece1d 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrEllipseEffect.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrEllipseEffect.fp
@@ -9,6 +9,7 @@
#include "src/gpu/GrShaderCaps.h"
}
+in fragmentProcessor? inputFP;
layout(key) in GrClipEdgeType edgeType;
in float2 center;
in float2 radii;
@@ -23,25 +24,29 @@ bool medPrecision = !sk_Caps.floatIs32Bits;
layout(when=medPrecision) uniform float2 scale;
@make {
- static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, SkPoint center,
- SkPoint radii, const GrShaderCaps& caps) {
+ static GrFPResult Make(std::unique_ptr<GrFragmentProcessor> inputFP, GrClipEdgeType edgeType,
+ SkPoint center, SkPoint radii, const GrShaderCaps& caps) {
// Small radii produce bad results on devices without full float.
if (!caps.floatIs32Bits() && (radii.fX < 0.5f || radii.fY < 0.5f)) {
- return nullptr;
+ return GrFPFailure(std::move(inputFP));
}
// Very narrow ellipses produce bad results on devices without full float
if (!caps.floatIs32Bits() && (radii.fX > 255*radii.fY || radii.fY > 255*radii.fX)) {
- return nullptr;
+ return GrFPFailure(std::move(inputFP));
}
// Very large ellipses produce bad results on devices without full float
if (!caps.floatIs32Bits() && (radii.fX > 16384 || radii.fY > 16384)) {
- return nullptr;
+ return GrFPFailure(std::move(inputFP));
}
- return std::unique_ptr<GrFragmentProcessor>(new GrEllipseEffect(edgeType, center, radii));
+ return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>(
+ new GrEllipseEffect(std::move(inputFP), edgeType, center, radii)));
}
}
-@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag }
+@optimizationFlags {
+ (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag
+}
@setData(pdman) {
if (radii != prevRadii || center != prevCenter) {
@@ -114,7 +119,8 @@ void main() {
// hairline not supported
discard;
}
- sk_OutColor = sk_InColor * alpha;
+ half4 inputColor = sample(inputFP, sk_InColor);
+ sk_OutColor = inputColor * alpha;
}
@test(testData) {
@@ -123,10 +129,13 @@ void main() {
center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f);
SkScalar rx = testData->fRandom->nextRangeF(0.f, 1000.f);
SkScalar ry = testData->fRandom->nextRangeF(0.f, 1000.f);
- GrClipEdgeType et;
+ bool success;
+ std::unique_ptr<GrFragmentProcessor> fp;
do {
- et = (GrClipEdgeType) testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
- } while (GrClipEdgeType::kHairlineAA == et);
- return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry),
- *testData->caps()->shaderCaps());
+ GrClipEdgeType et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
+ std::tie(success, fp) = GrEllipseEffect::Make(/*inputFP=*/nullptr, et, center,
+ SkPoint::Make(rx, ry),
+ *testData->caps()->shaderCaps());
+ } while (!success);
+ return fp;
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
index da7d950609a..3c8db3455a8 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
@@ -140,29 +140,23 @@ std::unique_ptr<GrFragmentProcessor> GrGaussianConvolutionFragmentProcessor::Mak
int halfWidth,
float gaussianSigma,
GrSamplerState::WrapMode wm,
- const int bounds[2],
+ const SkIRect& subset,
+ const SkIRect* pixelDomain,
const GrCaps& caps) {
std::unique_ptr<GrFragmentProcessor> child;
- GrSamplerState sampler;
- switch (dir) {
- case Direction::kX: sampler.setWrapModeX(wm); break;
- case Direction::kY: sampler.setWrapModeY(wm); break;
- }
- if (bounds) {
- SkASSERT(bounds[0] < bounds[1]);
- SkRect subset;
+ GrSamplerState sampler(wm, GrSamplerState::Filter::kNearest);
+ if (pixelDomain) {
+ // Inset because we expect to be invoked at pixel centers.
+ SkRect domain = SkRect::Make(*pixelDomain).makeInset(0.5, 0.5f);
switch (dir) {
- case Direction::kX:
- subset = SkRect::MakeLTRB(bounds[0], 0, bounds[1], view.height());
- break;
- case Direction::kY:
- subset = SkRect::MakeLTRB(0, bounds[0], view.width(), bounds[1]);
- break;
+ case Direction::kX: domain.outset(halfWidth, 0); break;
+ case Direction::kY: domain.outset(0, halfWidth); break;
}
child = GrTextureEffect::MakeSubset(std::move(view), alphaType, SkMatrix::I(), sampler,
- subset, caps);
+ SkRect::Make(subset), domain, caps);
} else {
- child = GrTextureEffect::Make(std::move(view), alphaType, SkMatrix::I(), sampler, caps);
+ child = GrTextureEffect::MakeSubset(std::move(view), alphaType, SkMatrix::I(), sampler,
+ SkRect::Make(subset), caps);
}
return std::unique_ptr<GrFragmentProcessor>(new GrGaussianConvolutionFragmentProcessor(
std::move(child), dir, halfWidth, gaussianSigma));
@@ -177,8 +171,7 @@ GrGaussianConvolutionFragmentProcessor::GrGaussianConvolutionFragmentProcessor(
ProcessorOptimizationFlags(child.get()))
, fRadius(radius)
, fDirection(direction) {
- child->setSampledWithExplicitCoords();
- this->registerChildProcessor(std::move(child));
+ this->registerExplicitlySampledChild(std::move(child));
SkASSERT(radius <= kMaxKernelRadius);
fill_in_1D_gaussian_kernel(fKernel, gaussianSigma, fRadius);
this->addCoordTransform(&fCoordTransform);
@@ -189,9 +182,7 @@ GrGaussianConvolutionFragmentProcessor::GrGaussianConvolutionFragmentProcessor(
: INHERITED(kGrGaussianConvolutionFragmentProcessor_ClassID, that.optimizationFlags())
, fRadius(that.fRadius)
, fDirection(that.fDirection) {
- auto child = that.childProcessor(0).clone();
- child->setSampledWithExplicitCoords();
- this->registerChildProcessor(std::move(child));
+ this->cloneAndRegisterAllChildProcessors(that);
memcpy(fKernel, that.fKernel, radius_to_width(fRadius) * sizeof(float));
this->addCoordTransform(&fCoordTransform);
}
@@ -220,27 +211,33 @@ std::unique_ptr<GrFragmentProcessor> GrGaussianConvolutionFragmentProcessor::Tes
GrProcessorTestData* d) {
auto [view, ct, at] = d->randomView();
- Direction dir;
- int bounds[2];
- do {
- if (d->fRandom->nextBool()) {
- dir = Direction::kX;
- bounds[0] = d->fRandom->nextRangeU(0, view.width() - 1);
- bounds[1] = d->fRandom->nextRangeU(0, view.width() - 1);
- } else {
- dir = Direction::kY;
- bounds[0] = d->fRandom->nextRangeU(0, view.height() - 1);
- bounds[1] = d->fRandom->nextRangeU(0, view.height() - 1);
- }
- } while (bounds[0] == bounds[1]);
- std::sort(bounds, bounds + 2);
+ Direction dir = d->fRandom->nextBool() ? Direction::kY : Direction::kX;
+ SkIRect subset{
+ static_cast<int>(d->fRandom->nextRangeU(0, view.width() - 1)),
+ static_cast<int>(d->fRandom->nextRangeU(0, view.height() - 1)),
+ static_cast<int>(d->fRandom->nextRangeU(0, view.width() - 1)),
+ static_cast<int>(d->fRandom->nextRangeU(0, view.height() - 1)),
+ };
+ subset.sort();
auto wm = static_cast<GrSamplerState::WrapMode>(
d->fRandom->nextULessThan(GrSamplerState::kWrapModeCount));
int radius = d->fRandom->nextRangeU(1, kMaxKernelRadius);
float sigma = radius / 3.f;
+ SkIRect temp;
+ SkIRect* domain = nullptr;
+ if (d->fRandom->nextBool()) {
+ temp = {
+ static_cast<int>(d->fRandom->nextRangeU(0, view.width() - 1)),
+ static_cast<int>(d->fRandom->nextRangeU(0, view.height() - 1)),
+ static_cast<int>(d->fRandom->nextRangeU(0, view.width() - 1)),
+ static_cast<int>(d->fRandom->nextRangeU(0, view.height() - 1)),
+ };
+ temp.sort();
+ domain = &temp;
+ }
return GrGaussianConvolutionFragmentProcessor::Make(std::move(view), at, dir, radius, sigma, wm,
- bounds, *d->caps());
+ subset, domain, *d->caps());
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h
index 70fa89bbdae..61f6e4e3231 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h
+++ b/chromium/third_party/skia/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h
@@ -22,17 +22,22 @@ public:
/**
* Convolve with a Gaussian kernel. Bounds limits the coords sampled by the effect along the
- * axis indicated by Direction. The WrapMode is applied to the bounds interval. If bounds is
- * nullptr then the full proxy width/height is used.
+ * axis indicated by Direction. The WrapMode is applied to the subset. If present, the
+ * pixelDomain indicates the domain of pixels that this effect will be called with. It should
+ * not account for outsetting due to the filter radius, this effect will handle that. It is
+ * assumed that the effect is only invoked at pixel centers within the pixelDomain, the
+ * effect will optimize for that, and may produce incorrect results if it is not the case. If
+ * pixelDomain is null then the effect will work correctly with any sample coordinates.
*/
- static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView view,
- SkAlphaType alphaType,
- Direction dir,
+ static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView,
+ SkAlphaType,
+ Direction,
int halfWidth,
float gaussianSigma,
GrSamplerState::WrapMode,
- const int bounds[2],
- const GrCaps& caps);
+ const SkIRect& subset,
+ const SkIRect* pixelDomain,
+ const GrCaps&);
const char* name() const override { return "GaussianConvolution"; }
diff --git a/chromium/third_party/skia/src/gpu/effects/GrHSLToRGBFilterEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrHSLToRGBFilterEffect.fp
index 02125f8e709..029f7b2adf7 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrHSLToRGBFilterEffect.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrHSLToRGBFilterEffect.fp
@@ -13,19 +13,23 @@
// [2] http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
// [3] http://www.chilliant.com/rgb2hsv.html
+in fragmentProcessor? inputFP;
+
void main() {
- half3 hsl = sk_InColor.rgb;
+ half4 inputColor = sample(inputFP, sk_InColor);
+ half3 hsl = inputColor.rgb;
half C = (1 - abs(2 * hsl.z - 1)) * hsl.y;
half3 p = hsl.xxx + half3(0, 2/3.0, 1/3.0);
half3 q = saturate(abs(fract(p) * 6 - 3) - 1);
half3 rgb = (q - 0.5) * C + hsl.z;
- sk_OutColor = saturate(half4(rgb, sk_InColor.a));
+ sk_OutColor = saturate(half4(rgb, inputColor.a));
sk_OutColor.rgb *= sk_OutColor.a;
}
@optimizationFlags {
+ (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
(kConstantOutputForConstantInput_OptimizationFlag | kPreservesOpaqueInput_OptimizationFlag)
}
@@ -33,7 +37,10 @@ void main() {
#include "include/private/SkColorData.h"
#include "include/private/SkNx.h"
- SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& c) const override {
+ SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
+ SkPMColor4f c = this->numChildProcessors()
+ ? ConstantOutputForConstantInput(this->childProcessor(0), inColor)
+ : inColor;
const auto H = c[0],
S = c[1],
L = c[2],
diff --git a/chromium/third_party/skia/src/gpu/effects/GrLumaColorFilterEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrLumaColorFilterEffect.fp
index 1548b26e0bf..67188459df8 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrLumaColorFilterEffect.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrLumaColorFilterEffect.fp
@@ -5,14 +5,20 @@
* found in the LICENSE file.
*/
+in fragmentProcessor? inputFP;
+
@optimizationFlags {
- kConstantOutputForConstantInput_OptimizationFlag
+ (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
+ kConstantOutputForConstantInput_OptimizationFlag
}
@class {
#include "include/private/SkColorData.h"
- SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
+ SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
+ SkPMColor4f input = this->numChildProcessors()
+ ? ConstantOutputForConstantInput(this->childProcessor(inputFP_index), inColor)
+ : inColor;
float luma = SK_ITU_BT709_LUM_COEFF_R * input.fR +
SK_ITU_BT709_LUM_COEFF_G * input.fG +
SK_ITU_BT709_LUM_COEFF_B * input.fB;
@@ -21,7 +27,8 @@
}
void main() {
+ half4 inputColor = sample(inputFP, sk_InColor);
const half3 SK_ITU_BT709_LUM_COEFF = half3(0.2126, 0.7152, 0.0722);
- half luma = saturate(dot(SK_ITU_BT709_LUM_COEFF, sk_InColor.rgb));
+ half luma = saturate(dot(SK_ITU_BT709_LUM_COEFF, inputColor.rgb));
sk_OutColor = half4(0, 0, 0, luma);
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrMagnifierEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrMagnifierEffect.fp
index 582fc4bb298..b4af4c4804b 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrMagnifierEffect.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrMagnifierEffect.fp
@@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
-in uniform sampler2D src;
+in fragmentProcessor src;
layout(ctype=SkIRect) in int4 bounds;
uniform float4 boundsUniform;
layout(ctype=SkRect) in float4 srcRect;
@@ -16,9 +16,7 @@ in uniform float yInvInset;
uniform half2 offset;
-@coordTransform(src) {
- SkMatrix::I()
-}
+@coordTransform { SkMatrix::I() }
void main() {
float2 coord = sk_TransformedCoords2D[0];
@@ -42,36 +40,11 @@ void main() {
}
@setData(pdman) {
- SkScalar invW = 1.0f / src.width();
- SkScalar invH = 1.0f / src.height();
-
- {
- SkScalar y = srcRect.y() * invH;
- if (srcView.origin() != kTopLeft_GrSurfaceOrigin) {
- y = 1.0f - (srcRect.height() / bounds.height()) - y;
- }
-
- pdman.set2f(offset, srcRect.x() * invW, y);
- }
-
- {
- SkScalar y = bounds.y() * invH;
- SkScalar hSign = 1.f;
- if (srcView.origin() != kTopLeft_GrSurfaceOrigin) {
- y = 1.0f - bounds.y() * invH;
- hSign = -1.f;
- }
-
- pdman.set4f(boundsUniform,
- bounds.x() * invW,
- y,
- SkIntToScalar(src.width()) / bounds.width(),
- hSign * SkIntToScalar(src.height()) / bounds.height());
- }
+ pdman.set2f(offset, srcRect.x(), srcRect.y());
+ pdman.set4f(boundsUniform, bounds.x(), bounds.y(), 1.f/ bounds.width(), 1.f / bounds.height());
}
@test(d) {
- auto [view, ct, at] = d->randomView();
const int kMaxWidth = 200;
const int kMaxHeight = 200;
const SkScalar kMaxInset = 20.0f;
@@ -82,7 +55,8 @@ void main() {
SkIRect bounds = SkIRect::MakeWH(SkIntToScalar(kMaxWidth), SkIntToScalar(kMaxHeight));
SkRect srcRect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
- auto effect = GrMagnifierEffect::Make(std::move(view),
+ auto src = GrProcessorUnitTest::MakeChildFP(d);
+ auto effect = GrMagnifierEffect::Make(std::move(src),
bounds,
srcRect,
srcRect.width() / bounds.width(),
diff --git a/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.cpp
index 8de8deefce0..04036d03ded 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.cpp
@@ -42,9 +42,12 @@ private:
typedef GrGLSLFragmentProcessor INHERITED;
};
-GrMatrixConvolutionEffect::KernelWrapper GrMatrixConvolutionEffect::KernelWrapper::Make(
- GrRecordingContext* context, SkISize size, const GrCaps& caps, const SkScalar* values) {
- if (nullptr == context || nullptr == values || size.isEmpty()) {
+GrMatrixConvolutionEffect::KernelWrapper::MakeResult
+GrMatrixConvolutionEffect::KernelWrapper::Make(GrRecordingContext* context,
+ SkISize size,
+ const GrCaps& caps,
+ const SkScalar* values) {
+ if (!context || !values || size.isEmpty()) {
return {};
}
const int length = size.area();
@@ -54,10 +57,10 @@ GrMatrixConvolutionEffect::KernelWrapper GrMatrixConvolutionEffect::KernelWrappe
for (int i = 0; i < length; i++) {
result.fArray[i] = SkScalarToFloat(values[i]);
}
- return result;
+ return {result, nullptr};
}
- ScalableSampler& scalableSampler = result.fScalableSampler;
+ BiasAndGain& scalableSampler = result.fBiasAndGain;
bool useA16 =
context->defaultBackendFormat(kA16_float_SkColorType, GrRenderable::kNo).isValid();
SkScalar min = values[0];
@@ -108,8 +111,7 @@ GrMatrixConvolutionEffect::KernelWrapper GrMatrixConvolutionEffect::KernelWrappe
view = {std::move(cachedKernel), kTopLeft_GrSurfaceOrigin, swizzle};
} else {
SkBitmap bm;
- auto info = SkImageInfo::Make({(int)GrNextPow2(length), 1}, colorType,
- kPremul_SkAlphaType, nullptr);
+ auto info = SkImageInfo::Make({length, 1}, colorType, kPremul_SkAlphaType, nullptr);
if (!bm.tryAllocPixels(info)) {
return {};
}
@@ -131,23 +133,23 @@ GrMatrixConvolutionEffect::KernelWrapper GrMatrixConvolutionEffect::KernelWrappe
proxyProvider->assignUniqueKeyToProxy(key, view.asTextureProxy());
}
}
- scalableSampler.fSampler = { std::move(view) };
- return result;
+ auto kernelFP = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
+ return {result, std::move(kernelFP)};
}
bool GrMatrixConvolutionEffect::KernelWrapper::operator==(const KernelWrapper& k) const {
if (fSize != k.fSize) {
return false;
} else if (this->isSampled()) {
- return fScalableSampler == k.fScalableSampler;
+ return fBiasAndGain == k.fBiasAndGain;
} else {
return std::equal(fArray.begin(), fArray.begin() + fSize.area(), k.fArray.begin());
}
}
-bool GrMatrixConvolutionEffect::KernelWrapper::ScalableSampler::operator==(
- const ScalableSampler& k) const {
- return fSampler == k.fSampler && fGain == k.fGain && fBias == k.fBias;
+bool GrMatrixConvolutionEffect::KernelWrapper::BiasAndGain::operator==(
+ const BiasAndGain& k) const {
+ return fGain == k.fGain && fBias == k.fBias;
}
// For sampled kernels, emit a for loop that does all the kernel accumulation.
@@ -162,7 +164,6 @@ void GrGLMatrixConvolutionEffect::emitKernelBlock(EmitArgs& args, SkIPoint loc)
int kernelArea = kernelWidth * kernelHeight;
if (mce.kernelIsSampled()) {
- fragBuilder->codeAppendf("half2 kernelCoord = half2(0, 0);");
fragBuilder->codeAppendf("for (int i = 0; i < %d; ++i)", (int)kernelArea);
}
@@ -172,13 +173,11 @@ void GrGLMatrixConvolutionEffect::emitKernelBlock(EmitArgs& args, SkIPoint loc)
fragBuilder->codeAppend("half2 sourceOffset;");
if (mce.kernelIsSampled()) {
const char* kernelBias = uniformHandler->getUniformCStr(fKernelBiasUni);
- fragBuilder->codeAppend("k = ");
- fragBuilder->appendTextureLookup(args.fTexSamplers[0], "kernelCoord");
- fragBuilder->codeAppendf(".w + %s;", kernelBias);
+ SkString kernelCoord = SkStringPrintf("float2(float(i) + 0.5, 0.5)");
+ SkString kernelSample = this->invokeChild(1, args, kernelCoord.c_str());
+ fragBuilder->codeAppendf("k = %s.w + %s;", kernelSample.c_str(), kernelBias);
fragBuilder->codeAppendf("sourceOffset.y = floor(i / %d);", kernelWidth);
fragBuilder->codeAppendf("sourceOffset.x = i - sourceOffset.y * %d;", kernelWidth);
- float kernelStride = 1.0f / (float)GrNextPow2(kernelArea);
- fragBuilder->codeAppendf("kernelCoord.x += %f;", kernelStride);
} else {
fragBuilder->codeAppendf("sourceOffset = half2(%d, %d);", loc.x(), loc.y());
int offset = loc.y() * kernelWidth + loc.x();
@@ -191,7 +190,7 @@ void GrGLMatrixConvolutionEffect::emitKernelBlock(EmitArgs& args, SkIPoint loc)
auto sample = this->invokeChild(0, args, "coord + sourceOffset");
fragBuilder->codeAppendf("half4 c = %s;", sample.c_str());
if (!mce.convolveAlpha()) {
- fragBuilder->codeAppend("c.rgb /= max(c.a, 0.0001);");
+ fragBuilder->codeAppend("c = unpremul(c);");
fragBuilder->codeAppend("c.rgb = saturate(c.rgb);");
}
fragBuilder->codeAppend("sum += c * k;");
@@ -282,7 +281,8 @@ void GrGLMatrixConvolutionEffect::onSetData(const GrGLSLProgramDataManager& pdma
}
GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(std::unique_ptr<GrFragmentProcessor> child,
- KernelWrapper kernel,
+ const KernelWrapper& kernel,
+ std::unique_ptr<GrFragmentProcessor> kernelFP,
SkScalar gain,
SkScalar bias,
const SkIPoint& kernelOffset,
@@ -290,14 +290,13 @@ GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(std::unique_ptr<GrFragmentP
// To advertise either the modulation or opaqueness optimizations we'd have to examine the
// parameters.
: INHERITED(kGrMatrixConvolutionEffect_ClassID, kNone_OptimizationFlags)
- , fKernel(std::move(kernel))
+ , fKernel(kernel)
, fGain(SkScalarToFloat(gain))
, fBias(SkScalarToFloat(bias) / 255.0f)
, fConvolveAlpha(convolveAlpha) {
- child->setSampledWithExplicitCoords();
- this->registerChildProcessor(std::move(child));
- if (fKernel.isSampled()) {
- this->setTextureSamplerCnt(1);
+ this->registerExplicitlySampledChild(std::move(child));
+ if (kernelFP) {
+ this->registerExplicitlySampledChild(std::move(kernelFP));
}
fKernelOffset = {static_cast<float>(kernelOffset.x()),
static_cast<float>(kernelOffset.y())};
@@ -311,12 +310,7 @@ GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(const GrMatrixConvolutionEf
, fBias(that.fBias)
, fKernelOffset(that.fKernelOffset)
, fConvolveAlpha(that.fConvolveAlpha) {
- auto child = that.childProcessor(0).clone();
- child->setSampledWithExplicitCoords();
- this->registerChildProcessor(std::move(child));
- if (fKernel.isSampled()) {
- this->setTextureSamplerCnt(1);
- }
+ this->cloneAndRegisterAllChildProcessors(that);
this->addCoordTransform(&fCoordTransform);
}
@@ -342,11 +336,6 @@ bool GrMatrixConvolutionEffect::onIsEqual(const GrFragmentProcessor& sBase) cons
fConvolveAlpha == s.convolveAlpha();
}
-const GrFragmentProcessor::TextureSampler& GrMatrixConvolutionEffect::onTextureSampler(
- int index) const {
- return IthTextureSampler(index, fKernel.scalableSampler().fSampler);
-}
-
static void fill_in_1D_gaussian_kernel_with_stride(float* kernel, int size, int stride,
float twoSigmaSqrd) {
SkASSERT(!SkScalarNearlyZero(twoSigmaSqrd, SK_ScalarNearlyZero));
@@ -437,15 +426,16 @@ std::unique_ptr<GrFragmentProcessor> GrMatrixConvolutionEffect::Make(GrRecording
GrSamplerState::WrapMode wm,
bool convolveAlpha,
const GrCaps& caps) {
- auto kw = KernelWrapper::Make(context, kernelSize, caps, kernel);
- if (!kw.isValid()) {
+ auto [kernelWrapper, kernelFP] = KernelWrapper::Make(context, kernelSize, caps, kernel);
+ if (!kernelWrapper.isValid()) {
return nullptr;
}
GrSamplerState sampler(wm, GrSamplerState::Filter::kNearest);
auto child = GrTextureEffect::MakeSubset(std::move(srcView), kPremul_SkAlphaType, SkMatrix::I(),
sampler, SkRect::Make(srcBounds), caps);
- return std::unique_ptr<GrFragmentProcessor>(new GrMatrixConvolutionEffect(
- std::move(child), std::move(kw), gain, bias, kernelOffset, convolveAlpha));
+ return std::unique_ptr<GrFragmentProcessor>(
+ new GrMatrixConvolutionEffect(std::move(child), kernelWrapper, std::move(kernelFP),
+ gain, bias, kernelOffset, convolveAlpha));
}
std::unique_ptr<GrFragmentProcessor> GrMatrixConvolutionEffect::MakeGaussian(
diff --git a/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.h b/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.h
index 4a5627bdec3..e28cb957484 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/GrMatrixConvolutionEffect.h
@@ -49,8 +49,8 @@ public:
const SkV2 kernelOffset() const { return fKernelOffset; }
bool kernelIsSampled() const { return fKernel.isSampled(); }
const float *kernel() const { return fKernel.array().data(); }
- float kernelSampleGain() const { return fKernel.scalableSampler().fGain; }
- float kernelSampleBias() const { return fKernel.scalableSampler().fBias; }
+ float kernelSampleGain() const { return fKernel.biasAndGain().fGain; }
+ float kernelSampleBias() const { return fKernel.biasAndGain().fBias; }
float gain() const { return fGain; }
float bias() const { return fBias; }
bool convolveAlpha() const { return fConvolveAlpha; }
@@ -67,36 +67,24 @@ private:
*/
class KernelWrapper {
public:
- struct ScalableSampler {
- TextureSampler fSampler;
+ struct BiasAndGain {
// Only used in A8 mode. Applied before any other math.
- float fBias = 0.0f;
+ float fBias;
// Only used in A8 mode. Premultiplied in with user gain to save time.
- float fGain = 1.0f;
- bool operator==(const ScalableSampler&) const;
+ float fGain;
+ bool operator==(const BiasAndGain&) const;
};
- static KernelWrapper Make(GrRecordingContext*, SkISize,
- const GrCaps&, const float* values);
+ using MakeResult = std::tuple<KernelWrapper, std::unique_ptr<GrFragmentProcessor>>;
+ static MakeResult Make(GrRecordingContext*, SkISize, const GrCaps&, const float* values);
- KernelWrapper(KernelWrapper&& that) : fSize(that.fSize) {
- if (that.isSampled()) {
- new (&fScalableSampler) ScalableSampler(std::move(that.fScalableSampler));
- } else {
- new (&fArray) std::array<float, kMaxUniformSize>(std::move(that.fArray));
- }
- }
+ KernelWrapper() = default;
KernelWrapper(const KernelWrapper& that) : fSize(that.fSize) {
if (that.isSampled()) {
- new (&fScalableSampler) ScalableSampler(that.fScalableSampler);
+ fBiasAndGain = that.fBiasAndGain;
} else {
new (&fArray) std::array<float, kMaxUniformSize>(that.fArray);
}
}
- ~KernelWrapper() {
- if (this->isSampled()) {
- fScalableSampler.~ScalableSampler();
- }
- }
bool isValid() const { return !fSize.isEmpty(); }
SkISize size() const { return fSize; }
@@ -105,29 +93,29 @@ private:
SkASSERT(!this->isSampled());
return fArray;
}
- const ScalableSampler& scalableSampler() const {
+ const BiasAndGain& biasAndGain() const {
SkASSERT(this->isSampled());
- return fScalableSampler;
+ return fBiasAndGain;
}
bool operator==(const KernelWrapper&) const;
private:
- KernelWrapper() : fSize({}) {}
KernelWrapper(SkISize size) : fSize(size) {
if (this->isSampled()) {
- new (&fScalableSampler) ScalableSampler;
+ fBiasAndGain = {0.f , 1.f};
}
}
- SkISize fSize;
+ SkISize fSize = {};
union {
std::array<float, kMaxUniformSize> fArray;
- ScalableSampler fScalableSampler;
+ BiasAndGain fBiasAndGain;
};
};
GrMatrixConvolutionEffect(std::unique_ptr<GrFragmentProcessor> child,
- KernelWrapper kernel,
+ const KernelWrapper& kernel,
+ std::unique_ptr<GrFragmentProcessor> kernelFP,
SkScalar gain,
SkScalar bias,
const SkIPoint& kernelOffset,
@@ -141,8 +129,6 @@ private:
bool onIsEqual(const GrFragmentProcessor&) const override;
- const GrFragmentProcessor::TextureSampler& onTextureSampler(int index) const override;
-
// We really just want the unaltered local coords, but the only way to get that right now is
// an identity coord transform.
GrCoordTransform fCoordTransform = {};
diff --git a/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.cpp
new file mode 100644
index 00000000000..aa5cd3cd888
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/effects/GrMatrixEffect.h"
+
+#include "src/gpu/GrTexture.h"
+#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
+#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
+#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
+#include "src/sksl/SkSLCPP.h"
+#include "src/sksl/SkSLUtil.h"
+
+class GrGLSLMatrixEffect : public GrGLSLFragmentProcessor {
+public:
+ GrGLSLMatrixEffect() {}
+
+ void emitCode(EmitArgs& args) override {
+ fMatrixVar = args.fUniformHandler->addUniform(&args.fFp, kFragment_GrShaderFlag,
+ kFloat3x3_GrSLType, "matrix");
+ SkString child = this->invokeChild(0, args.fInputColor, args);
+ args.fFragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, child.c_str());
+ }
+
+private:
+ void onSetData(const GrGLSLProgramDataManager& pdman,
+ const GrFragmentProcessor& proc) override {
+ const GrMatrixEffect& mtx = proc.cast<GrMatrixEffect>();
+ pdman.setSkMatrix(fMatrixVar, mtx.matrix());
+ }
+
+ UniformHandle fMatrixVar;
+};
+
+GrGLSLFragmentProcessor* GrMatrixEffect::onCreateGLSLInstance() const {
+ return new GrGLSLMatrixEffect();
+}
+
+void GrMatrixEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
+ GrProcessorKeyBuilder* b) const {}
+
+bool GrMatrixEffect::onIsEqual(const GrFragmentProcessor& other) const {
+ const GrMatrixEffect& that = other.cast<GrMatrixEffect>();
+ if (fMatrix != that.fMatrix) return false;
+ return true;
+}
+
+GrMatrixEffect::GrMatrixEffect(const GrMatrixEffect& src)
+ : INHERITED(kGrMatrixEffect_ClassID, src.optimizationFlags())
+ , fMatrix(src.fMatrix) {
+ this->cloneAndRegisterAllChildProcessors(src);
+}
+
+std::unique_ptr<GrFragmentProcessor> GrMatrixEffect::clone() const {
+ return std::unique_ptr<GrFragmentProcessor>(new GrMatrixEffect(*this));
+}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.fp
deleted file mode 100644
index d325c7b73e3..00000000000
--- a/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.fp
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2020 Google LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-in uniform float3x3 matrix;
-in fragmentProcessor child;
-
-@class {
- static std::unique_ptr<GrFragmentProcessor> Apply(const SkMatrix& matrix,
- std::unique_ptr<GrFragmentProcessor> processor) {
- if (matrix.isIdentity()) {
- return processor;
- }
- SkASSERT(!processor->isSampledWithExplicitCoords());
- SkASSERT(processor->sampleMatrix().fKind == SkSL::SampleMatrix::Kind::kNone);
- return Make(matrix, std::move(processor));
- }
-}
-
-void main() {
- sk_OutColor = sample(child, sk_InColor, matrix);
-}
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrMatrixEffect.h b/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.h
index 75a2dbc32ff..69fd1be37e1 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrMatrixEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/GrMatrixEffect.h
@@ -5,49 +5,48 @@
* found in the LICENSE file.
*/
-/**************************************************************************************************
- *** This file was autogenerated from GrMatrixEffect.fp; do not modify.
- **************************************************************************************************/
#ifndef GrMatrixEffect_DEFINED
#define GrMatrixEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrMatrixEffect : public GrFragmentProcessor {
public:
- static std::unique_ptr<GrFragmentProcessor> Apply(
- const SkMatrix& matrix, std::unique_ptr<GrFragmentProcessor> processor) {
+ static std::unique_ptr<GrFragmentProcessor> Make(
+ const SkMatrix& matrix, std::unique_ptr<GrFragmentProcessor> child) {
if (matrix.isIdentity()) {
- return processor;
+ return child;
}
- SkASSERT(!processor->isSampledWithExplicitCoords());
- SkASSERT(processor->sampleMatrix().fKind == SkSL::SampleMatrix::Kind::kNone);
- return Make(matrix, std::move(processor));
- }
- static std::unique_ptr<GrFragmentProcessor> Make(SkMatrix matrix,
- std::unique_ptr<GrFragmentProcessor> child) {
- return std::unique_ptr<GrFragmentProcessor>(new GrMatrixEffect(matrix, std::move(child)));
+ SkASSERT(!child->isSampledWithExplicitCoords());
+ SkASSERT(child->sampleMatrix().fKind == SkSL::SampleMatrix::Kind::kNone);
+ return std::unique_ptr<GrFragmentProcessor>(
+ new GrMatrixEffect(matrix, std::move(child)));
}
- GrMatrixEffect(const GrMatrixEffect& src);
+
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "MatrixEffect"; }
- SkMatrix matrix;
- int child_index = -1;
+ const SkMatrix& matrix() const { return fMatrix; }
private:
+ GrMatrixEffect(const GrMatrixEffect& src);
+
GrMatrixEffect(SkMatrix matrix, std::unique_ptr<GrFragmentProcessor> child)
- : INHERITED(kGrMatrixEffect_ClassID, kNone_OptimizationFlags), matrix(matrix) {
+ : INHERITED(kGrMatrixEffect_ClassID, kNone_OptimizationFlags)
+ , fMatrix(matrix) {
SkASSERT(child);
- child_index = this->numChildProcessors();
- child->setSampleMatrix(
- SkSL::SampleMatrix(SkSL::SampleMatrix::Kind::kConstantOrUniform, this, "matrix"));
- this->registerChildProcessor(std::move(child));
+ this->registerChild(std::move(child), SkSL::SampleMatrix::MakeConstUniform("matrix"));
}
+
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
+
+ SkMatrix fMatrix;
+
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
typedef GrFragmentProcessor INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.cpp
index b7c001cd54b..a84e6c2c737 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.cpp
@@ -11,23 +11,20 @@
#include "src/gpu/effects/generated/GrCircleEffect.h"
#include "src/gpu/effects/generated/GrEllipseEffect.h"
-std::unique_ptr<GrFragmentProcessor> GrOvalEffect::Make(GrClipEdgeType edgeType, const SkRect& oval,
- const GrShaderCaps& caps) {
- if (GrClipEdgeType::kHairlineAA == edgeType) {
- return nullptr;
- }
+GrFPResult GrOvalEffect::Make(std::unique_ptr<GrFragmentProcessor> inputFP, GrClipEdgeType edgeType,
+ const SkRect& oval, const GrShaderCaps& caps) {
SkScalar w = oval.width();
SkScalar h = oval.height();
if (SkScalarNearlyEqual(w, h)) {
w /= 2;
- return GrCircleEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + w),
- w);
+ return GrCircleEffect::Make(std::move(inputFP), edgeType,
+ SkPoint::Make(oval.fLeft + w, oval.fTop + w), w);
} else {
w /= 2;
h /= 2;
- return GrEllipseEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h),
+ return GrEllipseEffect::Make(std::move(inputFP), edgeType,
+ SkPoint::Make(oval.fLeft + w, oval.fTop + h),
SkPoint::Make(w, h), caps);
}
-
- return nullptr;
+ SkUNREACHABLE;
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.h b/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.h
index 8b4c95d71b1..955c1949566 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.h
@@ -11,8 +11,8 @@
#include "include/core/SkRefCnt.h"
#include "include/gpu/GrTypes.h"
#include "include/private/GrTypesPriv.h"
+#include "src/gpu/GrFragmentProcessor.h"
-class GrFragmentProcessor;
class GrShaderCaps;
struct SkRect;
@@ -21,7 +21,8 @@ namespace GrOvalEffect {
/**
* Creates an effect that performs clipping against an oval.
*/
-std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRect&, const GrShaderCaps&);
+GrFPResult Make(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType, const SkRect&,
+ const GrShaderCaps&);
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/GrPremulInputFragmentProcessor.fp b/chromium/third_party/skia/src/gpu/effects/GrPremulInputFragmentProcessor.fp
deleted file mode 100644
index cbba6070740..00000000000
--- a/chromium/third_party/skia/src/gpu/effects/GrPremulInputFragmentProcessor.fp
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-@optimizationFlags {
- kPreservesOpaqueInput_OptimizationFlag | kConstantOutputForConstantInput_OptimizationFlag
-}
-
-void main() {
- sk_OutColor = sk_InColor;
- sk_OutColor.rgb *= sk_InColor.a;
-}
-
-@class {
- SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
- return SkColor4f { input.fR, input.fG, input.fB, input.fA }.premul();
- }
-}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrRGBToHSLFilterEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrRGBToHSLFilterEffect.fp
index 443fd1ae395..b30d798ebbb 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrRGBToHSLFilterEffect.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrRGBToHSLFilterEffect.fp
@@ -25,8 +25,10 @@
// [2] http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
// [3] http://www.chilliant.com/rgb2hsv.html
+in fragmentProcessor? inputFP;
+
void main() {
- half4 c = sk_InColor;
+ half4 c = sample(inputFP, sk_InColor);
half4 p = (c.g < c.b) ? half4(c.bg, -1, 2/3.0)
: half4(c.gb, 0, -1/3.0);
half4 q = (c.r < p.x) ? half4(p.x, c.r, p.yw)
@@ -48,13 +50,17 @@ void main() {
}
@optimizationFlags {
+ (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
(kConstantOutputForConstantInput_OptimizationFlag | kPreservesOpaqueInput_OptimizationFlag)
}
@class {
#include "include/private/SkColorData.h"
- SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& c) const override {
+ SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
+ SkPMColor4f c = this->numChildProcessors()
+ ? ConstantOutputForConstantInput(this->childProcessor(0), inColor)
+ : inColor;
const auto p = (c.fG < c.fB) ? SkPMColor4f{ c.fB, c.fG, -1, 2/3.f }
: SkPMColor4f{ c.fG, c.fB, 0, -1/3.f },
q = (c.fR < p[0]) ? SkPMColor4f{ p[0], c.fR, p[1], p[3] }
diff --git a/chromium/third_party/skia/src/gpu/effects/GrRRectBlurEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrRRectBlurEffect.fp
index 02a8743c166..e8cb928439d 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrRRectBlurEffect.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrRRectBlurEffect.fp
@@ -5,10 +5,11 @@
* found in the LICENSE file.
*/
+in fragmentProcessor? inputFP;
in float sigma;
layout(ctype=SkRect) in float4 rect;
in uniform half cornerRadius;
-in uniform sampler2D ninePatchSampler;
+in fragmentProcessor ninePatchFP;
layout(ctype=SkRect) uniform float4 proxyRect;
uniform half blurRadius;
@@ -19,19 +20,20 @@ uniform half blurRadius;
#include "src/core/SkGpuBlurUtils.h"
#include "src/core/SkRRectPriv.h"
#include "src/gpu/GrCaps.h"
- #include "src/gpu/GrClip.h"
#include "src/gpu/GrPaint.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrStyle.h"
+ #include "src/gpu/effects/GrTextureEffect.h"
}
@class {
- static GrSurfaceProxyView find_or_create_rrect_blur_mask(GrRecordingContext* context,
- const SkRRect& rrectToDraw,
- const SkISize& dimensions,
- float xformedSigma) {
+ static std::unique_ptr<GrFragmentProcessor> find_or_create_rrect_blur_mask_fp(
+ GrRecordingContext* context,
+ const SkRRect& rrectToDraw,
+ const SkISize& dimensions,
+ float xformedSigma) {
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey key;
GrUniqueKey::Builder builder(&key, kDomain, 9, "RoundRect Blur Mask");
@@ -47,31 +49,37 @@ uniform half blurRadius;
}
builder.finish();
+ // It seems like we could omit this matrix and modify the shader code to not normalize
+ // the coords used to sample the texture effect. However, the "proxyDims" value in the
+ // shader is not always the actual the proxy dimensions. This is because 'dimensions' here
+ // was computed using integer corner radii as determined in
+ // SkComputeBlurredRRectParams whereas the shader code uses the float radius to compute
+ // 'proxyDims'. Why it draws correctly with these unequal values is a mystery for the ages.
+ auto m = SkMatrix::Scale(dimensions.width(), dimensions.height());
static constexpr auto kMaskOrigin = kBottomLeft_GrSurfaceOrigin;
GrProxyProvider* proxyProvider = context->priv().proxyProvider();
if (auto view = proxyProvider->findCachedProxyWithColorTypeFallback(
key, kMaskOrigin, GrColorType::kAlpha_8, 1)) {
- return view;
+ return GrTextureEffect::Make(std::move(view), kPremul_SkAlphaType, m);
}
auto rtc = GrRenderTargetContext::MakeWithFallback(
context, GrColorType::kAlpha_8, nullptr, SkBackingFit::kExact, dimensions, 1,
GrMipMapped::kNo, GrProtected::kNo, kMaskOrigin);
if (!rtc) {
- return {};
+ return nullptr;
}
GrPaint paint;
- rtc->clear(nullptr, SK_PMColor4fTRANSPARENT,
- GrRenderTargetContext::CanClearFullscreen::kYes);
- rtc->drawRRect(GrNoClip(), std::move(paint), GrAA::kYes, SkMatrix::I(), rrectToDraw,
+ rtc->clear(SK_PMColor4fTRANSPARENT);
+ rtc->drawRRect(nullptr, std::move(paint), GrAA::kYes, SkMatrix::I(), rrectToDraw,
GrStyle::SimpleFill());
GrSurfaceProxyView srcView = rtc->readSurfaceView();
if (!srcView) {
- return {};
+ return nullptr;
}
SkASSERT(srcView.asTextureProxy());
auto rtc2 = SkGpuBlurUtils::GaussianBlur(context,
@@ -86,27 +94,28 @@ uniform half blurRadius;
SkTileMode::kClamp,
SkBackingFit::kExact);
if (!rtc2) {
- return {};
+ return nullptr;
}
GrSurfaceProxyView mask = rtc2->readSurfaceView();
if (!mask) {
- return {};
+ return nullptr;
}
SkASSERT(mask.asTextureProxy());
- SkASSERT(mask.origin() == kBottomLeft_GrSurfaceOrigin);
+ SkASSERT(mask.origin() == kMaskOrigin);
proxyProvider->assignUniqueKeyToProxy(key, mask.asTextureProxy());
-
- return mask;
+ return GrTextureEffect::Make(std::move(mask), kPremul_SkAlphaType, m);
}
}
@optimizationFlags {
- kCompatibleWithCoverageAsAlpha_OptimizationFlag
+ (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag
}
@make {
- static std::unique_ptr<GrFragmentProcessor> Make(GrRecordingContext* context,
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrRecordingContext* context,
float sigma,
float xformedSigma,
const SkRRect& srcRRect,
@@ -114,11 +123,13 @@ uniform half blurRadius;
}
@cpp {
- std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::Make(GrRecordingContext* context,
- float sigma,
- float xformedSigma,
- const SkRRect& srcRRect,
- const SkRRect& devRRect) {
+ std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::Make(
+ std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrRecordingContext* context,
+ float sigma,
+ float xformedSigma,
+ const SkRRect& srcRRect,
+ const SkRRect& devRRect) {
SkASSERT(!SkRRectPriv::IsCircle(devRRect) && !devRRect.isRect()); // Should've been caught up-stream
// TODO: loosen this up
@@ -147,15 +158,15 @@ uniform half blurRadius;
return nullptr;
}
- GrSurfaceProxyView mask = find_or_create_rrect_blur_mask(context, rrectToDraw, dimensions,
- xformedSigma);
- if (!mask) {
+ std::unique_ptr<GrFragmentProcessor> maskFP = find_or_create_rrect_blur_mask_fp(
+ context, rrectToDraw, dimensions, xformedSigma);
+ if (!maskFP) {
return nullptr;
}
return std::unique_ptr<GrFragmentProcessor>(
- new GrRRectBlurEffect(xformedSigma, devRRect.getBounds(),
- SkRRectPriv::GetSimpleRadii(devRRect).fX, std::move(mask)));
+ new GrRRectBlurEffect(std::move(inputFP), xformedSigma, devRRect.getBounds(),
+ SkRRectPriv::GetSimpleRadii(devRRect).fX, std::move(maskFP)));
}
}
@@ -166,33 +177,46 @@ uniform half blurRadius;
SkScalar sigma = d->fRandom->nextRangeF(1.f,10.f);
SkRRect rrect;
rrect.setRectXY(SkRect::MakeWH(w, h), r, r);
- return GrRRectBlurEffect::Make(d->context(), sigma, sigma, rrect, rrect);
+ return GrRRectBlurEffect::Make(/*inputFP=*/nullptr, d->context(), sigma, sigma, rrect, rrect);
}
void main() {
- // warp the fragment position to the appropriate part of the 9patch blur texture
-
- half2 rectCenter = half2((proxyRect.xy + proxyRect.zw) / 2.0);
- half2 translatedFragPos = half2(sk_FragCoord.xy - proxyRect.xy);
- half threshold = cornerRadius + 2.0 * blurRadius;
- half2 middle = half2(proxyRect.zw - proxyRect.xy - 2.0 * threshold);
-
- if (translatedFragPos.x >= threshold && translatedFragPos.x < (middle.x + threshold)) {
- translatedFragPos.x = threshold;
- } else if (translatedFragPos.x >= (middle.x + threshold)) {
- translatedFragPos.x -= middle.x - 1.0;
- }
-
- if (translatedFragPos.y > threshold && translatedFragPos.y < (middle.y+threshold)) {
- translatedFragPos.y = threshold;
- } else if (translatedFragPos.y >= (middle.y + threshold)) {
- translatedFragPos.y -= middle.y - 1.0;
- }
-
- half2 proxyDims = half2(2.0 * threshold + 1.0);
+ // Warp the fragment position to the appropriate part of the 9-patch blur texture by snipping
+ // out the middle section of the proxy rect.
+ half2 translatedFragPos = half2(sk_FragCoord.xy - proxyRect.LT);
+ half2 proxyCenter = half2((proxyRect.RB - proxyRect.LT) * 0.5);
+ half edgeSize = 2.0 * blurRadius + cornerRadius + 0.5;
+
+ // Position the fragment so that (0, 0) marks the center of the proxy rectangle.
+ // Negative coordinates are on the left/top side and positive numbers are on the right/bottom.
+ translatedFragPos -= proxyCenter;
+
+ // Temporarily strip off the fragment's sign. x/y are now strictly increasing as we move away
+ // from the center.
+ half2 fragDirection = sign(translatedFragPos);
+ translatedFragPos = abs(translatedFragPos);
+
+ // Our goal is to snip out the "middle section" of the proxy rect (everything but the edge).
+ // We've repositioned our fragment position so that (0, 0) is the centerpoint and x/y are always
+ // positive, so we can subtract here and interpret negative results as being within the middle
+ // section.
+ translatedFragPos -= proxyCenter - edgeSize;
+
+ // Remove the middle section by clamping to zero.
+ translatedFragPos = max(translatedFragPos, 0);
+
+ // Reapply the fragment's sign, so that negative coordinates once again mean left/top side and
+ // positive means bottom/right side.
+ translatedFragPos *= fragDirection;
+
+ // Offset the fragment so that (0, 0) marks the upper-left again, instead of the center point.
+ translatedFragPos += half2(edgeSize);
+
+ half2 proxyDims = half2(2.0 * edgeSize);
half2 texCoord = translatedFragPos / proxyDims;
- sk_OutColor = sk_InColor * sample(ninePatchSampler, texCoord);
+ half4 inputColor = sample(inputFP, sk_InColor);
+ sk_OutColor = inputColor * sample(ninePatchFP, texCoord);
}
@setData(pdman) {
diff --git a/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.cpp
index f444034e426..a5f8538f86a 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.cpp
@@ -45,8 +45,8 @@ public:
// The flags are used to indicate which corners are circluar (unflagged corners are assumed to
// be square).
- static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType,
- uint32_t circularCornerFlags, const SkRRect&);
+ static GrFPResult Make(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType,
+ uint32_t circularCornerFlags, const SkRRect&);
~CircularRRectEffect() override {}
@@ -60,8 +60,14 @@ public:
GrClipEdgeType getEdgeType() const { return fEdgeType; }
+ bool hasInputFP() const {
+ return this->numChildProcessors() > 0;
+ }
+
private:
- CircularRRectEffect(GrClipEdgeType, uint32_t circularCornerFlags, const SkRRect&);
+ CircularRRectEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType, uint32_t circularCornerFlags, const SkRRect&);
+ CircularRRectEffect(const CircularRRectEffect& that);
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
@@ -69,36 +75,50 @@ private:
bool onIsEqual(const GrFragmentProcessor& other) const override;
- SkRRect fRRect;
+ SkRRect fRRect;
GrClipEdgeType fEdgeType;
- uint32_t fCircularCornerFlags;
+ uint32_t fCircularCornerFlags;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
typedef GrFragmentProcessor INHERITED;
};
-std::unique_ptr<GrFragmentProcessor> CircularRRectEffect::Make(GrClipEdgeType edgeType,
- uint32_t circularCornerFlags,
- const SkRRect& rrect) {
+GrFPResult CircularRRectEffect::Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType,
+ uint32_t circularCornerFlags, const SkRRect& rrect) {
if (GrClipEdgeType::kFillAA != edgeType && GrClipEdgeType::kInverseFillAA != edgeType) {
- return nullptr;
+ return GrFPFailure(std::move(inputFP));
}
- return std::unique_ptr<GrFragmentProcessor>(
- new CircularRRectEffect(edgeType, circularCornerFlags, rrect));
+ return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>(
+ new CircularRRectEffect(std::move(inputFP), edgeType, circularCornerFlags, rrect)));
}
-CircularRRectEffect::CircularRRectEffect(GrClipEdgeType edgeType, uint32_t circularCornerFlags,
+CircularRRectEffect::CircularRRectEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType, uint32_t circularCornerFlags,
const SkRRect& rrect)
- : INHERITED(kCircularRRectEffect_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag)
+ : INHERITED(
+ kCircularRRectEffect_ClassID,
+ (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, fRRect(rrect)
, fEdgeType(edgeType)
, fCircularCornerFlags(circularCornerFlags) {
+ if (inputFP != nullptr) {
+ this->registerChild(std::move(inputFP));
+ }
+}
+
+CircularRRectEffect::CircularRRectEffect(const CircularRRectEffect& that)
+ : INHERITED(kCircularRRectEffect_ClassID, that.optimizationFlags())
+ , fRRect(that.fRRect)
+ , fEdgeType(that.fEdgeType)
+ , fCircularCornerFlags(that.fCircularCornerFlags) {
+ this->cloneAndRegisterAllChildProcessors(that);
}
std::unique_ptr<GrFragmentProcessor> CircularRRectEffect::clone() const {
- return std::unique_ptr<GrFragmentProcessor>(
- new CircularRRectEffect(fEdgeType, fCircularCornerFlags, fRRect));
+ return std::unique_ptr<GrFragmentProcessor>(new CircularRRectEffect(*this));
}
bool CircularRRectEffect::onIsEqual(const GrFragmentProcessor& other) const {
@@ -119,11 +139,13 @@ std::unique_ptr<GrFragmentProcessor> CircularRRectEffect::TestCreate(GrProcessor
SkRRect rrect;
rrect.setRectXY(SkRect::MakeWH(w, h), r, r);
std::unique_ptr<GrFragmentProcessor> fp;
+ bool success;
do {
GrClipEdgeType et =
(GrClipEdgeType)d->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
- fp = GrRRectEffect::Make(et, rrect, *d->caps()->shaderCaps());
- } while (nullptr == fp);
+ std::tie(success, fp) = GrRRectEffect::Make(/*inputFP=*/nullptr, et, rrect,
+ *d->caps()->shaderCaps());
+ } while (!success);
return fp;
}
#endif
@@ -191,85 +213,85 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) {
// alphas together.
switch (crre.getCircularCornerFlags()) {
case CircularRRectEffect::kAll_CornerFlags:
- fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
- fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
+ fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName);
+ fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName);
fragBuilder->codeAppend("float2 dxy = max(max(dxy0, dxy1), 0.0);");
fragBuilder->codeAppendf("half alpha = half(%s);", clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kTopLeft_CornerFlag:
- fragBuilder->codeAppendf("float2 dxy = max(%s.xy - sk_FragCoord.xy, 0.0);",
+ fragBuilder->codeAppendf("float2 dxy = max(%s.LT - sk_FragCoord.xy, 0.0);",
rectName);
- fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.z - sk_FragCoord.x));",
+ fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.R - sk_FragCoord.x));",
rectName);
- fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.w - sk_FragCoord.y));",
+ fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.B - sk_FragCoord.y));",
rectName);
fragBuilder->codeAppendf("half alpha = bottomAlpha * rightAlpha * half(%s);",
clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kTopRight_CornerFlag:
- fragBuilder->codeAppendf("float2 dxy = max(float2(sk_FragCoord.x - %s.z, "
- "%s.y - sk_FragCoord.y), 0.0);",
+ fragBuilder->codeAppendf("float2 dxy = max(float2(sk_FragCoord.x - %s.R, "
+ "%s.T - sk_FragCoord.y), 0.0);",
rectName, rectName);
- fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.x));",
+ fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.L));",
rectName);
- fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.w - sk_FragCoord.y));",
+ fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.B - sk_FragCoord.y));",
rectName);
fragBuilder->codeAppendf("half alpha = bottomAlpha * leftAlpha * half(%s);",
clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kBottomRight_CornerFlag:
- fragBuilder->codeAppendf("float2 dxy = max(sk_FragCoord.xy - %s.zw, 0.0);",
+ fragBuilder->codeAppendf("float2 dxy = max(sk_FragCoord.xy - %s.RB, 0.0);",
rectName);
- fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.x));",
+ fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.L));",
rectName);
- fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.y));",
+ fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.T));",
rectName);
fragBuilder->codeAppendf("half alpha = topAlpha * leftAlpha * half(%s);",
clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kBottomLeft_CornerFlag:
- fragBuilder->codeAppendf("float2 dxy = max(float2(%s.x - sk_FragCoord.x, "
- "sk_FragCoord.y - %s.w), 0.0);",
+ fragBuilder->codeAppendf("float2 dxy = max(float2(%s.L - sk_FragCoord.x, "
+ "sk_FragCoord.y - %s.B), 0.0);",
rectName, rectName);
- fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.z - sk_FragCoord.x));",
+ fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.R - sk_FragCoord.x));",
rectName);
- fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.y));",
+ fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.T));",
rectName);
fragBuilder->codeAppendf("half alpha = topAlpha * rightAlpha * half(%s);",
clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kLeft_CornerFlags:
- fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
- fragBuilder->codeAppendf("float dy1 = sk_FragCoord.y - %s.w;", rectName);
+ fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName);
+ fragBuilder->codeAppendf("float dy1 = sk_FragCoord.y - %s.B;", rectName);
fragBuilder->codeAppend("float2 dxy = max(float2(dxy0.x, max(dxy0.y, dy1)), 0.0);");
- fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.z - sk_FragCoord.x));",
+ fragBuilder->codeAppendf("half rightAlpha = half(saturate(%s.R - sk_FragCoord.x));",
rectName);
fragBuilder->codeAppendf("half alpha = rightAlpha * half(%s);",
clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kTop_CornerFlags:
- fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
- fragBuilder->codeAppendf("float dx1 = sk_FragCoord.x - %s.z;", rectName);
+ fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName);
+ fragBuilder->codeAppendf("float dx1 = sk_FragCoord.x - %s.R;", rectName);
fragBuilder->codeAppend("float2 dxy = max(float2(max(dxy0.x, dx1), dxy0.y), 0.0);");
- fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.w - sk_FragCoord.y));",
+ fragBuilder->codeAppendf("half bottomAlpha = half(saturate(%s.B - sk_FragCoord.y));",
rectName);
fragBuilder->codeAppendf("half alpha = bottomAlpha * half(%s);",
clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kRight_CornerFlags:
- fragBuilder->codeAppendf("float dy0 = %s.y - sk_FragCoord.y;", rectName);
- fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
+ fragBuilder->codeAppendf("float dy0 = %s.T - sk_FragCoord.y;", rectName);
+ fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName);
fragBuilder->codeAppend("float2 dxy = max(float2(dxy1.x, max(dy0, dxy1.y)), 0.0);");
- fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.x));",
+ fragBuilder->codeAppendf("half leftAlpha = half(saturate(sk_FragCoord.x - %s.L));",
rectName);
fragBuilder->codeAppendf("half alpha = leftAlpha * half(%s);",
clampedCircleDistance.c_str());
break;
case CircularRRectEffect::kBottom_CornerFlags:
- fragBuilder->codeAppendf("float dx0 = %s.x - sk_FragCoord.x;", rectName);
- fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
+ fragBuilder->codeAppendf("float dx0 = %s.L - sk_FragCoord.x;", rectName);
+ fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName);
fragBuilder->codeAppend("float2 dxy = max(float2(max(dx0, dxy1.x), dxy1.y), 0.0);");
- fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.y));",
+ fragBuilder->codeAppendf("half topAlpha = half(saturate(sk_FragCoord.y - %s.T));",
rectName);
fragBuilder->codeAppendf("half alpha = topAlpha * half(%s);",
clampedCircleDistance.c_str());
@@ -280,7 +302,11 @@ void GLCircularRRectEffect::emitCode(EmitArgs& args) {
fragBuilder->codeAppend("alpha = 1.0 - alpha;");
}
- fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, args.fInputColor);
+ SkString inputSample = crre.hasInputFP()
+ ? this->invokeChild(/*childIndex=*/0, args.fInputColor, args)
+ : SkString(args.fInputColor);
+
+ fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, inputSample.c_str());
}
void GLCircularRRectEffect::GenKey(const GrProcessor& processor, const GrShaderCaps&,
@@ -385,7 +411,7 @@ GrGLSLFragmentProcessor* CircularRRectEffect::onCreateGLSLInstance() const {
class EllipticalRRectEffect : public GrFragmentProcessor {
public:
- static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRRect&);
+ static GrFPResult Make(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType, const SkRRect&);
~EllipticalRRectEffect() override {}
@@ -397,8 +423,13 @@ public:
GrClipEdgeType getEdgeType() const { return fEdgeType; }
+ bool hasInputFP() const {
+ return this->numChildProcessors() > 0;
+ }
+
private:
- EllipticalRRectEffect(GrClipEdgeType, const SkRRect&);
+ EllipticalRRectEffect(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType, const SkRRect&);
+ EllipticalRRectEffect(const EllipticalRRectEffect& that);
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
@@ -414,22 +445,37 @@ private:
typedef GrFragmentProcessor INHERITED;
};
-std::unique_ptr<GrFragmentProcessor> EllipticalRRectEffect::Make(GrClipEdgeType edgeType,
- const SkRRect& rrect) {
+GrFPResult EllipticalRRectEffect::Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType, const SkRRect& rrect) {
if (GrClipEdgeType::kFillAA != edgeType && GrClipEdgeType::kInverseFillAA != edgeType) {
- return nullptr;
+ return GrFPFailure(std::move(inputFP));
}
- return std::unique_ptr<GrFragmentProcessor>(new EllipticalRRectEffect(edgeType, rrect));
+ return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>(
+ new EllipticalRRectEffect(std::move(inputFP), edgeType, rrect)));
}
-EllipticalRRectEffect::EllipticalRRectEffect(GrClipEdgeType edgeType, const SkRRect& rrect)
- : INHERITED(kEllipticalRRectEffect_ClassID, kCompatibleWithCoverageAsAlpha_OptimizationFlag)
+EllipticalRRectEffect::EllipticalRRectEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType, const SkRRect& rrect)
+ : INHERITED(
+ kEllipticalRRectEffect_ClassID,
+ (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, fRRect(rrect)
, fEdgeType(edgeType) {
+ if (inputFP != nullptr) {
+ this->registerChild(std::move(inputFP));
+ }
+}
+
+EllipticalRRectEffect::EllipticalRRectEffect(const EllipticalRRectEffect& that)
+ : INHERITED(kEllipticalRRectEffect_ClassID, that.optimizationFlags())
+ , fRRect(that.fRRect)
+ , fEdgeType(that.fEdgeType) {
+ this->cloneAndRegisterAllChildProcessors(that);
}
std::unique_ptr<GrFragmentProcessor> EllipticalRRectEffect::clone() const {
- return std::unique_ptr<GrFragmentProcessor>(new EllipticalRRectEffect(fEdgeType, fRRect));
+ return std::unique_ptr<GrFragmentProcessor>(new EllipticalRRectEffect(*this));
}
bool EllipticalRRectEffect::onIsEqual(const GrFragmentProcessor& other) const {
@@ -470,10 +516,12 @@ std::unique_ptr<GrFragmentProcessor> EllipticalRRectEffect::TestCreate(GrProcess
r[SkRRect::kUpperLeft_Corner].fY);
}
std::unique_ptr<GrFragmentProcessor> fp;
+ bool success;
do {
GrClipEdgeType et = (GrClipEdgeType)d->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
- fp = GrRRectEffect::Make(et, rrect, *d->caps()->shaderCaps());
- } while (nullptr == fp);
+ std::tie(success, fp) = GrRRectEffect::Make(/*inputFP=*/nullptr, et, rrect,
+ *d->caps()->shaderCaps());
+ } while (!success);
return fp;
}
#endif
@@ -520,8 +568,8 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
// The code below is a simplified version of the above that performs maxs on the vector
// components before computing distances and alpha values so that only one distance computation
// need be computed to determine the min alpha.
- fragBuilder->codeAppendf("float2 dxy0 = %s.xy - sk_FragCoord.xy;", rectName);
- fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.zw;", rectName);
+ fragBuilder->codeAppendf("float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName);
+ fragBuilder->codeAppendf("float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName);
// If we're on a device where float != fp32 then we'll do the distance computation in a space
// that is normalized by the largest radius. The scale uniform will be scale, 1/scale. The
@@ -589,7 +637,11 @@ void GLEllipticalRRectEffect::emitCode(EmitArgs& args) {
fragBuilder->codeAppend("half alpha = clamp(0.5 + approx_dist, 0.0, 1.0);");
}
- fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, args.fInputColor);
+ SkString inputSample = erre.hasInputFP()
+ ? this->invokeChild(/*childIndex=*/0, args.fInputColor, args)
+ : SkString(args.fInputColor);
+
+ fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, inputSample.c_str());
}
void GLEllipticalRRectEffect::GenKey(const GrProcessor& effect, const GrShaderCaps&,
@@ -671,15 +723,15 @@ GrGLSLFragmentProcessor* EllipticalRRectEffect::onCreateGLSLInstance() const {
//////////////////////////////////////////////////////////////////////////////
-std::unique_ptr<GrFragmentProcessor> GrRRectEffect::Make(GrClipEdgeType edgeType,
- const SkRRect& rrect,
- const GrShaderCaps& caps) {
+GrFPResult GrRRectEffect::Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType, const SkRRect& rrect,
+ const GrShaderCaps& caps) {
if (rrect.isRect()) {
- return GrConvexPolyEffect::Make(edgeType, rrect.getBounds());
+ return GrConvexPolyEffect::Make(std::move(inputFP), edgeType, rrect.getBounds());
}
if (rrect.isOval()) {
- return GrOvalEffect::Make(edgeType, rrect.getBounds(), caps);
+ return GrOvalEffect::Make(std::move(inputFP), edgeType, rrect.getBounds(), caps);
}
if (rrect.isSimple()) {
@@ -687,13 +739,13 @@ std::unique_ptr<GrFragmentProcessor> GrRRectEffect::Make(GrClipEdgeType edgeType
SkRRectPriv::GetSimpleRadii(rrect).fY < kRadiusMin) {
// In this case the corners are extremely close to rectangular and we collapse the
// clip to a rectangular clip.
- return GrConvexPolyEffect::Make(edgeType, rrect.getBounds());
+ return GrConvexPolyEffect::Make(std::move(inputFP), edgeType, rrect.getBounds());
}
if (SkRRectPriv::GetSimpleRadii(rrect).fX == SkRRectPriv::GetSimpleRadii(rrect).fY) {
- return CircularRRectEffect::Make(edgeType, CircularRRectEffect::kAll_CornerFlags,
- rrect);
+ return CircularRRectEffect::Make(std::move(inputFP), edgeType,
+ CircularRRectEffect::kAll_CornerFlags, rrect);
} else {
- return EllipticalRRectEffect::Make(edgeType, rrect);
+ return EllipticalRRectEffect::Make(std::move(inputFP), edgeType, rrect);
}
}
@@ -737,6 +789,7 @@ std::unique_ptr<GrFragmentProcessor> GrRRectEffect::Make(GrClipEdgeType edgeType
// This rrect should have been caught in the simple case above. Though, it would
// be correctly handled in the fallthrough code.
SkASSERT(false);
+ [[fallthrough]];
case CircularRRectEffect::kTopLeft_CornerFlag:
case CircularRRectEffect::kTopRight_CornerFlag:
case CircularRRectEffect::kBottomRight_CornerFlag:
@@ -749,24 +802,24 @@ std::unique_ptr<GrFragmentProcessor> GrRRectEffect::Make(GrClipEdgeType edgeType
if (squashedRadii) {
rr.writable()->setRectRadii(rrect.getBounds(), radii);
}
- return CircularRRectEffect::Make(edgeType, cornerFlags, *rr);
+ return CircularRRectEffect::Make(std::move(inputFP), edgeType, cornerFlags, *rr);
+ }
+ case CircularRRectEffect::kNone_CornerFlags: {
+ return GrConvexPolyEffect::Make(std::move(inputFP), edgeType, rrect.getBounds());
}
- case CircularRRectEffect::kNone_CornerFlags:
- return GrConvexPolyEffect::Make(edgeType, rrect.getBounds());
default: {
if (squashedRadii) {
// If we got here then we squashed some but not all the radii to zero. (If all
// had been squashed cornerFlags would be 0.) The elliptical effect doesn't
// support some rounded and some square corners.
- return nullptr;
+ return GrFPFailure(std::move(inputFP));
}
if (rrect.isNinePatch()) {
- return EllipticalRRectEffect::Make(edgeType, rrect);
+ return EllipticalRRectEffect::Make(std::move(inputFP), edgeType, rrect);
}
- return nullptr;
+ return GrFPFailure(std::move(inputFP));
}
}
}
-
- return nullptr;
+ return GrFPFailure(std::move(inputFP));
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.h b/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.h
index 426cb8f3c2c..e61246fdd94 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.h
@@ -11,8 +11,8 @@
#include "include/core/SkRefCnt.h"
#include "include/gpu/GrTypes.h"
#include "include/private/GrTypesPriv.h"
+#include "src/gpu/GrFragmentProcessor.h"
-class GrFragmentProcessor;
class GrShaderCaps;
class GrProcessor;
class SkRRect;
@@ -21,9 +21,11 @@ namespace GrRRectEffect {
/**
* Creates an effect that performs anti-aliased clipping against a SkRRect. It doesn't support
- * all varieties of SkRRect so the caller must check for a nullptr return.
+ * all varieties of SkRRect, so the caller must check `success` in the GrFPResult.
*/
-std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRRect&, const GrShaderCaps&);
+GrFPResult Make(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType, const SkRRect&,
+ const GrShaderCaps&);
+
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/GrRectBlurEffect.fp b/chromium/third_party/skia/src/gpu/effects/GrRectBlurEffect.fp
index ec11611dda9..56cd64fcb7d 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrRectBlurEffect.fp
+++ b/chromium/third_party/skia/src/gpu/effects/GrRectBlurEffect.fp
@@ -17,8 +17,10 @@
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrShaderCaps.h"
+#include "src/gpu/effects/GrTextureEffect.h"
}
+in fragmentProcessor? inputFP;
in float4 rect;
layout(key) bool highp = abs(rect.x) > 16000 || abs(rect.y) > 16000 ||
@@ -27,17 +29,20 @@ layout(key) bool highp = abs(rect.x) > 16000 || abs(rect.y) > 16000 ||
layout(when= highp) uniform float4 rectF;
layout(when=!highp) uniform half4 rectH;
-// Texture that is a LUT for integral of normal distribution. The value at x (where x is a texture
-// coord between 0 and 1) is the integral from -inf to (3 * sigma * (-2 * x - 1)). I.e. x is mapped
-// 0 3*sigma to -3 sigma. The flip saves a reversal in the shader.
-in uniform sampler2D integral;
-// Used to produce normalized texture coords for lookups in 'integral'
-in uniform half invSixSigma;
+// Effect that is a LUT for integral of normal distribution. The value at x:[0,6*sigma] is the
+// integral from -inf to (3*sigma - x). I.e. x is mapped from [0, 6*sigma] to [3*sigma to -3*sigma].
+// The flip saves a reversal in the shader.
+in fragmentProcessor integral;
// There is a fast variant of the effect that does 2 texture lookups and a more general one for
// wider blurs relative to rect sizes that does 4.
layout(key) in bool isFast;
+@optimizationFlags {
+ (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag
+}
+
@constructorParams {
GrSamplerState samplerParams
}
@@ -45,8 +50,10 @@ layout(key) in bool isFast;
@samplerParams(integral) {
samplerParams
}
+
@class {
-static GrSurfaceProxyView CreateIntegralTexture(GrRecordingContext* context, float sixSigma) {
+static std::unique_ptr<GrFragmentProcessor> MakeIntegralFP(GrRecordingContext* context,
+ float sixSigma) {
// The texture we're producing represents the integral of a normal distribution over a six-sigma
// range centered at zero. We want enough resolution so that the linear interpolation done in
// texture lookup doesn't introduce noticeable artifacts. We conservatively choose to have 2
@@ -61,11 +68,15 @@ static GrSurfaceProxyView CreateIntegralTexture(GrRecordingContext* context, flo
builder[0] = width;
builder.finish();
+ SkMatrix m = SkMatrix::Scale(width/sixSigma, 1.f);
+
GrProxyProvider* proxyProvider = context->priv().proxyProvider();
if (sk_sp<GrTextureProxy> proxy = proxyProvider->findOrCreateProxyByUniqueKey(key)) {
GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(proxy->backendFormat(),
GrColorType::kAlpha_8);
- return {std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle};
+ GrSurfaceProxyView view{std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle};
+ return GrTextureEffect::Make(
+ std::move(view), kPremul_SkAlphaType, m, GrSamplerState::Filter::kBilerp);
}
SkBitmap bitmap;
@@ -90,12 +101,14 @@ static GrSurfaceProxyView CreateIntegralTexture(GrRecordingContext* context, flo
}
SkASSERT(view.origin() == kTopLeft_GrSurfaceOrigin);
proxyProvider->assignUniqueKeyToProxy(key, view.asTextureProxy());
- return view;
+ return GrTextureEffect::Make(
+ std::move(view), kPremul_SkAlphaType, m, GrSamplerState::Filter::kBilerp);
}
}
@make {
- static std::unique_ptr<GrFragmentProcessor> Make(GrRecordingContext* context,
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrRecordingContext* context,
const GrShaderCaps& caps,
const SkRect& rect, float sigma) {
SkASSERT(rect.isSorted());
@@ -110,7 +123,7 @@ static GrSurfaceProxyView CreateIntegralTexture(GrRecordingContext* context, flo
}
const float sixSigma = 6 * sigma;
- GrSurfaceProxyView integral = CreateIntegralTexture(context, sixSigma);
+ std::unique_ptr<GrFragmentProcessor> integral = MakeIntegralFP(context, sixSigma);
if (!integral) {
return nullptr;
}
@@ -130,71 +143,61 @@ static GrSurfaceProxyView CreateIntegralTexture(GrRecordingContext* context, flo
// less than 6 sigma wide then things aren't so simple and we have to consider both the
// left and right edge of the rectangle (and similar in y).
bool isFast = insetRect.isSorted();
- // 1 / (6 * sigma) is the domain of the integral texture. We use the inverse to produce
- // normalized texture coords from frag coord distances.
- float invSixSigma = 1.f / sixSigma;
- return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect(insetRect,
- std::move(integral), invSixSigma, isFast, GrSamplerState::Filter::kBilerp));
+ return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect(
+ std::move(inputFP), insetRect, std::move(integral),
+ isFast, GrSamplerState::Filter::kBilerp));
}
}
void main() {
- half xCoverage, yCoverage;
- @if (isFast) {
- // Get the smaller of the signed distance from the frag coord to the left and right
- // edges and similar for y.
- // The integral texture goes "backwards" (from 3*sigma to -3*sigma), So, the below
- // computations align the left edge of the integral texture with the inset rect's edge
- // extending outward 6 * sigma from the inset rect.
- half x, y;
- @if (highp) {
- x = max(half(rectF.x - sk_FragCoord.x), half(sk_FragCoord.x - rectF.z));
- y = max(half(rectF.y - sk_FragCoord.y), half(sk_FragCoord.y - rectF.w));
- } else {
- x = max(half(rectH.x - sk_FragCoord.x), half(sk_FragCoord.x - rectH.z));
- y = max(half(rectH.y - sk_FragCoord.y), half(sk_FragCoord.y - rectH.w));
- }
- xCoverage = sample(integral, half2(x * invSixSigma, 0.5)).a;
- yCoverage = sample(integral, half2(y * invSixSigma, 0.5)).a;
- sk_OutColor = sk_InColor * xCoverage * yCoverage;
+ half xCoverage, yCoverage;
+ @if (isFast) {
+ // Get the smaller of the signed distance from the frag coord to the left and right
+ // edges and similar for y.
+ // The integral texture goes "backwards" (from 3*sigma to -3*sigma), So, the below
+ // computations align the left edge of the integral texture with the inset rect's edge
+ // extending outward 6 * sigma from the inset rect.
+ half2 xy;
+ @if (highp) {
+ xy = max(half2(rectF.LT - sk_FragCoord.xy),
+ half2(sk_FragCoord.xy - rectF.RB));
+ } else {
+ xy = max(half2(rectH.LT - sk_FragCoord.xy),
+ half2(sk_FragCoord.xy - rectH.RB));
+ }
+ xCoverage = sample(integral, half2(xy.x, 0.5)).a;
+ yCoverage = sample(integral, half2(xy.y, 0.5)).a;
+ } else {
+ // We just consider just the x direction here. In practice we compute x and y separately
+ // and multiply them together.
+ // We define our coord system so that the point at which we're evaluating a kernel
+ // defined by the normal distribution (K) at 0. In this coord system let L be left
+ // edge and R be the right edge of the rectangle.
+ // We can calculate C by integrating K with the half infinite ranges outside the L to R
+ // range and subtracting from 1:
+ // C = 1 - <integral of K from from -inf to L> - <integral of K from R to inf>
+ // K is symmetric about x=0 so:
+ // C = 1 - <integral of K from from -inf to L> - <integral of K from -inf to -R>
+
+ // The integral texture goes "backwards" (from 3*sigma to -3*sigma) which is factored
+ // in to the below calculations.
+ // Also, our rect uniform was pre-inset by 3 sigma from the actual rect being blurred,
+ // also factored in.
+ half4 rect;
+ @if (highp) {
+ rect.LT = half2(rectF.LT - sk_FragCoord.xy);
+ rect.RB = half2(sk_FragCoord.xy - rectF.RB);
} else {
- // We just consider just the x direction here. In practice we compute x and y separately
- // and multiply them together.
- // We define our coord system so that the point at which we're evaluating a kernel
- // defined by the normal distribution (K) as 0. In this coord system let L be left
- // edge and R be the right edge of the rectangle.
- // We can calculate C by integrating K with the half infinite ranges outside the L to R
- // range and subtracting from 1:
- // C = 1 - <integral of K from from -inf to L> - <integral of K from R to inf>
- // K is symmetric about x=0 so:
- // C = 1 - <integral of K from from -inf to L> - <integral of K from -inf to -R>
-
- // The integral texture goes "backwards" (from 3*sigma to -3*sigma) which is factored
- // in to the below calculations.
- // Also, our rect uniform was pre-inset by 3 sigma from the actual rect being blurred,
- // also factored in.
- half l, r, t, b;
- @if (highp) {
- l = half(sk_FragCoord.x - rectF.x);
- r = half(rectF.z - sk_FragCoord.x);
- t = half(sk_FragCoord.y - rectF.y);
- b = half(rectF.w - sk_FragCoord.y);
- } else {
- l = half(sk_FragCoord.x - rectH.x);
- r = half(rectH.z - sk_FragCoord.x);
- t = half(sk_FragCoord.y - rectH.y);
- b = half(rectH.w - sk_FragCoord.y);
- }
- half il = 1 + l * invSixSigma;
- half ir = 1 + r * invSixSigma;
- half it = 1 + t * invSixSigma;
- half ib = 1 + b * invSixSigma;
- xCoverage = 1 - sample(integral, half2(il, 0.5)).a
- - sample(integral, half2(ir, 0.5)).a;
- yCoverage = 1 - sample(integral, half2(it, 0.5)).a
- - sample(integral, half2(ib, 0.5)).a;
+ rect.LT = half2(rectH.LT - sk_FragCoord.xy);
+ rect.RB = half2(sk_FragCoord.xy - rectH.RB);
}
- sk_OutColor = sk_InColor * xCoverage * yCoverage;
+ xCoverage = 1 - sample(integral, half2(rect.L, 0.5)).a
+ - sample(integral, half2(rect.R, 0.5)).a;
+ yCoverage = 1 - sample(integral, half2(rect.T, 0.5)).a
+ - sample(integral, half2(rect.B, 0.5)).a;
+ }
+ half4 inputColor = sample(inputFP, sk_InColor);
+ sk_OutColor = inputColor * xCoverage * yCoverage;
}
@setData(pdman) {
@@ -202,12 +205,10 @@ void main() {
pdman.set4fv(highp ? rectF : rectH, 1, r);
}
-@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag }
-
@test(data) {
float sigma = data->fRandom->nextRangeF(3,8);
float width = data->fRandom->nextRangeF(200,300);
float height = data->fRandom->nextRangeF(200,300);
- return GrRectBlurEffect::Make(data->context(), *data->caps()->shaderCaps(),
+ return GrRectBlurEffect::Make(/*inputFP=*/nullptr, data->context(), *data->caps()->shaderCaps(),
SkRect::MakeWH(width, height), sigma);
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrShadowGeoProc.cpp b/chromium/third_party/skia/src/gpu/effects/GrShadowGeoProc.cpp
index de6db266441..d129a7d2ff0 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrShadowGeoProc.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrShadowGeoProc.cpp
@@ -22,7 +22,6 @@ public:
const GrRRectShadowGeoProc& rsgp = args.fGP.cast<GrRRectShadowGeoProc>();
GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
- GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
// emit attributes
@@ -35,13 +34,7 @@ public:
// Setup position
this->writeOutputPosition(vertBuilder, gpArgs, rsgp.inPosition().name());
-
- // emit transforms
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- rsgp.inPosition().asShaderVar(),
- args.fFPCoordTransformHandler);
+ // No need for local coordinates, this GP does not combine with fragment processors
fragBuilder->codeAppend("half d = length(shadowParams.xy);");
fragBuilder->codeAppend("float2 uv = float2(shadowParams.z * (1.0 - d), 0.5);");
@@ -53,7 +46,7 @@ public:
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
const CoordTransformRange& transformRange) override {
- this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
}
private:
diff --git a/chromium/third_party/skia/src/gpu/effects/GrSkSLFP.cpp b/chromium/third_party/skia/src/gpu/effects/GrSkSLFP.cpp
index a2e9b465d64..b2ed34f653c 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrSkSLFP.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrSkSLFP.cpp
@@ -198,8 +198,7 @@ const char* GrSkSLFP::name() const {
}
void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child) {
- child->setSampledWithExplicitCoords();
- this->registerChildProcessor(std::move(child));
+ this->registerExplicitlySampledChild(std::move(child));
}
GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const {
@@ -259,6 +258,7 @@ GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSkSLFP);
#include "include/effects/SkArithmeticImageFilter.h"
#include "include/effects/SkOverdrawColorFilter.h"
#include "include/gpu/GrContext.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/gpu/effects/generated/GrConstColorProcessor.h"
extern const char* SKSL_ARITHMETIC_SRC;
@@ -284,7 +284,7 @@ std::unique_ptr<GrFragmentProcessor> GrSkSLFP::TestCreate(GrProcessorTestData* d
auto result = GrSkSLFP::Make(d->context(), effect, "Arithmetic",
SkData::MakeWithCopy(&inputs, sizeof(inputs)));
result->addChild(GrConstColorProcessor::Make(
- SK_PMColor4fWHITE, GrConstColorProcessor::InputMode::kIgnore));
+ /*inputFP=*/nullptr, SK_PMColor4fWHITE, GrConstColorProcessor::InputMode::kIgnore));
return std::unique_ptr<GrFragmentProcessor>(result.release());
}
case 2: {
@@ -292,8 +292,8 @@ std::unique_ptr<GrFragmentProcessor> GrSkSLFP::TestCreate(GrProcessorTestData* d
for (SkColor& c : colors) {
c = d->fRandom->nextU();
}
- return SkOverdrawColorFilter::MakeWithSkColors(colors)
- ->asFragmentProcessor(d->context(), GrColorInfo{});
+ auto filter = SkOverdrawColorFilter::MakeWithSkColors(colors);
+ return as_CFB(filter)->asFragmentProcessor(d->context(), GrColorInfo{});
}
}
SK_ABORT("unreachable");
diff --git a/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.cpp
index b2ed99eea71..5113cbf8137 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.cpp
@@ -9,7 +9,7 @@
#include "src/gpu/GrTexture.h"
#include "src/gpu/GrTexturePriv.h"
-#include "src/gpu/effects/generated/GrMatrixEffect.h"
+#include "src/gpu/effects/GrMatrixEffect.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
@@ -110,7 +110,7 @@ GrTextureEffect::Sampling::Sampling(const GrSurfaceProxy& proxy,
r.fShaderSubset = r.fShaderClamp = {0, 0};
return r;
}
- r.fShaderMode = static_cast<ShaderMode>(mode);
+ r.fShaderMode = GetShaderMode(mode, filter);
r.fHWMode = Mode::kClamp;
return r;
};
@@ -142,8 +142,7 @@ bool GrTextureEffect::Sampling::hasBorderAlpha() const {
fHWSampler.wrapModeY() == GrSamplerState::WrapMode::kClampToBorder) {
return true;
}
- if (fShaderModes[0] == ShaderMode::kClampToBorder ||
- fShaderModes[1] == ShaderMode::kClampToBorder) {
+ if (ShaderModeIsClampToBorder(fShaderModes[0]) || ShaderModeIsClampToBorder(fShaderModes[1])) {
return fBorder[3] < 1.f;
}
return false;
@@ -196,7 +195,7 @@ std::unique_ptr<GrFragmentProcessor> GrTextureEffect::Make(GrSurfaceProxyView vi
SkMatrix final;
bool lazyProxyNormalization;
get_matrix(matrix, view, &final, &lazyProxyNormalization);
- return GrMatrixEffect::Apply(final, std::unique_ptr<GrFragmentProcessor>(
+ return GrMatrixEffect::Make(final, std::unique_ptr<GrFragmentProcessor>(
new GrTextureEffect(std::move(view),
alphaType,
Sampling(filter),
@@ -214,7 +213,7 @@ std::unique_ptr<GrFragmentProcessor> GrTextureEffect::Make(GrSurfaceProxyView vi
SkMatrix final;
bool lazyProxyNormalization;
get_matrix(matrix, view, &final, &lazyProxyNormalization);
- return GrMatrixEffect::Apply(final, std::unique_ptr<GrFragmentProcessor>(
+ return GrMatrixEffect::Make(final, std::unique_ptr<GrFragmentProcessor>(
new GrTextureEffect(std::move(view),
alphaType,
sampling,
@@ -232,7 +231,7 @@ std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeSubset(GrSurfaceProxyV
SkMatrix final;
bool lazyProxyNormalization;
get_matrix(matrix, view, &final, &lazyProxyNormalization);
- return GrMatrixEffect::Apply(final, std::unique_ptr<GrFragmentProcessor>(
+ return GrMatrixEffect::Make(final, std::unique_ptr<GrFragmentProcessor>(
new GrTextureEffect(std::move(view),
alphaType,
sampling,
@@ -251,37 +250,41 @@ std::unique_ptr<GrFragmentProcessor> GrTextureEffect::MakeSubset(GrSurfaceProxyV
SkMatrix final;
bool lazyProxyNormalization;
get_matrix(matrix, view, &final, &lazyProxyNormalization);
- return GrMatrixEffect::Apply(final, std::unique_ptr<GrFragmentProcessor>(
+ return GrMatrixEffect::Make(final, std::unique_ptr<GrFragmentProcessor>(
new GrTextureEffect(std::move(view),
alphaType,
sampling,
lazyProxyNormalization)));
}
-GrTextureEffect::FilterLogic GrTextureEffect::GetFilterLogic(ShaderMode mode,
- GrSamplerState::Filter filter) {
+GrTextureEffect::ShaderMode GrTextureEffect::GetShaderMode(GrSamplerState::WrapMode mode,
+ GrSamplerState::Filter filter) {
switch (mode) {
- case ShaderMode::kMirrorRepeat:
- case ShaderMode::kNone:
- case ShaderMode::kClamp:
- return FilterLogic::kNone;
- case ShaderMode::kRepeat:
+ case GrSamplerState::WrapMode::kMirrorRepeat:
+ return ShaderMode::kMirrorRepeat;
+ case GrSamplerState::WrapMode::kClamp:
+ return ShaderMode::kClamp;
+ case GrSamplerState::WrapMode::kRepeat:
switch (filter) {
case GrSamplerState::Filter::kNearest:
- return FilterLogic::kNone;
+ return ShaderMode::kRepeatNearest;
case GrSamplerState::Filter::kBilerp:
- return FilterLogic::kRepeatBilerp;
+ return ShaderMode::kRepeatBilerp;
case GrSamplerState::Filter::kMipMap:
- return FilterLogic::kRepeatMipMap;
+ return ShaderMode::kRepeatMipMap;
}
SkUNREACHABLE;
- case ShaderMode::kClampToBorder:
- return filter > GrSamplerState::Filter::kNearest ? FilterLogic::kClampToBorderFilter
- : FilterLogic::kClampToBorderNearest;
+ case GrSamplerState::WrapMode::kClampToBorder:
+ return filter == GrSamplerState::Filter::kNearest ? ShaderMode::kClampToBorderNearest
+ : ShaderMode::kClampToBorderFilter;
}
SkUNREACHABLE;
}
+inline bool GrTextureEffect::ShaderModeIsClampToBorder(ShaderMode m) {
+ return m == ShaderMode::kClampToBorderNearest || m == ShaderMode::kClampToBorderFilter;
+}
+
GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
class Impl : public GrGLSLFragmentProcessor {
UniformHandle fSubsetUni;
@@ -300,10 +303,18 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
}
auto* fb = args.fFragBuilder;
if (te.sampleMatrix().fKind == SkSL::SampleMatrix::Kind::kMixed) {
+ // FIXME this is very similar to the extra logic in
+ // GrGLSLFragmentShaderBuilder::ensureCoords2D
args.fUniformHandler->writeUniformMappings(te.sampleMatrix().fOwner, fb);
- coords = SkStringPrintf("(%s * _matrix * float3(%s, 1)).xy",
- te.sampleMatrix().fExpression.c_str(),
- coords.c_str());
+ SkString coords2D;
+ coords2D.printf("%s_teSample", coords.c_str());
+
+ fb->codeAppendf("float3 %s_3d = %s * _matrix * %s.xy1;\n",
+ coords2D.c_str(), te.sampleMatrix().fExpression.c_str(),
+ coords.c_str());
+ fb->codeAppendf("float2 %s = %s_3d.xy / %s_3d.z;\n",
+ coords2D.c_str(), coords2D.c_str(), coords2D.c_str());
+ coords = coords2D;
}
if (te.fShaderModes[0] == ShaderMode::kNone &&
te.fShaderModes[1] == ShaderMode::kNone) {
@@ -354,24 +365,55 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
const auto& m = te.fShaderModes;
GrTextureType textureType = te.fSampler.proxy()->backendFormat().textureType();
bool normCoords = textureType != GrTextureType::kRectangle;
- auto filter = te.fSampler.samplerState().filter();
- FilterLogic filterLogic[2] = {GetFilterLogic(m[0], filter),
- GetFilterLogic(m[1], filter)};
const char* borderName = nullptr;
- if (te.fShaderModes[0] == ShaderMode::kClampToBorder ||
- te.fShaderModes[1] == ShaderMode::kClampToBorder) {
+ if (te.hasClampToBorderShaderMode()) {
fBorderUni = args.fUniformHandler->addUniform(
&te, kFragment_GrShaderFlag, kHalf4_GrSLType, "border", &borderName);
}
auto modeUsesSubset = [](ShaderMode m) {
- return m == ShaderMode::kRepeat || m == ShaderMode::kMirrorRepeat ||
- m == ShaderMode::kClampToBorder;
+ switch (m) {
+ case ShaderMode::kNone: return false;
+ case ShaderMode::kClamp: return false;
+ case ShaderMode::kRepeatNearest: return true;
+ case ShaderMode::kRepeatBilerp: return true;
+ case ShaderMode::kRepeatMipMap: return true;
+ case ShaderMode::kMirrorRepeat: return true;
+ case ShaderMode::kClampToBorderNearest: return true;
+ case ShaderMode::kClampToBorderFilter: return true;
+ }
+ SkUNREACHABLE;
+ };
+
+ auto modeUsesClamp = [](ShaderMode m) {
+ switch (m) {
+ case ShaderMode::kNone: return false;
+ case ShaderMode::kClamp: return true;
+ case ShaderMode::kRepeatNearest: return true;
+ case ShaderMode::kRepeatBilerp: return true;
+ case ShaderMode::kRepeatMipMap: return true;
+ case ShaderMode::kMirrorRepeat: return true;
+ case ShaderMode::kClampToBorderNearest: return false;
+ case ShaderMode::kClampToBorderFilter: return true;
+ }
+ SkUNREACHABLE;
};
- auto modeUsesClamp = [filter](ShaderMode m) {
- return m != ShaderMode::kNone &&
- (m != ShaderMode::kClampToBorder || filter > Filter::kNearest);
+ // To keep things a little simpler, when we have filtering logic in the shader we
+ // operate on unnormalized texture coordinates. We will add a uniform that stores
+ // {w, h, 1/w, 1/h} in a float4 below.
+ auto modeRequiresUnormCoords = [](ShaderMode m) {
+ switch (m) {
+ case ShaderMode::kNone: return false;
+ case ShaderMode::kClamp: return false;
+ case ShaderMode::kRepeatNearest: return false;
+ case ShaderMode::kRepeatBilerp: return true;
+ case ShaderMode::kRepeatMipMap: return true;
+ case ShaderMode::kMirrorRepeat: return false;
+ case ShaderMode::kClampToBorderNearest: return true;
+ case ShaderMode::kClampToBorderFilter: return true;
+ }
+ SkUNREACHABLE;
};
bool useSubset[2] = {modeUsesSubset(m[0]), modeUsesSubset(m[1])};
@@ -389,12 +431,9 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
&te, kFragment_GrShaderFlag, kFloat4_GrSLType, "clamp", &clampName);
}
- // To keep things a little simpler, when we have filtering logic in the shader we
- // operate on unnormalized texture coordinates. We add a uniform that stores
- // {w, h, 1/w, 1/h} in a float4.
const char* norm = nullptr;
- if (normCoords && (filterLogic[0] != FilterLogic::kNone ||
- filterLogic[1] != FilterLogic::kNone)) {
+ if (normCoords && (modeRequiresUnormCoords(m[0]) ||
+ modeRequiresUnormCoords(m[1]))) {
// TODO: Detect support for textureSize() or polyfill textureSize() in SkSL and
// always use?
fNormUni = args.fUniformHandler->addUniform(&te, kFragment_GrShaderFlag,
@@ -428,55 +467,56 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
// These modes either don't use the subset rect or don't need to map the
// coords to be within the subset.
case ShaderMode::kNone:
- case ShaderMode::kClampToBorder:
+ case ShaderMode::kClampToBorderNearest:
+ case ShaderMode::kClampToBorderFilter:
case ShaderMode::kClamp:
fb->codeAppendf("subsetCoord.%s = inCoord.%s;", coordSwizzle,
coordSwizzle);
break;
- case ShaderMode::kRepeat:
- if (filter == Filter::kMipMap) {
- // The approach here is to generate two sets of texture coords that
- // are both "moving" at the same speed (if not direction) as
- // inCoords. We accomplish that by using two out of phase mirror
- // repeat coords. We will always sample using both coords but the
- // read from the upward sloping one is selected using a weight
- // that transitions from one set to the other near the reflection
- // point. Like the coords, the weight is a saw-tooth function,
- // phase-shifted, vertically translated, and then clamped to 0..1.
- // TODO: Skip this and use textureGrad() when available.
- SkASSERT(extraCoord);
- SkASSERT(coordWeight);
- fb->codeAppend("{");
- fb->codeAppendf("float w = %s.%s - %s.%s;", subsetName,
- subsetStopSwizzle, subsetName, subsetStartSwizzle);
- fb->codeAppendf("float w2 = 2 * w;");
- fb->codeAppendf("float d = inCoord.%s - %s.%s;", coordSwizzle,
- subsetName, subsetStartSwizzle);
- fb->codeAppend("float m = mod(d, w2);");
- fb->codeAppend("float o = mix(m, w2 - m, step(w, m));");
- fb->codeAppendf("subsetCoord.%s = o + %s.%s;", coordSwizzle,
- subsetName, subsetStartSwizzle);
- fb->codeAppendf("%s = w - o + %s.%s;", extraCoord, subsetName,
- subsetStartSwizzle);
- // coordWeight is used as the third param of mix() to blend between a
- // sample taken using subsetCoord and a sample at extraCoord.
- fb->codeAppend("float hw = w/2;");
- fb->codeAppend("float n = mod(d - hw, w2);");
- fb->codeAppendf(
- "%s = saturate(half(mix(n, w2 - n, step(w, n)) - hw + "
- "0.5));",
- coordWeight);
- fb->codeAppend("}");
- } else {
- fb->codeAppendf(
- "subsetCoord.%s = mod(inCoord.%s - %s.%s, %s.%s - %s.%s) + "
- "%s.%s;",
- coordSwizzle, coordSwizzle, subsetName, subsetStartSwizzle,
- subsetName, subsetStopSwizzle, subsetName,
- subsetStartSwizzle, subsetName, subsetStartSwizzle);
- }
+ case ShaderMode::kRepeatNearest:
+ case ShaderMode::kRepeatBilerp:
+ fb->codeAppendf(
+ "subsetCoord.%s = mod(inCoord.%s - %s.%s, %s.%s - %s.%s) + "
+ "%s.%s;",
+ coordSwizzle, coordSwizzle, subsetName, subsetStartSwizzle,
+ subsetName, subsetStopSwizzle, subsetName, subsetStartSwizzle,
+ subsetName, subsetStartSwizzle);
+ break;
+ case ShaderMode::kRepeatMipMap:
+ // The approach here is to generate two sets of texture coords that
+ // are both "moving" at the same speed (if not direction) as
+ // inCoords. We accomplish that by using two out of phase mirror
+ // repeat coords. We will always sample using both coords but the
+ // read from the upward sloping one is selected using a weight
+ // that transitions from one set to the other near the reflection
+ // point. Like the coords, the weight is a saw-tooth function,
+ // phase-shifted, vertically translated, and then clamped to 0..1.
+ // TODO: Skip this and use textureGrad() when available.
+ SkASSERT(extraCoord);
+ SkASSERT(coordWeight);
+ fb->codeAppend("{");
+ fb->codeAppendf("float w = %s.%s - %s.%s;", subsetName,
+ subsetStopSwizzle, subsetName, subsetStartSwizzle);
+ fb->codeAppendf("float w2 = 2 * w;");
+ fb->codeAppendf("float d = inCoord.%s - %s.%s;", coordSwizzle,
+ subsetName, subsetStartSwizzle);
+ fb->codeAppend("float m = mod(d, w2);");
+ fb->codeAppend("float o = mix(m, w2 - m, step(w, m));");
+ fb->codeAppendf("subsetCoord.%s = o + %s.%s;", coordSwizzle, subsetName,
+ subsetStartSwizzle);
+ fb->codeAppendf("%s = w - o + %s.%s;", extraCoord, subsetName,
+ subsetStartSwizzle);
+ // coordWeight is used as the third param of mix() to blend between a
+ // sample taken using subsetCoord and a sample at extraCoord.
+ fb->codeAppend("float hw = w/2;");
+ fb->codeAppend("float n = mod(d - hw, w2);");
+ fb->codeAppendf(
+ "%s = saturate(half(mix(n, w2 - n, step(w, n)) - hw + "
+ "0.5));",
+ coordWeight);
+ fb->codeAppend("}");
break;
- case ShaderMode::kMirrorRepeat: {
+ case ShaderMode::kMirrorRepeat:
fb->codeAppend("{");
fb->codeAppendf("float w = %s.%s - %s.%s;", subsetName,
subsetStopSwizzle, subsetName, subsetStartSwizzle);
@@ -487,7 +527,6 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
coordSwizzle, subsetName, subsetStartSwizzle);
fb->codeAppend("}");
break;
- }
}
};
@@ -510,12 +549,12 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
const char* repeatCoordWeightX = nullptr;
const char* extraRepeatCoordY = nullptr;
const char* repeatCoordWeightY = nullptr;
- if (filterLogic[0] == FilterLogic::kRepeatMipMap) {
+ if (m[0] == ShaderMode::kRepeatMipMap) {
fb->codeAppend("float extraRepeatCoordX; half repeatCoordWeightX;");
extraRepeatCoordX = "extraRepeatCoordX";
repeatCoordWeightX = "repeatCoordWeightX";
}
- if (filterLogic[1] == FilterLogic::kRepeatMipMap) {
+ if (m[1] == ShaderMode::kRepeatMipMap) {
fb->codeAppend("float extraRepeatCoordY; half repeatCoordWeightY;");
extraRepeatCoordY = "extraRepeatCoordY";
repeatCoordWeightY = "repeatCoordWeightY";
@@ -532,11 +571,11 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
clampCoord(useClamp[1], "y", "y", "w");
// Additional clamping for the extra coords for kRepeatMipMap.
- if (filterLogic[0] == FilterLogic::kRepeatMipMap) {
+ if (m[0] == ShaderMode::kRepeatMipMap) {
fb->codeAppendf("extraRepeatCoordX = clamp(extraRepeatCoordX, %s.x, %s.z);",
clampName, clampName);
}
- if (filterLogic[1] == FilterLogic::kRepeatMipMap) {
+ if (m[1] == ShaderMode::kRepeatMipMap) {
fb->codeAppendf("extraRepeatCoordY = clamp(extraRepeatCoordY, %s.y, %s.w);",
clampName, clampName);
}
@@ -544,8 +583,7 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
// Do the 2 or 4 texture reads for kRepeatMipMap and then apply the weight(s)
// to blend between them. If neither direction is kRepeatMipMap do a single
// read at clampedCoord.
- if (filterLogic[0] == FilterLogic::kRepeatMipMap &&
- filterLogic[1] == FilterLogic::kRepeatMipMap) {
+ if (m[0] == ShaderMode::kRepeatMipMap && m[1] == ShaderMode::kRepeatMipMap) {
fb->codeAppendf(
"half4 textureColor ="
" mix(mix(%s, %s, repeatCoordWeightX),"
@@ -556,11 +594,11 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
read("float2(clampedCoord.x, extraRepeatCoordY)").c_str(),
read("float2(extraRepeatCoordX, extraRepeatCoordY)").c_str());
- } else if (filterLogic[0] == FilterLogic::kRepeatMipMap) {
+ } else if (m[0] == ShaderMode::kRepeatMipMap) {
fb->codeAppendf("half4 textureColor = mix(%s, %s, repeatCoordWeightX);",
read("clampedCoord").c_str(),
read("float2(extraRepeatCoordX, clampedCoord.y)").c_str());
- } else if (filterLogic[1] == FilterLogic::kRepeatMipMap) {
+ } else if (m[1] == ShaderMode::kRepeatMipMap) {
fb->codeAppendf("half4 textureColor = mix(%s, %s, repeatCoordWeightY);",
read("clampedCoord").c_str(),
read("float2(clampedCoord.x, extraRepeatCoordY)").c_str());
@@ -575,15 +613,13 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
// Calculate the amount the coord moved for clamping. This will be used
// to implement shader-based filtering for kClampToBorder and kRepeat.
- if (filterLogic[0] == FilterLogic::kRepeatBilerp ||
- filterLogic[0] == FilterLogic::kClampToBorderFilter) {
+ if (m[0] == ShaderMode::kRepeatBilerp || m[0] == ShaderMode::kClampToBorderFilter) {
fb->codeAppend("half errX = half(subsetCoord.x - clampedCoord.x);");
fb->codeAppendf("float repeatCoordX = errX > 0 ? %s.x : %s.z;", clampName,
clampName);
repeatBilerpReadX = read("float2(repeatCoordX, clampedCoord.y)");
}
- if (filterLogic[1] == FilterLogic::kRepeatBilerp ||
- filterLogic[1] == FilterLogic::kClampToBorderFilter) {
+ if (m[1] == ShaderMode::kRepeatBilerp || m[1] == ShaderMode::kClampToBorderFilter) {
fb->codeAppend("half errY = half(subsetCoord.y - clampedCoord.y);");
fb->codeAppendf("float repeatCoordY = errY > 0 ? %s.y : %s.w;", clampName,
clampName);
@@ -595,8 +631,7 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
// or a corner. Then blend the multiple reads using the err values calculated
// above.
const char* ifStr = "if";
- if (filterLogic[0] == FilterLogic::kRepeatBilerp &&
- filterLogic[1] == FilterLogic::kRepeatBilerp) {
+ if (m[0] == ShaderMode::kRepeatBilerp && m[1] == ShaderMode::kRepeatBilerp) {
auto repeatBilerpReadXY = read("float2(repeatCoordX, repeatCoordY)");
fb->codeAppendf(
"if (errX != 0 && errY != 0) {"
@@ -609,14 +644,14 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
repeatBilerpReadXY.c_str());
ifStr = "else if";
}
- if (filterLogic[0] == FilterLogic::kRepeatBilerp) {
+ if (m[0] == ShaderMode::kRepeatBilerp) {
fb->codeAppendf(
"%s (errX != 0) {"
" textureColor = mix(textureColor, %s, abs(errX));"
"}",
ifStr, repeatBilerpReadX.c_str());
}
- if (filterLogic[1] == FilterLogic::kRepeatBilerp) {
+ if (m[1] == ShaderMode::kRepeatBilerp) {
fb->codeAppendf(
"%s (errY != 0) {"
" textureColor = mix(textureColor, %s, abs(errY));"
@@ -626,27 +661,30 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
// Do soft edge shader filtering against border color for kClampToBorderFilter using
// the err values calculated above.
- if (filterLogic[0] == FilterLogic::kClampToBorderFilter) {
+ if (m[0] == ShaderMode::kClampToBorderFilter) {
fb->codeAppendf("textureColor = mix(textureColor, %s, min(abs(errX), 1));",
borderName);
}
- if (filterLogic[1] == FilterLogic::kClampToBorderFilter) {
+ if (m[1] == ShaderMode::kClampToBorderFilter) {
fb->codeAppendf("textureColor = mix(textureColor, %s, min(abs(errY), 1));",
borderName);
}
// Do hard-edge shader transition to border color for kClampToBorderNearest at the
- // subset boundaries.
- if (filterLogic[0] == FilterLogic::kClampToBorderNearest) {
+ // subset boundaries. Snap the input coordinates to nearest neighbor (with an
+ // epsilon) before comparing to the subset rect to avoid GPU interpolation errors
+ if (m[0] == ShaderMode::kClampToBorderNearest) {
fb->codeAppendf(
- "if (inCoord.x < %s.x || inCoord.x > %s.z) {"
+ "float snappedX = floor(inCoord.x + 0.001) + 0.5;"
+ "if (snappedX < %s.x || snappedX > %s.z) {"
" textureColor = %s;"
"}",
subsetName, subsetName, borderName);
}
- if (filterLogic[1] == FilterLogic::kClampToBorderNearest) {
+ if (m[1] == ShaderMode::kClampToBorderNearest) {
fb->codeAppendf(
- "if (inCoord.y < %s.y || inCoord.y > %s.w) {"
+ "float snappedY = floor(inCoord.y + 0.001) + 0.5;"
+ "if (snappedY < %s.y || snappedY > %s.w) {"
" textureColor = %s;"
"}",
subsetName, subsetName, borderName);
@@ -708,10 +746,7 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
void GrTextureEffect::onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const {
auto m0 = static_cast<uint32_t>(fShaderModes[0]);
auto m1 = static_cast<uint32_t>(fShaderModes[1]);
- auto filter = fSampler.samplerState().filter();
- auto l0 = static_cast<uint32_t>(GetFilterLogic(fShaderModes[0], filter));
- auto l1 = static_cast<uint32_t>(GetFilterLogic(fShaderModes[1], filter));
- b->add32((l0 << 24) | (l1 << 16) | (m0 << 8) | m1);
+ b->add32((m0 << 16) | m1);
}
bool GrTextureEffect::onIsEqual(const GrFragmentProcessor& other) const {
@@ -722,9 +757,7 @@ bool GrTextureEffect::onIsEqual(const GrFragmentProcessor& other) const {
if (fSubset != that.fSubset) {
return false;
}
- if ((fShaderModes[0] == ShaderMode::kClampToBorder ||
- fShaderModes[1] == ShaderMode::kClampToBorder) &&
- !std::equal(fBorder, fBorder + 4, that.fBorder)) {
+ if (this->hasClampToBorderShaderMode() && !std::equal(fBorder, fBorder + 4, that.fBorder)) {
return false;
}
return true;
diff --git a/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.h b/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.h
index c808bfb3018..47acda81472 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/GrTextureEffect.h
@@ -71,28 +71,24 @@ public:
const char* name() const override { return "TextureEffect"; }
private:
- enum class ShaderMode : uint16_t {
- kClamp = static_cast<int>(GrSamplerState::WrapMode::kClamp),
- kRepeat = static_cast<int>(GrSamplerState::WrapMode::kRepeat),
- kMirrorRepeat = static_cast<int>(GrSamplerState::WrapMode::kMirrorRepeat),
- kClampToBorder = static_cast<int>(GrSamplerState::WrapMode::kClampToBorder),
- kNone,
- };
-
struct Sampling;
/**
- * Sometimes the implementation of a ShaderMode depends on which GrSamplerState::Filter is
- * used.
+ * Possible implementation of wrap mode in shader code. Some modes are specialized by
+ * filter.
*/
- enum class FilterLogic {
- kNone, // The shader isn't specialized for the filter.
+ enum class ShaderMode : uint16_t {
+ kNone, // Using HW mode
+ kClamp, // Shader based clamp, no filter specialization
+ kRepeatNearest, // Simple repeat for nearest sampling
kRepeatBilerp, // Filter across the subset boundary for kRepeat mode
kRepeatMipMap, // Logic for LOD selection with kRepeat mode.
- kClampToBorderFilter, // Logic for fading to border color when filtering.
+ kMirrorRepeat, // Mirror repeat (doesn't depend on filter))
kClampToBorderNearest, // Logic for hard transition to border color when not filtering.
+ kClampToBorderFilter, // Logic for fading to border color when filtering.
};
- static FilterLogic GetFilterLogic(ShaderMode mode, GrSamplerState::Filter filter);
+ static ShaderMode GetShaderMode(GrSamplerState::WrapMode, GrSamplerState::Filter);
+ static bool ShaderModeIsClampToBorder(ShaderMode);
GrCoordTransform fCoordTransform;
TextureSampler fSampler;
@@ -115,6 +111,11 @@ private:
const TextureSampler& onTextureSampler(int) const override;
+ bool hasClampToBorderShaderMode() const {
+ return ShaderModeIsClampToBorder(fShaderModes[0]) ||
+ ShaderModeIsClampToBorder(fShaderModes[1]);
+ }
+
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
typedef GrFragmentProcessor INHERITED;
diff --git a/chromium/third_party/skia/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index 3d060a69fa9..fe09020845c 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -62,8 +62,8 @@ private:
SkBlendMode mode)
: INHERITED(kComposeTwoFragmentProcessor_ClassID, OptFlags(src.get(), dst.get(), mode))
, fMode(mode) {
- SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(std::move(src));
- SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(std::move(dst));
+ SkDEBUGCODE(int shaderAChildIndex = )this->registerChild(std::move(src));
+ SkDEBUGCODE(int shaderBChildIndex = )this->registerChild(std::move(dst));
SkASSERT(0 == shaderAChildIndex);
SkASSERT(1 == shaderBChildIndex);
}
@@ -245,7 +245,7 @@ std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoPro
SkBlendMode mode) {
switch (mode) {
case SkBlendMode::kClear:
- return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
+ return GrConstColorProcessor::Make(/*inputFP=*/nullptr, SK_PMColor4fTRANSPARENT,
GrConstColorProcessor::InputMode::kIgnore);
case SkBlendMode::kSrc:
return src;
@@ -413,7 +413,7 @@ private:
: INHERITED(kComposeOneFragmentProcessor_ClassID, OptFlags(fp.get(), mode, child))
, fMode(mode)
, fChild(child) {
- SkDEBUGCODE(int dstIndex =) this->registerChildProcessor(std::move(fp));
+ SkDEBUGCODE(int dstIndex =) this->registerChild(std::move(fp));
SkASSERT(0 == dstIndex);
}
@@ -496,7 +496,7 @@ std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstPro
std::unique_ptr<GrFragmentProcessor> dst, SkBlendMode mode) {
switch (mode) {
case SkBlendMode::kClear:
- return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
+ return GrConstColorProcessor::Make(/*inputFP=*/nullptr, SK_PMColor4fTRANSPARENT,
GrConstColorProcessor::InputMode::kIgnore);
case SkBlendMode::kSrc:
return nullptr;
@@ -510,7 +510,7 @@ std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcPro
std::unique_ptr<GrFragmentProcessor> src, SkBlendMode mode) {
switch (mode) {
case SkBlendMode::kClear:
- return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
+ return GrConstColorProcessor::Make(/*inputFP=*/nullptr, SK_PMColor4fTRANSPARENT,
GrConstColorProcessor::InputMode::kIgnore);
case SkBlendMode::kDst:
return nullptr;
diff --git a/chromium/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp
index 114f54b2aa6..ad0584a72b3 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.cpp
@@ -74,7 +74,7 @@ std::unique_ptr<GrFragmentProcessor> GrYUVtoRGBEffect::Make(GrSurfaceProxyView v
dimensions.height() == yDimensions.height() / 2 + 1) {
sy = 0.5f;
}
- *planeMatrix.writable() = SkMatrix::MakeScale(sx, sy);
+ *planeMatrix.writable() = SkMatrix::Scale(sx, sy);
planeMatrix.writable()->preConcat(localMatrix);
planeFilter = subsampledPlaneFilterMode;
if (subset) {
@@ -112,7 +112,7 @@ GrYUVtoRGBEffect::GrYUVtoRGBEffect(std::unique_ptr<GrFragmentProcessor> planeFPs
ModulateForClampedSamplerOptFlags(alpha_type(yuvaIndices)))
, fYUVColorSpace(yuvColorSpace) {
for (int i = 0; i < numPlanes; ++i) {
- this->registerChildProcessor(std::move(planeFPs[i]));
+ this->registerChild(std::move(planeFPs[i]));
}
std::copy_n(yuvaIndices, 4, fYUVAIndices);
}
@@ -251,10 +251,7 @@ bool GrYUVtoRGBEffect::onIsEqual(const GrFragmentProcessor& other) const {
GrYUVtoRGBEffect::GrYUVtoRGBEffect(const GrYUVtoRGBEffect& src)
: GrFragmentProcessor(kGrYUVtoRGBEffect_ClassID, src.optimizationFlags())
, fYUVColorSpace(src.fYUVColorSpace) {
- int numPlanes = src.numChildProcessors();
- for (int i = 0; i < numPlanes; ++i) {
- this->registerChildProcessor(this->childProcessor(i).clone());
- }
+ this->cloneAndRegisterAllChildProcessors(src);
std::copy_n(src.fYUVAIndices, this->numChildProcessors(), fYUVAIndices);
}
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.cpp
index 63f3a67364a..233c42a7d0e 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.cpp
@@ -28,34 +28,48 @@ public:
auto rect = _outer.rect;
(void)rect;
prevRect = float4(-1.0);
- rectUniformVar = args.fUniformHandler->addUniform(
- &_outer, kFragment_GrShaderFlag, kFloat4_GrSLType, "rectUniform");
+ rectUniformVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
+ kFloat4_GrSLType, "rectUniform");
fragBuilder->codeAppendf(
- "float4 prevRect = float4(%f, %f, %f, %f);\nhalf alpha;\n@switch (%d) {\n case "
- "0:\n case 2:\n alpha = half(all(greaterThan(float4(sk_FragCoord.xy, "
- "%s.zw), float4(%s.xy, sk_FragCoord.xy))) ? 1 : 0);\n break;\n "
- "default:\n half xSub, ySub;\n xSub = min(half(sk_FragCoord.x - "
- "%s.x), 0.0);\n xSub += min(half(%s.z - sk_FragCoord.x), 0.0);\n "
- "ySub = min(half(sk_FragCoord.y - %s.y), 0.0);\n ySub += min(half(%s.w - "
- "sk_FragCoord.y), 0.0);\n alpha = (1.0 + ",
- prevRect.left(),
- prevRect.top(),
- prevRect.right(),
- prevRect.bottom(),
- (int)_outer.edgeType,
- args.fUniformHandler->getUniformCStr(rectUniformVar),
+ R"SkSL(float4 prevRect = float4(%f, %f, %f, %f);
+half alpha;
+@switch (%d) {
+ case 0:
+ case 2:
+ alpha = half(all(greaterThan(float4(sk_FragCoord.xy, %s.zw), float4(%s.xy, sk_FragCoord.xy))) ? 1 : 0);
+ break;
+ default:
+ half xSub, ySub;
+ xSub = min(half(sk_FragCoord.x - %s.x), 0.0);
+ xSub += min(half(%s.z - sk_FragCoord.x), 0.0);
+ ySub = min(half(sk_FragCoord.y - %s.y), 0.0);
+ ySub += min(half(%s.w - sk_FragCoord.y), 0.0);
+ alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));
+}
+@if (%d == 2 || %d == 3) {
+ alpha = 1.0 - alpha;
+})SkSL",
+ prevRect.left(), prevRect.top(), prevRect.right(), prevRect.bottom(),
+ (int)_outer.edgeType, args.fUniformHandler->getUniformCStr(rectUniformVar),
args.fUniformHandler->getUniformCStr(rectUniformVar),
args.fUniformHandler->getUniformCStr(rectUniformVar),
args.fUniformHandler->getUniformCStr(rectUniformVar),
args.fUniformHandler->getUniformCStr(rectUniformVar),
- args.fUniformHandler->getUniformCStr(rectUniformVar));
+ args.fUniformHandler->getUniformCStr(rectUniformVar), (int)_outer.edgeType,
+ (int)_outer.edgeType);
+ SkString _input1677(args.fInputColor);
+ SkString _sample1677;
+ if (_outer.inputFP_index >= 0) {
+ _sample1677 = this->invokeChild(_outer.inputFP_index, _input1677.c_str(), args);
+ } else {
+ _sample1677.swap(_input1677);
+ }
fragBuilder->codeAppendf(
- "max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n}\n@if (%d == 2 || %d == 3) {\n "
- "alpha = 1.0 - alpha;\n}\n%s = %s * alpha;\n",
- (int)_outer.edgeType,
- (int)_outer.edgeType,
- args.fOutputColor,
- args.fInputColor);
+ R"SkSL(
+half4 inputColor = %s;
+%s = inputColor * alpha;
+)SkSL",
+ _sample1677.c_str(), args.fOutputColor);
}
private:
@@ -95,7 +109,11 @@ bool GrAARectEffect::onIsEqual(const GrFragmentProcessor& other) const {
GrAARectEffect::GrAARectEffect(const GrAARectEffect& src)
: INHERITED(kGrAARectEffect_ClassID, src.optimizationFlags())
, edgeType(src.edgeType)
- , rect(src.rect) {}
+ , rect(src.rect) {
+ if (src.inputFP_index >= 0) {
+ inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
+ }
+}
std::unique_ptr<GrFragmentProcessor> GrAARectEffect::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrAARectEffect(*this));
}
@@ -111,7 +129,7 @@ std::unique_ptr<GrFragmentProcessor> GrAARectEffect::TestCreate(GrProcessorTestD
GrClipEdgeType edgeType =
static_cast<GrClipEdgeType>(d->fRandom->nextULessThan(kGrClipEdgeTypeCnt));
- fp = GrAARectEffect::Make(edgeType, rect);
+ fp = GrAARectEffect::Make(/*inputFP=*/nullptr, edgeType, rect);
} while (nullptr == fp);
return fp;
}
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.h
index 42324b4c6dc..88891e443b5 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrAARectEffect.h
@@ -10,28 +10,42 @@
**************************************************************************************************/
#ifndef GrAARectEffect_DEFINED
#define GrAARectEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrAARectEffect : public GrFragmentProcessor {
public:
- static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, SkRect rect) {
- return std::unique_ptr<GrFragmentProcessor>(new GrAARectEffect(edgeType, rect));
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType,
+ SkRect rect) {
+ return std::unique_ptr<GrFragmentProcessor>(
+ new GrAARectEffect(std::move(inputFP), edgeType, rect));
}
GrAARectEffect(const GrAARectEffect& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "AARectEffect"; }
+ int inputFP_index = -1;
GrClipEdgeType edgeType;
SkRect rect;
private:
- GrAARectEffect(GrClipEdgeType edgeType, SkRect rect)
+ GrAARectEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType,
+ SkRect rect)
: INHERITED(kGrAARectEffect_ClassID,
- (OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag)
+ (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
+ : kAll_OptimizationFlags) &
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, edgeType(edgeType)
- , rect(rect) {}
+ , rect(rect) {
+ if (inputFP) {
+ inputFP_index = this->registerChild(std::move(inputFP));
+ }
+ }
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp
index 915684f1222..c9f7c7bf634 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp
@@ -10,15 +10,6 @@
**************************************************************************************************/
#include "GrAlphaThresholdFragmentProcessor.h"
-inline GrFragmentProcessor::OptimizationFlags GrAlphaThresholdFragmentProcessor::optFlags(
- float outerThreshold) {
- if (outerThreshold >= 1.0) {
- return kPreservesOpaqueInput_OptimizationFlag |
- kCompatibleWithCoverageAsAlpha_OptimizationFlag;
- } else {
- return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
- }
-}
#include "src/gpu/GrTexture.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
@@ -41,22 +32,34 @@ public:
kHalf_GrSLType, "innerThreshold");
outerThresholdVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
kHalf_GrSLType, "outerThreshold");
- SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(
- args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix());
+ SkString _input515(args.fInputColor);
+ SkString _sample515;
+ if (_outer.inputFP_index >= 0) {
+ _sample515 = this->invokeChild(_outer.inputFP_index, _input515.c_str(), args);
+ } else {
+ _sample515.swap(_input515);
+ }
fragBuilder->codeAppendf(
- "half4 color = %s;\nhalf4 mask_color = sample(%s, %s).%s;\nif (mask_color.w < 0.5) "
- "{\n if (color.w > %s) {\n half scale = %s / color.w;\n color.xyz "
- "*= scale;\n color.w = %s;\n }\n} else if (color.w < %s) {\n half "
- "scale = %s / max(0.0010000000474974513, color.w);\n color.xyz *= scale;\n "
- "color.w = %s;\n}\n%s = color;\n",
- args.fInputColor,
- fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
- sk_TransformedCoords2D_0.c_str(),
- fragBuilder->getProgramBuilder()
- ->samplerSwizzle(args.fTexSamplers[0])
- .asString()
- .c_str(),
- args.fUniformHandler->getUniformCStr(outerThresholdVar),
+ R"SkSL(half4 color = %s;)SkSL", _sample515.c_str());
+ SkString _sample567;
+ _sample567 = this->invokeChild(_outer.maskFP_index, args);
+ fragBuilder->codeAppendf(
+ R"SkSL(
+half4 mask_color = %s;
+if (mask_color.w < 0.5) {
+ if (color.w > %s) {
+ half scale = %s / color.w;
+ color.xyz *= scale;
+ color.w = %s;
+ }
+} else if (color.w < %s) {
+ half scale = %s / max(0.0010000000474974513, color.w);
+ color.xyz *= scale;
+ color.w = %s;
+}
+%s = color;
+)SkSL",
+ _sample567.c_str(), args.fUniformHandler->getUniformCStr(outerThresholdVar),
args.fUniformHandler->getUniformCStr(outerThresholdVar),
args.fUniformHandler->getUniformCStr(outerThresholdVar),
args.fUniformHandler->getUniformCStr(innerThresholdVar),
@@ -85,7 +88,6 @@ void GrAlphaThresholdFragmentProcessor::onGetGLSLProcessorKey(const GrShaderCaps
bool GrAlphaThresholdFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const {
const GrAlphaThresholdFragmentProcessor& that = other.cast<GrAlphaThresholdFragmentProcessor>();
(void)that;
- if (mask != that.mask) return false;
if (innerThreshold != that.innerThreshold) return false;
if (outerThreshold != that.outerThreshold) return false;
return true;
@@ -93,37 +95,30 @@ bool GrAlphaThresholdFragmentProcessor::onIsEqual(const GrFragmentProcessor& oth
GrAlphaThresholdFragmentProcessor::GrAlphaThresholdFragmentProcessor(
const GrAlphaThresholdFragmentProcessor& src)
: INHERITED(kGrAlphaThresholdFragmentProcessor_ClassID, src.optimizationFlags())
- , maskCoordTransform(src.maskCoordTransform)
- , mask(src.mask)
, innerThreshold(src.innerThreshold)
, outerThreshold(src.outerThreshold) {
- this->setTextureSamplerCnt(1);
- this->addCoordTransform(&maskCoordTransform);
+ if (src.inputFP_index >= 0) {
+ inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
+ }
+ { maskFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.maskFP_index)); }
}
std::unique_ptr<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrAlphaThresholdFragmentProcessor(*this));
}
-const GrFragmentProcessor::TextureSampler& GrAlphaThresholdFragmentProcessor::onTextureSampler(
- int index) const {
- return IthTextureSampler(index, mask);
-}
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrAlphaThresholdFragmentProcessor);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::TestCreate(
GrProcessorTestData* testData) {
- auto[maskView, ct, at] = testData->randomAlphaOnlyView();
- // Make the inner and outer thresholds be in (0, 1) exclusive and be sorted correctly.
- float innerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f;
- float outerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f;
- const int kMaxWidth = 1000;
- const int kMaxHeight = 1000;
- uint32_t width = testData->fRandom->nextULessThan(kMaxWidth);
- uint32_t height = testData->fRandom->nextULessThan(kMaxHeight);
- uint32_t x = testData->fRandom->nextULessThan(kMaxWidth - width);
- uint32_t y = testData->fRandom->nextULessThan(kMaxHeight - height);
- SkIRect bounds = SkIRect::MakeXYWH(x, y, width, height);
+ // Make the inner and outer thresholds be in [0, 1].
+ float outerThresh = testData->fRandom->nextUScalar1();
+ float innerThresh = testData->fRandom->nextUScalar1();
+ std::unique_ptr<GrFragmentProcessor> inputChild, maskChild;
+ if (testData->fRandom->nextBool()) {
+ inputChild = GrProcessorUnitTest::MakeChildFP(testData);
+ }
+ maskChild = GrProcessorUnitTest::MakeChildFP(testData);
- return GrAlphaThresholdFragmentProcessor::Make(std::move(maskView), innerThresh, outerThresh,
- bounds);
+ return GrAlphaThresholdFragmentProcessor::Make(std::move(inputChild), std::move(maskChild),
+ innerThresh, outerThresh);
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.h
index c4de913733f..eeb9e9cfa51 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.h
@@ -10,50 +10,51 @@
**************************************************************************************************/
#ifndef GrAlphaThresholdFragmentProcessor_DEFINED
#define GrAlphaThresholdFragmentProcessor_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrAlphaThresholdFragmentProcessor : public GrFragmentProcessor {
public:
- inline OptimizationFlags optFlags(float outerThreshold);
-
- static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView mask,
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ std::unique_ptr<GrFragmentProcessor> maskFP,
float innerThreshold,
- float outerThreshold,
- const SkIRect& bounds) {
+ float outerThreshold) {
return std::unique_ptr<GrFragmentProcessor>(new GrAlphaThresholdFragmentProcessor(
- std::move(mask), innerThreshold, outerThreshold, bounds));
+ std::move(inputFP), std::move(maskFP), innerThreshold, outerThreshold));
}
GrAlphaThresholdFragmentProcessor(const GrAlphaThresholdFragmentProcessor& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "AlphaThresholdFragmentProcessor"; }
- GrCoordTransform maskCoordTransform;
- TextureSampler mask;
+ int inputFP_index = -1;
+ int maskFP_index = -1;
float innerThreshold;
float outerThreshold;
private:
- GrAlphaThresholdFragmentProcessor(GrSurfaceProxyView mask,
+ GrAlphaThresholdFragmentProcessor(std::unique_ptr<GrFragmentProcessor> inputFP,
+ std::unique_ptr<GrFragmentProcessor> maskFP,
float innerThreshold,
- float outerThreshold,
- const SkIRect& bounds)
- : INHERITED(kGrAlphaThresholdFragmentProcessor_ClassID, kNone_OptimizationFlags)
- , maskCoordTransform(
- SkMatrix::MakeTrans(SkIntToScalar(-bounds.x()), SkIntToScalar(-bounds.y())),
- mask.proxy(),
- mask.origin())
- , mask(std::move(mask))
+ float outerThreshold)
+ : INHERITED(kGrAlphaThresholdFragmentProcessor_ClassID,
+ (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
+ : kAll_OptimizationFlags) &
+ ((outerThreshold >= 1.0) ? kPreservesOpaqueInput_OptimizationFlag
+ : kNone_OptimizationFlags))
, innerThreshold(innerThreshold)
, outerThreshold(outerThreshold) {
- this->setTextureSamplerCnt(1);
- this->addCoordTransform(&maskCoordTransform);
+ if (inputFP) {
+ inputFP_index = this->registerChild(std::move(inputFP));
+ }
+ SkASSERT(maskFP);
+ maskFP_index = this->registerChild(std::move(maskFP));
}
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
- const TextureSampler& onTextureSampler(int) const override;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
typedef GrFragmentProcessor INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp
index 5c6dbc3db6f..3d5b7b12380 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp
@@ -26,12 +26,27 @@ public:
(void)_outer;
auto mode = _outer.mode;
(void)mode;
+ SkString _input308(args.fInputColor);
+ SkString _sample308;
+ if (_outer.inputFP_index >= 0) {
+ _sample308 = this->invokeChild(_outer.inputFP_index, _input308.c_str(), args);
+ } else {
+ _sample308.swap(_input308);
+ }
fragBuilder->codeAppendf(
- "half factor = 1.0 - %s.w;\n@switch (%d) {\n case 0:\n factor = "
- "exp((-factor * factor) * 4.0) - 0.017999999225139618;\n break;\n case "
- "1:\n factor = smoothstep(1.0, 0.0, factor);\n break;\n}\n%s = "
- "half4(factor);\n",
- args.fInputColor, (int)_outer.mode, args.fOutputColor);
+ R"SkSL(half inputAlpha = %s.w;
+half factor = 1.0 - inputAlpha;
+@switch (%d) {
+ case 0:
+ factor = exp((-factor * factor) * 4.0) - 0.017999999225139618;
+ break;
+ case 1:
+ factor = smoothstep(1.0, 0.0, factor);
+ break;
+}
+%s = half4(factor);
+)SkSL",
+ _sample308.c_str(), (int)_outer.mode, args.fOutputColor);
}
private:
@@ -54,7 +69,11 @@ bool GrBlurredEdgeFragmentProcessor::onIsEqual(const GrFragmentProcessor& other)
GrBlurredEdgeFragmentProcessor::GrBlurredEdgeFragmentProcessor(
const GrBlurredEdgeFragmentProcessor& src)
: INHERITED(kGrBlurredEdgeFragmentProcessor_ClassID, src.optimizationFlags())
- , mode(src.mode) {}
+ , mode(src.mode) {
+ if (src.inputFP_index >= 0) {
+ inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
+ }
+}
std::unique_ptr<GrFragmentProcessor> GrBlurredEdgeFragmentProcessor::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrBlurredEdgeFragmentProcessor(*this));
}
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.h
index 188280327a9..d9c0c3b5516 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.h
@@ -10,26 +10,35 @@
**************************************************************************************************/
#ifndef GrBlurredEdgeFragmentProcessor_DEFINED
#define GrBlurredEdgeFragmentProcessor_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrBlurredEdgeFragmentProcessor : public GrFragmentProcessor {
public:
enum class Mode { kGaussian = 0, kSmoothStep = 1 };
- static std::unique_ptr<GrFragmentProcessor> Make(Mode mode) {
- return std::unique_ptr<GrFragmentProcessor>(new GrBlurredEdgeFragmentProcessor(mode));
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ Mode mode) {
+ return std::unique_ptr<GrFragmentProcessor>(
+ new GrBlurredEdgeFragmentProcessor(std::move(inputFP), mode));
}
GrBlurredEdgeFragmentProcessor(const GrBlurredEdgeFragmentProcessor& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "BlurredEdgeFragmentProcessor"; }
+ int inputFP_index = -1;
Mode mode;
private:
- GrBlurredEdgeFragmentProcessor(Mode mode)
+ GrBlurredEdgeFragmentProcessor(std::unique_ptr<GrFragmentProcessor> inputFP, Mode mode)
: INHERITED(kGrBlurredEdgeFragmentProcessor_ClassID, kNone_OptimizationFlags)
- , mode(mode) {}
+ , mode(mode) {
+ if (inputFP) {
+ inputFP_index = this->registerChild(std::move(inputFP));
+ }
+ }
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp
index 451dd98d0d4..67449dd8a54 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp
@@ -177,14 +177,14 @@ static void create_half_plane_profile(uint8_t* profile, int profileWidth) {
profile[profileWidth - 1] = 0;
}
-static GrSurfaceProxyView create_profile_texture(GrRecordingContext* context,
- const SkRect& circle,
- float sigma,
- float* solidRadius,
- float* textureRadius) {
+static std::unique_ptr<GrFragmentProcessor> create_profile_effect(GrRecordingContext* context,
+ const SkRect& circle,
+ float sigma,
+ float* solidRadius,
+ float* textureRadius) {
float circleR = circle.width() / 2.0f;
if (circleR < SK_ScalarNearlyZero) {
- return {};
+ return nullptr;
}
// Profile textures are cached by the ratio of sigma to circle radius and by the size of the
// profile texture (binned by powers of 2).
@@ -214,6 +214,12 @@ static GrSurfaceProxyView create_profile_texture(GrRecordingContext* context,
*textureRadius = circleR + 3 * sigma;
}
+ static constexpr int kProfileTextureWidth = 512;
+ // This would be kProfileTextureWidth/textureRadius if it weren't for the fact that we do
+ // the calculation of the profile coord in a coord space that has already been scaled by
+ // 1 / textureRadius. This is done to avoid overflow in length().
+ SkMatrix texM = SkMatrix::Scale(kProfileTextureWidth, 1.f);
+
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey key;
GrUniqueKey::Builder builder(&key, kDomain, 1, "1-D Circular Blur");
@@ -224,14 +230,13 @@ static GrSurfaceProxyView create_profile_texture(GrRecordingContext* context,
if (sk_sp<GrTextureProxy> blurProfile = proxyProvider->findOrCreateProxyByUniqueKey(key)) {
GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(blurProfile->backendFormat(),
GrColorType::kAlpha_8);
- return {std::move(blurProfile), kTopLeft_GrSurfaceOrigin, swizzle};
+ GrSurfaceProxyView profileView{std::move(blurProfile), kTopLeft_GrSurfaceOrigin, swizzle};
+ return GrTextureEffect::Make(std::move(profileView), kPremul_SkAlphaType, texM);
}
- static constexpr int kProfileTextureWidth = 512;
-
SkBitmap bm;
if (!bm.tryAllocPixels(SkImageInfo::MakeA8(kProfileTextureWidth, 1))) {
- return {};
+ return nullptr;
}
if (useHalfPlaneApprox) {
@@ -246,25 +251,28 @@ static GrSurfaceProxyView create_profile_texture(GrRecordingContext* context,
bm.setImmutable();
GrBitmapTextureMaker maker(context, bm, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
- auto blurView = maker.view(GrMipMapped::kNo);
- if (!blurView) {
- return {};
+ auto profileView = maker.view(GrMipMapped::kNo);
+ if (!profileView) {
+ return nullptr;
}
- proxyProvider->assignUniqueKeyToProxy(key, blurView.asTextureProxy());
- return blurView;
+ proxyProvider->assignUniqueKeyToProxy(key, profileView.asTextureProxy());
+ return GrTextureEffect::Make(std::move(profileView), kPremul_SkAlphaType, texM);
}
std::unique_ptr<GrFragmentProcessor> GrCircleBlurFragmentProcessor::Make(
- GrRecordingContext* context, const SkRect& circle, float sigma) {
+ std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrRecordingContext* context,
+ const SkRect& circle,
+ float sigma) {
float solidRadius;
float textureRadius;
- GrSurfaceProxyView profile =
- create_profile_texture(context, circle, sigma, &solidRadius, &textureRadius);
+ std::unique_ptr<GrFragmentProcessor> profile =
+ create_profile_effect(context, circle, sigma, &solidRadius, &textureRadius);
if (!profile) {
return nullptr;
}
return std::unique_ptr<GrFragmentProcessor>(new GrCircleBlurFragmentProcessor(
- circle, textureRadius, solidRadius, std::move(profile)));
+ std::move(inputFP), circle, solidRadius, textureRadius, std::move(profile)));
}
#include "src/gpu/GrTexture.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
@@ -282,28 +290,39 @@ public:
(void)_outer;
auto circleRect = _outer.circleRect;
(void)circleRect;
- auto textureRadius = _outer.textureRadius;
- (void)textureRadius;
auto solidRadius = _outer.solidRadius;
(void)solidRadius;
+ auto textureRadius = _outer.textureRadius;
+ (void)textureRadius;
circleDataVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
kHalf4_GrSLType, "circleData");
fragBuilder->codeAppendf(
- "half2 vec = half2(half((sk_FragCoord.x - float(%s.x)) * float(%s.w)), "
- "half((sk_FragCoord.y - float(%s.y)) * float(%s.w)));\nhalf dist = length(vec) + "
- "(0.5 - %s.z) * %s.w;\n%s = %s * sample(%s, float2(half2(dist, 0.5))).%s.w;\n",
- args.fUniformHandler->getUniformCStr(circleDataVar),
- args.fUniformHandler->getUniformCStr(circleDataVar),
+ R"SkSL(;
+half2 vec = half2((sk_FragCoord.xy - float2(%s.xy)) * float(%s.w));
+half dist = length(vec) + (0.5 - %s.z) * %s.w;)SkSL",
args.fUniformHandler->getUniformCStr(circleDataVar),
args.fUniformHandler->getUniformCStr(circleDataVar),
args.fUniformHandler->getUniformCStr(circleDataVar),
- args.fUniformHandler->getUniformCStr(circleDataVar), args.fOutputColor,
- args.fInputColor,
- fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
- fragBuilder->getProgramBuilder()
- ->samplerSwizzle(args.fTexSamplers[0])
- .asString()
- .c_str());
+ args.fUniformHandler->getUniformCStr(circleDataVar));
+ SkString _input13945(args.fInputColor);
+ SkString _sample13945;
+ if (_outer.inputFP_index >= 0) {
+ _sample13945 = this->invokeChild(_outer.inputFP_index, _input13945.c_str(), args);
+ } else {
+ _sample13945.swap(_input13945);
+ }
+ fragBuilder->codeAppendf(
+ R"SkSL(
+half4 inputColor = %s;)SkSL",
+ _sample13945.c_str());
+ SkString _sample14005;
+ SkString _coords14005("float2(half2(dist, 0.5))");
+ _sample14005 = this->invokeChild(_outer.blurProfile_index, args, _coords14005.c_str());
+ fragBuilder->codeAppendf(
+ R"SkSL(
+%s = inputColor * %s.w;
+)SkSL",
+ args.fOutputColor, _sample14005.c_str());
}
private:
@@ -312,13 +331,10 @@ private:
const GrCircleBlurFragmentProcessor& _outer = _proc.cast<GrCircleBlurFragmentProcessor>();
auto circleRect = _outer.circleRect;
(void)circleRect;
- auto textureRadius = _outer.textureRadius;
- (void)textureRadius;
auto solidRadius = _outer.solidRadius;
(void)solidRadius;
- const GrSurfaceProxyView& blurProfileSamplerView = _outer.textureSampler(0).view();
- GrTexture& blurProfileSampler = *blurProfileSamplerView.proxy()->peekTexture();
- (void)blurProfileSampler;
+ auto textureRadius = _outer.textureRadius;
+ (void)textureRadius;
UniformHandle& circleData = circleDataVar;
(void)circleData;
@@ -336,27 +352,27 @@ bool GrCircleBlurFragmentProcessor::onIsEqual(const GrFragmentProcessor& other)
const GrCircleBlurFragmentProcessor& that = other.cast<GrCircleBlurFragmentProcessor>();
(void)that;
if (circleRect != that.circleRect) return false;
- if (textureRadius != that.textureRadius) return false;
if (solidRadius != that.solidRadius) return false;
- if (blurProfileSampler != that.blurProfileSampler) return false;
+ if (textureRadius != that.textureRadius) return false;
return true;
}
GrCircleBlurFragmentProcessor::GrCircleBlurFragmentProcessor(
const GrCircleBlurFragmentProcessor& src)
: INHERITED(kGrCircleBlurFragmentProcessor_ClassID, src.optimizationFlags())
, circleRect(src.circleRect)
- , textureRadius(src.textureRadius)
, solidRadius(src.solidRadius)
- , blurProfileSampler(src.blurProfileSampler) {
- this->setTextureSamplerCnt(1);
+ , textureRadius(src.textureRadius) {
+ if (src.inputFP_index >= 0) {
+ inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
+ }
+ {
+ blurProfile_index =
+ this->cloneAndRegisterChildProcessor(src.childProcessor(src.blurProfile_index));
+ }
}
std::unique_ptr<GrFragmentProcessor> GrCircleBlurFragmentProcessor::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrCircleBlurFragmentProcessor(*this));
}
-const GrFragmentProcessor::TextureSampler& GrCircleBlurFragmentProcessor::onTextureSampler(
- int index) const {
- return IthTextureSampler(index, blurProfileSampler);
-}
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrCircleBlurFragmentProcessor);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrCircleBlurFragmentProcessor::TestCreate(
@@ -364,6 +380,7 @@ std::unique_ptr<GrFragmentProcessor> GrCircleBlurFragmentProcessor::TestCreate(
SkScalar wh = testData->fRandom->nextRangeScalar(100.f, 1000.f);
SkScalar sigma = testData->fRandom->nextRangeF(1.f, 10.f);
SkRect circle = SkRect::MakeWH(wh, wh);
- return GrCircleBlurFragmentProcessor::Make(testData->context(), circle, sigma);
+ return GrCircleBlurFragmentProcessor::Make(/*inputFP=*/nullptr, testData->context(), circle,
+ sigma);
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.h
index b61315ac533..164ccdd8113 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.h
@@ -10,41 +10,52 @@
**************************************************************************************************/
#ifndef GrCircleBlurFragmentProcessor_DEFINED
#define GrCircleBlurFragmentProcessor_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
+
+#include "src/gpu/effects/GrTextureEffect.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrCircleBlurFragmentProcessor : public GrFragmentProcessor {
public:
- static std::unique_ptr<GrFragmentProcessor> Make(GrRecordingContext*,
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrRecordingContext*,
const SkRect& circle,
float sigma);
GrCircleBlurFragmentProcessor(const GrCircleBlurFragmentProcessor& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "CircleBlurFragmentProcessor"; }
+ int inputFP_index = -1;
SkRect circleRect;
- float textureRadius;
float solidRadius;
- TextureSampler blurProfileSampler;
+ float textureRadius;
+ int blurProfile_index = -1;
private:
- GrCircleBlurFragmentProcessor(SkRect circleRect,
- float textureRadius,
+ GrCircleBlurFragmentProcessor(std::unique_ptr<GrFragmentProcessor> inputFP,
+ SkRect circleRect,
float solidRadius,
- GrSurfaceProxyView blurProfileSampler)
+ float textureRadius,
+ std::unique_ptr<GrFragmentProcessor> blurProfile)
: INHERITED(kGrCircleBlurFragmentProcessor_ClassID,
- (OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag)
+ (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
+ : kAll_OptimizationFlags) &
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, circleRect(circleRect)
- , textureRadius(textureRadius)
, solidRadius(solidRadius)
- , blurProfileSampler(std::move(blurProfileSampler)) {
- this->setTextureSamplerCnt(1);
+ , textureRadius(textureRadius) {
+ if (inputFP) {
+ inputFP_index = this->registerChild(std::move(inputFP));
+ }
+ SkASSERT(blurProfile);
+ blurProfile_index = this->registerExplicitlySampledChild(std::move(blurProfile));
}
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
- const TextureSampler& onTextureSampler(int) const override;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
typedef GrFragmentProcessor INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.cpp
index 272d33234a5..f9df3c9fdcb 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.cpp
@@ -33,20 +33,39 @@ public:
circleVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
kFloat4_GrSLType, "circle");
fragBuilder->codeAppendf(
- "float2 prevCenter;\nfloat prevRadius = %f;\nhalf d;\n@if (%d == 2 || %d == 3) {\n "
- " d = half((length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * %s.z);\n} else {\n "
- " d = half((1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * %s.z);\n}\n@if "
- "((%d == 1 || %d == 3) || %d == 4) {\n %s = %s * clamp(d, 0.0, 1.0);\n} else "
- "{\n %s = d > 0.5 ? %s : half4(0.0);\n}\n",
+ R"SkSL(float2 prevCenter;
+float prevRadius = %f;
+half d;
+@if (%d == 2 || %d == 3) {
+ d = half((length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * %s.z);
+} else {
+ d = half((1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * %s.z);
+})SkSL",
prevRadius, (int)_outer.edgeType, (int)_outer.edgeType,
args.fUniformHandler->getUniformCStr(circleVar),
args.fUniformHandler->getUniformCStr(circleVar),
args.fUniformHandler->getUniformCStr(circleVar),
args.fUniformHandler->getUniformCStr(circleVar),
args.fUniformHandler->getUniformCStr(circleVar),
- args.fUniformHandler->getUniformCStr(circleVar), (int)_outer.edgeType,
- (int)_outer.edgeType, (int)_outer.edgeType, args.fOutputColor, args.fInputColor,
- args.fOutputColor, args.fInputColor);
+ args.fUniformHandler->getUniformCStr(circleVar));
+ SkString _input2509(args.fInputColor);
+ SkString _sample2509;
+ if (_outer.inputFP_index >= 0) {
+ _sample2509 = this->invokeChild(_outer.inputFP_index, _input2509.c_str(), args);
+ } else {
+ _sample2509.swap(_input2509);
+ }
+ fragBuilder->codeAppendf(
+ R"SkSL(
+half4 inputColor = %s;
+@if (%d == 1 || %d == 3) {
+ %s = inputColor * clamp(d, 0.0, 1.0);
+} else {
+ %s = d > 0.5 ? inputColor : half4(0.0);
+}
+)SkSL",
+ _sample2509.c_str(), (int)_outer.edgeType, (int)_outer.edgeType, args.fOutputColor,
+ args.fOutputColor);
}
private:
@@ -101,7 +120,11 @@ GrCircleEffect::GrCircleEffect(const GrCircleEffect& src)
: INHERITED(kGrCircleEffect_ClassID, src.optimizationFlags())
, edgeType(src.edgeType)
, center(src.center)
- , radius(src.radius) {}
+ , radius(src.radius) {
+ if (src.inputFP_index >= 0) {
+ inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
+ }
+}
std::unique_ptr<GrFragmentProcessor> GrCircleEffect::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(*this));
}
@@ -112,10 +135,12 @@ std::unique_ptr<GrFragmentProcessor> GrCircleEffect::TestCreate(GrProcessorTestD
center.fX = testData->fRandom->nextRangeScalar(0.f, 1000.f);
center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f);
SkScalar radius = testData->fRandom->nextRangeF(1.f, 1000.f);
- GrClipEdgeType et;
+ bool success;
+ std::unique_ptr<GrFragmentProcessor> fp;
do {
- et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
- } while (GrClipEdgeType::kHairlineAA == et);
- return GrCircleEffect::Make(et, center, radius);
+ GrClipEdgeType et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
+ std::tie(success, fp) = GrCircleEffect::Make(/*inputFP=*/nullptr, et, center, radius);
+ } while (!success);
+ return fp;
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.h
index b20412c70ae..ded95ae941f 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrCircleEffect.h
@@ -10,37 +10,51 @@
**************************************************************************************************/
#ifndef GrCircleEffect_DEFINED
#define GrCircleEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrCircleEffect : public GrFragmentProcessor {
public:
- static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType,
- SkPoint center,
- float radius) {
+ static GrFPResult Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType,
+ SkPoint center,
+ float radius) {
// A radius below half causes the implicit insetting done by this processor to become
// inverted. We could handle this case by making the processor code more complicated.
if (radius < .5f && GrProcessorEdgeTypeIsInverseFill(edgeType)) {
- return nullptr;
+ return GrFPFailure(std::move(inputFP));
}
- return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(edgeType, center, radius));
+ return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>(
+ new GrCircleEffect(std::move(inputFP), edgeType, center, radius)));
}
GrCircleEffect(const GrCircleEffect& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "CircleEffect"; }
+ int inputFP_index = -1;
GrClipEdgeType edgeType;
SkPoint center;
float radius;
private:
- GrCircleEffect(GrClipEdgeType edgeType, SkPoint center, float radius)
+ GrCircleEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType,
+ SkPoint center,
+ float radius)
: INHERITED(kGrCircleEffect_ClassID,
- (OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag)
+ (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
+ : kAll_OptimizationFlags) &
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, edgeType(edgeType)
, center(center)
- , radius(radius) {}
+ , radius(radius) {
+ if (inputFP) {
+ inputFP_index = this->registerChild(std::move(inputFP));
+ }
+ }
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.cpp
index 7d692b52de2..f218bf889db 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.cpp
@@ -25,11 +25,24 @@ public:
(void)_outer;
auto clampToPremul = _outer.clampToPremul;
(void)clampToPremul;
+ SkString _input464(args.fInputColor);
+ SkString _sample464;
+ if (_outer.inputFP_index >= 0) {
+ _sample464 = this->invokeChild(_outer.inputFP_index, _input464.c_str(), args);
+ } else {
+ _sample464.swap(_input464);
+ }
fragBuilder->codeAppendf(
- "@if (%s) {\n half alpha = clamp(%s.w, 0.0, 1.0);\n %s = half4(clamp(%s.xyz, "
- "0.0, alpha), alpha);\n} else {\n %s = clamp(%s, 0.0, 1.0);\n}\n",
- (_outer.clampToPremul ? "true" : "false"), args.fInputColor, args.fOutputColor,
- args.fInputColor, args.fOutputColor, args.fInputColor);
+ R"SkSL(half4 inputColor = %s;
+@if (%s) {
+ half alpha = clamp(inputColor.w, 0.0, 1.0);
+ %s = half4(clamp(inputColor.xyz, 0.0, alpha), alpha);
+} else {
+ %s = clamp(inputColor, 0.0, 1.0);
+}
+)SkSL",
+ _sample464.c_str(), (_outer.clampToPremul ? "true" : "false"), args.fOutputColor,
+ args.fOutputColor);
}
private:
@@ -51,13 +64,17 @@ bool GrClampFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const
}
GrClampFragmentProcessor::GrClampFragmentProcessor(const GrClampFragmentProcessor& src)
: INHERITED(kGrClampFragmentProcessor_ClassID, src.optimizationFlags())
- , clampToPremul(src.clampToPremul) {}
+ , clampToPremul(src.clampToPremul) {
+ if (src.inputFP_index >= 0) {
+ inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
+ }
+}
std::unique_ptr<GrFragmentProcessor> GrClampFragmentProcessor::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrClampFragmentProcessor(*this));
}
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrClampFragmentProcessor);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrClampFragmentProcessor::TestCreate(GrProcessorTestData* d) {
- return GrClampFragmentProcessor::Make(d->fRandom->nextBool());
+ return GrClampFragmentProcessor::Make(/*inputFP=*/nullptr, d->fRandom->nextBool());
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.h
index 61dc3a03d60..795555a7d18 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrClampFragmentProcessor.h
@@ -10,33 +10,47 @@
**************************************************************************************************/
#ifndef GrClampFragmentProcessor_DEFINED
#define GrClampFragmentProcessor_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrClampFragmentProcessor : public GrFragmentProcessor {
public:
- SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
+ SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
+ SkPMColor4f input = this->numChildProcessors() ? ConstantOutputForConstantInput(
+ this->childProcessor(0), inColor)
+ : inColor;
float clampedAlpha = SkTPin(input.fA, 0.f, 1.f);
float clampVal = clampToPremul ? clampedAlpha : 1.f;
return {SkTPin(input.fR, 0.f, clampVal), SkTPin(input.fG, 0.f, clampVal),
SkTPin(input.fB, 0.f, clampVal), clampedAlpha};
}
- static std::unique_ptr<GrFragmentProcessor> Make(bool clampToPremul) {
- return std::unique_ptr<GrFragmentProcessor>(new GrClampFragmentProcessor(clampToPremul));
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ bool clampToPremul) {
+ return std::unique_ptr<GrFragmentProcessor>(
+ new GrClampFragmentProcessor(std::move(inputFP), clampToPremul));
}
GrClampFragmentProcessor(const GrClampFragmentProcessor& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "ClampFragmentProcessor"; }
+ int inputFP_index = -1;
bool clampToPremul;
private:
- GrClampFragmentProcessor(bool clampToPremul)
+ GrClampFragmentProcessor(std::unique_ptr<GrFragmentProcessor> inputFP, bool clampToPremul)
: INHERITED(kGrClampFragmentProcessor_ClassID,
- (OptimizationFlags)kConstantOutputForConstantInput_OptimizationFlag |
- kPreservesOpaqueInput_OptimizationFlag)
- , clampToPremul(clampToPremul) {}
+ (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
+ : kAll_OptimizationFlags) &
+ (kConstantOutputForConstantInput_OptimizationFlag |
+ kPreservesOpaqueInput_OptimizationFlag))
+ , clampToPremul(clampToPremul) {
+ if (inputFP) {
+ inputFP_index = this->registerChild(std::move(inputFP));
+ }
+ }
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp
index 1f3091a88dd..ad8eca849ca 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp
@@ -38,13 +38,35 @@ public:
"m");
vVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf4_GrSLType,
"v");
+ SkString _input585(args.fInputColor);
+ SkString _sample585;
+ if (_outer.inputFP_index >= 0) {
+ _sample585 = this->invokeChild(_outer.inputFP_index, _input585.c_str(), args);
+ } else {
+ _sample585.swap(_input585);
+ }
fragBuilder->codeAppendf(
- "half4 inputColor = %s;\n@if (%s) {\n half nonZeroAlpha = max(inputColor.w, "
- "9.9999997473787516e-05);\n inputColor = half4(inputColor.xyz / nonZeroAlpha, "
- "inputColor.w);\n}\n%s = %s * inputColor + %s;\n@if (%s) {\n %s = clamp(%s, "
- "0.0, 1.0);\n} else {\n %s.w = clamp(%s.w, 0.0, 1.0);\n}\n@if (%s) {\n "
- "%s.xyz *= %s.w;\n}\n",
- args.fInputColor, (_outer.unpremulInput ? "true" : "false"), args.fOutputColor,
+ R"SkSL(half4 inputColor = %s;
+@if (%s) {
+ half4 inlineResult0;
+ half4 inlineArg1_0 = inputColor;
+ {
+ inlineResult0 = half4(inlineArg1_0.xyz / max(inlineArg1_0.w, 9.9999997473787516e-05), inlineArg1_0.w);
+ }
+ inputColor = inlineResult0;
+
+}
+%s = %s * inputColor + %s;
+@if (%s) {
+ %s = clamp(%s, 0.0, 1.0);
+} else {
+ %s.w = clamp(%s.w, 0.0, 1.0);
+}
+@if (%s) {
+ %s.xyz *= %s.w;
+}
+)SkSL",
+ _sample585.c_str(), (_outer.unpremulInput ? "true" : "false"), args.fOutputColor,
args.fUniformHandler->getUniformCStr(mVar),
args.fUniformHandler->getUniformCStr(vVar),
(_outer.clampRGBOutput ? "true" : "false"), args.fOutputColor, args.fOutputColor,
@@ -100,7 +122,11 @@ GrColorMatrixFragmentProcessor::GrColorMatrixFragmentProcessor(
, v(src.v)
, unpremulInput(src.unpremulInput)
, clampRGBOutput(src.clampRGBOutput)
- , premulOutput(src.premulOutput) {}
+ , premulOutput(src.premulOutput) {
+ if (src.inputFP_index >= 0) {
+ inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
+ }
+}
std::unique_ptr<GrFragmentProcessor> GrColorMatrixFragmentProcessor::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrColorMatrixFragmentProcessor(*this));
}
@@ -115,6 +141,6 @@ std::unique_ptr<GrFragmentProcessor> GrColorMatrixFragmentProcessor::TestCreate(
bool unpremul = d->fRandom->nextBool();
bool clampRGB = d->fRandom->nextBool();
bool premul = d->fRandom->nextBool();
- return Make(m, unpremul, clampRGB, premul);
+ return Make(/*inputFP=*/nullptr, m, unpremul, clampRGB, premul);
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h
index e8fa784cabf..4160af95949 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h
@@ -10,14 +10,19 @@
**************************************************************************************************/
#ifndef GrColorMatrixFragmentProcessor_DEFINED
#define GrColorMatrixFragmentProcessor_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrColorMatrixFragmentProcessor : public GrFragmentProcessor {
public:
- SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
+ SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
+ SkPMColor4f input = this->numChildProcessors() ? ConstantOutputForConstantInput(
+ this->childProcessor(0), inColor)
+ : inColor;
SkColor4f color;
if (unpremulInput) {
color = input.unpremul();
@@ -42,7 +47,8 @@ public:
}
}
- static std::unique_ptr<GrFragmentProcessor> Make(const float matrix[20],
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ const float matrix[20],
bool unpremulInput,
bool clampRGBOutput,
bool premulOutput) {
@@ -51,11 +57,12 @@ public:
matrix[17], matrix[18]);
SkV4 v4 = {matrix[4], matrix[9], matrix[14], matrix[19]};
return std::unique_ptr<GrFragmentProcessor>(new GrColorMatrixFragmentProcessor(
- m44, v4, unpremulInput, clampRGBOutput, premulOutput));
+ std::move(inputFP), m44, v4, unpremulInput, clampRGBOutput, premulOutput));
}
GrColorMatrixFragmentProcessor(const GrColorMatrixFragmentProcessor& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "ColorMatrixFragmentProcessor"; }
+ int inputFP_index = -1;
SkM44 m;
SkV4 v;
bool unpremulInput;
@@ -63,15 +70,25 @@ public:
bool premulOutput;
private:
- GrColorMatrixFragmentProcessor(
- SkM44 m, SkV4 v, bool unpremulInput, bool clampRGBOutput, bool premulOutput)
+ GrColorMatrixFragmentProcessor(std::unique_ptr<GrFragmentProcessor> inputFP,
+ SkM44 m,
+ SkV4 v,
+ bool unpremulInput,
+ bool clampRGBOutput,
+ bool premulOutput)
: INHERITED(kGrColorMatrixFragmentProcessor_ClassID,
- (OptimizationFlags)kConstantOutputForConstantInput_OptimizationFlag)
+ (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
+ : kAll_OptimizationFlags) &
+ kConstantOutputForConstantInput_OptimizationFlag)
, m(m)
, v(v)
, unpremulInput(unpremulInput)
, clampRGBOutput(clampRGBOutput)
- , premulOutput(premulOutput) {}
+ , premulOutput(premulOutput) {
+ if (inputFP) {
+ inputFP_index = this->registerChild(std::move(inputFP));
+ }
+ }
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.cpp
index 78aabacb90d..3a4a323672d 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.cpp
@@ -39,11 +39,12 @@ public:
} else {
_sample358 = "half4(1)";
}
- fragBuilder->codeAppendf("%s = mix(%s ? %s : %s, %s ? %s : %s, half(%s));\n",
- args.fOutputColor, _outer.child1_index >= 0 ? "true" : "false",
- _sample290.c_str(), args.fInputColor,
- _outer.child2_index >= 0 ? "true" : "false", _sample358.c_str(),
- args.fInputColor, args.fUniformHandler->getUniformCStr(weightVar));
+ fragBuilder->codeAppendf(
+ R"SkSL(%s = mix(%s ? %s : %s, %s ? %s : %s, half(%s));
+)SkSL",
+ args.fOutputColor, _outer.child1_index >= 0 ? "true" : "false", _sample290.c_str(),
+ args.fInputColor, _outer.child2_index >= 0 ? "true" : "false", _sample358.c_str(),
+ args.fInputColor, args.fUniformHandler->getUniformCStr(weightVar));
}
private:
@@ -66,23 +67,12 @@ bool GrComposeLerpEffect::onIsEqual(const GrFragmentProcessor& other) const {
return true;
}
GrComposeLerpEffect::GrComposeLerpEffect(const GrComposeLerpEffect& src)
- : INHERITED(kGrComposeLerpEffect_ClassID, src.optimizationFlags())
- , child1_index(src.child1_index)
- , child2_index(src.child2_index)
- , weight(src.weight) {
- if (child1_index >= 0) {
- auto clone = src.childProcessor(child1_index).clone();
- if (src.childProcessor(child1_index).isSampledWithExplicitCoords()) {
- clone->setSampledWithExplicitCoords();
- }
- this->registerChildProcessor(std::move(clone));
+ : INHERITED(kGrComposeLerpEffect_ClassID, src.optimizationFlags()), weight(src.weight) {
+ if (src.child1_index >= 0) {
+ child1_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child1_index));
}
- if (child2_index >= 0) {
- auto clone = src.childProcessor(child2_index).clone();
- if (src.childProcessor(child2_index).isSampledWithExplicitCoords()) {
- clone->setSampledWithExplicitCoords();
- }
- this->registerChildProcessor(std::move(clone));
+ if (src.child2_index >= 0) {
+ child2_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child2_index));
}
}
std::unique_ptr<GrFragmentProcessor> GrComposeLerpEffect::clone() const {
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.h
index d1fb0ff42cb..1f9d225043f 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrComposeLerpEffect.h
@@ -10,11 +10,13 @@
**************************************************************************************************/
#ifndef GrComposeLerpEffect_DEFINED
#define GrComposeLerpEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrComposeLerpEffect : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> child1,
@@ -36,12 +38,10 @@ private:
float weight)
: INHERITED(kGrComposeLerpEffect_ClassID, kNone_OptimizationFlags), weight(weight) {
if (child1) {
- child1_index = this->numChildProcessors();
- this->registerChildProcessor(std::move(child1));
+ child1_index = this->registerChild(std::move(child1));
}
if (child2) {
- child2_index = this->numChildProcessors();
- this->registerChildProcessor(std::move(child2));
+ child2_index = this->registerChild(std::move(child2));
}
}
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.cpp
index 9a3e9877d31..0ec66fd31d0 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.cpp
@@ -28,10 +28,16 @@ public:
fragBuilder->forceHighPrecision();
fragBuilder->codeAppendf(
- "%s = floor(%s * 255.0 + 0.5) / 255.0;\n@switch (%d) {\n case 0:\n "
- "%s.xyz = floor((%s.xyz * %s.w) * 255.0 + 0.5) / 255.0;\n break;\n case "
- "1:\n %s.xyz = %s.w <= 0.0 ? half3(0.0) : floor((%s.xyz / %s.w) * 255.0 + "
- "0.5) / 255.0;\n break;\n}\n",
+ R"SkSL(%s = floor(%s * 255.0 + 0.5) / 255.0;
+@switch (%d) {
+ case 0:
+ %s.xyz = floor((%s.xyz * %s.w) * 255.0 + 0.5) / 255.0;
+ break;
+ case 1:
+ %s.xyz = %s.w <= 0.0 ? half3(0.0) : floor((%s.xyz / %s.w) * 255.0 + 0.5) / 255.0;
+ break;
+}
+)SkSL",
args.fOutputColor, args.fInputColor, (int)_outer.pmConversion, args.fOutputColor,
args.fOutputColor, args.fOutputColor, args.fOutputColor, args.fOutputColor,
args.fOutputColor, args.fOutputColor);
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.h
index f6172b9e35d..129c21dd17f 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrConfigConversionEffect.h
@@ -10,18 +10,19 @@
**************************************************************************************************/
#ifndef GrConfigConversionEffect_DEFINED
#define GrConfigConversionEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "include/gpu/GrContext.h"
#include "src/gpu/GrBitmapTextureMaker.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrImageInfo.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrConfigConversionEffect : public GrFragmentProcessor {
public:
static bool TestForPreservingPMConversions(GrContext* context) {
@@ -93,8 +94,7 @@ public:
paint1.addColorFragmentProcessor(pmToUPM->clone());
paint1.setPorterDuffXPFactory(SkBlendMode::kSrc);
- readRTC->fillRectToRect(GrNoClip(), std::move(paint1), GrAA::kNo, SkMatrix::I(), kRect,
- kRect);
+ readRTC->fillRectToRect(nullptr, std::move(paint1), GrAA::kNo, SkMatrix::I(), kRect, kRect);
if (!readRTC->readPixels(ii, firstRead, 0, {0, 0})) {
return false;
}
@@ -108,16 +108,14 @@ public:
paint2.addColorFragmentProcessor(std::move(upmToPM));
paint2.setPorterDuffXPFactory(SkBlendMode::kSrc);
- tempRTC->fillRectToRect(GrNoClip(), std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect,
- kRect);
+ tempRTC->fillRectToRect(nullptr, std::move(paint2), GrAA::kNo, SkMatrix::I(), kRect, kRect);
paint3.addColorFragmentProcessor(
GrTextureEffect::Make(tempRTC->readSurfaceView(), kPremul_SkAlphaType));
paint3.addColorFragmentProcessor(std::move(pmToUPM));
paint3.setPorterDuffXPFactory(SkBlendMode::kSrc);
- readRTC->fillRectToRect(GrNoClip(), std::move(paint3), GrAA::kNo, SkMatrix::I(), kRect,
- kRect);
+ readRTC->fillRectToRect(nullptr, std::move(paint3), GrAA::kNo, SkMatrix::I(), kRect, kRect);
if (!readRTC->readPixels(ii, secondRead, 0, {0, 0})) {
return false;
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.cpp
index 22079b65a21..50b4b749e23 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.cpp
@@ -30,12 +30,49 @@ public:
colorVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
kHalf4_GrSLType, "color");
fragBuilder->codeAppendf(
- "@switch (%d) {\n case 0:\n %s = %s;\n break;\n case 1:\n "
- " %s = %s * %s;\n break;\n case 2:\n %s = %s.w * %s;\n "
- "break;\n}\n",
- (int)_outer.mode, args.fOutputColor, args.fUniformHandler->getUniformCStr(colorVar),
- args.fOutputColor, args.fInputColor, args.fUniformHandler->getUniformCStr(colorVar),
- args.fOutputColor, args.fInputColor,
+ R"SkSL(@switch (%d) {
+ case 0:
+ {
+ %s = %s;
+ break;
+ }
+ case 1:
+ {)SkSL",
+ (int)_outer.mode, args.fOutputColor,
+ args.fUniformHandler->getUniformCStr(colorVar));
+ SkString _input1009(args.fInputColor);
+ SkString _sample1009;
+ if (_outer.inputFP_index >= 0) {
+ _sample1009 = this->invokeChild(_outer.inputFP_index, _input1009.c_str(), args);
+ } else {
+ _sample1009.swap(_input1009);
+ }
+ fragBuilder->codeAppendf(
+ R"SkSL(
+ half4 inputColor = %s;
+ %s = inputColor * %s;
+ break;
+ }
+ case 2:
+ {)SkSL",
+ _sample1009.c_str(), args.fOutputColor,
+ args.fUniformHandler->getUniformCStr(colorVar));
+ SkString _input1181(args.fInputColor);
+ SkString _sample1181;
+ if (_outer.inputFP_index >= 0) {
+ _sample1181 = this->invokeChild(_outer.inputFP_index, _input1181.c_str(), args);
+ } else {
+ _sample1181.swap(_input1181);
+ }
+ fragBuilder->codeAppendf(
+ R"SkSL(
+ half inputAlpha = %s.w;
+ %s = inputAlpha * %s;
+ break;
+ }
+}
+)SkSL",
+ _sample1181.c_str(), args.fOutputColor,
args.fUniformHandler->getUniformCStr(colorVar));
}
@@ -71,7 +108,11 @@ bool GrConstColorProcessor::onIsEqual(const GrFragmentProcessor& other) const {
GrConstColorProcessor::GrConstColorProcessor(const GrConstColorProcessor& src)
: INHERITED(kGrConstColorProcessor_ClassID, src.optimizationFlags())
, color(src.color)
- , mode(src.mode) {}
+ , mode(src.mode) {
+ if (src.inputFP_index >= 0) {
+ inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
+ }
+}
std::unique_ptr<GrFragmentProcessor> GrConstColorProcessor::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrConstColorProcessor(*this));
}
@@ -98,6 +139,6 @@ std::unique_ptr<GrFragmentProcessor> GrConstColorProcessor::TestCreate(GrProcess
break;
}
InputMode mode = static_cast<InputMode>(d->fRandom->nextULessThan(kInputModeCnt));
- return GrConstColorProcessor::Make(color, mode);
+ return GrConstColorProcessor::Make(/*inputFP=*/nullptr, color, mode);
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.h
index 6d84f836cf2..e9b8b86c5cc 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrConstColorProcessor.h
@@ -10,53 +10,73 @@
**************************************************************************************************/
#ifndef GrConstColorProcessor_DEFINED
#define GrConstColorProcessor_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrConstColorProcessor : public GrFragmentProcessor {
public:
enum class InputMode { kIgnore = 0, kLast = 2, kModulateA = 2, kModulateRGBA = 1 };
static const int kInputModeCnt = (int)InputMode::kLast + 1;
- static OptimizationFlags OptFlags(const SkPMColor4f& color, InputMode mode) {
- OptimizationFlags flags = kConstantOutputForConstantInput_OptimizationFlag;
- if (mode != InputMode::kIgnore) {
- flags |= kCompatibleWithCoverageAsAlpha_OptimizationFlag;
- }
- if (color.isOpaque()) {
- flags |= kPreservesOpaqueInput_OptimizationFlag;
- }
- return flags;
- }
-
- SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
+ SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
switch (mode) {
- case InputMode::kIgnore:
+ case InputMode::kIgnore: {
return color;
- case InputMode::kModulateA:
+ }
+ case InputMode::kModulateA: {
+ SkPMColor4f input = this->numChildProcessors()
+ ? ConstantOutputForConstantInput(
+ this->childProcessor(inputFP_index), inColor)
+ : inColor;
return color * input.fA;
- case InputMode::kModulateRGBA:
+ }
+ case InputMode::kModulateRGBA: {
+ SkPMColor4f input = this->numChildProcessors()
+ ? ConstantOutputForConstantInput(
+ this->childProcessor(inputFP_index), inColor)
+ : inColor;
return color * input;
+ }
}
- SK_ABORT("Unexpected mode");
+ SkUNREACHABLE;
}
- static std::unique_ptr<GrFragmentProcessor> Make(SkPMColor4f color, InputMode mode) {
- return std::unique_ptr<GrFragmentProcessor>(new GrConstColorProcessor(color, mode));
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ SkPMColor4f color,
+ InputMode mode) {
+ return std::unique_ptr<GrFragmentProcessor>(
+ new GrConstColorProcessor(std::move(inputFP), color, mode));
}
GrConstColorProcessor(const GrConstColorProcessor& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "ConstColorProcessor"; }
+ int inputFP_index = -1;
SkPMColor4f color;
InputMode mode;
private:
- GrConstColorProcessor(SkPMColor4f color, InputMode mode)
- : INHERITED(kGrConstColorProcessor_ClassID, (OptimizationFlags)OptFlags(color, mode))
+ GrConstColorProcessor(std::unique_ptr<GrFragmentProcessor> inputFP,
+ SkPMColor4f color,
+ InputMode mode)
+ : INHERITED(kGrConstColorProcessor_ClassID,
+ (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
+ : kAll_OptimizationFlags) &
+ (kConstantOutputForConstantInput_OptimizationFlag |
+ ((mode != InputMode::kIgnore)
+ ? kCompatibleWithCoverageAsAlpha_OptimizationFlag
+ : kNone_OptimizationFlags) |
+ ((color.isOpaque()) ? kPreservesOpaqueInput_OptimizationFlag
+ : kNone_OptimizationFlags)))
, color(color)
- , mode(mode) {}
+ , mode(mode) {
+ if (inputFP) {
+ inputFP_index = this->registerChild(std::move(inputFP));
+ }
+ }
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.cpp
index be9e92c6ecf..4fec9b1ab0d 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.cpp
@@ -23,17 +23,32 @@ public:
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrDeviceSpaceEffect& _outer = args.fFp.cast<GrDeviceSpaceEffect>();
(void)_outer;
- SkString _input204 = SkStringPrintf("%s", args.fInputColor);
- SkString _sample204;
- SkString _coords204("sk_FragCoord.xy");
- _sample204 =
- this->invokeChild(_outer.fp_index, _input204.c_str(), args, _coords204.c_str());
- fragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, _sample204.c_str());
+ auto matrix = _outer.matrix;
+ (void)matrix;
+ matrixVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
+ kFloat3x3_GrSLType, "matrix");
+ fragBuilder->codeAppendf(
+ R"SkSL(float3 p = %s * float3(sk_FragCoord.xy, 1);)SkSL",
+ args.fUniformHandler->getUniformCStr(matrixVar));
+ SkString _input276(args.fInputColor);
+ SkString _sample276;
+ SkString _coords276("p.xy / p.z");
+ _sample276 =
+ this->invokeChild(_outer.fp_index, _input276.c_str(), args, _coords276.c_str());
+ fragBuilder->codeAppendf(
+ R"SkSL(
+%s = %s;
+)SkSL",
+ args.fOutputColor, _sample276.c_str());
}
private:
void onSetData(const GrGLSLProgramDataManager& pdman,
- const GrFragmentProcessor& _proc) override {}
+ const GrFragmentProcessor& _proc) override {
+ const GrDeviceSpaceEffect& _outer = _proc.cast<GrDeviceSpaceEffect>();
+ { pdman.setSkMatrix(matrixVar, (_outer.matrix)); }
+ }
+ UniformHandle matrixVar;
};
GrGLSLFragmentProcessor* GrDeviceSpaceEffect::onCreateGLSLInstance() const {
return new GrGLSLDeviceSpaceEffect();
@@ -43,17 +58,12 @@ void GrDeviceSpaceEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
bool GrDeviceSpaceEffect::onIsEqual(const GrFragmentProcessor& other) const {
const GrDeviceSpaceEffect& that = other.cast<GrDeviceSpaceEffect>();
(void)that;
+ if (matrix != that.matrix) return false;
return true;
}
GrDeviceSpaceEffect::GrDeviceSpaceEffect(const GrDeviceSpaceEffect& src)
- : INHERITED(kGrDeviceSpaceEffect_ClassID, src.optimizationFlags()), fp_index(src.fp_index) {
- {
- auto clone = src.childProcessor(fp_index).clone();
- if (src.childProcessor(fp_index).isSampledWithExplicitCoords()) {
- clone->setSampledWithExplicitCoords();
- }
- this->registerChildProcessor(std::move(clone));
- }
+ : INHERITED(kGrDeviceSpaceEffect_ClassID, src.optimizationFlags()), matrix(src.matrix) {
+ { fp_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.fp_index)); }
}
std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceEffect::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrDeviceSpaceEffect(*this));
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.h
index e08d29d892d..c7e4f2439aa 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrDeviceSpaceEffect.h
@@ -10,28 +10,30 @@
**************************************************************************************************/
#ifndef GrDeviceSpaceEffect_DEFINED
#define GrDeviceSpaceEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrDeviceSpaceEffect : public GrFragmentProcessor {
public:
- static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp) {
- return std::unique_ptr<GrFragmentProcessor>(new GrDeviceSpaceEffect(std::move(fp)));
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp,
+ const SkMatrix& matrix = SkMatrix::I()) {
+ return std::unique_ptr<GrFragmentProcessor>(new GrDeviceSpaceEffect(std::move(fp), matrix));
}
GrDeviceSpaceEffect(const GrDeviceSpaceEffect& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "DeviceSpaceEffect"; }
int fp_index = -1;
+ SkMatrix matrix;
private:
- GrDeviceSpaceEffect(std::unique_ptr<GrFragmentProcessor> fp)
- : INHERITED(kGrDeviceSpaceEffect_ClassID, kNone_OptimizationFlags) {
+ GrDeviceSpaceEffect(std::unique_ptr<GrFragmentProcessor> fp, SkMatrix matrix)
+ : INHERITED(kGrDeviceSpaceEffect_ClassID, kNone_OptimizationFlags), matrix(matrix) {
SkASSERT(fp);
- fp_index = this->numChildProcessors();
- fp->setSampledWithExplicitCoords();
- this->registerChildProcessor(std::move(fp));
+ fp_index = this->registerExplicitlySampledChild(std::move(fp));
}
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.cpp
index fa349032589..0a75b96dd8e 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.cpp
@@ -38,26 +38,61 @@ public:
kFloat2_GrSLType, "scale");
}
fragBuilder->codeAppendf(
- "float2 prevCenter;\nfloat2 prevRadii = float2(%f, %f);\nbool medPrecision = "
- "%s;\nfloat2 d = sk_FragCoord.xy - %s.xy;\n@if (medPrecision) {\n d *= "
- "%s.y;\n}\nfloat2 Z = d * %s.zw;\nfloat implicit = dot(Z, d) - 1.0;\nfloat "
- "grad_dot = 4.0 * dot(Z, Z);\n@if (medPrecision) {\n grad_dot = max(grad_dot, "
- "6.1036000261083245e-05);\n} else {\n grad_dot = max(grad_dot, "
- "1.1754999560161448e-38);\n}\nfloat approx_dist = implicit * "
- "inversesqrt(grad_dot);\n@if (medPrecision) {\n approx_dist *= %s.x;\n}\nhalf "
- "alph",
+ R"SkSL(float2 prevCenter;
+float2 prevRadii = float2(%f, %f);
+bool medPrecision = %s;
+float2 d = sk_FragCoord.xy - %s.xy;
+@if (medPrecision) {
+ d *= %s.y;
+}
+float2 Z = d * %s.zw;
+float implicit = dot(Z, d) - 1.0;
+float grad_dot = 4.0 * dot(Z, Z);
+@if (medPrecision) {
+ grad_dot = max(grad_dot, 6.1036000261083245e-05);
+} else {
+ grad_dot = max(grad_dot, 1.1754999560161448e-38);
+}
+float approx_dist = implicit * inversesqrt(grad_dot);
+@if (medPrecision) {
+ approx_dist *= %s.x;
+}
+half alpha;
+@switch (%d) {
+ case 0:
+ alpha = approx_dist > 0.0 ? 0.0 : 1.0;
+ break;
+ case 1:
+ alpha = clamp(0.5 - half(approx_dist), 0.0, 1.0);
+ break;
+ case 2:
+ alpha = approx_dist > 0.0 ? 1.0 : 0.0;
+ break;
+ case 3:
+ alpha = clamp(0.5 + half(approx_dist), 0.0, 1.0);
+ break;
+ default:
+ discard;
+})SkSL",
prevRadii.fX, prevRadii.fY, (medPrecision ? "true" : "false"),
args.fUniformHandler->getUniformCStr(ellipseVar),
scaleVar.isValid() ? args.fUniformHandler->getUniformCStr(scaleVar) : "float2(0)",
args.fUniformHandler->getUniformCStr(ellipseVar),
- scaleVar.isValid() ? args.fUniformHandler->getUniformCStr(scaleVar) : "float2(0)");
+ scaleVar.isValid() ? args.fUniformHandler->getUniformCStr(scaleVar) : "float2(0)",
+ (int)_outer.edgeType);
+ SkString _input4481(args.fInputColor);
+ SkString _sample4481;
+ if (_outer.inputFP_index >= 0) {
+ _sample4481 = this->invokeChild(_outer.inputFP_index, _input4481.c_str(), args);
+ } else {
+ _sample4481.swap(_input4481);
+ }
fragBuilder->codeAppendf(
- "a;\n@switch (%d) {\n case 0:\n alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n "
- " break;\n case 1:\n alpha = clamp(0.5 - half(approx_dist), 0.0, "
- "1.0);\n break;\n case 2:\n alpha = approx_dist > 0.0 ? 1.0 : "
- "0.0;\n break;\n case 3:\n alpha = clamp(0.5 + half(approx_dist), "
- "0.0, 1.0);\n break;\n default:\n discard;\n}\n%s = %s * alpha;\n",
- (int)_outer.edgeType, args.fOutputColor, args.fInputColor);
+ R"SkSL(
+half4 inputColor = %s;
+%s = inputColor * alpha;
+)SkSL",
+ _sample4481.c_str(), args.fOutputColor);
}
private:
@@ -125,7 +160,11 @@ GrEllipseEffect::GrEllipseEffect(const GrEllipseEffect& src)
: INHERITED(kGrEllipseEffect_ClassID, src.optimizationFlags())
, edgeType(src.edgeType)
, center(src.center)
- , radii(src.radii) {}
+ , radii(src.radii) {
+ if (src.inputFP_index >= 0) {
+ inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
+ }
+}
std::unique_ptr<GrFragmentProcessor> GrEllipseEffect::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrEllipseEffect(*this));
}
@@ -137,11 +176,14 @@ std::unique_ptr<GrFragmentProcessor> GrEllipseEffect::TestCreate(GrProcessorTest
center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f);
SkScalar rx = testData->fRandom->nextRangeF(0.f, 1000.f);
SkScalar ry = testData->fRandom->nextRangeF(0.f, 1000.f);
- GrClipEdgeType et;
+ bool success;
+ std::unique_ptr<GrFragmentProcessor> fp;
do {
- et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
- } while (GrClipEdgeType::kHairlineAA == et);
- return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry),
- *testData->caps()->shaderCaps());
+ GrClipEdgeType et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
+ std::tie(success, fp) =
+ GrEllipseEffect::Make(/*inputFP=*/nullptr, et, center, SkPoint::Make(rx, ry),
+ *testData->caps()->shaderCaps());
+ } while (!success);
+ return fp;
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.h
index fb746b36c88..6348d97b34d 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrEllipseEffect.h
@@ -10,47 +10,61 @@
**************************************************************************************************/
#ifndef GrEllipseEffect_DEFINED
#define GrEllipseEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrEllipseEffect : public GrFragmentProcessor {
public:
- static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType,
- SkPoint center,
- SkPoint radii,
- const GrShaderCaps& caps) {
+ static GrFPResult Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType,
+ SkPoint center,
+ SkPoint radii,
+ const GrShaderCaps& caps) {
// Small radii produce bad results on devices without full float.
if (!caps.floatIs32Bits() && (radii.fX < 0.5f || radii.fY < 0.5f)) {
- return nullptr;
+ return GrFPFailure(std::move(inputFP));
}
// Very narrow ellipses produce bad results on devices without full float
if (!caps.floatIs32Bits() && (radii.fX > 255 * radii.fY || radii.fY > 255 * radii.fX)) {
- return nullptr;
+ return GrFPFailure(std::move(inputFP));
}
// Very large ellipses produce bad results on devices without full float
if (!caps.floatIs32Bits() && (radii.fX > 16384 || radii.fY > 16384)) {
- return nullptr;
+ return GrFPFailure(std::move(inputFP));
}
- return std::unique_ptr<GrFragmentProcessor>(new GrEllipseEffect(edgeType, center, radii));
+ return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>(
+ new GrEllipseEffect(std::move(inputFP), edgeType, center, radii)));
}
GrEllipseEffect(const GrEllipseEffect& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "EllipseEffect"; }
+ int inputFP_index = -1;
GrClipEdgeType edgeType;
SkPoint center;
SkPoint radii;
private:
- GrEllipseEffect(GrClipEdgeType edgeType, SkPoint center, SkPoint radii)
+ GrEllipseEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrClipEdgeType edgeType,
+ SkPoint center,
+ SkPoint radii)
: INHERITED(kGrEllipseEffect_ClassID,
- (OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag)
+ (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
+ : kAll_OptimizationFlags) &
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, edgeType(edgeType)
, center(center)
- , radii(radii) {}
+ , radii(radii) {
+ if (inputFP) {
+ inputFP_index = this->registerChild(std::move(inputFP));
+ }
+ }
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp
index 11effd21a3e..91796e1f0d7 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp
@@ -23,13 +23,24 @@ public:
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrHSLToRGBFilterEffect& _outer = args.fFp.cast<GrHSLToRGBFilterEffect>();
(void)_outer;
+ SkString _input523(args.fInputColor);
+ SkString _sample523;
+ if (_outer.inputFP_index >= 0) {
+ _sample523 = this->invokeChild(_outer.inputFP_index, _input523.c_str(), args);
+ } else {
+ _sample523.swap(_input523);
+ }
fragBuilder->codeAppendf(
- "half3 hsl = %s.xyz;\nhalf C = (1.0 - abs(2.0 * hsl.z - 1.0)) * hsl.y;\nhalf3 p = "
- "hsl.xxx + half3(0.0, 0.66666666666666663, 0.33333333333333331);\nhalf3 q = "
- "clamp(abs(fract(p) * 6.0 - 3.0) - 1.0, 0.0, 1.0);\nhalf3 rgb = (q - 0.5) * C + "
- "hsl.z;\n%s = clamp(half4(rgb, %s.w), 0.0, 1.0);\n%s.xyz *= %s.w;\n",
- args.fInputColor, args.fOutputColor, args.fInputColor, args.fOutputColor,
- args.fOutputColor);
+ R"SkSL(half4 inputColor = %s;
+half3 hsl = inputColor.xyz;
+half C = (1.0 - abs(2.0 * hsl.z - 1.0)) * hsl.y;
+half3 p = hsl.xxx + half3(0.0, 0.66666666666666663, 0.33333333333333331);
+half3 q = clamp(abs(fract(p) * 6.0 - 3.0) - 1.0, 0.0, 1.0);
+half3 rgb = (q - 0.5) * C + hsl.z;
+%s = clamp(half4(rgb, inputColor.w), 0.0, 1.0);
+%s.xyz *= %s.w;
+)SkSL",
+ _sample523.c_str(), args.fOutputColor, args.fOutputColor, args.fOutputColor);
}
private:
@@ -47,7 +58,11 @@ bool GrHSLToRGBFilterEffect::onIsEqual(const GrFragmentProcessor& other) const {
return true;
}
GrHSLToRGBFilterEffect::GrHSLToRGBFilterEffect(const GrHSLToRGBFilterEffect& src)
- : INHERITED(kGrHSLToRGBFilterEffect_ClassID, src.optimizationFlags()) {}
+ : INHERITED(kGrHSLToRGBFilterEffect_ClassID, src.optimizationFlags()) {
+ if (src.inputFP_index >= 0) {
+ inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
+ }
+}
std::unique_ptr<GrFragmentProcessor> GrHSLToRGBFilterEffect::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrHSLToRGBFilterEffect(*this));
}
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.h
index a86c4af0464..25f10b87206 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrHSLToRGBFilterEffect.h
@@ -10,17 +10,22 @@
**************************************************************************************************/
#ifndef GrHSLToRGBFilterEffect_DEFINED
#define GrHSLToRGBFilterEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrHSLToRGBFilterEffect : public GrFragmentProcessor {
public:
#include "include/private/SkColorData.h"
#include "include/private/SkNx.h"
- SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& c) const override {
+ SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
+ SkPMColor4f c = this->numChildProcessors()
+ ? ConstantOutputForConstantInput(this->childProcessor(0), inColor)
+ : inColor;
const auto H = c[0], S = c[1], L = c[2], C = (1 - std::abs(2 * L - 1)) * S;
const auto p = H + Sk4f(0, 2 / 3.f, 1 / 3.f, 0),
@@ -30,18 +35,25 @@ public:
return SkColor4f{rgba[0], rgba[1], rgba[2], rgba[3]}.premul();
}
- static std::unique_ptr<GrFragmentProcessor> Make() {
- return std::unique_ptr<GrFragmentProcessor>(new GrHSLToRGBFilterEffect());
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP) {
+ return std::unique_ptr<GrFragmentProcessor>(new GrHSLToRGBFilterEffect(std::move(inputFP)));
}
GrHSLToRGBFilterEffect(const GrHSLToRGBFilterEffect& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "HSLToRGBFilterEffect"; }
+ int inputFP_index = -1;
private:
- GrHSLToRGBFilterEffect()
+ GrHSLToRGBFilterEffect(std::unique_ptr<GrFragmentProcessor> inputFP)
: INHERITED(kGrHSLToRGBFilterEffect_ClassID,
- (OptimizationFlags)(kConstantOutputForConstantInput_OptimizationFlag |
- kPreservesOpaqueInput_OptimizationFlag)) {}
+ (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
+ : kAll_OptimizationFlags) &
+ (kConstantOutputForConstantInput_OptimizationFlag |
+ kPreservesOpaqueInput_OptimizationFlag)) {
+ if (inputFP) {
+ inputFP_index = this->registerChild(std::move(inputFP));
+ }
+ }
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp
index c85bc65069b..ec9045b9324 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp
@@ -23,10 +23,20 @@ public:
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrLumaColorFilterEffect& _outer = args.fFp.cast<GrLumaColorFilterEffect>();
(void)_outer;
+ SkString _input953(args.fInputColor);
+ SkString _sample953;
+ if (_outer.inputFP_index >= 0) {
+ _sample953 = this->invokeChild(_outer.inputFP_index, _input953.c_str(), args);
+ } else {
+ _sample953.swap(_input953);
+ }
fragBuilder->codeAppendf(
- "\nhalf luma = clamp(dot(half3(0.2125999927520752, 0.71520000696182251, "
- "0.072200000286102295), %s.xyz), 0.0, 1.0);\n%s = half4(0.0, 0.0, 0.0, luma);\n",
- args.fInputColor, args.fOutputColor);
+ R"SkSL(half4 inputColor = %s;
+
+half luma = clamp(dot(half3(0.2125999927520752, 0.71520000696182251, 0.072200000286102295), inputColor.xyz), 0.0, 1.0);
+%s = half4(0.0, 0.0, 0.0, luma);
+)SkSL",
+ _sample953.c_str(), args.fOutputColor);
}
private:
@@ -44,7 +54,11 @@ bool GrLumaColorFilterEffect::onIsEqual(const GrFragmentProcessor& other) const
return true;
}
GrLumaColorFilterEffect::GrLumaColorFilterEffect(const GrLumaColorFilterEffect& src)
- : INHERITED(kGrLumaColorFilterEffect_ClassID, src.optimizationFlags()) {}
+ : INHERITED(kGrLumaColorFilterEffect_ClassID, src.optimizationFlags()) {
+ if (src.inputFP_index >= 0) {
+ inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
+ }
+}
std::unique_ptr<GrFragmentProcessor> GrLumaColorFilterEffect::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrLumaColorFilterEffect(*this));
}
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.h
index 3ee5c06aede..274958efef9 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrLumaColorFilterEffect.h
@@ -10,31 +10,45 @@
**************************************************************************************************/
#ifndef GrLumaColorFilterEffect_DEFINED
#define GrLumaColorFilterEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrLumaColorFilterEffect : public GrFragmentProcessor {
public:
#include "include/private/SkColorData.h"
- SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
+ SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
+ SkPMColor4f input = this->numChildProcessors()
+ ? ConstantOutputForConstantInput(
+ this->childProcessor(inputFP_index), inColor)
+ : inColor;
float luma = SK_ITU_BT709_LUM_COEFF_R * input.fR + SK_ITU_BT709_LUM_COEFF_G * input.fG +
SK_ITU_BT709_LUM_COEFF_B * input.fB;
return {0, 0, 0, SkTPin(luma, 0.0f, 1.0f)};
}
- static std::unique_ptr<GrFragmentProcessor> Make() {
- return std::unique_ptr<GrFragmentProcessor>(new GrLumaColorFilterEffect());
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP) {
+ return std::unique_ptr<GrFragmentProcessor>(
+ new GrLumaColorFilterEffect(std::move(inputFP)));
}
GrLumaColorFilterEffect(const GrLumaColorFilterEffect& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "LumaColorFilterEffect"; }
+ int inputFP_index = -1;
private:
- GrLumaColorFilterEffect()
+ GrLumaColorFilterEffect(std::unique_ptr<GrFragmentProcessor> inputFP)
: INHERITED(kGrLumaColorFilterEffect_ClassID,
- (OptimizationFlags)kConstantOutputForConstantInput_OptimizationFlag) {}
+ (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
+ : kAll_OptimizationFlags) &
+ kConstantOutputForConstantInput_OptimizationFlag) {
+ if (inputFP) {
+ inputFP_index = this->registerChild(std::move(inputFP));
+ }
+ }
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.cpp
index 0746fbf6c60..acc344d4a86 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.cpp
@@ -35,44 +35,51 @@ public:
(void)xInvInset;
auto yInvInset = _outer.yInvInset;
(void)yInvInset;
- boundsUniformVar = args.fUniformHandler->addUniform(
- &_outer, kFragment_GrShaderFlag, kFloat4_GrSLType, "boundsUniform");
- xInvZoomVar = args.fUniformHandler->addUniform(
- &_outer, kFragment_GrShaderFlag, kFloat_GrSLType, "xInvZoom");
- yInvZoomVar = args.fUniformHandler->addUniform(
- &_outer, kFragment_GrShaderFlag, kFloat_GrSLType, "yInvZoom");
- xInvInsetVar = args.fUniformHandler->addUniform(
- &_outer, kFragment_GrShaderFlag, kFloat_GrSLType, "xInvInset");
- yInvInsetVar = args.fUniformHandler->addUniform(
- &_outer, kFragment_GrShaderFlag, kFloat_GrSLType, "yInvInset");
- offsetVar = args.fUniformHandler->addUniform(
- &_outer, kFragment_GrShaderFlag, kHalf2_GrSLType, "offset");
+ boundsUniformVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
+ kFloat4_GrSLType, "boundsUniform");
+ xInvZoomVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
+ kFloat_GrSLType, "xInvZoom");
+ yInvZoomVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
+ kFloat_GrSLType, "yInvZoom");
+ xInvInsetVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
+ kFloat_GrSLType, "xInvInset");
+ yInvInsetVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
+ kFloat_GrSLType, "yInvInset");
+ offsetVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
+ kHalf2_GrSLType, "offset");
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(
args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix());
fragBuilder->codeAppendf(
- "float2 coord = %s;\nfloat2 zoom_coord = float2(%s) + coord * float2(%s, "
- "%s);\nfloat2 delta = (coord - %s.xy) * %s.zw;\ndelta = min(delta, "
- "float2(half2(1.0, 1.0)) - delta);\ndelta *= float2(%s, %s);\nfloat weight = "
- "0.0;\nif (delta.x < 2.0 && delta.y < 2.0) {\n delta = float2(half2(2.0, 2.0)) "
- "- delta;\n float dist = length(delta);\n dist = max(2.0 - dist, 0.0);\n "
- "weight = min(dist * dist, 1.0);\n} else {\n float2 delta_squared = delta * "
- "delta;\n weight = min(min(delta_squared.x, delta_square",
- sk_TransformedCoords2D_0.c_str(),
- args.fUniformHandler->getUniformCStr(offsetVar),
+ R"SkSL(float2 coord = %s;
+float2 zoom_coord = float2(%s) + coord * float2(%s, %s);
+float2 delta = (coord - %s.xy) * %s.zw;
+delta = min(delta, float2(half2(1.0, 1.0)) - delta);
+delta *= float2(%s, %s);
+float weight = 0.0;
+if (delta.x < 2.0 && delta.y < 2.0) {
+ delta = float2(half2(2.0, 2.0)) - delta;
+ float dist = length(delta);
+ dist = max(2.0 - dist, 0.0);
+ weight = min(dist * dist, 1.0);
+} else {
+ float2 delta_squared = delta * delta;
+ weight = min(min(delta_squared.x, delta_squared.y), 1.0);
+})SkSL",
+ sk_TransformedCoords2D_0.c_str(), args.fUniformHandler->getUniformCStr(offsetVar),
args.fUniformHandler->getUniformCStr(xInvZoomVar),
args.fUniformHandler->getUniformCStr(yInvZoomVar),
args.fUniformHandler->getUniformCStr(boundsUniformVar),
args.fUniformHandler->getUniformCStr(boundsUniformVar),
args.fUniformHandler->getUniformCStr(xInvInsetVar),
args.fUniformHandler->getUniformCStr(yInvInsetVar));
+ SkString _sample1112;
+ SkString _coords1112("mix(coord, zoom_coord, weight)");
+ _sample1112 = this->invokeChild(_outer.src_index, args, _coords1112.c_str());
fragBuilder->codeAppendf(
- "d.y), 1.0);\n}\n%s = sample(%s, mix(coord, zoom_coord, weight)).%s;\n",
- args.fOutputColor,
- fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
- fragBuilder->getProgramBuilder()
- ->samplerSwizzle(args.fTexSamplers[0])
- .asString()
- .c_str());
+ R"SkSL(
+%s = %s;
+)SkSL",
+ args.fOutputColor, _sample1112.c_str());
}
private:
@@ -85,9 +92,6 @@ private:
pdman.set1f(xInvInsetVar, (_outer.xInvInset));
pdman.set1f(yInvInsetVar, (_outer.yInvInset));
}
- const GrSurfaceProxyView& srcView = _outer.textureSampler(0).view();
- GrTexture& src = *srcView.proxy()->peekTexture();
- (void)src;
auto bounds = _outer.bounds;
(void)bounds;
UniformHandle& boundsUniform = boundsUniformVar;
@@ -105,32 +109,9 @@ private:
UniformHandle& offset = offsetVar;
(void)offset;
- SkScalar invW = 1.0f / src.width();
- SkScalar invH = 1.0f / src.height();
-
- {
- SkScalar y = srcRect.y() * invH;
- if (srcView.origin() != kTopLeft_GrSurfaceOrigin) {
- y = 1.0f - (srcRect.height() / bounds.height()) - y;
- }
-
- pdman.set2f(offset, srcRect.x() * invW, y);
- }
-
- {
- SkScalar y = bounds.y() * invH;
- SkScalar hSign = 1.f;
- if (srcView.origin() != kTopLeft_GrSurfaceOrigin) {
- y = 1.0f - bounds.y() * invH;
- hSign = -1.f;
- }
-
- pdman.set4f(boundsUniform,
- bounds.x() * invW,
- y,
- SkIntToScalar(src.width()) / bounds.width(),
- hSign * SkIntToScalar(src.height()) / bounds.height());
- }
+ pdman.set2f(offset, srcRect.x(), srcRect.y());
+ pdman.set4f(boundsUniform, bounds.x(), bounds.y(), 1.f / bounds.width(),
+ 1.f / bounds.height());
}
UniformHandle boundsUniformVar;
UniformHandle offsetVar;
@@ -147,7 +128,6 @@ void GrMagnifierEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
bool GrMagnifierEffect::onIsEqual(const GrFragmentProcessor& other) const {
const GrMagnifierEffect& that = other.cast<GrMagnifierEffect>();
(void)that;
- if (src != that.src) return false;
if (bounds != that.bounds) return false;
if (srcRect != that.srcRect) return false;
if (xInvZoom != that.xInvZoom) return false;
@@ -158,27 +138,22 @@ bool GrMagnifierEffect::onIsEqual(const GrFragmentProcessor& other) const {
}
GrMagnifierEffect::GrMagnifierEffect(const GrMagnifierEffect& src)
: INHERITED(kGrMagnifierEffect_ClassID, src.optimizationFlags())
- , srcCoordTransform(src.srcCoordTransform)
- , src(src.src)
+ , fCoordTransform0(src.fCoordTransform0)
, bounds(src.bounds)
, srcRect(src.srcRect)
, xInvZoom(src.xInvZoom)
, yInvZoom(src.yInvZoom)
, xInvInset(src.xInvInset)
, yInvInset(src.yInvInset) {
- this->setTextureSamplerCnt(1);
- this->addCoordTransform(&srcCoordTransform);
+ { src_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.src_index)); }
+ this->addCoordTransform(&fCoordTransform0);
}
std::unique_ptr<GrFragmentProcessor> GrMagnifierEffect::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrMagnifierEffect(*this));
}
-const GrFragmentProcessor::TextureSampler& GrMagnifierEffect::onTextureSampler(int index) const {
- return IthTextureSampler(index, src);
-}
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrMagnifierEffect);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrMagnifierEffect::TestCreate(GrProcessorTestData* d) {
- auto[view, ct, at] = d->randomView();
const int kMaxWidth = 200;
const int kMaxHeight = 200;
const SkScalar kMaxInset = 20.0f;
@@ -189,7 +164,8 @@ std::unique_ptr<GrFragmentProcessor> GrMagnifierEffect::TestCreate(GrProcessorTe
SkIRect bounds = SkIRect::MakeWH(SkIntToScalar(kMaxWidth), SkIntToScalar(kMaxHeight));
SkRect srcRect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
- auto effect = GrMagnifierEffect::Make(std::move(view),
+ auto src = GrProcessorUnitTest::MakeChildFP(d);
+ auto effect = GrMagnifierEffect::Make(std::move(src),
bounds,
srcRect,
srcRect.width() / bounds.width(),
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.h
index ab930d9cdb3..aff287f30a3 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrMagnifierEffect.h
@@ -10,14 +10,16 @@
**************************************************************************************************/
#ifndef GrMagnifierEffect_DEFINED
#define GrMagnifierEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrMagnifierEffect : public GrFragmentProcessor {
public:
- static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView src,
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> src,
SkIRect bounds,
SkRect srcRect,
float xInvZoom,
@@ -30,8 +32,8 @@ public:
GrMagnifierEffect(const GrMagnifierEffect& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "MagnifierEffect"; }
- GrCoordTransform srcCoordTransform;
- TextureSampler src;
+ GrCoordTransform fCoordTransform0;
+ int src_index = -1;
SkIRect bounds;
SkRect srcRect;
float xInvZoom;
@@ -40,7 +42,7 @@ public:
float yInvInset;
private:
- GrMagnifierEffect(GrSurfaceProxyView src,
+ GrMagnifierEffect(std::unique_ptr<GrFragmentProcessor> src,
SkIRect bounds,
SkRect srcRect,
float xInvZoom,
@@ -48,21 +50,20 @@ private:
float xInvInset,
float yInvInset)
: INHERITED(kGrMagnifierEffect_ClassID, kNone_OptimizationFlags)
- , srcCoordTransform(SkMatrix::I(), src.proxy(), src.origin())
- , src(std::move(src))
+ , fCoordTransform0(SkMatrix::I())
, bounds(bounds)
, srcRect(srcRect)
, xInvZoom(xInvZoom)
, yInvZoom(yInvZoom)
, xInvInset(xInvInset)
, yInvInset(yInvInset) {
- this->setTextureSamplerCnt(1);
- this->addCoordTransform(&srcCoordTransform);
+ SkASSERT(src);
+ src_index = this->registerExplicitlySampledChild(std::move(src));
+ this->addCoordTransform(&fCoordTransform0);
}
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
- const TextureSampler& onTextureSampler(int) const override;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
typedef GrFragmentProcessor INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrMatrixEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrMatrixEffect.cpp
deleted file mode 100644
index fa8b6910e2b..00000000000
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrMatrixEffect.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2020 Google LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/**************************************************************************************************
- *** This file was autogenerated from GrMatrixEffect.fp; do not modify.
- **************************************************************************************************/
-#include "GrMatrixEffect.h"
-
-#include "src/gpu/GrTexture.h"
-#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
-#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
-#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
-#include "src/sksl/SkSLCPP.h"
-#include "src/sksl/SkSLUtil.h"
-class GrGLSLMatrixEffect : public GrGLSLFragmentProcessor {
-public:
- GrGLSLMatrixEffect() {}
- void emitCode(EmitArgs& args) override {
- GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
- const GrMatrixEffect& _outer = args.fFp.cast<GrMatrixEffect>();
- (void)_outer;
- auto matrix = _outer.matrix;
- (void)matrix;
- matrixVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
- kFloat3x3_GrSLType, "matrix");
- SkString _input716 = SkStringPrintf("%s", args.fInputColor);
- SkString _sample716;
- _sample716 = this->invokeChild(_outer.child_index, _input716.c_str(), args);
- fragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, _sample716.c_str());
- }
-
-private:
- void onSetData(const GrGLSLProgramDataManager& pdman,
- const GrFragmentProcessor& _proc) override {
- const GrMatrixEffect& _outer = _proc.cast<GrMatrixEffect>();
- { pdman.setSkMatrix(matrixVar, (_outer.matrix)); }
- }
- UniformHandle matrixVar;
-};
-GrGLSLFragmentProcessor* GrMatrixEffect::onCreateGLSLInstance() const {
- return new GrGLSLMatrixEffect();
-}
-void GrMatrixEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
- GrProcessorKeyBuilder* b) const {}
-bool GrMatrixEffect::onIsEqual(const GrFragmentProcessor& other) const {
- const GrMatrixEffect& that = other.cast<GrMatrixEffect>();
- (void)that;
- if (matrix != that.matrix) return false;
- return true;
-}
-GrMatrixEffect::GrMatrixEffect(const GrMatrixEffect& src)
- : INHERITED(kGrMatrixEffect_ClassID, src.optimizationFlags())
- , matrix(src.matrix)
- , child_index(src.child_index) {
- {
- auto clone = src.childProcessor(child_index).clone();
- if (src.childProcessor(child_index).isSampledWithExplicitCoords()) {
- clone->setSampledWithExplicitCoords();
- }
- this->registerChildProcessor(std::move(clone));
- }
-}
-std::unique_ptr<GrFragmentProcessor> GrMatrixEffect::clone() const {
- return std::unique_ptr<GrFragmentProcessor>(new GrMatrixEffect(*this));
-}
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.cpp
index fea85f413a5..1dbf8ecabec 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.cpp
@@ -27,21 +27,25 @@ public:
(void)weight;
weightVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
kHalf_GrSLType, "weight");
- SkString _input1278 = SkStringPrintf("%s", args.fInputColor);
+ SkString _input1278(args.fInputColor);
SkString _sample1278;
_sample1278 = this->invokeChild(_outer.fp0_index, _input1278.c_str(), args);
- fragBuilder->codeAppendf("half4 in0 = %s;", _sample1278.c_str());
- SkString _input1335 = SkStringPrintf("%s", args.fInputColor);
+ fragBuilder->codeAppendf(
+ R"SkSL(half4 in0 = %s;)SkSL", _sample1278.c_str());
+ SkString _input1335(args.fInputColor);
SkString _sample1335;
if (_outer.fp1_index >= 0) {
_sample1335 = this->invokeChild(_outer.fp1_index, _input1335.c_str(), args);
} else {
- _sample1335 = "half4(1)";
+ _sample1335.swap(_input1335);
}
- fragBuilder->codeAppendf("\nhalf4 in1 = %s ? %s : %s;\n%s = mix(in0, in1, %s);\n",
- _outer.fp1_index >= 0 ? "true" : "false", _sample1335.c_str(),
- args.fInputColor, args.fOutputColor,
- args.fUniformHandler->getUniformCStr(weightVar));
+ fragBuilder->codeAppendf(
+ R"SkSL(
+half4 in1 = %s ? %s : %s;
+%s = mix(in0, in1, %s);
+)SkSL",
+ _outer.fp1_index >= 0 ? "true" : "false", _sample1335.c_str(), args.fInputColor,
+ args.fOutputColor, args.fUniformHandler->getUniformCStr(weightVar));
}
private:
@@ -64,23 +68,10 @@ bool GrMixerEffect::onIsEqual(const GrFragmentProcessor& other) const {
return true;
}
GrMixerEffect::GrMixerEffect(const GrMixerEffect& src)
- : INHERITED(kGrMixerEffect_ClassID, src.optimizationFlags())
- , fp0_index(src.fp0_index)
- , fp1_index(src.fp1_index)
- , weight(src.weight) {
- {
- auto clone = src.childProcessor(fp0_index).clone();
- if (src.childProcessor(fp0_index).isSampledWithExplicitCoords()) {
- clone->setSampledWithExplicitCoords();
- }
- this->registerChildProcessor(std::move(clone));
- }
- if (fp1_index >= 0) {
- auto clone = src.childProcessor(fp1_index).clone();
- if (src.childProcessor(fp1_index).isSampledWithExplicitCoords()) {
- clone->setSampledWithExplicitCoords();
- }
- this->registerChildProcessor(std::move(clone));
+ : INHERITED(kGrMixerEffect_ClassID, src.optimizationFlags()), weight(src.weight) {
+ { fp0_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.fp0_index)); }
+ if (src.fp1_index >= 0) {
+ fp1_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.fp1_index));
}
}
std::unique_ptr<GrFragmentProcessor> GrMixerEffect::clone() const {
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.h
index a9e3717f885..391fbf6bdb8 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrMixerEffect.h
@@ -10,11 +10,13 @@
**************************************************************************************************/
#ifndef GrMixerEffect_DEFINED
#define GrMixerEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrMixerEffect : public GrFragmentProcessor {
public:
static OptimizationFlags OptFlags(const std::unique_ptr<GrFragmentProcessor>& fp0,
@@ -54,11 +56,9 @@ private:
: INHERITED(kGrMixerEffect_ClassID, (OptimizationFlags)OptFlags(fp0, fp1))
, weight(weight) {
SkASSERT(fp0);
- fp0_index = this->numChildProcessors();
- this->registerChildProcessor(std::move(fp0));
+ fp0_index = this->registerChild(std::move(fp0));
if (fp1) {
- fp1_index = this->numChildProcessors();
- this->registerChildProcessor(std::move(fp1));
+ fp1_index = this->registerChild(std::move(fp1));
}
}
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp
index 0e34b530003..deae796c1b1 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp
@@ -35,8 +35,12 @@ public:
kHalf4_GrSLType, "uniformColor");
}
fragBuilder->codeAppendf(
- "half4 constColor;\n@if (%s) {\n constColor = %s;\n} else {\n constColor = "
- "half4(%f, %f, %f, %f);\n}",
+ R"SkSL(half4 constColor;
+@if (%s) {
+ constColor = %s;
+} else {
+ constColor = half4(%f, %f, %f, %f);
+})SkSL",
(_outer.useUniform ? "true" : "false"),
uniformColorVar.isValid() ? args.fUniformHandler->getUniformCStr(uniformColorVar)
: "half4(0)",
@@ -45,7 +49,11 @@ public:
SkString _input1992("constColor");
SkString _sample1992;
_sample1992 = this->invokeChild(_outer.fp_index, _input1992.c_str(), args);
- fragBuilder->codeAppendf("\n%s = %s;\n", args.fOutputColor, _sample1992.c_str());
+ fragBuilder->codeAppendf(
+ R"SkSL(
+%s = %s;
+)SkSL",
+ args.fOutputColor, _sample1992.c_str());
}
private:
@@ -87,17 +95,10 @@ bool GrOverrideInputFragmentProcessor::onIsEqual(const GrFragmentProcessor& othe
GrOverrideInputFragmentProcessor::GrOverrideInputFragmentProcessor(
const GrOverrideInputFragmentProcessor& src)
: INHERITED(kGrOverrideInputFragmentProcessor_ClassID, src.optimizationFlags())
- , fp_index(src.fp_index)
, useUniform(src.useUniform)
, uniformColor(src.uniformColor)
, literalColor(src.literalColor) {
- {
- auto clone = src.childProcessor(fp_index).clone();
- if (src.childProcessor(fp_index).isSampledWithExplicitCoords()) {
- clone->setSampledWithExplicitCoords();
- }
- this->registerChildProcessor(std::move(clone));
- }
+ { fp_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.fp_index)); }
}
std::unique_ptr<GrFragmentProcessor> GrOverrideInputFragmentProcessor::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrOverrideInputFragmentProcessor(*this));
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h
index d69c16ebbbe..988b1caf0c4 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h
@@ -10,11 +10,13 @@
**************************************************************************************************/
#ifndef GrOverrideInputFragmentProcessor_DEFINED
#define GrOverrideInputFragmentProcessor_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrOverrideInputFragmentProcessor : public GrFragmentProcessor {
public:
static OptimizationFlags OptFlags(const std::unique_ptr<GrFragmentProcessor>& fp,
@@ -59,8 +61,7 @@ private:
, uniformColor(uniformColor)
, literalColor(literalColor) {
SkASSERT(fp);
- fp_index = this->numChildProcessors();
- this->registerChildProcessor(std::move(fp));
+ fp_index = this->registerChild(std::move(fp));
}
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrPremulInputFragmentProcessor.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrPremulInputFragmentProcessor.cpp
deleted file mode 100644
index f327850bdb9..00000000000
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrPremulInputFragmentProcessor.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/**************************************************************************************************
- *** This file was autogenerated from GrPremulInputFragmentProcessor.fp; do not modify.
- **************************************************************************************************/
-#include "GrPremulInputFragmentProcessor.h"
-
-#include "src/gpu/GrTexture.h"
-#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
-#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
-#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
-#include "src/sksl/SkSLCPP.h"
-#include "src/sksl/SkSLUtil.h"
-class GrGLSLPremulInputFragmentProcessor : public GrGLSLFragmentProcessor {
-public:
- GrGLSLPremulInputFragmentProcessor() {}
- void emitCode(EmitArgs& args) override {
- GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
- const GrPremulInputFragmentProcessor& _outer =
- args.fFp.cast<GrPremulInputFragmentProcessor>();
- (void)_outer;
- fragBuilder->codeAppendf("%s = %s;\n%s.xyz *= %s.w;\n", args.fOutputColor, args.fInputColor,
- args.fOutputColor, args.fInputColor);
- }
-
-private:
- void onSetData(const GrGLSLProgramDataManager& pdman,
- const GrFragmentProcessor& _proc) override {}
-};
-GrGLSLFragmentProcessor* GrPremulInputFragmentProcessor::onCreateGLSLInstance() const {
- return new GrGLSLPremulInputFragmentProcessor();
-}
-void GrPremulInputFragmentProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps,
- GrProcessorKeyBuilder* b) const {}
-bool GrPremulInputFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const {
- const GrPremulInputFragmentProcessor& that = other.cast<GrPremulInputFragmentProcessor>();
- (void)that;
- return true;
-}
-GrPremulInputFragmentProcessor::GrPremulInputFragmentProcessor(
- const GrPremulInputFragmentProcessor& src)
- : INHERITED(kGrPremulInputFragmentProcessor_ClassID, src.optimizationFlags()) {}
-std::unique_ptr<GrFragmentProcessor> GrPremulInputFragmentProcessor::clone() const {
- return std::unique_ptr<GrFragmentProcessor>(new GrPremulInputFragmentProcessor(*this));
-}
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrPremulInputFragmentProcessor.h b/chromium/third_party/skia/src/gpu/effects/generated/GrPremulInputFragmentProcessor.h
deleted file mode 100644
index ae093ca6daf..00000000000
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrPremulInputFragmentProcessor.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/**************************************************************************************************
- *** This file was autogenerated from GrPremulInputFragmentProcessor.fp; do not modify.
- **************************************************************************************************/
-#ifndef GrPremulInputFragmentProcessor_DEFINED
-#define GrPremulInputFragmentProcessor_DEFINED
-#include "include/core/SkTypes.h"
-#include "include/core/SkM44.h"
-
-#include "src/gpu/GrCoordTransform.h"
-#include "src/gpu/GrFragmentProcessor.h"
-class GrPremulInputFragmentProcessor : public GrFragmentProcessor {
-public:
- SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
- return SkColor4f{input.fR, input.fG, input.fB, input.fA}.premul();
- }
- static std::unique_ptr<GrFragmentProcessor> Make() {
- return std::unique_ptr<GrFragmentProcessor>(new GrPremulInputFragmentProcessor());
- }
- GrPremulInputFragmentProcessor(const GrPremulInputFragmentProcessor& src);
- std::unique_ptr<GrFragmentProcessor> clone() const override;
- const char* name() const override { return "PremulInputFragmentProcessor"; }
-
-private:
- GrPremulInputFragmentProcessor()
- : INHERITED(kGrPremulInputFragmentProcessor_ClassID,
- (OptimizationFlags)kPreservesOpaqueInput_OptimizationFlag |
- kConstantOutputForConstantInput_OptimizationFlag) {}
- GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
- void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
- bool onIsEqual(const GrFragmentProcessor&) const override;
- GR_DECLARE_FRAGMENT_PROCESSOR_TEST
- typedef GrFragmentProcessor INHERITED;
-};
-#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp
index 6d93aa9ad2f..a2acd522195 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp
@@ -23,15 +23,27 @@ public:
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrRGBToHSLFilterEffect& _outer = args.fFp.cast<GrRGBToHSLFilterEffect>();
(void)_outer;
+ SkString _input1173(args.fInputColor);
+ SkString _sample1173;
+ if (_outer.inputFP_index >= 0) {
+ _sample1173 = this->invokeChild(_outer.inputFP_index, _input1173.c_str(), args);
+ } else {
+ _sample1173.swap(_input1173);
+ }
fragBuilder->codeAppendf(
- "half4 c = %s;\nhalf4 p = c.y < c.z ? half4(c.zy, -1.0, 0.66666666666666663) : "
- "half4(c.yz, 0.0, -0.33333333333333331);\nhalf4 q = c.x < p.x ? half4(p.x, c.x, "
- "p.yw) : half4(c.x, p.x, p.yz);\n\nhalf pmV = q.x;\nhalf pmC = pmV - min(q.y, "
- "q.z);\nhalf pmL = pmV - pmC * 0.5;\nhalf H = abs(q.w + (q.y - q.z) / (pmC * 6.0 + "
- "9.9999997473787516e-05));\nhalf S = pmC / ((c.w + 9.9999997473787516e-05) - "
- "abs(pmL * 2.0 - c.w));\nhalf L = pmL / (c.w + 9.9999997473787516e-05);\n%s = "
- "half4(H, S, L, c.w);\n",
- args.fInputColor, args.fOutputColor);
+ R"SkSL(half4 c = %s;
+half4 p = c.y < c.z ? half4(c.zy, -1.0, 0.66666666666666663) : half4(c.yz, 0.0, -0.33333333333333331);
+half4 q = c.x < p.x ? half4(p.x, c.x, p.yw) : half4(c.x, p.x, p.yz);
+
+half pmV = q.x;
+half pmC = pmV - min(q.y, q.z);
+half pmL = pmV - pmC * 0.5;
+half H = abs(q.w + (q.y - q.z) / (pmC * 6.0 + 9.9999997473787516e-05));
+half S = pmC / ((c.w + 9.9999997473787516e-05) - abs(pmL * 2.0 - c.w));
+half L = pmL / (c.w + 9.9999997473787516e-05);
+%s = half4(H, S, L, c.w);
+)SkSL",
+ _sample1173.c_str(), args.fOutputColor);
}
private:
@@ -49,7 +61,11 @@ bool GrRGBToHSLFilterEffect::onIsEqual(const GrFragmentProcessor& other) const {
return true;
}
GrRGBToHSLFilterEffect::GrRGBToHSLFilterEffect(const GrRGBToHSLFilterEffect& src)
- : INHERITED(kGrRGBToHSLFilterEffect_ClassID, src.optimizationFlags()) {}
+ : INHERITED(kGrRGBToHSLFilterEffect_ClassID, src.optimizationFlags()) {
+ if (src.inputFP_index >= 0) {
+ inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
+ }
+}
std::unique_ptr<GrFragmentProcessor> GrRGBToHSLFilterEffect::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrRGBToHSLFilterEffect(*this));
}
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.h
index e8e0bba7561..4b5fdccd835 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrRGBToHSLFilterEffect.h
@@ -10,16 +10,21 @@
**************************************************************************************************/
#ifndef GrRGBToHSLFilterEffect_DEFINED
#define GrRGBToHSLFilterEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrRGBToHSLFilterEffect : public GrFragmentProcessor {
public:
#include "include/private/SkColorData.h"
- SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& c) const override {
+ SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
+ SkPMColor4f c = this->numChildProcessors()
+ ? ConstantOutputForConstantInput(this->childProcessor(0), inColor)
+ : inColor;
const auto p = (c.fG < c.fB) ? SkPMColor4f{c.fB, c.fG, -1, 2 / 3.f}
: SkPMColor4f{c.fG, c.fB, 0, -1 / 3.f},
q = (c.fR < p[0]) ? SkPMColor4f{p[0], c.fR, p[1], p[3]}
@@ -32,18 +37,25 @@ public:
return {H, S, L, c.fA};
}
- static std::unique_ptr<GrFragmentProcessor> Make() {
- return std::unique_ptr<GrFragmentProcessor>(new GrRGBToHSLFilterEffect());
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP) {
+ return std::unique_ptr<GrFragmentProcessor>(new GrRGBToHSLFilterEffect(std::move(inputFP)));
}
GrRGBToHSLFilterEffect(const GrRGBToHSLFilterEffect& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "RGBToHSLFilterEffect"; }
+ int inputFP_index = -1;
private:
- GrRGBToHSLFilterEffect()
+ GrRGBToHSLFilterEffect(std::unique_ptr<GrFragmentProcessor> inputFP)
: INHERITED(kGrRGBToHSLFilterEffect_ClassID,
- (OptimizationFlags)(kConstantOutputForConstantInput_OptimizationFlag |
- kPreservesOpaqueInput_OptimizationFlag)) {}
+ (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
+ : kAll_OptimizationFlags) &
+ (kConstantOutputForConstantInput_OptimizationFlag |
+ kPreservesOpaqueInput_OptimizationFlag)) {
+ if (inputFP) {
+ inputFP_index = this->registerChild(std::move(inputFP));
+ }
+ }
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.cpp
index 74a49b102e0..968ab1e0ee6 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.cpp
@@ -10,11 +10,13 @@
**************************************************************************************************/
#include "GrRRectBlurEffect.h"
-std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::Make(GrRecordingContext* context,
- float sigma,
- float xformedSigma,
- const SkRRect& srcRRect,
- const SkRRect& devRRect) {
+std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::Make(
+ std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrRecordingContext* context,
+ float sigma,
+ float xformedSigma,
+ const SkRRect& srcRRect,
+ const SkRRect& devRRect) {
SkASSERT(!SkRRectPriv::IsCircle(devRRect) &&
!devRRect.isRect()); // Should've been caught up-stream
@@ -39,15 +41,15 @@ std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::Make(GrRecordingContext*
return nullptr;
}
- GrSurfaceProxyView mask =
- find_or_create_rrect_blur_mask(context, rrectToDraw, dimensions, xformedSigma);
- if (!mask) {
+ std::unique_ptr<GrFragmentProcessor> maskFP =
+ find_or_create_rrect_blur_mask_fp(context, rrectToDraw, dimensions, xformedSigma);
+ if (!maskFP) {
return nullptr;
}
return std::unique_ptr<GrFragmentProcessor>(
- new GrRRectBlurEffect(xformedSigma, devRRect.getBounds(),
- SkRRectPriv::GetSimpleRadii(devRRect).fX, std::move(mask)));
+ new GrRRectBlurEffect(std::move(inputFP), xformedSigma, devRRect.getBounds(),
+ SkRRectPriv::GetSimpleRadii(devRRect).fX, std::move(maskFP)));
}
#include "src/gpu/GrTexture.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
@@ -75,29 +77,42 @@ public:
blurRadiusVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
kHalf_GrSLType, "blurRadius");
fragBuilder->codeAppendf(
- "\nhalf2 translatedFragPos = half2(sk_FragCoord.xy - %s.xy);\nhalf threshold = %s "
- "+ 2.0 * %s;\nhalf2 middle = half2((%s.zw - %s.xy) - float(2.0 * threshold));\nif "
- "(translatedFragPos.x >= threshold && translatedFragPos.x < middle.x + threshold) "
- "{\n translatedFragPos.x = threshold;\n} else if (translatedFragPos.x >= "
- "middle.x + threshold) {\n translatedFragPos.x -= middle.x - 1.0;\n}\nif "
- "(translatedFragPos.y > threshold && translatedFragPos.y < middle.y + threshold) "
- "{\n translatedFragPos.y = threshold;",
+ R"SkSL(half2 translatedFragPos = half2(sk_FragCoord.xy - %s.xy);
+half2 proxyCenter = half2((%s.zw - %s.xy) * 0.5);
+half edgeSize = (2.0 * %s + %s) + 0.5;
+translatedFragPos -= proxyCenter;
+half2 fragDirection = sign(translatedFragPos);
+translatedFragPos = abs(translatedFragPos);
+translatedFragPos -= proxyCenter - edgeSize;
+translatedFragPos = max(translatedFragPos, 0.0);
+translatedFragPos *= fragDirection;
+translatedFragPos += half2(edgeSize);
+half2 proxyDims = half2(2.0 * edgeSize);
+half2 texCoord = translatedFragPos / proxyDims;)SkSL",
+ args.fUniformHandler->getUniformCStr(proxyRectVar),
args.fUniformHandler->getUniformCStr(proxyRectVar),
- args.fUniformHandler->getUniformCStr(cornerRadiusVar),
- args.fUniformHandler->getUniformCStr(blurRadiusVar),
args.fUniformHandler->getUniformCStr(proxyRectVar),
- args.fUniformHandler->getUniformCStr(proxyRectVar));
+ args.fUniformHandler->getUniformCStr(blurRadiusVar),
+ args.fUniformHandler->getUniformCStr(cornerRadiusVar));
+ SkString _input9604(args.fInputColor);
+ SkString _sample9604;
+ if (_outer.inputFP_index >= 0) {
+ _sample9604 = this->invokeChild(_outer.inputFP_index, _input9604.c_str(), args);
+ } else {
+ _sample9604.swap(_input9604);
+ }
+ fragBuilder->codeAppendf(
+ R"SkSL(
+half4 inputColor = %s;)SkSL",
+ _sample9604.c_str());
+ SkString _sample9664;
+ SkString _coords9664("float2(texCoord)");
+ _sample9664 = this->invokeChild(_outer.ninePatchFP_index, args, _coords9664.c_str());
fragBuilder->codeAppendf(
- "\n} else if (translatedFragPos.y >= middle.y + threshold) {\n "
- "translatedFragPos.y -= middle.y - 1.0;\n}\nhalf2 proxyDims = half2(2.0 * "
- "threshold + 1.0);\nhalf2 texCoord = translatedFragPos / proxyDims;\n%s = %s * "
- "sample(%s, float2(texCoord)).%s;\n",
- args.fOutputColor, args.fInputColor,
- fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
- fragBuilder->getProgramBuilder()
- ->samplerSwizzle(args.fTexSamplers[0])
- .asString()
- .c_str());
+ R"SkSL(
+%s = inputColor * %s;
+)SkSL",
+ args.fOutputColor, _sample9664.c_str());
}
private:
@@ -111,9 +126,6 @@ private:
(void)rect;
UniformHandle& cornerRadius = cornerRadiusVar;
(void)cornerRadius;
- const GrSurfaceProxyView& ninePatchSamplerView = _outer.textureSampler(0).view();
- GrTexture& ninePatchSampler = *ninePatchSamplerView.proxy()->peekTexture();
- (void)ninePatchSampler;
UniformHandle& proxyRect = proxyRectVar;
(void)proxyRect;
UniformHandle& blurRadius = blurRadiusVar;
@@ -141,23 +153,24 @@ bool GrRRectBlurEffect::onIsEqual(const GrFragmentProcessor& other) const {
if (sigma != that.sigma) return false;
if (rect != that.rect) return false;
if (cornerRadius != that.cornerRadius) return false;
- if (ninePatchSampler != that.ninePatchSampler) return false;
return true;
}
GrRRectBlurEffect::GrRRectBlurEffect(const GrRRectBlurEffect& src)
: INHERITED(kGrRRectBlurEffect_ClassID, src.optimizationFlags())
, sigma(src.sigma)
, rect(src.rect)
- , cornerRadius(src.cornerRadius)
- , ninePatchSampler(src.ninePatchSampler) {
- this->setTextureSamplerCnt(1);
+ , cornerRadius(src.cornerRadius) {
+ if (src.inputFP_index >= 0) {
+ inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
+ }
+ {
+ ninePatchFP_index =
+ this->cloneAndRegisterChildProcessor(src.childProcessor(src.ninePatchFP_index));
+ }
}
std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrRRectBlurEffect(*this));
}
-const GrFragmentProcessor::TextureSampler& GrRRectBlurEffect::onTextureSampler(int index) const {
- return IthTextureSampler(index, ninePatchSampler);
-}
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRRectBlurEffect);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::TestCreate(GrProcessorTestData* d) {
@@ -167,6 +180,6 @@ std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::TestCreate(GrProcessorTe
SkScalar sigma = d->fRandom->nextRangeF(1.f, 10.f);
SkRRect rrect;
rrect.setRectXY(SkRect::MakeWH(w, h), r, r);
- return GrRRectBlurEffect::Make(d->context(), sigma, sigma, rrect, rrect);
+ return GrRRectBlurEffect::Make(/*inputFP=*/nullptr, d->context(), sigma, sigma, rrect, rrect);
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.h
index 84eb69d48d3..32efd147c60 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrRRectBlurEffect.h
@@ -10,8 +10,9 @@
**************************************************************************************************/
#ifndef GrRRectBlurEffect_DEFINED
#define GrRRectBlurEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "include/gpu/GrContext.h"
#include "include/private/GrRecordingContext.h"
@@ -19,21 +20,23 @@
#include "src/core/SkGpuBlurUtils.h"
#include "src/core/SkRRectPriv.h"
#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrPaint.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrStyle.h"
+#include "src/gpu/effects/GrTextureEffect.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrRRectBlurEffect : public GrFragmentProcessor {
public:
- static GrSurfaceProxyView find_or_create_rrect_blur_mask(GrRecordingContext* context,
- const SkRRect& rrectToDraw,
- const SkISize& dimensions,
- float xformedSigma) {
+ static std::unique_ptr<GrFragmentProcessor> find_or_create_rrect_blur_mask_fp(
+ GrRecordingContext* context,
+ const SkRRect& rrectToDraw,
+ const SkISize& dimensions,
+ float xformedSigma) {
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey key;
GrUniqueKey::Builder builder(&key, kDomain, 9, "RoundRect Blur Mask");
@@ -49,31 +52,37 @@ public:
}
builder.finish();
+ // It seems like we could omit this matrix and modify the shader code to not normalize
+ // the coords used to sample the texture effect. However, the "proxyDims" value in the
+ // shader is not always the actual the proxy dimensions. This is because 'dimensions' here
+ // was computed using integer corner radii as determined in
+ // SkComputeBlurredRRectParams whereas the shader code uses the float radius to compute
+ // 'proxyDims'. Why it draws correctly with these unequal values is a mystery for the ages.
+ auto m = SkMatrix::Scale(dimensions.width(), dimensions.height());
static constexpr auto kMaskOrigin = kBottomLeft_GrSurfaceOrigin;
GrProxyProvider* proxyProvider = context->priv().proxyProvider();
if (auto view = proxyProvider->findCachedProxyWithColorTypeFallback(
key, kMaskOrigin, GrColorType::kAlpha_8, 1)) {
- return view;
+ return GrTextureEffect::Make(std::move(view), kPremul_SkAlphaType, m);
}
auto rtc = GrRenderTargetContext::MakeWithFallback(
context, GrColorType::kAlpha_8, nullptr, SkBackingFit::kExact, dimensions, 1,
GrMipMapped::kNo, GrProtected::kNo, kMaskOrigin);
if (!rtc) {
- return {};
+ return nullptr;
}
GrPaint paint;
- rtc->clear(nullptr, SK_PMColor4fTRANSPARENT,
- GrRenderTargetContext::CanClearFullscreen::kYes);
- rtc->drawRRect(GrNoClip(), std::move(paint), GrAA::kYes, SkMatrix::I(), rrectToDraw,
+ rtc->clear(SK_PMColor4fTRANSPARENT);
+ rtc->drawRRect(nullptr, std::move(paint), GrAA::kYes, SkMatrix::I(), rrectToDraw,
GrStyle::SimpleFill());
GrSurfaceProxyView srcView = rtc->readSurfaceView();
if (!srcView) {
- return {};
+ return nullptr;
}
SkASSERT(srcView.asTextureProxy());
auto rtc2 = SkGpuBlurUtils::GaussianBlur(context,
@@ -88,21 +97,21 @@ public:
SkTileMode::kClamp,
SkBackingFit::kExact);
if (!rtc2) {
- return {};
+ return nullptr;
}
GrSurfaceProxyView mask = rtc2->readSurfaceView();
if (!mask) {
- return {};
+ return nullptr;
}
SkASSERT(mask.asTextureProxy());
- SkASSERT(mask.origin() == kBottomLeft_GrSurfaceOrigin);
+ SkASSERT(mask.origin() == kMaskOrigin);
proxyProvider->assignUniqueKeyToProxy(key, mask.asTextureProxy());
-
- return mask;
+ return GrTextureEffect::Make(std::move(mask), kPremul_SkAlphaType, m);
}
- static std::unique_ptr<GrFragmentProcessor> Make(GrRecordingContext* context,
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrRecordingContext* context,
float sigma,
float xformedSigma,
const SkRRect& srcRRect,
@@ -110,28 +119,34 @@ public:
GrRRectBlurEffect(const GrRRectBlurEffect& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "RRectBlurEffect"; }
+ int inputFP_index = -1;
float sigma;
SkRect rect;
float cornerRadius;
- TextureSampler ninePatchSampler;
+ int ninePatchFP_index = -1;
private:
- GrRRectBlurEffect(float sigma,
+ GrRRectBlurEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
+ float sigma,
SkRect rect,
float cornerRadius,
- GrSurfaceProxyView ninePatchSampler)
+ std::unique_ptr<GrFragmentProcessor> ninePatchFP)
: INHERITED(kGrRRectBlurEffect_ClassID,
- (OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag)
+ (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
+ : kAll_OptimizationFlags) &
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, sigma(sigma)
, rect(rect)
- , cornerRadius(cornerRadius)
- , ninePatchSampler(std::move(ninePatchSampler)) {
- this->setTextureSamplerCnt(1);
+ , cornerRadius(cornerRadius) {
+ if (inputFP) {
+ inputFP_index = this->registerChild(std::move(inputFP));
+ }
+ SkASSERT(ninePatchFP);
+ ninePatchFP_index = this->registerExplicitlySampledChild(std::move(ninePatchFP));
}
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
- const TextureSampler& onTextureSampler(int) const override;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
typedef GrFragmentProcessor INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.cpp b/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.cpp
index 11180695942..689c69bb725 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.cpp
@@ -25,8 +25,6 @@ public:
(void)_outer;
auto rect = _outer.rect;
(void)rect;
- auto invSixSigma = _outer.invSixSigma;
- (void)invSixSigma;
auto isFast = _outer.isFast;
(void)isFast;
highp = ((abs(rect.left()) > 16000.0 || abs(rect.top()) > 16000.0) ||
@@ -40,103 +38,94 @@ public:
rectHVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
kHalf4_GrSLType, "rectH");
}
- invSixSigmaVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
- kHalf_GrSLType, "invSixSigma");
fragBuilder->codeAppendf(
- "/* key */ bool highp = %s;\nhalf xCoverage, yCoverage;\n@if (%s) {\n half x, "
- "y;\n @if (highp) {\n x = max(half(%s.x - sk_FragCoord.x), "
- "half(sk_FragCoord.x - %s.z));\n y = max(half(%s.y - sk_FragCoord.y), "
- "half(sk_FragCoord.y - %s.w));\n } else {\n x = max(half(float(%s.x) - "
- "sk_FragCoord.x), half(sk_FragCoord.x - float(%s.z)));\n y = "
- "max(half(float(%s.y) - sk_FragCoord.y), half(sk_FragCoord.y - float(%s.w)));\n "
- "}\n xCoverage = sample(%s, float2(half2(x * %s, 0.5))).",
+ R"SkSL(/* key */ bool highp = %s;
+half xCoverage, yCoverage;
+@if (%s) {
+ half2 xy;
+ @if (highp) {
+ xy = max(half2(%s.xy - sk_FragCoord.xy), half2(sk_FragCoord.xy - %s.zw));
+ } else {
+ xy = max(half2(float2(%s.xy) - sk_FragCoord.xy), half2(sk_FragCoord.xy - float2(%s.zw)));
+ })SkSL",
(highp ? "true" : "false"), (_outer.isFast ? "true" : "false"),
rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
- rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
- rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
- rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)",
- rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)",
- rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)",
rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)",
- fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
- args.fUniformHandler->getUniformCStr(invSixSigmaVar));
+ rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)");
+ SkString _sample7215;
+ SkString _coords7215("float2(half2(xy.x, 0.5))");
+ _sample7215 = this->invokeChild(_outer.integral_index, args, _coords7215.c_str());
fragBuilder->codeAppendf(
- "%s.w;\n yCoverage = sample(%s, float2(half2(y * %s, 0.5))).%s.w;\n %s = (%s "
- "* xCoverage) * yCoverage;\n} else {\n half l, r, t, b;\n @if (highp) {\n "
- " l = half(sk_FragCoord.x - %s.x);\n r = half(%s.z - sk_FragCoord.x);\n "
- " t = half(sk_FragCoord.y - %s.y);\n b = half(%s.w - "
- "sk_FragCoord.y);\n } else {\n l = half(sk_FragCoord.x - float(%s.x));\n "
- " r = half(float(%s.z) - sk_FragCoord.x);\n t = half(sk_FragCoord.y - "
- "float(%s.y));\n b = half(float(",
- fragBuilder->getProgramBuilder()
- ->samplerSwizzle(args.fTexSamplers[0])
- .asString()
- .c_str(),
- fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
- args.fUniformHandler->getUniformCStr(invSixSigmaVar),
- fragBuilder->getProgramBuilder()
- ->samplerSwizzle(args.fTexSamplers[0])
- .asString()
- .c_str(),
- args.fOutputColor, args.fInputColor,
- rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
- rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
+ R"SkSL(
+ xCoverage = %s.w;)SkSL",
+ _sample7215.c_str());
+ SkString _sample7273;
+ SkString _coords7273("float2(half2(xy.y, 0.5))");
+ _sample7273 = this->invokeChild(_outer.integral_index, args, _coords7273.c_str());
+ fragBuilder->codeAppendf(
+ R"SkSL(
+ yCoverage = %s.w;
+} else {
+ half4 rect;
+ @if (highp) {
+ rect.xy = half2(%s.xy - sk_FragCoord.xy);
+ rect.zw = half2(sk_FragCoord.xy - %s.zw);
+ } else {
+ rect.xy = half2(float2(%s.xy) - sk_FragCoord.xy);
+ rect.zw = half2(sk_FragCoord.xy - float2(%s.zw));
+ })SkSL",
+ _sample7273.c_str(),
rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
rectFVar.isValid() ? args.fUniformHandler->getUniformCStr(rectFVar) : "float4(0)",
rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)",
- rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)",
rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)");
+ SkString _sample8640;
+ SkString _coords8640("float2(half2(rect.x, 0.5))");
+ _sample8640 = this->invokeChild(_outer.integral_index, args, _coords8640.c_str());
+ SkString _sample8703;
+ SkString _coords8703("float2(half2(rect.z, 0.5))");
+ _sample8703 = this->invokeChild(_outer.integral_index, args, _coords8703.c_str());
fragBuilder->codeAppendf(
- "%s.w) - sk_FragCoord.y);\n }\n half il = 1.0 + l * %s;\n half ir = 1.0 + "
- "r * %s;\n half it = 1.0 + t * %s;\n half ib = 1.0 + b * %s;\n xCoverage "
- "= (1.0 - sample(%s, float2(half2(il, 0.5))).%s.w) - sample(%s, float2(half2(ir, "
- "0.5))).%s.w;\n yCoverage = (1.0 - sample(%s, float2(half2(it, 0.5))).%s.w) - "
- "sample(%s, float2(half2(ib, 0.5))).%s.w;\n}\n%s = (%s * xCoverage) * yCoverage;\n",
- rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)",
- args.fUniformHandler->getUniformCStr(invSixSigmaVar),
- args.fUniformHandler->getUniformCStr(invSixSigmaVar),
- args.fUniformHandler->getUniformCStr(invSixSigmaVar),
- args.fUniformHandler->getUniformCStr(invSixSigmaVar),
- fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
- fragBuilder->getProgramBuilder()
- ->samplerSwizzle(args.fTexSamplers[0])
- .asString()
- .c_str(),
- fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
- fragBuilder->getProgramBuilder()
- ->samplerSwizzle(args.fTexSamplers[0])
- .asString()
- .c_str(),
- fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
- fragBuilder->getProgramBuilder()
- ->samplerSwizzle(args.fTexSamplers[0])
- .asString()
- .c_str(),
- fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
- fragBuilder->getProgramBuilder()
- ->samplerSwizzle(args.fTexSamplers[0])
- .asString()
- .c_str(),
- args.fOutputColor, args.fInputColor);
+ R"SkSL(
+ xCoverage = (1.0 - %s.w) - %s.w;)SkSL",
+ _sample8640.c_str(), _sample8703.c_str());
+ SkString _sample8767;
+ SkString _coords8767("float2(half2(rect.y, 0.5))");
+ _sample8767 = this->invokeChild(_outer.integral_index, args, _coords8767.c_str());
+ SkString _sample8830;
+ SkString _coords8830("float2(half2(rect.w, 0.5))");
+ _sample8830 = this->invokeChild(_outer.integral_index, args, _coords8830.c_str());
+ fragBuilder->codeAppendf(
+ R"SkSL(
+ yCoverage = (1.0 - %s.w) - %s.w;
+})SkSL",
+ _sample8767.c_str(), _sample8830.c_str());
+ SkString _input8899(args.fInputColor);
+ SkString _sample8899;
+ if (_outer.inputFP_index >= 0) {
+ _sample8899 = this->invokeChild(_outer.inputFP_index, _input8899.c_str(), args);
+ } else {
+ _sample8899.swap(_input8899);
+ }
+ fragBuilder->codeAppendf(
+ R"SkSL(
+half4 inputColor = %s;
+%s = (inputColor * xCoverage) * yCoverage;
+)SkSL",
+ _sample8899.c_str(), args.fOutputColor);
}
private:
void onSetData(const GrGLSLProgramDataManager& pdman,
const GrFragmentProcessor& _proc) override {
const GrRectBlurEffect& _outer = _proc.cast<GrRectBlurEffect>();
- { pdman.set1f(invSixSigmaVar, (_outer.invSixSigma)); }
auto rect = _outer.rect;
(void)rect;
UniformHandle& rectF = rectFVar;
(void)rectF;
UniformHandle& rectH = rectHVar;
(void)rectH;
- const GrSurfaceProxyView& integralView = _outer.textureSampler(0).view();
- GrTexture& integral = *integralView.proxy()->peekTexture();
- (void)integral;
- UniformHandle& invSixSigma = invSixSigmaVar;
- (void)invSixSigma;
auto isFast = _outer.isFast;
(void)isFast;
@@ -146,7 +135,6 @@ private:
bool highp = false;
UniformHandle rectFVar;
UniformHandle rectHVar;
- UniformHandle invSixSigmaVar;
};
GrGLSLFragmentProcessor* GrRectBlurEffect::onCreateGLSLInstance() const {
return new GrGLSLRectBlurEffect();
@@ -163,32 +151,31 @@ bool GrRectBlurEffect::onIsEqual(const GrFragmentProcessor& other) const {
const GrRectBlurEffect& that = other.cast<GrRectBlurEffect>();
(void)that;
if (rect != that.rect) return false;
- if (integral != that.integral) return false;
- if (invSixSigma != that.invSixSigma) return false;
if (isFast != that.isFast) return false;
return true;
}
GrRectBlurEffect::GrRectBlurEffect(const GrRectBlurEffect& src)
: INHERITED(kGrRectBlurEffect_ClassID, src.optimizationFlags())
, rect(src.rect)
- , integral(src.integral)
- , invSixSigma(src.invSixSigma)
, isFast(src.isFast) {
- this->setTextureSamplerCnt(1);
+ if (src.inputFP_index >= 0) {
+ inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
+ }
+ {
+ integral_index =
+ this->cloneAndRegisterChildProcessor(src.childProcessor(src.integral_index));
+ }
}
std::unique_ptr<GrFragmentProcessor> GrRectBlurEffect::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect(*this));
}
-const GrFragmentProcessor::TextureSampler& GrRectBlurEffect::onTextureSampler(int index) const {
- return IthTextureSampler(index, integral);
-}
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRectBlurEffect);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrRectBlurEffect::TestCreate(GrProcessorTestData* data) {
float sigma = data->fRandom->nextRangeF(3, 8);
float width = data->fRandom->nextRangeF(200, 300);
float height = data->fRandom->nextRangeF(200, 300);
- return GrRectBlurEffect::Make(data->context(), *data->caps()->shaderCaps(),
+ return GrRectBlurEffect::Make(/*inputFP=*/nullptr, data->context(), *data->caps()->shaderCaps(),
SkRect::MakeWH(width, height), sigma);
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.h b/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.h
index 37727a96d38..9b45f1e983e 100644
--- a/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/generated/GrRectBlurEffect.h
@@ -10,8 +10,9 @@
**************************************************************************************************/
#ifndef GrRectBlurEffect_DEFINED
#define GrRectBlurEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include <cmath>
#include "include/core/SkRect.h"
@@ -24,12 +25,15 @@
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrShaderCaps.h"
+#include "src/gpu/effects/GrTextureEffect.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrRectBlurEffect : public GrFragmentProcessor {
public:
- static GrSurfaceProxyView CreateIntegralTexture(GrRecordingContext* context, float sixSigma) {
+ static std::unique_ptr<GrFragmentProcessor> MakeIntegralFP(GrRecordingContext* context,
+ float sixSigma) {
// The texture we're producing represents the integral of a normal distribution over a
// six-sigma range centered at zero. We want enough resolution so that the linear
// interpolation done in texture lookup doesn't introduce noticeable artifacts. We
@@ -44,11 +48,15 @@ public:
builder[0] = width;
builder.finish();
+ SkMatrix m = SkMatrix::Scale(width / sixSigma, 1.f);
+
GrProxyProvider* proxyProvider = context->priv().proxyProvider();
if (sk_sp<GrTextureProxy> proxy = proxyProvider->findOrCreateProxyByUniqueKey(key)) {
GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(proxy->backendFormat(),
GrColorType::kAlpha_8);
- return {std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle};
+ GrSurfaceProxyView view{std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle};
+ return GrTextureEffect::Make(std::move(view), kPremul_SkAlphaType, m,
+ GrSamplerState::Filter::kBilerp);
}
SkBitmap bitmap;
@@ -73,10 +81,12 @@ public:
}
SkASSERT(view.origin() == kTopLeft_GrSurfaceOrigin);
proxyProvider->assignUniqueKeyToProxy(key, view.asTextureProxy());
- return view;
+ return GrTextureEffect::Make(std::move(view), kPremul_SkAlphaType, m,
+ GrSamplerState::Filter::kBilerp);
}
- static std::unique_ptr<GrFragmentProcessor> Make(GrRecordingContext* context,
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
+ GrRecordingContext* context,
const GrShaderCaps& caps,
const SkRect& rect,
float sigma) {
@@ -92,7 +102,7 @@ public:
}
const float sixSigma = 6 * sigma;
- GrSurfaceProxyView integral = CreateIntegralTexture(context, sixSigma);
+ std::unique_ptr<GrFragmentProcessor> integral = MakeIntegralFP(context, sixSigma);
if (!integral) {
return nullptr;
}
@@ -110,39 +120,39 @@ public:
// less than 6 sigma wide then things aren't so simple and we have to consider both the
// left and right edge of the rectangle (and similar in y).
bool isFast = insetRect.isSorted();
- // 1 / (6 * sigma) is the domain of the integral texture. We use the inverse to produce
- // normalized texture coords from frag coord distances.
- float invSixSigma = 1.f / sixSigma;
return std::unique_ptr<GrFragmentProcessor>(
- new GrRectBlurEffect(insetRect, std::move(integral), invSixSigma, isFast,
+ new GrRectBlurEffect(std::move(inputFP), insetRect, std::move(integral), isFast,
GrSamplerState::Filter::kBilerp));
}
GrRectBlurEffect(const GrRectBlurEffect& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "RectBlurEffect"; }
+ int inputFP_index = -1;
SkRect rect;
- TextureSampler integral;
- float invSixSigma;
+ int integral_index = -1;
bool isFast;
private:
- GrRectBlurEffect(SkRect rect,
- GrSurfaceProxyView integral,
- float invSixSigma,
+ GrRectBlurEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
+ SkRect rect,
+ std::unique_ptr<GrFragmentProcessor> integral,
bool isFast,
GrSamplerState samplerParams)
: INHERITED(kGrRectBlurEffect_ClassID,
- (OptimizationFlags)kCompatibleWithCoverageAsAlpha_OptimizationFlag)
+ (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
+ : kAll_OptimizationFlags) &
+ kCompatibleWithCoverageAsAlpha_OptimizationFlag)
, rect(rect)
- , integral(std::move(integral), samplerParams)
- , invSixSigma(invSixSigma)
, isFast(isFast) {
- this->setTextureSamplerCnt(1);
+ if (inputFP) {
+ inputFP_index = this->registerChild(std::move(inputFP));
+ }
+ SkASSERT(integral);
+ integral_index = this->registerExplicitlySampledChild(std::move(integral));
}
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
- const TextureSampler& onTextureSampler(int) const override;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
typedef GrFragmentProcessor INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/geometry/GrPathUtils.cpp b/chromium/third_party/skia/src/gpu/geometry/GrPathUtils.cpp
index 625b9d6756f..55d1207c4ca 100644
--- a/chromium/third_party/skia/src/gpu/geometry/GrPathUtils.cpp
+++ b/chromium/third_party/skia/src/gpu/geometry/GrPathUtils.cpp
@@ -188,6 +188,7 @@ int GrPathUtils::worstCasePointCount(const SkPath& path, int* subpaths, SkScalar
for (int i = 0; i < converter.countQuads(); ++i) {
pointCount += quadraticPointCount(quadPts + 2*i, tol);
}
+ [[fallthrough]];
}
case SkPath::kQuad_Verb:
pointCount += quadraticPointCount(pts, tol);
@@ -806,7 +807,7 @@ SkCubicType GrPathUtils::getCubicKLM(const SkPoint src[4], SkMatrix* klm, double
switch (type) {
case SkCubicType::kCuspAtInfinity:
SkASSERT(1 == t1 && 0 == s1); // Infinity.
- // fallthru.
+ [[fallthrough]];
case SkCubicType::kLocalCusp:
case SkCubicType::kSerpentine:
calc_serp_kcoeffs(t0, s0, t1, s1, skipTerm, &klmCoeffs[0]);
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLBuffer.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLBuffer.cpp
index fc11731b736..0ac421d116d 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLBuffer.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLBuffer.cpp
@@ -14,15 +14,17 @@
#define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X)
#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glGpu()->glInterface(), RET, X)
-#if GR_GL_CHECK_ALLOC_WITH_GET_ERROR
- #define CLEAR_ERROR_BEFORE_ALLOC(iface) GrGLClearErr(iface)
- #define GL_ALLOC_CALL(iface, call) GR_GL_CALL_NOERRCHECK(iface, call)
- #define CHECK_ALLOC_ERROR(iface) GR_GL_GET_ERROR(iface)
-#else
- #define CLEAR_ERROR_BEFORE_ALLOC(iface)
- #define GL_ALLOC_CALL(iface, call) GR_GL_CALL(iface, call)
- #define CHECK_ALLOC_ERROR(iface) GR_GL_NO_ERROR
-#endif
+#define GL_ALLOC_CALL(call) \
+ [&] { \
+ if (this->glGpu()->glCaps().skipErrorChecks()) { \
+ GR_GL_CALL(this->glGpu()->glInterface(), call); \
+ return static_cast<GrGLenum>(GR_GL_NO_ERROR); \
+ } else { \
+ this->glGpu()->clearErrorsAndCheckForOOM(); \
+ GR_GL_CALL_NOERRCHECK(this->glGpu()->glInterface(), call); \
+ return this->glGpu()->getErrorAndCheckForOOM(); \
+ } \
+ }()
#ifdef SK_DEBUG
#define VALIDATE() this->validate()
@@ -109,13 +111,8 @@ GrGLBuffer::GrGLBuffer(GrGLGpu* gpu, size_t size, GrGpuBufferType intendedType,
GL_CALL(GenBuffers(1, &fBufferID));
if (fBufferID) {
GrGLenum target = gpu->bindBuffer(fIntendedType, this);
- CLEAR_ERROR_BEFORE_ALLOC(gpu->glInterface());
- // make sure driver can allocate memory for this buffer
- GL_ALLOC_CALL(gpu->glInterface(), BufferData(target,
- (GrGLsizeiptr) size,
- data,
- fUsage));
- if (CHECK_ALLOC_ERROR(gpu->glInterface()) != GR_GL_NO_ERROR) {
+ GrGLenum error = GL_ALLOC_CALL(BufferData(target, (GrGLsizeiptr)size, data, fUsage));
+ if (error != GR_GL_NO_ERROR) {
GL_CALL(DeleteBuffers(1, &fBufferID));
fBufferID = 0;
} else {
@@ -182,7 +179,11 @@ void GrGLBuffer::onMap() {
if (!readOnly) {
// Let driver know it can discard the old data
if (this->glCaps().useBufferDataNullHint() || fGLSizeInBytes != this->size()) {
- GL_CALL(BufferData(target, this->size(), nullptr, fUsage));
+ GrGLenum error =
+ GL_ALLOC_CALL(BufferData(target, this->size(), nullptr, fUsage));
+ if (error != GR_GL_NO_ERROR) {
+ return;
+ }
}
}
GL_CALL_RET(fMapPtr, MapBuffer(target, readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY));
@@ -192,7 +193,10 @@ void GrGLBuffer::onMap() {
GrGLenum target = this->glGpu()->bindBuffer(fIntendedType, this);
// Make sure the GL buffer size agrees with fDesc before mapping.
if (fGLSizeInBytes != this->size()) {
- GL_CALL(BufferData(target, this->size(), nullptr, fUsage));
+ GrGLenum error = GL_ALLOC_CALL(BufferData(target, this->size(), nullptr, fUsage));
+ if (error != GR_GL_NO_ERROR) {
+ return;
+ }
}
GrGLbitfield access;
if (readOnly) {
@@ -211,7 +215,10 @@ void GrGLBuffer::onMap() {
GrGLenum target = this->glGpu()->bindBuffer(fIntendedType, this);
// Make sure the GL buffer size agrees with fDesc before mapping.
if (fGLSizeInBytes != this->size()) {
- GL_CALL(BufferData(target, this->size(), nullptr, fUsage));
+ GrGLenum error = GL_ALLOC_CALL(BufferData(target, this->size(), nullptr, fUsage));
+ if (error != GR_GL_NO_ERROR) {
+ return;
+ }
}
GL_CALL_RET(fMapPtr, MapBufferSubData(target, 0, this->size(),
readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY));
@@ -266,7 +273,11 @@ bool GrGLBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) {
if (this->glCaps().useBufferDataNullHint()) {
if (this->size() == srcSizeInBytes) {
- GL_CALL(BufferData(target, (GrGLsizeiptr) srcSizeInBytes, src, fUsage));
+ GrGLenum error =
+ GL_ALLOC_CALL(BufferData(target, (GrGLsizeiptr)srcSizeInBytes, src, fUsage));
+ if (error != GR_GL_NO_ERROR) {
+ return false;
+ }
} else {
// Before we call glBufferSubData we give the driver a hint using
// glBufferData with nullptr. This makes the old buffer contents
@@ -275,7 +286,11 @@ bool GrGLBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) {
// assign a different allocation for the new contents to avoid
// flushing the gpu past draws consuming the old contents.
// TODO I think we actually want to try calling bufferData here
- GL_CALL(BufferData(target, this->size(), nullptr, fUsage));
+ GrGLenum error =
+ GL_ALLOC_CALL(BufferData(target, (GrGLsizeiptr)this->size(), nullptr, fUsage));
+ if (error != GR_GL_NO_ERROR) {
+ return false;
+ }
GL_CALL(BufferSubData(target, 0, (GrGLsizeiptr) srcSizeInBytes, src));
}
fGLSizeInBytes = this->size();
@@ -283,7 +298,11 @@ bool GrGLBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) {
// Note that we're cheating on the size here. Currently no methods
// allow a partial update that preserves contents of non-updated
// portions of the buffer (map() does a glBufferData(..size, nullptr..))
- GL_CALL(BufferData(target, srcSizeInBytes, src, fUsage));
+ GrGLenum error =
+ GL_ALLOC_CALL(BufferData(target, (GrGLsizeiptr)srcSizeInBytes, src, fUsage));
+ if (error != GR_GL_NO_ERROR) {
+ return false;
+ }
fGLSizeInBytes = srcSizeInBytes;
}
VALIDATE();
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLCaps.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLCaps.cpp
index 062a3e10d87..dd4e89b084e 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLCaps.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLCaps.cpp
@@ -11,6 +11,7 @@
#include "src/core/SkCompressedDataUtils.h"
#include "src/core/SkTSearch.h"
#include "src/core/SkTSort.h"
+#include "src/gpu/GrBackendUtils.h"
#include "src/gpu/GrProgramDesc.h"
#include "src/gpu/GrRenderTargetProxyPriv.h"
#include "src/gpu/GrShaderCaps.h"
@@ -236,15 +237,8 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
fRectangleTextureSupport = true;
}
} else if (GR_IS_GR_GL_ES(standard)) {
- if (ctxInfo.driver() == kChromium_GrGLDriver ||
- ctxInfo.driver() == kSwiftShader_GrGLDriver) {
- fRectangleTextureSupport = ctxInfo.hasExtension("GL_ARB_texture_rectangle");
- } else {
- // ANGLE will advertise the extension in ES2 contexts but actually using the texture in
- // a shader requires ES3 shading language.
- fRectangleTextureSupport = ctxInfo.hasExtension("GL_ANGLE_texture_rectangle") &&
- ctxInfo.glslGeneration() >= k330_GrGLSLGeneration;
- }
+ fRectangleTextureSupport = ctxInfo.hasExtension("GL_ARB_texture_rectangle") ||
+ ctxInfo.hasExtension("GL_ANGLE_texture_rectangle");
} // no WebGL support
// GrCaps defaults fClampToBorderSupport to true, so disable when unsupported
@@ -335,6 +329,10 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
} // No WebGL support
fSkipErrorChecks = ctxInfo.driver() == kChromium_GrGLDriver;
+ if (GR_IS_GR_WEBGL(standard)) {
+ // Error checks are quite costly in webgl, especially in Chrome.
+ fSkipErrorChecks = true;
+ }
/**************************************************************************
* GrShaderCaps fields
@@ -652,13 +650,12 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
// Only in WebGL 2.0
fSemaphoreSupport = fFenceSyncSupport = version >= GR_GL_VER(2, 0);
fFenceType = FenceType::kSyncObject;
- } else if (ctxInfo.hasExtension("GL_ARB_sync") || ctxInfo.hasExtension("GL_APPLE_sync")) {
+ } else if (GR_IS_GR_GL(standard) &&
+ (version >= GR_GL_VER(3, 2) || ctxInfo.hasExtension("GL_ARB_sync"))) {
fSemaphoreSupport = fFenceSyncSupport = true;
fFenceType = FenceType::kSyncObject;
- } else if (GR_IS_GR_GL(standard) && version >= GR_GL_VER(3, 2)) {
- fSemaphoreSupport = fFenceSyncSupport = true;
- fFenceType = FenceType::kSyncObject;
- } else if (GR_IS_GR_GL_ES(standard) && version >= GR_GL_VER(3, 0)) {
+ } else if (GR_IS_GR_GL_ES(standard) &&
+ (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_APPLE_sync"))) {
fSemaphoreSupport = fFenceSyncSupport = true;
fFenceType = FenceType::kSyncObject;
} else if (ctxInfo.hasExtension("GL_NV_fence")) {
@@ -843,6 +840,14 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli
fFBFetchRequiresEnablePerSample = true;
}
shaderCaps->fUsesPrecisionModifiers = true;
+ } else if (GR_IS_GR_GL(standard)) {
+ if (ctxInfo.hasExtension("GL_EXT_shader_framebuffer_fetch")) {
+ shaderCaps->fFBFetchNeedsCustomOutput = (version >= GR_GL_VER(3, 0));
+ shaderCaps->fFBFetchSupport = true;
+ shaderCaps->fFBFetchColorName = "gl_LastFragData[0]";
+ shaderCaps->fFBFetchExtensionString = "GL_EXT_shader_framebuffer_fetch";
+ fFBFetchRequiresEnablePerSample = false;
+ }
} else if (GR_IS_GR_WEBGL(standard)) {
shaderCaps->fUsesPrecisionModifiers = true;
}
@@ -882,17 +887,21 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli
}
}
+ bool hasTessellationSupport = false;
if (GR_IS_GR_GL(standard)) {
- shaderCaps->fTessellationSupport =
- version >= GR_GL_VER(4,0) ||
- ctxInfo.hasExtension("GL_ARB_tessellation_shader");
- } else {
- if (version >= GR_GL_VER(3,2)) {
- shaderCaps->fTessellationSupport = true;
- } else if (ctxInfo.hasExtension("GL_OES_tessellation_shader")) {
- shaderCaps->fTessellationSupport = true;
- shaderCaps->fTessellationExtensionString = "GL_OES_tessellation_shader";
- }
+ hasTessellationSupport = version >= GR_GL_VER(4,0) ||
+ ctxInfo.hasExtension("GL_ARB_tessellation_shader");
+ } else if (version >= GR_GL_VER(3,2)) {
+ hasTessellationSupport = true;
+ } else if (ctxInfo.hasExtension("GL_OES_tessellation_shader")) {
+ hasTessellationSupport = true;
+ shaderCaps->fTessellationExtensionString = "GL_OES_tessellation_shader";
+ }
+ if (hasTessellationSupport) {
+ GR_GL_GetIntegerv(gli, GR_GL_MAX_TESS_GEN_LEVEL_OES,
+ &shaderCaps->fMaxTessellationSegments);
+ // Just in case a driver returns a negative number?
+ shaderCaps->fMaxTessellationSegments = std::max(0, shaderCaps->fMaxTessellationSegments);
}
shaderCaps->fVersionDeclString = get_glsl_version_decl_string(standard,
@@ -1029,13 +1038,6 @@ void GrGLCaps::initFSAASupport(const GrContextOptions& contextOptions,
fMSFBOType = kNone_MSFBOType;
}
}
-
- // We disable MSAA for all Intel GPUs. Before Gen9, performance was very bad. Even with Gen9,
- // we've seen driver crashes in the wild. We don't have data on Gen11 yet.
- // chromium:527565, chromium:983926
- if (kIntel_GrGLVendor == ctxInfo.vendor()) {
- fMSFBOType = kNone_MSFBOType;
- }
}
void GrGLCaps::initBlendEqationSupport(const GrGLContextInfo& ctxInfo) {
@@ -3640,6 +3642,10 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
// Tegra3 fract() seems to trigger undefined behavior for negative values, so we
// must avoid this condition.
shaderCaps->fCanUseFractForNegativeValues = false;
+
+ // Seeing crashes on Tegra3 with inlined functions that have early returns. Looks like the
+ // do { ... break; } while (false); construct is causing a crash in the driver.
+ shaderCaps->fCanUseDoLoops = false;
}
// On Intel GPU there is an issue where it reads the second argument to atan "- %s.x" as an int
@@ -3849,14 +3855,14 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
if (ctxInfo.version() >= GR_GL_VER(4,2)) {
fRequiresManualFBBarrierAfterTessellatedStencilDraw = true;
} else {
- shaderCaps->fTessellationSupport = false;
+ shaderCaps->fMaxTessellationSegments = 0;
}
} else {
// glMemoryBarrier wasn't around until es version 3.1.
if (ctxInfo.version() >= GR_GL_VER(3,1)) {
fRequiresManualFBBarrierAfterTessellatedStencilDraw = true;
} else {
- shaderCaps->fTessellationSupport = false;
+ shaderCaps->fMaxTessellationSegments = 0;
}
}
}
@@ -3864,7 +3870,7 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
if (kQualcomm_GrGLDriver == ctxInfo.driver()) {
// Qualcomm fails to link programs with tessellation and does not give an error message.
// http://skbug.com/9740
- shaderCaps->fTessellationSupport = false;
+ shaderCaps->fMaxTessellationSegments = 0;
}
#ifdef SK_BUILD_FOR_WIN
@@ -3937,8 +3943,10 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
#ifdef SK_BUILD_FOR_MAC
// On a MacBookPro 11.5 running MacOS 10.13 with a Radeon M370X the TransferPixelsFrom test
// fails when transferring out from a GL_RG8 texture using GL_RG/GL_UNSIGNED_BYTE.
+ // The same error also occurs in MacOS 10.15 with a Radeon Pro 5300M.
formatWorkarounds->fDisallowDirectRG8ReadPixels =
ctxInfo.renderer() == kAMDRadeonR9M3xx_GrGLRenderer ||
+ ctxInfo.renderer() == kAMDRadeonPro5xxx_GrGLRenderer ||
ctxInfo.renderer() == kAMDRadeonProVegaxx_GrGLRenderer;
#endif
@@ -3987,6 +3995,24 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
if (ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D9) {
formatWorkarounds->fDisallowBGRA8ReadPixels = true;
}
+
+ // We disable MSAA for all Intel GPUs. Before Gen9, performance was very bad. Even with Gen9,
+ // we've seen driver crashes in the wild. We don't have data on Gen11 yet.
+ // (crbug.com/527565, crbug.com/983926)
+ if (kIntel_GrGLVendor == ctxInfo.vendor()) {
+ fMSFBOType = kNone_MSFBOType;
+ }
+
+ // ANGLE doesn't support do-while loops
+ if (kANGLE_GrGLDriver == ctxInfo.driver()) {
+ shaderCaps->fCanUseDoLoops = false;
+ }
+
+ // ANGLE's D3D9 backend + AMD GPUs are flaky with program binary caching (skbug.com/10395)
+ if (ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D9 &&
+ ctxInfo.angleVendor() == GrGLANGLEVendor::kAMD) {
+ fProgramBinarySupport = false;
+ }
}
void GrGLCaps::onApplyOptionsOverrides(const GrContextOptions& options) {
@@ -4066,6 +4092,7 @@ size_t offset_alignment_for_transfer_buffer(GrGLenum externalType) {
case GR_GL_UNSIGNED_INT: return sizeof(GrGLuint);
case GR_GL_INT: return sizeof(GrGLint);
case GR_GL_HALF_FLOAT: return sizeof(GrGLhalf);
+ case GR_GL_HALF_FLOAT_OES: return sizeof(GrGLhalf);
case GR_GL_FLOAT: return sizeof(GrGLfloat);
case GR_GL_UNSIGNED_SHORT_5_6_5: return sizeof(GrGLushort);
case GR_GL_UNSIGNED_SHORT_4_4_4_4: return sizeof(GrGLushort);
@@ -4094,7 +4121,7 @@ GrCaps::SupportedRead GrGLCaps::onSupportedReadPixelsColorType(
GrColorType srcColorType, const GrBackendFormat& srcBackendFormat,
GrColorType dstColorType) const {
- SkImage::CompressionType compression = this->compressionType(srcBackendFormat);
+ SkImage::CompressionType compression = GrBackendFormatToCompressionType(srcBackendFormat);
if (compression != SkImage::CompressionType::kNone) {
return { SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
: GrColorType::kRGBA_8888,
@@ -4174,25 +4201,10 @@ bool GrGLCaps::isFormatSRGB(const GrBackendFormat& format) const {
return format.asGLFormat() == GrGLFormat::kSRGB8_ALPHA8;
}
-SkImage::CompressionType GrGLCaps::compressionType(const GrBackendFormat& format) const {
- auto fmt = format.asGLFormat();
-
- switch (fmt) {
- case GrGLFormat::kCOMPRESSED_ETC1_RGB8: // same compression layout as ETC2_RGB8_UNORM
- case GrGLFormat::kCOMPRESSED_RGB8_ETC2:
- return SkImage::CompressionType::kETC2_RGB8_UNORM;
- case GrGLFormat::kCOMPRESSED_RGB8_BC1:
- return SkImage::CompressionType::kBC1_RGB8_UNORM;
- case GrGLFormat::kCOMPRESSED_RGBA8_BC1:
- return SkImage::CompressionType::kBC1_RGBA8_UNORM;
- default:
- return SkImage::CompressionType::kNone;
- }
-
- SkUNREACHABLE;
-}
-
bool GrGLCaps::isFormatTexturable(const GrBackendFormat& format) const {
+ if (format.textureType() == GrTextureType::kRectangle && !this->rectangleTextureSupport()) {
+ return false;
+ }
return this->isFormatTexturable(format.asGLFormat());
}
@@ -4203,6 +4215,12 @@ bool GrGLCaps::isFormatTexturable(GrGLFormat format) const {
bool GrGLCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
int sampleCount) const {
+ if (format.textureType() == GrTextureType::kRectangle && !this->rectangleTextureSupport()) {
+ return false;
+ }
+ if (format.textureType() == GrTextureType::kExternal) {
+ return false;
+ }
auto f = format.asGLFormat();
const FormatInfo& info = this->getFormatInfo(f);
if (!SkToBool(info.colorTypeFlags(ct) & ColorTypeInfo::kRenderable_Flag)) {
@@ -4213,6 +4231,12 @@ bool GrGLCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendForm
}
bool GrGLCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount) const {
+ if (format.textureType() == GrTextureType::kRectangle && !this->rectangleTextureSupport()) {
+ return false;
+ }
+ if (format.textureType() == GrTextureType::kExternal) {
+ return false;
+ }
return this->isFormatRenderable(format.asGLFormat(), sampleCount);
}
@@ -4324,13 +4348,6 @@ void GrGLCaps::didQueryImplementationReadSupport(GrGLFormat format,
bool GrGLCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
const GrBackendFormat& format) const {
GrGLFormat glFormat = format.asGLFormat();
-
- SkImage::CompressionType compression = GrGLFormatToCompressionType(glFormat);
- if (compression != SkImage::CompressionType::kNone) {
- return ct == (SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
- : GrColorType::kRGBA_8888);
- }
-
const auto& info = this->getFormatInfo(glFormat);
for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
if (info.fColorTypeInfos[i].fColorType == ct) {
@@ -4379,8 +4396,9 @@ GrBackendFormat GrGLCaps::getBackendFormatFromCompressionType(
SkUNREACHABLE;
}
-GrSwizzle GrGLCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
- const auto& info = this->getFormatInfo(format.asGLFormat());
+GrSwizzle GrGLCaps::onGetReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
+ GrGLFormat glFormat = format.asGLFormat();
+ const auto& info = this->getFormatInfo(glFormat);
for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
const auto& ctInfo = info.fColorTypeInfos[i];
if (ctInfo.fColorType == colorType) {
@@ -4388,7 +4406,7 @@ GrSwizzle GrGLCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType co
}
}
SkDEBUGFAILF("Illegal color type (%d) and format (%d) combination.", colorType,
- format.asGLFormat());
+ glFormat);
return {};
}
@@ -4481,7 +4499,15 @@ std::vector<GrCaps::TestFormatColorTypeCombination> GrGLCaps::getTestingCombinat
combos.push_back({ GrColorType::kBGRA_8888,
GrBackendFormat::MakeGL(GR_GL_BGRA8, GR_GL_TEXTURE_2D) });
}
-
+ if (this->rectangleTextureSupport()) {
+ size_t count2D = combos.size();
+ for (size_t i = 0; i < count2D; ++i) {
+ auto combo2D = combos[i];
+ GrGLenum formatEnum = GrGLFormatToEnum(combo2D.fFormat.asGLFormat());
+ combos.push_back({combo2D.fColorType,
+ GrBackendFormat::MakeGL(formatEnum, GR_GL_TEXTURE_RECTANGLE)});
+ }
+ }
return combos;
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLCaps.h b/chromium/third_party/skia/src/gpu/gl/GrGLCaps.h
index 1371b26c28b..8ee8e9b84b5 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLCaps.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLCaps.h
@@ -114,7 +114,6 @@ public:
const GrGLInterface* glInterface);
bool isFormatSRGB(const GrBackendFormat&) const override;
- SkImage::CompressionType compressionType(const GrBackendFormat&) const override;
bool isFormatTexturable(const GrBackendFormat&) const override;
bool isFormatTexturable(GrGLFormat) const;
@@ -441,7 +440,6 @@ public:
GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override;
- GrSwizzle getReadSwizzle(const GrBackendFormat&, GrColorType) const override;
GrSwizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override;
uint64_t computeFormatKey(const GrBackendFormat&) const override;
@@ -502,6 +500,8 @@ private:
SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&,
GrColorType) const override;
+ GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override;
+
GrGLStandard fStandard = kNone_GrGLStandard;
SkTArray<StencilFormat, true> fStencilFormats;
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLDefines.h b/chromium/third_party/skia/src/gpu/gl/GrGLDefines.h
index a2ac31561c5..8fde6be2ebb 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLDefines.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLDefines.h
@@ -1140,4 +1140,7 @@
/** GL_NV_fence_sync */
#define GR_GL_ALL_COMPLETED 0x84F2
+/* Tessellation */
+#define GR_GL_MAX_TESS_GEN_LEVEL_OES 0x8E7E
+
#endif
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLGpu.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLGpu.cpp
index f1d744d3307..24d4318d6ad 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLGpu.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLGpu.cpp
@@ -19,10 +19,10 @@
#include "src/core/SkConvertPixels.h"
#include "src/core/SkMipMap.h"
#include "src/core/SkTraceEvent.h"
+#include "src/gpu/GrBackendUtils.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrCpuBuffer.h"
#include "src/gpu/GrDataUtils.h"
-#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrGpuResourcePriv.h"
#include "src/gpu/GrPipeline.h"
#include "src/gpu/GrProgramInfo.h"
@@ -50,9 +50,9 @@
GR_GL_CALL(this->glInterface(), call); \
return static_cast<GrGLenum>(GR_GL_NO_ERROR); \
} else { \
- GrGLClearErr(this->glInterface()); \
+ this->clearErrorsAndCheckForOOM(); \
GR_GL_CALL_NOERRCHECK(this->glInterface(), call); \
- return GR_GL_GET_ERROR(this->glInterface()); \
+ return this->getErrorAndCheckForOOM(); \
} \
}()
@@ -333,7 +333,11 @@ GrGLGpu::GrGLGpu(std::unique_ptr<GrGLContext> ctx, GrContext* context)
, fStencilClearFBOID(0)
, fFinishCallbacks(this) {
SkASSERT(fGLContext);
- GrGLClearErr(this->glInterface());
+ // Clear errors so we don't get confused whether we caused an error.
+ this->clearErrorsAndCheckForOOM();
+ // Toss out any pre-existing OOM that was hanging around before we got started.
+ this->checkAndResetOOMed();
+
fCaps = sk_ref_sp(fGLContext->caps());
fHWTextureUnitBindings.reset(this->numTextureUnits());
@@ -837,9 +841,10 @@ bool GrGLGpu::onWritePixels(GrSurface* surface, int left, int top, int width, in
this->bindTextureToScratchUnit(glTex->target(), glTex->textureID());
SkASSERT(!GrGLFormatIsCompressed(glTex->format()));
- return this->uploadTexData(glTex->format(), surfaceColorType, glTex->width(), glTex->height(),
- glTex->target(), left, top, width, height, srcColorType, texels,
- mipLevelCount);
+ SkIRect dstRect = SkIRect::MakeXYWH(left, top, width, height);
+ return this->uploadColorTypeTexData(glTex->format(), surfaceColorType, glTex->dimensions(),
+ glTex->target(), dstRect, srcColorType, texels,
+ mipLevelCount);
}
bool GrGLGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int width, int height,
@@ -931,33 +936,21 @@ void GrGLGpu::unbindCpuToGpuXferBuffer() {
}
}
-bool GrGLGpu::uploadTexData(GrGLFormat textureFormat, GrColorType textureColorType, int texWidth,
- int texHeight, GrGLenum target, int left, int top, int width,
- int height, GrColorType srcColorType, const GrMipLevel texels[],
- int mipLevelCount, GrMipMapsStatus* mipMapsStatus) {
+bool GrGLGpu::uploadColorTypeTexData(GrGLFormat textureFormat,
+ GrColorType textureColorType,
+ SkISize texDims,
+ GrGLenum target,
+ SkIRect dstRect,
+ GrColorType srcColorType,
+ const GrMipLevel texels[],
+ int mipLevelCount) {
// If we're uploading compressed data then we should be using uploadCompressedTexData
SkASSERT(!GrGLFormatIsCompressed(textureFormat));
SkASSERT(this->glCaps().isFormatTexturable(textureFormat));
- SkDEBUGCODE(
- SkIRect subRect = SkIRect::MakeXYWH(left, top, width, height);
- SkIRect bounds = SkIRect::MakeWH(texWidth, texHeight);
- SkASSERT(bounds.contains(subRect));
- )
- SkASSERT(1 == mipLevelCount ||
- (0 == left && 0 == top && width == texWidth && height == texHeight));
-
- this->unbindCpuToGpuXferBuffer();
-
- const GrGLInterface* interface = this->glInterface();
- const GrGLCaps& caps = this->glCaps();
size_t bpp = GrColorTypeBytesPerPixel(srcColorType);
- if (width == 0 || height == 0) {
- return false;
- }
-
// External format and type come from the upload data.
GrGLenum externalFormat;
GrGLenum externalType;
@@ -966,52 +959,100 @@ bool GrGLGpu::uploadTexData(GrGLFormat textureFormat, GrColorType textureColorTy
if (!externalFormat || !externalType) {
return false;
}
+ this->uploadTexData(texDims, target, dstRect, externalFormat, externalType, bpp, texels,
+ mipLevelCount);
+ return true;
+}
- /*
- * Check whether to allocate a temporary buffer for flipping y or
- * because our srcData has extra bytes past each row. If so, we need
- * to trim those off here, since GL ES may not let us specify
- * GL_UNPACK_ROW_LENGTH.
- */
- bool restoreGLRowLength = false;
+bool GrGLGpu::uploadColorToTex(GrGLFormat textureFormat,
+ SkISize texDims,
+ GrGLenum target,
+ SkColor4f color,
+ uint32_t levelMask) {
+ GrColorType colorType;
+ GrGLenum externalFormat, externalType;
+ this->glCaps().getTexSubImageDefaultFormatTypeAndColorType(textureFormat, &externalFormat,
+ &externalType, &colorType);
+ if (colorType == GrColorType::kUnknown) {
+ return false;
+ }
- if (mipMapsStatus) {
- *mipMapsStatus = (mipLevelCount > 1) ?
- GrMipMapsStatus::kValid : GrMipMapsStatus::kNotAllocated;
+ std::unique_ptr<char[]> pixelStorage;
+ size_t bpp = 0;
+ int numLevels = SkMipMap::ComputeLevelCount(texDims) + 1;
+ SkSTArray<16, GrMipLevel> levels;
+ levels.resize(numLevels);
+ SkISize levelDims = texDims;
+ for (int i = 0; i < numLevels; ++i, levelDims = {std::max(levelDims.width() >> 1, 1),
+ std::max(levelDims.height() >> 1, 1)}) {
+ if (levelMask & (1 << i)) {
+ if (!pixelStorage) {
+ // Make one tight image at the first size and reuse it for smaller levels.
+ GrImageInfo ii(colorType, kUnpremul_SkAlphaType, nullptr, levelDims);
+ size_t rb = ii.minRowBytes();
+ pixelStorage.reset(new char[rb * levelDims.height()]);
+ if (!GrClearImage(ii, pixelStorage.get(), ii.minRowBytes(), color)) {
+ return false;
+ }
+ bpp = ii.bpp();
+ }
+ levels[i] = {pixelStorage.get(), levelDims.width()*bpp};
+ }
}
+ this->uploadTexData(texDims, target, SkIRect::MakeSize(texDims), externalFormat, externalType,
+ bpp, levels.begin(), levels.count());
+ return true;
+}
- GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
+void GrGLGpu::uploadTexData(SkISize texDims,
+ GrGLenum target,
+ SkIRect dstRect,
+ GrGLenum externalFormat,
+ GrGLenum externalType,
+ size_t bpp,
+ const GrMipLevel texels[],
+ int mipLevelCount) {
+ SkASSERT(!texDims.isEmpty());
+ SkASSERT(!dstRect.isEmpty());
+ SkASSERT(SkIRect::MakeSize(texDims).contains(dstRect));
+ SkASSERT(mipLevelCount > 0 && mipLevelCount <= SkMipMap::ComputeLevelCount(texDims) + 1);
+ SkASSERT(mipLevelCount == 1 || dstRect == SkIRect::MakeSize(texDims));
- for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
- if (!texels[currentMipLevel].fPixels) {
- if (mipMapsStatus) {
- *mipMapsStatus = GrMipMapsStatus::kDirty;
- }
+ const GrGLCaps& caps = this->glCaps();
+
+ bool restoreGLRowLength = false;
+
+ this->unbindCpuToGpuXferBuffer();
+ GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
+
+ SkISize dims = dstRect.size();
+ for (int level = 0; level < mipLevelCount; ++level, dims = {std::max(dims.width() >> 1, 1),
+ std::max(dims.height() >> 1, 1)}) {
+ if (!texels[level].fPixels) {
continue;
}
- int twoToTheMipLevel = 1 << currentMipLevel;
- const int currentWidth = std::max(1, width / twoToTheMipLevel);
- const int currentHeight = std::max(1, height / twoToTheMipLevel);
- const size_t trimRowBytes = currentWidth * bpp;
- const size_t rowBytes = texels[currentMipLevel].fRowBytes;
+ const size_t trimRowBytes = dims.width() * bpp;
+ const size_t rowBytes = texels[level].fRowBytes;
if (caps.writePixelsRowBytesSupport() && (rowBytes != trimRowBytes || restoreGLRowLength)) {
GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
- GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
+ GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength));
restoreGLRowLength = true;
+ } else {
+ SkASSERT(rowBytes == trimRowBytes);
}
- GL_CALL(TexSubImage2D(target, currentMipLevel, left, top, currentWidth, currentHeight,
- externalFormat, externalType, texels[currentMipLevel].fPixels));
+ GL_CALL(TexSubImage2D(target, level, dstRect.x(), dstRect.y(), dims.width(), dims.height(),
+ externalFormat, externalType, texels[level].fPixels));
}
if (restoreGLRowLength) {
SkASSERT(caps.writePixelsRowBytesSupport());
GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
}
- return true;
}
-bool GrGLGpu::uploadCompressedTexData(GrGLFormat format,
+bool GrGLGpu::uploadCompressedTexData(SkImage::CompressionType compressionType,
+ GrGLFormat format,
SkISize dimensions,
GrMipMapped mipMapped,
GrGLenum target,
@@ -1025,7 +1066,6 @@ bool GrGLGpu::uploadCompressedTexData(GrGLFormat format,
return false;
}
- SkImage::CompressionType compressionType = GrGLFormatToCompressionType(format);
SkASSERT(compressionType != SkImage::CompressionType::kNone);
bool useTexStorage = caps.formatSupportsTexStorage(format);
@@ -1250,14 +1290,27 @@ sk_sp<GrTexture> GrGLGpu::onCreateTexture(SkISize dimensions,
GrGLTextureParameters::SamplerOverriddenState initialState;
GrGLTexture::Desc texDesc;
texDesc.fSize = dimensions;
- texDesc.fTarget = GR_GL_TEXTURE_2D;
+ switch (format.textureType()) {
+ case GrTextureType::kExternal:
+ case GrTextureType::kNone:
+ return nullptr;
+ case GrTextureType::k2D:
+ texDesc.fTarget = GR_GL_TEXTURE_2D;
+ break;
+ case GrTextureType::kRectangle:
+ if (mipLevelCount > 1 || !this->glCaps().rectangleTextureSupport()) {
+ return nullptr;
+ }
+ texDesc.fTarget = GR_GL_TEXTURE_RECTANGLE;
+ break;
+ }
texDesc.fFormat = format.asGLFormat();
texDesc.fOwnership = GrBackendObjectOwnership::kOwned;
SkASSERT(texDesc.fFormat != GrGLFormat::kUnknown);
SkASSERT(!GrGLFormatIsCompressed(texDesc.fFormat));
- texDesc.fID = this->createTexture2D(dimensions, texDesc.fFormat, renderable, &initialState,
- mipLevelCount);
+ texDesc.fID = this->createTexture(dimensions, texDesc.fFormat, texDesc.fTarget, renderable,
+ &initialState, mipLevelCount);
if (!texDesc.fID) {
return return_null_texture();
@@ -1283,11 +1336,11 @@ sk_sp<GrTexture> GrGLGpu::onCreateTexture(SkISize dimensions,
tex->parameters()->set(&initialState, GrGLTextureParameters::NonsamplerState(),
fResetTimestampForTextureParameters);
if (levelClearMask) {
- GrGLenum externalFormat, externalType;
- GrColorType colorType;
- this->glCaps().getTexSubImageDefaultFormatTypeAndColorType(texDesc.fFormat, &externalFormat,
- &externalType, &colorType);
if (this->glCaps().clearTextureSupport()) {
+ GrGLenum externalFormat, externalType;
+ GrColorType colorType;
+ this->glCaps().getTexSubImageDefaultFormatTypeAndColorType(
+ texDesc.fFormat, &externalFormat, &externalType, &colorType);
for (int i = 0; i < mipLevelCount; ++i) {
if (levelClearMask & (1U << i)) {
GL_CALL(ClearTexImage(tex->textureID(), i, externalFormat, externalType,
@@ -1310,24 +1363,10 @@ sk_sp<GrTexture> GrGLGpu::onCreateTexture(SkISize dimensions,
}
fHWBoundRenderTargetUniqueID.makeInvalid();
} else {
- std::unique_ptr<char[]> zeros;
- GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
- for (int i = 0; i < mipLevelCount; ++i) {
- if (levelClearMask & (1U << i)) {
- int levelWidth = std::max(1, texDesc.fSize.width() >> i);
- int levelHeight = std::max(1, texDesc.fSize.height() >> i);
- // Levels only get smaller as we proceed. Once we create a zeros use it for all
- // smaller levels that need clearing.
- if (!zeros) {
- size_t bpp = GrColorTypeBytesPerPixel(colorType);
- size_t size = levelWidth * levelHeight * bpp;
- zeros.reset(new char[size]());
- }
- this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, tex->textureID());
- GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, i, 0, 0, levelWidth, levelHeight,
- externalFormat, externalType, zeros.get()));
- }
- }
+ this->bindTextureToScratchUnit(texDesc.fTarget, tex->textureID());
+ static constexpr SkColor4f kZeroColor = {0, 0, 0, 0};
+ this->uploadColorToTex(texDesc.fFormat, texDesc.fSize, texDesc.fTarget, kZeroColor,
+ levelClearMask);
}
}
return std::move(tex);
@@ -1343,13 +1382,15 @@ sk_sp<GrTexture> GrGLGpu::onCreateCompressedTexture(SkISize dimensions,
if (isProtected == GrProtected::kYes) {
return nullptr;
}
+ SkImage::CompressionType compression = GrBackendFormatToCompressionType(format);
+
GrGLTextureParameters::SamplerOverriddenState initialState;
GrGLTexture::Desc desc;
desc.fSize = dimensions;
desc.fTarget = GR_GL_TEXTURE_2D;
desc.fOwnership = GrBackendObjectOwnership::kOwned;
desc.fFormat = format.asGLFormat();
- desc.fID = this->createCompressedTexture2D(desc.fSize, desc.fFormat,
+ desc.fID = this->createCompressedTexture2D(desc.fSize, compression, desc.fFormat,
mipMapped, &initialState,
data, dataSize);
if (!desc.fID) {
@@ -1386,16 +1427,16 @@ GrBackendTexture GrGLGpu::onCreateCompressedBackendTexture(
return {};
}
+ SkImage::CompressionType compression = GrBackendFormatToCompressionType(format);
+
const char* rawData = nullptr;
size_t rawDataSize = 0;
SkAutoMalloc am;
-
SkASSERT(!data || data->type() != BackendTextureData::Type::kPixmaps);
if (data && data->type() == BackendTextureData::Type::kCompressed) {
rawData = (const char*) data->compressedData();
rawDataSize = data->compressedSize();
} else if (data && data->type() == BackendTextureData::Type::kColor) {
- SkImage::CompressionType compression = GrGLFormatToCompressionType(glFormat);
SkASSERT(compression != SkImage::CompressionType::kNone);
rawDataSize = SkCompressedDataSize(compression, dimensions, nullptr,
@@ -1413,7 +1454,7 @@ GrBackendTexture GrGLGpu::onCreateCompressedBackendTexture(
info.fTarget = GR_GL_TEXTURE_2D;
info.fFormat = GrGLFormatToEnum(glFormat);
- info.fID = this->createCompressedTexture2D(dimensions, glFormat,
+ info.fID = this->createCompressedTexture2D(dimensions, compression, glFormat,
mipMapped, &initialState,
rawData, rawDataSize);
if (!info.fID) {
@@ -1466,8 +1507,8 @@ int GrGLGpu::getCompatibleStencilIndex(GrGLFormat format) {
// Default to unsupported, set this if we find a stencil format that works.
int firstWorkingStencilFormatIndex = -1;
- GrGLuint colorID =
- this->createTexture2D({kSize, kSize}, format, GrRenderable::kYes, nullptr, 1);
+ GrGLuint colorID = this->createTexture({kSize, kSize}, format, GR_GL_TEXTURE_2D,
+ GrRenderable::kYes, nullptr, 1);
if (!colorID) {
return -1;
}
@@ -1536,6 +1577,7 @@ int GrGLGpu::getCompatibleStencilIndex(GrGLFormat format) {
GrGLuint GrGLGpu::createCompressedTexture2D(
SkISize dimensions,
+ SkImage::CompressionType compression,
GrGLFormat format,
GrMipMapped mipMapped,
GrGLTextureParameters::SamplerOverriddenState* initialState,
@@ -1554,7 +1596,7 @@ GrGLuint GrGLGpu::createCompressedTexture2D(
*initialState = set_initial_texture_params(this->glInterface(), GR_GL_TEXTURE_2D);
if (data) {
- if (!this->uploadCompressedTexData(format, dimensions, mipMapped,
+ if (!this->uploadCompressedTexData(compression, format, dimensions, mipMapped,
GR_GL_TEXTURE_2D, data, dataSize)) {
GL_CALL(DeleteTextures(1, &id));
return 0;
@@ -1564,11 +1606,12 @@ GrGLuint GrGLGpu::createCompressedTexture2D(
return id;
}
-GrGLuint GrGLGpu::createTexture2D(SkISize dimensions,
- GrGLFormat format,
- GrRenderable renderable,
- GrGLTextureParameters::SamplerOverriddenState* initialState,
- int mipLevelCount) {
+GrGLuint GrGLGpu::createTexture(SkISize dimensions,
+ GrGLFormat format,
+ GrGLenum target,
+ GrRenderable renderable,
+ GrGLTextureParameters::SamplerOverriddenState* initialState,
+ int mipLevelCount) {
SkASSERT(format != GrGLFormat::kUnknown);
SkASSERT(!GrGLFormatIsCompressed(format));
@@ -1579,17 +1622,17 @@ GrGLuint GrGLGpu::createTexture2D(SkISize dimensions,
return 0;
}
- this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, id);
+ this->bindTextureToScratchUnit(target, id);
if (GrRenderable::kYes == renderable && this->glCaps().textureUsageSupport()) {
// provides a hint about how this texture will be used
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_USAGE, GR_GL_FRAMEBUFFER_ATTACHMENT));
+ GL_CALL(TexParameteri(target, GR_GL_TEXTURE_USAGE, GR_GL_FRAMEBUFFER_ATTACHMENT));
}
if (initialState) {
- *initialState = set_initial_texture_params(this->glInterface(), GR_GL_TEXTURE_2D);
+ *initialState = set_initial_texture_params(this->glInterface(), target);
} else {
- set_initial_texture_params(this->glInterface(), GR_GL_TEXTURE_2D);
+ set_initial_texture_params(this->glInterface(), target);
}
GrGLenum internalFormat = this->glCaps().getTexImageOrStorageInternalFormat(format);
@@ -1598,9 +1641,8 @@ GrGLuint GrGLGpu::createTexture2D(SkISize dimensions,
if (internalFormat) {
if (this->glCaps().formatSupportsTexStorage(format)) {
auto levelCount = std::max(mipLevelCount, 1);
- GrGLenum error =
- GL_ALLOC_CALL(TexStorage2D(GR_GL_TEXTURE_2D, levelCount, internalFormat,
- dimensions.width(), dimensions.height()));
+ GrGLenum error = GL_ALLOC_CALL(TexStorage2D(target, levelCount, internalFormat,
+ dimensions.width(), dimensions.height()));
success = (error == GR_GL_NO_ERROR);
} else {
GrGLenum externalFormat, externalType;
@@ -1611,9 +1653,9 @@ GrGLuint GrGLGpu::createTexture2D(SkISize dimensions,
const int twoToTheMipLevel = 1 << level;
const int currentWidth = std::max(1, dimensions.width() / twoToTheMipLevel);
const int currentHeight = std::max(1, dimensions.height() / twoToTheMipLevel);
- error = GL_ALLOC_CALL(TexImage2D(GR_GL_TEXTURE_2D, level, internalFormat,
- currentWidth, currentHeight, 0, externalFormat,
- externalType, nullptr));
+ error = GL_ALLOC_CALL(TexImage2D(target, level, internalFormat, currentWidth,
+ currentHeight, 0, externalFormat, externalType,
+ nullptr));
}
success = (error == GR_GL_NO_ERROR);
}
@@ -1748,8 +1790,7 @@ void GrGLGpu::disableWindowRectangles() {
#endif
}
-bool GrGLGpu::flushGLState(GrRenderTarget* renderTarget,
- const GrProgramInfo& programInfo) {
+bool GrGLGpu::flushGLState(GrRenderTarget* renderTarget, const GrProgramInfo& programInfo) {
this->handleDirtyContext();
sk_sp<GrGLProgram> program = fProgramCache->findOrCreateProgram(renderTarget, programInfo);
@@ -1847,51 +1888,29 @@ GrGLenum GrGLGpu::bindBuffer(GrGpuBufferType type, const GrBuffer* buffer) {
return bufferState->fGLTarget;
}
-void GrGLGpu::clear(const GrFixedClip& clip, const SkPMColor4f& color,
+void GrGLGpu::clear(const GrScissorState& scissor, const SkPMColor4f& color,
GrRenderTarget* target, GrSurfaceOrigin origin) {
// parent class should never let us get here with no RT
SkASSERT(target);
SkASSERT(!this->caps()->performColorClearsAsDraws());
- SkASSERT(!clip.scissorEnabled() || !this->caps()->performPartialClearsAsDraws());
+ SkASSERT(!scissor.enabled() || !this->caps()->performPartialClearsAsDraws());
this->handleDirtyContext();
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
- if (clip.scissorEnabled()) {
- this->flushRenderTarget(glRT, origin, clip.scissorRect());
+ if (scissor.enabled()) {
+ this->flushRenderTarget(glRT, origin, scissor.rect());
} else {
this->flushRenderTarget(glRT);
}
- this->flushScissor(clip.scissorState(), glRT->width(), glRT->height(), origin);
- this->flushWindowRectangles(clip.windowRectsState(), glRT, origin);
+ this->flushScissor(scissor, glRT->width(), glRT->height(), origin);
+ this->disableWindowRectangles();
this->flushColorWrite(true);
this->flushClearColor(color);
GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT));
}
-void GrGLGpu::clearStencil(GrRenderTarget* target, int clearValue) {
- SkASSERT(!this->caps()->performStencilClearsAsDraws());
-
- if (!target) {
- return;
- }
-
- // This should only be called internally when we know we have a stencil buffer.
- SkASSERT(target->renderTargetPriv().getStencilAttachment());
-
- GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
- this->flushRenderTargetNoColorWrites(glRT);
-
- this->flushScissorTest(GrScissorTest::kDisabled);
- this->disableWindowRectangles();
-
- GL_CALL(StencilMask(0xffffffff));
- GL_CALL(ClearStencil(clearValue));
- GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
- fHWStencilSettings.invalidate();
-}
-
static bool use_tiled_rendering(const GrGLCaps& glCaps,
const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilLoadStore) {
// Only use the tiled rendering extension if we can explicitly clear and discard the stencil.
@@ -1989,11 +2008,11 @@ void GrGLGpu::endCommandBuffer(GrRenderTarget* rt,
SkDEBUGCODE(fIsExecutingCommandBuffer_DebugOnly = false);
}
-void GrGLGpu::clearStencilClip(const GrFixedClip& clip,
- bool insideStencilMask,
+void GrGLGpu::clearStencilClip(const GrScissorState& scissor, bool insideStencilMask,
GrRenderTarget* target, GrSurfaceOrigin origin) {
SkASSERT(target);
SkASSERT(!this->caps()->performStencilClearsAsDraws());
+ SkASSERT(!scissor.enabled() || !this->caps()->performPartialClearsAsDraws());
this->handleDirtyContext();
GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment();
@@ -2024,8 +2043,8 @@ void GrGLGpu::clearStencilClip(const GrFixedClip& clip,
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
this->flushRenderTargetNoColorWrites(glRT);
- this->flushScissor(clip.scissorState(), glRT->width(), glRT->height(), origin);
- this->flushWindowRectangles(clip.windowRectsState(), glRT, origin);
+ this->flushScissor(scissor, glRT->width(), glRT->height(), origin);
+ this->disableWindowRectangles();
GL_CALL(StencilMask((uint32_t) clipStencilMask));
GL_CALL(ClearStencil(value));
@@ -2136,7 +2155,8 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int
}
GrOpsRenderPass* GrGLGpu::getOpsRenderPass(
- GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
+ GrRenderTarget* rt, GrStencilAttachment*,
+ GrSurfaceOrigin origin, const SkIRect& bounds,
const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
@@ -2258,11 +2278,11 @@ void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resol
fHWBoundRenderTargetUniqueID.makeInvalid();
if (GrGLCaps::kES_Apple_MSFBOType == this->glCaps().msFBOType()) {
// Apple's extension uses the scissor as the blit bounds.
- GrScissorState scissorState;
- scissorState.set(resolveRect);
// Passing in kTopLeft_GrSurfaceOrigin will make sure no transformation of the rect
// happens inside flushScissor since resolveRect is already in native device coordinates.
- this->flushScissor(scissorState, rt->width(), rt->height(), kTopLeft_GrSurfaceOrigin);
+ GrScissorState scissor(rt->dimensions());
+ SkAssertResult(scissor.set(resolveRect));
+ this->flushScissor(scissor, rt->width(), rt->height(), kTopLeft_GrSurfaceOrigin);
this->disableWindowRectangles();
GL_CALL(ResolveMultisampleFramebuffer());
} else {
@@ -3547,16 +3567,29 @@ GrBackendTexture GrGLGpu::onCreateBackendTexture(SkISize dimensions,
if (glFormat == GrGLFormat::kUnknown) {
return {};
}
-
- info.fTarget = GR_GL_TEXTURE_2D;
+ switch (format.textureType()) {
+ case GrTextureType::kNone:
+ case GrTextureType::kExternal:
+ return {};
+ case GrTextureType::k2D:
+ info.fTarget = GR_GL_TEXTURE_2D;
+ break;
+ case GrTextureType::kRectangle:
+ if (!this->glCaps().rectangleTextureSupport() || mipMapped == GrMipMapped::kYes) {
+ return {};
+ }
+ info.fTarget = GR_GL_TEXTURE_RECTANGLE;
+ break;
+ }
info.fFormat = GrGLFormatToEnum(glFormat);
- info.fID = this->createTexture2D(dimensions, glFormat, renderable, &initialState, numMipLevels);
+ info.fID = this->createTexture(dimensions, glFormat, info.fTarget, renderable, &initialState,
+ numMipLevels);
if (!info.fID) {
return {};
}
// Unbind this texture from the scratch texture unit.
- this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, 0);
+ this->bindTextureToScratchUnit(info.fTarget, 0);
auto parameters = sk_make_sp<GrGLTextureParameters>();
// The non-sampler params are still at their default values.
@@ -3581,25 +3614,26 @@ bool GrGLGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
GrGLFormat glFormat = GrGLFormatFromGLEnum(info.fFormat);
- this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, info.fID);
+ this->bindTextureToScratchUnit(info.fTarget, info.fID);
- // If we have mips make sure the base level is set to 0 and the max level set to numMipLevesl-1
+ // If we have mips make sure the base level is set to 0 and the max level set to numMipLevels-1
// so that the uploads go to the right levels.
- if (numMipLevels) {
+ if (numMipLevels && this->glCaps().mipMapLevelAndLodControlSupport()) {
auto params = backendTexture.getGLTextureParams();
GrGLTextureParameters::NonsamplerState nonsamplerState = params->nonsamplerState();
if (params->nonsamplerState().fBaseMipMapLevel != 0) {
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_BASE_LEVEL, 0));
+ GL_CALL(TexParameteri(info.fTarget, GR_GL_TEXTURE_BASE_LEVEL, 0));
nonsamplerState.fBaseMipMapLevel = 0;
}
if (params->nonsamplerState().fMaxMipMapLevel != (numMipLevels - 1)) {
- GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAX_LEVEL, numMipLevels - 1));
+ GL_CALL(TexParameteri(info.fTarget, GR_GL_TEXTURE_MAX_LEVEL, numMipLevels - 1));
nonsamplerState.fBaseMipMapLevel = numMipLevels - 1;
}
params->set(nullptr, nonsamplerState, fResetTimestampForTextureParameters);
}
SkASSERT(data->type() != BackendTextureData::Type::kCompressed);
+ bool result = false;
if (data->type() == BackendTextureData::Type::kPixmaps) {
SkTDArray<GrMipLevel> texels;
GrColorType colorType = SkColorTypeToGrColorType(data->pixmap(0).colorType());
@@ -3607,47 +3641,19 @@ bool GrGLGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
for (int i = 0; i < numMipLevels; ++i) {
texels[i] = {data->pixmap(i).addr(), data->pixmap(i).rowBytes()};
}
- if (!this->uploadTexData(glFormat, colorType, backendTexture.width(),
- backendTexture.height(), GR_GL_TEXTURE_2D, 0, 0,
- backendTexture.width(), backendTexture.height(),
- colorType, texels.begin(), texels.count())) {
- GL_CALL(DeleteTextures(1, &info.fID));
- return false;
- }
- } else if (data && data->type() == BackendTextureData::Type::kColor) {
- // TODO: Unify this with the clear texture code in onCreateTexture().
- GrColorType colorType;
- GrGLenum externalFormat, externalType;
- this->glCaps().getTexSubImageDefaultFormatTypeAndColorType(glFormat, &externalFormat,
- &externalType, &colorType);
- if (colorType == GrColorType::kUnknown) {
- GL_CALL(DeleteTextures(1, &info.fID));
- return false;
- }
-
- // Make one tight image at the base size and reuse it for smaller levels.
- GrImageInfo ii(colorType, kUnpremul_SkAlphaType, nullptr, backendTexture.dimensions());
- auto rb = ii.minRowBytes();
- std::unique_ptr<char[]> pixelStorage(new char[rb * backendTexture.height()]);
- if (!GrClearImage(ii, pixelStorage.get(), rb, data->color())) {
- GL_CALL(DeleteTextures(1, &info.fID));
- return false;
- }
-
- GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
- SkISize levelDimensions = backendTexture.dimensions();
- for (int i = 0; i < numMipLevels; ++i) {
- GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, i, 0, 0, levelDimensions.width(),
- levelDimensions.height(), externalFormat, externalType,
- pixelStorage.get()));
- levelDimensions = {std::max(1, levelDimensions.width() / 2),
- std::max(1, levelDimensions.height() / 2)};
- }
+ SkIRect dstRect = SkIRect::MakeSize(backendTexture.dimensions());
+ result = this->uploadColorTypeTexData(glFormat, colorType, backendTexture.dimensions(),
+ info.fTarget, dstRect, colorType, texels.begin(),
+ texels.count());
+ } else if (data->type() == BackendTextureData::Type::kColor) {
+ uint32_t levelMask = (1 << numMipLevels) - 1;
+ result = this->uploadColorToTex(glFormat, backendTexture.dimensions(), info.fTarget,
+ data->color(), levelMask);
}
// Unbind this texture from the scratch texture unit.
- this->bindTextureToScratchUnit(GR_GL_TEXTURE_2D, 0);
- return true;
+ this->bindTextureToScratchUnit(info.fTarget, 0);
+ return result;
}
void GrGLGpu::deleteBackendTexture(const GrBackendTexture& tex) {
@@ -3743,7 +3749,8 @@ GrBackendRenderTarget GrGLGpu::createTestingOnlyBackendRenderTarget(int w, int h
this->bindFramebuffer(GR_GL_FRAMEBUFFER, info.fFBOID);
if (useTexture) {
GrGLTextureParameters::SamplerOverriddenState initialState;
- colorID = this->createTexture2D({w, h}, format, GrRenderable::kYes, &initialState, 1);
+ colorID = this->createTexture({w, h}, format, GR_GL_TEXTURE_2D, GrRenderable::kYes,
+ &initialState, 1);
if (!colorID) {
deleteIDs();
return {};
@@ -3859,6 +3866,9 @@ bool GrGLGpu::onSubmitToGpu(bool syncCpu) {
// See if any previously inserted finish procs are good to go.
fFinishCallbacks.check();
}
+ if (!this->glCaps().skipErrorChecks()) {
+ this->clearErrorsAndCheckForOOM();
+ }
return true;
}
@@ -3938,6 +3948,7 @@ std::unique_ptr<GrSemaphore> GrGLGpu::wrapBackendSemaphore(
}
void GrGLGpu::insertSemaphore(GrSemaphore* semaphore) {
+ SkASSERT(semaphore);
GrGLSemaphore* glSem = static_cast<GrGLSemaphore*>(semaphore);
GrGLsync sync;
@@ -3947,6 +3958,7 @@ void GrGLGpu::insertSemaphore(GrSemaphore* semaphore) {
}
void GrGLGpu::waitSemaphore(GrSemaphore* semaphore) {
+ SkASSERT(semaphore);
GrGLSemaphore* glSem = static_cast<GrGLSemaphore*>(semaphore);
GL_CALL(WaitSync(glSem->sync(), 0, GR_GL_TIMEOUT_IGNORED));
@@ -3956,6 +3968,23 @@ void GrGLGpu::checkFinishProcs() {
fFinishCallbacks.check();
}
+void GrGLGpu::clearErrorsAndCheckForOOM() {
+ while (this->getErrorAndCheckForOOM() != GR_GL_NO_ERROR) {}
+}
+
+GrGLenum GrGLGpu::getErrorAndCheckForOOM() {
+#if GR_GL_CHECK_ERROR
+ if (this->glInterface()->checkAndResetOOMed()) {
+ this->setOOMed();
+ }
+#endif
+ GrGLenum error = this->fGLContext->glInterface()->fFunctions.fGetError();
+ if (error == GR_GL_OUT_OF_MEMORY) {
+ this->setOOMed();
+ }
+ return error;
+}
+
void GrGLGpu::deleteSync(GrGLsync sync) const {
if (this->glCaps().fenceType() == GrGLCaps::FenceType::kNVFence) {
GrGLuint nvFence = SkToUInt(reinterpret_cast<intptr_t>(sync));
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLGpu.h b/chromium/third_party/skia/src/gpu/gl/GrGLGpu.h
index a716cf8a03c..0a40333c531 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLGpu.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLGpu.h
@@ -104,18 +104,14 @@ public:
// The GrGLOpsRenderPass does not buffer up draws before submitting them to the gpu.
// Thus this is the implementation of the clear call for the corresponding passthrough function
// on GrGLOpsRenderPass.
- void clear(const GrFixedClip&, const SkPMColor4f&, GrRenderTarget*, GrSurfaceOrigin);
+ void clear(const GrScissorState&, const SkPMColor4f&, GrRenderTarget*, GrSurfaceOrigin);
// The GrGLOpsRenderPass does not buffer up draws before submitting them to the gpu.
// Thus this is the implementation of the clearStencil call for the corresponding passthrough
// function on GrGLOpsrenderPass.
- void clearStencilClip(const GrFixedClip&, bool insideStencilMask,
+ void clearStencilClip(const GrScissorState&, bool insideStencilMask,
GrRenderTarget*, GrSurfaceOrigin);
- // FIXME (michaelludwig): Can this go away and just use clearStencilClip() + marking the
- // stencil buffer as not dirty?
- void clearStencil(GrRenderTarget*, int clearValue);
-
void beginCommandBuffer(GrRenderTarget*, const SkIRect& bounds, GrSurfaceOrigin,
const GrOpsRenderPass::LoadAndStoreInfo& colorLoadStore,
const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilLoadStore);
@@ -124,7 +120,8 @@ public:
const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilLoadStore);
GrOpsRenderPass* getOpsRenderPass(
- GrRenderTarget*, GrSurfaceOrigin, const SkIRect&,
+ GrRenderTarget*, GrStencilAttachment*,
+ GrSurfaceOrigin, const SkIRect&,
const GrOpsRenderPass::LoadAndStoreInfo&,
const GrOpsRenderPass::StencilLoadAndStoreInfo&,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override;
@@ -172,6 +169,11 @@ public:
void checkFinishProcs() override;
+ // Calls glGetError() until no errors are reported. Also looks for OOMs.
+ void clearErrorsAndCheckForOOM();
+ // Calls glGetError() once and returns the result. Also looks for an OOM.
+ GrGLenum getErrorAndCheckForOOM();
+
std::unique_ptr<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override;
void deleteSync(GrGLsync) const;
@@ -181,6 +183,11 @@ public:
void insertManualFramebufferBarrier() override;
+ void flushProgram(sk_sp<GrGLProgram>);
+
+ // Version for programs that aren't GrGLProgram.
+ void flushProgram(GrGLuint);
+
private:
GrGLGpu(std::unique_ptr<GrGLContext>, GrContext*);
@@ -253,13 +260,15 @@ private:
// returned. On failure, zero is returned.
// The texture is populated with |texels|, if it is non-null.
// The texture parameters are cached in |initialTexParams|.
- GrGLuint createTexture2D(SkISize dimensions,
- GrGLFormat,
- GrRenderable,
- GrGLTextureParameters::SamplerOverriddenState*,
- int mipLevelCount);
+ GrGLuint createTexture(SkISize dimensions,
+ GrGLFormat,
+ GrGLenum target,
+ GrRenderable,
+ GrGLTextureParameters::SamplerOverriddenState*,
+ int mipLevelCount);
GrGLuint createCompressedTexture2D(SkISize dimensions,
+ SkImage::CompressionType compression,
GrGLFormat,
GrMipMapped,
GrGLTextureParameters::SamplerOverriddenState*,
@@ -299,11 +308,6 @@ private:
// binds texture unit in GL
void setTextureUnit(int unitIdx);
- void flushProgram(sk_sp<GrGLProgram>);
-
- // Version for programs that aren't GrGLProgram.
- void flushProgram(GrGLuint);
-
void flushBlendAndColorWrite(const GrXferProcessor::BlendInfo& blendInfo, const GrSwizzle&);
void addFinishedProc(GrGpuFinishedProc finishedProc,
@@ -411,14 +415,45 @@ private:
void flushFramebufferSRGB(bool enable);
- bool uploadTexData(GrGLFormat textureFormat, GrColorType textureColorType, int texWidth,
- int texHeight, GrGLenum target, int left, int top, int width, int height,
- GrColorType srcColorType, const GrMipLevel texels[], int mipLevelCount,
- GrMipMapsStatus* mipMapsStatus = nullptr);
+ // Uploads src data of a color type to the currently bound texture on the active texture unit.
+ // The caller specifies color type that the texture is being used with, which may be different
+ // than the src color type. This fails if the combination of texture format, texture color type,
+ // and src data color type are not valid. No conversion is performed on the data before passing
+ // it to GL. 'dstRect' must be the texture bounds if mipLevelCount is greater than 1.
+ bool uploadColorTypeTexData(GrGLFormat textureFormat,
+ GrColorType textureColorType,
+ SkISize texDims,
+ GrGLenum target,
+ SkIRect dstRect,
+ GrColorType srcColorType,
+ const GrMipLevel texels[],
+ int mipLevelCount);
+
+ // Uploads a constant color to a texture using the "default" format and color type. Overwrites
+ // entire levels. Bit n in 'levelMask' indicates whether level n should be written. This
+ // function doesn't know if MIP levels have been allocated, thus levelMask should not have bits
+ // beyond the low bit set if the texture is not MIP mapped.
+ bool uploadColorToTex(GrGLFormat textureFormat,
+ SkISize texDims,
+ GrGLenum target,
+ SkColor4f color,
+ uint32_t levelMask);
+
+ // Pushes data to the currently bound texture to the currently active unit. 'dstRect' must be
+ // the texture bounds if mipLevelCount is greater than 1.
+ void uploadTexData(SkISize dimensions,
+ GrGLenum target,
+ SkIRect dstRect,
+ GrGLenum externalFormat,
+ GrGLenum externalType,
+ size_t bpp,
+ const GrMipLevel texels[],
+ int mipLevelCount);
// Helper for onCreateCompressedTexture. Compressed textures are read-only so we only use this
// to populate a new texture. Returns false if we failed to create and upload the texture.
- bool uploadCompressedTexData(GrGLFormat,
+ bool uploadCompressedTexData(SkImage::CompressionType compressionType,
+ GrGLFormat,
SkISize dimensions,
GrMipMapped,
GrGLenum target,
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLInterfaceAutogen.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLInterfaceAutogen.cpp
index c465fe618c0..c4f61ffe9f7 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLInterfaceAutogen.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLInterfaceAutogen.cpp
@@ -19,6 +19,54 @@ GrGLInterface::GrGLInterface() {
fStandard = kNone_GrGLStandard;
}
+#if GR_GL_CHECK_ERROR
+static const char* get_error_string(GrGLenum err) {
+ switch (err) {
+ case GR_GL_NO_ERROR:
+ return "";
+ case GR_GL_INVALID_ENUM:
+ return "Invalid Enum";
+ case GR_GL_INVALID_VALUE:
+ return "Invalid Value";
+ case GR_GL_INVALID_OPERATION:
+ return "Invalid Operation";
+ case GR_GL_OUT_OF_MEMORY:
+ return "Out of Memory";
+ case GR_GL_CONTEXT_LOST:
+ return "Context Lost";
+ }
+ return "Unknown";
+}
+
+GrGLenum GrGLInterface::checkError(const char* location, const char* call) const {
+ GrGLenum error = fFunctions.fGetError();
+ if (error != GR_GL_NO_ERROR && !fSuppressErrorLogging) {
+ SkDebugf("---- glGetError 0x%x(%s)", error, get_error_string(error));
+ if (location) {
+ SkDebugf(" at\n\t%s", location);
+ }
+ if (call) {
+ SkDebugf("\n\t\t%s", call);
+ }
+ SkDebugf("\n");
+ if (error == GR_GL_OUT_OF_MEMORY) {
+ fOOMed = true;
+ }
+ }
+ return error;
+}
+
+bool GrGLInterface::checkAndResetOOMed() const {
+ if (fOOMed) {
+ fOOMed = false;
+ return true;
+ }
+ return false;
+}
+
+void GrGLInterface::suppressErrorLogging() { fSuppressErrorLogging = true; }
+#endif
+
#define RETURN_FALSE_INTERFACE \
SkDEBUGF("%s:%d GrGLInterface::validate() failed.\n", __FILE__, __LINE__); \
return false
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.cpp
index 865d8075fe8..0d2a801ed90 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.cpp
@@ -8,7 +8,6 @@
#include "src/gpu/gl/GrGLOpsRenderPass.h"
#include "src/gpu/GrContextPriv.h"
-#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrRenderTargetPriv.h"
@@ -259,12 +258,10 @@ void GrGLOpsRenderPass::onDrawIndexedIndirect(const GrBuffer* drawIndirectBuffer
}
}
-void GrGLOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& color) {
- fGpu->clear(clip, color, fRenderTarget, fOrigin);
+void GrGLOpsRenderPass::onClear(const GrScissorState& scissor, const SkPMColor4f& color) {
+ fGpu->clear(scissor, color, fRenderTarget, fOrigin);
}
-void GrGLOpsRenderPass::onClearStencilClip(const GrFixedClip& clip,
- bool insideStencilMask) {
- fGpu->clearStencilClip(clip, insideStencilMask, fRenderTarget, fOrigin);
+void GrGLOpsRenderPass::onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) {
+ fGpu->clearStencilClip(scissor, insideStencilMask, fRenderTarget, fOrigin);
}
-
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.h b/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.h
index b16dda1a953..038e5586f35 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLOpsRenderPass.h
@@ -69,8 +69,8 @@ private:
void onDrawIndirect(const GrBuffer* drawIndirectBuffer, size_t offset, int drawCount) override;
void onDrawIndexedIndirect(const GrBuffer* drawIndirectBuffer, size_t offset,
int drawCount) override;
- void onClear(const GrFixedClip& clip, const SkPMColor4f& color) override;
- void onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) override;
+ void onClear(const GrScissorState& scissor, const SkPMColor4f& color) override;
+ void onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) override;
GrGLGpu* fGpu;
SkIRect fContentBounds;
@@ -89,4 +89,3 @@ private:
};
#endif
-
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLProgram.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLProgram.cpp
index e8f08847ce6..17938d42a99 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLProgram.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLProgram.cpp
@@ -26,6 +26,43 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
+sk_sp<GrGLProgram> GrGLProgram::Make(
+ GrGLGpu* gpu,
+ const GrGLSLBuiltinUniformHandles& builtinUniforms,
+ GrGLuint programID,
+ const UniformInfoArray& uniforms,
+ const UniformInfoArray& textureSamplers,
+ const VaryingInfoArray& pathProcVaryings,
+ std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
+ std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
+ std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fps,
+ int fragmentProcessorCnt,
+ std::unique_ptr<Attribute[]> attributes,
+ int vertexAttributeCnt,
+ int instanceAttributeCnt,
+ int vertexStride,
+ int instanceStride) {
+ sk_sp<GrGLProgram> program(new GrGLProgram(gpu,
+ builtinUniforms,
+ programID,
+ uniforms,
+ textureSamplers,
+ pathProcVaryings,
+ std::move(geometryProcessor),
+ std::move(xferProcessor),
+ std::move(fps),
+ fragmentProcessorCnt,
+ std::move(attributes),
+ vertexAttributeCnt,
+ instanceAttributeCnt,
+ vertexStride,
+ instanceStride));
+ // Assign texture units to sampler uniforms one time up front.
+ gpu->flushProgram(program);
+ program->fProgramDataManager.setSamplerUniforms(textureSamplers, 0);
+ return program;
+}
+
GrGLProgram::GrGLProgram(
GrGLGpu* gpu,
const GrGLSLBuiltinUniformHandles& builtinUniforms,
@@ -35,7 +72,7 @@ GrGLProgram::GrGLProgram(
const VaryingInfoArray& pathProcVaryings,
std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
- std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,
+ std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fps,
int fragmentProcessorCnt,
std::unique_ptr<Attribute[]> attributes,
int vertexAttributeCnt,
@@ -46,7 +83,7 @@ GrGLProgram::GrGLProgram(
, fProgramID(programID)
, fPrimitiveProcessor(std::move(geometryProcessor))
, fXferProcessor(std::move(xferProcessor))
- , fFragmentProcessors(std::move(fragmentProcessors))
+ , fFragmentProcessors(std::move(fps))
, fFragmentProcessorCnt(fragmentProcessorCnt)
, fAttributes(std::move(attributes))
, fVertexAttributeCnt(vertexAttributeCnt)
@@ -56,9 +93,6 @@ GrGLProgram::GrGLProgram(
, fGpu(gpu)
, fProgramDataManager(gpu, programID, uniforms, pathProcVaryings)
, fNumTextureSamplers(textureSamplers.count()) {
- // Assign texture units to sampler uniforms one time up front.
- GL_CALL(UseProgram(fProgramID));
- fProgramDataManager.setSamplerUniforms(textureSamplers, 0);
}
GrGLProgram::~GrGLProgram() {
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLProgram.h b/chromium/third_party/skia/src/gpu/gl/GrGLProgram.h
index f784f2b0aa9..ce9e262f7bc 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLProgram.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLProgram.h
@@ -48,21 +48,21 @@ public:
* The attribute array consists of vertexAttributeCnt + instanceAttributeCnt elements with
* the vertex attributes preceding the instance attributes.
*/
- GrGLProgram(GrGLGpu*,
- const GrGLSLBuiltinUniformHandles&,
- GrGLuint programID,
- const UniformInfoArray& uniforms,
- const UniformInfoArray& textureSamplers,
- const VaryingInfoArray&, // used for NVPR only currently
- std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
- std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
- std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,
- int fragmentProcessorCnt,
- std::unique_ptr<Attribute[]>,
- int vertexAttributeCnt,
- int instanceAttributeCnt,
- int vertexStride,
- int instanceStride);
+ static sk_sp<GrGLProgram> Make(GrGLGpu*,
+ const GrGLSLBuiltinUniformHandles&,
+ GrGLuint programID,
+ const UniformInfoArray& uniforms,
+ const UniformInfoArray& textureSamplers,
+ const VaryingInfoArray&, // used for NVPR only currently
+ std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
+ std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
+ std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fps,
+ int fragmentProcessorCnt,
+ std::unique_ptr<Attribute[]>,
+ int vertexAttributeCnt,
+ int instanceAttributeCnt,
+ int vertexStride,
+ int instanceStride);
~GrGLProgram();
@@ -141,6 +141,22 @@ public:
}
private:
+ GrGLProgram(GrGLGpu*,
+ const GrGLSLBuiltinUniformHandles&,
+ GrGLuint programID,
+ const UniformInfoArray& uniforms,
+ const UniformInfoArray& textureSamplers,
+ const VaryingInfoArray&, // used for NVPR only currently
+ std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
+ std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
+ std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fps,
+ int fragmentProcessorCnt,
+ std::unique_ptr<Attribute[]>,
+ int vertexAttributeCnt,
+ int instanceAttributeCnt,
+ int vertexStride,
+ int instanceStride);
+
// Helper for setData() that sets the view matrix and loads the render target height uniform
void setRenderTargetState(const GrRenderTarget*, GrSurfaceOrigin, const GrPrimitiveProcessor&);
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLUtil.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLUtil.cpp
index 28bdbd6588e..fc4781d2814 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLUtil.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLUtil.cpp
@@ -12,46 +12,6 @@
#include "src/gpu/gl/GrGLUtil.h"
#include <stdio.h>
-void GrGLClearErr(const GrGLInterface* gl) {
- while (GR_GL_NO_ERROR != gl->fFunctions.fGetError()) {}
-}
-
-namespace {
-const char *get_error_string(uint32_t err) {
- switch (err) {
- case GR_GL_NO_ERROR:
- return "";
- case GR_GL_INVALID_ENUM:
- return "Invalid Enum";
- case GR_GL_INVALID_VALUE:
- return "Invalid Value";
- case GR_GL_INVALID_OPERATION:
- return "Invalid Operation";
- case GR_GL_OUT_OF_MEMORY:
- return "Out of Memory";
- case GR_GL_CONTEXT_LOST:
- return "Context Lost";
- }
- return "Unknown";
-}
-}
-
-void GrGLCheckErr(const GrGLInterface* gl,
- const char* location,
- const char* call) {
- uint32_t err = GR_GL_GET_ERROR(gl);
- if (GR_GL_NO_ERROR != err) {
- SkDebugf("---- glGetError 0x%x(%s)", err, get_error_string(err));
- if (location) {
- SkDebugf(" at\n\t%s", location);
- }
- if (call) {
- SkDebugf("\n\t\t%s", call);
- }
- SkDebugf("\n");
- }
-}
-
///////////////////////////////////////////////////////////////////////////////
#if GR_GL_LOG_CALLS
@@ -480,33 +440,38 @@ GrGLRenderer GrGLGetRendererFromStrings(const char* rendererString,
static constexpr char kRadeonStr[] = "Radeon ";
if (const char* amdString = strstr(rendererString, kRadeonStr)) {
amdString += strlen(kRadeonStr);
- char amdGeneration, amdTier, amdRevision;
// Sometimes there is a (TM) and sometimes not.
static constexpr char kTMStr[] = "(TM) ";
if (!strncmp(amdString, kTMStr, strlen(kTMStr))) {
amdString += strlen(kTMStr);
}
- n = sscanf(amdString, "R9 M%c%c%c", &amdGeneration, &amdTier, &amdRevision);
- if (3 == n) {
- if ('3' == amdGeneration) {
- return kAMDRadeonR9M3xx_GrGLRenderer;
- } else if ('4' == amdGeneration) {
- return kAMDRadeonR9M4xx_GrGLRenderer;
- }
- }
char amd0, amd1, amd2;
+ int amdModel;
+ n = sscanf(amdString, "R9 M3%c%c", &amd0, &amd1);
+ if (2 == n && isdigit(amd0) && isdigit(amd1)) {
+ return kAMDRadeonR9M3xx_GrGLRenderer;
+ }
+
+ n = sscanf(amdString, "R9 M4%c%c", &amd0, &amd1);
+ if (2 == n && isdigit(amd0) && isdigit(amd1)) {
+ return kAMDRadeonR9M4xx_GrGLRenderer;
+ }
+
n = sscanf(amdString, "HD 7%c%c%c Series", &amd0, &amd1, &amd2);
- if (3 == n) {
+ if (3 == n && isdigit(amd0) && isdigit(amd1) && isdigit(amd2)) {
return kAMDRadeonHD7xxx_GrGLRenderer;
}
- int amdVegaModel=0;
- n = sscanf(amdString, "Pro Vega %i", &amdVegaModel);
+ n = sscanf(amdString, "Pro 5%c%c%c", &amd0, &amd1, &amd2);
+ if (3 == n && isdigit(amd0) && isdigit(amd1) && isdigit(amd2)) {
+ return kAMDRadeonPro5xxx_GrGLRenderer;
+ }
+
+ n = sscanf(amdString, "Pro Vega %i", &amdModel);
if (1 == n) {
return kAMDRadeonProVegaxx_GrGLRenderer;
}
-
}
if (strstr(rendererString, "llvmpipe")) {
@@ -579,6 +544,8 @@ std::tuple<GrGLANGLEBackend, GrGLANGLEVendor, GrGLANGLERenderer> GrGLGetANGLEInf
}
} else if (strstr(rendererString, "NVIDIA")) {
vendor = GrGLANGLEVendor::kNVIDIA;
+ } else if (strstr(rendererString, "Radeon")) {
+ vendor = GrGLANGLEVendor::kAMD;
}
if (strstr(rendererString, "Direct3D11")) {
backend = GrGLANGLEBackend::kD3D11;
@@ -678,37 +645,3 @@ bool GrGLFormatIsCompressed(GrGLFormat format) {
SkUNREACHABLE;
}
-SkImage::CompressionType GrGLFormatToCompressionType(GrGLFormat format) {
- switch (format) {
- case GrGLFormat::kCOMPRESSED_ETC1_RGB8:
- case GrGLFormat::kCOMPRESSED_RGB8_ETC2:
- return SkImage::CompressionType::kETC2_RGB8_UNORM;
- case GrGLFormat::kCOMPRESSED_RGB8_BC1:
- return SkImage::CompressionType::kBC1_RGB8_UNORM;
- case GrGLFormat::kCOMPRESSED_RGBA8_BC1:
- return SkImage::CompressionType::kBC1_RGBA8_UNORM;
-
- case GrGLFormat::kRGBA8:
- case GrGLFormat::kR8:
- case GrGLFormat::kALPHA8:
- case GrGLFormat::kLUMINANCE8:
- case GrGLFormat::kBGRA8:
- case GrGLFormat::kRGB565:
- case GrGLFormat::kRGBA16F:
- case GrGLFormat::kR16F:
- case GrGLFormat::kLUMINANCE16F:
- case GrGLFormat::kRGB8:
- case GrGLFormat::kRG8:
- case GrGLFormat::kRGB10_A2:
- case GrGLFormat::kRGBA4:
- case GrGLFormat::kSRGB8_ALPHA8:
- case GrGLFormat::kR16:
- case GrGLFormat::kRG16:
- case GrGLFormat::kRGBA16:
- case GrGLFormat::kRG16F:
- case GrGLFormat::kUnknown:
- return SkImage::CompressionType::kNone;
- }
- SkUNREACHABLE;
-}
-
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLUtil.h b/chromium/third_party/skia/src/gpu/gl/GrGLUtil.h
index e168275a16d..08435d0a1ab 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLUtil.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLUtil.h
@@ -130,6 +130,7 @@ enum GrGLRenderer {
kAMDRadeonHD7xxx_GrGLRenderer, // AMD Radeon HD 7000 Series
kAMDRadeonR9M3xx_GrGLRenderer, // AMD Radeon R9 M300 Series
kAMDRadeonR9M4xx_GrGLRenderer, // AMD Radeon R9 M400 Series
+ kAMDRadeonPro5xxx_GrGLRenderer, // AMD Radeon Pro 5000 Series
kAMDRadeonProVegaxx_GrGLRenderer, // AMD Radeon Pro Vega
kOther_GrGLRenderer
@@ -157,7 +158,8 @@ enum class GrGLANGLEBackend {
enum class GrGLANGLEVendor {
kUnknown,
kIntel,
- kNVIDIA
+ kNVIDIA,
+ kAMD
};
enum class GrGLANGLERenderer {
@@ -255,23 +257,25 @@ void GrGLCheckErr(const GrGLInterface* gl,
const char* location,
const char* call);
-void GrGLClearErr(const GrGLInterface* gl);
-
////////////////////////////////////////////////////////////////////////////////
/**
* Macros for using GrGLInterface to make GL calls
*/
-// internal macro to conditionally call glGetError based on compile-time and
-// run-time flags.
+// Conditionally checks glGetError based on compile-time and run-time flags.
#if GR_GL_CHECK_ERROR
extern bool gCheckErrorGL;
- #define GR_GL_CHECK_ERROR_IMPL(IFACE, X) \
- if (gCheckErrorGL) \
- GrGLCheckErr(IFACE, GR_FILE_AND_LINE_STR, #X)
+#define GR_GL_CHECK_ERROR_IMPL(IFACE, X) \
+ do { \
+ if (gCheckErrorGL) { \
+ IFACE->checkError(GR_FILE_AND_LINE_STR, #X); \
+ } \
+ } while (false)
#else
- #define GR_GL_CHECK_ERROR_IMPL(IFACE, X)
+#define GR_GL_CHECK_ERROR_IMPL(IFACE, X) \
+ do { \
+ } while (false)
#endif
// internal macro to conditionally log the gl call using SkDebugf based on
@@ -314,9 +318,6 @@ void GrGLClearErr(const GrGLInterface* gl);
GR_GL_LOG_CALLS_IMPL(X); \
} while (false)
-// call glGetError without doing a redundant error check or logging.
-#define GR_GL_GET_ERROR(IFACE) (IFACE)->fFunctions.fGetError()
-
static constexpr GrGLFormat GrGLFormatFromGLEnum(GrGLenum glFormat) {
switch (glFormat) {
case GR_GL_RGBA8: return GrGLFormat::kRGBA8;
@@ -415,9 +416,4 @@ GrGLenum GrToGLStencilFunc(GrStencilTest test);
*/
bool GrGLFormatIsCompressed(GrGLFormat);
-/**
- * This will return CompressionType::kNone if the format is uncompressed.
- */
-SkImage::CompressionType GrGLFormatToCompressionType(GrGLFormat);
-
#endif
diff --git a/chromium/third_party/skia/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/chromium/third_party/skia/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index 6c2ba755bcd..230298f00c7 100644
--- a/chromium/third_party/skia/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -10,9 +10,9 @@
#include "include/gpu/GrContext.h"
#include "src/core/SkATrace.h"
#include "src/core/SkAutoMalloc.h"
-#include "src/core/SkReader32.h"
+#include "src/core/SkReadBuffer.h"
#include "src/core/SkTraceEvent.h"
-#include "src/core/SkWriter32.h"
+#include "src/core/SkWriteBuffer.h"
#include "src/gpu/GrAutoLocaleSetter.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrCoordTransform.h"
@@ -166,16 +166,19 @@ void GrGLProgramBuilder::storeShaderInCache(const SkSL::Program::Inputs& inputs,
GrGLsizei length = 0;
GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length));
if (length > 0) {
- SkWriter32 writer;
- writer.write32(kGLPB_Tag);
+ SkBinaryWriteBuffer writer;
+ writer.writeInt(GrPersistentCacheUtils::kCurrentVersion);
+ writer.writeUInt(kGLPB_Tag);
- writer.writePad(&inputs, sizeof(inputs));
- writer.write32(length);
+ writer.writePad32(&inputs, sizeof(inputs));
- void* binary = writer.reservePad(length);
+ SkAutoSMalloc<2048> binary(length);
GrGLenum binaryFormat;
- GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary));
- writer.write32(binaryFormat);
+ GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary.get()));
+
+ writer.writeUInt(binaryFormat);
+ writer.writeInt(length);
+ writer.writePad32(binary.get(), length);
auto data = writer.snapshotAsData();
this->gpu()->getContext()->priv().getPersistentCache()->store(*key, *data);
@@ -254,7 +257,7 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr
usedProgramBinaries = true;
} else if (cached) {
ATRACE_ANDROID_FRAMEWORK_ALWAYS("cache_hit");
- SkReader32 reader(fCached->data(), fCached->size());
+ SkReadBuffer reader(fCached->data(), fCached->size());
SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
switch (shaderType) {
@@ -265,15 +268,18 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr
cached = false;
break;
}
- reader.read(&inputs, sizeof(inputs));
- GrGLsizei length = reader.readInt();
+ reader.readPad32(&inputs, sizeof(inputs));
+ GrGLenum binaryFormat = reader.readUInt();
+ GrGLsizei length = reader.readInt();
const void* binary = reader.skip(length);
- GrGLenum binaryFormat = reader.readU32();
- GrGLClearErr(this->gpu()->glInterface());
+ if (!reader.isValid()) {
+ break;
+ }
+ this->gpu()->clearErrorsAndCheckForOOM();
GR_GL_CALL_NOERRCHECK(this->gpu()->glInterface(),
ProgramBinary(programID, binaryFormat,
const_cast<void*>(binary), length));
- if (GR_GL_GET_ERROR(this->gpu()->glInterface()) == GR_GL_NO_ERROR) {
+ if (this->gpu()->getErrorAndCheckForOOM() == GR_GL_NO_ERROR) {
if (checkLinked) {
cached = this->checkLinkStatus(programID, errorHandler, nullptr, nullptr);
}
@@ -295,11 +301,20 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr
case kSKSL_Tag:
// SkSL cache hit, this should only happen in tools overriding the generated SkSL
- GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, &inputs, 1);
- for (int i = 0; i < kGrShaderTypeCount; ++i) {
- sksl[i] = &cached_sksl[i];
+ if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, &inputs, 1)) {
+ for (int i = 0; i < kGrShaderTypeCount; ++i) {
+ sksl[i] = &cached_sksl[i];
+ }
}
break;
+
+ default:
+ // We got something invalid, so pretend it wasn't there
+ reader.validate(false);
+ break;
+ }
+ if (!reader.isValid()) {
+ cached = false;
}
}
if (!usedProgramBinaries) {
@@ -376,7 +391,8 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr
}
SkString tessControlShader = primProc.getTessControlShaderGLSL(
- versionAndExtensionDecls.c_str(), *this->shaderCaps());
+ fGeometryProcessor.get(), versionAndExtensionDecls.c_str(), fUniformHandler,
+ *this->shaderCaps());
if (!this->compileAndAttachShaders(tessControlShader.c_str(), programID,
GR_GL_TESS_CONTROL_SHADER, &shadersToDelete,
errorHandler)) {
@@ -385,7 +401,8 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr
}
SkString tessEvaluationShader = primProc.getTessEvaluationShaderGLSL(
- versionAndExtensionDecls.c_str(), *this->shaderCaps());
+ fGeometryProcessor.get(), versionAndExtensionDecls.c_str(), fUniformHandler,
+ *this->shaderCaps());
if (!this->compileAndAttachShaders(tessEvaluationShader.c_str(), programID,
GR_GL_TESS_EVALUATION_SHADER, &shadersToDelete,
errorHandler)) {
@@ -534,27 +551,27 @@ void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID, boo
}
sk_sp<GrGLProgram> GrGLProgramBuilder::createProgram(GrGLuint programID) {
- return sk_sp<GrGLProgram>(new GrGLProgram(fGpu,
- fUniformHandles,
- programID,
- fUniformHandler.fUniforms,
- fUniformHandler.fSamplers,
- fVaryingHandler.fPathProcVaryingInfos,
- std::move(fGeometryProcessor),
- std::move(fXferProcessor),
- std::move(fFragmentProcessors),
- fFragmentProcessorCnt,
- std::move(fAttributes),
- fVertexAttributeCnt,
- fInstanceAttributeCnt,
- fVertexStride,
- fInstanceStride));
+ return GrGLProgram::Make(fGpu,
+ fUniformHandles,
+ programID,
+ fUniformHandler.fUniforms,
+ fUniformHandler.fSamplers,
+ fVaryingHandler.fPathProcVaryingInfos,
+ std::move(fGeometryProcessor),
+ std::move(fXferProcessor),
+ std::move(fFragmentProcessors),
+ fFragmentProcessorCnt,
+ std::move(fAttributes),
+ fVertexAttributeCnt,
+ fInstanceAttributeCnt,
+ fVertexStride,
+ fInstanceStride);
}
bool GrGLProgramBuilder::PrecompileProgram(GrGLPrecompiledProgram* precompiledProgram,
GrGLGpu* gpu,
const SkData& cachedData) {
- SkReader32 reader(cachedData.data(), cachedData.size());
+ SkReadBuffer reader(cachedData.data(), cachedData.size());
SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
if (shaderType != kSKSL_Tag) {
// TODO: Support GLSL, and maybe even program binaries, too?
@@ -563,13 +580,6 @@ bool GrGLProgramBuilder::PrecompileProgram(GrGLPrecompiledProgram* precompiledPr
const GrGLInterface* gl = gpu->glInterface();
auto errorHandler = gpu->getContext()->priv().getShaderErrorHandler();
- GrGLuint programID;
- GR_GL_CALL_RET(gl, programID, CreateProgram());
- if (0 == programID) {
- return false;
- }
-
- SkTDArray<GrGLuint> shadersToDelete;
SkSL::Program::Settings settings;
const GrGLCaps& caps = gpu->glCaps();
@@ -580,7 +590,17 @@ bool GrGLProgramBuilder::PrecompileProgram(GrGLPrecompiledProgram* precompiledPr
SkSL::String shaders[kGrShaderTypeCount];
SkSL::Program::Inputs inputs;
- GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders, &inputs, 1, &meta);
+ if (!GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders, &inputs, 1, &meta)) {
+ return false;
+ }
+
+ GrGLuint programID;
+ GR_GL_CALL_RET(gl, programID, CreateProgram());
+ if (0 == programID) {
+ return false;
+ }
+
+ SkTDArray<GrGLuint> shadersToDelete;
auto compileShader = [&](SkSL::Program::Kind kind, const SkSL::String& sksl, GrGLenum type) {
SkSL::String glsl;
diff --git a/chromium/third_party/skia/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/chromium/third_party/skia/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
index ad629d0bf59..68ba303dc33 100644
--- a/chromium/third_party/skia/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
+++ b/chromium/third_party/skia/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
@@ -88,9 +88,16 @@ SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords,
}
switch (matrix.fKind) {
case SkSL::SampleMatrix::Kind::kMixed:
- case SkSL::SampleMatrix::Kind::kVariable:
- result = SkStringPrintf("(_matrix * float3(%s, 1)).xy", result.c_str());
- break;
+ case SkSL::SampleMatrix::Kind::kVariable: {
+ SkString sampleCoords2D;
+ sampleCoords2D.printf("%s_sample", coords.c_str());
+ this->codeAppendf("\tfloat3 %s_3d = _matrix * %s.xy1;\n",
+ sampleCoords2D.c_str(), result.c_str());
+ this->codeAppendf("\tfloat2 %s = %s_3d.xy / %s_3d.z;\n",
+ sampleCoords2D.c_str(), sampleCoords2D.c_str(),
+ sampleCoords2D.c_str());
+ result = sampleCoords2D;
+ break; }
default:
break;
}
@@ -181,11 +188,15 @@ SkString GrGLSLFPFragmentBuilder::writeProcessorFunction(GrGLSLFragmentProcessor
const GrShaderVar& transform = args.fTransformedCoords[0].fTransform;
switch (transform.getType()) {
case kFloat4_GrSLType:
+ // This is a scale+translate, so there's no perspective division needed
this->codeAppendf("_coords = _coords * %s.xz + %s.yw;\n", transform.c_str(),
transform.c_str());
break;
case kFloat3x3_GrSLType:
- this->codeAppendf("_coords = (%s * float3(_coords, 1)).xy;\n", transform.c_str());
+ this->codeAppend("{\n");
+ this->codeAppendf("float3 _coords3 = (%s * _coords.xy1);\n", transform.c_str());
+ this->codeAppend("_coords = _coords3.xy / _coords3.z;\n");
+ this->codeAppend("}\n");
break;
default:
SkASSERT(transform.getType() == kVoid_GrSLType);
@@ -195,8 +206,12 @@ SkString GrGLSLFPFragmentBuilder::writeProcessorFunction(GrGLSLFragmentProcessor
SkASSERT(!hasVariableMatrix);
this->codeAppend("{\n");
args.fUniformHandler->writeUniformMappings(args.fFp.sampleMatrix().fOwner, this);
- this->codeAppendf("_coords = (%s * float3(_coords, 1)).xy;\n",
+ // FIXME This is not a variable matrix, we could key on the matrix type and skip
+ // perspective division; it may also be worth detecting if it was scale+translate and
+ // evaluating this similarly to the kFloat4 explicit coord case.
+ this->codeAppendf("float3 _coords3 = (%s * _coords.xy1);\n",
args.fFp.sampleMatrix().fExpression.c_str());
+ this->codeAppend("_coords = _coords3.xy / _coords3.z;\n");
this->codeAppend("}\n");
}
}
diff --git a/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.cpp b/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
index 3ef36d4f48c..4d2ee7e532c 100644
--- a/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
+++ b/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
@@ -14,10 +14,19 @@
#include "src/gpu/glsl/GrGLSLVarying.h"
#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
+#include <unordered_map>
+
void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) {
GrGPArgs gpArgs;
this->onEmitCode(args, &gpArgs);
+ // FIXME This must always be called at the moment, even when fLocalCoordVar is uninitialized
+ // and void because collectTransforms registers the uniforms for legacy coord transforms, which
+ // still need to be added even if the FPs are sampled explicitly. When they are gone, we only
+ // need to call this if the local coord isn't void (plus verify that FPs really don't need it).
+ this->collectTransforms(args.fVertBuilder, args.fVaryingHandler, args.fUniformHandler,
+ gpArgs.fLocalCoordVar, args.fFPCoordTransformHandler);
+
if (args.fGP.willUseTessellationShaders()) {
// Tessellation shaders are temporarily responsible for integrating their own code strings
// while we work out full support.
@@ -42,11 +51,14 @@ void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) {
vBuilder->codeAppendf("sk_Position = float4(%s", gpArgs.fPositionVar.c_str());
switch (gpArgs.fPositionVar.getType()) {
case kFloat_GrSLType:
- vBuilder->codeAppend(", 0"); // fallthru.
+ vBuilder->codeAppend(", 0");
+ [[fallthrough]];
case kFloat2_GrSLType:
- vBuilder->codeAppend(", 0"); // fallthru.
+ vBuilder->codeAppend(", 0");
+ [[fallthrough]];
case kFloat3_GrSLType:
- vBuilder->codeAppend(", 1"); // fallthru.
+ vBuilder->codeAppend(", 1");
+ [[fallthrough]];
case kFloat4_GrSLType:
vBuilder->codeAppend(");");
break;
@@ -57,12 +69,11 @@ void GrGLSLGeometryProcessor::emitCode(EmitArgs& args) {
}
}
-void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
- GrGLSLVaryingHandler* varyingHandler,
- GrGLSLUniformHandler* uniformHandler,
- const GrShaderVar& localCoordsVar,
- const SkMatrix& localMatrix,
- FPCoordTransformHandler* handler) {
+void GrGLSLGeometryProcessor::collectTransforms(GrGLSLVertexBuilder* vb,
+ GrGLSLVaryingHandler* varyingHandler,
+ GrGLSLUniformHandler* uniformHandler,
+ const GrShaderVar& localCoordsVar,
+ FPCoordTransformHandler* handler) {
// We only require localCoordsVar to be valid if there is a coord transform that needs
// it. CTs on FPs called with explicit coords do not require a local coord.
auto getLocalCoords = [&localCoordsVar,
@@ -115,8 +126,7 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
if (!fp.isSampledWithExplicitCoords()) {
auto [localCoordsStr, localCoordLength] = getLocalCoords();
GrGLSLVarying v(kFloat2_GrSLType);
- if (localMatrix.hasPerspective() || coordTransform.matrix().hasPerspective() ||
- localCoordLength == 3) {
+ if (coordTransform.matrix().hasPerspective() || localCoordLength == 3) {
v = GrGLSLVarying(kFloat3_GrSLType);
}
SkString strVaryingName;
@@ -142,41 +152,49 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
void GrGLSLGeometryProcessor::emitTransformCode(GrGLSLVertexBuilder* vb,
GrGLSLUniformHandler* uniformHandler) {
+ std::unordered_map<const GrFragmentProcessor*, const char*> localCoordsMap;
for (const auto& tr : fTransformInfos) {
switch (tr.fFP->sampleMatrix().fKind) {
- case SkSL::SampleMatrix::Kind::kConstantOrUniform:
+ case SkSL::SampleMatrix::Kind::kConstantOrUniform: {
+ SkString localCoords;
+ localCoordsMap.insert({ tr.fFP, tr.fName });
+ if (tr.fFP->sampleMatrix().fBase) {
+ SkASSERT(localCoordsMap[tr.fFP->sampleMatrix().fBase]);
+ localCoords = SkStringPrintf("float3(%s, 1)",
+ localCoordsMap[tr.fFP->sampleMatrix().fBase]);
+ } else {
+ localCoords = tr.fLocalCoords.c_str();
+ }
vb->codeAppend("{\n");
- uniformHandler->writeUniformMappings(tr.fFP->sampleMatrix().fOwner, vb);
+ if (tr.fFP->sampleMatrix().fOwner) {
+ uniformHandler->writeUniformMappings(tr.fFP->sampleMatrix().fOwner, vb);
+ }
if (tr.fType == kFloat2_GrSLType) {
vb->codeAppendf("%s = (%s * %s * %s).xy", tr.fName,
tr.fFP->sampleMatrix().fExpression.c_str(), tr.fMatrix.c_str(),
- tr.fLocalCoords.c_str());
+ localCoords.c_str());
} else {
SkASSERT(tr.fType == kFloat3_GrSLType);
vb->codeAppendf("%s = %s * %s * %s", tr.fName,
tr.fFP->sampleMatrix().fExpression.c_str(), tr.fMatrix.c_str(),
- tr.fLocalCoords.c_str());
+ localCoords.c_str());
}
vb->codeAppend(";\n");
vb->codeAppend("}\n");
+ break;
+ }
default:
break;
}
}
}
-void GrGLSLGeometryProcessor::setTransformDataHelper(const SkMatrix& localMatrix,
- const GrGLSLProgramDataManager& pdman,
+void GrGLSLGeometryProcessor::setTransformDataHelper(const GrGLSLProgramDataManager& pdman,
const CoordTransformRange& transformRange) {
int i = 0;
for (auto [transform, fp] : transformRange) {
if (fInstalledTransforms[i].fHandle.isValid()) {
- SkMatrix m;
- if (fp.isSampledWithExplicitCoords()) {
- m = GetTransformMatrix(transform, SkMatrix::I());
- } else {
- m = GetTransformMatrix(transform, localMatrix);
- }
+ SkMatrix m = GetTransformMatrix(transform, SkMatrix::I());
if (!SkMatrixPriv::CheapEqual(fInstalledTransforms[i].fCurrentValue, m)) {
if (fInstalledTransforms[i].fType == kFloat4_GrSLType) {
float values[4] = {m.getScaleX(), m.getTranslateX(),
@@ -196,11 +214,94 @@ void GrGLSLGeometryProcessor::setTransformDataHelper(const SkMatrix& localMatrix
SkASSERT(i == fInstalledTransforms.count());
}
+void GrGLSLGeometryProcessor::setTransform(const GrGLSLProgramDataManager& pdman,
+ const UniformHandle& uniform,
+ const SkMatrix& matrix,
+ SkMatrix* state) const {
+ if (!uniform.isValid() || (state && SkMatrixPriv::CheapEqual(*state, matrix))) {
+ // No update needed
+ return;
+ }
+ if (state) {
+ *state = matrix;
+ }
+ if (matrix.isScaleTranslate()) {
+ // ComputeMatrixKey and writeX() assume the uniform is a float4 (can't assert since nothing
+ // is exposed on a handle, but should be caught lower down).
+ float values[4] = {matrix.getScaleX(), matrix.getTranslateX(),
+ matrix.getScaleY(), matrix.getTranslateY()};
+ pdman.set4fv(uniform, 1, values);
+ } else {
+ pdman.setSkMatrix(uniform, matrix);
+ }
+}
+
+static void write_vertex_position(GrGLSLVertexBuilder* vertBuilder,
+ GrGLSLUniformHandler* uniformHandler,
+ const GrShaderVar& inPos,
+ const SkMatrix& matrix,
+ const char* matrixName,
+ GrShaderVar* outPos,
+ GrGLSLGeometryProcessor::UniformHandle* matrixUniform) {
+ SkASSERT(inPos.getType() == kFloat3_GrSLType || inPos.getType() == kFloat2_GrSLType);
+ SkString outName = vertBuilder->newTmpVarName(inPos.getName().c_str());
+
+ if (matrix.isIdentity()) {
+ // Direct assignment, we won't use a uniform for the matrix.
+ outPos->set(inPos.getType(), outName.c_str());
+ vertBuilder->codeAppendf("float%d %s = %s;", GrSLTypeVecLength(inPos.getType()),
+ outName.c_str(), inPos.getName().c_str());
+ } else {
+ SkASSERT(matrixUniform);
+
+ bool useCompactTransform = matrix.isScaleTranslate();
+ const char* mangledMatrixName;
+ *matrixUniform = uniformHandler->addUniform(nullptr,
+ kVertex_GrShaderFlag,
+ useCompactTransform ? kFloat4_GrSLType
+ : kFloat3x3_GrSLType,
+ matrixName,
+ &mangledMatrixName);
+
+ if (inPos.getType() == kFloat3_GrSLType) {
+ // A float3 stays a float3 whether or not the matrix adds perspective
+ if (useCompactTransform) {
+ vertBuilder->codeAppendf("float3 %s = %s.xz1 * %s + %s.yw0;\n",
+ outName.c_str(), mangledMatrixName,
+ inPos.getName().c_str(), mangledMatrixName);
+ } else {
+ vertBuilder->codeAppendf("float3 %s = %s * %s;\n", outName.c_str(),
+ mangledMatrixName, inPos.getName().c_str());
+ }
+ outPos->set(kFloat3_GrSLType, outName.c_str());
+ } else if (matrix.hasPerspective()) {
+ // A float2 is promoted to a float3 if we add perspective via the matrix
+ SkASSERT(!useCompactTransform);
+ vertBuilder->codeAppendf("float3 %s = (%s * %s.xy1);",
+ outName.c_str(), mangledMatrixName, inPos.getName().c_str());
+ outPos->set(kFloat3_GrSLType, outName.c_str());
+ } else {
+ if (useCompactTransform) {
+ vertBuilder->codeAppendf("float2 %s = %s.xz * %s + %s.yw;\n",
+ outName.c_str(), mangledMatrixName,
+ inPos.getName().c_str(), mangledMatrixName);
+ } else {
+ vertBuilder->codeAppendf("float2 %s = (%s * %s.xy1).xy;\n",
+ outName.c_str(), mangledMatrixName,
+ inPos.getName().c_str());
+ }
+ outPos->set(kFloat2_GrSLType, outName.c_str());
+ }
+ }
+}
+
void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
GrGPArgs* gpArgs,
const char* posName) {
- gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos2");
- vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
+ // writeOutputPosition assumes the incoming pos name points to a float2 variable
+ GrShaderVar inPos(posName, kFloat2_GrSLType);
+ write_vertex_position(vertBuilder, nullptr, inPos, SkMatrix::I(), "viewMatrix",
+ &gpArgs->fPositionVar, nullptr);
}
void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
@@ -209,24 +310,17 @@ void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuild
const char* posName,
const SkMatrix& mat,
UniformHandle* viewMatrixUniform) {
- if (mat.isIdentity()) {
- gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos2");
- vertBuilder->codeAppendf("float2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
- } else {
- const char* viewMatrixName;
- *viewMatrixUniform = uniformHandler->addUniform(nullptr,
- kVertex_GrShaderFlag,
- kFloat3x3_GrSLType,
- "uViewM",
- &viewMatrixName);
- if (!mat.hasPerspective()) {
- gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos2");
- vertBuilder->codeAppendf("float2 %s = (%s * float3(%s, 1)).xy;",
- gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
- } else {
- gpArgs->fPositionVar.set(kFloat3_GrSLType, "pos3");
- vertBuilder->codeAppendf("float3 %s = %s * float3(%s, 1);",
- gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
- }
- }
+ GrShaderVar inPos(posName, kFloat2_GrSLType);
+ write_vertex_position(vertBuilder, uniformHandler, inPos, mat, "viewMatrix",
+ &gpArgs->fPositionVar, viewMatrixUniform);
+}
+
+void GrGLSLGeometryProcessor::writeLocalCoord(GrGLSLVertexBuilder* vertBuilder,
+ GrGLSLUniformHandler* uniformHandler,
+ GrGPArgs* gpArgs,
+ GrShaderVar localVar,
+ const SkMatrix& localMatrix,
+ UniformHandle* localMatrixUniform) {
+ write_vertex_position(vertBuilder, uniformHandler, localVar, localMatrix, "localMatrix",
+ &gpArgs->fLocalCoordVar, localMatrixUniform);
}
diff --git a/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.h b/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.h
index f23bd0e800d..10e21376750 100644
--- a/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.h
+++ b/chromium/third_party/skia/src/gpu/glsl/GrGLSLGeometryProcessor.h
@@ -22,41 +22,33 @@ public:
/* Any general emit code goes in the base class emitCode. Subclasses override onEmitCode */
void emitCode(EmitArgs&) final;
+ // Generate the final code for assigning transformed coordinates to the varyings recorded in
+ // the call to collectTransforms(). This must happen after FP code emission so that it has
+ // access to any uniforms the FPs registered for const/uniform sample matrix invocations.
+ void emitTransformCode(GrGLSLVertexBuilder* vb,
+ GrGLSLUniformHandler* uniformHandler) override;
+
protected:
// A helper which subclasses can use to upload coord transform matrices in setData().
- void setTransformDataHelper(const SkMatrix& localMatrix,
- const GrGLSLProgramDataManager& pdman,
+ void setTransformDataHelper(const GrGLSLProgramDataManager& pdman,
const CoordTransformRange&);
- // Emit transformed local coords from the vertex shader as a uniform matrix and varying per
- // coord-transform. localCoordsVar must be a 2- or 3-component vector. If it is 3 then it is
- // assumed to be a 2D homogeneous coordinate.
- void emitTransforms(GrGLSLVertexBuilder*,
- GrGLSLVaryingHandler*,
- GrGLSLUniformHandler*,
- const GrShaderVar& localCoordsVar,
- const SkMatrix& localMatrix,
- FPCoordTransformHandler*);
-
- // Version of above that assumes identity for the local matrix.
- void emitTransforms(GrGLSLVertexBuilder* vb,
- GrGLSLVaryingHandler* varyingHandler,
- GrGLSLUniformHandler* uniformHandler,
- const GrShaderVar& localCoordsVar,
- FPCoordTransformHandler* handler) {
- this->emitTransforms(vb, varyingHandler, uniformHandler, localCoordsVar, SkMatrix::I(),
- handler);
- }
-
- // TODO: doc
- void emitTransformCode(GrGLSLVertexBuilder* vb,
- GrGLSLUniformHandler* uniformHandler) override;
+ // A helper for setting the matrix on a uniform handle initialized through
+ // writeOutputPosition or writeLocalCoord. Automatically handles elided uniforms,
+ // scale+translate matrices, and state tracking (if provided state pointer is non-null).
+ void setTransform(const GrGLSLProgramDataManager& pdman, const UniformHandle& uniform,
+ const SkMatrix& matrix, SkMatrix* state=nullptr) const;
struct GrGPArgs {
// Used to specify the output variable used by the GP to store its device position. It can
// either be a float2 or a float3 (in order to handle perspective). The subclass sets this
// in its onEmitCode().
GrShaderVar fPositionVar;
+ // Used to specify the variable storing the draw's local coordinates. It can be either a
+ // float2, float3, or void. It can only be void when no FP needs local coordinates. This
+ // variable can be an attribute or local variable, but should not itself be a varying.
+ // GrGLSLGeometryProcessor automatically determines if this must be passed to a FS.
+ GrShaderVar fLocalCoordVar;
};
// Helpers for adding code to write the transformed vertex position. The first simple version
@@ -73,19 +65,54 @@ protected:
const SkMatrix& mat,
UniformHandle* viewMatrixUniform);
- static uint32_t ComputePosKey(const SkMatrix& mat) {
+ // Helper to transform an existing variable by a given local matrix (e.g. the inverse view
+ // matrix). It will declare the transformed local coord variable and will set
+ // GrGPArgs::fLocalCoordVar.
+ void writeLocalCoord(GrGLSLVertexBuilder*, GrGLSLUniformHandler*, GrGPArgs*,
+ GrShaderVar localVar, const SkMatrix& localMatrix,
+ UniformHandle* localMatrixUniform);
+
+ // GPs that use writeOutputPosition and/or writeLocalCoord must incorporate the matrix type
+ // into their key, and should use this function or one of the other related helpers.
+ static uint32_t ComputeMatrixKey(const SkMatrix& mat) {
if (mat.isIdentity()) {
- return 0x0;
+ return 0b00;
+ } else if (mat.isScaleTranslate()) {
+ return 0b01;
} else if (!mat.hasPerspective()) {
- return 0x01;
+ return 0b10;
} else {
- return 0x02;
+ return 0b11;
}
}
+ static uint32_t ComputeMatrixKeys(const SkMatrix& viewMatrix, const SkMatrix& localMatrix) {
+ return (ComputeMatrixKey(viewMatrix) << kMatrixKeyBits) | ComputeMatrixKey(localMatrix);
+ }
+ static uint32_t AddMatrixKeys(uint32_t flags, const SkMatrix& viewMatrix,
+ const SkMatrix& localMatrix) {
+ // Shifting to make room for the matrix keys shouldn't lose bits
+ SkASSERT(((flags << (2 * kMatrixKeyBits)) >> (2 * kMatrixKeyBits)) == flags);
+ return (flags << (2 * kMatrixKeyBits)) | ComputeMatrixKeys(viewMatrix, localMatrix);
+ }
+ static constexpr int kMatrixKeyBits = 2;
private:
virtual void onEmitCode(EmitArgs&, GrGPArgs*) = 0;
+ // Iterates over the FPs in 'handler' to register additional varyings and uniforms to support
+ // VS-promoted local coord evaluation for the FPs. Subclasses must call this with
+ // 'localCoordsVar' set to an SkSL variable expression of type 'float2' or 'float3' representing
+ // the original local coordinates of the draw.
+ //
+ // This must happen before FP code emission so that the FPs can find the appropriate varying
+ // handles they use in place of explicit coord sampling; it is automatically called after
+ // onEmitCode() returns using the value stored in GpArgs::fLocalCoordVar.
+ void collectTransforms(GrGLSLVertexBuilder* vb,
+ GrGLSLVaryingHandler* varyingHandler,
+ GrGLSLUniformHandler* uniformHandler,
+ const GrShaderVar& localCoordsVar,
+ FPCoordTransformHandler* handler);
+
struct TransformUniform {
UniformHandle fHandle;
GrSLType fType = kVoid_GrSLType;
diff --git a/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.cpp b/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.cpp
index 95f97feb695..e5a9c1448ff 100644
--- a/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.cpp
+++ b/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.cpp
@@ -20,7 +20,8 @@ GrGLSLShaderBuilder::GrGLSLShaderBuilder(GrGLSLProgramBuilder* program)
, fOutputs(GrGLSLProgramBuilder::kVarsPerBlock)
, fFeaturesAddedMask(0)
, fCodeIndex(kCode)
- , fFinalized(false) {
+ , fFinalized(false)
+ , fTmpVariableCounter(0) {
// We push back some dummy pointers which will later become our header
for (int i = 0; i <= kCode; i++) {
fShaderStrings.push_back();
@@ -198,9 +199,7 @@ void GrGLSLShaderBuilder::appendColorGamutXform(SkString* out,
GrShaderVar("color", useFloat ? kFloat4_GrSLType : kHalf4_GrSLType)};
SkString body;
if (colorXformHelper->applyUnpremul()) {
- body.appendf("%s nonZeroAlpha = max(color.a, 0.0001);", useFloat ? "float" : "half");
- body.appendf("color = %s(color.rgb / nonZeroAlpha, nonZeroAlpha);",
- useFloat ? "float4" : "half4");
+ body.appendf("color = unpremul%s(color);", useFloat ? "_float" : "");
}
if (colorXformHelper->applySrcTF()) {
body.appendf("color.r = %s(half(color.r));", srcTFFuncName.c_str());
diff --git a/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.h b/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.h
index b69abe89442..b766280d23a 100644
--- a/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.h
+++ b/chromium/third_party/skia/src/gpu/glsl/GrGLSLShaderBuilder.h
@@ -84,6 +84,13 @@ public:
void declareGlobal(const GrShaderVar&);
+ // Generates a unique variable name for holding the result of a temporary expression when it's
+ // not reasonable to just add a new block for scoping. Does not declare anything.
+ SkString newTmpVarName(const char* suffix) {
+ int tmpIdx = fTmpVariableCounter++;
+ return SkStringPrintf("_tmp_%d_%s", tmpIdx, suffix);
+ }
+
/**
* Called by GrGLSLProcessors to add code to one of the shaders.
*/
@@ -238,6 +245,9 @@ protected:
int fCodeIndex;
bool fFinalized;
+ // Counter for generating unique scratch variable names in a shader.
+ int fTmpVariableCounter;
+
friend class GrCCCoverageProcessor; // to access code().
friend class GrGLSLProgramBuilder;
friend class GrGLProgramBuilder;
diff --git a/chromium/third_party/skia/src/gpu/gradients/GrGradientShader.cpp b/chromium/third_party/skia/src/gpu/gradients/GrGradientShader.cpp
index 59624f2bb7f..8981955a38e 100644
--- a/chromium/third_party/skia/src/gpu/gradients/GrGradientShader.cpp
+++ b/chromium/third_party/skia/src/gpu/gradients/GrGradientShader.cpp
@@ -27,6 +27,7 @@
#include "src/gpu/GrColorInfo.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/SkGr.h"
+#include "src/gpu/effects/GrTextureEffect.h"
// Intervals smaller than this (that aren't hard stops) on low-precision-only devices force us to
// use the textured gradient
@@ -64,8 +65,11 @@ static std::unique_ptr<GrFragmentProcessor> make_textured_colorizer(const SkPMCo
SkDebugf("Gradient won't draw. Could not create texture.");
return nullptr;
}
-
- return GrTextureGradientColorizer::Make(std::move(view));
+ // TODO: When we start sampling colorizers with explicit coords rather than using sk_InColor
+ // the GrTextureEffect can simply be the colorizer.
+ auto m = SkMatrix::Scale(view.width(), 1.f);
+ auto te = GrTextureEffect::Make(std::move(view), alphaType, m, GrSamplerState::Filter::kBilerp);
+ return GrTextureGradientColorizer::Make(std::move(te));
}
// Analyze the shader's color stops and positions and chooses an appropriate colorizer to represent
diff --git a/chromium/third_party/skia/src/gpu/gradients/GrTextureGradientColorizer.fp b/chromium/third_party/skia/src/gpu/gradients/GrTextureGradientColorizer.fp
index c2146459f3e..b8dba025808 100644
--- a/chromium/third_party/skia/src/gpu/gradients/GrTextureGradientColorizer.fp
+++ b/chromium/third_party/skia/src/gpu/gradients/GrTextureGradientColorizer.fp
@@ -6,13 +6,9 @@
*/
// Should have height = 1px, horizontal axis represents t = 0 to 1
-in uniform sampler2D gradient;
-
-@samplerParams(gradient) {
- GrSamplerState::Filter::kBilerp
-}
+in fragmentProcessor textureFP;
void main() {
half2 coord = half2(sk_InColor.x, 0.5);
- sk_OutColor = sample(gradient, coord);
+ sk_OutColor = sample(textureFP, coord);
}
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.cpp
index 044165365d9..7e309c35b7e 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.cpp
@@ -38,8 +38,14 @@ public:
SkString _sample1099;
_sample1099 = this->invokeChild(_outer.gradLayout_index, args);
fragBuilder->codeAppendf(
- "half4 t = %s;\nif (!%s && t.y < 0.0) {\n %s = half4(0.0);\n} else if (t.x < "
- "0.0) {\n %s = %s;\n} else if (t.x > 1.0) {\n %s = %s;\n} else {",
+ R"SkSL(half4 t = %s;
+if (!%s && t.y < 0.0) {
+ %s = half4(0.0);
+} else if (t.x < 0.0) {
+ %s = %s;
+} else if (t.x > 1.0) {
+ %s = %s;
+} else {)SkSL",
_sample1099.c_str(),
(_outer.childProcessor(_outer.gradLayout_index).preservesOpaqueInput() ? "true"
: "false"),
@@ -49,10 +55,16 @@ public:
SkString _input1767("t");
SkString _sample1767;
_sample1767 = this->invokeChild(_outer.colorizer_index, _input1767.c_str(), args);
- fragBuilder->codeAppendf("\n %s = %s;\n}\n@if (%s) {\n %s.xyz *= %s.w;\n}\n",
- args.fOutputColor, _sample1767.c_str(),
- (_outer.makePremul ? "true" : "false"), args.fOutputColor,
- args.fOutputColor);
+ fragBuilder->codeAppendf(
+ R"SkSL(
+ %s = %s;
+}
+@if (%s) {
+ %s.xyz *= %s.w;
+}
+)SkSL",
+ args.fOutputColor, _sample1767.c_str(), (_outer.makePremul ? "true" : "false"),
+ args.fOutputColor, args.fOutputColor);
}
private:
@@ -95,25 +107,17 @@ bool GrClampedGradientEffect::onIsEqual(const GrFragmentProcessor& other) const
}
GrClampedGradientEffect::GrClampedGradientEffect(const GrClampedGradientEffect& src)
: INHERITED(kGrClampedGradientEffect_ClassID, src.optimizationFlags())
- , colorizer_index(src.colorizer_index)
- , gradLayout_index(src.gradLayout_index)
, leftBorderColor(src.leftBorderColor)
, rightBorderColor(src.rightBorderColor)
, makePremul(src.makePremul)
, colorsAreOpaque(src.colorsAreOpaque) {
{
- auto clone = src.childProcessor(colorizer_index).clone();
- if (src.childProcessor(colorizer_index).isSampledWithExplicitCoords()) {
- clone->setSampledWithExplicitCoords();
- }
- this->registerChildProcessor(std::move(clone));
+ colorizer_index =
+ this->cloneAndRegisterChildProcessor(src.childProcessor(src.colorizer_index));
}
{
- auto clone = src.childProcessor(gradLayout_index).clone();
- if (src.childProcessor(gradLayout_index).isSampledWithExplicitCoords()) {
- clone->setSampledWithExplicitCoords();
- }
- this->registerChildProcessor(std::move(clone));
+ gradLayout_index =
+ this->cloneAndRegisterChildProcessor(src.childProcessor(src.gradLayout_index));
}
}
std::unique_ptr<GrFragmentProcessor> GrClampedGradientEffect::clone() const {
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.h
index 4779cdbb61f..eee25ff2726 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.h
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrClampedGradientEffect.h
@@ -10,11 +10,13 @@
**************************************************************************************************/
#ifndef GrClampedGradientEffect_DEFINED
#define GrClampedGradientEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrClampedGradientEffect : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(
@@ -55,11 +57,9 @@ private:
, makePremul(makePremul)
, colorsAreOpaque(colorsAreOpaque) {
SkASSERT(colorizer);
- colorizer_index = this->numChildProcessors();
- this->registerChildProcessor(std::move(colorizer));
+ colorizer_index = this->registerChild(std::move(colorizer));
SkASSERT(gradLayout);
- gradLayout_index = this->numChildProcessors();
- this->registerChildProcessor(std::move(gradLayout));
+ gradLayout_index = this->registerChild(std::move(gradLayout));
}
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.cpp
index 88b50df48f0..323fec5e1bb 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.cpp
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.cpp
@@ -45,9 +45,17 @@ public:
thresholdVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
kHalf_GrSLType, "threshold");
fragBuilder->codeAppendf(
- "half t = %s.x;\nfloat4 scale, bias;\nif (t < %s) {\n scale = %s;\n bias = "
- "%s;\n} else {\n scale = %s;\n bias = %s;\n}\n%s = half4(float(t) * scale + "
- "bias);\n",
+ R"SkSL(half t = %s.x;
+float4 scale, bias;
+if (t < %s) {
+ scale = %s;
+ bias = %s;
+} else {
+ scale = %s;
+ bias = %s;
+}
+%s = half4(float(t) * scale + bias);
+)SkSL",
args.fInputColor, args.fUniformHandler->getUniformCStr(thresholdVar),
args.fUniformHandler->getUniformCStr(scale01Var),
args.fUniformHandler->getUniformCStr(bias01Var),
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.h
index d8ebc1ef29b..58a97a3128a 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.h
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.h
@@ -10,11 +10,13 @@
**************************************************************************************************/
#ifndef GrDualIntervalGradientColorizer_DEFINED
#define GrDualIntervalGradientColorizer_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrDualIntervalGradientColorizer : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(const SkPMColor4f& c0,
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.cpp
index 2d28b92df08..5bc1732a773 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.cpp
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.cpp
@@ -28,7 +28,9 @@ public:
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(
args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix());
fragBuilder->codeAppendf(
- "half t = half(%s.x) + 9.9999997473787516e-06;\n%s = half4(t, 1.0, 0.0, 0.0);\n",
+ R"SkSL(half t = half(%s.x) + 9.9999997473787516e-06;
+%s = half4(t, 1.0, 0.0, 0.0);
+)SkSL",
sk_TransformedCoords2D_0.c_str(), args.fOutputColor);
}
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.h
index 6ecbeee850c..5c3323d2759 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.h
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrLinearGradientLayout.h
@@ -10,14 +10,16 @@
**************************************************************************************************/
#ifndef GrLinearGradientLayout_DEFINED
#define GrLinearGradientLayout_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/gradients/GrGradientShader.h"
#include "src/shaders/gradients/SkLinearGradient.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrLinearGradientLayout : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(const SkLinearGradient& gradient,
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.cpp
index ecf6e742233..c17f77a3c48 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.cpp
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.cpp
@@ -27,8 +27,11 @@ public:
(void)gradientMatrix;
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(
args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix());
- fragBuilder->codeAppendf("half t = half(length(%s));\n%s = half4(t, 1.0, 0.0, 0.0);\n",
- sk_TransformedCoords2D_0.c_str(), args.fOutputColor);
+ fragBuilder->codeAppendf(
+ R"SkSL(half t = half(length(%s));
+%s = half4(t, 1.0, 0.0, 0.0);
+)SkSL",
+ sk_TransformedCoords2D_0.c_str(), args.fOutputColor);
}
private:
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.h
index 44be21202e4..897a97f02d2 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.h
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrRadialGradientLayout.h
@@ -10,14 +10,16 @@
**************************************************************************************************/
#ifndef GrRadialGradientLayout_DEFINED
#define GrRadialGradientLayout_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/gradients/GrGradientShader.h"
#include "src/shaders/gradients/SkRadialGradient.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrRadialGradientLayout : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(const SkRadialGradient& gradient,
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.cpp
index cc4c82289d0..4a524a11f96 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.cpp
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.cpp
@@ -32,10 +32,12 @@ public:
kHalf4_GrSLType, "start");
endVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf4_GrSLType,
"end");
- fragBuilder->codeAppendf("half t = %s.x;\n%s = (1.0 - t) * %s + t * %s;\n",
- args.fInputColor, args.fOutputColor,
- args.fUniformHandler->getUniformCStr(startVar),
- args.fUniformHandler->getUniformCStr(endVar));
+ fragBuilder->codeAppendf(
+ R"SkSL(half t = %s.x;
+%s = (1.0 - t) * %s + t * %s;
+)SkSL",
+ args.fInputColor, args.fOutputColor, args.fUniformHandler->getUniformCStr(startVar),
+ args.fUniformHandler->getUniformCStr(endVar));
}
private:
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.h
index 2c808102c9d..a8cd30feea1 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.h
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.h
@@ -10,11 +10,13 @@
**************************************************************************************************/
#ifndef GrSingleIntervalGradientColorizer_DEFINED
#define GrSingleIntervalGradientColorizer_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrSingleIntervalGradientColorizer : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(SkPMColor4f start, SkPMColor4f end) {
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.cpp
index cd4653a75ea..0776671193d 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.cpp
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.cpp
@@ -36,10 +36,15 @@ public:
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(
args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix());
fragBuilder->codeAppendf(
- "half angle;\nif (sk_Caps.atan2ImplementedAsAtanYOverX) {\n angle = half(2.0 * "
- "atan(-%s.y, length(%s) - %s.x));\n} else {\n angle = half(atan(-%s.y, "
- "-%s.x));\n}\nhalf t = ((angle * 0.15915493667125702 + 0.5) + %s) * %s;\n%s = "
- "half4(t, 1.0, 0.0, 0.0);\n",
+ R"SkSL(half angle;
+if (sk_Caps.atan2ImplementedAsAtanYOverX) {
+ angle = half(2.0 * atan(-%s.y, length(%s) - %s.x));
+} else {
+ angle = half(atan(-%s.y, -%s.x));
+}
+half t = ((angle * 0.15915493667125702 + 0.5) + %s) * %s;
+%s = half4(t, 1.0, 0.0, 0.0);
+)SkSL",
sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str(),
sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str(),
sk_TransformedCoords2D_0.c_str(), args.fUniformHandler->getUniformCStr(biasVar),
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.h
index ef7a2ea4918..b547ec1db98 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.h
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrSweepGradientLayout.h
@@ -10,14 +10,16 @@
**************************************************************************************************/
#ifndef GrSweepGradientLayout_DEFINED
#define GrSweepGradientLayout_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/gradients/GrGradientShader.h"
#include "src/shaders/gradients/SkSweepGradient.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrSweepGradientLayout : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(const SkSweepGradient& gradient,
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.cpp
index f2b079145de..c2f05339732 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.cpp
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.cpp
@@ -24,13 +24,15 @@ public:
const GrTextureGradientColorizer& _outer = args.fFp.cast<GrTextureGradientColorizer>();
(void)_outer;
fragBuilder->codeAppendf(
- "half2 coord = half2(%s.x, 0.5);\n%s = sample(%s, float2(coord)).%s;\n",
- args.fInputColor, args.fOutputColor,
- fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]),
- fragBuilder->getProgramBuilder()
- ->samplerSwizzle(args.fTexSamplers[0])
- .asString()
- .c_str());
+ R"SkSL(half2 coord = half2(%s.x, 0.5);)SkSL", args.fInputColor);
+ SkString _sample327;
+ SkString _coords327("float2(coord)");
+ _sample327 = this->invokeChild(_outer.textureFP_index, args, _coords327.c_str());
+ fragBuilder->codeAppendf(
+ R"SkSL(
+%s = %s;
+)SkSL",
+ args.fOutputColor, _sample327.c_str());
}
private:
@@ -45,18 +47,15 @@ void GrTextureGradientColorizer::onGetGLSLProcessorKey(const GrShaderCaps& caps,
bool GrTextureGradientColorizer::onIsEqual(const GrFragmentProcessor& other) const {
const GrTextureGradientColorizer& that = other.cast<GrTextureGradientColorizer>();
(void)that;
- if (gradient != that.gradient) return false;
return true;
}
GrTextureGradientColorizer::GrTextureGradientColorizer(const GrTextureGradientColorizer& src)
- : INHERITED(kGrTextureGradientColorizer_ClassID, src.optimizationFlags())
- , gradient(src.gradient) {
- this->setTextureSamplerCnt(1);
+ : INHERITED(kGrTextureGradientColorizer_ClassID, src.optimizationFlags()) {
+ {
+ textureFP_index =
+ this->cloneAndRegisterChildProcessor(src.childProcessor(src.textureFP_index));
+ }
}
std::unique_ptr<GrFragmentProcessor> GrTextureGradientColorizer::clone() const {
return std::unique_ptr<GrFragmentProcessor>(new GrTextureGradientColorizer(*this));
}
-const GrFragmentProcessor::TextureSampler& GrTextureGradientColorizer::onTextureSampler(
- int index) const {
- return IthTextureSampler(index, gradient);
-}
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.h
index 0672b9fdf0d..b49637ac8f4 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.h
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrTextureGradientColorizer.h
@@ -10,32 +10,34 @@
**************************************************************************************************/
#ifndef GrTextureGradientColorizer_DEFINED
#define GrTextureGradientColorizer_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrTextureGradientColorizer : public GrFragmentProcessor {
public:
- static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView gradient) {
+ static std::unique_ptr<GrFragmentProcessor> Make(
+ std::unique_ptr<GrFragmentProcessor> textureFP) {
return std::unique_ptr<GrFragmentProcessor>(
- new GrTextureGradientColorizer(std::move(gradient)));
+ new GrTextureGradientColorizer(std::move(textureFP)));
}
GrTextureGradientColorizer(const GrTextureGradientColorizer& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "TextureGradientColorizer"; }
- TextureSampler gradient;
+ int textureFP_index = -1;
private:
- GrTextureGradientColorizer(GrSurfaceProxyView gradient)
- : INHERITED(kGrTextureGradientColorizer_ClassID, kNone_OptimizationFlags)
- , gradient(std::move(gradient), GrSamplerState::Filter::kBilerp) {
- this->setTextureSamplerCnt(1);
+ GrTextureGradientColorizer(std::unique_ptr<GrFragmentProcessor> textureFP)
+ : INHERITED(kGrTextureGradientColorizer_ClassID, kNone_OptimizationFlags) {
+ SkASSERT(textureFP);
+ textureFP_index = this->registerExplicitlySampledChild(std::move(textureFP));
}
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
- const TextureSampler& onTextureSampler(int) const override;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
typedef GrFragmentProcessor INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.cpp
index 248e7f9303d..3d9dc96d92c 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.cpp
@@ -32,11 +32,20 @@ public:
SkString _sample453;
_sample453 = this->invokeChild(_outer.gradLayout_index, args);
fragBuilder->codeAppendf(
- "half4 t = %s;\nif (!%s && t.y < 0.0) {\n %s = half4(0.0);\n} else {\n @if "
- "(%s) {\n half t_1 = t.x - 1.0;\n half tiled_t = (t_1 - 2.0 * "
- "floor(t_1 * 0.5)) - 1.0;\n if (sk_Caps.mustDoOpBetweenFloorAndAbs) {\n "
- " tiled_t = clamp(tiled_t, -1.0, 1.0);\n }\n t.x = "
- "abs(tiled_t);\n } else {\n t.x = fract(t.x);\n }",
+ R"SkSL(half4 t = %s;
+if (!%s && t.y < 0.0) {
+ %s = half4(0.0);
+} else {
+ @if (%s) {
+ half t_1 = t.x - 1.0;
+ half tiled_t = (t_1 - 2.0 * floor(t_1 * 0.5)) - 1.0;
+ if (sk_Caps.mustDoOpBetweenFloorAndAbs) {
+ tiled_t = clamp(tiled_t, -1.0, 1.0);
+ }
+ t.x = abs(tiled_t);
+ } else {
+ t.x = fract(t.x);
+ })SkSL",
_sample453.c_str(),
(_outer.childProcessor(_outer.gradLayout_index).preservesOpaqueInput() ? "true"
: "false"),
@@ -44,10 +53,16 @@ public:
SkString _input1464("t");
SkString _sample1464;
_sample1464 = this->invokeChild(_outer.colorizer_index, _input1464.c_str(), args);
- fragBuilder->codeAppendf("\n %s = %s;\n}\n@if (%s) {\n %s.xyz *= %s.w;\n}\n",
- args.fOutputColor, _sample1464.c_str(),
- (_outer.makePremul ? "true" : "false"), args.fOutputColor,
- args.fOutputColor);
+ fragBuilder->codeAppendf(
+ R"SkSL(
+ %s = %s;
+}
+@if (%s) {
+ %s.xyz *= %s.w;
+}
+)SkSL",
+ args.fOutputColor, _sample1464.c_str(), (_outer.makePremul ? "true" : "false"),
+ args.fOutputColor, args.fOutputColor);
}
private:
@@ -72,24 +87,16 @@ bool GrTiledGradientEffect::onIsEqual(const GrFragmentProcessor& other) const {
}
GrTiledGradientEffect::GrTiledGradientEffect(const GrTiledGradientEffect& src)
: INHERITED(kGrTiledGradientEffect_ClassID, src.optimizationFlags())
- , colorizer_index(src.colorizer_index)
- , gradLayout_index(src.gradLayout_index)
, mirror(src.mirror)
, makePremul(src.makePremul)
, colorsAreOpaque(src.colorsAreOpaque) {
{
- auto clone = src.childProcessor(colorizer_index).clone();
- if (src.childProcessor(colorizer_index).isSampledWithExplicitCoords()) {
- clone->setSampledWithExplicitCoords();
- }
- this->registerChildProcessor(std::move(clone));
+ colorizer_index =
+ this->cloneAndRegisterChildProcessor(src.childProcessor(src.colorizer_index));
}
{
- auto clone = src.childProcessor(gradLayout_index).clone();
- if (src.childProcessor(gradLayout_index).isSampledWithExplicitCoords()) {
- clone->setSampledWithExplicitCoords();
- }
- this->registerChildProcessor(std::move(clone));
+ gradLayout_index =
+ this->cloneAndRegisterChildProcessor(src.childProcessor(src.gradLayout_index));
}
}
std::unique_ptr<GrFragmentProcessor> GrTiledGradientEffect::clone() const {
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.h
index d22d1c61106..4fbf2d3b264 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.h
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrTiledGradientEffect.h
@@ -10,11 +10,13 @@
**************************************************************************************************/
#ifndef GrTiledGradientEffect_DEFINED
#define GrTiledGradientEffect_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrTiledGradientEffect : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(
@@ -50,11 +52,9 @@ private:
, makePremul(makePremul)
, colorsAreOpaque(colorsAreOpaque) {
SkASSERT(colorizer);
- colorizer_index = this->numChildProcessors();
- this->registerChildProcessor(std::move(colorizer));
+ colorizer_index = this->registerChild(std::move(colorizer));
SkASSERT(gradLayout);
- gradLayout_index = this->numChildProcessors();
- this->registerChildProcessor(std::move(gradLayout));
+ gradLayout_index = this->registerChild(std::move(gradLayout));
}
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.cpp
index 2f80228e6a1..fa172c76c29 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.cpp
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.cpp
@@ -45,48 +45,90 @@ public:
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(
args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix());
fragBuilder->codeAppendf(
- "float2 p = %s;\nfloat t = -1.0;\nhalf v = 1.0;\n@switch (%d) {\n case 1:\n "
- " {\n half r0_2 = %s.y;\n t = float(r0_2) - p.y * p.y;\n "
- " if (t >= 0.0) {\n t = p.x + sqrt(t);\n } else "
- "{\n v = -1.0;\n }\n }\n break;\n case "
- "0:\n {\n half r0 = %s.x;\n @if (%s) {\n "
- " t = length(p) - float(r0);\n } else {\n t = "
- "-length(p) - float(r0);\n ",
+ R"SkSL(float2 p = %s;
+float t = -1.0;
+half v = 1.0;
+@switch (%d) {
+ case 1:
+ {
+ half r0_2 = %s.y;
+ t = float(r0_2) - p.y * p.y;
+ if (t >= 0.0) {
+ t = p.x + sqrt(t);
+ } else {
+ v = -1.0;
+ }
+ }
+ break;
+ case 0:
+ {
+ half r0 = %s.x;
+ @if (%s) {
+ t = length(p) - float(r0);
+ } else {
+ t = -length(p) - float(r0);
+ }
+ }
+ break;
+ case 2:
+ {
+ half invR1 = %s.x;
+ half fx = %s.y;
+ float x_t = -1.0;
+ @if (%s) {
+ x_t = dot(p, p) / p.x;
+ } else if (%s) {
+ x_t = length(p) - p.x * float(invR1);
+ } else {
+ float temp = p.x * p.x - p.y * p.y;
+ if (temp >= 0.0) {
+ @if (%s || !%s) {
+ x_t = -sqrt(temp) - p.x * float(invR1);
+ } else {
+ x_t = sqrt(temp) - p.x * float(invR1);
+ }
+ }
+ }
+ @if (!%s) {
+ if (x_t <= 0.0) {
+ v = -1.0;
+ }
+ }
+ @if (%s) {
+ @if (%s) {
+ t = x_t;
+ } else {
+ t = x_t + float(fx);
+ }
+ } else {
+ @if (%s) {
+ t = -x_t;
+ } else {
+ t = -x_t + float(fx);
+ }
+ }
+ @if (%s) {
+ t = 1.0 - t;
+ }
+ }
+ break;
+}
+%s = half4(half(t), v, 0.0, 0.0);
+)SkSL",
sk_TransformedCoords2D_0.c_str(), (int)_outer.type,
args.fUniformHandler->getUniformCStr(focalParamsVar),
args.fUniformHandler->getUniformCStr(focalParamsVar),
- (_outer.isRadiusIncreasing ? "true" : "false"));
- fragBuilder->codeAppendf(
- " }\n }\n break;\n case 2:\n {\n half invR1 "
- "= %s.x;\n half fx = %s.y;\n float x_t = -1.0;\n "
- "@if (%s) {\n x_t = dot(p, p) / p.x;\n } else if (%s) "
- "{\n x_t = length(p) - p.x * float(invR1);\n } else {\n "
- " float temp = p.x * p.x - p.y * p.y;\n if (temp >= "
- "0.0) {\n @if (%s || !%s) {\n x_t = "
- "-sqrt(temp) - p.x * float(invR1)",
+ (_outer.isRadiusIncreasing ? "true" : "false"),
args.fUniformHandler->getUniformCStr(focalParamsVar),
args.fUniformHandler->getUniformCStr(focalParamsVar),
(_outer.isFocalOnCircle ? "true" : "false"),
(_outer.isWellBehaved ? "true" : "false"), (_outer.isSwapped ? "true" : "false"),
- (_outer.isRadiusIncreasing ? "true" : "false"));
- fragBuilder->codeAppendf(
- ";\n } else {\n x_t = sqrt(temp) - p.x * "
- "float(invR1);\n }\n }\n }\n "
- " @if (!%s) {\n if (x_t <= 0.0) {\n v = -1.0;\n "
- " }\n }\n @if (%s) {\n @if (%s) "
- "{\n t = x_t;\n } else {\n t "
- "= x_t + float(fx);\n }\n } else {\n @if "
- "(%s) {\n ",
+ (_outer.isRadiusIncreasing ? "true" : "false"),
(_outer.isWellBehaved ? "true" : "false"),
(_outer.isRadiusIncreasing ? "true" : "false"),
(_outer.isNativelyFocal ? "true" : "false"),
- (_outer.isNativelyFocal ? "true" : "false"));
- fragBuilder->codeAppendf(
- " t = -x_t;\n } else {\n t = -x_t + "
- "float(fx);\n }\n }\n @if (%s) {\n "
- " t = 1.0 - t;\n }\n }\n break;\n}\n%s = "
- "half4(half(t), v, 0.0, 0.0);\n",
- (_outer.isSwapped ? "true" : "false"), args.fOutputColor);
+ (_outer.isNativelyFocal ? "true" : "false"), (_outer.isSwapped ? "true" : "false"),
+ args.fOutputColor);
}
private:
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.h
index 4a08aea9831..afd93db24f3 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.h
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.h
@@ -10,14 +10,16 @@
**************************************************************************************************/
#ifndef GrTwoPointConicalGradientLayout_DEFINED
#define GrTwoPointConicalGradientLayout_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/gradients/GrGradientShader.h"
#include "src/shaders/gradients/SkTwoPointConicalGradient.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrTwoPointConicalGradientLayout : public GrFragmentProcessor {
public:
enum class Type { kFocal = 2, kRadial = 0, kStrip = 1 };
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.cpp b/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.cpp
index 3f5c5aca95d..38368dbb505 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.cpp
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.cpp
@@ -127,13 +127,47 @@ public:
thresholds9_13Var = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
kHalf4_GrSLType, "thresholds9_13");
fragBuilder->codeAppendf(
- "half t = %s.x;\nfloat4 scale, bias;\nif (%d <= 4 || t < %s.w) {\n if (%d <= 2 "
- "|| t < %s.y) {\n if (%d <= 1 || t < %s.x) {\n scale = %s;\n "
- " bias = %s;\n } else {\n scale = %s;\n bias = "
- "%s;\n }\n } else {\n if (%d <= 3 || t < %s.z) {\n "
- "scale = %s;\n bias = %s;\n } else {\n scale = %s;\n "
- " bias = %s;\n }\n }\n} else {\n if (%d <= 6 || t < %s.y) "
- "{\n if (%d <= 5 || t <",
+ R"SkSL(half t = %s.x;
+float4 scale, bias;
+if (%d <= 4 || t < %s.w) {
+ if (%d <= 2 || t < %s.y) {
+ if (%d <= 1 || t < %s.x) {
+ scale = %s;
+ bias = %s;
+ } else {
+ scale = %s;
+ bias = %s;
+ }
+ } else {
+ if (%d <= 3 || t < %s.z) {
+ scale = %s;
+ bias = %s;
+ } else {
+ scale = %s;
+ bias = %s;
+ }
+ }
+} else {
+ if (%d <= 6 || t < %s.y) {
+ if (%d <= 5 || t < %s.x) {
+ scale = %s;
+ bias = %s;
+ } else {
+ scale = %s;
+ bias = %s;
+ }
+ } else {
+ if (%d <= 7 || t < %s.z) {
+ scale = %s;
+ bias = %s;
+ } else {
+ scale = %s;
+ bias = %s;
+ }
+ }
+}
+%s = half4(float(t) * scale + bias);
+)SkSL",
args.fInputColor, _outer.intervalCount,
args.fUniformHandler->getUniformCStr(thresholds1_7Var), _outer.intervalCount,
args.fUniformHandler->getUniformCStr(thresholds1_7Var), _outer.intervalCount,
@@ -154,14 +188,7 @@ public:
bias6_7Var.isValid() ? args.fUniformHandler->getUniformCStr(bias6_7Var)
: "float4(0)",
_outer.intervalCount, args.fUniformHandler->getUniformCStr(thresholds9_13Var),
- _outer.intervalCount);
- fragBuilder->codeAppendf(
- " %s.x) {\n scale = %s;\n bias = %s;\n } else {\n "
- " scale = %s;\n bias = %s;\n }\n } else {\n if "
- "(%d <= 7 || t < %s.z) {\n scale = %s;\n bias = %s;\n "
- "} else {\n scale = %s;\n bias = %s;\n }\n "
- "}\n}\n%s = half4(float(t) * scale + bias);\n",
- args.fUniformHandler->getUniformCStr(thresholds9_13Var),
+ _outer.intervalCount, args.fUniformHandler->getUniformCStr(thresholds9_13Var),
scale8_9Var.isValid() ? args.fUniformHandler->getUniformCStr(scale8_9Var)
: "float4(0)",
bias8_9Var.isValid() ? args.fUniformHandler->getUniformCStr(bias8_9Var)
diff --git a/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.h b/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.h
index 9c9ecea611f..144cd8c0447 100644
--- a/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.h
+++ b/chromium/third_party/skia/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.h
@@ -10,11 +10,13 @@
**************************************************************************************************/
#ifndef GrUnrolledBinaryGradientColorizer_DEFINED
#define GrUnrolledBinaryGradientColorizer_DEFINED
-#include "include/core/SkTypes.h"
+
#include "include/core/SkM44.h"
+#include "include/core/SkTypes.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
+
class GrUnrolledBinaryGradientColorizer : public GrFragmentProcessor {
public:
static const int kMaxColorCount = 16;
diff --git a/chromium/third_party/skia/src/gpu/mock/GrMockCaps.h b/chromium/third_party/skia/src/gpu/mock/GrMockCaps.h
index 42a97144593..6548aa634ba 100644
--- a/chromium/third_party/skia/src/gpu/mock/GrMockCaps.h
+++ b/chromium/third_party/skia/src/gpu/mock/GrMockCaps.h
@@ -35,7 +35,7 @@ public:
fShaderCaps->fShaderDerivativeSupport = options.fShaderDerivativeSupport;
fShaderCaps->fDualSourceBlendingSupport = options.fDualSourceBlendingSupport;
fShaderCaps->fSampleMaskSupport = true;
- fShaderCaps->fTessellationSupport = options.fTessellationSupport;
+ fShaderCaps->fMaxTessellationSegments = options.fMaxTessellationSegments;
this->finishInitialization(contextOptions);
}
@@ -50,10 +50,6 @@ public:
return GrGetColorTypeDesc(ct).encoding() == GrColorTypeEncoding::kSRGBUnorm;
}
- SkImage::CompressionType compressionType(const GrBackendFormat& format) const override {
- return format.asMockCompressionType();
- }
-
bool isFormatTexturable(const GrBackendFormat& format) const override {
SkImage::CompressionType compression = format.asMockCompressionType();
if (compression != SkImage::CompressionType::kNone) {
@@ -155,10 +151,6 @@ public:
return {};
}
- GrSwizzle getReadSwizzle(const GrBackendFormat& format, GrColorType ct) const override {
- SkASSERT(this->areColorTypeAndFormatCompatible(ct, format));
- return GrSwizzle("rgba");
- }
GrSwizzle getWriteSwizzle(const GrBackendFormat& format, GrColorType ct) const override {
SkASSERT(this->areColorTypeAndFormatCompatible(ct, format));
return GrSwizzle("rgba");
@@ -205,6 +197,11 @@ private:
return SupportedRead{srcColorType, 1};
}
+ GrSwizzle onGetReadSwizzle(const GrBackendFormat& format, GrColorType ct) const override {
+ SkASSERT(this->areColorTypeAndFormatCompatible(ct, format));
+ return GrSwizzle("rgba");
+ }
+
static const int kMaxSampleCnt = 16;
GrMockOptions fOptions;
diff --git a/chromium/third_party/skia/src/gpu/mock/GrMockGpu.cpp b/chromium/third_party/skia/src/gpu/mock/GrMockGpu.cpp
index 3348c4bbdb7..ccd1157cf89 100644
--- a/chromium/third_party/skia/src/gpu/mock/GrMockGpu.cpp
+++ b/chromium/third_party/skia/src/gpu/mock/GrMockGpu.cpp
@@ -53,7 +53,8 @@ sk_sp<GrGpu> GrMockGpu::Make(const GrMockOptions* mockOptions,
}
GrOpsRenderPass* GrMockGpu::getOpsRenderPass(
- GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
+ GrRenderTarget* rt, GrStencilAttachment*,
+ GrSurfaceOrigin origin, const SkIRect& bounds,
const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
const GrOpsRenderPass::StencilLoadAndStoreInfo&,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
diff --git a/chromium/third_party/skia/src/gpu/mock/GrMockGpu.h b/chromium/third_party/skia/src/gpu/mock/GrMockGpu.h
index 05fdda7599a..29dda81d2b3 100644
--- a/chromium/third_party/skia/src/gpu/mock/GrMockGpu.h
+++ b/chromium/third_party/skia/src/gpu/mock/GrMockGpu.h
@@ -25,7 +25,10 @@ public:
~GrMockGpu() override {}
GrOpsRenderPass* getOpsRenderPass(
- GrRenderTarget*, GrSurfaceOrigin, const SkIRect&,
+ GrRenderTarget*,
+ GrStencilAttachment*,
+ GrSurfaceOrigin,
+ const SkIRect&,
const GrOpsRenderPass::LoadAndStoreInfo&,
const GrOpsRenderPass::StencilLoadAndStoreInfo&,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override;
diff --git a/chromium/third_party/skia/src/gpu/mock/GrMockOpsRenderPass.h b/chromium/third_party/skia/src/gpu/mock/GrMockOpsRenderPass.h
index 5a45a3e9713..703eac21333 100644
--- a/chromium/third_party/skia/src/gpu/mock/GrMockOpsRenderPass.h
+++ b/chromium/third_party/skia/src/gpu/mock/GrMockOpsRenderPass.h
@@ -45,8 +45,10 @@ private:
void onDrawIndexedInstanced(int, int, int, int, int) override { this->dummyDraw(); }
void onDrawIndirect(const GrBuffer*, size_t, int) override { this->dummyDraw(); }
void onDrawIndexedIndirect(const GrBuffer*, size_t, int) override { this->dummyDraw(); }
- void onClear(const GrFixedClip&, const SkPMColor4f&) override { this->markRenderTargetDirty(); }
- void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) override {}
+ void onClear(const GrScissorState& scissor, const SkPMColor4f&) override {
+ this->markRenderTargetDirty();
+ }
+ void onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) override {}
void dummyDraw() {
this->markRenderTargetDirty();
++fNumDraws;
diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.h b/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.h
index 09ae534a9b6..0650c5a9b61 100644
--- a/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.h
+++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.h
@@ -27,7 +27,6 @@ public:
MTLFeatureSet featureSet);
bool isFormatSRGB(const GrBackendFormat&) const override;
- SkImage::CompressionType compressionType(const GrBackendFormat&) const override;
bool isFormatTexturable(const GrBackendFormat&) const override;
bool isFormatTexturable(MTLPixelFormat) const;
@@ -82,7 +81,6 @@ public:
return fColorTypeToFormatTable[idx];
}
- GrSwizzle getReadSwizzle(const GrBackendFormat&, GrColorType) const override;
GrSwizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override;
uint64_t computeFormatKey(const GrBackendFormat&) const override;
@@ -113,6 +111,8 @@ private:
SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&,
GrColorType) const override;
+ GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override;
+
// ColorTypeInfo for a specific format
struct ColorTypeInfo {
GrColorType fColorType = GrColorType::kUnknown;
diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.mm b/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.mm
index 4b28bf7034b..2fb81021f4e 100644
--- a/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.mm
+++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlCaps.mm
@@ -10,6 +10,7 @@
#include "include/core/SkRect.h"
#include "include/gpu/GrBackendSurface.h"
#include "src/core/SkCompressedDataUtils.h"
+#include "src/gpu/GrBackendUtils.h"
#include "src/gpu/GrProcessor.h"
#include "src/gpu/GrProgramDesc.h"
#include "src/gpu/GrProgramInfo.h"
@@ -318,24 +319,6 @@ bool GrMtlCaps::isFormatSRGB(const GrBackendFormat& format) const {
return format_is_srgb(GrBackendFormatAsMTLPixelFormat(format));
}
-SkImage::CompressionType GrMtlCaps::compressionType(const GrBackendFormat& format) const {
-
- switch (GrBackendFormatAsMTLPixelFormat(format)) {
-#ifdef SK_BUILD_FOR_IOS
- case MTLPixelFormatETC2_RGB8:
- // ETC2 uses the same compression layout as ETC1
- return SkImage::CompressionType::kETC2_RGB8_UNORM;
-#else
- case MTLPixelFormatBC1_RGBA:
- return SkImage::CompressionType::kBC1_RGBA8_UNORM;
-#endif
- default:
- return SkImage::CompressionType::kNone;
- }
-
- SkUNREACHABLE;
-}
-
bool GrMtlCaps::isFormatTexturable(const GrBackendFormat& format) const {
MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
return this->isFormatTexturable(mtlFormat);
@@ -900,12 +883,6 @@ bool GrMtlCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
const GrBackendFormat& format) const {
MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
- SkImage::CompressionType compression = GrMtlFormatToCompressionType(mtlFormat);
- if (compression != SkImage::CompressionType::kNone) {
- return ct == (SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
- : GrColorType::kRGBA_8888);
- }
-
const auto& info = this->getFormatInfo(mtlFormat);
for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
if (info.fColorTypeInfos[i].fColorType == ct) {
@@ -948,7 +925,7 @@ GrBackendFormat GrMtlCaps::getBackendFormatFromCompressionType(
SK_ABORT("Invalid compression type");
}
-GrSwizzle GrMtlCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
+GrSwizzle GrMtlCaps::onGetReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
SkASSERT(mtlFormat != MTLPixelFormatInvalid);
const auto& info = this->getFormatInfo(mtlFormat);
@@ -1008,9 +985,7 @@ GrCaps::SupportedWrite GrMtlCaps::supportedWritePixelsColorType(
GrCaps::SupportedRead GrMtlCaps::onSupportedReadPixelsColorType(
GrColorType srcColorType, const GrBackendFormat& srcBackendFormat,
GrColorType dstColorType) const {
- MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(srcBackendFormat);
-
- SkImage::CompressionType compression = GrMtlFormatToCompressionType(mtlFormat);
+ SkImage::CompressionType compression = GrBackendFormatToCompressionType(srcBackendFormat);
if (compression != SkImage::CompressionType::kNone) {
#ifdef SK_BUILD_FOR_IOS
// Reading back to kRGB_888x doesn't work on Metal/iOS (skbug.com/9839)
@@ -1024,6 +999,7 @@ GrCaps::SupportedRead GrMtlCaps::onSupportedReadPixelsColorType(
// Metal requires the destination offset for copyFromTexture to be a multiple of the textures
// pixels size.
size_t offsetAlignment = GrColorTypeBytesPerPixel(srcColorType);
+ MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(srcBackendFormat);
const auto& info = this->getFormatInfo(mtlFormat);
for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlCppUtil.h b/chromium/third_party/skia/src/gpu/mtl/GrMtlCppUtil.h
index f431ec81076..bcbdbdd4b14 100644
--- a/chromium/third_party/skia/src/gpu/mtl/GrMtlCppUtil.h
+++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlCppUtil.h
@@ -8,14 +8,19 @@
#ifndef GrMtlCppUtil_DEFINED
#define GrMtlCppUtil_DEFINED
+#include "include/core/SkImage.h"
#include "include/gpu/mtl/GrMtlTypes.h"
+class GrBackendFormat;
+
// Utilities that can be used from cpp files (rather than .mm).
GrMTLPixelFormat GrGetMTLPixelFormatFromMtlTextureInfo(const GrMtlTextureInfo&);
uint32_t GrMtlFormatChannels(GrMTLPixelFormat);
+SkImage::CompressionType GrMtlBackendFormatToCompressionType(const GrBackendFormat& format);
+
#if GR_TEST_UTILS
const char* GrMtlFormatToStr(GrMTLPixelFormat mtlFormat);
bool GrMtlFormatIsBGRA8(GrMTLPixelFormat mtlFormat);
diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.h b/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.h
index 191c0bacf37..16bd0fe8442 100644
--- a/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.h
+++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.h
@@ -68,6 +68,10 @@ public:
void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
void testingOnly_flushGpuAndSync() override;
+
+ void resetShaderCacheForTesting() const override {
+ fResourceProvider.resetShaderCacheForTesting();
+ }
#endif
void copySurfaceAsResolve(GrSurface* dst, GrSurface* src);
@@ -79,7 +83,8 @@ public:
const SkIPoint& dstPoint) override;
GrOpsRenderPass* getOpsRenderPass(
- GrRenderTarget*, GrSurfaceOrigin, const SkIRect& bounds,
+ GrRenderTarget*, GrStencilAttachment*,
+ GrSurfaceOrigin, const SkIRect& bounds,
const GrOpsRenderPass::LoadAndStoreInfo&,
const GrOpsRenderPass::StencilLoadAndStoreInfo&,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override;
diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.mm b/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.mm
index 420bb896679..dced04f7b58 100644
--- a/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.mm
+++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlGpu.mm
@@ -11,6 +11,7 @@
#include "src/core/SkCompressedDataUtils.h"
#include "src/core/SkConvertPixels.h"
#include "src/core/SkMipMap.h"
+#include "src/gpu/GrBackendUtils.h"
#include "src/gpu/GrDataUtils.h"
#include "src/gpu/GrRenderTargetPriv.h"
#include "src/gpu/GrTexturePriv.h"
@@ -159,7 +160,8 @@ void GrMtlGpu::destroyResources() {
}
GrOpsRenderPass* GrMtlGpu::getOpsRenderPass(
- GrRenderTarget* renderTarget, GrSurfaceOrigin origin, const SkIRect& bounds,
+ GrRenderTarget* renderTarget, GrStencilAttachment*,
+ GrSurfaceOrigin origin, const SkIRect& bounds,
const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
@@ -545,7 +547,7 @@ sk_sp<GrTexture> GrMtlGpu::onCreateCompressedTexture(SkISize dimensions,
id<MTLTexture> mtlTexture = tex->mtlTexture();
SkASSERT(mtlTexture);
- auto compressionType = GrMtlFormatToCompressionType(mtlTexture.pixelFormat);
+ auto compressionType = GrBackendFormatToCompressionType(format);
SkASSERT(compressionType != SkImage::CompressionType::kNone);
SkTArray<size_t> individualMipOffsets(numMipLevels);
@@ -844,7 +846,8 @@ bool GrMtlGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
int numMipLevels = mtlTexture.mipmapLevelCount;
GrMipMapped mipMapped = numMipLevels > 1 ? GrMipMapped::kYes : GrMipMapped::kNo;
- SkImage::CompressionType compression = GrMtlFormatToCompressionType(mtlFormat);
+ SkImage::CompressionType compression = GrBackendFormatToCompressionType(
+ backendTexture.getBackendFormat());
// Create a transfer buffer and fill with data.
SkSTArray<16, size_t> individualMipOffsets;
@@ -1349,6 +1352,7 @@ std::unique_ptr<GrSemaphore> GrMtlGpu::wrapBackendSemaphore(
void GrMtlGpu::insertSemaphore(GrSemaphore* semaphore) {
if (@available(macOS 10.14, iOS 12.0, *)) {
+ SkASSERT(semaphore);
GrMtlSemaphore* mtlSem = static_cast<GrMtlSemaphore*>(semaphore);
this->commandBuffer()->encodeSignalEvent(mtlSem->event(), mtlSem->value());
@@ -1357,6 +1361,7 @@ void GrMtlGpu::insertSemaphore(GrSemaphore* semaphore) {
void GrMtlGpu::waitSemaphore(GrSemaphore* semaphore) {
if (@available(macOS 10.14, iOS 12.0, *)) {
+ SkASSERT(semaphore);
GrMtlSemaphore* mtlSem = static_cast<GrMtlSemaphore*>(semaphore);
this->commandBuffer()->encodeWaitForEvent(mtlSem->event(), mtlSem->value());
diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.h b/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.h
index 77229ce8487..c4cf385ef0d 100644
--- a/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.h
+++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.h
@@ -49,9 +49,9 @@ private:
void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance,
int baseVertex) override;
- void onClear(const GrFixedClip& clip, const SkPMColor4f& color) override;
+ void onClear(const GrScissorState& scissor, const SkPMColor4f& color) override;
- void onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) override;
+ void onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) override;
void setupRenderPass(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo);
@@ -80,4 +80,3 @@ private:
};
#endif
-
diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.mm b/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.mm
index 576a1349c3b..13ef3a3bce8 100644
--- a/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.mm
+++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlOpsRenderPass.mm
@@ -8,7 +8,6 @@
#include "src/gpu/mtl/GrMtlOpsRenderPass.h"
#include "src/gpu/GrColor.h"
-#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrRenderTargetPriv.h"
#include "src/gpu/mtl/GrMtlCommandBuffer.h"
#include "src/gpu/mtl/GrMtlPipelineState.h"
@@ -123,7 +122,10 @@ bool GrMtlOpsRenderPass::onBindTextures(const GrPrimitiveProcessor& primProc,
return true;
}
-void GrMtlOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& color) {
+void GrMtlOpsRenderPass::onClear(const GrScissorState& scissor, const SkPMColor4f& color) {
+ // Partial clears are not supported
+ SkASSERT(!scissor.enabled());
+
// Ideally we should never end up here since all clears should either be done as draws or
// load ops in metal. However, if a client inserts a wait op we need to handle it.
fRenderPassDesc.colorAttachments[0].clearColor =
@@ -135,8 +137,9 @@ void GrMtlOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& col
fGpu->commandBuffer()->getRenderCommandEncoder(fRenderPassDesc, nullptr, this);
}
-void GrMtlOpsRenderPass::onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
- SkASSERT(!clip.hasWindowRectangles());
+void GrMtlOpsRenderPass::onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) {
+ // Partial clears are not supported
+ SkASSERT(!scissor.enabled());
GrStencilAttachment* sb = fRenderTarget->renderTargetPriv().getStencilAttachment();
// this should only be called internally when we know we have a
diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.h b/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.h
index cd1d1021523..eed06eb2c54 100644
--- a/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.h
+++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.h
@@ -21,7 +21,7 @@ class GrProgramInfo;
class GrMtlCaps;
class GrMtlGpu;
class GrMtlPipelineState;
-class SkReader32;
+class SkReadBuffer;
class GrMtlPipelineStateBuilder : public GrGLSLProgramBuilder {
public:
@@ -58,7 +58,7 @@ private:
SkSL::Program::Inputs inputs);
void storeShadersInCache(const SkSL::String shaders[], const SkSL::Program::Inputs inputs[],
bool isSkSL);
- void loadShadersFromCache(SkReader32* cached, __strong id<MTLLibrary> outLibraries[]);
+ bool loadShadersFromCache(SkReadBuffer* cached, __strong id<MTLLibrary> outLibraries[]);
GrGLSLUniformHandler* uniformHandler() override { return &fUniformHandler; }
const GrGLSLUniformHandler* uniformHandler() const override { return &fUniformHandler; }
diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.mm b/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.mm
index 3c2c91bb039..0bfd4ee7976 100644
--- a/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.mm
+++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlPipelineStateBuilder.mm
@@ -8,7 +8,7 @@
#include "src/gpu/mtl/GrMtlPipelineStateBuilder.h"
#include "include/gpu/GrContext.h"
-#include "src/core/SkReader32.h"
+#include "src/core/SkReadBuffer.h"
#include "src/core/SkTraceEvent.h"
#include "src/gpu/GrAutoLocaleSetter.h"
#include "src/gpu/GrContextPriv.h"
@@ -66,12 +66,14 @@ static constexpr SkFourByteTag kMSL_Tag = SkSetFourByteTag('M', 'S', 'L', ' ');
static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
-void GrMtlPipelineStateBuilder::loadShadersFromCache(SkReader32* cached,
+bool GrMtlPipelineStateBuilder::loadShadersFromCache(SkReadBuffer* cached,
__strong id<MTLLibrary> outLibraries[]) {
SkSL::String shaders[kGrShaderTypeCount];
SkSL::Program::Inputs inputs[kGrShaderTypeCount];
- GrPersistentCacheUtils::UnpackCachedShaders(cached, shaders, inputs, kGrShaderTypeCount);
+ if (!GrPersistentCacheUtils::UnpackCachedShaders(cached, shaders, inputs, kGrShaderTypeCount)) {
+ return false;
+ }
outLibraries[kVertex_GrShaderType] = this->compileMtlShaderLibrary(
shaders[kVertex_GrShaderType],
@@ -80,11 +82,9 @@ void GrMtlPipelineStateBuilder::loadShadersFromCache(SkReader32* cached,
shaders[kFragment_GrShaderType],
inputs[kFragment_GrShaderType]);
- // Geometry shaders are not supported
- SkASSERT(shaders[kGeometry_GrShaderType].empty());
-
- SkASSERT(outLibraries[kVertex_GrShaderType]);
- SkASSERT(outLibraries[kFragment_GrShaderType]);
+ return outLibraries[kVertex_GrShaderType] &&
+ outLibraries[kFragment_GrShaderType] &&
+ shaders[kGeometry_GrShaderType].empty(); // Geometry shaders are not supported
}
void GrMtlPipelineStateBuilder::storeShadersInCache(const SkSL::String shaders[],
@@ -399,7 +399,7 @@ GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(GrRenderTarget* renderTa
SkASSERT(!this->fragColorIsInOut());
sk_sp<SkData> cached;
- SkReader32 reader;
+ SkReadBuffer reader;
SkFourByteTag shaderType = 0;
auto persistentCache = fGpu->getContext()->priv().getPersistentCache();
if (persistentCache) {
@@ -414,10 +414,10 @@ GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(GrRenderTarget* renderTa
}
}
- SkSL::String shaders[kGrShaderTypeCount];
- if (kMSL_Tag == shaderType) {
- this->loadShadersFromCache(&reader, shaderLibraries);
+ if (kMSL_Tag == shaderType && this->loadShadersFromCache(&reader, shaderLibraries)) {
+ // We successfully loaded and compiled MSL
} else {
+ SkSL::String shaders[kGrShaderTypeCount];
SkSL::Program::Inputs inputs[kGrShaderTypeCount];
SkSL::String* sksl[kGrShaderTypeCount] = {
@@ -427,10 +427,11 @@ GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(GrRenderTarget* renderTa
};
SkSL::String cached_sksl[kGrShaderTypeCount];
if (kSKSL_Tag == shaderType) {
- GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, inputs,
- kGrShaderTypeCount);
- for (int i = 0; i < kGrShaderTypeCount; ++i) {
- sksl[i] = &cached_sksl[i];
+ if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, inputs,
+ kGrShaderTypeCount)) {
+ for (int i = 0; i < kGrShaderTypeCount; ++i) {
+ sksl[i] = &cached_sksl[i];
+ }
}
}
diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlResourceProvider.h b/chromium/third_party/skia/src/gpu/mtl/GrMtlResourceProvider.h
index 5d1f213b154..20e6eb29aa1 100644
--- a/chromium/third_party/skia/src/gpu/mtl/GrMtlResourceProvider.h
+++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlResourceProvider.h
@@ -41,6 +41,10 @@ public:
// Destroy any cached resources. To be called before releasing the MtlDevice.
void destroyResources();
+#if GR_TEST_UTILS
+ void resetShaderCacheForTesting() const { fPipelineStateCache->release(); }
+#endif
+
private:
#ifdef SK_DEBUG
#define GR_PIPELINE_STATE_CACHE_STATS
diff --git a/chromium/third_party/skia/src/gpu/mtl/GrMtlUtil.mm b/chromium/third_party/skia/src/gpu/mtl/GrMtlUtil.mm
index c890e4b8991..df519b3037a 100644
--- a/chromium/third_party/skia/src/gpu/mtl/GrMtlUtil.mm
+++ b/chromium/third_party/skia/src/gpu/mtl/GrMtlUtil.mm
@@ -7,6 +7,7 @@
#include "src/gpu/mtl/GrMtlUtil.h"
+#include "include/gpu/GrBackendSurface.h"
#include "include/private/GrTypesPriv.h"
#include "include/private/SkMutex.h"
#include "src/gpu/GrSurface.h"
@@ -269,6 +270,12 @@ uint32_t GrMtlFormatChannels(GrMTLPixelFormat mtlFormat) {
}
}
+SkImage::CompressionType GrMtlBackendFormatToCompressionType(const GrBackendFormat& format) {
+ MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
+ return GrMtlFormatToCompressionType(mtlFormat);
+}
+
+
bool GrMtlFormatIsCompressed(MTLPixelFormat mtlFormat) {
switch (mtlFormat) {
#ifdef SK_BUILD_FOR_IOS
diff --git a/chromium/third_party/skia/src/gpu/ops/GrAAConvexPathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrAAConvexPathRenderer.cpp
index e427a4a7383..2dc3e1add28 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -213,6 +213,7 @@ static void update_degenerate_test(DegenerateTestData* data, const SkPoint& pt)
if (SkScalarAbs(data->fLineNormal.dot(pt) + data->fLineC) > kClose) {
data->fStage = DegenerateTestData::kNonDegenerate;
}
+ break;
case DegenerateTestData::kNonDegenerate:
break;
default:
@@ -576,14 +577,11 @@ public:
// Setup position
this->writeOutputPosition(vertBuilder, gpArgs, qe.fInPosition.name());
-
- // emit transforms
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- qe.fInPosition.asShaderVar(),
- qe.fLocalMatrix,
- args.fFPCoordTransformHandler);
+ if (qe.fUsesLocalCoords) {
+ this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
+ qe.fInPosition.asShaderVar(), qe.fLocalMatrix,
+ &fLocalMatrixUniform);
+ }
fragBuilder->codeAppendf("half edgeAlpha;");
@@ -610,18 +608,24 @@ public:
const GrShaderCaps&,
GrProcessorKeyBuilder* b) {
const QuadEdgeEffect& qee = gp.cast<QuadEdgeEffect>();
- b->add32(SkToBool(qee.fUsesLocalCoords && qee.fLocalMatrix.hasPerspective()));
+ uint32_t key = (uint32_t) qee.fUsesLocalCoords;
+ key |= ComputeMatrixKey(qee.fLocalMatrix) << 1;
+ b->add32(key);
}
void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& gp,
const CoordTransformRange& transformRange) override {
const QuadEdgeEffect& qe = gp.cast<QuadEdgeEffect>();
- this->setTransformDataHelper(qe.fLocalMatrix, pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
+ this->setTransform(pdman, fLocalMatrixUniform, qe.fLocalMatrix, &fLocalMatrix);
}
private:
typedef GrGLSLGeometryProcessor INHERITED;
+
+ SkMatrix fLocalMatrix = SkMatrix::InvalidMatrix();
+ UniformHandle fLocalMatrixUniform;
};
void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
@@ -915,7 +919,7 @@ bool GrAAConvexPathRenderer::onDrawPath(const DrawPathArgs& args) {
std::unique_ptr<GrDrawOp> op = AAConvexPathOp::Make(args.fContext, std::move(args.fPaint),
*args.fViewMatrix,
path, args.fUserStencilSettings);
- args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+ args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
return true;
}
diff --git a/chromium/third_party/skia/src/gpu/ops/GrAAHairLinePathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrAAHairLinePathRenderer.cpp
index 537d0f1c62d..b87d2f6a8d6 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrAAHairLinePathRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrAAHairLinePathRenderer.cpp
@@ -15,12 +15,12 @@
#include "src/gpu/GrAuditTrail.h"
#include "src/gpu/GrBuffer.h"
#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrDefaultGeoProcFactory.h"
#include "src/gpu/GrDrawOpTest.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrProcessor.h"
#include "src/gpu/GrProgramInfo.h"
+#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/effects/GrBezierEffect.h"
@@ -1011,7 +1011,6 @@ void AAHairlineOp::makeQuadProgramInfo(const GrCaps& caps, SkArenaAlloc* arena,
GrGeometryProcessor* quadGP = GrQuadEffect::Make(arena,
this->color(),
*geometryProcessorViewM,
- GrClipEdgeType::kHairlineAA,
caps,
*geometryProcessorLocalM,
fHelper.usesLocalCoords(),
@@ -1034,7 +1033,6 @@ void AAHairlineOp::makeConicProgramInfo(const GrCaps& caps, SkArenaAlloc* arena,
GrGeometryProcessor* conicGP = GrConicEffect::Make(arena,
this->color(),
*geometryProcessorViewM,
- GrClipEdgeType::kHairlineAA,
caps,
*geometryProcessorLocalM,
fHelper.usesLocalCoords(),
@@ -1117,7 +1115,7 @@ void AAHairlineOp::onPrePrepareDraws(GrRecordingContext* context,
const GrCaps* caps = context->priv().caps();
// This is equivalent to a GrOpFlushState::detachAppliedClip
- GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
+ GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled();
// Conservatively predict which programs will be required
fCharacterization = this->predictPrograms(caps);
@@ -1272,14 +1270,13 @@ bool GrAAHairLinePathRenderer::onDrawPath(const DrawPathArgs& args) {
"GrAAHairlinePathRenderer::onDrawPath");
SkASSERT(args.fRenderTargetContext->numSamples() <= 1);
- SkIRect devClipBounds = args.fClip->getConservativeBounds(args.fRenderTargetContext->width(),
- args.fRenderTargetContext->height());
SkPath path;
args.fShape->asPath(&path);
std::unique_ptr<GrDrawOp> op =
AAHairlineOp::Make(args.fContext, std::move(args.fPaint), *args.fViewMatrix, path,
- args.fShape->style(), devClipBounds, args.fUserStencilSettings);
- args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+ args.fShape->style(), *args.fClipConservativeBounds,
+ args.fUserStencilSettings);
+ args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
return true;
}
diff --git a/chromium/third_party/skia/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
index d6d644986d1..9c67fd8c3a0 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
@@ -405,7 +405,7 @@ bool GrAALinearizingConvexPathRenderer::onDrawPath(const DrawPathArgs& args) {
std::unique_ptr<GrDrawOp> op = AAFlatteningConvexPathOp::Make(
args.fContext, std::move(args.fPaint), *args.fViewMatrix, path, strokeWidth,
stroke.getStyle(), join, miterLimit, args.fUserStencilSettings);
- args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+ args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
return true;
}
diff --git a/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.cpp
index 80a34c66b1b..4e4e7f7e2e6 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.cpp
@@ -16,6 +16,7 @@
#include "src/gpu/GrMemoryPool.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrRecordingContextPriv.h"
+#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/effects/GrBitmapTextGeoProc.h"
#include "src/gpu/effects/GrDistanceFieldGeoProc.h"
@@ -23,6 +24,10 @@
#include "src/gpu/text/GrAtlasManager.h"
#include "src/gpu/text/GrDistanceFieldAdjustTable.h"
+#if GR_TEST_UTILS
+#include "src/gpu/GrDrawOpTest.h"
+#endif
+
///////////////////////////////////////////////////////////////////////////////////////////////////
GrAtlasTextOp::GrAtlasTextOp(MaskType maskType,
@@ -43,7 +48,7 @@ GrAtlasTextOp::GrAtlasTextOp(MaskType maskType,
, fDFGPFlags{DFGPFlags}
, fGeoDataAllocSize{kMinGeometryAllocated}
, fProcessors{std::move(paint)}
- , fNumGlyphs{SkTo<int>(subrun->fGlyphs.size())} {
+ , fNumGlyphs{subrun->glyphCount()} {
GrAtlasTextOp::Geometry& geometry = fGeoData[0];
// Unref handled in ~GrAtlasTextOp().
@@ -62,6 +67,11 @@ GrAtlasTextOp::GrAtlasTextOp(MaskType maskType,
this->setBounds(bounds, HasAABloat::kNo, IsHairline::kNo);
}
+void GrAtlasTextOp::Geometry::fillVertexData(void *dst, int offset, int count) const {
+ fSubRunPtr->fillVertexData(dst, offset, count, fColor.toBytes_RGBA(),
+ fDrawMatrix, fDrawOrigin, fClipRect);
+}
+
std::unique_ptr<GrAtlasTextOp> GrAtlasTextOp::MakeBitmap(GrRecordingContext* context,
GrPaint&& paint,
GrTextBlob::SubRun* subrun,
@@ -193,113 +203,6 @@ GrProcessorSet::Analysis GrAtlasTextOp::finalize(
return analysis;
}
-static void clip_quads(const SkIRect& clipRect, char* currVertex, const char* blobVertices,
- size_t vertexStride, int glyphCount) {
- for (int i = 0; i < glyphCount; ++i) {
- const SkPoint* blobPositionLT = reinterpret_cast<const SkPoint*>(blobVertices);
- const SkPoint* blobPositionRB =
- reinterpret_cast<const SkPoint*>(blobVertices + 3 * vertexStride);
-
- // positions for bitmap glyphs are pixel boundary aligned
- SkIRect positionRect = SkIRect::MakeLTRB(SkScalarRoundToInt(blobPositionLT->fX),
- SkScalarRoundToInt(blobPositionLT->fY),
- SkScalarRoundToInt(blobPositionRB->fX),
- SkScalarRoundToInt(blobPositionRB->fY));
- if (clipRect.contains(positionRect)) {
- memcpy(currVertex, blobVertices, 4 * vertexStride);
- currVertex += 4 * vertexStride;
- } else {
- // Pull out some more data that we'll need.
- // In the LCD case the color will be garbage, but we'll overwrite it with the texcoords
- // and it avoids a lot of conditionals.
- auto color = *reinterpret_cast<const SkColor*>(blobVertices + sizeof(SkPoint));
- size_t coordOffset = vertexStride - 2*sizeof(uint16_t);
- auto* blobCoordsLT = reinterpret_cast<const uint16_t*>(blobVertices + coordOffset);
- auto* blobCoordsRB = reinterpret_cast<const uint16_t*>(blobVertices + 3 * vertexStride +
- coordOffset);
- // Pull out the texel coordinates and texture index bits
- uint16_t coordsRectL = blobCoordsLT[0];
- uint16_t coordsRectT = blobCoordsLT[1];
- uint16_t coordsRectR = blobCoordsRB[0];
- uint16_t coordsRectB = blobCoordsRB[1];
- int index0, index1;
- std::tie(coordsRectL, coordsRectT, index0) =
- GrDrawOpAtlas::UnpackIndexFromTexCoords(coordsRectL, coordsRectT);
- std::tie(coordsRectR, coordsRectB, index1) =
- GrDrawOpAtlas::UnpackIndexFromTexCoords(coordsRectR, coordsRectB);
- SkASSERT(index0 == index1);
-
- int positionRectWidth = positionRect.width();
- int positionRectHeight = positionRect.height();
- SkASSERT(positionRectWidth == (coordsRectR - coordsRectL));
- SkASSERT(positionRectHeight == (coordsRectB - coordsRectT));
-
- // Clip position and texCoords to the clipRect
- unsigned int delta;
- delta = std::min(std::max(clipRect.fLeft - positionRect.fLeft, 0), positionRectWidth);
- coordsRectL += delta;
- positionRect.fLeft += delta;
-
- delta = std::min(std::max(clipRect.fTop - positionRect.fTop, 0), positionRectHeight);
- coordsRectT += delta;
- positionRect.fTop += delta;
-
- delta = std::min(std::max(positionRect.fRight - clipRect.fRight, 0), positionRectWidth);
- coordsRectR -= delta;
- positionRect.fRight -= delta;
-
- delta = std::min(std::max(positionRect.fBottom - clipRect.fBottom, 0), positionRectHeight);
- coordsRectB -= delta;
- positionRect.fBottom -= delta;
-
- // Repack texel coordinates and index
- std::tie(coordsRectL, coordsRectT) =
- GrDrawOpAtlas::PackIndexInTexCoords(coordsRectL, coordsRectT, index0);
- std::tie(coordsRectR, coordsRectB) =
- GrDrawOpAtlas::PackIndexInTexCoords(coordsRectR, coordsRectB, index1);
-
- // Set new positions and coords
- SkPoint* currPosition = reinterpret_cast<SkPoint*>(currVertex);
- currPosition->fX = positionRect.fLeft;
- currPosition->fY = positionRect.fTop;
- *(reinterpret_cast<SkColor*>(currVertex + sizeof(SkPoint))) = color;
- uint16_t* currCoords = reinterpret_cast<uint16_t*>(currVertex + coordOffset);
- currCoords[0] = coordsRectL;
- currCoords[1] = coordsRectT;
- currVertex += vertexStride;
-
- currPosition = reinterpret_cast<SkPoint*>(currVertex);
- currPosition->fX = positionRect.fLeft;
- currPosition->fY = positionRect.fBottom;
- *(reinterpret_cast<SkColor*>(currVertex + sizeof(SkPoint))) = color;
- currCoords = reinterpret_cast<uint16_t*>(currVertex + coordOffset);
- currCoords[0] = coordsRectL;
- currCoords[1] = coordsRectB;
- currVertex += vertexStride;
-
- currPosition = reinterpret_cast<SkPoint*>(currVertex);
- currPosition->fX = positionRect.fRight;
- currPosition->fY = positionRect.fTop;
- *(reinterpret_cast<SkColor*>(currVertex + sizeof(SkPoint))) = color;
- currCoords = reinterpret_cast<uint16_t*>(currVertex + coordOffset);
- currCoords[0] = coordsRectR;
- currCoords[1] = coordsRectT;
- currVertex += vertexStride;
-
- currPosition = reinterpret_cast<SkPoint*>(currVertex);
- currPosition->fX = positionRect.fRight;
- currPosition->fY = positionRect.fBottom;
- *(reinterpret_cast<SkColor*>(currVertex + sizeof(SkPoint))) = color;
- currCoords = reinterpret_cast<uint16_t*>(currVertex + coordOffset);
- currCoords[0] = coordsRectR;
- currCoords[1] = coordsRectB;
- currVertex += vertexStride;
- }
-
- blobVertices += 4 * vertexStride;
- }
-}
-
void GrAtlasTextOp::onPrepareDraws(Target* target) {
auto resourceProvider = target->resourceProvider();
@@ -381,8 +284,6 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
SkASSERT((int)subRun->vertexStride() == vertexStride);
subRun->prepareGrGlyphs(target->strikeCache());
- subRun->updateVerticesColorIfNeeded(args.fColor.toBytes_RGBA());
- subRun->translateVerticesIfNeeded(args.fDrawMatrix, args.fDrawOrigin);
// TODO4F: Preserve float colors
GrTextBlob::VertexRegenerator regenerator(resourceProvider, subRun,
@@ -390,7 +291,7 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
// Where the subRun begins and ends relative to totalGlyphsRegened.
int subRunBegin = totalGlyphsRegened;
- int subRunEnd = subRunBegin + subRun->fGlyphs.count();
+ int subRunEnd = subRunBegin + subRun->glyphCount();
// Draw all the glyphs in the subRun.
while (totalGlyphsRegened < subRunEnd) {
@@ -409,39 +310,10 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
// Update all the vertices for glyphsRegenerate glyphs.
if (glyphsRegenerated > 0) {
int quadBufferIndex = totalGlyphsRegened - quadBufferBegin;
- int subRunIndex = totalGlyphsRegened - subRunBegin;
auto regeneratedQuadBuffer =
SkTAddOffset<char>(vertices, subRun->quadOffset(quadBufferIndex));
- if (args.fClipRect.isEmpty()) {
- memcpy(regeneratedQuadBuffer,
- subRun->quadStart(subRunIndex),
- glyphsRegenerated * quadSize);
- } else {
- SkASSERT(!vmPerspective);
- clip_quads(args.fClipRect,
- regeneratedQuadBuffer,
- subRun->quadStart(subRunIndex),
- vertexStride,
- glyphsRegenerated);
- }
- if (fNeedsGlyphTransform && !args.fDrawMatrix.isIdentity()) {
- // We always do the distance field view matrix transformation after copying
- // rather than during blob vertex generation time in the blob as handling
- // successive arbitrary transformations would be complicated and accumulate
- // error.
- if (args.fDrawMatrix.hasPerspective()) {
- auto* pos = reinterpret_cast<SkPoint3*>(regeneratedQuadBuffer);
- SkMatrixPriv::MapHomogeneousPointsWithStride(
- args.fDrawMatrix, pos,
- vertexStride, pos,
- vertexStride,
- glyphsRegenerated * kVerticesPerGlyph);
- } else {
- auto* pos = reinterpret_cast<SkPoint*>(regeneratedQuadBuffer);
- SkMatrixPriv::MapPointsWithStride(args.fDrawMatrix, pos, vertexStride,
- glyphsRegenerated * kVerticesPerGlyph);
- }
- }
+ int subRunIndex = totalGlyphsRegened - subRunBegin;
+ args.fillVertexData(regeneratedQuadBuffer, subRunIndex, glyphsRegenerated);
}
totalGlyphsRegened += glyphsRegenerated;
@@ -619,7 +491,6 @@ GrOp::CombineResult GrAtlasTextOp::onCombineIfPossible(GrOp* t, GrRecordingConte
static const int kDistanceAdjustLumShift = 5;
// TODO trying to figure out why lcd is so whack
-// (see comments in GrTextContext::ComputeCanonicalColor)
GrGeometryProcessor* GrAtlasTextOp::setupDfProcessor(SkArenaAlloc* arena,
const GrShaderCaps& caps,
const GrSurfaceProxyView* views,
@@ -672,3 +543,78 @@ GrGeometryProcessor* GrAtlasTextOp::setupDfProcessor(SkArenaAlloc* arena,
}
}
+#if GR_TEST_UTILS
+std::unique_ptr<GrDrawOp> GrAtlasTextOp::CreateOpTestingOnly(GrRenderTargetContext* rtc,
+ const SkPaint& skPaint,
+ const SkFont& font,
+ const SkMatrixProvider& mtxProvider,
+ const char* text,
+ int x,
+ int y) {
+ static SkSurfaceProps surfaceProps(SkSurfaceProps::kLegacyFontHost_InitType);
+
+ size_t textLen = (int)strlen(text);
+
+ const SkMatrix& drawMatrix(mtxProvider.localToDevice());
+
+ auto drawOrigin = SkPoint::Make(x, y);
+ SkGlyphRunBuilder builder;
+ builder.drawTextUTF8(skPaint, font, text, textLen, drawOrigin);
+
+ auto glyphRunList = builder.useGlyphRunList();
+
+ const GrRecordingContextPriv& contextPriv = rtc->fContext->priv();
+ GrSDFTOptions SDFOptions = rtc->fContext->priv().SDFTOptions();
+
+ if (glyphRunList.empty()) {
+ return nullptr;
+ }
+ sk_sp<GrTextBlob> blob = GrTextBlob::Make(glyphRunList, drawMatrix);
+ SkGlyphRunListPainter* painter = &rtc->fGlyphPainter;
+ painter->processGlyphRunList(
+ glyphRunList, drawMatrix, surfaceProps,
+ contextPriv.caps()->shaderCaps()->supportsDistanceFieldText(),
+ SDFOptions, blob.get());
+
+ return blob->firstSubRun()->makeOp(mtxProvider,
+ drawOrigin,
+ SkIRect::MakeEmpty(),
+ skPaint,
+ surfaceProps,
+ rtc->textTarget());
+}
+
+GR_DRAW_OP_TEST_DEFINE(GrAtlasTextOp) {
+ // Setup dummy SkPaint / GrPaint / GrRenderTargetContext
+ auto rtc = GrRenderTargetContext::Make(
+ context, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kApprox, {1024, 1024});
+
+ SkSimpleMatrixProvider matrixProvider(GrTest::TestMatrixInvertible(random));
+
+ SkPaint skPaint;
+ skPaint.setColor(random->nextU());
+
+ SkFont font;
+ if (random->nextBool()) {
+ font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
+ } else {
+ font.setEdging(random->nextBool() ? SkFont::Edging::kAntiAlias : SkFont::Edging::kAlias);
+ }
+ font.setSubpixel(random->nextBool());
+
+ const char* text = "The quick brown fox jumps over the lazy dog.";
+
+ // create some random x/y offsets, including negative offsets
+ static const int kMaxTrans = 1024;
+ int xPos = (random->nextU() % 2) * 2 - 1;
+ int yPos = (random->nextU() % 2) * 2 - 1;
+ int xInt = (random->nextU() % kMaxTrans) * xPos;
+ int yInt = (random->nextU() % kMaxTrans) * yPos;
+
+ return GrAtlasTextOp::CreateOpTestingOnly(
+ rtc.get(), skPaint, font, matrixProvider, text, xInt, yInt);
+}
+
+#endif
+
+
diff --git a/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.h b/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.h
index 451de49aec4..e4e9af9b20a 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.h
+++ b/chromium/third_party/skia/src/gpu/ops/GrAtlasTextOp.h
@@ -12,7 +12,6 @@
#include "src/gpu/text/GrTextBlob.h"
class GrRecordingContext;
-class SkAtlasTextTarget;
class GrAtlasTextOp final : public GrMeshDrawOp {
public:
@@ -34,6 +33,8 @@ public:
SkPoint fDrawOrigin;
GrTextBlob::SubRun* fSubRunPtr;
SkPMColor4f fColor;
+
+ void fillVertexData(void* dst, int offset, int count) const;
};
static std::unique_ptr<GrAtlasTextOp> MakeBitmap(GrRecordingContext* context,
@@ -81,8 +82,15 @@ public:
MaskType maskType() const { return fMaskType; }
- void finalizeForTextTarget(uint32_t color, const GrCaps&);
- void executeForTextTarget(SkAtlasTextTarget*);
+#if GR_TEST_UTILS
+ static std::unique_ptr<GrDrawOp> CreateOpTestingOnly(GrRenderTargetContext* rtc,
+ const SkPaint& skPaint,
+ const SkFont& font,
+ const SkMatrixProvider& mtxProvider,
+ const char* text,
+ int x,
+ int y);
+#endif
private:
friend class GrOpMemoryPool; // for ctor
diff --git a/chromium/third_party/skia/src/gpu/ops/GrClearOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrClearOp.cpp
index 28529f47a0e..7f82206654c 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrClearOp.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrClearOp.cpp
@@ -14,52 +14,74 @@
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
-std::unique_ptr<GrClearOp> GrClearOp::Make(GrRecordingContext* context,
- const GrFixedClip& clip,
- const SkPMColor4f& color,
- GrSurfaceProxy* dstProxy) {
- const SkIRect rect = SkIRect::MakeSize(dstProxy->dimensions());
- if (clip.scissorEnabled() && !SkIRect::Intersects(clip.scissorRect(), rect)) {
- return nullptr;
- }
+static bool contains_scissor(const GrScissorState& a, const GrScissorState& b) {
+ return !a.enabled() || (b.enabled() && a.rect().contains(b.rect()));
+}
+std::unique_ptr<GrClearOp> GrClearOp::MakeColor(GrRecordingContext* context,
+ const GrScissorState& scissor,
+ const SkPMColor4f& color) {
GrOpMemoryPool* pool = context->priv().opMemoryPool();
-
- return pool->allocate<GrClearOp>(clip, color, dstProxy);
+ return pool->allocate<GrClearOp>(Buffer::kColor, scissor, color, false);
}
-std::unique_ptr<GrClearOp> GrClearOp::Make(GrRecordingContext* context,
- const SkIRect& rect,
- const SkPMColor4f& color,
- bool fullScreen) {
- SkASSERT(fullScreen || !rect.isEmpty());
-
+std::unique_ptr<GrClearOp> GrClearOp::MakeStencilClip(GrRecordingContext* context,
+ const GrScissorState& scissor,
+ bool insideMask) {
GrOpMemoryPool* pool = context->priv().opMemoryPool();
-
- return pool->allocate<GrClearOp>(rect, color, fullScreen);
+ return pool->allocate<GrClearOp>(Buffer::kStencilClip, scissor, SkPMColor4f(), insideMask);
}
-GrClearOp::GrClearOp(const GrFixedClip& clip, const SkPMColor4f& color, GrSurfaceProxy* proxy)
+GrClearOp::GrClearOp(Buffer buffer, const GrScissorState& scissor,
+ const SkPMColor4f& color, bool insideMask)
: INHERITED(ClassID())
- , fClip(clip)
- , fColor(color) {
- const SkIRect rtRect = SkIRect::MakeSize(proxy->dimensions());
- if (fClip.scissorEnabled()) {
- // Don't let scissors extend outside the RT. This may improve op combining.
- if (!fClip.intersect(rtRect)) {
- SkASSERT(0); // should be caught upstream
- fClip = GrFixedClip(SkIRect::MakeEmpty());
- }
+ , fScissor(scissor)
+ , fColor(color)
+ , fStencilInsideMask(insideMask)
+ , fBuffer(buffer) {
+ this->setBounds(SkRect::Make(scissor.rect()), HasAABloat::kNo, IsHairline::kNo);
+}
- if (proxy->isFunctionallyExact() && fClip.scissorRect() == rtRect) {
- fClip.disableScissor();
+GrOp::CombineResult GrClearOp::onCombineIfPossible(GrOp* t, GrRecordingContext::Arenas*,
+ const GrCaps& caps) {
+ GrClearOp* other = t->cast<GrClearOp>();
+
+ if (other->fBuffer == fBuffer) {
+ // This could be much more complicated. Currently we look at cases where the new clear
+ // contains the old clear, or when the new clear is a subset of the old clear and they clear
+ // to the same value (color or stencil mask depending on target).
+ if (contains_scissor(other->fScissor, fScissor)) {
+ fScissor = other->fScissor;
+ fColor = other->fColor;
+ fStencilInsideMask = other->fStencilInsideMask;
+ return CombineResult::kMerged;
+ } else if (other->fColor == fColor && other->fStencilInsideMask == fStencilInsideMask &&
+ contains_scissor(fScissor, other->fScissor)) {
+ return CombineResult::kMerged;
+ }
+ } else if (other->fScissor == fScissor) {
+ // When the scissors are the exact same but the buffers are different, we can combine and
+ // clear both stencil and clear together in onExecute().
+ if (other->fBuffer & Buffer::kColor) {
+ SkASSERT((fBuffer & Buffer::kStencilClip) && !(fBuffer & Buffer::kColor));
+ fColor = other->fColor;
+ }
+ if (other->fBuffer & Buffer::kStencilClip) {
+ SkASSERT(!(fBuffer & Buffer::kStencilClip) && (fBuffer & Buffer::kColor));
+ fStencilInsideMask = other->fStencilInsideMask;
}
+ fBuffer = Buffer::kBoth;
}
- this->setBounds(SkRect::Make(fClip.scissorEnabled() ? fClip.scissorRect() : rtRect),
- HasAABloat::kNo, IsHairline::kNo);
+ return CombineResult::kCannotCombine;
}
void GrClearOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
SkASSERT(state->opsRenderPass());
- state->opsRenderPass()->clear(fClip, fColor);
+ if (fBuffer & Buffer::kColor) {
+ state->opsRenderPass()->clear(fScissor, fColor);
+ }
+
+ if (fBuffer & Buffer::kStencilClip) {
+ state->opsRenderPass()->clearStencilClip(fScissor, fStencilInsideMask);
+ }
}
diff --git a/chromium/third_party/skia/src/gpu/ops/GrClearOp.h b/chromium/third_party/skia/src/gpu/ops/GrClearOp.h
index fbac02f9a74..5eaff4bb19c 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrClearOp.h
+++ b/chromium/third_party/skia/src/gpu/ops/GrClearOp.h
@@ -8,7 +8,8 @@
#ifndef GrClearOp_DEFINED
#define GrClearOp_DEFINED
-#include "src/gpu/GrFixedClip.h"
+#include "include/gpu/GrTypes.h"
+#include "src/gpu/GrScissorState.h"
#include "src/gpu/ops/GrOp.h"
class GrOpFlushState;
@@ -18,15 +19,14 @@ class GrClearOp final : public GrOp {
public:
DEFINE_OP_CLASS_ID
- static std::unique_ptr<GrClearOp> Make(GrRecordingContext* context,
- const GrFixedClip& clip,
- const SkPMColor4f& color,
- GrSurfaceProxy* dstProxy);
+ // A fullscreen or scissored clear, depending on the clip and proxy dimensions
+ static std::unique_ptr<GrClearOp> MakeColor(GrRecordingContext* context,
+ const GrScissorState& scissor,
+ const SkPMColor4f& color);
- static std::unique_ptr<GrClearOp> Make(GrRecordingContext* context,
- const SkIRect& rect,
- const SkPMColor4f& color,
- bool fullScreen);
+ static std::unique_ptr<GrClearOp> MakeStencilClip(GrRecordingContext* context,
+ const GrScissorState& scissor,
+ bool insideMask);
const char* name() const override { return "Clear"; }
@@ -35,8 +35,8 @@ public:
SkString string;
string.append(INHERITED::dumpInfo());
string.appendf("Scissor [ ");
- if (fClip.scissorEnabled()) {
- const SkIRect& r = fClip.scissorRect();
+ if (fScissor.enabled()) {
+ const SkIRect& r = fScissor.rect();
string.appendf("L: %d, T: %d, R: %d, B: %d", r.fLeft, r.fTop, r.fRight, r.fBottom);
} else {
string.append("disabled");
@@ -46,64 +46,37 @@ public:
}
#endif
- const SkPMColor4f& color() const { return fColor; }
- void setColor(const SkPMColor4f& color) { fColor = color; }
-
private:
friend class GrOpMemoryPool; // for ctors
- GrClearOp(const GrFixedClip& clip, const SkPMColor4f& color, GrSurfaceProxy* proxy);
+ enum class Buffer {
+ kColor = 0b01,
+ kStencilClip = 0b10,
- GrClearOp(const SkIRect& rect, const SkPMColor4f& color, bool fullScreen)
- : INHERITED(ClassID())
- , fClip(GrFixedClip(rect))
- , fColor(color) {
+ kBoth = 0b11,
+ };
+ GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(Buffer);
- if (fullScreen) {
- fClip.disableScissor();
- }
- this->setBounds(SkRect::Make(rect), HasAABloat::kNo, IsHairline::kNo);
- }
+ GrClearOp(Buffer buffer, const GrScissorState& scissor, const SkPMColor4f& color, bool stencil);
CombineResult onCombineIfPossible(GrOp* t, GrRecordingContext::Arenas*,
- const GrCaps& caps) override {
- // This could be much more complicated. Currently we look at cases where the new clear
- // contains the old clear, or when the new clear is a subset of the old clear and is the
- // same color.
- GrClearOp* cb = t->cast<GrClearOp>();
- if (fClip.windowRectsState() != cb->fClip.windowRectsState()) {
- return CombineResult::kCannotCombine;
- }
- if (cb->contains(this)) {
- fClip = cb->fClip;
- fColor = cb->fColor;
- return CombineResult::kMerged;
- } else if (cb->fColor == fColor && this->contains(cb)) {
- return CombineResult::kMerged;
- }
- return CombineResult::kCannotCombine;
- }
-
- bool contains(const GrClearOp* that) const {
- // The constructor ensures that scissor gets disabled on any clip that fills the entire RT.
- return !fClip.scissorEnabled() ||
- (that->fClip.scissorEnabled() &&
- fClip.scissorRect().contains(that->fClip.scissorRect()));
- }
+ const GrCaps& caps) override;
- void onPrePrepare(GrRecordingContext*,
- const GrSurfaceProxyView* writeView,
- GrAppliedClip*,
+ void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView* writeView, GrAppliedClip*,
const GrXferProcessor::DstProxyView&) override {}
void onPrepare(GrOpFlushState*) override {}
void onExecute(GrOpFlushState* state, const SkRect& chainBounds) override;
- GrFixedClip fClip;
- SkPMColor4f fColor;
+ GrScissorState fScissor;
+ SkPMColor4f fColor;
+ bool fStencilInsideMask;
+ Buffer fBuffer;
typedef GrOp INHERITED;
};
+GR_MAKE_BITFIELD_CLASS_OPS(GrClearOp::Buffer)
+
#endif
diff --git a/chromium/third_party/skia/src/gpu/ops/GrClearStencilClipOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrClearStencilClipOp.cpp
deleted file mode 100644
index 7ca4063b967..00000000000
--- a/chromium/third_party/skia/src/gpu/ops/GrClearStencilClipOp.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "src/gpu/ops/GrClearStencilClipOp.h"
-
-#include "include/private/GrRecordingContext.h"
-#include "src/gpu/GrMemoryPool.h"
-#include "src/gpu/GrOpFlushState.h"
-#include "src/gpu/GrOpsRenderPass.h"
-#include "src/gpu/GrRecordingContextPriv.h"
-
-std::unique_ptr<GrOp> GrClearStencilClipOp::Make(GrRecordingContext* context,
- const GrFixedClip& clip,
- bool insideStencilMask,
- GrRenderTargetProxy* proxy) {
- GrOpMemoryPool* pool = context->priv().opMemoryPool();
-
- return pool->allocate<GrClearStencilClipOp>(clip, insideStencilMask, proxy);
-}
-
-void GrClearStencilClipOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
- SkASSERT(state->opsRenderPass());
- state->opsRenderPass()->clearStencilClip(fClip, fInsideStencilMask);
-}
diff --git a/chromium/third_party/skia/src/gpu/ops/GrClearStencilClipOp.h b/chromium/third_party/skia/src/gpu/ops/GrClearStencilClipOp.h
deleted file mode 100644
index 68f825a7e40..00000000000
--- a/chromium/third_party/skia/src/gpu/ops/GrClearStencilClipOp.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrClearStencilClipOp_DEFINED
-#define GrClearStencilClipOp_DEFINED
-
-#include "src/gpu/GrFixedClip.h"
-#include "src/gpu/GrRenderTargetProxy.h"
-#include "src/gpu/ops/GrOp.h"
-
-class GrOpFlushState;
-class GrRecordingContext;
-
-class GrClearStencilClipOp final : public GrOp {
-public:
- DEFINE_OP_CLASS_ID
-
- static std::unique_ptr<GrOp> Make(GrRecordingContext* context,
- const GrFixedClip& clip,
- bool insideStencilMask,
- GrRenderTargetProxy* proxy);
-
- const char* name() const override { return "ClearStencilClip"; }
-
-#ifdef SK_DEBUG
- SkString dumpInfo() const override {
- SkString string("Scissor [");
- if (fClip.scissorEnabled()) {
- const SkIRect& r = fClip.scissorRect();
- string.appendf("L: %d, T: %d, R: %d, B: %d", r.fLeft, r.fTop, r.fRight, r.fBottom);
- } else {
- string.append("disabled");
- }
- string.appendf("], insideMask: %s\n", fInsideStencilMask ? "true" : "false");
- string.append(INHERITED::dumpInfo());
- return string;
- }
-#endif
-
-private:
- friend class GrOpMemoryPool; // for ctor
-
- GrClearStencilClipOp(const GrFixedClip& clip, bool insideStencilMask,
- GrRenderTargetProxy* proxy)
- : INHERITED(ClassID())
- , fClip(clip)
- , fInsideStencilMask(insideStencilMask) {
- const SkRect& bounds =
- fClip.scissorEnabled() ? SkRect::Make(fClip.scissorRect()) : proxy->getBoundsRect();
- this->setBounds(bounds, HasAABloat::kNo, IsHairline::kNo);
- }
-
- void onPrePrepare(GrRecordingContext*,
- const GrSurfaceProxyView* writeView,
- GrAppliedClip*,
- const GrXferProcessor::DstProxyView&) override {}
-
- void onPrepare(GrOpFlushState*) override {}
-
- void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
-
- const GrFixedClip fClip;
- const bool fInsideStencilMask;
-
- typedef GrOp INHERITED;
-};
-
-#endif
diff --git a/chromium/third_party/skia/src/gpu/ops/GrDashLinePathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrDashLinePathRenderer.cpp
index 96fc06cde17..e5cf9e4038b 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrDashLinePathRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrDashLinePathRenderer.cpp
@@ -53,6 +53,6 @@ bool GrDashLinePathRenderer::onDrawPath(const DrawPathArgs& args) {
if (!op) {
return false;
}
- args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+ args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
return true;
}
diff --git a/chromium/third_party/skia/src/gpu/ops/GrDashOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrDashOp.cpp
index 7e1b63fdc82..5ee04a42a2a 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrDashOp.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrDashOp.cpp
@@ -167,9 +167,9 @@ static void setup_dashed_rect(const SkRect& rect,
// 'dashRect' gets interpolated over the rendered 'rect'. For y we want the perpendicular signed
// distance from the stroke center line in device space. 'perpScale' is the scale factor applied
// to the y dimension of 'rect' isolated from 'matrix'.
- SkScalar halfDevRectHeight = rect.height()*perpScale/2.f;
+ SkScalar halfDevRectHeight = rect.height() * perpScale / 2.f;
SkRect dashRect = { offset - bloatX, -halfDevRectHeight,
- offset + len + bloatX, halfDevRectHeight};
+ offset + len + bloatX, halfDevRectHeight };
if (kRound_DashCap == cap) {
SkScalar radius = SkScalarHalf(strokeWidth) - 0.5f;
@@ -311,9 +311,8 @@ private:
SkMatrix& combinedMatrix = fLines[0].fSrcRotInv;
combinedMatrix.postConcat(geometry.fViewMatrix);
- IsHairline zeroArea = geometry.fSrcStrokeWidth ? IsHairline::kNo
- : IsHairline::kYes;
- HasAABloat aaBloat = (aaMode == AAMode::kNone) ? HasAABloat ::kNo : HasAABloat::kYes;
+ IsHairline zeroArea = geometry.fSrcStrokeWidth ? IsHairline::kNo : IsHairline::kYes;
+ HasAABloat aaBloat = (aaMode == AAMode::kNone) ? HasAABloat::kNo : HasAABloat::kYes;
this->setTransformedBounds(bounds, combinedMatrix, aaBloat, zeroArea);
}
@@ -418,18 +417,15 @@ private:
bool hasCap = SkPaint::kButt_Cap != cap;
- // We always want to at least stroke out half a pixel on each side in device space
- // so 0.5f / perpScale gives us this min in src space
- SkScalar halfSrcStroke =
- std::max(args.fSrcStrokeWidth * 0.5f, 0.5f / args.fPerpendicularScale);
-
- SkScalar strokeAdj;
- if (!hasCap) {
- strokeAdj = 0.f;
- } else {
- strokeAdj = halfSrcStroke;
+ SkScalar halfSrcStroke = args.fSrcStrokeWidth * 0.5f;
+ if (halfSrcStroke == 0.0f || this->aaMode() != AAMode::kCoverageWithMSAA) {
+ // In the non-MSAA case, we always want to at least stroke out half a pixel on each
+ // side in device space. 0.5f / fPerpendicularScale gives us this min in src space.
+ // This is also necessary when the stroke width is zero, to allow hairlines to draw.
+ halfSrcStroke = std::max(halfSrcStroke, 0.5f / args.fPerpendicularScale);
}
+ SkScalar strokeAdj = hasCap ? halfSrcStroke : 0.0f;
SkScalar startAdj = 0;
bool lineDone = false;
@@ -536,14 +532,20 @@ private:
}
SkScalar startOffset = devIntervals[1] * 0.5f + devPhase;
- // For EdgeAA, we bloat in X & Y for both square and round caps.
- // For MSAA, we don't bloat at all for square caps, and bloat in Y only for round caps.
- SkScalar devBloatX = this->aaMode() == AAMode::kCoverage ? 0.5f : 0.0f;
- SkScalar devBloatY;
- if (SkPaint::kRound_Cap == cap && this->aaMode() == AAMode::kCoverageWithMSAA) {
- devBloatY = 0.5f;
- } else {
- devBloatY = devBloatX;
+ SkScalar devBloatX = 0.0f;
+ SkScalar devBloatY = 0.0f;
+ switch (this->aaMode()) {
+ case AAMode::kNone:
+ break;
+ case AAMode::kCoverage:
+ // For EdgeAA, we bloat in X & Y for both square and round caps.
+ devBloatX = 0.5f;
+ devBloatY = 0.5f;
+ break;
+ case AAMode::kCoverageWithMSAA:
+ // For MSAA, we only bloat in Y for round caps.
+ devBloatY = (cap == SkPaint::kRound_Cap) ? 0.5f : 0.0f;
+ break;
}
SkScalar bloatX = devBloatX / args.fParallelScale;
@@ -782,7 +784,7 @@ std::unique_ptr<GrDrawOp> GrDashOp::MakeDashLineOp(GrRecordingContext* context,
SkScalar strokeWidth = lineData.fSrcStrokeWidth * lineData.fPerpendicularScale;
if (SkPaint::kSquare_Cap == cap && 0 != lineData.fSrcStrokeWidth) {
- // add cap to on interveal and remove from off interval
+ // add cap to on interval and remove from off interval
offInterval -= strokeWidth;
}
@@ -874,14 +876,19 @@ public:
private:
UniformHandle fParamUniform;
UniformHandle fColorUniform;
+ UniformHandle fLocalMatrixUniform;
+
+ SkMatrix fLocalMatrix;
SkPMColor4f fColor;
SkScalar fPrevRadius;
SkScalar fPrevCenterX;
SkScalar fPrevIntervalLength;
+
typedef GrGLSLGeometryProcessor INHERITED;
};
GLDashingCircleEffect::GLDashingCircleEffect() {
+ fLocalMatrix = SkMatrix::InvalidMatrix();
fColor = SK_PMColor4fILLEGAL;
fPrevRadius = SK_ScalarMin;
fPrevCenterX = SK_ScalarMin;
@@ -913,14 +920,10 @@ void GLDashingCircleEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
// Setup position
this->writeOutputPosition(vertBuilder, gpArgs, dce.fInPosition.name());
-
- // emit transforms
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- dce.fInPosition.asShaderVar(),
- dce.localMatrix(),
- args.fFPCoordTransformHandler);
+ if (dce.usesLocalCoords()) {
+ this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, dce.fInPosition.asShaderVar(),
+ dce.localMatrix(), &fLocalMatrixUniform);
+ }
// transforms all points so that we can compare them to our test circle
fragBuilder->codeAppendf("half xShifted = half(%s.x - floor(%s.x / %s.z) * %s.z);",
@@ -949,7 +952,8 @@ void GLDashingCircleEffect::setData(const GrGLSLProgramDataManager& pdman,
pdman.set4fv(fColorUniform, 1, dce.color().vec());
fColor = dce.color();
}
- this->setTransformDataHelper(dce.localMatrix(), pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
+ this->setTransform(pdman, fLocalMatrixUniform, dce.localMatrix(), &fLocalMatrix);
}
void GLDashingCircleEffect::GenKey(const GrGeometryProcessor& gp,
@@ -957,8 +961,9 @@ void GLDashingCircleEffect::GenKey(const GrGeometryProcessor& gp,
GrProcessorKeyBuilder* b) {
const DashingCircleEffect& dce = gp.cast<DashingCircleEffect>();
uint32_t key = 0;
- key |= dce.usesLocalCoords() && dce.localMatrix().hasPerspective() ? 0x1 : 0x0;
+ key |= dce.usesLocalCoords() ? 0x1 : 0x0;
key |= static_cast<uint32_t>(dce.aaMode()) << 1;
+ key |= ComputeMatrixKey(dce.localMatrix()) << 3;
b->add32(key);
}
@@ -1084,6 +1089,10 @@ public:
private:
SkPMColor4f fColor;
UniformHandle fColorUniform;
+
+ SkMatrix fLocalMatrix;
+ UniformHandle fLocalMatrixUniform;
+
typedef GrGLSLGeometryProcessor INHERITED;
};
@@ -1116,14 +1125,10 @@ void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
// Setup position
this->writeOutputPosition(vertBuilder, gpArgs, de.fInPosition.name());
-
- // emit transforms
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- de.fInPosition.asShaderVar(),
- de.localMatrix(),
- args.fFPCoordTransformHandler);
+ if (de.usesLocalCoords()) {
+ this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, de.fInPosition.asShaderVar(),
+ de.localMatrix(), &fLocalMatrixUniform);
+ }
// transforms all points so that we can compare them to our test rect
fragBuilder->codeAppendf("half xShifted = half(%s.x - floor(%s.x / %s.z) * %s.z);",
@@ -1176,7 +1181,8 @@ void GLDashingLineEffect::setData(const GrGLSLProgramDataManager& pdman,
pdman.set4fv(fColorUniform, 1, de.color().vec());
fColor = de.color();
}
- this->setTransformDataHelper(de.localMatrix(), pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
+ this->setTransform(pdman, fLocalMatrixUniform, de.localMatrix(), &fLocalMatrix);
}
void GLDashingLineEffect::GenKey(const GrGeometryProcessor& gp,
@@ -1184,8 +1190,9 @@ void GLDashingLineEffect::GenKey(const GrGeometryProcessor& gp,
GrProcessorKeyBuilder* b) {
const DashingLineEffect& de = gp.cast<DashingLineEffect>();
uint32_t key = 0;
- key |= de.usesLocalCoords() && de.localMatrix().hasPerspective() ? 0x1 : 0x0;
- key |= static_cast<int>(de.aaMode()) << 8;
+ key |= de.usesLocalCoords() ? 0x1 : 0x0;
+ key |= static_cast<int>(de.aaMode()) << 1;
+ key |= ComputeMatrixKey(de.localMatrix()) << 3;
b->add32(key);
}
diff --git a/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.cpp
index 7f4f634b33e..88175db9d20 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.cpp
@@ -14,9 +14,9 @@
#include "src/core/SkTraceEvent.h"
#include "src/gpu/GrAuditTrail.h"
#include "src/gpu/GrCaps.h"
+#include "src/gpu/GrClip.h"
#include "src/gpu/GrDefaultGeoProcFactory.h"
#include "src/gpu/GrDrawOpTest.h"
-#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrRenderTargetContextPriv.h"
@@ -537,7 +537,7 @@ bool GrDefaultPathRenderer::internalDrawPath(GrRenderTargetContext* renderTarget
GrPaint&& paint,
GrAAType aaType,
const GrUserStencilSettings& userStencilSettings,
- const GrClip& clip,
+ const GrClip* clip,
const SkMatrix& viewMatrix,
const GrStyledShape& shape,
bool stencilOnly) {
@@ -583,7 +583,7 @@ bool GrDefaultPathRenderer::internalDrawPath(GrRenderTargetContext* renderTarget
switch (path.getFillType()) {
case SkPathFillType::kInverseEvenOdd:
reverse = true;
- // fallthrough
+ [[fallthrough]];
case SkPathFillType::kEvenOdd:
passes[0] = &gEOStencilPass;
if (stencilOnly) {
@@ -602,7 +602,7 @@ bool GrDefaultPathRenderer::internalDrawPath(GrRenderTargetContext* renderTarget
case SkPathFillType::kInverseWinding:
reverse = true;
- // fallthrough
+ [[fallthrough]];
case SkPathFillType::kWinding:
passes[0] = &gWindStencilPass;
passCount = 2;
@@ -705,7 +705,7 @@ bool GrDefaultPathRenderer::onDrawPath(const DrawPathArgs& args) {
return this->internalDrawPath(
args.fRenderTargetContext, std::move(args.fPaint), aaType, *args.fUserStencilSettings,
- *args.fClip, *args.fViewMatrix, *args.fShape, false);
+ args.fClip, *args.fViewMatrix, *args.fShape, false);
}
void GrDefaultPathRenderer::onStencilPath(const StencilPathArgs& args) {
@@ -720,7 +720,7 @@ void GrDefaultPathRenderer::onStencilPath(const StencilPathArgs& args) {
this->internalDrawPath(
args.fRenderTargetContext, std::move(paint), aaType, GrUserStencilSettings::kUnused,
- *args.fClip, *args.fViewMatrix, *args.fShape, true);
+ args.fClip, *args.fViewMatrix, *args.fShape, true);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.h b/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.h
index e709964f690..7b0a32d1128 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.h
+++ b/chromium/third_party/skia/src/gpu/ops/GrDefaultPathRenderer.h
@@ -35,7 +35,7 @@ private:
GrPaint&&,
GrAAType,
const GrUserStencilSettings&,
- const GrClip&,
+ const GrClip*,
const SkMatrix& viewMatrix,
const GrStyledShape&,
bool stencilOnly);
diff --git a/chromium/third_party/skia/src/gpu/ops/GrDrawVerticesOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrDrawVerticesOp.cpp
index f9a42f35cfe..111cc7e7c09 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrDrawVerticesOp.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrDrawVerticesOp.cpp
@@ -58,21 +58,29 @@ static GrSLType SkVerticesAttributeToGrSLType(const SkVertices::Attribute& a) {
SkUNREACHABLE;
}
+static bool AttributeUsesViewMatrix(const SkVertices::Attribute& attr) {
+ return (attr.fMarkerID == 0) && (attr.fUsage == SkVertices::Attribute::Usage::kVector ||
+ attr.fUsage == SkVertices::Attribute::Usage::kNormalVector ||
+ attr.fUsage == SkVertices::Attribute::Usage::kPosition);
+}
+
// Container for a collection of [uint32_t, Matrix] pairs. For a GrDrawVerticesOp whose custom
// attributes reference some set of IDs, this stores the actual values of those matrices,
// at the time the Op is created.
class MarkedMatrices {
public:
- // For each ID required by 'info', fetch the value of that matrix from 'matrixProvider'
+ // For each ID required by 'info', fetch the value of that matrix from 'matrixProvider'.
+ // For vectors/normals/positions, we let ID 0 refer to the canvas CTM matrix.
void gather(const SkVerticesPriv& info, const SkMatrixProvider& matrixProvider) {
for (int i = 0; i < info.attributeCount(); ++i) {
- if (uint32_t id = info.attributes()[i].fMarkerID) {
+ uint32_t id = info.attributes()[i].fMarkerID;
+ if (id != 0 || AttributeUsesViewMatrix(info.attributes()[i])) {
if (std::none_of(fMatrices.begin(), fMatrices.end(),
[id](const auto& m) { return m.first == id; })) {
SkM44 matrix;
- // SkCanvas should guarantee that this succeeds
+ // SkCanvas should guarantee that this succeeds.
SkAssertResult(matrixProvider.getLocalToMarker(id, &matrix));
- fMatrices.push_back({id, matrix});
+ fMatrices.emplace_back(id, matrix);
}
}
}
@@ -177,12 +185,7 @@ public:
// emit transforms using either explicit local coords or positions
const auto& coordsAttr = gp.localCoordsAttr().isInitialized() ? gp.localCoordsAttr()
: gp.positionAttr();
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- coordsAttr.asShaderVar(),
- SkMatrix::I(),
- args.fFPCoordTransformHandler);
+ gpArgs->fLocalCoordVar = coordsAttr.asShaderVar();
// Add varyings and globals for all custom attributes
using Usage = SkVertices::Attribute::Usage;
@@ -195,7 +198,7 @@ public:
SkString varyingIn(attr.name());
UniformHandle matrixHandle;
- if (customAttr.fMarkerID) {
+ if (customAttr.fMarkerID || AttributeUsesViewMatrix(customAttr)) {
bool normal = customAttr.fUsage == Usage::kNormalVector;
for (const MarkedUniform& matrixUni : fCustomMatrixUniforms) {
if (matrixUni.fID == customAttr.fMarkerID && matrixUni.fNormal == normal) {
@@ -214,10 +217,6 @@ public:
}
}
- // TODO: For now, vectors/normals/positions with a 0 markerID get no transform.
- // Those should use localToDevice instead. That means we need to change batching
- // logic and then guarantee that we have the view matrix as a uniform here.
-
switch (customAttr.fUsage) {
case Usage::kRaw:
break;
@@ -302,7 +301,7 @@ public:
const VerticesGP& vgp = gp.cast<VerticesGP>();
uint32_t key = 0;
key |= (vgp.fColorArrayType == ColorArrayType::kSkColor) ? 0x1 : 0;
- key |= ComputePosKey(vgp.viewMatrix()) << 20;
+ key |= ComputeMatrixKey(vgp.viewMatrix()) << 20;
b->add32(key);
b->add32(GrColorSpaceXform::XformKey(vgp.fColorSpaceXform.get()));
@@ -319,19 +318,14 @@ public:
const CoordTransformRange& transformRange) override {
const VerticesGP& vgp = gp.cast<VerticesGP>();
- if (!vgp.viewMatrix().isIdentity() &&
- !SkMatrixPriv::CheapEqual(fViewMatrix, vgp.viewMatrix())) {
- fViewMatrix = vgp.viewMatrix();
- pdman.setSkMatrix(fViewMatrixUniform, fViewMatrix);
- }
+ this->setTransform(pdman, fViewMatrixUniform, vgp.viewMatrix(), &fViewMatrix);
+ this->setTransformDataHelper(pdman, transformRange);
if (!vgp.colorAttr().isInitialized() && vgp.color() != fColor) {
pdman.set4fv(fColorUniform, 1, vgp.color().vec());
fColor = vgp.color();
}
- this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
-
fColorSpaceHelper.setData(pdman, vgp.fColorSpaceXform.get());
for (const auto& matrixUni : fCustomMatrixUniforms) {
diff --git a/chromium/third_party/skia/src/gpu/ops/GrFillRRectOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrFillRRectOp.cpp
index 76122e576ce..630955fe042 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrFillRRectOp.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrFillRRectOp.cpp
@@ -680,15 +680,13 @@ class FillRRectOp::Processor::CoverageImpl : public GrGLSLGeometryProcessor {
v->codeAppend("float2 aa_outset = aa_bloat_direction.xy * aa_bloatradius;");
v->codeAppend("float2 vertexpos = corner + radius_outset * radii + aa_outset;");
- // Emit transforms.
+ // Write positions
GrShaderVar localCoord("", kFloat2_GrSLType);
if (proc.fFlags & ProcessorFlags::kHasLocalCoords) {
v->codeAppend("float2 localcoord = (local_rect.xy * (1 - vertexpos) + "
"local_rect.zw * (1 + vertexpos)) * .5;");
- localCoord.set(kFloat2_GrSLType, "localcoord");
+ gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord");
}
- this->emitTransforms(v, varyings, args.fUniformHandler, localCoord,
- args.fFPCoordTransformHandler);
// Transform to device space.
SkASSERT(!(proc.fFlags & ProcessorFlags::kHasPerspective));
@@ -743,7 +741,7 @@ class FillRRectOp::Processor::CoverageImpl : public GrGLSLGeometryProcessor {
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
const CoordTransformRange& transformRange) override {
- this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
}
};
@@ -781,15 +779,13 @@ class FillRRectOp::Processor::MSAAImpl : public GrGLSLGeometryProcessor {
// [-1,-1,+1,+1] space.
v->codeAppend("float2 vertexpos = corner + radius_outset * radii;");
- // Emit transforms.
+ // Write positions
GrShaderVar localCoord("", kFloat2_GrSLType);
if (hasLocalCoords) {
v->codeAppend("float2 localcoord = (local_rect.xy * (1 - vertexpos) + "
"local_rect.zw * (1 + vertexpos)) * .5;");
- localCoord.set(kFloat2_GrSLType, "localcoord");
+ gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord");
}
- this->emitTransforms(v, varyings, args.fUniformHandler, localCoord,
- args.fFPCoordTransformHandler);
// Transform to device space.
if (!hasPerspective) {
@@ -849,7 +845,7 @@ class FillRRectOp::Processor::MSAAImpl : public GrGLSLGeometryProcessor {
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
const CoordTransformRange& transformRange) override {
- this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
}
};
diff --git a/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.cpp
index 9e27f9dfe77..5d20400675b 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.cpp
@@ -250,7 +250,7 @@ private:
SkArenaAlloc* arena = context->priv().recordTimeAllocator();
// This is equivalent to a GrOpFlushState::detachAppliedClip
- GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
+ GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled();
this->createProgramInfo(context->priv().caps(), arena, writeView,
std::move(appliedClip), dstProxyView);
@@ -524,7 +524,7 @@ std::unique_ptr<GrDrawOp> GrFillRectOp::MakeOp(GrRecordingContext* context,
}
void GrFillRectOp::AddFillRectOps(GrRenderTargetContext* rtc,
- const GrClip& clip,
+ const GrClip* clip,
GrRecordingContext* context,
GrPaint&& paint,
GrAAType aaType,
diff --git a/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.h b/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.h
index 947ee7c8a3f..4a8f211ee05 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.h
+++ b/chromium/third_party/skia/src/gpu/ops/GrFillRectOp.h
@@ -49,7 +49,7 @@ public:
// Bulk API for drawing quads with a single op
// TODO(michaelludwig) - remove if the bulk API is not useful for SkiaRenderer
static void AddFillRectOps(GrRenderTargetContext*,
- const GrClip& clip,
+ const GrClip* clip,
GrRecordingContext*,
GrPaint&&,
GrAAType,
diff --git a/chromium/third_party/skia/src/gpu/ops/GrLatticeOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrLatticeOp.cpp
index 7efe3a322fa..fe9983fb51d 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrLatticeOp.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrLatticeOp.cpp
@@ -49,7 +49,7 @@ public:
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
const CoordTransformRange& transformRange) override {
const auto& latticeGP = proc.cast<LatticeGP>();
- this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
fColorSpaceXformHelper.setData(pdman, latticeGP.fColorSpaceXform.get());
}
@@ -62,11 +62,8 @@ public:
args.fVaryingHandler->emitAttributes(latticeGP);
this->writeOutputPosition(args.fVertBuilder, gpArgs, latticeGP.fInPosition.name());
- this->emitTransforms(args.fVertBuilder,
- args.fVaryingHandler,
- args.fUniformHandler,
- latticeGP.fInTextureCoords.asShaderVar(),
- args.fFPCoordTransformHandler);
+ gpArgs->fLocalCoordVar = latticeGP.fInTextureCoords.asShaderVar();
+
args.fFragBuilder->codeAppend("float2 textureCoords;");
args.fVaryingHandler->addPassThroughAttribute(latticeGP.fInTextureCoords,
"textureCoords");
diff --git a/chromium/third_party/skia/src/gpu/ops/GrMeshDrawOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrMeshDrawOp.cpp
index f5a8c040477..809620b91b7 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrMeshDrawOp.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrMeshDrawOp.cpp
@@ -33,7 +33,7 @@ void GrMeshDrawOp::onPrePrepareDraws(GrRecordingContext* context,
SkArenaAlloc* arena = context->priv().recordTimeAllocator();
// This is equivalent to a GrOpFlushState::detachAppliedClip
- GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
+ GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled();
this->createProgramInfo(context->priv().caps(), arena, writeView,
std::move(appliedClip), dstProxyView);
diff --git a/chromium/third_party/skia/src/gpu/ops/GrOvalOpFactory.cpp b/chromium/third_party/skia/src/gpu/ops/GrOvalOpFactory.cpp
index d85755781bf..f720f638607 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrOvalOpFactory.cpp
@@ -155,14 +155,9 @@ private:
// Setup position
this->writeOutputPosition(vertBuilder, gpArgs, cgp.fInPosition.name());
-
- // emit transforms
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- cgp.fInPosition.asShaderVar(),
- cgp.fLocalMatrix,
- args.fFPCoordTransformHandler);
+ this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
+ cgp.fInPosition.asShaderVar(), cgp.fLocalMatrix,
+ &fLocalMatrixUniform);
fragBuilder->codeAppend("float d = length(circleEdge.xy);");
fragBuilder->codeAppend("half distanceToOuterEdge = half(circleEdge.z * (1.0 - d));");
@@ -210,24 +205,29 @@ private:
const GrShaderCaps&,
GrProcessorKeyBuilder* b) {
const CircleGeometryProcessor& cgp = gp.cast<CircleGeometryProcessor>();
- uint16_t key;
+ uint32_t key;
key = cgp.fStroke ? 0x01 : 0x0;
- key |= cgp.fLocalMatrix.hasPerspective() ? 0x02 : 0x0;
- key |= cgp.fInClipPlane.isInitialized() ? 0x04 : 0x0;
- key |= cgp.fInIsectPlane.isInitialized() ? 0x08 : 0x0;
- key |= cgp.fInUnionPlane.isInitialized() ? 0x10 : 0x0;
- key |= cgp.fInRoundCapCenters.isInitialized() ? 0x20 : 0x0;
+ key |= cgp.fInClipPlane.isInitialized() ? 0x02 : 0x0;
+ key |= cgp.fInIsectPlane.isInitialized() ? 0x04 : 0x0;
+ key |= cgp.fInUnionPlane.isInitialized() ? 0x08 : 0x0;
+ key |= cgp.fInRoundCapCenters.isInitialized() ? 0x10 : 0x0;
+ key |= (ComputeMatrixKey(cgp.fLocalMatrix) << 16);
b->add32(key);
}
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
const CoordTransformRange& transformRange) override {
- this->setTransformDataHelper(primProc.cast<CircleGeometryProcessor>().fLocalMatrix,
- pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
+ this->setTransform(pdman, fLocalMatrixUniform,
+ primProc.cast<CircleGeometryProcessor>().fLocalMatrix,
+ &fLocalMatrix);
}
private:
typedef GrGLSLGeometryProcessor INHERITED;
+
+ SkMatrix fLocalMatrix = SkMatrix::InvalidMatrix();
+ UniformHandle fLocalMatrixUniform;
};
SkMatrix fLocalMatrix;
@@ -389,14 +389,10 @@ private:
// Setup position
this->writeOutputPosition(vertBuilder, gpArgs, bcscgp.fInPosition.name());
+ this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
+ bcscgp.fInPosition.asShaderVar(), bcscgp.fLocalMatrix,
+ &fLocalMatrixUniform);
- // emit transforms
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- bcscgp.fInPosition.asShaderVar(),
- bcscgp.fLocalMatrix,
- args.fFPCoordTransformHandler);
GrShaderVar fnArgs[] = {
GrShaderVar("angleToEdge", kFloat_GrSLType),
GrShaderVar("diameter", kFloat_GrSLType),
@@ -477,18 +473,22 @@ private:
GrProcessorKeyBuilder* b) {
const ButtCapDashedCircleGeometryProcessor& bcscgp =
gp.cast<ButtCapDashedCircleGeometryProcessor>();
- b->add32(bcscgp.fLocalMatrix.hasPerspective());
+ b->add32(ComputeMatrixKey(bcscgp.fLocalMatrix));
}
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
const CoordTransformRange& transformRange) override {
- this->setTransformDataHelper(
- primProc.cast<ButtCapDashedCircleGeometryProcessor>().fLocalMatrix, pdman,
- transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
+ this->setTransform(pdman, fLocalMatrixUniform,
+ primProc.cast<ButtCapDashedCircleGeometryProcessor>().fLocalMatrix,
+ &fLocalMatrix);
}
private:
typedef GrGLSLGeometryProcessor INHERITED;
+
+ SkMatrix fLocalMatrix = SkMatrix::InvalidMatrix();
+ UniformHandle fLocalMatrixUniform;
};
SkMatrix fLocalMatrix;
@@ -588,14 +588,10 @@ private:
// Setup position
this->writeOutputPosition(vertBuilder, gpArgs, egp.fInPosition.name());
+ this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
+ egp.fInPosition.asShaderVar(), egp.fLocalMatrix,
+ &fLocalMatrixUniform);
- // emit transforms
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- egp.fInPosition.asShaderVar(),
- egp.fLocalMatrix,
- args.fFPCoordTransformHandler);
// For stroked ellipses, we use the full ellipse equation (x^2/a^2 + y^2/b^2 = 1)
// to compute both the edges because we need two separate test equations for
// the single offset.
@@ -666,19 +662,23 @@ private:
const GrShaderCaps&,
GrProcessorKeyBuilder* b) {
const EllipseGeometryProcessor& egp = gp.cast<EllipseGeometryProcessor>();
- uint16_t key = egp.fStroke ? 0x1 : 0x0;
- key |= egp.fLocalMatrix.hasPerspective() ? 0x2 : 0x0;
+ uint32_t key = egp.fStroke ? 0x1 : 0x0;
+ key |= ComputeMatrixKey(egp.fLocalMatrix) << 1;
b->add32(key);
}
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
const CoordTransformRange& transformRange) override {
const EllipseGeometryProcessor& egp = primProc.cast<EllipseGeometryProcessor>();
- this->setTransformDataHelper(egp.fLocalMatrix, pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
+ this->setTransform(pdman, fLocalMatrixUniform, egp.fLocalMatrix, &fLocalMatrix);
}
private:
typedef GrGLSLGeometryProcessor INHERITED;
+
+ SkMatrix fLocalMatrix = SkMatrix::InvalidMatrix();
+ UniformHandle fLocalMatrixUniform;
};
Attribute fInPosition;
@@ -791,13 +791,7 @@ private:
diegp.fInPosition.name(),
diegp.fViewMatrix,
&fViewMatrixUniform);
-
- // emit transforms
- this->emitTransforms(vertBuilder,
- varyingHandler,
- uniformHandler,
- diegp.fInPosition.asShaderVar(),
- args.fFPCoordTransformHandler);
+ gpArgs->fLocalCoordVar = diegp.fInPosition.asShaderVar();
// for outer curve
fragBuilder->codeAppendf("float2 scaledOffset = %s.xy;", offsets0.fsIn());
@@ -862,8 +856,8 @@ private:
const GrShaderCaps&,
GrProcessorKeyBuilder* b) {
const DIEllipseGeometryProcessor& diegp = gp.cast<DIEllipseGeometryProcessor>();
- uint16_t key = static_cast<uint16_t>(diegp.fStyle);
- key |= ComputePosKey(diegp.fViewMatrix) << 10;
+ uint32_t key = static_cast<uint32_t>(diegp.fStyle);
+ key |= ComputeMatrixKey(diegp.fViewMatrix) << 10;
b->add32(key);
}
@@ -871,17 +865,12 @@ private:
const CoordTransformRange& transformRange) override {
const DIEllipseGeometryProcessor& diegp = gp.cast<DIEllipseGeometryProcessor>();
- if (!diegp.fViewMatrix.isIdentity() &&
- !SkMatrixPriv::CheapEqual(fViewMatrix, diegp.fViewMatrix))
- {
- fViewMatrix = diegp.fViewMatrix;
- pdman.setSkMatrix(fViewMatrixUniform, fViewMatrix);
- }
- this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+ this->setTransform(pdman, fViewMatrixUniform, diegp.fViewMatrix, &fViewMatrix);
+ this->setTransformDataHelper(pdman, transformRange);
}
private:
- SkMatrix fViewMatrix;
+ SkMatrix fViewMatrix;
UniformHandle fViewMatrixUniform;
typedef GrGLSLGeometryProcessor INHERITED;
diff --git a/chromium/third_party/skia/src/gpu/ops/GrQuadPerEdgeAA.cpp b/chromium/third_party/skia/src/gpu/ops/GrQuadPerEdgeAA.cpp
index bc5de24d968..ca420dd839f 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrQuadPerEdgeAA.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrQuadPerEdgeAA.cpp
@@ -571,7 +571,7 @@ public:
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
const CoordTransformRange& transformRange) override {
const auto& gp = proc.cast<QuadPerEdgeAAGeometryProcessor>();
- this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
fTextureColorSpaceXformHelper.setData(pdman, gp.fTextureColorSpaceXform.get());
}
@@ -604,18 +604,10 @@ public:
gpArgs->fPositionVar = gp.fPosition.asShaderVar();
}
- // Handle local coordinates if they exist. This is required even when the op
- // isn't providing local coords but there are FPs called with explicit coords.
- // It installs the uniforms that transform their coordinates in the fragment
- // shader.
- // NOTE: If the only usage of local coordinates is for the inline texture fetch
- // before FPs, then there are no registered FPCoordTransforms and this ends up
- // emitting nothing, so there isn't a duplication of local coordinates
- this->emitTransforms(args.fVertBuilder,
- args.fVaryingHandler,
- args.fUniformHandler,
- gp.fLocalCoord.asShaderVar(),
- args.fFPCoordTransformHandler);
+ // This attribute will be uninitialized if earlier FP analysis determined no
+ // local coordinates are needed (and this will not include the inline texture
+ // fetch this GP does before invoking FPs).
+ gpArgs->fLocalCoordVar = gp.fLocalCoord.asShaderVar();
// Solid color before any texturing gets modulated in
if (gp.fColor.isInitialized()) {
diff --git a/chromium/third_party/skia/src/gpu/ops/GrSmallPathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrSmallPathRenderer.cpp
index 075376d7f18..0f3ab8ae4fb 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -885,7 +885,7 @@ bool GrSmallPathRenderer::onDrawPath(const DrawPathArgs& args) {
std::unique_ptr<GrDrawOp> op = SmallPathOp::Make(
args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix, fAtlas.get(),
&fShapeCache, &fShapeList, args.fGammaCorrect, args.fUserStencilSettings);
- args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+ args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
return true;
}
diff --git a/chromium/third_party/skia/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
index 59a8bf75a7a..fcff78cf6f0 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
@@ -7,7 +7,6 @@
#include "include/private/GrRecordingContext.h"
#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrPath.h"
#include "src/gpu/GrRenderTargetContextPriv.h"
@@ -101,7 +100,7 @@ void GrStencilAndCoverPathRenderer::onStencilPath(const StencilPathArgs& args) {
"GrStencilAndCoverPathRenderer::onStencilPath");
sk_sp<GrPath> p(get_gr_path(fResourceProvider, *args.fShape));
args.fRenderTargetContext->priv().stencilPath(
- *args.fClip, args.fDoStencilMSAA, *args.fViewMatrix, std::move(p));
+ args.fClip, args.fDoStencilMSAA, *args.fViewMatrix, std::move(p));
}
bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) {
@@ -125,15 +124,16 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) {
args.fRenderTargetContext->height()); // Inverse fill.
// fake inverse with a stencil and cover
- GrAppliedClip appliedClip;
- if (!args.fClip->apply(
+ GrAppliedClip appliedClip(args.fRenderTargetContext->dimensions());
+ if (args.fClip && !args.fClip->apply(
args.fContext, args.fRenderTargetContext, doStencilMSAA, true, &appliedClip,
&devBounds)) {
return true;
}
- GrStencilClip stencilClip(appliedClip.stencilStackID());
+ GrStencilClip stencilClip(args.fRenderTargetContext->dimensions(),
+ appliedClip.stencilStackID());
if (appliedClip.scissorState().enabled()) {
- stencilClip.fixedClip().setScissor(appliedClip.scissorState().rect());
+ SkAssertResult(stencilClip.fixedClip().setScissor(appliedClip.scissorState().rect()));
}
if (appliedClip.windowRectsState().enabled()) {
stencilClip.fixedClip().setWindowRectangles(appliedClip.windowRectsState().windows(),
@@ -142,7 +142,7 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) {
// Just ignore the analytic FPs (if any) during the stencil pass. They will still clip the
// final draw and it is meaningless to multiply by coverage when drawing to stencil.
args.fRenderTargetContext->priv().stencilPath(
- stencilClip, GrAA(doStencilMSAA), viewMatrix, std::move(path));
+ &stencilClip, GrAA(doStencilMSAA), viewMatrix, std::move(path));
{
static constexpr GrUserStencilSettings kInvertedCoverPass(
@@ -179,14 +179,14 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) {
doStencilMSAA = GrAA::kYes;
}
args.fRenderTargetContext->priv().stencilRect(
- *args.fClip, &kInvertedCoverPass, std::move(args.fPaint), doStencilMSAA,
+ args.fClip, &kInvertedCoverPass, std::move(args.fPaint), doStencilMSAA,
coverMatrix, coverBounds, &localMatrix);
}
} else {
std::unique_ptr<GrDrawOp> op = GrDrawPathOp::Make(
args.fContext, viewMatrix, std::move(args.fPaint), GrAA(doStencilMSAA),
std::move(path));
- args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+ args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
}
return true;
diff --git a/chromium/third_party/skia/src/gpu/ops/GrTextureOp.cpp b/chromium/third_party/skia/src/gpu/ops/GrTextureOp.cpp
index 92904e97fad..ee712911f95 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrTextureOp.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrTextureOp.cpp
@@ -95,7 +95,7 @@ static bool filter_has_effect(const GrQuad& srcQuad, const GrQuad& dstQuad) {
// regular and rectangular textures, w/ or w/o origin correction.
struct NormalizationParams {
float fIW; // 1 / width of texture, or 1.0 for texture rectangles
- float fIH; // 1 / height of texture, or 1.0 for tex rects, X -1 if bottom-left origin
+ float fInvH; // 1 / height of texture, or 1.0 for tex rects, X -1 if bottom-left origin
float fYOffset; // 0 for top-left origin, height of [normalized] tex if bottom-left
};
static NormalizationParams proxy_normalization_params(const GrSurfaceProxy* proxy,
@@ -120,21 +120,13 @@ static NormalizationParams proxy_normalization_params(const GrSurfaceProxy* prox
}
}
-static SkRect inset_subset_for_bilerp(const NormalizationParams& params, const SkRect& subsetRect) {
- // Normalized pixel size is also equal to iw and ih, so the insets for bilerp are just
- // in those units and can be applied safely after normalization. However, if the subset is
- // smaller than a texel, it should clamp to the center of that axis.
- float dw = subsetRect.width() < params.fIW ? subsetRect.width() : params.fIW;
- float dh = subsetRect.height() < params.fIH ? subsetRect.height() : params.fIH;
- return subsetRect.makeInset(0.5f * dw, 0.5f * dh);
-}
-
// Normalize the subset. If 'subsetRect' is null, it is assumed no subset constraint is desired,
// so a sufficiently large rect is returned even if the quad ends up batched with an op that uses
-// subsets overall.
-static SkRect normalize_subset(GrSamplerState::Filter filter,
- const NormalizationParams& params,
- const SkRect* subsetRect) {
+// subsets overall. When there is a subset it will be inset based on the filter mode. Normalization
+// and y-flipping are applied as indicated by NormalizationParams.
+static SkRect normalize_and_inset_subset(GrSamplerState::Filter filter,
+ const NormalizationParams& params,
+ const SkRect* subsetRect) {
static constexpr SkRect kLargeRect = {-100000, -100000, 1000000, 1000000};
if (!subsetRect) {
// Either the quad has no subset constraint and is batched with a subset constrained op
@@ -144,10 +136,20 @@ static SkRect normalize_subset(GrSamplerState::Filter filter,
}
auto ltrb = skvx::Vec<4, float>::Load(subsetRect);
+ auto flipHi = skvx::Vec<4, float>({1.f, 1.f, -1.f, -1.f});
+ if (filter == GrSamplerState::Filter::kNearest) {
+ // Make sure our insetting puts us at pixel centers.
+ ltrb = skvx::floor(ltrb*flipHi)*flipHi;
+ }
+ // Inset with pin to the rect center.
+ ltrb += skvx::Vec<4, float>({.5f, .5f, -.5f, -.5f});
+ auto mid = (skvx::shuffle<2, 3, 0, 1>(ltrb) + ltrb)*0.5f;
+ ltrb = skvx::min(ltrb*flipHi, mid*flipHi)*flipHi;
+
// Normalize and offset
- ltrb = mad(ltrb, {params.fIW, params.fIH, params.fIW, params.fIH},
+ ltrb = mad(ltrb, {params.fIW, params.fInvH, params.fIW, params.fInvH},
{0.f, params.fYOffset, 0.f, params.fYOffset});
- if (params.fIH < 0.f) {
+ if (params.fInvH < 0.f) {
// Flip top and bottom to keep the rect sorted when loaded back to SkRect.
ltrb = skvx::shuffle<0, 3, 2, 1>(ltrb);
}
@@ -163,7 +165,7 @@ static void normalize_src_quad(const NormalizationParams& params,
// The src quad should not have any perspective
SkASSERT(!srcQuad->hasPerspective());
skvx::Vec<4, float> xs = srcQuad->x4f() * params.fIW;
- skvx::Vec<4, float> ys = mad(srcQuad->y4f(), params.fIH, params.fYOffset);
+ skvx::Vec<4, float> ys = mad(srcQuad->y4f(), params.fInvH, params.fYOffset);
xs.store(srcQuad->xs());
ys.store(srcQuad->ys());
}
@@ -183,6 +185,32 @@ static int proxy_run_count(const GrRenderTargetContext::TextureSetEntry set[], i
return actualProxyRunCount;
}
+static bool safe_to_ignore_subset_rect(GrAAType aaType, GrSamplerState::Filter filter,
+ const DrawQuad& quad, const SkRect& subsetRect) {
+ // If both the device and local quad are both axis-aligned, and filtering is off, the local quad
+ // can push all the way up to the edges of the the subset rect and the sampler shouldn't
+ // overshoot. Unfortunately, antialiasing adds enough jitter that we can only rely on this in
+ // the non-antialiased case.
+ SkRect localBounds = quad.fLocal.bounds();
+ if (aaType == GrAAType::kNone &&
+ filter == GrSamplerState::Filter::kNearest &&
+ quad.fDevice.quadType() == GrQuad::Type::kAxisAligned &&
+ quad.fLocal.quadType() == GrQuad::Type::kAxisAligned &&
+ subsetRect.contains(localBounds)) {
+
+ return true;
+ }
+
+ // If the subset rect is inset by at least 0.5 pixels into the local quad's bounds, the
+ // sampler shouldn't overshoot, even when antialiasing and filtering is taken into account.
+ if (subsetRect.makeInset(0.5f, 0.5f).contains(localBounds)) {
+ return true;
+ }
+
+ // The subset rect cannot be ignored safely.
+ return false;
+}
+
/**
* Op that implements GrTextureOp::Make. It draws textured quads. Each quad can modulate against a
* the texture by color. The blend with the destination is always src-over. The edges are non-AA.
@@ -415,9 +443,7 @@ private:
void allocatePrePreparedVertices(SkArenaAlloc* arena) {
fPrePreparedVertices = arena->makeArrayDefault<char>(this->totalSizeInBytes());
}
-
};
-
// If subsetRect is not null it will be used to apply a strict src rect-style constraint.
TextureOp(GrSurfaceProxyView proxyView,
sk_sp<GrColorSpaceXform> textureColorSpaceXform,
@@ -444,19 +470,19 @@ private:
!subsetRect->contains(proxyView.proxy()->backingStoreBoundsRect()));
// We may have had a strict constraint with nearest filter solely due to possible AA bloat.
- // If we don't have (or determined we don't need) coverage AA then we can skip using a
- // subset.
- if (subsetRect && filter == GrSamplerState::Filter::kNearest &&
- aaType != GrAAType::kCoverage) {
- subsetRect = nullptr;
- fMetadata.fSubset = static_cast<uint16_t>(Subset::kNo);
+ // Try to identify cases where the subsetting isn't actually necessary, and skip it.
+ if (subsetRect) {
+ if (safe_to_ignore_subset_rect(aaType, filter, *quad, *subsetRect)) {
+ subsetRect = nullptr;
+ fMetadata.fSubset = static_cast<uint16_t>(Subset::kNo);
+ }
}
// Normalize src coordinates and the subset (if set)
NormalizationParams params = proxy_normalization_params(proxyView.proxy(),
proxyView.origin());
normalize_src_quad(params, &quad->fLocal);
- SkRect subset = normalize_subset(filter, params, subsetRect);
+ SkRect subset = normalize_and_inset_subset(filter, params, subsetRect);
// Set bounds before clipping so we don't have to worry about unioning the bounds of
// the two potential quads (GrQuad::bounds() is perspective-safe).
@@ -542,11 +568,6 @@ private:
netFilter = GrSamplerState::Filter::kBilerp;
}
- // Normalize the src quads and apply origin
- NormalizationParams proxyParams = proxy_normalization_params(
- curProxy, set[q].fProxyView.origin());
- normalize_src_quad(proxyParams, &quad.fLocal);
-
// Update overall bounds of the op as the union of all quads
bounds.joinPossiblyEmptyRect(quad.fDevice.bounds());
@@ -554,6 +575,7 @@ private:
GrAAType aaForQuad;
GrQuadUtils::ResolveAAType(aaType, set[q].fAAFlags, quad.fDevice,
&aaForQuad, &quad.fEdgeFlags);
+
// Resolve sets aaForQuad to aaType or None, there is never a change between aa methods
SkASSERT(aaForQuad == GrAAType::kNone || aaForQuad == aaType);
if (netAAType == GrAAType::kNone && aaForQuad != GrAAType::kNone) {
@@ -563,27 +585,29 @@ private:
// Calculate metadata for the entry
const SkRect* subsetForQuad = nullptr;
if (constraint == SkCanvas::kStrict_SrcRectConstraint) {
- // Check (briefly) if the strict constraint is needed for this set entry
- if (!set[q].fSrcRect.contains(curProxy->backingStoreBoundsRect()) &&
- (filter == GrSamplerState::Filter::kBilerp ||
- aaForQuad == GrAAType::kCoverage)) {
- // Can't rely on hardware clamping and the draw will access outer texels
- // for AA and/or bilerp. Unlike filter quality, this op still has per-quad
- // control over AA so that can check aaForQuad, not netAAType.
- netSubset = Subset::kYes;
- subsetForQuad = &set[q].fSrcRect;
+ // Check (briefly) if the subset rect is actually needed for this set entry.
+ SkRect* subsetRect = &set[q].fSrcRect;
+ if (!subsetRect->contains(curProxy->backingStoreBoundsRect())) {
+ if (!safe_to_ignore_subset_rect(aaForQuad, filter, quad, *subsetRect)) {
+ netSubset = Subset::kYes;
+ subsetForQuad = subsetRect;
+ }
}
}
+
+ // Normalize the src quads and apply origin
+ NormalizationParams proxyParams = proxy_normalization_params(
+ curProxy, set[q].fProxyView.origin());
+ normalize_src_quad(proxyParams, &quad.fLocal);
+
// This subset may represent a no-op, otherwise it will have the origin and dimensions
// of the texture applied to it. Insetting for bilinear filtering is deferred until
// on[Pre]Prepare so that the overall filter can be lazily determined.
- SkRect subset = normalize_subset(filter, proxyParams, subsetForQuad);
+ SkRect subset = normalize_and_inset_subset(filter, proxyParams, subsetForQuad);
// Always append a quad (or 2 if perspective clipped), it just may refer back to a prior
// ViewCountPair (this frequently happens when Chrome draws 9-patches).
- float alpha = SkTPin(set[q].fAlpha, 0.f, 1.f);
- fViewCountPairs[p].fQuadCnt += this->appendQuad(
- &quad, {alpha, alpha, alpha, alpha}, subset);
+ fViewCountPairs[p].fQuadCnt += this->appendQuad(&quad, set[q].fColor, subset);
}
// The # of proxy switches should match what was provided (+1 because we incremented p
// when a new proxy was encountered).
@@ -689,21 +713,12 @@ private:
const int quadCnt = op.fViewCountPairs[p].fQuadCnt;
SkDEBUGCODE(int meshVertexCnt = quadCnt * desc->fVertexSpec.verticesPerQuad());
- // Can just use top-left for origin here since we only need the dimensions to
- // determine the texel size for insetting.
- NormalizationParams params = proxy_normalization_params(
- op.fViewCountPairs[p].fProxy.get(), kTopLeft_GrSurfaceOrigin);
-
- bool inset = texOp->fMetadata.filter() != GrSamplerState::Filter::kNearest;
-
for (int i = 0; i < quadCnt && iter.next(); ++i) {
SkASSERT(iter.isLocalValid());
const ColorSubsetAndAA& info = iter.metadata();
tessellator.append(iter.deviceQuad(), iter.localQuad(), info.fColor,
- inset ? inset_subset_for_bilerp(params, info.fSubsetRect)
- : info.fSubsetRect,
- info.aaFlags());
+ info.fSubsetRect, info.aaFlags());
}
SkASSERT((totVerticesSeen + meshVertexCnt) * vertexSize
@@ -1041,21 +1056,20 @@ std::unique_ptr<GrDrawOp> GrTextureOp::Make(GrRecordingContext* context,
const auto& caps = *context->priv().caps();
SkRect localRect;
if (quad->fLocal.asRect(&localRect)) {
- fp = GrTextureEffect::MakeSubset(std::move(proxyView), alphaType, SkMatrix::I(), filter,
- *subset, localRect, caps);
+ fp = GrTextureEffect::MakeSubset(std::move(proxyView), alphaType, SkMatrix::I(),
+ filter, *subset, localRect, caps);
} else {
- fp = GrTextureEffect::MakeSubset(std::move(proxyView), alphaType, SkMatrix::I(), filter,
- *subset, caps);
+ fp = GrTextureEffect::MakeSubset(std::move(proxyView), alphaType, SkMatrix::I(),
+ filter, *subset, caps);
}
} else {
fp = GrTextureEffect::Make(std::move(proxyView), alphaType, SkMatrix::I(), filter);
}
fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(textureXform));
- paint.addColorFragmentProcessor(std::move(fp));
if (saturate == GrTextureOp::Saturate::kYes) {
- paint.addColorFragmentProcessor(GrClampFragmentProcessor::Make(false));
+ fp = GrClampFragmentProcessor::Make(std::move(fp), /*clampToPremul=*/false);
}
-
+ paint.addColorFragmentProcessor(std::move(fp));
return GrFillRectOp::Make(context, std::move(paint), aaType, quad);
}
}
@@ -1064,7 +1078,7 @@ std::unique_ptr<GrDrawOp> GrTextureOp::Make(GrRecordingContext* context,
class GrTextureOp::BatchSizeLimiter {
public:
BatchSizeLimiter(GrRenderTargetContext* rtc,
- const GrClip& clip,
+ const GrClip* clip,
GrRecordingContext* context,
int numEntries,
GrSamplerState::Filter filter,
@@ -1102,7 +1116,7 @@ public:
private:
GrRenderTargetContext* fRTC;
- const GrClip& fClip;
+ const GrClip* fClip;
GrRecordingContext* fContext;
GrSamplerState::Filter fFilter;
GrTextureOp::Saturate fSaturate;
@@ -1116,7 +1130,7 @@ private:
// Greedily clump quad draws together until the index buffer limit is exceeded.
void GrTextureOp::AddTextureSetOps(GrRenderTargetContext* rtc,
- const GrClip& clip,
+ const GrClip* clip,
GrRecordingContext* context,
GrRenderTargetContext::TextureSetEntry set[],
int cnt,
@@ -1141,7 +1155,6 @@ void GrTextureOp::AddTextureSetOps(GrRenderTargetContext* rtc,
// automatically creates the appropriate GrFillRectOp to emulate GrTextureOp.
SkMatrix ctm;
for (int i = 0; i < cnt; ++i) {
- float alpha = set[i].fAlpha;
ctm = viewMatrix;
if (set[i].fPreViewMatrix) {
ctm.preConcat(*set[i].fPreViewMatrix);
@@ -1164,7 +1177,7 @@ void GrTextureOp::AddTextureSetOps(GrRenderTargetContext* rtc,
? &set[i].fSrcRect : nullptr;
auto op = Make(context, set[i].fProxyView, set[i].fSrcAlphaType, textureColorSpaceXform,
- filter, {alpha, alpha, alpha, alpha}, saturate, blendMode, aaType,
+ filter, set[i].fColor, saturate, blendMode, aaType,
&quad, subset);
rtc->addDrawOp(clip, std::move(op));
}
diff --git a/chromium/third_party/skia/src/gpu/ops/GrTextureOp.h b/chromium/third_party/skia/src/gpu/ops/GrTextureOp.h
index 404535b68f4..2c1f48e16cd 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrTextureOp.h
+++ b/chromium/third_party/skia/src/gpu/ops/GrTextureOp.h
@@ -56,7 +56,7 @@ public:
// supported, or if the blend mode is not src-over. 'cnt' is the size of the entry array.
// 'proxyCnt' <= 'cnt' and represents the number of proxy switches within the array.
static void AddTextureSetOps(GrRenderTargetContext*,
- const GrClip& clip,
+ const GrClip* clip,
GrRecordingContext*,
GrRenderTargetContext::TextureSetEntry[],
int cnt,
diff --git a/chromium/third_party/skia/src/gpu/ops/GrTriangulatingPathRenderer.cpp b/chromium/third_party/skia/src/gpu/ops/GrTriangulatingPathRenderer.cpp
index 67f829827ae..7e696c4ae2f 100644
--- a/chromium/third_party/skia/src/gpu/ops/GrTriangulatingPathRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/ops/GrTriangulatingPathRenderer.cpp
@@ -11,12 +11,12 @@
#include "src/core/SkGeometry.h"
#include "src/gpu/GrAuditTrail.h"
#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrDefaultGeoProcFactory.h"
#include "src/gpu/GrDrawOpTest.h"
#include "src/gpu/GrEagerVertexAllocator.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrProgramInfo.h"
+#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrResourceCache.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrSimpleMesh.h"
@@ -419,12 +419,11 @@ private:
bool GrTriangulatingPathRenderer::onDrawPath(const DrawPathArgs& args) {
GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
"GrTriangulatingPathRenderer::onDrawPath");
- SkIRect clipBoundsI = args.fClip->getConservativeBounds(args.fRenderTargetContext->width(),
- args.fRenderTargetContext->height());
+
std::unique_ptr<GrDrawOp> op = TriangulatingPathOp::Make(
- args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix, clipBoundsI,
- args.fAAType, args.fUserStencilSettings);
- args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+ args.fContext, std::move(args.fPaint), *args.fShape, *args.fViewMatrix,
+ *args.fClipConservativeBounds, args.fAAType, args.fUserStencilSettings);
+ args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
return true;
}
diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.cpp b/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.cpp
index 142e20cb5fb..cda13bea6f6 100644
--- a/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.cpp
+++ b/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.cpp
@@ -18,8 +18,8 @@
namespace {
constexpr static GrGeometryProcessor::Attribute kInstanceAttribs[] = {
- {"devibounds", kInt4_GrVertexAttribType, kInt4_GrSLType},
- {"dev_to_atlas_offset", kInt2_GrVertexAttribType, kInt2_GrSLType},
+ {"dev_xywh", kInt4_GrVertexAttribType, kInt4_GrSLType},
+ {"atlas_xy", kInt2_GrVertexAttribType, kInt2_GrSLType},
{"color", kFloat4_GrVertexAttribType, kHalf4_GrSLType},
{"viewmatrix_scaleskew", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
{"viewmatrix_trans", kFloat2_GrVertexAttribType, kFloat2_GrSLType}};
@@ -73,22 +73,24 @@ class DrawAtlasPathShader::Impl : public GrGLSLGeometryProcessor {
args.fVertBuilder->codeAppendf(R"(
float2 T = float2(sk_VertexID & 1, sk_VertexID >> 1);
- float2 devcoord = mix(float2(devibounds.xy), float2(devibounds.zw), T);
- float2 atlascoord = devcoord + float2(dev_to_atlas_offset);
+ float2 devtopleft = float2(dev_xywh.xy);
+ float2 devcoord = abs(float2(dev_xywh.zw)) * T + devtopleft;
+ float2 atlascoord = devcoord - devtopleft;
+ if (dev_xywh.w < 0) { // Negative height indicates that the path is transposed.
+ atlascoord = atlascoord.yx;
+ }
+ atlascoord += atlas_xy;
%s = atlascoord * %s;)",
atlasCoord.vsOut(), atlasAdjust);
gpArgs->fPositionVar.set(kFloat2_GrSLType, "devcoord");
- GrShaderVar localCoord = gpArgs->fPositionVar;
if (shader.fUsesLocalCoords) {
args.fVertBuilder->codeAppendf(R"(
float2x2 M = float2x2(viewmatrix_scaleskew);
float2 localcoord = inverse(M) * (devcoord - viewmatrix_trans);)");
- localCoord.set(kFloat2_GrSLType, "localcoord");
+ gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord");
}
- this->emitTransforms(args.fVertBuilder, args.fVaryingHandler, args.fUniformHandler,
- localCoord, args.fFPCoordTransformHandler);
args.fFragBuilder->codeAppendf("%s = ", args.fOutputCoverage);
args.fFragBuilder->appendTextureLookup(args.fTexSamplers[0], atlasCoord.fsIn());
@@ -99,7 +101,7 @@ class DrawAtlasPathShader::Impl : public GrGLSLGeometryProcessor {
const CoordTransformRange& transformRange) override {
const SkISize& dimensions = primProc.cast<DrawAtlasPathShader>().fAtlasDimensions;
pdman.set2f(fAtlasAdjustUniform, 1.f / dimensions.width(), 1.f / dimensions.height());
- this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
}
GrGLSLUniformHandler::UniformHandle fAtlasAdjustUniform;
diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.h b/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.h
index b20583ba41c..43f8671167b 100644
--- a/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.h
+++ b/chromium/third_party/skia/src/gpu/tessellate/GrDrawAtlasPathOp.h
@@ -8,6 +8,7 @@
#ifndef GrDrawAtlasPathOp_DEFINED
#define GrDrawAtlasPathOp_DEFINED
+#include "src/core/SkIPoint16.h"
#include "src/gpu/ops/GrDrawOp.h"
class GrDrawAtlasPathOp : public GrDrawOp {
@@ -15,12 +16,13 @@ public:
DEFINE_OP_CLASS_ID
GrDrawAtlasPathOp(int numRenderTargetSamples, sk_sp<GrTextureProxy> atlasProxy,
- const SkIRect& devIBounds, const SkIVector& devToAtlasOffset,
- const SkMatrix& viewMatrix, GrPaint&& paint)
+ const SkIRect& devIBounds, const SkIPoint16& locationInAtlas,
+ bool transposedInAtlas, const SkMatrix& viewMatrix, GrPaint&& paint)
: GrDrawOp(ClassID())
, fEnableHWAA(numRenderTargetSamples > 1)
, fAtlasProxy(std::move(atlasProxy))
- , fInstanceList(devIBounds, devToAtlasOffset, paint.getColor4f(), viewMatrix)
+ , fInstanceList(devIBounds, locationInAtlas, transposedInAtlas, paint.getColor4f(),
+ viewMatrix)
, fProcessors(std::move(paint)) {
this->setBounds(SkRect::Make(devIBounds), HasAABloat::kYes, IsHairline::kNo);
}
@@ -53,25 +55,27 @@ private:
}
return stride;
}
- Instance(const SkIRect& devIBounds, SkIVector devToAtlasOffset, const SkPMColor4f& color,
- const SkMatrix& m)
- : fDevIBounds(devIBounds)
- , fDevToAtlasOffset(devToAtlasOffset)
+ Instance(const SkIRect& devIBounds, const SkIPoint16& locationInAtlas,
+ bool transposedInAtlas, const SkPMColor4f& color, const SkMatrix& m)
+ : fDevXYWH{devIBounds.left(), devIBounds.top(), devIBounds.width(),
+ // We use negative height to indicate that the path is transposed.
+ (transposedInAtlas) ? -devIBounds.height() : devIBounds.height()}
+ , fAtlasXY{locationInAtlas.x(), locationInAtlas.y()}
, fColor(color)
, fViewMatrixIfUsingLocalCoords{m.getScaleX(), m.getSkewY(),
m.getSkewX(), m.getScaleY(),
m.getTranslateX(), m.getTranslateY()} {
}
- SkIRect fDevIBounds;
- SkIVector fDevToAtlasOffset;
+ std::array<int, 4> fDevXYWH;
+ std::array<int, 2> fAtlasXY;
SkPMColor4f fColor;
float fViewMatrixIfUsingLocalCoords[6];
};
struct InstanceList {
- InstanceList(const SkIRect& devIBounds, SkIVector devToAtlasOffset,
- const SkPMColor4f& color, const SkMatrix& viewMatrix)
- : fInstance(devIBounds, devToAtlasOffset, color, viewMatrix) {
+ InstanceList(const SkIRect& devIBounds, const SkIPoint16& locationInAtlas,
+ bool transposedInAtlas, const SkPMColor4f& color, const SkMatrix& viewMatrix)
+ : fInstance(devIBounds, locationInAtlas, transposedInAtlas, color, viewMatrix) {
}
InstanceList* fNext = nullptr;
Instance fInstance;
diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrFillPathShader.cpp b/chromium/third_party/skia/src/gpu/tessellate/GrFillPathShader.cpp
index f87ac4a03ce..93e6e598d5f 100644
--- a/chromium/third_party/skia/src/gpu/tessellate/GrFillPathShader.cpp
+++ b/chromium/third_party/skia/src/gpu/tessellate/GrFillPathShader.cpp
@@ -26,11 +26,8 @@ public:
args.fVertBuilder->codeAppend("float2 localcoord, vertexpos;");
shader.emitVertexCode(this, args.fVertBuilder, viewMatrix, args.fUniformHandler);
- this->emitTransforms(args.fVertBuilder, args.fVaryingHandler, args.fUniformHandler,
- GrShaderVar("localcoord", kFloat2_GrSLType),
- args.fFPCoordTransformHandler);
-
gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertexpos");
+ gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord");
const char* color;
fColorUniform = args.fUniformHandler->addUniform(
@@ -53,7 +50,7 @@ public:
pdman.set4f(fPathBoundsUniform, b.left(), b.top(), b.right(), b.bottom());
}
- this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
}
GrGLSLUniformHandler::UniformHandle fViewMatrixUniform;
diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h b/chromium/third_party/skia/src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h
index 258e175fdbb..482f2e3bb37 100644
--- a/chromium/third_party/skia/src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h
+++ b/chromium/third_party/skia/src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h
@@ -40,10 +40,12 @@
// recursion, we manipulate an O(log N) stack to determine the correct middle-out triangulation.
class GrMiddleOutPolygonTriangulator {
public:
- GrMiddleOutPolygonTriangulator(SkPoint* vertexData, int maxVertices)
- : fTriangleData(reinterpret_cast<std::array<SkPoint, 3>*>(vertexData)) {
+ GrMiddleOutPolygonTriangulator(SkPoint* vertexData, int perTriangleVertexAdvance,
+ int maxPushVertexCalls)
+ : fVertexData(vertexData)
+ , fPerTriangleVertexAdvance(perTriangleVertexAdvance) {
// Determine the deepest our stack can ever go.
- int maxStackDepth = SkNextLog2(maxVertices) + 1;
+ int maxStackDepth = SkNextLog2(maxPushVertexCalls) + 1;
if (maxStackDepth > kStackPreallocCount) {
fVertexStack.reset(maxStackDepth);
}
@@ -75,17 +77,15 @@ public:
// (This is a stack-based implementation of the recursive example method from the class
// comment.)
while (vertexIdxDelta == fTop->fVertexIdxDelta) {
- *fTriangleData++ = {fTop[-1].fPoint, fTop->fPoint, pt};
+ this->popTopTriangle(pt);
vertexIdxDelta *= 2;
- this->popTop();
}
- this->pushTop();
- *fTop = {vertexIdxDelta, pt};
+ this->pushVertex(vertexIdxDelta, pt);
}
int close() {
- if (fTop == &fVertexStack[0]) { // The stack only contains one point (the starting point).
- return fTotalClosedVertexCount;
+ if (fTop == fVertexStack) { // The stack only contains one point (the starting point).
+ return fTotalClosedTriangleCount;
}
// We will count vertices by walking the stack backwards.
int finalVertexCount = 1;
@@ -94,24 +94,23 @@ public:
// vertexIdxDeltas match.
const SkPoint& p0 = fVertexStack[0].fPoint;
SkASSERT(fTop->fPoint != p0); // We should have detected and handled this case earlier.
- while (fTop > &fVertexStack[1]) {
- *fTriangleData++ = {fTop[-1].fPoint, fTop->fPoint, p0};
+ while (fTop - 1 > fVertexStack) {
finalVertexCount += fTop->fVertexIdxDelta;
- this->popTop();
+ this->popTopTriangle(p0);
}
+ SkASSERT(fTop == fVertexStack + 1);
finalVertexCount += fTop->fVertexIdxDelta;
- this->popTop();
- SkASSERT(fTop == &fVertexStack[0]);
SkASSERT(fVertexStack[0].fVertexIdxDelta == 0);
+ fTop = fVertexStack;
int numTriangles = finalVertexCount - 2;
SkASSERT(numTriangles >= 0);
- fTotalClosedVertexCount += numTriangles * 3;
- return fTotalClosedVertexCount;
+ fTotalClosedTriangleCount += numTriangles;
+ return fTotalClosedTriangleCount;
}
void closeAndMove(const SkPoint& startPt) {
this->close();
- SkASSERT(fTop == &fVertexStack[0]); // The stack should only contain a starting point now.
+ SkASSERT(fTop == fVertexStack); // The stack should only contain a starting point now.
fTop->fPoint = startPt; // Modify the starting point.
SkASSERT(fTop->fVertexIdxDelta == 0); // Ensure we are in the initial stack state.
}
@@ -129,23 +128,30 @@ private:
SkPoint fPoint;
};
- void pushTop() {
+ void pushVertex(int vertexIdxDelta, const SkPoint& point) {
++fTop;
// We should never push deeper than fStackAllocCount.
- SkASSERT(fTop < &fVertexStack[fStackAllocCount]);
+ SkASSERT(fTop < fVertexStack + fStackAllocCount);
+ fTop->fVertexIdxDelta = vertexIdxDelta;
+ fTop->fPoint = point;
}
- void popTop() {
- SkASSERT(fTop > &fVertexStack[0]); // We should never pop the starting point.
+ void popTopTriangle(const SkPoint& lastPt) {
+ SkASSERT(fTop > fVertexStack); // We should never pop the starting point.
--fTop;
+ fVertexData[0] = fTop[0].fPoint;
+ fVertexData[1] = fTop[1].fPoint;
+ fVertexData[2] = lastPt;
+ fVertexData += fPerTriangleVertexAdvance;
}
constexpr static int kStackPreallocCount = 32;
SkAutoSTMalloc<kStackPreallocCount, StackVertex> fVertexStack;
SkDEBUGCODE(int fStackAllocCount;)
StackVertex* fTop;
- std::array<SkPoint, 3>* fTriangleData;
- int fTotalClosedVertexCount = 0;
+ SkPoint* fVertexData;
+ int fPerTriangleVertexAdvance;
+ int fTotalClosedTriangleCount = 0;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrResolveLevelCounter.h b/chromium/third_party/skia/src/gpu/tessellate/GrResolveLevelCounter.h
new file mode 100644
index 00000000000..66b0540fea5
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/tessellate/GrResolveLevelCounter.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrResolveLevelCounter_DEFINED
+#define GrResolveLevelCounter_DEFINED
+
+#include "src/core/SkPathPriv.h"
+#include "src/gpu/tessellate/GrStencilPathShader.h"
+#include "src/gpu/tessellate/GrWangsFormula.h"
+
+// This class helps bin cubics by log2 "resolveLevel" when we don't use hardware tessellation. It is
+// composed of simple counters that track how many cubics we intend to draw at each resolveLevel,
+// and how many resolveLevels there are that have at least one cubic.
+class GrResolveLevelCounter {
+public:
+ void reset() {
+ memset(fInstanceCounts, 0, sizeof(fInstanceCounts));
+ SkDEBUGCODE(fHasCalledReset = true;)
+ }
+
+ void reset(const SkPath& path, const SkMatrix& viewMatrix, float intolerance) {
+ this->reset();
+ GrVectorXform xform(viewMatrix);
+ for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
+ switch (verb) {
+ case SkPathVerb::kQuad:
+ // Quadratics get converted to cubics before rendering.
+ this->countCubic(GrWangsFormula::quadratic_log2(intolerance, pts, xform));
+ break;
+ case SkPathVerb::kCubic:
+ this->countCubic(GrWangsFormula::cubic_log2(intolerance, pts, xform));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ void countCubic(int resolveLevel) {
+ SkASSERT(fHasCalledReset);
+ SkASSERT(resolveLevel >= 0);
+ if (resolveLevel == 0) {
+ // Cubics with 2^0=1 segments are empty (zero area). We ignore them completely.
+ return;
+ }
+ resolveLevel = std::min(resolveLevel, GrMiddleOutCubicShader::kMaxResolveLevel);
+ if (!fInstanceCounts[resolveLevel]++) {
+ ++fTotalCubicIndirectDrawCount;
+ }
+ ++fTotalCubicInstanceCount;
+ }
+
+ int operator[](int resolveLevel) const {
+ SkASSERT(fHasCalledReset);
+ SkASSERT(resolveLevel > 0); // Empty cubics with 2^0=1 segments do not need to be drawn.
+ SkASSERT(resolveLevel <= GrMiddleOutCubicShader::kMaxResolveLevel);
+ return fInstanceCounts[resolveLevel];
+ }
+ int totalCubicInstanceCount() const { return fTotalCubicInstanceCount; }
+ int totalCubicIndirectDrawCount() const { return fTotalCubicIndirectDrawCount; }
+
+private:
+ SkDEBUGCODE(bool fHasCalledReset = false;)
+ int fInstanceCounts[GrMiddleOutCubicShader::kMaxResolveLevel + 1];
+ int fTotalCubicInstanceCount = 0;
+ int fTotalCubicIndirectDrawCount = 0;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.cpp b/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.cpp
index 9b36c2ac582..c6e95ef9027 100644
--- a/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.cpp
+++ b/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.cpp
@@ -35,6 +35,7 @@ constexpr char kEvalCubicFn[] = R"(
})";
class GrStencilPathShader::Impl : public GrGLSLGeometryProcessor {
+protected:
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
const auto& shader = args.fGP.cast<GrStencilPathShader>();
args.fVaryingHandler->emitAttributes(shader);
@@ -45,7 +46,7 @@ class GrStencilPathShader::Impl : public GrGLSLGeometryProcessor {
fViewMatrixUniform = args.fUniformHandler->addUniform(
nullptr, kVertex_GrShaderFlag, kFloat3x3_GrSLType, "view_matrix", &viewMatrix);
args.fVertBuilder->codeAppendf(
- "float2 vertexpos = (%s * float3(point, 1)).xy;", viewMatrix);
+ "float2 vertexpos = (%s * float3(inputPoint, 1)).xy;", viewMatrix);
vertexPos.set(kFloat2_GrSLType, "vertexpos");
}
@@ -75,8 +76,10 @@ GrGLSLPrimitiveProcessor* GrStencilPathShader::createGLSLInstance(const GrShader
return new Impl;
}
-SkString GrStencilCubicShader::getTessControlShaderGLSL(const char* versionAndExtensionDecls,
- const GrShaderCaps&) const {
+SkString GrTessellateCubicShader::getTessControlShaderGLSL(const GrGLSLPrimitiveProcessor*,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
+ const GrShaderCaps&) const {
SkString code(versionAndExtensionDecls);
code.append(kWangsFormulaCubicFn);
code.append(R"(
@@ -115,8 +118,9 @@ SkString GrStencilCubicShader::getTessControlShaderGLSL(const char* versionAndEx
return code;
}
-SkString GrStencilCubicShader::getTessEvaluationShaderGLSL(const char* versionAndExtensionDecls,
- const GrShaderCaps&) const {
+SkString GrTessellateCubicShader::getTessEvaluationShaderGLSL(
+ const GrGLSLPrimitiveProcessor*, const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&, const GrShaderCaps&) const {
SkString code(versionAndExtensionDecls);
code.append(kEvalCubicFn);
code.append(R"(
@@ -147,8 +151,10 @@ SkString GrStencilCubicShader::getTessEvaluationShaderGLSL(const char* versionAn
return code;
}
-SkString GrStencilWedgeShader::getTessControlShaderGLSL(const char* versionAndExtensionDecls,
- const GrShaderCaps&) const {
+SkString GrTessellateWedgeShader::getTessControlShaderGLSL(const GrGLSLPrimitiveProcessor*,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
+ const GrShaderCaps&) const {
SkString code(versionAndExtensionDecls);
code.append(kWangsFormulaCubicFn);
code.append(R"(
@@ -183,8 +189,9 @@ SkString GrStencilWedgeShader::getTessControlShaderGLSL(const char* versionAndEx
return code;
}
-SkString GrStencilWedgeShader::getTessEvaluationShaderGLSL(const char* versionAndExtensionDecls,
- const GrShaderCaps&) const {
+SkString GrTessellateWedgeShader::getTessEvaluationShaderGLSL(
+ const GrGLSLPrimitiveProcessor*, const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&, const GrShaderCaps&) const {
SkString code(versionAndExtensionDecls);
code.append(kEvalCubicFn);
code.append(R"(
@@ -218,3 +225,109 @@ SkString GrStencilWedgeShader::getTessEvaluationShaderGLSL(const char* versionAn
return code;
}
+
+GR_DECLARE_STATIC_UNIQUE_KEY(gMiddleOutIndexBufferKey);
+
+sk_sp<const GrGpuBuffer> GrMiddleOutCubicShader::FindOrMakeMiddleOutIndexBuffer(
+ GrResourceProvider* resourceProvider) {
+ GR_DEFINE_STATIC_UNIQUE_KEY(gMiddleOutIndexBufferKey);
+ if (auto buffer = resourceProvider->findByUniqueKey<GrGpuBuffer>(gMiddleOutIndexBufferKey)) {
+ return std::move(buffer);
+ }
+
+ // One explicit triangle at index 0, and one middle-out cubic with kMaxResolveLevel line
+ // segments beginning at index 3.
+ constexpr static int kIndexCount = 3 + NumVerticesAtResolveLevel(kMaxResolveLevel);
+ auto buffer = resourceProvider->createBuffer(
+ kIndexCount * sizeof(uint16_t), GrGpuBufferType::kIndex, kStatic_GrAccessPattern);
+ if (!buffer) {
+ return nullptr;
+ }
+
+ // We shouldn't bin and/or cache static buffers.
+ SkASSERT(buffer->size() == kIndexCount * sizeof(uint16_t));
+ SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
+ auto indexData = static_cast<uint16_t*>(buffer->map());
+ SkAutoTMalloc<uint16_t> stagingBuffer;
+ if (!indexData) {
+ SkASSERT(!buffer->isMapped());
+ indexData = stagingBuffer.reset(kIndexCount);
+ }
+
+ // Indices 0,1,2 contain special values that emit points P0, P1, and P2 respectively. (When the
+ // vertex shader is fed an index value larger than (1 << kMaxResolveLevel), it emits
+ // P[index % 4].)
+ int i = 0;
+ indexData[i++] = (1 << kMaxResolveLevel) + 4; // % 4 == 0
+ indexData[i++] = (1 << kMaxResolveLevel) + 5; // % 4 == 1
+ indexData[i++] = (1 << kMaxResolveLevel) + 6; // % 4 == 2
+
+ // Starting at index 3, we triangulate a cubic with 2^kMaxResolveLevel line segments. Each
+ // index value corresponds to parametric value T=(index / 2^kMaxResolveLevel). Since the
+ // triangles are arranged in "middle-out" order, we will be able to conveniently control the
+ // resolveLevel by changing only the indexCount.
+ for (uint16_t advance = 1 << (kMaxResolveLevel - 1); advance; advance >>= 1) {
+ uint16_t T = 0;
+ do {
+ indexData[i++] = T;
+ indexData[i++] = (T += advance);
+ indexData[i++] = (T += advance);
+ } while (T != (1 << kMaxResolveLevel));
+ }
+ SkASSERT(i == kIndexCount);
+
+ if (buffer->isMapped()) {
+ buffer->unmap();
+ } else {
+ buffer->updateData(stagingBuffer, kIndexCount * sizeof(uint16_t));
+ }
+ buffer->resourcePriv().setUniqueKey(gMiddleOutIndexBufferKey);
+ return std::move(buffer);
+}
+
+class GrMiddleOutCubicShader::Impl : public GrStencilPathShader::Impl {
+ void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
+ const auto& shader = args.fGP.cast<GrMiddleOutCubicShader>();
+ args.fVaryingHandler->emitAttributes(shader);
+ args.fVertBuilder->defineConstant("kMaxResolveLevel", kMaxResolveLevel);
+ args.fVertBuilder->codeAppend(R"(
+ float4x2 P = float4x2(inputPoints_0_1, inputPoints_2_3);
+ float2 point;
+ if (sk_VertexID > (1 << kMaxResolveLevel)) {
+ // This is a special index value that wants us to emit a specific point.
+ point = P[sk_VertexID & 3];
+ } else {)");
+ // Evaluate the cubic at T=(sk_VertexID / 2^kMaxResolveLevel).
+ if (args.fShaderCaps->fpManipulationSupport()) {
+ args.fVertBuilder->codeAppend(R"(
+ float T = ldexp(sk_VertexID, -kMaxResolveLevel);)");
+ } else {
+ args.fVertBuilder->codeAppend(R"(
+ float T = sk_VertexID / float(1 << kMaxResolveLevel);)");
+ }
+ args.fVertBuilder->codeAppend(R"(
+ float2 ab = mix(P[0], P[1], T);
+ float2 bc = mix(P[1], P[2], T);
+ float2 cd = mix(P[2], P[3], T);
+ float2 abc = mix(ab, bc, T);
+ float2 bcd = mix(bc, cd, T);
+ point = mix(abc, bcd, T);
+ })");
+
+ GrShaderVar vertexPos("point", kFloat2_GrSLType);
+ if (!shader.viewMatrix().isIdentity()) {
+ const char* viewMatrix;
+ fViewMatrixUniform = args.fUniformHandler->addUniform(
+ nullptr, kVertex_GrShaderFlag, kFloat3x3_GrSLType, "view_matrix", &viewMatrix);
+ args.fVertBuilder->codeAppendf(R"(
+ float2 transformedPoint = (%s * float3(point, 1)).xy;)", viewMatrix);
+ vertexPos.set(kFloat2_GrSLType, "transformedPoint");
+ }
+ gpArgs->fPositionVar = vertexPos;
+ // No fragment shader.
+ }
+};
+
+GrGLSLPrimitiveProcessor* GrMiddleOutCubicShader::createGLSLInstance(const GrShaderCaps&) const {
+ return new Impl;
+}
diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.h b/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.h
index 0aa0b5983b4..c098f76a8d5 100644
--- a/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.h
+++ b/chromium/third_party/skia/src/gpu/tessellate/GrStencilPathShader.h
@@ -9,6 +9,7 @@
#define GrStencilPathShader_DEFINED
#include "src/gpu/tessellate/GrPathShader.h"
+#include "src/gpu/tessellate/GrTessellationPathRenderer.h"
// This is the base class for shaders that stencil path elements, namely, triangles, standalone
// cubics, and wedges.
@@ -17,16 +18,15 @@ public:
GrStencilPathShader(ClassID classID, const SkMatrix& viewMatrix, GrPrimitiveType primitiveType,
int tessellationPatchVertexCount = 0)
: GrPathShader(classID, viewMatrix, primitiveType, tessellationPatchVertexCount) {
- constexpr static Attribute kPointAttrib = {
- "point", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
- this->setVertexAttributes(&kPointAttrib, 1);
}
-private:
- void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const final {
+protected:
+ constexpr static Attribute kSinglePointAttrib{"inputPoint", kFloat2_GrVertexAttribType,
+ kFloat2_GrSLType};
+ void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
b->add32(this->viewMatrix().isIdentity());
}
- GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final;
+ GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
class Impl;
};
@@ -35,23 +35,30 @@ private:
class GrStencilTriangleShader : public GrStencilPathShader {
public:
GrStencilTriangleShader(const SkMatrix& viewMatrix) : GrStencilPathShader(
- kTessellate_GrStencilTriangleShader_ClassID, viewMatrix, GrPrimitiveType::kTriangles) {}
+ kTessellate_GrStencilTriangleShader_ClassID, viewMatrix, GrPrimitiveType::kTriangles) {
+ this->setVertexAttributes(&kSinglePointAttrib, 1);
+ }
const char* name() const override { return "tessellate_GrStencilTriangleShader"; }
};
-// Uses GPU tessellation shaders to linearize, triangulate, and render standalone cubics. Here, a
-// "cubic" is a standalone closed contour consisting of a single cubic bezier.
+// Uses GPU tessellation shaders to linearize, triangulate, and render standalone closed cubics.
// TODO: Eventually we want to use rational cubic wedges in order to support perspective and conics.
-class GrStencilCubicShader : public GrStencilPathShader {
+class GrTessellateCubicShader : public GrStencilPathShader {
public:
- GrStencilCubicShader(const SkMatrix& viewMatrix) : GrStencilPathShader(
- kTessellate_GrStencilCubicShader_ClassID, viewMatrix, GrPrimitiveType::kPatches, 4) {}
- const char* name() const override { return "tessellate_GrStencilCubicShader"; }
+ GrTessellateCubicShader(const SkMatrix& viewMatrix) : GrStencilPathShader(
+ kTessellate_GrTessellateCubicShader_ClassID, viewMatrix, GrPrimitiveType::kPatches, 4) {
+ this->setVertexAttributes(&kSinglePointAttrib, 1);
+ }
+ const char* name() const override { return "tessellate_GrTessellateCubicShader"; }
private:
- SkString getTessControlShaderGLSL(const char* versionAndExtensionDecls,
+ SkString getTessControlShaderGLSL(const GrGLSLPrimitiveProcessor*,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
const GrShaderCaps&) const override;
- SkString getTessEvaluationShaderGLSL(const char* versionAndExtensionDecls,
+ SkString getTessEvaluationShaderGLSL(const GrGLSLPrimitiveProcessor*,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
const GrShaderCaps&) const override;
};
@@ -59,17 +66,88 @@ private:
// wedge is a 5-point patch consisting of 4 cubic control points, plus an anchor point fanning from
// the center of the curve's resident contour.
// TODO: Eventually we want to use rational cubic wedges in order to support perspective and conics.
-class GrStencilWedgeShader : public GrStencilPathShader {
+class GrTessellateWedgeShader : public GrStencilPathShader {
public:
- GrStencilWedgeShader(const SkMatrix& viewMatrix) : GrStencilPathShader(
- kTessellate_GrStencilWedgeShader_ClassID, viewMatrix, GrPrimitiveType::kPatches, 5) {}
- const char* name() const override { return "tessellate_GrStencilWedgeShader"; }
+ GrTessellateWedgeShader(const SkMatrix& viewMatrix) : GrStencilPathShader(
+ kTessellate_GrTessellateWedgeShader_ClassID, viewMatrix, GrPrimitiveType::kPatches, 5) {
+ this->setVertexAttributes(&kSinglePointAttrib, 1);
+ }
+ const char* name() const override { return "tessellate_GrTessellateWedgeShader"; }
private:
- SkString getTessControlShaderGLSL(const char* versionAndExtensionDecls,
+ SkString getTessControlShaderGLSL(const GrGLSLPrimitiveProcessor*,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
const GrShaderCaps&) const override;
- SkString getTessEvaluationShaderGLSL(const char* versionAndExtensionDecls,
+ SkString getTessEvaluationShaderGLSL(const GrGLSLPrimitiveProcessor*,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
const GrShaderCaps&) const override;
};
+// Uses indirect (instanced) draws to triangulate standalone closed cubics with a "middle-out"
+// topology. The caller must compute each cubic's resolveLevel on the CPU (i.e., the log2 number of
+// line segments it will be divided into; see GrWangsFormula::cubic_log2/quadratic_log2), and then
+// sort the instance buffer by resolveLevel for efficient batching of indirect draws.
+class GrMiddleOutCubicShader : public GrStencilPathShader {
+public:
+ // Each resolveLevel linearizes the curve into 2^resolveLevel line segments. The finest
+ // supported resolveLevel is therefore 2^12=4096 line segments.
+ constexpr static int kMaxResolveLevel = GrTessellationPathRenderer::kMaxResolveLevel;
+
+ // How many vertices do we need to draw in order to triangulate a cubic with 2^resolveLevel
+ // line segments?
+ constexpr static int NumVerticesAtResolveLevel(int resolveLevel) {
+ // resolveLevel=0 -> 0 line segments -> 0 triangles -> 0 vertices
+ // resolveLevel=1 -> 2 line segments -> 1 triangle -> 3 vertices
+ // resolveLevel=2 -> 4 line segments -> 3 triangles -> 9 vertices
+ // resolveLevel=3 -> 8 line segments -> 7 triangles -> 21 vertices
+ // ...
+ return ((1 << resolveLevel) - 1) * 3;
+ }
+
+ // Configures an indirect draw to render cubic instances with 2^resolveLevel evenly-spaced (in
+ // the parametric sense) line segments.
+ static GrDrawIndexedIndirectCommand MakeDrawCubicsIndirectCmd(int resolveLevel,
+ uint32_t instanceCount,
+ uint32_t baseInstance) {
+ SkASSERT(resolveLevel > 0 && resolveLevel <= kMaxResolveLevel);
+ // Starting at baseIndex=3, the index buffer triangulates a cubic with 2^kMaxResolveLevel
+ // line segments. Each index value corresponds to a parametric T value on the curve. Since
+ // the triangles are arranged in "middle-out" order, we can conveniently control the
+ // resolveLevel by changing only the indexCount.
+ uint32_t indexCount = NumVerticesAtResolveLevel(resolveLevel);
+ return {indexCount, instanceCount, 3, 0, baseInstance};
+ }
+
+ // For performance reasons we can often express triangles as an indirect cubic draw and sneak
+ // them in alongside the other indirect draws. This method configures an indirect draw to emit
+ // the triangle [P0, P1, P2] from a 4-point instance.
+ static GrDrawIndexedIndirectCommand MakeDrawTrianglesIndirectCmd(uint32_t instanceCount,
+ uint32_t baseInstance) {
+ // Indices 0,1,2 have special index values that emit points P0, P1, and P2 respectively.
+ return {3, instanceCount, 0, 0, baseInstance};
+ }
+
+ // Returns the index buffer that should be bound when drawing with this shader.
+ // (Our vertex shader uses raw index values directly, so there is no vertex buffer.)
+ static sk_sp<const GrGpuBuffer> FindOrMakeMiddleOutIndexBuffer(GrResourceProvider*);
+
+ GrMiddleOutCubicShader(const SkMatrix& viewMatrix)
+ : GrStencilPathShader(kTessellate_GrMiddleOutCubicShader_ClassID, viewMatrix,
+ GrPrimitiveType::kTriangles) {
+ constexpr static Attribute kInputPtsAttribs[] = {
+ {"inputPoints_0_1", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
+ {"inputPoints_2_3", kFloat4_GrVertexAttribType, kFloat4_GrSLType}};
+ this->setInstanceAttributes(kInputPtsAttribs, 2);
+ }
+
+ const char* name() const override { return "tessellate_GrMiddleOutCubicShader"; }
+
+private:
+ GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
+
+ class Impl;
+};
+
#endif
diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrStrokeGeometry.cpp b/chromium/third_party/skia/src/gpu/tessellate/GrStrokeGeometry.cpp
new file mode 100644
index 00000000000..b097c73a2d5
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/tessellate/GrStrokeGeometry.cpp
@@ -0,0 +1,583 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/tessellate/GrStrokeGeometry.h"
+
+#include "include/core/SkStrokeRec.h"
+#include "include/private/SkNx.h"
+#include "src/core/SkGeometry.h"
+#include "src/core/SkMathPriv.h"
+
+// This is the maximum distance in pixels that we can stray from the edge of a stroke when
+// converting it to flat line segments.
+static constexpr float kMaxErrorFromLinearization = 1/8.f;
+
+static inline float length(const Sk2f& n) {
+ Sk2f nn = n*n;
+ return SkScalarSqrt(nn[0] + nn[1]);
+}
+
+static inline Sk2f normalize(const Sk2f& v) {
+ Sk2f vv = v*v;
+ vv += SkNx_shuffle<1,0>(vv);
+ return v * vv.rsqrt();
+}
+
+static inline void transpose(const Sk2f& a, const Sk2f& b, Sk2f* X, Sk2f* Y) {
+ float transpose[4];
+ a.store(transpose);
+ b.store(transpose+2);
+ Sk2f::Load2(transpose, X, Y);
+}
+
+static inline void normalize2(const Sk2f& v0, const Sk2f& v1, SkPoint out[2]) {
+ Sk2f X, Y;
+ transpose(v0, v1, &X, &Y);
+ Sk2f invlength = (X*X + Y*Y).rsqrt();
+ Sk2f::Store2(out, Y * invlength, -X * invlength);
+}
+
+static inline float calc_curvature_costheta(const Sk2f& leftTan, const Sk2f& rightTan) {
+ Sk2f X, Y;
+ transpose(leftTan, rightTan, &X, &Y);
+ Sk2f invlength = (X*X + Y*Y).rsqrt();
+ Sk2f dotprod = leftTan * rightTan;
+ return (dotprod[0] + dotprod[1]) * invlength[0] * invlength[1];
+}
+
+static GrStrokeGeometry::Verb join_verb_from_join(SkPaint::Join join) {
+ using Verb = GrStrokeGeometry::Verb;
+ switch (join) {
+ case SkPaint::kBevel_Join:
+ return Verb::kBevelJoin;
+ case SkPaint::kMiter_Join:
+ return Verb::kMiterJoin;
+ case SkPaint::kRound_Join:
+ return Verb::kRoundJoin;
+ }
+ SK_ABORT("Invalid SkPaint::Join.");
+}
+
+void GrStrokeGeometry::beginPath(const SkStrokeRec& stroke, float strokeDevWidth,
+ InstanceTallies* tallies) {
+ SkASSERT(!fInsideContour);
+ // Client should have already converted the stroke to device space (i.e. width=1 for hairline).
+ SkASSERT(strokeDevWidth > 0);
+
+ fCurrStrokeRadius = strokeDevWidth/2;
+ fCurrStrokeJoinVerb = join_verb_from_join(stroke.getJoin());
+ fCurrStrokeCapType = stroke.getCap();
+ fCurrStrokeTallies = tallies;
+
+ if (Verb::kMiterJoin == fCurrStrokeJoinVerb) {
+ // We implement miters by placing a triangle-shaped cap on top of a bevel join. Convert the
+ // "miter limit" to how tall that triangle cap can be.
+ float m = stroke.getMiter();
+ fMiterMaxCapHeightOverWidth = .5f * SkScalarSqrt(m*m - 1);
+ }
+
+ // Find the angle of curvature where the arc height above a simple line from point A to point B
+ // is equal to kMaxErrorFromLinearization.
+ float r = std::max(1 - kMaxErrorFromLinearization / fCurrStrokeRadius, 0.f);
+ fMaxCurvatureCosTheta = 2*r*r - 1;
+
+ fCurrContourFirstPtIdx = -1;
+ fCurrContourFirstNormalIdx = -1;
+
+ fVerbs.push_back(Verb::kBeginPath);
+}
+
+void GrStrokeGeometry::moveTo(SkPoint pt) {
+ SkASSERT(!fInsideContour);
+ fCurrContourFirstPtIdx = fPoints.count();
+ fCurrContourFirstNormalIdx = fNormals.count();
+ fPoints.push_back(pt);
+ SkDEBUGCODE(fInsideContour = true);
+}
+
+void GrStrokeGeometry::lineTo(SkPoint pt) {
+ SkASSERT(fInsideContour);
+ this->lineTo(fCurrStrokeJoinVerb, pt);
+}
+
+void GrStrokeGeometry::lineTo(Verb leftJoinVerb, SkPoint pt) {
+ Sk2f tan = Sk2f::Load(&pt) - Sk2f::Load(&fPoints.back());
+ if ((tan == 0).allTrue()) {
+ return;
+ }
+
+ tan = normalize(tan);
+ SkVector n = SkVector::Make(tan[1], -tan[0]);
+
+ this->recordLeftJoinIfNotEmpty(leftJoinVerb, n);
+ fNormals.push_back(n);
+
+ this->recordStroke(Verb::kLinearStroke, 0);
+ fPoints.push_back(pt);
+}
+
+void GrStrokeGeometry::quadraticTo(const SkPoint P[3]) {
+ SkASSERT(fInsideContour);
+ this->quadraticTo(fCurrStrokeJoinVerb, P, SkFindQuadMaxCurvature(P));
+}
+
+// Wang's formula for quadratics (1985) gives us the number of evenly spaced (in the parametric
+// sense) line segments that are guaranteed to be within a distance of "kMaxErrorFromLinearization"
+// from the actual curve.
+static inline float wangs_formula_quadratic(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2) {
+ static constexpr float k = 2 / (8 * kMaxErrorFromLinearization);
+ float f = SkScalarSqrt(k * length(p2 - p1*2 + p0));
+ return SkScalarCeilToInt(f);
+}
+
+void GrStrokeGeometry::quadraticTo(Verb leftJoinVerb, const SkPoint P[3], float maxCurvatureT) {
+ Sk2f p0 = Sk2f::Load(P);
+ Sk2f p1 = Sk2f::Load(P+1);
+ Sk2f p2 = Sk2f::Load(P+2);
+
+ Sk2f tan0 = p1 - p0;
+ Sk2f tan1 = p2 - p1;
+
+ // Snap to a "lineTo" if the control point is so close to an endpoint that FP error will become
+ // an issue.
+ if ((tan0.abs() < SK_ScalarNearlyZero).allTrue() || // p0 ~= p1
+ (tan1.abs() < SK_ScalarNearlyZero).allTrue()) { // p1 ~= p2
+ this->lineTo(leftJoinVerb, P[2]);
+ return;
+ }
+
+ SkPoint normals[2];
+ normalize2(tan0, tan1, normals);
+
+ // Decide how many flat line segments to chop the curve into.
+ int numSegments = wangs_formula_quadratic(p0, p1, p2);
+ numSegments = std::min(numSegments, 1 << kMaxNumLinearSegmentsLog2);
+ if (numSegments <= 1) {
+ this->rotateTo(leftJoinVerb, normals[0]);
+ this->lineTo(Verb::kInternalRoundJoin, P[2]);
+ this->rotateTo(Verb::kInternalRoundJoin, normals[1]);
+ return;
+ }
+
+ // At + B gives a vector tangent to the quadratic.
+ Sk2f A = p0 - p1*2 + p2;
+ Sk2f B = p1 - p0;
+
+ // Find a line segment that crosses max curvature.
+ float segmentLength = SkScalarInvert(numSegments);
+ float leftT = maxCurvatureT - segmentLength/2;
+ float rightT = maxCurvatureT + segmentLength/2;
+ Sk2f leftTan, rightTan;
+ if (leftT <= 0) {
+ leftT = 0;
+ leftTan = tan0;
+ rightT = segmentLength;
+ rightTan = A*rightT + B;
+ } else if (rightT >= 1) {
+ leftT = 1 - segmentLength;
+ leftTan = A*leftT + B;
+ rightT = 1;
+ rightTan = tan1;
+ } else {
+ leftTan = A*leftT + B;
+ rightTan = A*rightT + B;
+ }
+
+ // Check if curvature is too strong for a triangle strip on the line segment that crosses max
+ // curvature. If it is, we will chop and convert the segment to a "lineTo" with round joins.
+ //
+ // FIXME: This is quite costly and the vast majority of curves only have moderate curvature. We
+ // would benefit significantly from a quick reject that detects curves that don't need special
+ // treatment for strong curvature.
+ bool isCurvatureTooStrong = calc_curvature_costheta(leftTan, rightTan) < fMaxCurvatureCosTheta;
+ if (isCurvatureTooStrong) {
+ SkPoint ptsBuffer[5];
+ const SkPoint* currQuadratic = P;
+
+ if (leftT > 0) {
+ SkChopQuadAt(currQuadratic, ptsBuffer, leftT);
+ this->quadraticTo(leftJoinVerb, ptsBuffer, /*maxCurvatureT=*/1);
+ if (rightT < 1) {
+ rightT = (rightT - leftT) / (1 - leftT);
+ }
+ currQuadratic = ptsBuffer + 2;
+ } else {
+ this->rotateTo(leftJoinVerb, normals[0]);
+ }
+
+ if (rightT < 1) {
+ SkChopQuadAt(currQuadratic, ptsBuffer, rightT);
+ this->lineTo(Verb::kInternalRoundJoin, ptsBuffer[2]);
+ this->quadraticTo(Verb::kInternalRoundJoin, ptsBuffer + 2, /*maxCurvatureT=*/0);
+ } else {
+ this->lineTo(Verb::kInternalRoundJoin, currQuadratic[2]);
+ this->rotateTo(Verb::kInternalRoundJoin, normals[1]);
+ }
+ return;
+ }
+
+ this->recordLeftJoinIfNotEmpty(leftJoinVerb, normals[0]);
+ fNormals.push_back_n(2, normals);
+
+ this->recordStroke(Verb::kQuadraticStroke, SkNextLog2(numSegments));
+ p1.store(&fPoints.push_back());
+ p2.store(&fPoints.push_back());
+}
+
+void GrStrokeGeometry::cubicTo(const SkPoint P[4]) {
+ SkASSERT(fInsideContour);
+ float roots[3];
+ int numRoots = SkFindCubicMaxCurvature(P, roots);
+ this->cubicTo(fCurrStrokeJoinVerb, P,
+ numRoots > 0 ? roots[numRoots/2] : 0,
+ numRoots > 1 ? roots[0] : kLeftMaxCurvatureNone,
+ numRoots > 2 ? roots[2] : kRightMaxCurvatureNone);
+}
+
+// Wang's formula for cubics (1985) gives us the number of evenly spaced (in the parametric sense)
+// line segments that are guaranteed to be within a distance of "kMaxErrorFromLinearization"
+// from the actual curve.
+static inline float wangs_formula_cubic(const Sk2f& p0, const Sk2f& p1, const Sk2f& p2,
+ const Sk2f& p3) {
+ static constexpr float k = (3 * 2) / (8 * kMaxErrorFromLinearization);
+ float f = SkScalarSqrt(k * length(Sk2f::Max((p2 - p1*2 + p0).abs(),
+ (p3 - p2*2 + p1).abs())));
+ return SkScalarCeilToInt(f);
+}
+
+void GrStrokeGeometry::cubicTo(Verb leftJoinVerb, const SkPoint P[4], float maxCurvatureT,
+ float leftMaxCurvatureT, float rightMaxCurvatureT) {
+ Sk2f p0 = Sk2f::Load(P);
+ Sk2f p1 = Sk2f::Load(P+1);
+ Sk2f p2 = Sk2f::Load(P+2);
+ Sk2f p3 = Sk2f::Load(P+3);
+
+ Sk2f tan0 = p1 - p0;
+ Sk2f tan1 = p3 - p2;
+
+ // Snap control points to endpoints if they are so close that FP error will become an issue.
+ if ((tan0.abs() < SK_ScalarNearlyZero).allTrue()) { // p0 ~= p1
+ p1 = p0;
+ tan0 = p2 - p0;
+ if ((tan0.abs() < SK_ScalarNearlyZero).allTrue()) { // p0 ~= p1 ~= p2
+ this->lineTo(leftJoinVerb, P[3]);
+ return;
+ }
+ }
+ if ((tan1.abs() < SK_ScalarNearlyZero).allTrue()) { // p2 ~= p3
+ p2 = p3;
+ tan1 = p3 - p1;
+ if ((tan1.abs() < SK_ScalarNearlyZero).allTrue() || // p1 ~= p2 ~= p3
+ (p0 == p1).allTrue()) { // p0 ~= p1 AND p2 ~= p3
+ this->lineTo(leftJoinVerb, P[3]);
+ return;
+ }
+ }
+
+ SkPoint normals[2];
+ normalize2(tan0, tan1, normals);
+
+ // Decide how many flat line segments to chop the curve into.
+ int numSegments = wangs_formula_cubic(p0, p1, p2, p3);
+ numSegments = std::min(numSegments, 1 << kMaxNumLinearSegmentsLog2);
+ if (numSegments <= 1) {
+ this->rotateTo(leftJoinVerb, normals[0]);
+ this->lineTo(leftJoinVerb, P[3]);
+ this->rotateTo(Verb::kInternalRoundJoin, normals[1]);
+ return;
+ }
+
+ // At^2 + Bt + C gives a vector tangent to the cubic. (More specifically, it's the derivative
+ // minus an irrelevant scale by 3, since all we care about is the direction.)
+ Sk2f A = p3 + (p1 - p2)*3 - p0;
+ Sk2f B = (p0 - p1*2 + p2)*2;
+ Sk2f C = p1 - p0;
+
+ // Find a line segment that crosses max curvature.
+ float segmentLength = SkScalarInvert(numSegments);
+ float leftT = maxCurvatureT - segmentLength/2;
+ float rightT = maxCurvatureT + segmentLength/2;
+ Sk2f leftTan, rightTan;
+ if (leftT <= 0) {
+ leftT = 0;
+ leftTan = tan0;
+ rightT = segmentLength;
+ rightTan = A*rightT*rightT + B*rightT + C;
+ } else if (rightT >= 1) {
+ leftT = 1 - segmentLength;
+ leftTan = A*leftT*leftT + B*leftT + C;
+ rightT = 1;
+ rightTan = tan1;
+ } else {
+ leftTan = A*leftT*leftT + B*leftT + C;
+ rightTan = A*rightT*rightT + B*rightT + C;
+ }
+
+ // Check if curvature is too strong for a triangle strip on the line segment that crosses max
+ // curvature. If it is, we will chop and convert the segment to a "lineTo" with round joins.
+ //
+ // FIXME: This is quite costly and the vast majority of curves only have moderate curvature. We
+ // would benefit significantly from a quick reject that detects curves that don't need special
+ // treatment for strong curvature.
+ bool isCurvatureTooStrong = calc_curvature_costheta(leftTan, rightTan) < fMaxCurvatureCosTheta;
+ if (isCurvatureTooStrong) {
+ SkPoint ptsBuffer[7];
+ p0.store(ptsBuffer);
+ p1.store(ptsBuffer + 1);
+ p2.store(ptsBuffer + 2);
+ p3.store(ptsBuffer + 3);
+ const SkPoint* currCubic = ptsBuffer;
+
+ if (leftT > 0) {
+ SkChopCubicAt(currCubic, ptsBuffer, leftT);
+ this->cubicTo(leftJoinVerb, ptsBuffer, /*maxCurvatureT=*/1,
+ (kLeftMaxCurvatureNone != leftMaxCurvatureT)
+ ? leftMaxCurvatureT/leftT : kLeftMaxCurvatureNone,
+ kRightMaxCurvatureNone);
+ if (rightT < 1) {
+ rightT = (rightT - leftT) / (1 - leftT);
+ }
+ if (rightMaxCurvatureT < 1 && kRightMaxCurvatureNone != rightMaxCurvatureT) {
+ rightMaxCurvatureT = (rightMaxCurvatureT - leftT) / (1 - leftT);
+ }
+ currCubic = ptsBuffer + 3;
+ } else {
+ this->rotateTo(leftJoinVerb, normals[0]);
+ }
+
+ if (rightT < 1) {
+ SkChopCubicAt(currCubic, ptsBuffer, rightT);
+ this->lineTo(Verb::kInternalRoundJoin, ptsBuffer[3]);
+ currCubic = ptsBuffer + 3;
+ this->cubicTo(Verb::kInternalRoundJoin, currCubic, /*maxCurvatureT=*/0,
+ kLeftMaxCurvatureNone, kRightMaxCurvatureNone);
+ } else {
+ this->lineTo(Verb::kInternalRoundJoin, currCubic[3]);
+ this->rotateTo(Verb::kInternalRoundJoin, normals[1]);
+ }
+ return;
+ }
+
+ // Recurse and check the other two points of max curvature, if any.
+ if (kRightMaxCurvatureNone != rightMaxCurvatureT) {
+ this->cubicTo(leftJoinVerb, P, rightMaxCurvatureT, leftMaxCurvatureT,
+ kRightMaxCurvatureNone);
+ return;
+ }
+ if (kLeftMaxCurvatureNone != leftMaxCurvatureT) {
+ SkASSERT(kRightMaxCurvatureNone == rightMaxCurvatureT);
+ this->cubicTo(leftJoinVerb, P, leftMaxCurvatureT, kLeftMaxCurvatureNone,
+ kRightMaxCurvatureNone);
+ return;
+ }
+
+ this->recordLeftJoinIfNotEmpty(leftJoinVerb, normals[0]);
+ fNormals.push_back_n(2, normals);
+
+ this->recordStroke(Verb::kCubicStroke, SkNextLog2(numSegments));
+ p1.store(&fPoints.push_back());
+ p2.store(&fPoints.push_back());
+ p3.store(&fPoints.push_back());
+}
+
+void GrStrokeGeometry::recordStroke(Verb verb, int numSegmentsLog2) {
+ SkASSERT(Verb::kLinearStroke != verb || 0 == numSegmentsLog2);
+ SkASSERT(numSegmentsLog2 <= kMaxNumLinearSegmentsLog2);
+ fVerbs.push_back(verb);
+ if (Verb::kLinearStroke != verb) {
+ SkASSERT(numSegmentsLog2 > 0);
+ fParams.push_back().fNumLinearSegmentsLog2 = numSegmentsLog2;
+ }
+ ++fCurrStrokeTallies->fStrokes[numSegmentsLog2];
+}
+
+void GrStrokeGeometry::rotateTo(Verb leftJoinVerb, SkVector normal) {
+ this->recordLeftJoinIfNotEmpty(leftJoinVerb, normal);
+ fNormals.push_back(normal);
+}
+
+void GrStrokeGeometry::recordLeftJoinIfNotEmpty(Verb joinVerb, SkVector nextNormal) {
+ if (fNormals.count() <= fCurrContourFirstNormalIdx) {
+ // The contour is empty. Nothing to join with.
+ SkASSERT(fNormals.count() == fCurrContourFirstNormalIdx);
+ return;
+ }
+
+ if (Verb::kBevelJoin == joinVerb) {
+ this->recordBevelJoin(Verb::kBevelJoin);
+ return;
+ }
+
+ Sk2f n0 = Sk2f::Load(&fNormals.back());
+ Sk2f n1 = Sk2f::Load(&nextNormal);
+ Sk2f base = n1 - n0;
+ if ((base.abs() * fCurrStrokeRadius < kMaxErrorFromLinearization).allTrue()) {
+ // Treat any join as a bevel when the outside corners of the two adjoining strokes are
+ // close enough to each other. This is important because "miterCapHeightOverWidth" becomes
+ // unstable when n0 and n1 are nearly equal.
+ this->recordBevelJoin(joinVerb);
+ return;
+ }
+
+ // We implement miters and round joins by placing a triangle-shaped cap on top of a bevel join.
+ // (For round joins this triangle cap comprises the conic control points.) Find how tall to make
+ // this triangle cap, relative to its width.
+ //
+ // NOTE: This value would be infinite at 180 degrees, but we clamp miterCapHeightOverWidth at
+ // near-infinity. 180-degree round joins still look perfectly acceptable like this (though
+ // technically not pure arcs).
+ Sk2f cross = base * SkNx_shuffle<1,0>(n0);
+ Sk2f dot = base * n0;
+ float miterCapHeight = SkScalarAbs(dot[0] + dot[1]);
+ float miterCapWidth = SkScalarAbs(cross[0] - cross[1]) * 2;
+
+ if (Verb::kMiterJoin == joinVerb) {
+ if (miterCapHeight > fMiterMaxCapHeightOverWidth * miterCapWidth) {
+ // This join is tighter than the miter limit. Treat it as a bevel.
+ this->recordBevelJoin(Verb::kMiterJoin);
+ return;
+ }
+ this->recordMiterJoin(miterCapHeight / miterCapWidth);
+ return;
+ }
+
+ SkASSERT(Verb::kRoundJoin == joinVerb || Verb::kInternalRoundJoin == joinVerb);
+
+ // Conic arcs become unstable when they approach 180 degrees. When the conic control point
+ // begins shooting off to infinity (i.e., height/width > 32), split the conic into two.
+ static constexpr float kAlmost180Degrees = 32;
+ if (miterCapHeight > kAlmost180Degrees * miterCapWidth) {
+ Sk2f bisect = normalize(n0 - n1);
+ this->rotateTo(joinVerb, SkVector::Make(-bisect[1], bisect[0]));
+ this->recordLeftJoinIfNotEmpty(joinVerb, nextNormal);
+ return;
+ }
+
+ float miterCapHeightOverWidth = miterCapHeight / miterCapWidth;
+
+ // Find the heights of this round join's conic control point as well as the arc itself.
+ Sk2f X, Y;
+ transpose(base * base, n0 * n1, &X, &Y);
+ Sk2f r = Sk2f::Max(X + Y + Sk2f(0, 1), 0.f).sqrt();
+ Sk2f heights = SkNx_fma(r, Sk2f(miterCapHeightOverWidth, -SK_ScalarRoot2Over2), Sk2f(0, 1));
+ float controlPointHeight = SkScalarAbs(heights[0]);
+ float curveHeight = heights[1];
+ if (curveHeight * fCurrStrokeRadius < kMaxErrorFromLinearization) {
+ // Treat round joins as bevels when their curvature is nearly flat.
+ this->recordBevelJoin(joinVerb);
+ return;
+ }
+
+ float w = curveHeight / (controlPointHeight - curveHeight);
+ this->recordRoundJoin(joinVerb, miterCapHeightOverWidth, w);
+}
+
+void GrStrokeGeometry::recordBevelJoin(Verb originalJoinVerb) {
+ if (!IsInternalJoinVerb(originalJoinVerb)) {
+ fVerbs.push_back(Verb::kBevelJoin);
+ ++fCurrStrokeTallies->fTriangles;
+ } else {
+ fVerbs.push_back(Verb::kInternalBevelJoin);
+ fCurrStrokeTallies->fTriangles += 2;
+ }
+}
+
+void GrStrokeGeometry::recordMiterJoin(float miterCapHeightOverWidth) {
+ fVerbs.push_back(Verb::kMiterJoin);
+ fParams.push_back().fMiterCapHeightOverWidth = miterCapHeightOverWidth;
+ fCurrStrokeTallies->fTriangles += 2;
+}
+
+void GrStrokeGeometry::recordRoundJoin(Verb joinVerb, float miterCapHeightOverWidth,
+ float conicWeight) {
+ fVerbs.push_back(joinVerb);
+ fParams.push_back().fConicWeight = conicWeight;
+ fParams.push_back().fMiterCapHeightOverWidth = miterCapHeightOverWidth;
+ if (Verb::kRoundJoin == joinVerb) {
+ ++fCurrStrokeTallies->fTriangles;
+ ++fCurrStrokeTallies->fConics;
+ } else {
+ SkASSERT(Verb::kInternalRoundJoin == joinVerb);
+ fCurrStrokeTallies->fTriangles += 2;
+ fCurrStrokeTallies->fConics += 2;
+ }
+}
+
+void GrStrokeGeometry::closeContour() {
+ SkASSERT(fInsideContour);
+ SkASSERT(fPoints.count() > fCurrContourFirstPtIdx);
+ if (fPoints.back() != fPoints[fCurrContourFirstPtIdx]) {
+ // Draw a line back to the beginning.
+ this->lineTo(fCurrStrokeJoinVerb, fPoints[fCurrContourFirstPtIdx]);
+ }
+ if (fNormals.count() > fCurrContourFirstNormalIdx) {
+ // Join the first and last lines.
+ this->rotateTo(fCurrStrokeJoinVerb,fNormals[fCurrContourFirstNormalIdx]);
+ } else {
+ // This contour is empty. Add a bogus normal since the iterator always expects one.
+ SkASSERT(fNormals.count() == fCurrContourFirstNormalIdx);
+ fNormals.push_back({0, 0});
+ }
+ fVerbs.push_back(Verb::kEndContour);
+ SkDEBUGCODE(fInsideContour = false);
+}
+
+void GrStrokeGeometry::capContourAndExit() {
+ SkASSERT(fInsideContour);
+ if (fCurrContourFirstNormalIdx >= fNormals.count()) {
+ // This contour is empty. Add a normal in the direction that caps orient on empty geometry.
+ SkASSERT(fNormals.count() == fCurrContourFirstNormalIdx);
+ fNormals.push_back({1, 0});
+ }
+
+ this->recordCapsIfAny();
+ fVerbs.push_back(Verb::kEndContour);
+
+ SkDEBUGCODE(fInsideContour = false);
+}
+
+void GrStrokeGeometry::recordCapsIfAny() {
+ SkASSERT(fInsideContour);
+ SkASSERT(fCurrContourFirstNormalIdx < fNormals.count());
+
+ if (SkPaint::kButt_Cap == fCurrStrokeCapType) {
+ return;
+ }
+
+ Verb capVerb;
+ if (SkPaint::kSquare_Cap == fCurrStrokeCapType) {
+ if (fCurrStrokeRadius * SK_ScalarRoot2Over2 < kMaxErrorFromLinearization) {
+ return;
+ }
+ capVerb = Verb::kSquareCap;
+ fCurrStrokeTallies->fStrokes[0] += 2;
+ } else {
+ SkASSERT(SkPaint::kRound_Cap == fCurrStrokeCapType);
+ if (fCurrStrokeRadius < kMaxErrorFromLinearization) {
+ return;
+ }
+ capVerb = Verb::kRoundCap;
+ fCurrStrokeTallies->fTriangles += 2;
+ fCurrStrokeTallies->fConics += 4;
+ }
+
+ fVerbs.push_back(capVerb);
+ fVerbs.push_back(Verb::kEndContour);
+
+ fVerbs.push_back(capVerb);
+
+ // Reserve the space first, since push_back() takes the point by reference and might
+ // invalidate the reference if the array grows.
+ fPoints.reserve(fPoints.count() + 1);
+ fPoints.push_back(fPoints[fCurrContourFirstPtIdx]);
+
+ // Reserve the space first, since push_back() takes the normal by reference and might
+ // invalidate the reference if the array grows. (Although in this case we should be fine
+ // since there is a negate operator.)
+ fNormals.reserve(fNormals.count() + 1);
+ fNormals.push_back(-fNormals[fCurrContourFirstNormalIdx]);
+}
diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrStrokeGeometry.h b/chromium/third_party/skia/src/gpu/tessellate/GrStrokeGeometry.h
new file mode 100644
index 00000000000..98a85fffac9
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/tessellate/GrStrokeGeometry.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGrStrokeGeometry_DEFINED
+#define GrGrStrokeGeometry_DEFINED
+
+#include "include/core/SkPaint.h"
+#include "include/core/SkPoint.h"
+#include "include/private/SkTArray.h"
+
+class SkStrokeRec;
+
+/**
+ * This class converts post-transform stroked paths into a set of independent strokes, joins, and
+ * caps that map directly to GPU instances.
+ */
+class GrStrokeGeometry {
+public:
+ static constexpr int kMaxNumLinearSegmentsLog2 = 15;
+
+ GrStrokeGeometry(int numSkPoints = 0, int numSkVerbs = 0)
+ : fVerbs(numSkVerbs * 5/2) // Reserve for a 2.5x expansion in verbs. (Joins get their
+ // own separate verb in our representation.)
+ , fParams(numSkVerbs * 3) // Somewhere around 1-2 params per verb.
+ , fPoints(numSkPoints * 5/4) // Reserve for a 1.25x expansion in points and normals.
+ , fNormals(numSkPoints * 5/4) {}
+
+ // A string of verbs and their corresponding, params, points, and normals are a compact
+ // representation of what will eventually be independent instances in GPU buffers.
+ enum class Verb : uint8_t {
+ kBeginPath, // Instructs the iterator to advance its stroke width, atlas offset, etc.
+
+ // Independent strokes of a single line or curve, with (antialiased) butt caps on the ends.
+ kLinearStroke,
+ kQuadraticStroke,
+ kCubicStroke,
+
+ // Joins are a triangles that connect the outer corners of two adjoining strokes. Miters
+ // have an additional triangle cap on top of the bevel, and round joins have an arc on top.
+ kBevelJoin,
+ kMiterJoin,
+ kRoundJoin,
+
+ // We use internal joins when we have to internally break up a stroke because its curvature
+ // is too strong for a triangle strip. They are coverage-counted, self-intersecting
+ // quadrilaterals that tie the four corners of two adjoining strokes together a like a
+ // shoelace. (Coverage is negative on the inside half.) We place an arc on both ends of an
+ // internal round join.
+ kInternalBevelJoin,
+ kInternalRoundJoin,
+
+ kSquareCap,
+ kRoundCap,
+
+ kEndContour // Instructs the iterator to advance its internal point and normal ptrs.
+ };
+ static bool IsInternalJoinVerb(Verb verb);
+
+ // Some verbs require additional parameters(s).
+ union Parameter {
+ // For cubic and quadratic strokes: How many flat line segments to chop the curve into?
+ int fNumLinearSegmentsLog2;
+ // For miter and round joins: How tall should the triangle cap be on top of the join?
+ // (This triangle is the conic control points for a round join.)
+ float fMiterCapHeightOverWidth;
+ float fConicWeight; // Round joins only.
+ };
+
+ const SkTArray<Verb, true>& verbs() const { SkASSERT(!fInsideContour); return fVerbs; }
+ const SkTArray<Parameter, true>& params() const { SkASSERT(!fInsideContour); return fParams; }
+ const SkTArray<SkPoint, true>& points() const { SkASSERT(!fInsideContour); return fPoints; }
+ const SkTArray<SkVector, true>& normals() const { SkASSERT(!fInsideContour); return fNormals; }
+
+ // These track the numbers of instances required to draw all the recorded strokes.
+ struct InstanceTallies {
+ int fStrokes[kMaxNumLinearSegmentsLog2 + 1];
+ int fTriangles;
+ int fConics;
+
+ InstanceTallies operator+(const InstanceTallies&) const;
+ };
+
+ void beginPath(const SkStrokeRec&, float strokeDevWidth, InstanceTallies*);
+ void moveTo(SkPoint);
+ void lineTo(SkPoint);
+ void quadraticTo(const SkPoint[3]);
+ void cubicTo(const SkPoint[4]);
+ void closeContour(); // Connect back to the first point in the contour and exit.
+ void capContourAndExit(); // Add endcaps (if any) and exit the contour.
+
+private:
+ void lineTo(Verb leftJoinVerb, SkPoint);
+ void quadraticTo(Verb leftJoinVerb, const SkPoint[3], float maxCurvatureT);
+
+ static constexpr float kLeftMaxCurvatureNone = 1;
+ static constexpr float kRightMaxCurvatureNone = 0;
+ void cubicTo(Verb leftJoinVerb, const SkPoint[4], float maxCurvatureT, float leftMaxCurvatureT,
+ float rightMaxCurvatureT);
+
+ // Pushes a new normal to fNormals and records a join, without changing the current position.
+ void rotateTo(Verb leftJoinVerb, SkVector normal);
+
+ // Records a stroke in fElememts.
+ void recordStroke(Verb, int numSegmentsLog2);
+
+ // Records a join in fElememts with the previous stroke, if the cuurent contour is not empty.
+ void recordLeftJoinIfNotEmpty(Verb joinType, SkVector nextNormal);
+ void recordBevelJoin(Verb originalJoinVerb);
+ void recordMiterJoin(float miterCapHeightOverWidth);
+ void recordRoundJoin(Verb roundJoinVerb, float miterCapHeightOverWidth, float conicWeight);
+
+ void recordCapsIfAny();
+
+ float fCurrStrokeRadius;
+ Verb fCurrStrokeJoinVerb;
+ SkPaint::Cap fCurrStrokeCapType;
+ InstanceTallies* fCurrStrokeTallies = nullptr;
+
+ // We implement miters by placing a triangle-shaped cap on top of a bevel join. This field tells
+ // us what the miter limit is, restated in terms of how tall that triangle cap can be.
+ float fMiterMaxCapHeightOverWidth;
+
+ // Any curvature on the original curve gets magnified on the outer edge of the stroke,
+ // proportional to how thick the stroke radius is. This field tells us the maximum curvature we
+ // can tolerate using the current stroke radius, before linearization artifacts begin to appear
+ // on the outer edge.
+ //
+ // (Curvature this strong is quite rare in practice, but when it does happen, we decompose the
+ // section with strong curvature into lineTo's with round joins in between.)
+ float fMaxCurvatureCosTheta;
+
+ int fCurrContourFirstPtIdx;
+ int fCurrContourFirstNormalIdx;
+
+ SkDEBUGCODE(bool fInsideContour = false);
+
+ SkSTArray<128, Verb, true> fVerbs;
+ SkSTArray<128, Parameter, true> fParams;
+ SkSTArray<128, SkPoint, true> fPoints;
+ SkSTArray<128, SkVector, true> fNormals;
+};
+
+inline GrStrokeGeometry::InstanceTallies GrStrokeGeometry::InstanceTallies::operator+(
+ const InstanceTallies& t) const {
+ InstanceTallies ret;
+ for (int i = 0; i <= kMaxNumLinearSegmentsLog2; ++i) {
+ ret.fStrokes[i] = fStrokes[i] + t.fStrokes[i];
+ }
+ ret.fTriangles = fTriangles + t.fTriangles;
+ ret.fConics = fConics + t.fConics;
+ return ret;
+}
+
+inline bool GrStrokeGeometry::IsInternalJoinVerb(Verb verb) {
+ switch (verb) {
+ case Verb::kInternalBevelJoin:
+ case Verb::kInternalRoundJoin:
+ return true;
+ case Verb::kBeginPath:
+ case Verb::kLinearStroke:
+ case Verb::kQuadraticStroke:
+ case Verb::kCubicStroke:
+ case Verb::kBevelJoin:
+ case Verb::kMiterJoin:
+ case Verb::kRoundJoin:
+ case Verb::kSquareCap:
+ case Verb::kRoundCap:
+ case Verb::kEndContour:
+ return false;
+ }
+ SK_ABORT("Invalid GrStrokeGeometry::Verb.");
+}
+#endif
diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.cpp b/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.cpp
index 7e0950ac460..4d028b357c4 100644
--- a/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.cpp
+++ b/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.cpp
@@ -14,7 +14,16 @@
#include "src/gpu/tessellate/GrFillPathShader.h"
#include "src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h"
#include "src/gpu/tessellate/GrMidpointContourParser.h"
+#include "src/gpu/tessellate/GrResolveLevelCounter.h"
#include "src/gpu/tessellate/GrStencilPathShader.h"
+#include "src/gpu/tessellate/GrTessellationPathRenderer.h"
+
+constexpr static float kLinearizationIntolerance =
+ GrTessellationPathRenderer::kLinearizationIntolerance;
+
+constexpr static int kMaxResolveLevel = GrTessellationPathRenderer::kMaxResolveLevel;
+
+using OpFlags = GrTessellationPathRenderer::OpFlags;
GrTessellatePathOp::FixedFunctionFlags GrTessellatePathOp::fixedFunctionFlags() const {
auto flags = FixedFunctionFlags::kUsesStencil;
@@ -30,50 +39,68 @@ void GrTessellatePathOp::onPrePrepare(GrRecordingContext*,
const GrXferProcessor::DstProxyView&) {
}
-void GrTessellatePathOp::onPrepare(GrOpFlushState* state) {
+void GrTessellatePathOp::onPrepare(GrOpFlushState* flushState) {
+ int numVerbs = fPath.countVerbs();
+ if (numVerbs <= 0) {
+ return;
+ }
+
// First check if the path is large and/or simple enough that we can actually triangulate the
// inner polygon(s) on the CPU. This is our fastest approach. It allows us to stencil only the
- // curves, and then fill the internal polygons directly to the final render target, thus filling
- // in the majority of pixels in a single render pass.
+ // curves, and then fill the internal polygons directly to the final render target, thus drawing
+ // the majority of pixels in a single render pass.
SkScalar scales[2];
SkAssertResult(fViewMatrix.getMinMaxScales(scales)); // Will fail if perspective.
const SkRect& bounds = fPath.getBounds();
- int numVerbs = fPath.countVerbs();
- if (numVerbs <= 0) {
- return;
- }
float gpuFragmentWork = bounds.height() * scales[0] * bounds.width() * scales[1];
float cpuTessellationWork = (float)numVerbs * SkNextLog2(numVerbs); // N log N.
if (cpuTessellationWork * 500 + (256 * 256) < gpuFragmentWork) { // Don't try below 256x256.
- int numCountedCurves;
+ int numCountedCubics;
// This will fail if the inner triangles do not form a simple polygon (e.g., self
// intersection, double winding).
- if (this->prepareNonOverlappingInnerTriangles(state, &numCountedCurves)) {
- // Prepare cubics on an instance boundary so we can use the buffer to fill local convex
- // hulls as well.
- this->prepareOuterCubics(state, numCountedCurves,
- CubicDataAlignment::kInstanceBoundary);
+ if (this->prepareNonOverlappingInnerTriangles(flushState, &numCountedCubics)) {
+ if (!numCountedCubics) {
+ return;
+ }
+ // Always use indirect draws for cubics instead of tessellation here. Our goal in this
+ // mode is to maximize GPU performance, and the middle-out topology used by our indirect
+ // draws is easier on the rasterizer than a tessellated fan. There also seems to be a
+ // small amount of fixed tessellation overhead that this avoids.
+ GrResolveLevelCounter resolveLevelCounter;
+ resolveLevelCounter.reset(fPath, fViewMatrix, kLinearizationIntolerance);
+ this->prepareIndirectOuterCubics(flushState, resolveLevelCounter);
return;
}
}
- // Next see if we can split up inner polygon triangles and curves, and triangulate the inner
- // polygon(s) more efficiently. This causes greater CPU overhead due to the extra shaders and
- // draw calls, but the better triangulation can reduce the rasterizer load by a great deal on
- // complex paths.
+ // When there are only a few verbs, it seems to always be fastest to make a single indirect draw
+ // that contains both the inner triangles and the outer cubics, instead of using hardware
+ // tessellation. Also take this path if tessellation is not supported.
+ bool drawTrianglesAsIndirectCubicDraw = (numVerbs < 50);
+ if (drawTrianglesAsIndirectCubicDraw || (fOpFlags & OpFlags::kDisableHWTessellation)) {
+ // Prepare outer cubics with indirect draws.
+ GrResolveLevelCounter resolveLevelCounter;
+ this->prepareMiddleOutTrianglesAndCubics(flushState, &resolveLevelCounter,
+ drawTrianglesAsIndirectCubicDraw);
+ return;
+ }
+
+ // The caller should have sent Flags::kDisableHWTessellation if it was not supported.
+ SkASSERT(flushState->caps().shaderCaps()->tessellationSupport());
+
+ // Next see if we can split up the inner triangles and outer cubics into two draw calls. This
+ // allows for a more efficient inner triangle topology that can reduce the rasterizer load by a
+ // large margin on complex paths, but also causes greater CPU overhead due to the extra shader
+ // switches and draw calls.
// NOTE: Raster-edge work is 1-dimensional, so we sum height and width instead of multiplying.
float rasterEdgeWork = (bounds.height() + bounds.width()) * scales[1] * fPath.countVerbs();
- if (rasterEdgeWork > 1000 * 1000) {
- int numCountedCurves;
- this->prepareMiddleOutInnerTriangles(state, &numCountedCurves);
- // We will fill the path with a bounding box instead local cubic convex hulls, so there is
- // no need to prepare the cubics on an instance boundary.
- this->prepareOuterCubics(state, numCountedCurves, CubicDataAlignment::kVertexBoundary);
+ if (rasterEdgeWork > 300 * 300) {
+ this->prepareMiddleOutTrianglesAndCubics(flushState);
return;
}
// Fastest CPU approach: emit one cubic wedge per verb, fanning out from the center.
- this->prepareCubicWedges(state);
+ this->prepareTessellatedCubicWedges(flushState);
}
bool GrTessellatePathOp::prepareNonOverlappingInnerTriangles(GrMeshDrawOp::Target* target,
@@ -93,52 +120,88 @@ bool GrTessellatePathOp::prepareNonOverlappingInnerTriangles(GrMeshDrawOp::Targe
// simple.
return false;
}
- if (((Flags::kStencilOnly | Flags::kWireframe) & fFlags) || GrAAType::kCoverage == fAAType ||
+ if (((OpFlags::kStencilOnly | OpFlags::kWireframe) & fOpFlags) ||
+ GrAAType::kCoverage == fAAType ||
(target->appliedClip() && target->appliedClip()->hasStencilClip())) {
// If we have certain flags, mixed samples, or a stencil clip then we unfortunately
// can't fill the inner polygon directly. Indicate that these triangles need to be
// stencilled.
fDoStencilTriangleBuffer = true;
}
- if (!(Flags::kStencilOnly & fFlags)) {
+ if (!(OpFlags::kStencilOnly & fOpFlags)) {
fDoFillTriangleBuffer = true;
}
return true;
}
-void GrTessellatePathOp::prepareMiddleOutInnerTriangles(GrMeshDrawOp::Target* target,
- int* numCountedCurves) {
+void GrTessellatePathOp::prepareMiddleOutTrianglesAndCubics(
+ GrMeshDrawOp::Target* target, GrResolveLevelCounter* resolveLevelCounter,
+ bool drawTrianglesAsIndirectCubicDraw) {
SkASSERT(!fTriangleBuffer);
SkASSERT(!fDoStencilTriangleBuffer);
SkASSERT(!fDoFillTriangleBuffer);
+ SkASSERT(!fCubicBuffer);
+ SkASSERT(!fStencilCubicsShader);
+ SkASSERT(!fIndirectDrawBuffer);
// No initial moveTo, plus an implicit close at the end; n-2 triangles fill an n-gon.
- // Each triangle has 3 vertices.
- int maxVertices = (fPath.countVerbs() - 1) * 3;
-
- GrEagerDynamicVertexAllocator vertexAlloc(target, &fTriangleBuffer, &fBaseTriangleVertex);
- auto* vertexData = vertexAlloc.lock<SkPoint>(maxVertices);
+ int maxInnerTriangles = fPath.countVerbs() - 1;
+ int maxCubics = fPath.countVerbs();
+
+ SkPoint* vertexData;
+ int vertexAdvancePerTriangle;
+ if (drawTrianglesAsIndirectCubicDraw) {
+ // Allocate the triangles as 4-point instances at the beginning of the cubic buffer.
+ SkASSERT(resolveLevelCounter);
+ vertexAdvancePerTriangle = 4;
+ int baseTriangleInstance;
+ vertexData = static_cast<SkPoint*>(target->makeVertexSpace(
+ sizeof(SkPoint) * 4, maxInnerTriangles + maxCubics, &fCubicBuffer,
+ &baseTriangleInstance));
+ fBaseCubicVertex = baseTriangleInstance * 4;
+ } else {
+ // Allocate the triangles as normal 3-point instances in the triangle buffer.
+ vertexAdvancePerTriangle = 3;
+ vertexData = static_cast<SkPoint*>(target->makeVertexSpace(
+ sizeof(SkPoint), maxInnerTriangles * 3, &fTriangleBuffer, &fBaseTriangleVertex));
+ }
if (!vertexData) {
return;
}
- GrMiddleOutPolygonTriangulator middleOut(vertexData, maxVertices);
- int localCurveCount = 0;
+ GrVectorXform xform(fViewMatrix);
+ GrMiddleOutPolygonTriangulator middleOut(vertexData, vertexAdvancePerTriangle,
+ fPath.countVerbs());
+ if (resolveLevelCounter) {
+ resolveLevelCounter->reset();
+ }
+ int numCountedCurves = 0;
for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
switch (verb) {
case SkPathVerb::kMove:
- middleOut.closeAndMove(*pts++);
+ middleOut.closeAndMove(pts[0]);
break;
case SkPathVerb::kLine:
middleOut.pushVertex(pts[1]);
break;
case SkPathVerb::kQuad:
middleOut.pushVertex(pts[2]);
- ++localCurveCount;
+ if (resolveLevelCounter) {
+ // Quadratics get converted to cubics before rendering.
+ resolveLevelCounter->countCubic(GrWangsFormula::quadratic_log2(
+ kLinearizationIntolerance, pts, xform));
+ break;
+ }
+ ++numCountedCurves;
break;
case SkPathVerb::kCubic:
middleOut.pushVertex(pts[3]);
- ++localCurveCount;
+ if (resolveLevelCounter) {
+ resolveLevelCounter->countCubic(GrWangsFormula::cubic_log2(
+ kLinearizationIntolerance, pts, xform));
+ break;
+ }
+ ++numCountedCurves;
break;
case SkPathVerb::kClose:
middleOut.close();
@@ -147,13 +210,31 @@ void GrTessellatePathOp::prepareMiddleOutInnerTriangles(GrMeshDrawOp::Target* ta
SkUNREACHABLE;
}
}
- fTriangleVertexCount = middleOut.close();
- *numCountedCurves = localCurveCount;
-
- vertexAlloc.unlock(fTriangleVertexCount);
-
- if (fTriangleVertexCount) {
- fDoStencilTriangleBuffer = true;
+ int triangleCount = middleOut.close();
+ SkASSERT(triangleCount <= maxInnerTriangles);
+
+ if (drawTrianglesAsIndirectCubicDraw) {
+ SkASSERT(resolveLevelCounter);
+ int totalInstanceCount = triangleCount + resolveLevelCounter->totalCubicInstanceCount();
+ SkASSERT(vertexAdvancePerTriangle == 4);
+ target->putBackVertices(maxInnerTriangles + maxCubics - totalInstanceCount,
+ sizeof(SkPoint) * 4);
+ if (totalInstanceCount) {
+ this->prepareIndirectOuterCubicsAndTriangles(target, *resolveLevelCounter, vertexData,
+ triangleCount);
+ }
+ } else {
+ SkASSERT(vertexAdvancePerTriangle == 3);
+ target->putBackVertices(maxInnerTriangles - triangleCount, sizeof(SkPoint) * 3);
+ fTriangleVertexCount = triangleCount * 3;
+ if (fTriangleVertexCount) {
+ fDoStencilTriangleBuffer = true;
+ }
+ if (resolveLevelCounter) {
+ this->prepareIndirectOuterCubics(target, *resolveLevelCounter);
+ } else {
+ this->prepareTessellatedOuterCubics(target, numCountedCurves);
+ }
}
}
@@ -176,8 +257,141 @@ static void quad2cubic(const SkPoint pts[], SkPoint* out) {
out[3] = pts[2];
}
-void GrTessellatePathOp::prepareOuterCubics(GrMeshDrawOp::Target* target, int numCountedCurves,
- CubicDataAlignment alignment) {
+void GrTessellatePathOp::prepareIndirectOuterCubics(
+ GrMeshDrawOp::Target* target, const GrResolveLevelCounter& resolveLevelCounter) {
+ SkASSERT(resolveLevelCounter.totalCubicInstanceCount() >= 0);
+ if (resolveLevelCounter.totalCubicInstanceCount() == 0) {
+ return;
+ }
+ // Allocate a buffer to store the cubic data.
+ SkPoint* cubicData;
+ int baseInstance;
+ cubicData = static_cast<SkPoint*>(target->makeVertexSpace(
+ sizeof(SkPoint) * 4, resolveLevelCounter.totalCubicInstanceCount(), &fCubicBuffer,
+ &baseInstance));
+ if (!cubicData) {
+ return;
+ }
+ fBaseCubicVertex = baseInstance * 4;
+ this->prepareIndirectOuterCubicsAndTriangles(target, resolveLevelCounter, cubicData,
+ /*numTrianglesAtBeginningOfData=*/0);
+}
+
+void GrTessellatePathOp::prepareIndirectOuterCubicsAndTriangles(
+ GrMeshDrawOp::Target* target, const GrResolveLevelCounter& resolveLevelCounter,
+ SkPoint* cubicData, int numTrianglesAtBeginningOfData) {
+ SkASSERT(target->caps().drawInstancedSupport());
+ SkASSERT(numTrianglesAtBeginningOfData + resolveLevelCounter.totalCubicInstanceCount() > 0);
+ SkASSERT(!fStencilCubicsShader);
+ SkASSERT(cubicData);
+
+ fIndirectIndexBuffer = GrMiddleOutCubicShader::FindOrMakeMiddleOutIndexBuffer(
+ target->resourceProvider());
+ if (!fIndirectIndexBuffer) {
+ return;
+ }
+
+ // Here we treat fCubicBuffer as an instance buffer. It should have been prepared with the base
+ // vertex on an instance boundary in order to accommodate this.
+ SkASSERT(fBaseCubicVertex % 4 == 0);
+ int baseInstance = fBaseCubicVertex >> 2;
+
+ // Start preparing the indirect draw buffer.
+ fIndirectDrawCount = resolveLevelCounter.totalCubicIndirectDrawCount();
+ if (numTrianglesAtBeginningOfData) {
+ ++fIndirectDrawCount; // Add an indirect draw for the triangles at the beginning.
+ }
+
+ // Allocate space for the GrDrawIndexedIndirectCommand structs.
+ GrDrawIndexedIndirectCommand* indirectData = target->makeDrawIndexedIndirectSpace(
+ fIndirectDrawCount, &fIndirectDrawBuffer, &fIndirectDrawOffset);
+ if (!indirectData) {
+ SkASSERT(!fIndirectDrawBuffer);
+ return;
+ }
+
+ // Fill out the GrDrawIndexedIndirectCommand structs and determine the starting instance data
+ // location at each resolve level.
+ SkPoint* instanceLocations[kMaxResolveLevel + 1];
+ int indirectIdx = 0;
+ int runningInstanceCount = 0;
+ if (numTrianglesAtBeginningOfData) {
+ // The caller has already packed "triangleInstanceCount" triangles into 4-point instances
+ // at the beginning of the instance buffer. Add a special-case indirect draw here that will
+ // emit the triangles [P0, P1, P2] from these 4-point instances.
+ indirectData[0] = GrMiddleOutCubicShader::MakeDrawTrianglesIndirectCmd(
+ numTrianglesAtBeginningOfData, baseInstance);
+ indirectIdx = 1;
+ runningInstanceCount = numTrianglesAtBeginningOfData;
+ }
+ for (int resolveLevel = 1; resolveLevel <= kMaxResolveLevel; ++resolveLevel) {
+ instanceLocations[resolveLevel] = cubicData + runningInstanceCount * 4;
+ if (int instanceCountAtCurrLevel = resolveLevelCounter[resolveLevel]) {
+ indirectData[indirectIdx++] = GrMiddleOutCubicShader::MakeDrawCubicsIndirectCmd(
+ resolveLevel, instanceCountAtCurrLevel, baseInstance + runningInstanceCount);
+ runningInstanceCount += instanceCountAtCurrLevel;
+ }
+ }
+
+#ifdef SK_DEBUG
+ SkASSERT(indirectIdx == fIndirectDrawCount);
+ SkASSERT(runningInstanceCount == numTrianglesAtBeginningOfData +
+ resolveLevelCounter.totalCubicInstanceCount());
+ SkASSERT(fIndirectDrawCount > 0);
+
+ SkPoint* endLocations[kMaxResolveLevel + 1];
+ memcpy(endLocations, instanceLocations + 1, kMaxResolveLevel * sizeof(SkPoint*));
+ int totalInstanceCount = numTrianglesAtBeginningOfData +
+ resolveLevelCounter.totalCubicInstanceCount();
+ endLocations[kMaxResolveLevel] = cubicData + totalInstanceCount * 4;
+#endif
+
+ fCubicVertexCount = numTrianglesAtBeginningOfData * 4;
+
+ if (resolveLevelCounter.totalCubicInstanceCount()) {
+ GrVectorXform xform(fViewMatrix);
+ for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
+ int level;
+ switch (verb) {
+ default:
+ continue;
+ case SkPathVerb::kQuad:
+ level = GrWangsFormula::quadratic_log2(kLinearizationIntolerance, pts, xform);
+ if (level == 0) {
+ continue;
+ }
+ level = std::min(level, kMaxResolveLevel);
+ quad2cubic(pts, instanceLocations[level]);
+ break;
+ case SkPathVerb::kCubic:
+ level = GrWangsFormula::cubic_log2(kLinearizationIntolerance, pts, xform);
+ if (level == 0) {
+ continue;
+ }
+ level = std::min(level, kMaxResolveLevel);
+ memcpy(instanceLocations[level], pts, sizeof(SkPoint) * 4);
+ break;
+ }
+ instanceLocations[level] += 4;
+ fCubicVertexCount += 4;
+ }
+ }
+
+#ifdef SK_DEBUG
+ for (int i = 1; i <= kMaxResolveLevel; ++i) {
+ SkASSERT(instanceLocations[i] == endLocations[i]);
+ }
+ SkASSERT(fCubicVertexCount == (numTrianglesAtBeginningOfData +
+ resolveLevelCounter.totalCubicInstanceCount()) * 4);
+#endif
+
+ fStencilCubicsShader = target->allocator()->make<GrMiddleOutCubicShader>(fViewMatrix);
+}
+
+void GrTessellatePathOp::prepareTessellatedOuterCubics(GrMeshDrawOp::Target* target,
+ int numCountedCurves) {
+ SkASSERT(target->caps().shaderCaps()->tessellationSupport());
+ SkASSERT(numCountedCurves >= 0);
SkASSERT(!fCubicBuffer);
SkASSERT(!fStencilCubicsShader);
@@ -185,41 +399,35 @@ void GrTessellatePathOp::prepareOuterCubics(GrMeshDrawOp::Target* target, int nu
return;
}
- bool instanceAligned = (alignment == CubicDataAlignment::kInstanceBoundary);
- int instanceOrVertexStride = (instanceAligned) ? sizeof(SkPoint) * 4 : sizeof(SkPoint);
- int instanceOrVertexCount = (instanceAligned) ? numCountedCurves : numCountedCurves * 4;
- int baseInstanceOrVertex;
-
auto* vertexData = static_cast<SkPoint*>(target->makeVertexSpace(
- instanceOrVertexStride, instanceOrVertexCount, &fCubicBuffer, &baseInstanceOrVertex));
+ sizeof(SkPoint), numCountedCurves * 4, &fCubicBuffer, &fBaseCubicVertex));
if (!vertexData) {
return;
}
- fBaseCubicVertex = (instanceAligned) ? baseInstanceOrVertex * 4 : baseInstanceOrVertex;
fCubicVertexCount = 0;
for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
switch (verb) {
+ default:
+ continue;
case SkPathVerb::kQuad:
SkASSERT(fCubicVertexCount < numCountedCurves * 4);
quad2cubic(pts, vertexData + fCubicVertexCount);
- fCubicVertexCount += 4;
break;
case SkPathVerb::kCubic:
SkASSERT(fCubicVertexCount < numCountedCurves * 4);
memcpy(vertexData + fCubicVertexCount, pts, sizeof(SkPoint) * 4);
- fCubicVertexCount += 4;
- break;
- default:
break;
}
+ fCubicVertexCount += 4;
}
SkASSERT(fCubicVertexCount == numCountedCurves * 4);
- fStencilCubicsShader = target->allocator()->make<GrStencilCubicShader>(fViewMatrix);
+ fStencilCubicsShader = target->allocator()->make<GrTessellateCubicShader>(fViewMatrix);
}
-void GrTessellatePathOp::prepareCubicWedges(GrMeshDrawOp::Target* target) {
+void GrTessellatePathOp::prepareTessellatedCubicWedges(GrMeshDrawOp::Target* target) {
+ SkASSERT(target->caps().shaderCaps()->tessellationSupport());
SkASSERT(!fCubicBuffer);
SkASSERT(!fStencilCubicsShader);
@@ -274,18 +482,18 @@ void GrTessellatePathOp::prepareCubicWedges(GrMeshDrawOp::Target* target) {
vertexAlloc.unlock(fCubicVertexCount);
if (fCubicVertexCount) {
- fStencilCubicsShader = target->allocator()->make<GrStencilWedgeShader>(fViewMatrix);
+ fStencilCubicsShader = target->allocator()->make<GrTessellateWedgeShader>(fViewMatrix);
}
}
-void GrTessellatePathOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
- this->drawStencilPass(state);
- if (!(Flags::kStencilOnly & fFlags)) {
- this->drawCoverPass(state);
+void GrTessellatePathOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
+ this->drawStencilPass(flushState);
+ if (!(OpFlags::kStencilOnly & fOpFlags)) {
+ this->drawCoverPass(flushState);
}
}
-void GrTessellatePathOp::drawStencilPass(GrOpFlushState* state) {
+void GrTessellatePathOp::drawStencilPass(GrOpFlushState* flushState) {
// Increments clockwise triangles and decrements counterclockwise. Used for "winding" fill.
constexpr static GrUserStencilSettings kIncrDecrStencil(
GrUserStencilSettings::StaticInitSeparate<
@@ -310,41 +518,48 @@ void GrTessellatePathOp::drawStencilPass(GrOpFlushState* state) {
if (GrAAType::kNone != fAAType) {
initArgs.fInputFlags |= GrPipeline::InputFlags::kHWAntialias;
}
- if (state->caps().wireframeSupport() && (Flags::kWireframe & fFlags)) {
+ if (flushState->caps().wireframeSupport() && (OpFlags::kWireframe & fOpFlags)) {
initArgs.fInputFlags |= GrPipeline::InputFlags::kWireframe;
}
SkASSERT(SkPathFillType::kWinding == fPath.getFillType() ||
SkPathFillType::kEvenOdd == fPath.getFillType());
initArgs.fUserStencil = (SkPathFillType::kWinding == fPath.getFillType()) ?
&kIncrDecrStencil : &kInvertStencil;
- initArgs.fCaps = &state->caps();
+ initArgs.fCaps = &flushState->caps();
GrPipeline pipeline(initArgs, GrDisableColorXPFactory::MakeXferProcessor(),
- state->appliedHardClip());
+ flushState->appliedHardClip());
if (fDoStencilTriangleBuffer) {
SkASSERT(fTriangleBuffer);
GrStencilTriangleShader stencilTriangleShader(fViewMatrix);
- GrPathShader::ProgramInfo programInfo(state->writeView(), &pipeline,
+ GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline,
&stencilTriangleShader);
- state->bindPipelineAndScissorClip(programInfo, this->bounds());
- state->bindBuffers(nullptr, nullptr, fTriangleBuffer.get());
- state->draw(fTriangleVertexCount, fBaseTriangleVertex);
+ flushState->bindPipelineAndScissorClip(programInfo, this->bounds());
+ flushState->bindBuffers(nullptr, nullptr, fTriangleBuffer.get());
+ flushState->draw(fTriangleVertexCount, fBaseTriangleVertex);
}
if (fStencilCubicsShader) {
- GrPathShader::ProgramInfo programInfo(state->writeView(), &pipeline, fStencilCubicsShader);
- state->bindPipelineAndScissorClip(programInfo, this->bounds());
- state->bindBuffers(nullptr, nullptr, fCubicBuffer.get());
- state->draw(fCubicVertexCount, fBaseCubicVertex);
- }
-
- // http://skbug.com/9739
- if (state->caps().requiresManualFBBarrierAfterTessellatedStencilDraw()) {
- state->gpu()->insertManualFramebufferBarrier();
+ SkASSERT(fCubicBuffer);
+ GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline,
+ fStencilCubicsShader);
+ flushState->bindPipelineAndScissorClip(programInfo, this->bounds());
+ if (fIndirectDrawBuffer) {
+ SkASSERT(fIndirectIndexBuffer);
+ flushState->bindBuffers(fIndirectIndexBuffer.get(), fCubicBuffer.get(), nullptr);
+ flushState->drawIndexedIndirect(fIndirectDrawBuffer.get(), fIndirectDrawOffset,
+ fIndirectDrawCount);
+ } else {
+ flushState->bindBuffers(nullptr, nullptr, fCubicBuffer.get());
+ flushState->draw(fCubicVertexCount, fBaseCubicVertex);
+ if (flushState->caps().requiresManualFBBarrierAfterTessellatedStencilDraw()) {
+ flushState->gpu()->insertManualFramebufferBarrier(); // http://skbug.com/9739
+ }
+ }
}
}
-void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state) {
+void GrTessellatePathOp::drawCoverPass(GrOpFlushState* flushState) {
// Allows non-zero stencil values to pass and write a color, and resets the stencil value back
// to zero; discards immediately on stencil values of zero.
// NOTE: It's ok to not check the clip here because the previous stencil pass only wrote to
@@ -361,7 +576,7 @@ void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state) {
GrPipeline::InitArgs initArgs;
if (GrAAType::kNone != fAAType) {
initArgs.fInputFlags |= GrPipeline::InputFlags::kHWAntialias;
- if (1 == state->proxy()->numSamples()) {
+ if (1 == flushState->proxy()->numSamples()) {
SkASSERT(GrAAType::kCoverage == fAAType);
// We are mixed sampled. Use conservative raster to make the sample coverage mask 100%
// at every fragment. This way we will still get a double hit on shared edges, but
@@ -370,10 +585,10 @@ void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state) {
initArgs.fInputFlags |= GrPipeline::InputFlags::kConservativeRaster;
}
}
- initArgs.fCaps = &state->caps();
- initArgs.fDstProxyView = state->drawOpArgs().dstProxyView();
- initArgs.fWriteSwizzle = state->drawOpArgs().writeSwizzle();
- GrPipeline pipeline(initArgs, std::move(fProcessors), state->detachAppliedClip());
+ initArgs.fCaps = &flushState->caps();
+ initArgs.fDstProxyView = flushState->drawOpArgs().dstProxyView();
+ initArgs.fWriteSwizzle = flushState->drawOpArgs().writeSwizzle();
+ GrPipeline pipeline(initArgs, std::move(fProcessors), flushState->detachAppliedClip());
if (fDoFillTriangleBuffer) {
SkASSERT(fTriangleBuffer);
@@ -420,29 +635,32 @@ void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state) {
}
GrFillTriangleShader fillTriangleShader(fViewMatrix, fColor);
- GrPathShader::ProgramInfo programInfo(state->writeView(), &pipeline, &fillTriangleShader);
- state->bindPipelineAndScissorClip(programInfo, this->bounds());
- state->bindTextures(fillTriangleShader, nullptr, pipeline);
- state->bindBuffers(nullptr, nullptr, fTriangleBuffer.get());
- state->draw(fTriangleVertexCount, fBaseTriangleVertex);
+ GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline,
+ &fillTriangleShader);
+ flushState->bindPipelineAndScissorClip(programInfo, this->bounds());
+ flushState->bindTextures(fillTriangleShader, nullptr, pipeline);
+ flushState->bindBuffers(nullptr, nullptr, fTriangleBuffer.get());
+ flushState->draw(fTriangleVertexCount, fBaseTriangleVertex);
if (fStencilCubicsShader) {
+ SkASSERT(fCubicBuffer);
+
// At this point, every pixel is filled in except the ones touched by curves. Issue a
// final cover pass over the curves by drawing their convex hulls. This will fill in any
// remaining samples and reset the stencil buffer.
pipeline.setUserStencil(&kTestAndResetStencil);
GrFillCubicHullShader fillCubicHullShader(fViewMatrix, fColor);
- GrPathShader::ProgramInfo programInfo(state->writeView(), &pipeline,
+ GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline,
&fillCubicHullShader);
- state->bindPipelineAndScissorClip(programInfo, this->bounds());
- state->bindTextures(fillCubicHullShader, nullptr, pipeline);
+ flushState->bindPipelineAndScissorClip(programInfo, this->bounds());
+ flushState->bindTextures(fillCubicHullShader, nullptr, pipeline);
// Here we treat fCubicBuffer as an instance buffer. It should have been prepared with
// the base vertex on an instance boundary in order to accommodate this.
SkASSERT((fCubicVertexCount % 4) == 0);
SkASSERT((fBaseCubicVertex % 4) == 0);
- state->bindBuffers(nullptr, fCubicBuffer.get(), nullptr);
- state->drawInstanced(fCubicVertexCount >> 2, fBaseCubicVertex >> 2, 4, 0);
+ flushState->bindBuffers(nullptr, fCubicBuffer.get(), nullptr);
+ flushState->drawInstanced(fCubicVertexCount >> 2, fBaseCubicVertex >> 2, 4, 0);
}
return;
}
@@ -450,9 +668,10 @@ void GrTessellatePathOp::drawCoverPass(GrOpFlushState* state) {
// There are no triangles to fill. Just draw a bounding box.
pipeline.setUserStencil(&kTestAndResetStencil);
GrFillBoundingBoxShader fillBoundingBoxShader(fViewMatrix, fColor, fPath.getBounds());
- GrPathShader::ProgramInfo programInfo(state->writeView(), &pipeline, &fillBoundingBoxShader);
- state->bindPipelineAndScissorClip(programInfo, this->bounds());
- state->bindTextures(fillBoundingBoxShader, nullptr, pipeline);
- state->bindBuffers(nullptr, nullptr, nullptr);
- state->draw(4, 0);
+ GrPathShader::ProgramInfo programInfo(flushState->writeView(), &pipeline,
+ &fillBoundingBoxShader);
+ flushState->bindPipelineAndScissorClip(programInfo, this->bounds());
+ flushState->bindTextures(fillBoundingBoxShader, nullptr, pipeline);
+ flushState->bindBuffers(nullptr, nullptr, nullptr);
+ flushState->draw(4, 0);
}
diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.h b/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.h
index 8ee6d21bd65..c53e194a7f1 100644
--- a/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.h
+++ b/chromium/third_party/skia/src/gpu/tessellate/GrTessellatePathOp.h
@@ -9,28 +9,23 @@
#define GrTessellatePathOp_DEFINED
#include "src/gpu/ops/GrMeshDrawOp.h"
+#include "src/gpu/tessellate/GrTessellationPathRenderer.h"
class GrAppliedHardClip;
class GrStencilPathShader;
+class GrResolveLevelCounter;
-// Renders paths using a hybrid Red Book "stencil, then cover" method. Curves get linearized by
-// GPU tessellation shaders. This Op doesn't apply analytic AA, so it requires a render target that
-// supports either MSAA or mixed samples if AA is desired.
+// Renders paths using a hybrid "Red Book" (stencil, then cover) method. Curves get linearized by
+// either GPU tessellation shaders or indirect draws. This Op doesn't apply analytic AA, so it
+// requires a render target that supports either MSAA or mixed samples if AA is desired.
class GrTessellatePathOp : public GrDrawOp {
-public:
- enum class Flags {
- kNone = 0,
- kStencilOnly = (1 << 0),
- kWireframe = (1 << 1)
- };
-
private:
DEFINE_OP_CLASS_ID
GrTessellatePathOp(const SkMatrix& viewMatrix, const SkPath& path, GrPaint&& paint,
- GrAAType aaType, Flags flags = Flags::kNone)
+ GrAAType aaType, GrTessellationPathRenderer::OpFlags opFlags)
: GrDrawOp(ClassID())
- , fFlags(flags)
+ , fOpFlags(opFlags)
, fViewMatrix(viewMatrix)
, fPath(path)
, fAAType(aaType)
@@ -66,25 +61,41 @@ private:
// and this is not an option as it would introduce T-junctions with the outer cubics.
bool prepareNonOverlappingInnerTriangles(GrMeshDrawOp::Target*, int* numCountedCurves);
- // Produces a "Red Book" style triangulation of the SkPath's inner polygon(s). The inner
- // polygons connect the endpoints of each verb. (i.e., they are the path that would result from
- // collapsing all curves to single lines.) Stencilled together with the outer cubics, these
- // define the complete path.
+ // Produces a "Red Book" style triangulation of the SkPath's inner polygon(s) using a
+ // "middle-out" topology (See GrMiddleOutPolygonTriangulator), and then prepares outer cubics in
+ // the cubic buffer. The inner triangles and outer cubics stencilled together define the
+ // complete path.
//
- // This method emits the inner triangles with a "middle-out" topology. Middle-out can reduce
- // the load on the rasterizer by a great deal as compared to a linear triangle strip or fan.
- // See GrMiddleOutPolygonTriangulator.
- void prepareMiddleOutInnerTriangles(GrMeshDrawOp::Target*, int* numCountedCurves);
-
- enum class CubicDataAlignment : bool {
- kVertexBoundary,
- kInstanceBoundary
- };
-
- // Writes an array of "outer" cubics from each bezier in the SkPath, converting any quadratics
- // to cubics. An outer cubic is an independent, 4-point closed contour consisting of a single
- // cubic curve. Stencilled together with the inner triangles, these define the complete path.
- void prepareOuterCubics(GrMeshDrawOp::Target*, int numCountedCurves, CubicDataAlignment);
+ // If a resolveLevel counter is provided, this method resets it and uses it to count and
+ // prepares the outer cubics as indirect draws. Otherwise they are prepared as hardware
+ // tessellation patches.
+ //
+ // If drawTrianglesAsIndirectCubicDraw is true, then the resolveLevel counter must be non-null,
+ // and we express the inner triangles as an indirect cubic draw and sneak them in alongside the
+ // other cubic draws.
+ void prepareMiddleOutTrianglesAndCubics(GrMeshDrawOp::Target*, GrResolveLevelCounter* = nullptr,
+ bool drawTrianglesAsIndirectCubicDraw = false);
+
+ // Prepares a list of indirect draw commands and instance data for the path's "outer cubics",
+ // converting any quadratics to cubics. An outer cubic is an independent, 4-point closed contour
+ // consisting of a single cubic curve. Stencilled together with the inner triangles, these
+ // define the complete path.
+ void prepareIndirectOuterCubics(GrMeshDrawOp::Target*, const GrResolveLevelCounter&);
+
+ // For performance reasons we can often express triangles as an indirect cubic draw and sneak
+ // them in alongside the other indirect draws. This prepareIndirectOuterCubics variant allows
+ // the caller to provide a mapped cubic buffer with triangles already written into 4-point
+ // instances at the beginning. If numTrianglesAtBeginningOfData is nonzero, we add an extra
+ // indirect draw that renders these triangles.
+ void prepareIndirectOuterCubicsAndTriangles(GrMeshDrawOp::Target*, const GrResolveLevelCounter&,
+ SkPoint* cubicData,
+ int numTrianglesAtBeginningOfData);
+
+ // Writes an array of "outer cubic" tessellation patches from each bezier in the SkPath,
+ // converting any quadratics to cubics. An outer cubic is an independent, 4-point closed contour
+ // consisting of a single cubic curve. Stencilled together with the inner triangles, these
+ // define the complete path.
+ void prepareTessellatedOuterCubics(GrMeshDrawOp::Target*, int numCountedCurves);
// Writes an array of cubic "wedges" from the SkPath, converting any lines or quadratics to
// cubics. A wedge is an independent, 5-point closed contour consisting of 4 cubic control
@@ -92,13 +103,13 @@ private:
// stencilled, these wedges alone define the complete path.
//
// TODO: Eventually we want to use rational cubic wedges in order to support conics.
- void prepareCubicWedges(GrMeshDrawOp::Target*);
+ void prepareTessellatedCubicWedges(GrMeshDrawOp::Target*);
void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
void drawStencilPass(GrOpFlushState*);
void drawCoverPass(GrOpFlushState*);
- const Flags fFlags;
+ const GrTessellationPathRenderer::OpFlags fOpFlags;
const SkMatrix fViewMatrix;
const SkPath fPath;
const GrAAType fAAType;
@@ -137,6 +148,14 @@ private:
int fCubicVertexCount;
GrStencilPathShader* fStencilCubicsShader = nullptr;
+ // If fIndirectDrawBuffer is non-null, then we issue an indexed-indirect draw instead of using
+ // hardware tessellation. This is oftentimes faster than tessellation, and other times it serves
+ // as a polyfill when tessellation just isn't supported.
+ sk_sp<const GrBuffer> fIndirectDrawBuffer;
+ size_t fIndirectDrawOffset;
+ int fIndirectDrawCount;
+ sk_sp<const GrBuffer> fIndirectIndexBuffer;
+
friend class GrOpMemoryPool; // For ctor.
public:
@@ -144,6 +163,4 @@ public:
class TestingOnly_Benchmark;
};
-GR_MAKE_BITFIELD_CLASS_OPS(GrTessellatePathOp::Flags);
-
#endif
diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.cpp b/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.cpp
index e632c23a6f9..482a1ef7849 100644
--- a/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.cpp
@@ -7,6 +7,8 @@
#include "src/gpu/tessellate/GrTessellationPathRenderer.h"
+#include "include/pathops/SkPathOps.h"
+#include "src/core/SkIPoint16.h"
#include "src/core/SkPathPriv.h"
#include "src/gpu/GrClip.h"
#include "src/gpu/GrMemoryPool.h"
@@ -17,19 +19,87 @@
#include "src/gpu/ops/GrFillRectOp.h"
#include "src/gpu/tessellate/GrDrawAtlasPathOp.h"
#include "src/gpu/tessellate/GrTessellatePathOp.h"
+#include "src/gpu/tessellate/GrWangsFormula.h"
constexpr static SkISize kAtlasInitialSize{512, 512};
constexpr static int kMaxAtlasSize = 2048;
-GrTessellationPathRenderer::GrTessellationPathRenderer(const GrCaps& caps) : fAtlas(
- GrColorType::kAlpha_8, GrDynamicAtlas::InternalMultisample::kYes, kAtlasInitialSize,
- std::min(kMaxAtlasSize, caps.maxPreferredRenderTargetSize()), caps) {
+// The atlas is only used for small-area paths, which means at least one dimension of every path is
+// guaranteed to be quite small. So if we transpose tall paths, then every path will have a small
+// height, which lends very well to efficient pow2 atlas packing.
+constexpr static auto kAtlasAlgorithm = GrDynamicAtlas::RectanizerAlgorithm::kPow2;
+
+// Ensure every path in the atlas falls in or below the 128px high rectanizer band.
+constexpr static int kMaxAtlasPathHeight = 128;
+
+GrTessellationPathRenderer::GrTessellationPathRenderer(const GrCaps& caps)
+ : fAtlas(GrColorType::kAlpha_8, GrDynamicAtlas::InternalMultisample::kYes,
+ kAtlasInitialSize, std::min(kMaxAtlasSize, caps.maxPreferredRenderTargetSize()),
+ caps, kAtlasAlgorithm) {
+ this->initAtlasFlags(*caps.shaderCaps());
+}
+
+void GrTessellationPathRenderer::initAtlasFlags(const GrShaderCaps& shaderCaps) {
+ fStencilAtlasFlags = OpFlags::kStencilOnly | OpFlags::kDisableHWTessellation;
+ fMaxAtlasPathWidth = fAtlas.maxAtlasSize() / 2;
+ // The atlas usually does better with hardware tessellation. If hardware tessellation is
+ // supported, we choose a max atlas path width that is guaranteed to never require more
+ // tessellation segments than are supported by the hardware.
+ if (!shaderCaps.tessellationSupport()) {
+ return;
+ }
+ // Since we limit the area of paths in the atlas to kMaxAtlasPathHeight^2, taller paths can't
+ // get very wide anyway. Find the tallest path whose width is limited by
+ // GrWangsFormula::worst_case_cubic() rather than the max area constraint, and use that for our
+ // max atlas path width.
+ //
+ // Solve the following equation for w:
+ //
+ // GrWangsFormula::worst_case_cubic(kLinearizationIntolerance, w, kMaxAtlasPathHeight^2 / w)
+ // == maxTessellationSegments
+ //
+ float k = GrWangsFormula::cubic_k(kLinearizationIntolerance);
+ float h = kMaxAtlasPathHeight;
+ float s = shaderCaps.maxTessellationSegments();
+ // Quadratic formula from Numerical Recipes in C:
+ //
+ // q = -1/2 [b + sign(b) sqrt(b*b - 4*a*c)]
+ // x1 = q/a
+ // x2 = c/q
+ //
+ // float a = 1; // 'a' is always 1 in our specific equation.
+ float b = -s*s*s*s / (4*k*k); // Always negative.
+ float c = h*h*h*h; // Always positive.
+ float det = b*b - 4*1*c;
+ if (det <= 0) {
+ // maxTessellationSegments is too small for any path whose area == kMaxAtlasPathHeight^2.
+ // (This is unexpected because the GL spec mandates a minimum of 64 segments.)
+ SkDebugf("WARNING: maxTessellationSegments seems too low. (%i)\n",
+ shaderCaps.maxTessellationSegments());
+ return;
+ }
+ float q = -.5f * (b - std::sqrt(det)); // Always positive.
+ // The two roots represent the width^2 and height^2 of the tallest rectangle that is limited by
+ // GrWangsFormula::worst_case_cubic().
+ float r0 = q; // Always positive.
+ float r1 = c/q; // Always positive.
+ float worstCaseWidth = std::sqrt(std::max(r0, r1));
+#ifdef SK_DEBUG
+ float worstCaseHeight = std::sqrt(std::min(r0, r1));
+ // Verify the above equation worked as expected. It should have found a width and height whose
+ // area == kMaxAtlasPathHeight^2.
+ SkASSERT(SkScalarNearlyEqual(worstCaseHeight * worstCaseWidth, h*h, 1));
+ // Verify GrWangsFormula::worst_case_cubic() still works as we expect. The worst case number of
+ // segments for this bounding box should be maxTessellationSegments.
+ SkASSERT(SkScalarNearlyEqual(GrWangsFormula::worst_case_cubic(
+ kLinearizationIntolerance, worstCaseWidth, worstCaseHeight), s, 1));
+#endif
+ fStencilAtlasFlags &= ~OpFlags::kDisableHWTessellation;
+ fMaxAtlasPathWidth = std::min(fMaxAtlasPathWidth, (int)worstCaseWidth);
}
GrPathRenderer::CanDrawPath GrTessellationPathRenderer::onCanDrawPath(
const CanDrawPathArgs& args) const {
- // This class should not have been added to the chain without tessellation support.
- SkASSERT(args.fCaps->shaderCaps()->tessellationSupport());
if (!args.fShape->style().isSimpleFill() || args.fShape->inverseFilled() ||
args.fViewMatrix->hasPerspective()) {
return CanDrawPath::kNo;
@@ -51,63 +121,142 @@ GrPathRenderer::CanDrawPath GrTessellationPathRenderer::onCanDrawPath(
bool GrTessellationPathRenderer::onDrawPath(const DrawPathArgs& args) {
GrRenderTargetContext* renderTargetContext = args.fRenderTargetContext;
GrOpMemoryPool* pool = args.fContext->priv().opMemoryPool();
+ const GrShaderCaps& shaderCaps = *args.fContext->priv().caps()->shaderCaps();
+
SkPath path;
args.fShape->asPath(&path);
+ SkRect devBounds;
+ args.fViewMatrix->mapRect(&devBounds, path.getBounds());
+
// See if the path is small and simple enough to atlas instead of drawing directly.
//
// NOTE: The atlas uses alpha8 coverage even for msaa render targets. We could theoretically
// render the sample mask to an integer texture, but such a scheme would probably require
// GL_EXT_post_depth_coverage, which appears to have low adoption.
SkIRect devIBounds;
- SkIVector devToAtlasOffset;
- if (this->tryAddPathToAtlas(*args.fContext->priv().caps(), *args.fViewMatrix, path,
- args.fAAType, &devIBounds, &devToAtlasOffset)) {
+ SkIPoint16 locationInAtlas;
+ bool transposedInAtlas;
+ if (this->tryAddPathToAtlas(*args.fContext->priv().caps(), *args.fViewMatrix, path, devBounds,
+ args.fAAType, &devIBounds, &locationInAtlas, &transposedInAtlas)) {
+#ifdef SK_DEBUG
+ // If using hardware tessellation in the atlas, make sure the max number of segments is
+ // sufficient for this path. fMaxAtlasPathWidth should have been tuned for this to always be
+ // the case.
+ if (!(fStencilAtlasFlags & OpFlags::kDisableHWTessellation)) {
+ int worstCaseNumSegments = GrWangsFormula::worst_case_cubic(kLinearizationIntolerance,
+ devIBounds.width(),
+ devIBounds.height());
+ SkASSERT(worstCaseNumSegments <= shaderCaps.maxTessellationSegments());
+ }
+#endif
auto op = pool->allocate<GrDrawAtlasPathOp>(
renderTargetContext->numSamples(), sk_ref_sp(fAtlas.textureProxy()),
- devIBounds, devToAtlasOffset, *args.fViewMatrix, std::move(args.fPaint));
- renderTargetContext->addDrawOp(*args.fClip, std::move(op));
+ devIBounds, locationInAtlas, transposedInAtlas, *args.fViewMatrix,
+ std::move(args.fPaint));
+ renderTargetContext->addDrawOp(args.fClip, std::move(op));
return true;
}
- auto op = pool->allocate<GrTessellatePathOp>(
- *args.fViewMatrix, path, std::move(args.fPaint), args.fAAType);
- renderTargetContext->addDrawOp(*args.fClip, std::move(op));
+ auto drawPathFlags = OpFlags::kNone;
+
+ // Find the worst-case log2 number of line segments that a curve in this path might need to be
+ // divided into.
+ int worstCaseResolveLevel = GrWangsFormula::worst_case_cubic_log2(kLinearizationIntolerance,
+ devBounds.width(),
+ devBounds.height());
+ if (worstCaseResolveLevel > kMaxResolveLevel) {
+ // The path is too large for our internal indirect draw shaders. Crop it to the viewport.
+ SkPath viewport;
+ viewport.addRect(SkRect::MakeIWH(renderTargetContext->width(),
+ renderTargetContext->height()).makeOutset(1, 1));
+ // Perform the crop in device space so it's a simple rect-path intersection.
+ path.transform(*args.fViewMatrix);
+ if (!Op(viewport, path, kIntersect_SkPathOp, &path)) {
+ // The crop can fail if the PathOps encounter NaN or infinities. Return true
+ // because drawing nothing is acceptable behavior for FP overflow.
+ return true;
+ }
+ // Transform the path back to its own local space.
+ SkMatrix inverse;
+ if (!args.fViewMatrix->invert(&inverse)) {
+ return true; // Singular view matrix. Nothing would have drawn anyway. Return true.
+ }
+ path.transform(inverse);
+ path.setIsVolatile(true);
+ args.fViewMatrix->mapRect(&devBounds, path.getBounds());
+ worstCaseResolveLevel = GrWangsFormula::worst_case_cubic_log2(kLinearizationIntolerance,
+ devBounds.width(),
+ devBounds.height());
+ // kMaxResolveLevel should be large enough to tessellate paths the size of any screen we
+ // might encounter.
+ SkASSERT(worstCaseResolveLevel <= kMaxResolveLevel);
+ }
+
+ if ((1 << worstCaseResolveLevel) > shaderCaps.maxTessellationSegments()) {
+ // The path is too large for hardware tessellation; a curve in this bounding box could
+ // potentially require more segments than are supported by the hardware. Fall back on
+ // indirect draws.
+ drawPathFlags |= OpFlags::kDisableHWTessellation;
+ }
+
+ auto op = pool->allocate<GrTessellatePathOp>(*args.fViewMatrix, path, std::move(args.fPaint),
+ args.fAAType, drawPathFlags);
+ renderTargetContext->addDrawOp(args.fClip, std::move(op));
return true;
}
bool GrTessellationPathRenderer::tryAddPathToAtlas(
- const GrCaps& caps, const SkMatrix& viewMatrix, const SkPath& path, GrAAType aaType,
- SkIRect* devIBounds, SkIVector* devToAtlasOffset) {
+ const GrCaps& caps, const SkMatrix& viewMatrix, const SkPath& path, const SkRect& devBounds,
+ GrAAType aaType, SkIRect* devIBounds, SkIPoint16* locationInAtlas,
+ bool* transposedInAtlas) {
if (!caps.multisampleDisableSupport() && GrAAType::kNone == aaType) {
return false;
}
- // Atlas paths require their points to be transformed on CPU. Check if the path has too many
- // points to justify this CPU transformation.
- if (path.countPoints() > 150) {
+ // Atlas paths require their points to be transformed on the CPU and copied into an "uber path".
+ // Check if this path has too many points to justify this extra work.
+ if (path.countPoints() > 200) {
return false;
}
- // Check if the path is too large for an atlas.
- SkRect devBounds;
- viewMatrix.mapRect(&devBounds, path.getBounds());
- if (devBounds.height() * devBounds.width() > 100 * 100 ||
- std::max(devBounds.height(), devBounds.width()) > kMaxAtlasSize / 2) {
+ // Transpose tall paths in the atlas. Since we limit ourselves to small-area paths, this
+ // guarantees that every atlas entry has a small height, which lends very well to efficient pow2
+ // atlas packing.
+ devBounds.roundOut(devIBounds);
+ int maxDimenstion = devIBounds->width();
+ int minDimension = devIBounds->height();
+ *transposedInAtlas = minDimension > maxDimenstion;
+ if (*transposedInAtlas) {
+ std::swap(minDimension, maxDimenstion);
+ }
+
+ // Check if the path is too large for an atlas. Since we use "minDimension" for height in the
+ // atlas, limiting to kMaxAtlasPathHeight^2 pixels guarantees height <= kMaxAtlasPathHeight.
+ if (maxDimenstion * minDimension > kMaxAtlasPathHeight * kMaxAtlasPathHeight ||
+ maxDimenstion > fMaxAtlasPathWidth) {
return false;
}
- devBounds.roundOut(devIBounds);
- if (!fAtlas.addRect(*devIBounds, devToAtlasOffset)) {
+ if (!fAtlas.addRect(maxDimenstion, minDimension, locationInAtlas)) {
return false;
}
SkMatrix atlasMatrix = viewMatrix;
- atlasMatrix.postTranslate(devToAtlasOffset->x(), devToAtlasOffset->y());
+ if (*transposedInAtlas) {
+ std::swap(atlasMatrix[0], atlasMatrix[3]);
+ std::swap(atlasMatrix[1], atlasMatrix[4]);
+ float tx=atlasMatrix.getTranslateX(), ty=atlasMatrix.getTranslateY();
+ atlasMatrix.setTranslateX(ty - devIBounds->y() + locationInAtlas->x());
+ atlasMatrix.setTranslateY(tx - devIBounds->x() + locationInAtlas->y());
+ } else {
+ atlasMatrix.postTranslate(locationInAtlas->x() - devIBounds->x(),
+ locationInAtlas->y() - devIBounds->y());
+ }
// Concatenate this path onto our uber path that matches its fill and AA types.
SkPath* uberPath = this->getAtlasUberPath(path.getFillType(), GrAAType::kNone != aaType);
- uberPath->moveTo(devToAtlasOffset->x(), devToAtlasOffset->y()); // Implicit moveTo(0,0).
+ uberPath->moveTo(locationInAtlas->x(), locationInAtlas->y()); // Implicit moveTo(0,0).
uberPath->addPath(path, atlasMatrix);
return true;
}
@@ -119,8 +268,8 @@ void GrTessellationPathRenderer::onStencilPath(const StencilPathArgs& args) {
GrAAType aaType = (GrAA::kYes == args.fDoStencilMSAA) ? GrAAType::kMSAA : GrAAType::kNone;
auto op = args.fContext->priv().opMemoryPool()->allocate<GrTessellatePathOp>(
- *args.fViewMatrix, path, GrPaint(), aaType, GrTessellatePathOp::Flags::kStencilOnly);
- args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
+ *args.fViewMatrix, path, GrPaint(), aaType, OpFlags::kStencilOnly);
+ args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
}
void GrTessellationPathRenderer::preFlush(GrOnFlushResourceProvider* onFlushRP,
@@ -168,9 +317,8 @@ void GrTessellationPathRenderer::renderAtlas(GrOnFlushResourceProvider* onFlushR
uberPath->setFillType(fillType);
GrAAType aaType = (antialias) ? GrAAType::kMSAA : GrAAType::kNone;
auto op = onFlushRP->opMemoryPool()->allocate<GrTessellatePathOp>(
- SkMatrix::I(), *uberPath, GrPaint(), aaType,
- GrTessellatePathOp::Flags::kStencilOnly);
- rtc->addDrawOp(GrNoClip(), std::move(op));
+ SkMatrix::I(), *uberPath, GrPaint(), aaType, fStencilAtlasFlags);
+ rtc->addDrawOp(nullptr, std::move(op));
}
}
@@ -206,7 +354,7 @@ void GrTessellationPathRenderer::renderAtlas(GrOnFlushResourceProvider* onFlushR
auto coverOp = GrFillRectOp::Make(rtc->surfPriv().getContext(), std::move(paint),
GrAAType::kMSAA, &drawQuad, stencil, fillRectFlags);
- rtc->addDrawOp(GrNoClip(), std::move(coverOp));
+ rtc->addDrawOp(nullptr, std::move(coverOp));
if (rtc->asSurfaceProxy()->requiresManualMSAAResolve()) {
onFlushRP->addTextureResolveTask(sk_ref_sp(rtc->asTextureProxy()),
diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.h b/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.h
index bf8ea29eb70..4035a0d7a2f 100644
--- a/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.h
+++ b/chromium/third_party/skia/src/gpu/tessellate/GrTessellationPathRenderer.h
@@ -19,9 +19,32 @@
// target that supports either MSAA or mixed samples if AA is desired.
class GrTessellationPathRenderer : public GrPathRenderer, public GrOnFlushCallbackObject {
public:
- const char* name() const final { return "Tess"; }
+ // Don't allow linearized segments to be off by more than 1/4th of a pixel from the true curve.
+ constexpr static float kLinearizationIntolerance = 4;
+
+ // This is the maximum resolve level supported by our internal indirect draw shaders. (Indirect
+ // draws are an alternative to hardware tessellation, and we can use them when hardware support
+ // is lacking.)
+ //
+ // At a given resolveLevel, a curve gets linearized into 2^resolveLevel line segments. So the
+ // finest resolveLevel supported by our indirect draw shaders is 2^10 == 1024 line segments.
+ //
+ // 1024 line segments is enough resolution (with intolerance == 4) to guarantee we can render a
+ // 123575px x 123575px path. (See GrWangsFormula::worst_case_cubic.)
+ constexpr static int kMaxResolveLevel = 10;
+
+ // We send these flags to the internal tessellation Ops to control how a path gets rendered.
+ enum class OpFlags {
+ kNone = 0,
+ // Used when tessellation is not supported, or when a path will require more resolution than
+ // the max number of segments supported by the hardware.
+ kDisableHWTessellation = (1 << 0),
+ kStencilOnly = (1 << 1),
+ kWireframe = (1 << 2)
+ };
GrTessellationPathRenderer(const GrCaps&);
+ const char* name() const final { return "GrTessellationPathRenderer"; }
StencilSupport onGetStencilSupport(const GrStyledShape& shape) const override {
// TODO: Single-pass (e.g., convex) paths can have full support.
return kStencilOnly_StencilSupport;
@@ -33,18 +56,24 @@ public:
int numOpsTaskIDs) override;
private:
+ void initAtlasFlags(const GrShaderCaps& shaderCaps);
SkPath* getAtlasUberPath(SkPathFillType fillType, bool antialias) {
int idx = (int)antialias << 1;
idx |= (int)fillType & 1;
return &fAtlasUberPaths[idx];
}
// Allocates space in fAtlas if the path is small and simple enough, and if there is room.
- bool tryAddPathToAtlas(const GrCaps&, const SkMatrix&, const SkPath&, GrAAType,
- SkIRect* devIBounds, SkIVector* devToAtlasOffset);
+ bool tryAddPathToAtlas(const GrCaps&, const SkMatrix&, const SkPath&, const SkRect& devBounds,
+ GrAAType, SkIRect* devIBounds, SkIPoint16* locationInAtlas,
+ bool* transposedInAtlas);
void renderAtlas(GrOnFlushResourceProvider*);
GrDynamicAtlas fAtlas;
+ OpFlags fStencilAtlasFlags;
+ int fMaxAtlasPathWidth;
SkPath fAtlasUberPaths[4]; // 2 fillTypes * 2 antialias modes.
};
+GR_MAKE_BITFIELD_CLASS_OPS(GrTessellationPathRenderer::OpFlags);
+
#endif
diff --git a/chromium/third_party/skia/src/gpu/tessellate/GrWangsFormula.h b/chromium/third_party/skia/src/gpu/tessellate/GrWangsFormula.h
index 1fa79c6793e..b9c3264e479 100644
--- a/chromium/third_party/skia/src/gpu/tessellate/GrWangsFormula.h
+++ b/chromium/third_party/skia/src/gpu/tessellate/GrWangsFormula.h
@@ -22,6 +22,11 @@ SK_ALWAYS_INLINE static float length(const Sk2f& n) {
return std::sqrt(nn[0] + nn[1]);
}
+// Constant term for the quatratic formula.
+constexpr float quadratic_k(float intolerance) {
+ return .25f * intolerance;
+}
+
// Returns the minimum number of evenly spaced (in the parametric sense) line segments that the
// quadratic must be chopped into in order to guarantee all lines stay within a distance of
// "1/intolerance" pixels from the true curve.
@@ -29,10 +34,15 @@ SK_ALWAYS_INLINE static float quadratic(float intolerance, const SkPoint pts[])
Sk2f p0 = Sk2f::Load(pts);
Sk2f p1 = Sk2f::Load(pts + 1);
Sk2f p2 = Sk2f::Load(pts + 2);
- float k = intolerance * .25f;
+ float k = quadratic_k(intolerance);
return SkScalarSqrt(k * length(p0 - p1*2 + p2));
}
+// Constant term for the cubic formula.
+constexpr float cubic_k(float intolerance) {
+ return .75f * intolerance;
+}
+
// Returns the minimum number of evenly spaced (in the parametric sense) line segments that the
// cubic must be chopped into in order to guarantee all lines stay within a distance of
// "1/intolerance" pixels from the true curve.
@@ -41,11 +51,19 @@ SK_ALWAYS_INLINE static float cubic(float intolerance, const SkPoint pts[]) {
Sk2f p1 = Sk2f::Load(pts + 1);
Sk2f p2 = Sk2f::Load(pts + 2);
Sk2f p3 = Sk2f::Load(pts + 3);
- float k = intolerance * .75f;
+ float k = cubic_k(intolerance);
return SkScalarSqrt(k * length(Sk2f::Max((p0 - p1*2 + p2).abs(),
(p1 - p2*2 + p3).abs())));
}
+// Returns the maximum number of line segments a cubic with the given device-space bounding box size
+// would ever need to be divided into. This is simply a special case of the cubic formula where we
+// maximize its value by placing control points on specific corners of the bounding box.
+SK_ALWAYS_INLINE static float worst_case_cubic(float intolerance, float devWidth, float devHeight) {
+ float k = cubic_k(intolerance);
+ return SkScalarSqrt(2*k * SkVector::Length(devWidth, devHeight));
+}
+
// Returns the log2 of the provided value, were that value to be rounded up to the next power of 2.
// Returns 0 if value <= 0:
// Never returns a negative number, even if value is NaN.
@@ -63,6 +81,10 @@ SK_ALWAYS_INLINE static int nextlog2(float value) {
return exp & ~(exp >> 31); // Return 0 for negative or denormalized floats, and exponents < 0.
}
+SK_ALWAYS_INLINE static int ceil_log2_sqrt_sqrt(float f) {
+ return (nextlog2(f) + 3) >> 2; // i.e., "ceil(log2(sqrt(sqrt(f))))
+}
+
// Returns the minimum log2 number of evenly spaced (in the parametric sense) line segments that the
// transformed quadratic must be chopped into in order to guarantee all lines stay within a distance
// of "1/intolerance" pixels from the true curve.
@@ -74,9 +96,9 @@ SK_ALWAYS_INLINE static int quadratic_log2(float intolerance, const SkPoint pts[
Sk2f v = p0 + p1*-2 + p2;
v = vectorXform(v);
Sk2f vv = v*v;
- float k = intolerance * .25f;
+ float k = quadratic_k(intolerance);
float f = k*k * (vv[0] + vv[1]);
- return (nextlog2(f) + 3) >> 2; // ceil(log2(sqrt(sqrt(f))))
+ return ceil_log2_sqrt_sqrt(f);
}
// Returns the minimum log2 number of evenly spaced (in the parametric sense) line segments that the
@@ -91,9 +113,17 @@ SK_ALWAYS_INLINE static int cubic_log2(float intolerance, const SkPoint pts[],
v = vectorXform(v);
Sk4f vv = v*v;
vv = Sk4f::Max(vv, SkNx_shuffle<2,3,0,1>(vv));
- float k = intolerance * .75f;
+ float k = cubic_k(intolerance);
float f = k*k * (vv[0] + vv[1]);
- return (nextlog2(f) + 3) >> 2; // ceil(log2(sqrt(sqrt(f))))
+ return ceil_log2_sqrt_sqrt(f);
+}
+
+// Returns the maximum log2 number of line segments a cubic with the given device-space bounding box
+// size would ever need to be divided into.
+SK_ALWAYS_INLINE static int worst_case_cubic_log2(float intolerance, float devWidth,
+ float devHeight) {
+ float k = cubic_k(intolerance);
+ return ceil_log2_sqrt_sqrt(4*k*k * (devWidth * devWidth + devHeight * devHeight));
}
} // namespace
diff --git a/chromium/third_party/skia/src/gpu/text/GrAtlasManager.cpp b/chromium/third_party/skia/src/gpu/text/GrAtlasManager.cpp
index efe4a472683..3120255a7c8 100644
--- a/chromium/third_party/skia/src/gpu/text/GrAtlasManager.cpp
+++ b/chromium/third_party/skia/src/gpu/text/GrAtlasManager.cpp
@@ -7,6 +7,8 @@
#include "src/gpu/text/GrAtlasManager.h"
+#include "src/codec/SkMasks.h"
+#include "src/core/SkAutoMalloc.h"
#include "src/gpu/GrGlyph.h"
#include "src/gpu/GrImageInfo.h"
#include "src/gpu/text/GrStrikeCache.h"
@@ -32,6 +34,155 @@ bool GrAtlasManager::hasGlyph(GrMaskFormat format, GrGlyph* glyph) {
return this->getAtlas(format)->hasID(glyph->fAtlasLocator.plotLocator());
}
+template <typename INT_TYPE>
+static void expand_bits(INT_TYPE* dst,
+ const uint8_t* src,
+ int width,
+ int height,
+ int dstRowBytes,
+ int srcRowBytes) {
+ for (int i = 0; i < height; ++i) {
+ int rowWritesLeft = width;
+ const uint8_t* s = src;
+ INT_TYPE* d = dst;
+ while (rowWritesLeft > 0) {
+ unsigned mask = *s++;
+ for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) {
+ *d++ = (mask & (1 << i)) ? (INT_TYPE)(~0UL) : 0;
+ }
+ }
+ dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes);
+ src += srcRowBytes;
+ }
+}
+
+static void get_packed_glyph_image(
+ const SkGlyph& glyph, int dstRB, GrMaskFormat expectedMaskFormat, void* dst) {
+ const int width = glyph.width();
+ const int height = glyph.height();
+ const void* src = glyph.image();
+ SkASSERT(src != nullptr);
+
+ GrMaskFormat grMaskFormat = GrGlyph::FormatFromSkGlyph(glyph.maskFormat());
+ if (grMaskFormat == expectedMaskFormat) {
+ int srcRB = glyph.rowBytes();
+ // Notice this comparison is with the glyphs raw mask format, and not its GrMaskFormat.
+ if (glyph.maskFormat() != SkMask::kBW_Format) {
+ if (srcRB != dstRB) {
+ const int bbp = GrMaskFormatBytesPerPixel(expectedMaskFormat);
+ for (int y = 0; y < height; y++) {
+ memcpy(dst, src, width * bbp);
+ src = (const char*) src + srcRB;
+ dst = (char*) dst + dstRB;
+ }
+ } else {
+ memcpy(dst, src, dstRB * height);
+ }
+ } else {
+ // Handle 8-bit format by expanding the mask to the expected format.
+ const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
+ switch (expectedMaskFormat) {
+ case kA8_GrMaskFormat: {
+ uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
+ expand_bits(bytes, bits, width, height, dstRB, srcRB);
+ break;
+ }
+ case kA565_GrMaskFormat: {
+ uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst);
+ expand_bits(rgb565, bits, width, height, dstRB, srcRB);
+ break;
+ }
+ default:
+ SK_ABORT("Invalid GrMaskFormat");
+ }
+ }
+ } else if (grMaskFormat == kA565_GrMaskFormat && expectedMaskFormat == kARGB_GrMaskFormat) {
+ // Convert if the glyph uses a 565 mask format since it is using LCD text rendering
+ // but the expected format is 8888 (will happen on macOS with Metal since that
+ // combination does not support 565).
+ static constexpr SkMasks masks{
+ {0b1111'1000'0000'0000, 11, 5}, // Red
+ {0b0000'0111'1110'0000, 5, 6}, // Green
+ {0b0000'0000'0001'1111, 0, 5}, // Blue
+ {0, 0, 0} // Alpha
+ };
+ constexpr int a565Bpp = GrMaskFormatBytesPerPixel(kA565_GrMaskFormat);
+ constexpr int argbBpp = GrMaskFormatBytesPerPixel(kARGB_GrMaskFormat);
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ uint16_t color565 = 0;
+ memcpy(&color565, src, a565Bpp);
+ uint32_t colorRGBA = GrColorPackRGBA(masks.getRed(color565),
+ masks.getGreen(color565),
+ masks.getBlue(color565),
+ 0xFF);
+ memcpy(dst, &colorRGBA, argbBpp);
+ src = (char*)src + a565Bpp;
+ dst = (char*)dst + argbBpp;
+ }
+ }
+ } else {
+ // crbug:510931
+ // Retrieving the image from the cache can actually change the mask format. This case is
+ // very uncommon so for now we just draw a clear box for these glyphs.
+ const int bpp = GrMaskFormatBytesPerPixel(expectedMaskFormat);
+ for (int y = 0; y < height; y++) {
+ sk_bzero(dst, width * bpp);
+ dst = (char*)dst + dstRB;
+ }
+ }
+}
+
+// returns true if glyph successfully added to texture atlas, false otherwise. If the glyph's
+// mask format has changed, then addGlyphToAtlas will draw a clear box. This will almost never
+// happen.
+// TODO we can handle some of these cases if we really want to, but the long term solution is to
+// get the actual glyph image itself when we get the glyph metrics.
+GrDrawOpAtlas::ErrorCode GrAtlasManager::addGlyphToAtlas(const SkGlyph& skGlyph,
+ int padding,
+ GrGlyph* grGlyph,
+ GrResourceProvider* resourceProvider,
+ GrDeferredUploadTarget* uploadTarget) {
+ if (skGlyph.image() == nullptr) {
+ return GrDrawOpAtlas::ErrorCode::kError;
+ }
+ SkASSERT(grGlyph != nullptr);
+
+ GrMaskFormat glyphFormat = GrGlyph::FormatFromSkGlyph(skGlyph.maskFormat());
+ GrMaskFormat expectedMaskFormat = this->resolveMaskFormat(glyphFormat);
+ int bytesPerPixel = GrMaskFormatBytesPerPixel(expectedMaskFormat);
+
+ if (padding > 0) {
+ SkASSERT(skGlyph.maskFormat() != SkMask::kSDF_Format);
+ }
+
+ SkASSERT(padding == 0 || padding == 1);
+ // Add 1 pixel padding around grGlyph if needed.
+ const int width = skGlyph.width() + 2*padding;
+ const int height = skGlyph.height() + 2*padding;
+ int rowBytes = width * bytesPerPixel;
+ size_t size = height * rowBytes;
+
+ // Temporary storage for normalizing grGlyph image.
+ SkAutoSMalloc<1024> storage(size);
+ void* dataPtr = storage.get();
+ if (padding > 0) {
+ sk_bzero(dataPtr, size);
+ // Advance in one row and one column.
+ dataPtr = (char*)(dataPtr) + rowBytes + bytesPerPixel;
+ }
+
+ get_packed_glyph_image(skGlyph, rowBytes, expectedMaskFormat, dataPtr);
+
+ return this->addToAtlas(resourceProvider,
+ uploadTarget,
+ expectedMaskFormat,
+ width,
+ height,
+ storage.get(),
+ &grGlyph->fAtlasLocator);
+}
+
// add to texture atlas that matches this format
GrDrawOpAtlas::ErrorCode GrAtlasManager::addToAtlas(GrResourceProvider* resourceProvider,
GrDeferredUploadTarget* target,
diff --git a/chromium/third_party/skia/src/gpu/text/GrAtlasManager.h b/chromium/third_party/skia/src/gpu/text/GrAtlasManager.h
index 036495fa53b..97fcb9a81a8 100644
--- a/chromium/third_party/skia/src/gpu/text/GrAtlasManager.h
+++ b/chromium/third_party/skia/src/gpu/text/GrAtlasManager.h
@@ -28,18 +28,6 @@ public:
GrAtlasManager(GrProxyProvider*, size_t maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing);
~GrAtlasManager() override;
- // Change an expected 565 mask format to 8888 if 565 is not supported (will happen when using
- // Metal on macOS). The actual conversion of the data is handled in get_packed_glyph_image() in
- // GrStrikeCache.cpp
- GrMaskFormat resolveMaskFormat(GrMaskFormat format) const {
- if (kA565_GrMaskFormat == format &&
- !fProxyProvider->caps()->getDefaultBackendFormat(GrColorType::kBGR_565,
- GrRenderable::kNo).isValid()) {
- format = kARGB_GrMaskFormat;
- }
- return format;
- }
-
// if getViews returns nullptr, the client must not try to use other functions on the
// GrStrikeCache which use the atlas. This function *must* be called first, before other
// functions which use the atlas. Note that we can have proxies available but none active
@@ -58,6 +46,12 @@ public:
bool hasGlyph(GrMaskFormat, GrGlyph*);
+ GrDrawOpAtlas::ErrorCode addGlyphToAtlas(const SkGlyph& skGlyph,
+ int padding,
+ GrGlyph* grGlyph,
+ GrResourceProvider* resourceProvider,
+ GrDeferredUploadTarget* uploadTarget);
+
// To ensure the GrDrawOpAtlas does not evict the Glyph Mask from its texture backing store,
// the client must pass in the current op token along with the GrGlyph.
// A BulkUseTokenUpdater is used to manage bulk last use token updating in the Atlas.
@@ -118,6 +112,17 @@ public:
private:
bool initAtlas(GrMaskFormat);
+ // Change an expected 565 mask format to 8888 if 565 is not supported (will happen when using
+ // Metal on macOS). The actual conversion of the data is handled in get_packed_glyph_image() in
+ // GrStrikeCache.cpp
+ GrMaskFormat resolveMaskFormat(GrMaskFormat format) const {
+ if (kA565_GrMaskFormat == format &&
+ !fProxyProvider->caps()->getDefaultBackendFormat(GrColorType::kBGR_565,
+ GrRenderable::kNo).isValid()) {
+ format = kARGB_GrMaskFormat;
+ }
+ return format;
+ }
// There is a 1:1 mapping between GrMaskFormats and atlas indices
static int MaskFormatToAtlasIndex(GrMaskFormat format) { return static_cast<int>(format); }
diff --git a/chromium/third_party/skia/src/gpu/text/GrSDFTOptions.cpp b/chromium/third_party/skia/src/gpu/text/GrSDFTOptions.cpp
new file mode 100644
index 00000000000..e0ed2189e90
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/text/GrSDFTOptions.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/text/GrSDFTOptions.h"
+
+#include "include/core/SkFont.h"
+#include "include/core/SkMatrix.h"
+#include "include/core/SkPaint.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkSurfaceProps.h"
+
+#include <tuple>
+
+// DF sizes and thresholds for usage of the small and medium sizes. For example, above
+// kSmallDFFontLimit we will use the medium size. The large size is used up until the size at
+// which we switch over to drawing as paths as controlled by Options.
+static const int kSmallDFFontSize = 32;
+static const int kSmallDFFontLimit = 32;
+static const int kMediumDFFontSize = 72;
+static const int kMediumDFFontLimit = 72;
+static const int kLargeDFFontSize = 162;
+#ifdef SK_BUILD_FOR_MAC
+static const int kLargeDFFontLimit = 162;
+static const int kExtraLargeDFFontSize = 256;
+#endif
+
+GrSDFTOptions::GrSDFTOptions(SkScalar min, SkScalar max)
+ : fMinDistanceFieldFontSize{min}
+ , fMaxDistanceFieldFontSize{max} {
+ SkASSERT_RELEASE(min > 0 && max >= min);
+}
+
+bool GrSDFTOptions::canDrawAsDistanceFields(const SkPaint& paint, const SkFont& font,
+ const SkMatrix& viewMatrix,
+ const SkSurfaceProps& props,
+ bool contextSupportsDistanceFieldText) const {
+ // mask filters modify alpha, which doesn't translate well to distance
+ if (paint.getMaskFilter() || !contextSupportsDistanceFieldText) {
+ return false;
+ }
+
+ // TODO: add some stroking support
+ if (paint.getStyle() != SkPaint::kFill_Style) {
+ return false;
+ }
+
+ if (viewMatrix.hasPerspective()) {
+ // Don't use SDF for perspective. Paths look better.
+ return false;
+ } else {
+ SkScalar maxScale = viewMatrix.getMaxScale();
+ SkScalar scaledTextSize = maxScale * font.getSize();
+ // Hinted text looks far better at small resolutions
+ // Scaling up beyond 2x yields undesirable artifacts
+ if (scaledTextSize < fMinDistanceFieldFontSize ||
+ scaledTextSize > fMaxDistanceFieldFontSize) {
+ return false;
+ }
+
+ bool useDFT = props.isUseDeviceIndependentFonts();
+#if SK_FORCE_DISTANCE_FIELD_TEXT
+ useDFT = true;
+#endif
+
+ if (!useDFT && scaledTextSize < kLargeDFFontSize) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+SkScalar scaled_text_size(const SkScalar textSize, const SkMatrix& viewMatrix) {
+ SkScalar scaledTextSize = textSize;
+
+ if (viewMatrix.hasPerspective()) {
+ // for perspective, we simply force to the medium size
+ // TODO: compute a size based on approximate screen area
+ scaledTextSize = kMediumDFFontLimit;
+ } else {
+ SkScalar maxScale = viewMatrix.getMaxScale();
+ // if we have non-unity scale, we need to choose our base text size
+ // based on the SkPaint's text size multiplied by the max scale factor
+ // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)?
+ if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) {
+ scaledTextSize *= maxScale;
+ }
+ }
+
+ return scaledTextSize;
+}
+
+SkFont GrSDFTOptions::getSDFFont(const SkFont& font,
+ const SkMatrix& viewMatrix,
+ SkScalar* textRatio) const {
+ SkScalar textSize = font.getSize();
+ SkScalar scaledTextSize = scaled_text_size(textSize, viewMatrix);
+
+ SkFont dfFont{font};
+
+ if (scaledTextSize <= kSmallDFFontLimit) {
+ *textRatio = textSize / kSmallDFFontSize;
+ dfFont.setSize(SkIntToScalar(kSmallDFFontSize));
+ } else if (scaledTextSize <= kMediumDFFontLimit) {
+ *textRatio = textSize / kMediumDFFontSize;
+ dfFont.setSize(SkIntToScalar(kMediumDFFontSize));
+#ifdef SK_BUILD_FOR_MAC
+ } else if (scaledTextSize <= kLargeDFFontLimit) {
+ *textRatio = textSize / kLargeDFFontSize;
+ dfFont.setSize(SkIntToScalar(kLargeDFFontSize));
+ } else {
+ *textRatio = textSize / kExtraLargeDFFontSize;
+ dfFont.setSize(SkIntToScalar(kExtraLargeDFFontSize));
+ }
+#else
+ } else {
+ *textRatio = textSize / kLargeDFFontSize;
+ dfFont.setSize(SkIntToScalar(kLargeDFFontSize));
+ }
+#endif
+
+ dfFont.setEdging(SkFont::Edging::kAntiAlias);
+ dfFont.setForceAutoHinting(false);
+ dfFont.setHinting(SkFontHinting::kNormal);
+
+ // The sub-pixel position will always happen when transforming to the screen.
+ dfFont.setSubpixel(false);
+ return dfFont;
+}
+
+std::pair<SkScalar, SkScalar> GrSDFTOptions::computeSDFMinMaxScale(
+ SkScalar textSize, const SkMatrix& viewMatrix) const {
+
+ SkScalar scaledTextSize = scaled_text_size(textSize, viewMatrix);
+
+ // We have three sizes of distance field text, and within each size 'bucket' there is a floor
+ // and ceiling. A scale outside of this range would require regenerating the distance fields
+ SkScalar dfMaskScaleFloor;
+ SkScalar dfMaskScaleCeil;
+ if (scaledTextSize <= kSmallDFFontLimit) {
+ dfMaskScaleFloor = fMinDistanceFieldFontSize;
+ dfMaskScaleCeil = kSmallDFFontLimit;
+ } else if (scaledTextSize <= kMediumDFFontLimit) {
+ dfMaskScaleFloor = kSmallDFFontLimit;
+ dfMaskScaleCeil = kMediumDFFontLimit;
+ } else {
+ dfMaskScaleFloor = kMediumDFFontLimit;
+ dfMaskScaleCeil = fMaxDistanceFieldFontSize;
+ }
+
+ // Because there can be multiple runs in the blob, we want the overall maxMinScale, and
+ // minMaxScale to make regeneration decisions. Specifically, we want the maximum minimum scale
+ // we can tolerate before we'd drop to a lower mip size, and the minimum maximum scale we can
+ // tolerate before we'd have to move to a large mip size. When we actually test these values
+ // we look at the delta in scale between the new viewmatrix and the old viewmatrix, and test
+ // against these values to decide if we can reuse or not(ie, will a given scale change our mip
+ // level)
+ SkASSERT(dfMaskScaleFloor <= scaledTextSize && scaledTextSize <= dfMaskScaleCeil);
+
+ return std::make_pair(dfMaskScaleFloor / scaledTextSize, dfMaskScaleCeil / scaledTextSize);
+}
+
+
diff --git a/chromium/third_party/skia/src/gpu/text/GrSDFTOptions.h b/chromium/third_party/skia/src/gpu/text/GrSDFTOptions.h
new file mode 100644
index 00000000000..33e7b6bd2db
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/text/GrSDFTOptions.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrSDFTOptions_DEFINED
+#define GrSDFTOptions_DEFINED
+
+#include "include/core/SkFont.h"
+#include "include/core/SkScalar.h"
+
+class SkMatrix;
+class SkSurfaceProps;
+
+class GrSDFTOptions {
+public:
+ GrSDFTOptions(SkScalar min, SkScalar max);
+
+ bool canDrawAsDistanceFields(const SkPaint&, const SkFont&, const SkMatrix& viewMatrix,
+ const SkSurfaceProps& props,
+ bool contextSupportsDistanceFieldText) const;
+ SkFont getSDFFont(const SkFont& font,
+ const SkMatrix& viewMatrix,
+ SkScalar* textRatio) const;
+ std::pair<SkScalar, SkScalar> computeSDFMinMaxScale(
+ SkScalar textSize, const SkMatrix& viewMatrix) const;
+private:
+ // Below this size (in device space) distance field text will not be used.
+ const SkScalar fMinDistanceFieldFontSize;
+
+ // Above this size (in device space) distance field text will not be used and glyphs will
+ // be rendered from outline as individual paths.
+ const SkScalar fMaxDistanceFieldFontSize;
+};
+
+#endif // GrSDFTOptions_DEFINED
diff --git a/chromium/third_party/skia/src/gpu/text/GrTextBlob.cpp b/chromium/third_party/skia/src/gpu/text/GrTextBlob.cpp
index e73868beaa7..565d605f995 100644
--- a/chromium/third_party/skia/src/gpu/text/GrTextBlob.cpp
+++ b/chromium/third_party/skia/src/gpu/text/GrTextBlob.cpp
@@ -8,11 +8,10 @@
#include "include/core/SkColorFilter.h"
#include "include/gpu/GrContext.h"
#include "include/private/SkTemplates.h"
-#include "src/codec/SkMasks.h"
-#include "src/core/SkAutoMalloc.h"
#include "src/core/SkMaskFilterBase.h"
#include "src/core/SkMatrixProvider.h"
#include "src/core/SkPaintPriv.h"
+#include "src/core/SkStrikeSpec.h"
#include "src/gpu/GrBlurUtils.h"
#include "src/gpu/GrClip.h"
#include "src/gpu/GrStyle.h"
@@ -41,153 +40,229 @@ GrTextBlob::PathGlyph::PathGlyph(const SkPath& path, SkPoint origin)
// -- GrTextBlob::SubRun ---------------------------------------------------------------------------
GrTextBlob::SubRun::SubRun(SubRunType type, GrTextBlob* textBlob, const SkStrikeSpec& strikeSpec,
- GrMaskFormat format, const SkSpan<PackedGlyphIDorGrGlyph>& glyphs,
- const SkSpan<char>& vertexData)
- : fType{type}
- , fBlob{textBlob}
+ GrMaskFormat format, SkRect vertexBounds,
+ const SkSpan<VertexData>& vertexData)
+ : fBlob{textBlob}
+ , fType{type}
, fMaskFormat{format}
- , fGlyphs{glyphs}
- , fVertexData{vertexData}
, fStrikeSpec{strikeSpec}
- , fCurrentColor{textBlob->fColor}
- , fCurrentOrigin{textBlob->fInitialOrigin}
- , fCurrentMatrix{textBlob->fInitialMatrix} {
- SkASSERT(type != kTransformedPath);
- textBlob->insertSubRun(this);
+ , fVertexBounds{vertexBounds}
+ , fVertexData{vertexData} {
+ SkASSERT(fType != kTransformedPath);
}
GrTextBlob::SubRun::SubRun(GrTextBlob* textBlob, const SkStrikeSpec& strikeSpec)
- : fType{kTransformedPath}
- , fBlob{textBlob}
+ : fBlob{textBlob}
+ , fType{kTransformedPath}
, fMaskFormat{kA8_GrMaskFormat}
- , fGlyphs{SkSpan<PackedGlyphIDorGrGlyph>{}}
- , fVertexData{SkSpan<char>{}}
, fStrikeSpec{strikeSpec}
- , fCurrentColor{textBlob->fColor}
- , fPaths{} {
- textBlob->insertSubRun(this);
-}
-
-static SkRect dest_rect(const SkGlyph& g, SkPoint origin) {
- return SkRect::MakeXYWH(
- SkIntToScalar(g.left()) + origin.x(),
- SkIntToScalar(g.top()) + origin.y(),
- SkIntToScalar(g.width()),
- SkIntToScalar(g.height()));
-}
-
-static bool is_SDF(const SkGlyph& skGlyph) {
- return skGlyph.maskFormat() == SkMask::kSDF_Format;
-}
-
-static SkRect dest_rect(const SkGlyph& g, SkPoint origin, SkScalar textScale) {
- if (!is_SDF(g)) {
- return SkRect::MakeXYWH(
- SkIntToScalar(g.left()) * textScale + origin.x(),
- SkIntToScalar(g.top()) * textScale + origin.y(),
- SkIntToScalar(g.width()) * textScale,
- SkIntToScalar(g.height()) * textScale);
- } else {
- return SkRect::MakeXYWH(
- (SkIntToScalar(g.left()) + SK_DistanceFieldInset) * textScale + origin.x(),
- (SkIntToScalar(g.top()) + SK_DistanceFieldInset) * textScale + origin.y(),
- (SkIntToScalar(g.width()) - 2 * SK_DistanceFieldInset) * textScale,
- (SkIntToScalar(g.height()) - 2 * SK_DistanceFieldInset) * textScale);
- }
-}
-
-void GrTextBlob::SubRun::appendGlyphs(const SkZip<SkGlyphVariant, SkPoint>& drawables) {
- SkScalar strikeToSource = fStrikeSpec.strikeToSourceRatio();
- SkASSERT(!this->isPrepared());
- PackedGlyphIDorGrGlyph* packedIDCursor = fGlyphs.data();
- char* vertexCursor = fVertexData.data();
- size_t vertexStride = this->vertexStride();
- // We always write the third position component used by SDFs. If it is unused it gets
- // overwritten. Similarly, we always write the color and the blob will later overwrite it
- // with texture coords if it is unused.
- size_t colorOffset = this->colorOffset();
- for (auto [variant, pos] : drawables) {
- SkGlyph* skGlyph = variant;
- // Only floor the device coordinates.
- SkRect dstRect;
- if (!this->needsTransform()) {
- pos = {SkScalarFloorToScalar(pos.x()), SkScalarFloorToScalar(pos.y())};
- dstRect = dest_rect(*skGlyph, pos);
- } else {
- dstRect = dest_rect(*skGlyph, pos, strikeToSource);
- }
-
- this->joinGlyphBounds(dstRect);
-
- // V0
- *reinterpret_cast<SkPoint3*>(vertexCursor) = {dstRect.fLeft, dstRect.fTop, 1.f};
- *reinterpret_cast<GrColor*>(vertexCursor + colorOffset) = fCurrentColor;
- vertexCursor += vertexStride;
-
- // V1
- *reinterpret_cast<SkPoint3*>(vertexCursor) = {dstRect.fLeft, dstRect.fBottom, 1.f};
- *reinterpret_cast<GrColor*>(vertexCursor + colorOffset) = fCurrentColor;
- vertexCursor += vertexStride;
-
- // V2
- *reinterpret_cast<SkPoint3*>(vertexCursor) = {dstRect.fRight, dstRect.fTop, 1.f};
- *reinterpret_cast<GrColor*>(vertexCursor + colorOffset) = fCurrentColor;
- vertexCursor += vertexStride;
-
- // V3
- *reinterpret_cast<SkPoint3*>(vertexCursor) = {dstRect.fRight, dstRect.fBottom, 1.f};
- *reinterpret_cast<GrColor*>(vertexCursor + colorOffset) = fCurrentColor;
- vertexCursor += vertexStride;
-
- packedIDCursor->fPackedGlyphID = skGlyph->getPackedID();
- packedIDCursor++;
- }
-
- // Use the negative initial origin to make the fVertexBounds {0, 0} based.
- SkPoint pt = fBlob->fInitialOrigin;
- if (!this->needsTransform()) {
- // If the box is in device space, then transform the source space origin to device space.
- pt = fBlob->fInitialMatrix.mapXY(pt.x(), pt.y());
- }
- fVertexBounds.offset(-pt);
-}
+ , fVertexBounds{SkRect::MakeEmpty()}
+ , fVertexData{SkSpan<VertexData>{}} { }
void GrTextBlob::SubRun::resetBulkUseToken() { fBulkUseToken.reset(); }
GrDrawOpAtlas::BulkUseTokenUpdater* GrTextBlob::SubRun::bulkUseToken() { return &fBulkUseToken; }
-GrTextStrike* GrTextBlob::SubRun::strike() const { return fStrike.get(); }
GrMaskFormat GrTextBlob::SubRun::maskFormat() const { return fMaskFormat; }
-size_t GrTextBlob::SubRun::vertexStride() const {
- return GetVertexStride(this->maskFormat(), this->hasW());
-}
-size_t GrTextBlob::SubRun::colorOffset() const {
- return this->hasW() ? offsetof(SDFT3DVertex, color) : offsetof(Mask2DVertex, color);
-}
-size_t GrTextBlob::SubRun::texCoordOffset() const {
- switch (fMaskFormat) {
+size_t GrTextBlob::SubRun::vertexStride() const {
+ switch (this->maskFormat()) {
case kA8_GrMaskFormat:
- return this->hasW() ? offsetof(SDFT3DVertex, atlasPos)
- : offsetof(Mask2DVertex, atlasPos);
+ return this->hasW() ? sizeof(Mask3DVertex) : sizeof(Mask2DVertex);
case kARGB_GrMaskFormat:
- return this->hasW() ? offsetof(ARGB3DVertex, atlasPos)
- : offsetof(ARGB2DVertex, atlasPos);
+ return this->hasW() ? sizeof(ARGB3DVertex) : sizeof(ARGB2DVertex);
default:
SkASSERT(!this->hasW());
- return offsetof(Mask2DVertex, atlasPos);
+ return sizeof(Mask2DVertex);
}
-}
-
-char* GrTextBlob::SubRun::quadStart(size_t index) const {
- return SkTAddOffset<char>(fVertexData.data(), this->quadOffset(index));
+ SkUNREACHABLE;
}
size_t GrTextBlob::SubRun::quadOffset(size_t index) const {
return index * kVerticesPerGlyph * this->vertexStride();
}
-void GrTextBlob::SubRun::joinGlyphBounds(const SkRect& glyphBounds) {
- fVertexBounds.joinNonEmptyArg(glyphBounds);
+template <typename Rect>
+static auto ltbr(const Rect& r) {
+ return std::make_tuple(r.left(), r.top(), r.right(), r.bottom());
+}
+
+void GrTextBlob::SubRun::fillVertexData(
+ void *vertexDst, int offset, int count,
+ GrColor color, const SkMatrix& drawMatrix, SkPoint drawOrigin, SkIRect clip) const {
+
+ SkMatrix matrix = drawMatrix;
+ matrix.preTranslate(drawOrigin.x(), drawOrigin.y());
+
+ auto transformed2D = [&](auto dst, SkScalar dstPadding, SkScalar srcPadding) {
+ SkScalar strikeToSource = fStrikeSpec.strikeToSourceRatio();
+ SkPoint inset = {dstPadding, dstPadding};
+ for (auto[quad, vertexData] : SkMakeZip(dst, fVertexData.subspan(offset, count))) {
+ auto[glyph, pos, rect] = vertexData;
+ auto [l, t, r, b] = rect;
+ SkPoint sLT = (SkPoint::Make(l, t) + inset) * strikeToSource + pos,
+ sRB = (SkPoint::Make(r, b) - inset) * strikeToSource + pos;
+ SkPoint lt = matrix.mapXY(sLT.x(), sLT.y()),
+ lb = matrix.mapXY(sLT.x(), sRB.y()),
+ rt = matrix.mapXY(sRB.x(), sLT.y()),
+ rb = matrix.mapXY(sRB.x(), sRB.y());
+ auto[al, at, ar, ab] = glyph.grGlyph->fAtlasLocator.getUVs(srcPadding);
+ quad[0] = {lt, color, {al, at}}; // L,T
+ quad[1] = {lb, color, {al, ab}}; // L,B
+ quad[2] = {rt, color, {ar, at}}; // R,T
+ quad[3] = {rb, color, {ar, ab}}; // R,B
+ }
+ };
+
+ auto transformed3D = [&](auto dst, SkScalar dstPadding, SkScalar srcPadding) {
+ SkScalar strikeToSource = fStrikeSpec.strikeToSourceRatio();
+ SkPoint inset = {dstPadding, dstPadding};
+ auto mapXYZ = [&](SkScalar x, SkScalar y) {
+ SkPoint pt{x, y};
+ SkPoint3 result;
+ matrix.mapHomogeneousPoints(&result, &pt, 1);
+ return result;
+ };
+ for (auto[quad, vertexData] : SkMakeZip(dst, fVertexData.subspan(offset, count))) {
+ auto[glyph, pos, rect] = vertexData;
+ auto [l, t, r, b] = rect;
+ SkPoint sLT = (SkPoint::Make(l, t) + inset) * strikeToSource + pos,
+ sRB = (SkPoint::Make(r, b) - inset) * strikeToSource + pos;
+ SkPoint3 lt = mapXYZ(sLT.x(), sLT.y()),
+ lb = mapXYZ(sLT.x(), sRB.y()),
+ rt = mapXYZ(sRB.x(), sLT.y()),
+ rb = mapXYZ(sRB.x(), sRB.y());
+ auto[al, at, ar, ab] = glyph.grGlyph->fAtlasLocator.getUVs(srcPadding);
+ quad[0] = {lt, color, {al, at}}; // L,T
+ quad[1] = {lb, color, {al, ab}}; // L,B
+ quad[2] = {rt, color, {ar, at}}; // R,T
+ quad[3] = {rb, color, {ar, ab}}; // R,B
+ }
+ };
+
+ auto direct2D = [&](auto dst, SkIRect* clip) {
+ // Rectangles in device space
+ SkPoint originInDeviceSpace = matrix.mapXY(0, 0);
+ for (auto[quad, vertexData] : SkMakeZip(dst, fVertexData.subspan(offset, count))) {
+ auto[glyph, pos, rect] = vertexData;
+ auto[l, t, r, b] = rect;
+ auto[fx, fy] = pos + originInDeviceSpace;
+ auto[al, at, ar, ab] = glyph.grGlyph->fAtlasLocator.getUVs(0);
+ if (clip == nullptr) {
+ SkScalar dx = SkScalarRoundToScalar(fx),
+ dy = SkScalarRoundToScalar(fy);
+ auto[dl, dt, dr, db] = SkRect::MakeLTRB(l + dx, t + dy, r + dx, b + dy);
+ quad[0] = {{dl, dt}, color, {al, at}}; // L,T
+ quad[1] = {{dl, db}, color, {al, ab}}; // L,B
+ quad[2] = {{dr, dt}, color, {ar, at}}; // R,T
+ quad[3] = {{dr, db}, color, {ar, ab}}; // R,B
+ } else {
+ int dx = SkScalarRoundToInt(fx),
+ dy = SkScalarRoundToInt(fy);
+ SkIRect devIRect = SkIRect::MakeLTRB(l + dx, t + dy, r + dx, b + dy);
+ SkScalar dl, dt, dr, db;
+ uint16_t tl, tt, tr, tb;
+ if (!clip->containsNoEmptyCheck(devIRect)) {
+ if (SkIRect clipped; clipped.intersect(devIRect, *clip)) {
+ int lD = clipped.left() - devIRect.left();
+ int tD = clipped.top() - devIRect.top();
+ int rD = clipped.right() - devIRect.right();
+ int bD = clipped.bottom() - devIRect.bottom();
+ int indexLT, indexRB;
+ std::tie(dl, dt, dr, db) = ltbr(clipped);
+ std::tie(tl, tt, indexLT) =
+ GrDrawOpAtlas::UnpackIndexFromTexCoords(al, at);
+ std::tie(tr, tb, indexRB) =
+ GrDrawOpAtlas::UnpackIndexFromTexCoords(ar, ab);
+ std::tie(tl, tt) =
+ GrDrawOpAtlas::PackIndexInTexCoords(tl + lD, tt + tD, indexLT);
+ std::tie(tr, tb) =
+ GrDrawOpAtlas::PackIndexInTexCoords(tr + rD, tb + bD, indexRB);
+ } else {
+ // TODO: omit generating any vertex data for fully clipped glyphs ?
+ std::tie(dl, dt, dr, db) = std::make_tuple(0, 0, 0, 0);
+ std::tie(tl, tt, tr, tb) = std::make_tuple(0, 0, 0, 0);
+ }
+
+ } else {
+ std::tie(dl, dt, dr, db) = ltbr(devIRect);
+ std::tie(tl, tt, tr, tb) = std::tie(al, at, ar, ab);
+ }
+ quad[0] = {{dl, dt}, color, {tl, tt}}; // L,T
+ quad[1] = {{dl, db}, color, {tl, tb}}; // L,B
+ quad[2] = {{dr, dt}, color, {tr, tt}}; // R,T
+ quad[3] = {{dr, db}, color, {tr, tb}}; // R,B
+ }
+ }
+ };
+
+ switch (fType) {
+ case kDirectMask: {
+ if (clip.isEmpty()) {
+ if (this->maskFormat() != kARGB_GrMaskFormat) {
+ using Quad = Mask2DVertex[4];
+ SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph);
+ direct2D((Quad*) vertexDst, nullptr);
+ } else {
+ using Quad = ARGB2DVertex[4];
+ SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph);
+ direct2D((Quad*) vertexDst, nullptr);
+ }
+ } else {
+ if (this->maskFormat() != kARGB_GrMaskFormat) {
+ using Quad = Mask2DVertex[4];
+ SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph);
+ direct2D((Quad*) vertexDst, &clip);
+ } else {
+ using Quad = ARGB2DVertex[4];
+ SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph);
+ direct2D((Quad*) vertexDst, &clip);
+ }
+ }
+ break;
+ }
+ case kTransformedMask: {
+ if (!this->hasW()) {
+ if (this->maskFormat() == GrMaskFormat::kARGB_GrMaskFormat) {
+ using Quad = ARGB2DVertex[4];
+ SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph);
+ transformed2D((Quad*) vertexDst, 0, 1);
+ } else {
+ using Quad = Mask2DVertex[4];
+ SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph);
+ transformed2D((Quad*) vertexDst, 0, 1);
+ }
+ } else {
+ if (this->maskFormat() == GrMaskFormat::kARGB_GrMaskFormat) {
+ using Quad = ARGB3DVertex[4];
+ SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph);
+ transformed3D((Quad*) vertexDst, 0, 1);
+ } else {
+ using Quad = Mask3DVertex[4];
+ SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph);
+ transformed3D((Quad*) vertexDst, 0, 1);
+ }
+ }
+ break;
+ }
+ case kTransformedSDFT: {
+ if (!this->hasW()) {
+ using Quad = Mask2DVertex[4];
+ SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph);
+ transformed2D((Quad*) vertexDst, SK_DistanceFieldInset, SK_DistanceFieldInset);
+ } else {
+ using Quad = Mask3DVertex[4];
+ SkASSERT(sizeof(Quad) == this->vertexStride() * kVerticesPerGlyph);
+ transformed3D((Quad*) vertexDst, SK_DistanceFieldInset, SK_DistanceFieldInset);
+ }
+ break;
+ }
+ case kTransformedPath:
+ SK_ABORT("Paths don't generate vertex data.");
+ }
+}
+
+int GrTextBlob::SubRun::glyphCount() const {
+ return fVertexData.count();
}
bool GrTextBlob::SubRun::drawAsDistanceFields() const { return fType == kTransformedSDFT; }
@@ -204,8 +279,22 @@ bool GrTextBlob::SubRun::needsPadding() const {
return fType == kTransformedPath || fType == kTransformedMask;
}
+int GrTextBlob::SubRun::atlasPadding() const {
+ return SkTo<int>(this->needsPadding());
+}
+
+auto GrTextBlob::SubRun::vertexData() const -> SkSpan<const VertexData> {
+ return fVertexData;
+}
+
bool GrTextBlob::SubRun::hasW() const {
- return fBlob->hasW(fType);
+ if (fType == kTransformedSDFT || fType == kTransformedMask || fType == kTransformedPath) {
+ return fBlob->hasPerspective();
+ }
+
+ // The viewMatrix is implicitly SkMatrix::I when drawing kDirectMask, because it is not
+ // used.
+ return false;
}
void GrTextBlob::SubRun::prepareGrGlyphs(GrStrikeCache* strikeCache) {
@@ -215,114 +304,248 @@ void GrTextBlob::SubRun::prepareGrGlyphs(GrStrikeCache* strikeCache) {
fStrike = fStrikeSpec.findOrCreateGrStrike(strikeCache);
- for (auto& tmp : fGlyphs) {
- tmp.fGrGlyph = fStrike->getGlyph(tmp.fPackedGlyphID);
+ for (auto& tmp : fVertexData) {
+ tmp.glyph.grGlyph = fStrike->getGlyph(tmp.glyph.packedGlyphID);
}
}
-void GrTextBlob::SubRun::translateVerticesIfNeeded(
- const SkMatrix& drawMatrix, SkPoint drawOrigin) {
- SkVector translation;
+SkRect GrTextBlob::SubRun::deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const {
+ SkRect outBounds = fVertexBounds;
if (this->needsTransform()) {
- // If transform is needed, then the vertices are in source space, calculate the source
- // space translation.
- translation = drawOrigin - fCurrentOrigin;
+ // if the glyph needs transformation offset the by the new origin, and map to device space.
+ outBounds.offset(drawOrigin);
+ outBounds = drawMatrix.mapRect(outBounds);
} else {
- // Calculate the translation in source space to a translation in device space. Calculate
- // the translation by mapping (0, 0) through both the current matrix, and the draw
- // matrix, and taking the difference.
- SkMatrix currentMatrix{fCurrentMatrix};
- currentMatrix.preTranslate(fCurrentOrigin.x(), fCurrentOrigin.y());
- SkPoint currentDeviceOrigin{0, 0};
- currentMatrix.mapPoints(&currentDeviceOrigin, 1);
- SkMatrix completeDrawMatrix{drawMatrix};
- completeDrawMatrix.preTranslate(drawOrigin.x(), drawOrigin.y());
- SkPoint drawDeviceOrigin{0, 0};
- completeDrawMatrix.mapPoints(&drawDeviceOrigin, 1);
- translation = drawDeviceOrigin - currentDeviceOrigin;
+ SkPoint offset = drawMatrix.mapXY(drawOrigin.x(), drawOrigin.y());
+ // The vertex bounds are already {0, 0} based, so just add the new origin offset.
+ outBounds.offset(offset);
+
+ // Due to floating point numerical inaccuracies, we have to round out here
+ outBounds.roundOut();
}
+ return outBounds;
+}
- if (translation != SkPoint{0, 0}) {
- size_t vertexStride = this->vertexStride();
- for (size_t quad = 0; quad < fGlyphs.size(); quad++) {
- SkPoint* vertexCursor = reinterpret_cast<SkPoint*>(quadStart(quad));
- for (int i = 0; i < 4; ++i) {
- *vertexCursor += translation;
- vertexCursor = SkTAddOffset<SkPoint>(vertexCursor, vertexStride);
- }
- }
- fCurrentMatrix = drawMatrix;
- fCurrentOrigin = drawOrigin;
+GrGlyph* GrTextBlob::SubRun::grGlyph(int i) const {
+ return fVertexData[i].glyph.grGlyph;
+}
+
+void GrTextBlob::SubRun::setUseLCDText(bool useLCDText) { fUseLCDText = useLCDText; }
+bool GrTextBlob::SubRun::hasUseLCDText() const { return fUseLCDText; }
+void GrTextBlob::SubRun::setAntiAliased(bool antiAliased) { fAntiAliased = antiAliased; }
+bool GrTextBlob::SubRun::isAntiAliased() const { return fAntiAliased; }
+const SkStrikeSpec& GrTextBlob::SubRun::strikeSpec() const { return fStrikeSpec; }
+
+auto GrTextBlob::SubRun::MakePaths(
+ const SkZip<SkGlyphVariant, SkPoint>& drawables,
+ const SkFont& runFont,
+ const SkStrikeSpec& strikeSpec,
+ GrTextBlob* blob,
+ SkArenaAlloc* alloc) -> SubRun* {
+ SubRun* subRun = alloc->make<SubRun>(blob, strikeSpec);
+ subRun->setAntiAliased(runFont.hasSomeAntiAliasing());
+ for (auto [variant, pos] : drawables) {
+ subRun->fPaths.emplace_back(*variant.path(), pos);
}
+ return subRun;
+};
+
+auto GrTextBlob::SubRun::MakeSDFT(
+ const SkZip<SkGlyphVariant, SkPoint>& drawables,
+ const SkFont& runFont,
+ const SkStrikeSpec& strikeSpec,
+ GrTextBlob* blob,
+ SkArenaAlloc* alloc) -> SubRun* {
+ SubRun* subRun = SubRun::InitForAtlas(
+ kTransformedSDFT, drawables, strikeSpec, kA8_GrMaskFormat, blob, alloc);
+ subRun->setUseLCDText(runFont.getEdging() == SkFont::Edging::kSubpixelAntiAlias);
+ subRun->setAntiAliased(runFont.hasSomeAntiAliasing());
+ return subRun;
+}
+
+auto GrTextBlob::SubRun::MakeDirectMask(
+ const SkZip<SkGlyphVariant, SkPoint>& drawables,
+ const SkStrikeSpec& strikeSpec,
+ GrMaskFormat format,
+ GrTextBlob* blob,
+ SkArenaAlloc* alloc) -> SubRun* {
+ return SubRun::InitForAtlas(kDirectMask, drawables, strikeSpec, format, blob, alloc);
}
-void GrTextBlob::SubRun::updateVerticesColorIfNeeded(GrColor newColor) {
- if (this->maskFormat() != kARGB_GrMaskFormat && fCurrentColor != newColor) {
- size_t vertexStride = this->vertexStride();
- size_t colorOffset = this->colorOffset();
- for (size_t quad = 0; quad < fGlyphs.size(); quad++) {
- GrColor* colorCursor = SkTAddOffset<GrColor>(quadStart(quad), colorOffset);
- for (int i = 0; i < 4; ++i) {
- *colorCursor = newColor;
- colorCursor = SkTAddOffset<GrColor>(colorCursor, vertexStride);
+auto GrTextBlob::SubRun::MakeTransformedMask(
+ const SkZip<SkGlyphVariant, SkPoint>& drawables,
+ const SkStrikeSpec& strikeSpec,
+ GrMaskFormat format,
+ GrTextBlob* blob,
+ SkArenaAlloc* alloc) -> SubRun* {
+ return SubRun::InitForAtlas(kTransformedMask, drawables, strikeSpec, format, blob, alloc);
+}
+
+void GrTextBlob::SubRun::insertSubRunOpsIntoTarget(GrTextTarget* target,
+ const SkSurfaceProps& props,
+ const SkPaint& paint,
+ const GrClip* clip,
+ const SkMatrixProvider& deviceMatrix,
+ SkPoint drawOrigin) {
+ if (this->drawAsPaths()) {
+ SkPaint runPaint{paint};
+ runPaint.setAntiAlias(this->isAntiAliased());
+ // If there are shaders, blurs or styles, the path must be scaled into source
+ // space independently of the CTM. This allows the CTM to be correct for the
+ // different effects.
+ GrStyle style(runPaint);
+
+ bool needsExactCTM = runPaint.getShader()
+ || style.applies()
+ || runPaint.getMaskFilter();
+
+ // Calculate the matrix that maps the path glyphs from their size in the strike to
+ // the graphics source space.
+ SkScalar scale = this->fStrikeSpec.strikeToSourceRatio();
+ SkMatrix strikeToSource = SkMatrix::Scale(scale, scale);
+ strikeToSource.postTranslate(drawOrigin.x(), drawOrigin.y());
+ if (!needsExactCTM) {
+ for (const auto& pathPos : this->fPaths) {
+ const SkPath& path = pathPos.fPath;
+ const SkPoint pos = pathPos.fOrigin; // Transform the glyph to source space.
+ SkMatrix pathMatrix = strikeToSource;
+ pathMatrix.postTranslate(pos.x(), pos.y());
+ SkPreConcatMatrixProvider strikeToDevice(deviceMatrix, pathMatrix);
+
+ GrStyledShape shape(path, paint);
+ target->drawShape(clip, runPaint, strikeToDevice, shape);
+ }
+ } else {
+ // Transform the path to device because the deviceMatrix must be unchanged to
+ // draw effect, filter or shader paths.
+ for (const auto& pathPos : this->fPaths) {
+ const SkPath& path = pathPos.fPath;
+ const SkPoint pos = pathPos.fOrigin;
+ // Transform the glyph to source space.
+ SkMatrix pathMatrix = strikeToSource;
+ pathMatrix.postTranslate(pos.x(), pos.y());
+
+ SkPath deviceOutline;
+ path.transform(pathMatrix, &deviceOutline);
+ deviceOutline.setIsVolatile(true);
+ GrStyledShape shape(deviceOutline, paint);
+ target->drawShape(clip, runPaint, deviceMatrix, shape);
}
}
- this->fCurrentColor = newColor;
+ } else {
+ int glyphCount = this->glyphCount();
+ if (0 == glyphCount) {
+ return;
+ }
+
+ bool skipClip = false;
+ SkIRect clipRect = SkIRect::MakeEmpty();
+ SkRect rtBounds = SkRect::MakeWH(target->width(), target->height());
+ SkRRect clipRRect = SkRRect::MakeRect(rtBounds);
+ GrAA aa;
+ // We can clip geometrically if we're not using SDFs or transformed glyphs,
+ // and we have an axis-aligned rectangular non-AA clip
+ if (!this->drawAsDistanceFields() &&
+ !this->needsTransform() &&
+ (!clip || (clip->isRRect(&clipRRect, &aa) &&
+ clipRRect.isRect() && GrAA::kNo == aa))) {
+ // We only need to do clipping work if the subrun isn't contained by the clip
+ SkRect subRunBounds = this->deviceRect(deviceMatrix.localToDevice(), drawOrigin);
+ if (!clipRRect.getBounds().contains(subRunBounds)) {
+ // If the subrun is completely outside, don't add an op for it
+ if (!clipRRect.getBounds().intersects(subRunBounds)) {
+ return;
+ } else {
+ clipRRect.getBounds().round(&clipRect);
+ }
+ }
+ skipClip = true;
+ }
+
+ auto op = this->makeOp(deviceMatrix, drawOrigin, clipRect, paint, props, target);
+ if (op != nullptr) {
+ target->addDrawOp(skipClip ? nullptr : clip, std::move(op));
+ }
}
}
-void GrTextBlob::SubRun::updateTexCoords(int begin, int end) {
- SkASSERT(this->isPrepared());
-
- const size_t vertexStride = this->vertexStride();
- const size_t texCoordOffset = this->texCoordOffset();
- char* vertex = this->quadStart(begin);
- uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
- for (int i = begin; i < end; i++) {
- GrGlyph* glyph = this->fGlyphs[i].fGrGlyph;
- SkASSERT(glyph != nullptr);
-
- int pad = this->drawAsDistanceFields() ? SK_DistanceFieldInset
- : (this->needsPadding() ? 1 : 0);
- std::array<uint16_t, 4> uvs = glyph->fAtlasLocator.getUVs(pad);
-
- textureCoords[0] = uvs[0];
- textureCoords[1] = uvs[1];
- textureCoords = SkTAddOffset<uint16_t>(textureCoords, vertexStride);
- textureCoords[0] = uvs[0];
- textureCoords[1] = uvs[3];
- textureCoords = SkTAddOffset<uint16_t>(textureCoords, vertexStride);
- textureCoords[0] = uvs[2];
- textureCoords[1] = uvs[1];
- textureCoords = SkTAddOffset<uint16_t>(textureCoords, vertexStride);
- textureCoords[0] = uvs[2];
- textureCoords[1] = uvs[3];
- textureCoords = SkTAddOffset<uint16_t>(textureCoords, vertexStride);
+SkPMColor4f generate_filtered_color(const SkPaint& paint, const GrColorInfo& colorInfo) {
+ SkColor4f c = paint.getColor4f();
+ if (auto* xform = colorInfo.colorSpaceXformFromSRGB()) {
+ c = xform->apply(c);
+ }
+ if (auto* cf = paint.getColorFilter()) {
+ c = cf->filterColor4f(c, colorInfo.colorSpace(), colorInfo.colorSpace());
}
+ return c.premul();
}
-SkRect GrTextBlob::SubRun::deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const {
- SkRect outBounds = fVertexBounds;
- if (this->needsTransform()) {
- // if the glyph needs transformation offset the by the new origin, and map to device space.
- outBounds.offset(drawOrigin);
- outBounds = drawMatrix.mapRect(outBounds);
- } else {
- SkPoint offset = drawMatrix.mapXY(drawOrigin.x(), drawOrigin.y());
- // The vertex bounds are already {0, 0} based, so just add the new origin offset.
- outBounds.offset(offset);
+std::unique_ptr<GrAtlasTextOp> GrTextBlob::SubRun::makeOp(const SkMatrixProvider& matrixProvider,
+ SkPoint drawOrigin,
+ const SkIRect& clipRect,
+ const SkPaint& paint,
+ const SkSurfaceProps& props,
+ GrTextTarget* target) {
+ GrPaint grPaint;
+ target->makeGrPaint(this->maskFormat(), paint, matrixProvider, &grPaint);
+ const GrColorInfo& colorInfo = target->colorInfo();
+ // This is the color the op will use to draw.
+ SkPMColor4f drawingColor = generate_filtered_color(paint, colorInfo);
- // Due to floating point numerical inaccuracies, we have to round out here
- outBounds.roundOut();
+ if (this->drawAsDistanceFields()) {
+ // TODO: Can we be even smarter based on the dest transfer function?
+ return GrAtlasTextOp::MakeDistanceField(target->getContext(),
+ std::move(grPaint),
+ this,
+ matrixProvider.localToDevice(),
+ drawOrigin,
+ clipRect,
+ drawingColor,
+ target->colorInfo().isLinearlyBlended(),
+ SkPaintPriv::ComputeLuminanceColor(paint),
+ props);
+ } else {
+ return GrAtlasTextOp::MakeBitmap(target->getContext(),
+ std::move(grPaint),
+ this,
+ matrixProvider.localToDevice(),
+ drawOrigin,
+ clipRect,
+ drawingColor);
}
- return outBounds;
}
-void GrTextBlob::SubRun::setUseLCDText(bool useLCDText) { fFlags.useLCDText = useLCDText; }
-bool GrTextBlob::SubRun::hasUseLCDText() const { return fFlags.useLCDText; }
-void GrTextBlob::SubRun::setAntiAliased(bool antiAliased) { fFlags.antiAliased = antiAliased; }
-bool GrTextBlob::SubRun::isAntiAliased() const { return fFlags.antiAliased; }
-const SkStrikeSpec& GrTextBlob::SubRun::strikeSpec() const { return fStrikeSpec; }
+auto GrTextBlob::SubRun::InitForAtlas(SubRunType type,
+ const SkZip<SkGlyphVariant, SkPoint>& drawables,
+ const SkStrikeSpec& strikeSpec,
+ GrMaskFormat format,
+ GrTextBlob* blob,
+ SkArenaAlloc* alloc) -> SubRun* {
+ size_t vertexCount = drawables.size();
+ using Data = VertexData;
+ SkRect bounds = SkRectPriv::MakeLargestInverted();
+ auto initializer = [&, strikeToSource=strikeSpec.strikeToSourceRatio()](size_t i) {
+ auto [variant, pos] = drawables[i];
+ SkGlyph* skGlyph = variant;
+ int16_t l = skGlyph->left();
+ int16_t t = skGlyph->top();
+ int16_t r = l + skGlyph->width();
+ int16_t b = t + skGlyph->height();
+ SkPoint lt = SkPoint::Make(l, t) * strikeToSource + pos,
+ rb = SkPoint::Make(r, b) * strikeToSource + pos;
+
+ bounds.joinPossiblyEmptyRect(SkRect::MakeLTRB(lt.x(), lt.y(), rb.x(), rb.y()));
+ return Data{{skGlyph->getPackedID()}, pos, {l, t, r, b}};
+ };
+
+ SkSpan<Data> vertexData{
+ alloc->makeInitializedArray<Data>(vertexCount, initializer), vertexCount};
+
+ SubRun* subRun = alloc->make<SubRun>(type, blob, strikeSpec, format, bounds, vertexData);
+
+ return subRun;
+}
+
// -- GrTextBlob -----------------------------------------------------------------------------------
void GrTextBlob::operator delete(void* p) { ::operator delete(p); }
@@ -331,33 +554,12 @@ void* GrTextBlob::operator new(size_t, void* p) { return p; }
GrTextBlob::~GrTextBlob() = default;
-sk_sp<GrTextBlob> GrTextBlob::Make(const SkGlyphRunList& glyphRunList,
- const SkMatrix& drawMatrix,
- GrColor color,
- bool forceWForDistanceFields) {
-
- static_assert(sizeof(ARGB2DVertex) <= sizeof(Mask2DVertex));
- static_assert(alignof(ARGB2DVertex) <= alignof(Mask2DVertex));
- size_t quadSize = sizeof(Mask2DVertex) * kVerticesPerGlyph;
- if (drawMatrix.hasPerspective() || forceWForDistanceFields) {
- static_assert(sizeof(ARGB3DVertex) <= sizeof(SDFT3DVertex));
- static_assert(alignof(ARGB3DVertex) <= alignof(SDFT3DVertex));
- quadSize = sizeof(SDFT3DVertex) * kVerticesPerGlyph;
- }
-
- // We can use the alignment of SDFT3DVertex as a proxy for all Vertex alignments.
- static_assert(alignof(SDFT3DVertex) >= alignof(Mask2DVertex));
- // Assume there is no padding needed between glyph pointers and vertices.
- static_assert(alignof(GrGlyph*) >= alignof(SDFT3DVertex));
-
- // In the arena, the layout is GrGlyph*... | SDFT3DVertex... | SubRun, so there is no padding
- // between GrGlyph* and SDFT3DVertex, but padding is needed between the Mask2DVertex array
- // and the SubRun.
- size_t vertexToSubRunPadding = alignof(SDFT3DVertex) - alignof(SubRun);
- size_t arenaSize =
- sizeof(GrGlyph*) * glyphRunList.totalGlyphCount()
- + quadSize * glyphRunList.totalGlyphCount()
- + glyphRunList.runCount() * (sizeof(SubRun) + vertexToSubRunPadding);
+sk_sp<GrTextBlob> GrTextBlob::Make(const SkGlyphRunList& glyphRunList, const SkMatrix& drawMatrix) {
+ // The difference in alignment from the storage of VertexData to SubRun;
+ constexpr size_t alignDiff = alignof(SubRun) - alignof(SubRun::VertexData);
+ constexpr size_t vertexDataToSubRunPadding = alignDiff > 0 ? alignDiff : 0;
+ size_t arenaSize = sizeof(SubRun::VertexData) * glyphRunList.totalGlyphCount()
+ + glyphRunList.runCount() * (sizeof(SubRun) + vertexDataToSubRunPadding);
size_t allocationSize = sizeof(GrTextBlob) + arenaSize;
@@ -365,8 +567,7 @@ sk_sp<GrTextBlob> GrTextBlob::Make(const SkGlyphRunList& glyphRunList,
SkColor initialLuminance = SkPaintPriv::ComputeLuminanceColor(glyphRunList.paint());
sk_sp<GrTextBlob> blob{new (allocation) GrTextBlob{
- arenaSize, drawMatrix, glyphRunList.origin(),
- color, initialLuminance, forceWForDistanceFields}};
+ arenaSize, drawMatrix, glyphRunList.origin(), initialLuminance}};
return blob;
}
@@ -400,42 +601,31 @@ void GrTextBlob::setMinAndMaxScale(SkScalar scaledMin, SkScalar scaledMax) {
fMinMaxScale = std::min(scaledMax, fMinMaxScale);
}
-size_t GrTextBlob::GetVertexStride(GrMaskFormat maskFormat, bool hasWCoord) {
- switch (maskFormat) {
- case kA8_GrMaskFormat:
- return hasWCoord ? sizeof(SDFT3DVertex) : sizeof(Mask2DVertex);
- case kARGB_GrMaskFormat:
- return hasWCoord ? sizeof(ARGB3DVertex) : sizeof(ARGB2DVertex);
- default:
- SkASSERT(!hasWCoord);
- return sizeof(Mask2DVertex);
- }
-}
-
-bool GrTextBlob::mustRegenerate(const SkPaint& paint, bool anyRunHasSubpixelPosition,
- const SkMaskFilterBase::BlurRec& blurRec,
- const SkMatrix& drawMatrix, SkPoint drawOrigin) {
+bool GrTextBlob::canReuse(const SkPaint& paint,
+ const SkMaskFilterBase::BlurRec& blurRec,
+ const SkMatrix& drawMatrix,
+ SkPoint drawOrigin) {
// If we have LCD text then our canonical color will be set to transparent, in this case we have
// to regenerate the blob on any color change
// We use the grPaint to get any color filter effects
if (fKey.fCanonicalColor == SK_ColorTRANSPARENT &&
fInitialLuminance != SkPaintPriv::ComputeLuminanceColor(paint)) {
- return true;
+ return false;
}
if (fInitialMatrix.hasPerspective() != drawMatrix.hasPerspective()) {
- return true;
+ return false;
}
/** This could be relaxed for blobs with only distance field glyphs. */
if (fInitialMatrix.hasPerspective() && !SkMatrixPriv::CheapEqual(fInitialMatrix, drawMatrix)) {
- return true;
+ return false;
}
// We only cache one masked version
if (fKey.fHasBlur &&
(fBlurRec.fSigma != blurRec.fSigma || fBlurRec.fStyle != blurRec.fStyle)) {
- return true;
+ return false;
}
// Similarly, we only cache one version for each style
@@ -443,15 +633,14 @@ bool GrTextBlob::mustRegenerate(const SkPaint& paint, bool anyRunHasSubpixelPosi
(fStrokeInfo.fFrameWidth != paint.getStrokeWidth() ||
fStrokeInfo.fMiterLimit != paint.getStrokeMiter() ||
fStrokeInfo.fJoin != paint.getStrokeJoin())) {
- return true;
+ return false;
}
// Mixed blobs must be regenerated. We could probably figure out a way to do integer scrolls
// for mixed blobs if this becomes an issue.
if (this->hasBitmap() && this->hasDistanceField()) {
// Identical view matrices and we can reuse in all cases
- return !(SkMatrixPriv::CheapEqual(fInitialMatrix, drawMatrix) &&
- drawOrigin == fInitialOrigin);
+ return SkMatrixPriv::CheapEqual(fInitialMatrix, drawMatrix) && drawOrigin == fInitialOrigin;
}
if (this->hasBitmap()) {
@@ -459,7 +648,7 @@ bool GrTextBlob::mustRegenerate(const SkPaint& paint, bool anyRunHasSubpixelPosi
fInitialMatrix.getScaleY() != drawMatrix.getScaleY() ||
fInitialMatrix.getSkewX() != drawMatrix.getSkewX() ||
fInitialMatrix.getSkewY() != drawMatrix.getSkewY()) {
- return true;
+ return false;
}
// TODO(herb): this is not needed for full pixel glyph choice, but is needed to adjust
@@ -481,7 +670,7 @@ bool GrTextBlob::mustRegenerate(const SkPaint& paint, bool anyRunHasSubpixelPosi
SkPoint translation = drawDeviceOrigin - initialDeviceOrigin;
if (!SkScalarIsInt(translation.x()) || !SkScalarIsInt(translation.y())) {
- return true;
+ return false;
}
} else if (this->hasDistanceField()) {
// A scale outside of [blob.fMaxMinScale, blob.fMinMaxScale] would result in a different
@@ -490,170 +679,31 @@ bool GrTextBlob::mustRegenerate(const SkPaint& paint, bool anyRunHasSubpixelPosi
SkScalar oldMaxScale = fInitialMatrix.getMaxScale();
SkScalar scaleAdjust = newMaxScale / oldMaxScale;
if (scaleAdjust < fMaxMinScale || scaleAdjust > fMinMaxScale) {
- return true;
+ return false;
}
}
- // It is possible that a blob has neither distanceField nor bitmaptext. This is in the case
- // when all of the runs inside the blob are drawn as paths. In this case, we always regenerate
- // the blob anyways at flush time, so no need to regenerate explicitly
- return false;
+ // If the blob is all paths, there is no reason to regenerate.
+ return true;
}
-void GrTextBlob::addOp(GrTextTarget* target,
- const SkSurfaceProps& props,
- const SkPaint& paint,
- const SkPMColor4f& filteredColor,
- const GrClip& clip,
- const SkMatrixProvider& deviceMatrix,
- SkPoint drawOrigin) {
+void GrTextBlob::insertOpsIntoTarget(GrTextTarget* target,
+ const SkSurfaceProps& props,
+ const SkPaint& paint,
+ const GrClip* clip,
+ const SkMatrixProvider& deviceMatrix,
+ SkPoint drawOrigin) {
for (SubRun* subRun = fFirstSubRun; subRun != nullptr; subRun = subRun->fNextSubRun) {
- if (subRun->drawAsPaths()) {
- SkPaint runPaint{paint};
- runPaint.setAntiAlias(subRun->isAntiAliased());
- // If there are shaders, blurs or styles, the path must be scaled into source
- // space independently of the CTM. This allows the CTM to be correct for the
- // different effects.
- GrStyle style(runPaint);
-
- bool needsExactCTM = runPaint.getShader()
- || style.applies()
- || runPaint.getMaskFilter();
-
- // Calculate the matrix that maps the path glyphs from their size in the strike to
- // the graphics source space.
- SkMatrix strikeToSource = SkMatrix::MakeScale(
- subRun->fStrikeSpec.strikeToSourceRatio());
- strikeToSource.postTranslate(drawOrigin.x(), drawOrigin.y());
- if (!needsExactCTM) {
- for (const auto& pathPos : subRun->fPaths) {
- const SkPath& path = pathPos.fPath;
- const SkPoint pos = pathPos.fOrigin; // Transform the glyph to source space.
- SkMatrix pathMatrix = strikeToSource;
- pathMatrix.postTranslate(pos.x(), pos.y());
- SkPreConcatMatrixProvider strikeToDevice(deviceMatrix, pathMatrix);
-
- GrStyledShape shape(path, paint);
- target->drawShape(clip, runPaint, strikeToDevice, shape);
- }
- } else {
- // Transform the path to device because the deviceMatrix must be unchanged to
- // draw effect, filter or shader paths.
- for (const auto& pathPos : subRun->fPaths) {
- const SkPath& path = pathPos.fPath;
- const SkPoint pos = pathPos.fOrigin;
- // Transform the glyph to source space.
- SkMatrix pathMatrix = strikeToSource;
- pathMatrix.postTranslate(pos.x(), pos.y());
-
- SkPath deviceOutline;
- path.transform(pathMatrix, &deviceOutline);
- deviceOutline.setIsVolatile(true);
- GrStyledShape shape(deviceOutline, paint);
- target->drawShape(clip, runPaint, deviceMatrix, shape);
- }
- }
- } else {
- int glyphCount = subRun->fGlyphs.count();
- if (0 == glyphCount) {
- continue;
- }
-
- bool skipClip = false;
- SkIRect clipRect = SkIRect::MakeEmpty();
- SkRect rtBounds = SkRect::MakeWH(target->width(), target->height());
- SkRRect clipRRect;
- GrAA aa;
- // We can clip geometrically if we're not using SDFs or transformed glyphs,
- // and we have an axis-aligned rectangular non-AA clip
- if (!subRun->drawAsDistanceFields() &&
- !subRun->needsTransform() &&
- clip.isRRect(rtBounds, &clipRRect, &aa) &&
- clipRRect.isRect() && GrAA::kNo == aa) {
- skipClip = true;
- // We only need to do clipping work if the subrun isn't contained by the clip
- SkRect subRunBounds = subRun->deviceRect(deviceMatrix.localToDevice(), drawOrigin);
- if (!clipRRect.getBounds().contains(subRunBounds)) {
- // If the subrun is completely outside, don't add an op for it
- if (!clipRRect.getBounds().intersects(subRunBounds)) {
- continue;
- } else {
- clipRRect.getBounds().round(&clipRect);
- }
- }
- }
-
- auto op = this->makeOp(*subRun, deviceMatrix, drawOrigin, clipRect,
- paint, filteredColor, props, target);
- if (op) {
- if (skipClip) {
- target->addDrawOp(GrNoClip(), std::move(op));
- }
- else {
- target->addDrawOp(clip, std::move(op));
- }
- }
- }
+ subRun->insertSubRunOpsIntoTarget(target, props, paint, clip, deviceMatrix, drawOrigin);
}
}
const GrTextBlob::Key& GrTextBlob::key() const { return fKey; }
size_t GrTextBlob::size() const { return fSize; }
-std::unique_ptr<GrDrawOp> GrTextBlob::test_makeOp(const SkMatrixProvider& matrixProvider,
- SkPoint drawOrigin,
- const SkPaint& paint,
- const SkPMColor4f& filteredColor,
- const SkSurfaceProps& props,
- GrTextTarget* target) {
- SubRun* info = fFirstSubRun;
- SkIRect emptyRect = SkIRect::MakeEmpty();
- return this->makeOp(*info, matrixProvider, drawOrigin, emptyRect, paint,
- filteredColor, props, target);
-}
-
-bool GrTextBlob::hasW(GrTextBlob::SubRunType type) const {
- if (type == kTransformedSDFT) {
- return this->hasPerspective() || fForceWForDistanceFields;
- } else if (type == kTransformedMask || type == kTransformedPath) {
- return this->hasPerspective();
- }
-
- // The viewMatrix is implicitly SkMatrix::I when drawing kDirectMask, because it is not
- // used.
- return false;
-}
-
-GrTextBlob::SubRun* GrTextBlob::makeSubRun(SubRunType type,
- const SkZip<SkGlyphVariant, SkPoint>& drawables,
- const SkStrikeSpec& strikeSpec,
- GrMaskFormat format) {
- SkSpan<SubRun::PackedGlyphIDorGrGlyph> glyphs{
- fAlloc.makeArrayDefault<SubRun::PackedGlyphIDorGrGlyph>(drawables.size()), drawables.size()};
- bool hasW = this->hasW(type);
-
- SkASSERT(!fInitialMatrix.hasPerspective() || hasW);
-
- size_t vertexDataSize = drawables.size() * GetVertexStride(format, hasW) * kVerticesPerGlyph;
- SkSpan<char> vertexData{fAlloc.makeArrayDefault<char>(vertexDataSize), vertexDataSize};
-
- SubRun* subRun = fAlloc.make<SubRun>(type, this, strikeSpec, format, glyphs, vertexData);
-
- subRun->appendGlyphs(drawables);
-
- return subRun;
-}
-
-void GrTextBlob::addSingleMaskFormat(
- SubRunType type,
- const SkZip<SkGlyphVariant, SkPoint>& drawables,
- const SkStrikeSpec& strikeSpec,
- GrMaskFormat format) {
- this->makeSubRun(type, drawables, strikeSpec, format);
-}
-
+template<typename AddSingleMaskFormat>
void GrTextBlob::addMultiMaskFormat(
- SubRunType type,
+ AddSingleMaskFormat addSingle,
const SkZip<SkGlyphVariant, SkPoint>& drawables,
const SkStrikeSpec& strikeSpec) {
this->setHasBitmap();
@@ -668,39 +718,24 @@ void GrTextBlob::addMultiMaskFormat(
GrMaskFormat nextFormat = GrGlyph::FormatFromSkGlyph(glyph->maskFormat());
if (format != nextFormat) {
auto sameFormat = drawables.subspan(startIndex, i - startIndex);
- this->addSingleMaskFormat(type, sameFormat, strikeSpec, format);
+ SubRun* subRun = addSingle(sameFormat, strikeSpec, format, this, &fAlloc);
+ this->insertSubRun(subRun);
format = nextFormat;
startIndex = i;
}
}
auto sameFormat = drawables.last(drawables.size() - startIndex);
- this->addSingleMaskFormat(type, sameFormat, strikeSpec, format);
-}
-
-void GrTextBlob::addSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
- const SkStrikeSpec& strikeSpec,
- const SkFont& runFont,
- SkScalar minScale,
- SkScalar maxScale) {
- this->setHasDistanceField();
- this->setMinAndMaxScale(minScale, maxScale);
-
- SubRun* subRun = this->makeSubRun(kTransformedSDFT, drawables, strikeSpec, kA8_GrMaskFormat);
- subRun->setUseLCDText(runFont.getEdging() == SkFont::Edging::kSubpixelAntiAlias);
- subRun->setAntiAliased(runFont.hasSomeAntiAliasing());
+ SubRun* subRun = addSingle(sameFormat, strikeSpec, format, this, &fAlloc);
+ this->insertSubRun(subRun);
}
GrTextBlob::GrTextBlob(size_t allocSize,
const SkMatrix& drawMatrix,
SkPoint origin,
- GrColor color,
- SkColor initialLuminance,
- bool forceWForDistanceFields)
+ SkColor initialLuminance)
: fSize{allocSize}
, fInitialMatrix{drawMatrix}
, fInitialOrigin{origin}
- , fForceWForDistanceFields{forceWForDistanceFields}
- , fColor{color}
, fInitialLuminance{initialLuminance}
, fAlloc{SkTAddOffset<char>(this, sizeof(GrTextBlob)), allocSize, allocSize/2} { }
@@ -714,53 +749,18 @@ void GrTextBlob::insertSubRun(SubRun* subRun) {
}
}
-std::unique_ptr<GrAtlasTextOp> GrTextBlob::makeOp(SubRun& info,
- const SkMatrixProvider& matrixProvider,
- SkPoint drawOrigin,
- const SkIRect& clipRect,
- const SkPaint& paint,
- const SkPMColor4f& filteredColor,
- const SkSurfaceProps& props,
- GrTextTarget* target) {
- GrPaint grPaint;
- target->makeGrPaint(info.maskFormat(), paint, matrixProvider, &grPaint);
- if (info.drawAsDistanceFields()) {
- // TODO: Can we be even smarter based on the dest transfer function?
- return GrAtlasTextOp::MakeDistanceField(target->getContext(),
- std::move(grPaint),
- &info,
- matrixProvider.localToDevice(),
- drawOrigin,
- clipRect,
- filteredColor,
- target->colorInfo().isLinearlyBlended(),
- SkPaintPriv::ComputeLuminanceColor(paint),
- props);
- } else {
- return GrAtlasTextOp::MakeBitmap(target->getContext(),
- std::move(grPaint),
- &info,
- matrixProvider.localToDevice(),
- drawOrigin,
- clipRect,
- filteredColor);
- }
-}
-
void GrTextBlob::processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
const SkStrikeSpec& strikeSpec) {
- this->addMultiMaskFormat(kDirectMask, drawables, strikeSpec);
+
+ this->addMultiMaskFormat(SubRun::MakeDirectMask, drawables, strikeSpec);
}
void GrTextBlob::processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables,
const SkFont& runFont,
const SkStrikeSpec& strikeSpec) {
this->setHasBitmap();
- SubRun* subRun = fAlloc.make<SubRun>(this, strikeSpec);
- subRun->setAntiAliased(runFont.hasSomeAntiAliasing());
- for (auto [variant, pos] : drawables) {
- subRun->fPaths.emplace_back(*variant.path(), pos);
- }
+ SubRun* subRun = SubRun::MakePaths(drawables, runFont, strikeSpec, this, &fAlloc);
+ this->insertSubRun(subRun);
}
void GrTextBlob::processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
@@ -768,158 +768,18 @@ void GrTextBlob::processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawabl
const SkFont& runFont,
SkScalar minScale,
SkScalar maxScale) {
- this->addSDFT(drawables, strikeSpec, runFont, minScale, maxScale);
+ this->setHasDistanceField();
+ this->setMinAndMaxScale(minScale, maxScale);
+ SubRun* subRun = SubRun::MakeSDFT(drawables, runFont, strikeSpec, this, &fAlloc);
+ this->insertSubRun(subRun);
}
void GrTextBlob::processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
const SkStrikeSpec& strikeSpec) {
- this->addMultiMaskFormat(kTransformedMask, drawables, strikeSpec);
-}
-
-// -- Adding a mask to an atlas ----------------------------------------------------------------
-
-// expands each bit in a bitmask to 0 or ~0 of type INT_TYPE. Used to expand a BW glyph mask to
-// A8, RGB565, or RGBA8888.
-template <typename INT_TYPE>
-static void expand_bits(INT_TYPE* dst,
- const uint8_t* src,
- int width,
- int height,
- int dstRowBytes,
- int srcRowBytes) {
- for (int i = 0; i < height; ++i) {
- int rowWritesLeft = width;
- const uint8_t* s = src;
- INT_TYPE* d = dst;
- while (rowWritesLeft > 0) {
- unsigned mask = *s++;
- for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) {
- *d++ = (mask & (1 << i)) ? (INT_TYPE)(~0UL) : 0;
- }
- }
- dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes);
- src += srcRowBytes;
- }
-}
-
-static void get_packed_glyph_image(
- const SkGlyph& glyph, int dstRB, GrMaskFormat expectedMaskFormat, void* dst) {
- const int width = glyph.width();
- const int height = glyph.height();
- const void* src = glyph.image();
- SkASSERT(src != nullptr);
-
- GrMaskFormat grMaskFormat = GrGlyph::FormatFromSkGlyph(glyph.maskFormat());
- if (grMaskFormat == expectedMaskFormat) {
- int srcRB = glyph.rowBytes();
- // Notice this comparison is with the glyphs raw mask format, and not its GrMaskFormat.
- if (glyph.maskFormat() != SkMask::kBW_Format) {
- if (srcRB != dstRB) {
- const int bbp = GrMaskFormatBytesPerPixel(expectedMaskFormat);
- for (int y = 0; y < height; y++) {
- memcpy(dst, src, width * bbp);
- src = (const char*) src + srcRB;
- dst = (char*) dst + dstRB;
- }
- } else {
- memcpy(dst, src, dstRB * height);
- }
- } else {
- // Handle 8-bit format by expanding the mask to the expected format.
- const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
- switch (expectedMaskFormat) {
- case kA8_GrMaskFormat: {
- uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
- expand_bits(bytes, bits, width, height, dstRB, srcRB);
- break;
- }
- case kA565_GrMaskFormat: {
- uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst);
- expand_bits(rgb565, bits, width, height, dstRB, srcRB);
- break;
- }
- default:
- SK_ABORT("Invalid GrMaskFormat");
- }
- }
- } else if (grMaskFormat == kA565_GrMaskFormat && expectedMaskFormat == kARGB_GrMaskFormat) {
- // Convert if the glyph uses a 565 mask format since it is using LCD text rendering
- // but the expected format is 8888 (will happen on macOS with Metal since that
- // combination does not support 565).
- static constexpr SkMasks masks{
- {0b1111'1000'0000'0000, 11, 5}, // Red
- {0b0000'0111'1110'0000, 5, 6}, // Green
- {0b0000'0000'0001'1111, 0, 5}, // Blue
- {0, 0, 0} // Alpha
- };
- const int a565Bpp = GrMaskFormatBytesPerPixel(kA565_GrMaskFormat);
- const int argbBpp = GrMaskFormatBytesPerPixel(kARGB_GrMaskFormat);
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- uint16_t color565 = 0;
- memcpy(&color565, src, a565Bpp);
- uint32_t colorRGBA = GrColorPackRGBA(masks.getRed(color565),
- masks.getGreen(color565),
- masks.getBlue(color565),
- 0xFF);
- memcpy(dst, &colorRGBA, argbBpp);
- src = (char*)src + a565Bpp;
- dst = (char*)dst + argbBpp;
- }
- }
- } else {
- // crbug:510931
- // Retrieving the image from the cache can actually change the mask format. This case is
- // very uncommon so for now we just draw a clear box for these glyphs.
- const int bpp = GrMaskFormatBytesPerPixel(expectedMaskFormat);
- for (int y = 0; y < height; y++) {
- sk_bzero(dst, width * bpp);
- dst = (char*)dst + dstRB;
- }
- }
+ this->addMultiMaskFormat(SubRun::MakeTransformedMask, drawables, strikeSpec);
}
-// returns true if glyph successfully added to texture atlas, false otherwise. If the glyph's
-// mask format has changed, then add_glyph_to_atlas will draw a clear box. This will almost never
-// happen.
-// TODO we can handle some of these cases if we really want to, but the long term solution is to
-// get the actual glyph image itself when we get the glyph metrics.
-static GrDrawOpAtlas::ErrorCode add_glyph_to_atlas(const SkGlyph& skGlyph,
- GrMaskFormat expectedMaskFormat,
- bool needsPadding,
- GrResourceProvider* resourceProvider,
- GrDeferredUploadTarget* target,
- GrAtlasManager* fullAtlasManager,
- GrGlyph* grGlyph) {
- SkASSERT(grGlyph != nullptr);
- SkASSERT(skGlyph.image() != nullptr);
-
- expectedMaskFormat = fullAtlasManager->resolveMaskFormat(expectedMaskFormat);
- int bytesPerPixel = GrMaskFormatBytesPerPixel(expectedMaskFormat);
-
- SkDEBUGCODE(bool isSDFGlyph = skGlyph.maskFormat() == SkMask::kSDF_Format;)
- SkASSERT(!needsPadding || !isSDFGlyph);
-
- // Add 1 pixel padding around grGlyph if needed.
- const int width = needsPadding ? skGlyph.width() + 2 : skGlyph.width();
- const int height = needsPadding ? skGlyph.height() + 2 : skGlyph.height();
- int rowBytes = width * bytesPerPixel;
- size_t size = height * rowBytes;
-
- // Temporary storage for normalizing grGlyph image.
- SkAutoSMalloc<1024> storage(size);
- void* dataPtr = storage.get();
- if (needsPadding) {
- sk_bzero(dataPtr, size);
- // Advance in one row and one column.
- dataPtr = (char*)(dataPtr) + rowBytes + bytesPerPixel;
- }
-
- get_packed_glyph_image(skGlyph, rowBytes, expectedMaskFormat, dataPtr);
-
- return fullAtlasManager->addToAtlas(resourceProvider, target, expectedMaskFormat, width, height,
- storage.get(), &grGlyph->fAtlasLocator);
-}
+auto GrTextBlob::firstSubRun() const -> SubRun* { return fFirstSubRun; }
// -- GrTextBlob::VertexRegenerator ----------------------------------------------------------------
GrTextBlob::VertexRegenerator::VertexRegenerator(GrResourceProvider* resourceProvider,
@@ -935,43 +795,32 @@ std::tuple<bool, int> GrTextBlob::VertexRegenerator::updateTextureCoordinates(
const int begin, const int end) {
SkASSERT(fSubRun->isPrepared());
- const SkStrikeSpec& strikeSpec = fSubRun->strikeSpec();
- if (!fMetricsAndImages.isValid() ||
- fMetricsAndImages->descriptor() != strikeSpec.descriptor()) {
- fMetricsAndImages.init(strikeSpec);
- }
+ SkBulkGlyphMetricsAndImages metricsAndImages{fSubRun->strikeSpec()};
// Update the atlas information in the GrStrike.
- auto code = GrDrawOpAtlas::ErrorCode::kSucceeded;
auto tokenTracker = fUploadTarget->tokenTracker();
- int i = begin;
- for (; i < end; i++) {
- GrGlyph* grGlyph = fSubRun->fGlyphs[i].fGrGlyph;
- SkASSERT(grGlyph);
+ auto vertexData = fSubRun->vertexData().subspan(begin, end - begin);
+ int glyphsPlacedInAtlas = 0;
+ for (auto [glyph, pos, rect] : vertexData) {
+ GrGlyph* grGlyph = glyph.grGlyph;
+ SkASSERT(grGlyph != nullptr);
if (!fFullAtlasManager->hasGlyph(fSubRun->maskFormat(), grGlyph)) {
- const SkGlyph& skGlyph = *fMetricsAndImages->glyph(grGlyph->fPackedID);
- if (skGlyph.image() == nullptr) {
- return {false, 0};
- }
- code = add_glyph_to_atlas(skGlyph, fSubRun->maskFormat(),
- fSubRun->needsPadding(), fResourceProvider,
- fUploadTarget, fFullAtlasManager, grGlyph);
+ const SkGlyph& skGlyph = *metricsAndImages.glyph(grGlyph->fPackedID);
+ auto code = fFullAtlasManager->addGlyphToAtlas(
+ skGlyph, fSubRun->atlasPadding(), grGlyph, fResourceProvider, fUploadTarget);
if (code != GrDrawOpAtlas::ErrorCode::kSucceeded) {
- break;
+ return {code != GrDrawOpAtlas::ErrorCode::kError, glyphsPlacedInAtlas};
}
}
fFullAtlasManager->addGlyphToBulkAndSetUseToken(
fSubRun->bulkUseToken(), fSubRun->maskFormat(), grGlyph,
tokenTracker->nextDrawToken());
+ glyphsPlacedInAtlas++;
}
- int glyphsPlacedInAtlas = i - begin;
- // Update the quads with the new atlas coordinates.
- fSubRun->updateTexCoords(begin, begin + glyphsPlacedInAtlas);
-
- return {code != GrDrawOpAtlas::ErrorCode::kError, glyphsPlacedInAtlas};
+ return {true, glyphsPlacedInAtlas};
}
std::tuple<bool, int> GrTextBlob::VertexRegenerator::regenerate(int begin, int end) {
@@ -984,15 +833,16 @@ std::tuple<bool, int> GrTextBlob::VertexRegenerator::regenerate(int begin, int e
auto [success, glyphsPlacedInAtlas] = this->updateTextureCoordinates(begin, end);
// Update atlas generation if there are no more glyphs to put in the atlas.
- if (success && begin + glyphsPlacedInAtlas == fSubRun->fGlyphs.count()) {
+ if (success && begin + glyphsPlacedInAtlas == fSubRun->glyphCount()) {
// Need to get the freshest value of the atlas' generation because
// updateTextureCoordinates may have changed it.
fSubRun->fAtlasGeneration = fFullAtlasManager->atlasGeneration(fSubRun->maskFormat());
}
+
return {success, glyphsPlacedInAtlas};
} else {
// The atlas hasn't changed, so our texture coordinates are still valid.
- if (end == fSubRun->fGlyphs.count()) {
+ if (end == fSubRun->glyphCount()) {
// The atlas hasn't changed and the texture coordinates are all still valid. Update
// all the plots used to the new use token.
fFullAtlasManager->setUseTokenBulk(*fSubRun->bulkUseToken(),
diff --git a/chromium/third_party/skia/src/gpu/text/GrTextBlob.h b/chromium/third_party/skia/src/gpu/text/GrTextBlob.h
index 98f813a258c..ab04255c2da 100644
--- a/chromium/third_party/skia/src/gpu/text/GrTextBlob.h
+++ b/chromium/third_party/skia/src/gpu/text/GrTextBlob.h
@@ -27,7 +27,7 @@ class GrAtlasTextOp;
class GrDeferredUploadTarget;
class GrGlyph;
class GrStrikeCache;
-class GrTextContext;
+class GrTextTarget;
class SkMatrixProvider;
class SkSurfaceProps;
@@ -61,13 +61,6 @@ public:
class SubRun;
class VertexRegenerator;
- enum SubRunType {
- kDirectMask,
- kTransformedMask,
- kTransformedPath,
- kTransformedSDFT
- };
-
struct Key {
Key();
uint32_t fUniqueID;
@@ -105,9 +98,7 @@ public:
// Make an empty GrTextBlob, with all the invariants set to make the right decisions when
// adding SubRuns.
static sk_sp<GrTextBlob> Make(const SkGlyphRunList& glyphRunList,
- const SkMatrix& drawMatrix,
- GrColor color,
- bool forceWForDistanceFields);
+ const SkMatrix& drawMatrix);
// Key manipulation functions
void setupKey(const GrTextBlob::Key& key,
@@ -124,78 +115,30 @@ public:
void setHasBitmap();
void setMinAndMaxScale(SkScalar scaledMin, SkScalar scaledMax);
- static size_t GetVertexStride(GrMaskFormat maskFormat, bool hasWCoord);
+ bool canReuse(const SkPaint& paint, const SkMaskFilterBase::BlurRec& blurRec,
+ const SkMatrix& drawMatrix, SkPoint drawOrigin);
- bool mustRegenerate(const SkPaint&, bool, const SkMaskFilterBase::BlurRec& blurRec,
- const SkMatrix& drawMatrix, SkPoint drawOrigin);
-
- void addOp(GrTextTarget* target,
- const SkSurfaceProps& props,
- const SkPaint& paint,
- const SkPMColor4f& filteredColor,
- const GrClip& clip,
- const SkMatrixProvider& deviceMatrix,
- SkPoint drawOrigin);
-
-
- // Normal text mask, SDFT, or color.
- struct Mask2DVertex {
- SkPoint devicePos;
- GrColor color;
- SkIPoint16 atlasPos;
- };
- struct ARGB2DVertex {
- SkPoint devicePos;
- SkIPoint16 atlasPos;
- };
-
- // Perspective SDFT or SDFT forced to 3D or perspective color.
- struct SDFT3DVertex {
- SkPoint3 devicePos;
- GrColor color;
- SkIPoint16 atlasPos;
- };
- struct ARGB3DVertex {
- SkPoint3 devicePos;
- SkIPoint16 atlasPos;
- };
+ void insertOpsIntoTarget(GrTextTarget* target,
+ const SkSurfaceProps& props,
+ const SkPaint& paint,
+ const GrClip* clip,
+ const SkMatrixProvider& deviceMatrix,
+ SkPoint drawOrigin);
static const int kVerticesPerGlyph = 4;
const Key& key() const;
size_t size() const;
- // Internal test methods
- std::unique_ptr<GrDrawOp> test_makeOp(const SkMatrixProvider& matrixProvider,
- SkPoint drawOrigin,
- const SkPaint& paint,
- const SkPMColor4f& filteredColor,
- const SkSurfaceProps&,
- GrTextTarget*);
-
- bool hasW(SubRunType type) const;
-
- SubRun* makeSubRun(SubRunType type,
- const SkZip<SkGlyphVariant, SkPoint>& drawables,
- const SkStrikeSpec& strikeSpec,
- GrMaskFormat format);
-
- void addSingleMaskFormat(
- SubRunType type,
- const SkZip<SkGlyphVariant, SkPoint>& drawables,
- const SkStrikeSpec& strikeSpec,
- GrMaskFormat format);
-
+ template<typename AddSingleMaskFormat>
void addMultiMaskFormat(
- SubRunType type,
+ AddSingleMaskFormat addSingle,
const SkZip<SkGlyphVariant, SkPoint>& drawables,
const SkStrikeSpec& strikeSpec);
- void addSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
- const SkStrikeSpec& strikeSpec,
- const SkFont& runFont,
- SkScalar minScale,
- SkScalar maxScale);
+ SubRun* firstSubRun() const;
+
+ bool forceWForDistanceFields() const;
private:
enum TextType {
@@ -212,21 +155,10 @@ private:
GrTextBlob(size_t allocSize,
const SkMatrix& drawMatrix,
SkPoint origin,
- GrColor color,
- SkColor initialLuminance,
- bool forceWForDistanceFields);
+ SkColor initialLuminance);
void insertSubRun(SubRun* subRun);
- std::unique_ptr<GrAtlasTextOp> makeOp(SubRun& info,
- const SkMatrixProvider& matrixProvider,
- SkPoint drawOrigin,
- const SkIRect& clipRect,
- const SkPaint& paint,
- const SkPMColor4f& filteredColor,
- const SkSurfaceProps&,
- GrTextTarget*);
-
// Methods to satisfy SkGlyphRunPainterInterface
void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
const SkStrikeSpec& strikeSpec) override;
@@ -254,11 +186,6 @@ private:
// blob.
const SkPoint fInitialOrigin;
- // From the distance field options to force distance fields to have a W coordinate.
- const bool fForceWForDistanceFields;
-
- // The color of the text to draw for solid colors.
- const GrColor fColor;
const SkColor fInitialLuminance;
SkMaskFilterBase::BlurRec fBlurRec;
@@ -306,7 +233,6 @@ private:
GrResourceProvider* fResourceProvider;
GrDeferredUploadTarget* fUploadTarget;
GrAtlasManager* fFullAtlasManager;
- SkTLazy<SkBulkGlyphMetricsAndImages> fMetricsAndImages;
SubRun* fSubRun;
};
@@ -314,15 +240,24 @@ private:
// Hold data to draw the different types of sub run. SubRuns are produced knowing all the
// glyphs that are included in them.
class GrTextBlob::SubRun {
+ enum SubRunType {
+ kDirectMask,
+ kTransformedMask,
+ kTransformedPath,
+ kTransformedSDFT
+ };
+
public:
- // Within a glyph-based subRun, the glyphs are initially recorded as SkPackedGlyphs. At
- // flush time they are then converted to GrGlyph's (via the GrTextStrike). Once converted
- // they are never converted back.
- union PackedGlyphIDorGrGlyph {
- PackedGlyphIDorGrGlyph() {}
-
- SkPackedGlyphID fPackedGlyphID;
- GrGlyph* fGrGlyph;
+ struct VertexData {
+ union {
+ // Initially, filled with packed id, but changed to GrGlyph* in the onPrepare stage.
+ SkPackedGlyphID packedGlyphID;
+ GrGlyph* grGlyph;
+ } glyph;
+ const SkPoint pos;
+ // The rectangle of the glyphs in strike space. But, for kDirectMask this also implies a
+ // device space rect.
+ GrIRect16 rect;
};
// SubRun for masks
@@ -330,79 +265,144 @@ public:
GrTextBlob* textBlob,
const SkStrikeSpec& strikeSpec,
GrMaskFormat format,
- const SkSpan<PackedGlyphIDorGrGlyph>& glyphs,
- const SkSpan<char>& vertexData);
+ SkRect vertexBounds,
+ const SkSpan<VertexData>& vertexData);
// SubRun for paths
SubRun(GrTextBlob* textBlob, const SkStrikeSpec& strikeSpec);
- void appendGlyphs(const SkZip<SkGlyphVariant, SkPoint>& drawables);
-
// TODO when this object is more internal, drop the privacy
void resetBulkUseToken();
GrDrawOpAtlas::BulkUseTokenUpdater* bulkUseToken();
- GrTextStrike* strike() const;
GrMaskFormat maskFormat() const;
size_t vertexStride() const;
- size_t colorOffset() const;
- size_t texCoordOffset() const;
- char* quadStart(size_t index) const;
size_t quadOffset(size_t index) const;
+ void fillVertexData(
+ void* vertexDst, int offset, int count,
+ GrColor color, const SkMatrix& drawMatrix, SkPoint drawOrigin,
+ SkIRect clip) const;
- void joinGlyphBounds(const SkRect& glyphBounds);
+ int glyphCount() const;
bool drawAsDistanceFields() const;
- bool drawAsPaths() const;
bool needsTransform() const;
bool needsPadding() const;
+ int atlasPadding() const;
+ SkSpan<const VertexData> vertexData() const;
+
// Acquire a GrTextStrike and convert the SkPackedGlyphIDs to GrGlyphs for this run
void prepareGrGlyphs(GrStrikeCache*);
// has 'prepareGrGlyphs' been called (i.e., can the GrGlyphs be accessed) ?
SkDEBUGCODE(bool isPrepared() const { return SkToBool(fStrike); })
- void translateVerticesIfNeeded(const SkMatrix& drawMatrix, SkPoint drawOrigin);
- void updateVerticesColorIfNeeded(GrColor newColor);
- void updateTexCoords(int begin, int end);
-
// The rectangle that surrounds all the glyph bounding boxes in device space.
SkRect deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const;
+ GrGlyph* grGlyph(int i) const;
+
// df properties
- void setUseLCDText(bool useLCDText);
bool hasUseLCDText() const;
- void setAntiAliased(bool antiAliased);
bool isAntiAliased() const;
const SkStrikeSpec& strikeSpec() const;
+ static SubRun* MakePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables,
+ const SkFont& runFont,
+ const SkStrikeSpec& strikeSpec,
+ GrTextBlob* blob,
+ SkArenaAlloc* alloc);
+ static SubRun* MakeSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
+ const SkFont& runFont,
+ const SkStrikeSpec& strikeSpec,
+ GrTextBlob* blob,
+ SkArenaAlloc* alloc);
+ static SubRun* MakeDirectMask(const SkZip<SkGlyphVariant, SkPoint>& drawables,
+ const SkStrikeSpec& strikeSpec,
+ GrMaskFormat format,
+ GrTextBlob* blob,
+ SkArenaAlloc* alloc);
+ static SubRun* MakeTransformedMask(const SkZip<SkGlyphVariant, SkPoint>& drawables,
+ const SkStrikeSpec& strikeSpec,
+ GrMaskFormat format,
+ GrTextBlob* blob,
+ SkArenaAlloc* alloc);
+
+ void insertSubRunOpsIntoTarget(GrTextTarget* target,
+ const SkSurfaceProps& props,
+ const SkPaint& paint,
+ const GrClip* clip,
+ const SkMatrixProvider& deviceMatrix,
+ SkPoint drawOrigin);
+
+ std::unique_ptr<GrAtlasTextOp> makeOp(const SkMatrixProvider& matrixProvider,
+ SkPoint drawOrigin,
+ const SkIRect& clipRect,
+ const SkPaint& paint,
+ const SkSurfaceProps&,
+ GrTextTarget*);
+
SubRun* fNextSubRun{nullptr};
+ GrTextBlob* fBlob;
+ uint64_t fAtlasGeneration{GrDrawOpAtlas::kInvalidAtlasGeneration};
+
+private:
+ struct AtlasPt {
+ uint16_t u;
+ uint16_t v;
+ };
+
+ // Normal text mask, SDFT, or color.
+ struct Mask2DVertex {
+ SkPoint devicePos;
+ GrColor color;
+ AtlasPt atlasPos;
+ };
+ struct ARGB2DVertex {
+ ARGB2DVertex(SkPoint d, GrColor, AtlasPt a) : devicePos{d}, atlasPos{a} {}
+ SkPoint devicePos;
+ AtlasPt atlasPos;
+ };
+
+ // Perspective SDFT or SDFT forced to 3D or perspective color.
+ struct Mask3DVertex {
+ SkPoint3 devicePos;
+ GrColor color;
+ AtlasPt atlasPos;
+ };
+ struct ARGB3DVertex {
+ ARGB3DVertex(SkPoint3 d, GrColor, AtlasPt a) : devicePos{d}, atlasPos{a} {}
+ SkPoint3 devicePos;
+ AtlasPt atlasPos;
+ };
+
+ static SubRun* InitForAtlas(SubRunType type,
+ const SkZip<SkGlyphVariant, SkPoint>& drawables,
+ const SkStrikeSpec& strikeSpec,
+ GrMaskFormat format,
+ GrTextBlob* blob,
+ SkArenaAlloc* alloc);
+ bool hasW() const;
+ void setUseLCDText(bool useLCDText);
+ void setAntiAliased(bool antiAliased);
+ bool drawAsPaths() const;
+
const SubRunType fType;
- GrTextBlob* const fBlob;
const GrMaskFormat fMaskFormat;
- const SkSpan<PackedGlyphIDorGrGlyph> fGlyphs;
- const SkSpan<char> fVertexData;
+ bool fUseLCDText{false};
+ bool fAntiAliased{false};
+
const SkStrikeSpec fStrikeSpec;
sk_sp<GrTextStrike> fStrike;
- struct {
- bool useLCDText:1;
- bool antiAliased:1;
- } fFlags{false, false};
- GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken;
- uint64_t fAtlasGeneration{GrDrawOpAtlas::kInvalidAtlasGeneration};
- GrColor fCurrentColor;
- SkPoint fCurrentOrigin;
- SkMatrix fCurrentMatrix;
- std::vector<PathGlyph> fPaths;
-private:
+ GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken;
// The vertex bounds in device space if needsTransform() is false, otherwise the bounds in
// source space. The bounds are the joined rectangles of all the glyphs.
- SkRect fVertexBounds = SkRectPriv::MakeLargestInverted();
- bool hasW() const;
-
+ const SkRect fVertexBounds;
+ const SkSpan<VertexData> fVertexData;
+ std::vector<PathGlyph> fPaths;
}; // SubRun
#endif // GrTextBlob_DEFINED
diff --git a/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.cpp b/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.cpp
index c3a6860231e..29c855e7056 100644
--- a/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.cpp
+++ b/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.cpp
@@ -9,15 +9,64 @@
DECLARE_SKMESSAGEBUS_MESSAGE(GrTextBlobCache::PurgeBlobMessage)
+// This function is captured by the above macro using implementations from SkMessageBus.h
static inline bool SkShouldPostMessageToBus(
const GrTextBlobCache::PurgeBlobMessage& msg, uint32_t msgBusUniqueID) {
return msg.fContextID == msgBusUniqueID;
}
+GrTextBlobCache::GrTextBlobCache(PurgeMore purgeMore, uint32_t messageBusID)
+ : fPurgeMore(purgeMore)
+ , fSizeBudget(kDefaultBudget)
+ , fMessageBusID(messageBusID)
+ , fPurgeBlobInbox(messageBusID) { }
+
GrTextBlobCache::~GrTextBlobCache() {
this->freeAll();
}
+sk_sp<GrTextBlob>
+GrTextBlobCache::makeCachedBlob(const SkGlyphRunList& glyphRunList, const GrTextBlob::Key& key,
+ const SkMaskFilterBase::BlurRec& blurRec,
+ const SkMatrix& viewMatrix) {
+ sk_sp<GrTextBlob> cacheBlob(GrTextBlob::Make(glyphRunList, viewMatrix));
+ cacheBlob->setupKey(key, blurRec, glyphRunList.paint());
+ this->internalAdd(cacheBlob);
+ glyphRunList.temporaryShuntBlobNotifyAddedToCache(fMessageBusID);
+ return cacheBlob;
+}
+
+sk_sp<GrTextBlob> GrTextBlobCache::find(const GrTextBlob::Key& key) const {
+ const auto* idEntry = fBlobIDCache.find(key.fUniqueID);
+ return idEntry ? idEntry->find(key) : nullptr;
+}
+
+void GrTextBlobCache::remove(GrTextBlob* blob) {
+ this->internalRemove(blob);
+}
+
+void GrTextBlobCache::internalRemove(GrTextBlob* blob) {
+ auto id = GrTextBlob::GetKey(*blob).fUniqueID;
+ auto* idEntry = fBlobIDCache.find(id);
+ SkASSERT(idEntry);
+
+ fCurrentSize -= blob->size();
+ fBlobList.remove(blob);
+ idEntry->removeBlob(blob);
+ if (idEntry->fBlobs.empty()) {
+ fBlobIDCache.remove(id);
+ }
+}
+
+void GrTextBlobCache::makeMRU(GrTextBlob* blob) {
+ if (fBlobList.head() == blob) {
+ return;
+ }
+
+ fBlobList.remove(blob);
+ fBlobList.addToHead(blob);
+}
+
void GrTextBlobCache::freeAll() {
fBlobIDCache.foreach([this](uint32_t, BlobIDCacheEntry* entry) {
for (const auto& blob : entry->fBlobs) {
@@ -33,12 +82,21 @@ void GrTextBlobCache::freeAll() {
SkASSERT(fBlobList.isEmpty());
}
+void GrTextBlobCache::setBudget(size_t budget) {
+ fSizeBudget = budget;
+ this->internalCheckPurge();
+}
+
void GrTextBlobCache::PostPurgeBlobMessage(uint32_t blobID, uint32_t cacheID) {
SkASSERT(blobID != SK_InvalidGenID);
SkMessageBus<PurgeBlobMessage>::Post(PurgeBlobMessage(blobID, cacheID));
}
void GrTextBlobCache::purgeStaleBlobs() {
+ this->internalPurgeStaleBlobs();
+}
+
+void GrTextBlobCache::internalPurgeStaleBlobs() {
SkTArray<PurgeBlobMessage> msgs;
fPurgeBlobInbox.poll(&msgs);
@@ -60,36 +118,93 @@ void GrTextBlobCache::purgeStaleBlobs() {
}
}
-void GrTextBlobCache::checkPurge(GrTextBlob* blob) {
+size_t GrTextBlobCache::usedBytes() const {
+ return fCurrentSize;
+}
+
+void GrTextBlobCache::internalCheckPurge(GrTextBlob* blob) {
// First, purge all stale blob IDs.
- this->purgeStaleBlobs();
+ this->internalPurgeStaleBlobs();
// If we are still over budget, then unref until we are below budget again
if (fCurrentSize > fSizeBudget) {
- BitmapBlobList::Iter iter;
- iter.init(fBlobList, BitmapBlobList::Iter::kTail_IterStart);
+ TextBlobList::Iter iter;
+ iter.init(fBlobList, TextBlobList::Iter::kTail_IterStart);
GrTextBlob* lruBlob = nullptr;
while (fCurrentSize > fSizeBudget && (lruBlob = iter.get()) && lruBlob != blob) {
// Backup the iterator before removing and unrefing the blob
iter.prev();
- this->remove(lruBlob);
+ this->internalRemove(lruBlob);
}
// If we break out of the loop with lruBlob == blob, then we haven't purged enough
// use the call back and try to free some more. If we are still overbudget after this,
// then this single textblob is over our budget
if (blob && lruBlob == blob) {
- (*fCallback)(fData);
+ fPurgeMore();
}
-#ifdef SPEW_BUDGET_MESSAGE
+ #ifdef SPEW_BUDGET_MESSAGE
if (fCurrentSize > fSizeBudget) {
SkDebugf("Single textblob is larger than our whole budget");
}
-#endif
+ #endif
}
}
+void GrTextBlobCache::internalAdd(sk_sp<GrTextBlob> blob) {
+ auto id = GrTextBlob::GetKey(*blob).fUniqueID;
+ auto* idEntry = fBlobIDCache.find(id);
+ if (!idEntry) {
+ idEntry = fBlobIDCache.set(id, BlobIDCacheEntry(id));
+ }
+
+ // Safe to retain a raw ptr temporarily here, because the cache will hold a ref.
+ GrTextBlob* rawBlobPtr = blob.get();
+ fBlobList.addToHead(rawBlobPtr);
+ fCurrentSize += blob->size();
+ idEntry->addBlob(std::move(blob));
+
+ this->internalCheckPurge(rawBlobPtr);
+}
+
+GrTextBlobCache::BlobIDCacheEntry::BlobIDCacheEntry() : fID(SK_InvalidGenID) {}
+
+GrTextBlobCache::BlobIDCacheEntry::BlobIDCacheEntry(uint32_t id) : fID(id) {}
+
+uint32_t GrTextBlobCache::BlobIDCacheEntry::GetKey(const GrTextBlobCache::BlobIDCacheEntry& entry) {
+ return entry.fID;
+}
+
+void GrTextBlobCache::BlobIDCacheEntry::addBlob(sk_sp<GrTextBlob> blob) {
+ SkASSERT(blob);
+ SkASSERT(GrTextBlob::GetKey(*blob).fUniqueID == fID);
+ SkASSERT(!this->find(GrTextBlob::GetKey(*blob)));
+ fBlobs.emplace_back(std::move(blob));
+}
+
+void GrTextBlobCache::BlobIDCacheEntry::removeBlob(GrTextBlob* blob) {
+ SkASSERT(blob);
+ SkASSERT(GrTextBlob::GetKey(*blob).fUniqueID == fID);
+
+ auto index = this->findBlobIndex(GrTextBlob::GetKey(*blob));
+ SkASSERT(index >= 0);
+
+ fBlobs.removeShuffle(index);
+}
+sk_sp<GrTextBlob> GrTextBlobCache::BlobIDCacheEntry::find(const GrTextBlob::Key& key) const {
+ auto index = this->findBlobIndex(key);
+ return index < 0 ? nullptr : fBlobs[index];
+}
+
+int GrTextBlobCache::BlobIDCacheEntry::findBlobIndex(const GrTextBlob::Key& key) const {
+ for (int i = 0; i < fBlobs.count(); ++i) {
+ if (GrTextBlob::GetKey(*fBlobs[i]) == key) {
+ return i;
+ }
+ }
+ return -1;
+}
diff --git a/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.h b/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.h
index 9af2f2c5a1e..6dc46908229 100644
--- a/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.h
+++ b/chromium/third_party/skia/src/gpu/text/GrTextBlobCache.h
@@ -15,85 +15,30 @@
#include "src/core/SkTextBlobPriv.h"
#include "src/gpu/text/GrTextBlob.h"
+#include <functional>
+
class GrTextBlobCache {
public:
- /**
- * The callback function used by the cache when it is still over budget after a purge. The
- * passed in 'data' is the same 'data' handed to setOverbudgetCallback.
- */
- typedef void (*PFOverBudgetCB)(void* data);
-
- GrTextBlobCache(PFOverBudgetCB cb, void* data, uint32_t uniqueID)
- : fCallback(cb)
- , fData(data)
- , fSizeBudget(kDefaultBudget)
- , fUniqueID(uniqueID)
- , fPurgeBlobInbox(uniqueID) {
- SkASSERT(cb && data);
- }
- ~GrTextBlobCache();
+ // The callback function used by the cache when it is still over budget after a purge.
+ using PurgeMore = std::function<void()>;
- sk_sp<GrTextBlob> makeBlob(const SkGlyphRunList& glyphRunList,
- const SkMatrix& viewMatrix,
- GrColor color,
- bool forceW) {
- return GrTextBlob::Make(glyphRunList, viewMatrix, color, forceW);
- }
+ GrTextBlobCache(PurgeMore purgeMore, uint32_t messageBusID);
+ ~GrTextBlobCache();
sk_sp<GrTextBlob> makeCachedBlob(const SkGlyphRunList& glyphRunList,
const GrTextBlob::Key& key,
const SkMaskFilterBase::BlurRec& blurRec,
- const SkMatrix& viewMatrix,
- GrColor color,
- bool forceW) {
- sk_sp<GrTextBlob> cacheBlob(this->makeBlob(glyphRunList, viewMatrix, color, forceW));
- cacheBlob->setupKey(key, blurRec, glyphRunList.paint());
- this->add(cacheBlob);
- glyphRunList.temporaryShuntBlobNotifyAddedToCache(fUniqueID);
- return cacheBlob;
- }
-
- sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) const {
- const auto* idEntry = fBlobIDCache.find(key.fUniqueID);
- return idEntry ? idEntry->find(key) : nullptr;
- }
-
- void remove(GrTextBlob* blob) {
- auto id = GrTextBlob::GetKey(*blob).fUniqueID;
- auto* idEntry = fBlobIDCache.find(id);
- SkASSERT(idEntry);
-
- fCurrentSize -= blob->size();
- fBlobList.remove(blob);
- idEntry->removeBlob(blob);
- if (idEntry->fBlobs.empty()) {
- fBlobIDCache.remove(id);
- }
- }
-
- void makeMRU(GrTextBlob* blob) {
- if (fBlobList.head() == blob) {
- return;
- }
-
- fBlobList.remove(blob);
- fBlobList.addToHead(blob);
- }
+ const SkMatrix& viewMatrix);
- void freeAll();
+ sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) const;
- // TODO move to SkTextBlob
- static void BlobGlyphCount(int* glyphCount, int* runCount, const SkTextBlob* blob) {
- SkTextBlobRunIterator itCounter(blob);
- for (; !itCounter.done(); itCounter.next(), (*runCount)++) {
- *glyphCount += itCounter.glyphCount();
- }
- }
+ void remove(GrTextBlob* blob);
- void setBudget(size_t budget) {
- fSizeBudget = budget;
- this->checkPurge();
- }
+ void makeMRU(GrTextBlob* blob);
+
+ void freeAll();
+
+ void setBudget(size_t budget);
struct PurgeBlobMessage {
PurgeBlobMessage(uint32_t blobID, uint32_t contextUniqueID)
@@ -107,84 +52,48 @@ public:
void purgeStaleBlobs();
- size_t usedBytes() const { return fCurrentSize; }
+ size_t usedBytes() const;
private:
- using BitmapBlobList = SkTInternalLList<GrTextBlob>;
+ using TextBlobList = SkTInternalLList<GrTextBlob>;
struct BlobIDCacheEntry {
- BlobIDCacheEntry() : fID(SK_InvalidGenID) {}
- explicit BlobIDCacheEntry(uint32_t id) : fID(id) {}
-
- static uint32_t GetKey(const BlobIDCacheEntry& entry) {
- return entry.fID;
- }
-
- void addBlob(sk_sp<GrTextBlob> blob) {
- SkASSERT(blob);
- SkASSERT(GrTextBlob::GetKey(*blob).fUniqueID == fID);
- SkASSERT(!this->find(GrTextBlob::GetKey(*blob)));
-
- fBlobs.emplace_back(std::move(blob));
- }
-
- void removeBlob(GrTextBlob* blob) {
- SkASSERT(blob);
- SkASSERT(GrTextBlob::GetKey(*blob).fUniqueID == fID);
-
- auto index = this->findBlobIndex(GrTextBlob::GetKey(*blob));
- SkASSERT(index >= 0);
-
- fBlobs.removeShuffle(index);
- }
-
- sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) const {
- auto index = this->findBlobIndex(key);
- return index < 0 ? nullptr : fBlobs[index];
- }
-
- int findBlobIndex(const GrTextBlob::Key& key) const{
- for (int i = 0; i < fBlobs.count(); ++i) {
- if (GrTextBlob::GetKey(*fBlobs[i]) == key) {
- return i;
- }
- }
- return -1;
- }
-
- uint32_t fID;
+ BlobIDCacheEntry();
+ explicit BlobIDCacheEntry(uint32_t id);
+
+ static uint32_t GetKey(const BlobIDCacheEntry& entry);
+
+ void addBlob(sk_sp<GrTextBlob> blob);
+
+ void removeBlob(GrTextBlob* blob);
+
+ sk_sp<GrTextBlob> find(const GrTextBlob::Key& key) const;
+
+ int findBlobIndex(const GrTextBlob::Key& key) const;
+
+ uint32_t fID;
// Current clients don't generate multiple GrAtlasTextBlobs per SkTextBlob, so an array w/
// linear search is acceptable. If usage changes, we should re-evaluate this structure.
SkSTArray<1, sk_sp<GrTextBlob>> fBlobs;
};
- void add(sk_sp<GrTextBlob> blob) {
- auto id = GrTextBlob::GetKey(*blob).fUniqueID;
- auto* idEntry = fBlobIDCache.find(id);
- if (!idEntry) {
- idEntry = fBlobIDCache.set(id, BlobIDCacheEntry(id));
- }
-
- // Safe to retain a raw ptr temporarily here, because the cache will hold a ref.
- GrTextBlob* rawBlobPtr = blob.get();
- fBlobList.addToHead(rawBlobPtr);
- fCurrentSize += blob->size();
- idEntry->addBlob(std::move(blob));
+ void internalPurgeStaleBlobs();
- this->checkPurge(rawBlobPtr);
- }
+ void internalAdd(sk_sp<GrTextBlob> blob);
+ void internalRemove(GrTextBlob* blob);
- void checkPurge(GrTextBlob* blob = nullptr);
+ void internalCheckPurge(GrTextBlob* blob = nullptr);
- static const int kMinGrowthSize = 1 << 16;
static const int kDefaultBudget = 1 << 22;
- BitmapBlobList fBlobList;
+
+ TextBlobList fBlobList;
SkTHashMap<uint32_t, BlobIDCacheEntry> fBlobIDCache;
- PFOverBudgetCB fCallback;
- void* fData;
+ PurgeMore fPurgeMore;
size_t fSizeBudget;
size_t fCurrentSize{0};
- uint32_t fUniqueID; // unique id to use for messaging
+
+ // In practice 'messageBusID' is always the unique ID of the owning GrContext
+ uint32_t fMessageBusID;
SkMessageBus<PurgeBlobMessage>::Inbox fPurgeBlobInbox;
};
diff --git a/chromium/third_party/skia/src/gpu/text/GrTextContext.cpp b/chromium/third_party/skia/src/gpu/text/GrTextContext.cpp
deleted file mode 100644
index 59a3d46179f..00000000000
--- a/chromium/third_party/skia/src/gpu/text/GrTextContext.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "src/gpu/text/GrTextContext.h"
-
-#include "include/core/SkGraphics.h"
-#include "include/gpu/GrContext.h"
-#include "include/private/SkTo.h"
-#include "src/core/SkDistanceFieldGen.h"
-#include "src/core/SkDraw.h"
-#include "src/core/SkDrawProcs.h"
-#include "src/core/SkGlyphRun.h"
-#include "src/core/SkMaskFilterBase.h"
-#include "src/core/SkPaintPriv.h"
-#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrRecordingContextPriv.h"
-#include "src/gpu/SkGr.h"
-#include "src/gpu/ops/GrMeshDrawOp.h"
-#include "src/gpu/text/GrSDFMaskFilter.h"
-#include "src/gpu/text/GrTextBlobCache.h"
-
-// DF sizes and thresholds for usage of the small and medium sizes. For example, above
-// kSmallDFFontLimit we will use the medium size. The large size is used up until the size at
-// which we switch over to drawing as paths as controlled by Options.
-static const int kSmallDFFontSize = 32;
-static const int kSmallDFFontLimit = 32;
-static const int kMediumDFFontSize = 72;
-static const int kMediumDFFontLimit = 72;
-static const int kLargeDFFontSize = 162;
-#ifdef SK_BUILD_FOR_MAC
-static const int kLargeDFFontLimit = 162;
-static const int kExtraLargeDFFontSize = 256;
-#endif
-
-static const int kDefaultMinDistanceFieldFontSize = 18;
-#if defined(SK_BUILD_FOR_ANDROID)
-static const int kDefaultMaxDistanceFieldFontSize = 384;
-#elif defined(SK_BUILD_FOR_MAC)
-static const int kDefaultMaxDistanceFieldFontSize = kExtraLargeDFFontSize;
-#else
-static const int kDefaultMaxDistanceFieldFontSize = 2 * kLargeDFFontSize;
-#endif
-
-GrTextContext::GrTextContext(const Options& options) : fOptions(options) {
- SanitizeOptions(&fOptions);
-}
-
-std::unique_ptr<GrTextContext> GrTextContext::Make(const Options& options) {
- return std::unique_ptr<GrTextContext>(new GrTextContext(options));
-}
-
-SkColor GrTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd) {
- SkColor canonicalColor = SkPaintPriv::ComputeLuminanceColor(paint);
- if (lcd) {
- // This is the correct computation, but there are tons of cases where LCD can be overridden.
- // For now we just regenerate if any run in a textblob has LCD.
- // TODO figure out where all of these overrides are and see if we can incorporate that logic
- // at a higher level *OR* use sRGB
- SkASSERT(false);
- //canonicalColor = SkMaskGamma::CanonicalColor(canonicalColor);
- } else {
- // A8, though can have mixed BMP text but it shouldn't matter because BMP text won't have
- // gamma corrected masks anyways, nor color
- U8CPU lum = SkComputeLuminance(SkColorGetR(canonicalColor),
- SkColorGetG(canonicalColor),
- SkColorGetB(canonicalColor));
- // reduce to our finite number of bits
- canonicalColor = SkMaskGamma::CanonicalColor(SkColorSetRGB(lum, lum, lum));
- }
- return canonicalColor;
-}
-
-SkScalerContextFlags GrTextContext::ComputeScalerContextFlags(const GrColorInfo& colorInfo) {
- // If we're doing linear blending, then we can disable the gamma hacks.
- // Otherwise, leave them on. In either case, we still want the contrast boost:
- // TODO: Can we be even smarter about mask gamma based on the dest transfer function?
- if (colorInfo.isLinearlyBlended()) {
- return SkScalerContextFlags::kBoostContrast;
- } else {
- return SkScalerContextFlags::kFakeGammaAndBoostContrast;
- }
-}
-
-void GrTextContext::SanitizeOptions(Options* options) {
- if (options->fMaxDistanceFieldFontSize < 0.f) {
- options->fMaxDistanceFieldFontSize = kDefaultMaxDistanceFieldFontSize;
- }
- if (options->fMinDistanceFieldFontSize < 0.f) {
- options->fMinDistanceFieldFontSize = kDefaultMinDistanceFieldFontSize;
- }
-}
-
-bool GrTextContext::CanDrawAsDistanceFields(const SkPaint& paint, const SkFont& font,
- const SkMatrix& viewMatrix,
- const SkSurfaceProps& props,
- bool contextSupportsDistanceFieldText,
- const Options& options) {
- // mask filters modify alpha, which doesn't translate well to distance
- if (paint.getMaskFilter() || !contextSupportsDistanceFieldText) {
- return false;
- }
-
- // TODO: add some stroking support
- if (paint.getStyle() != SkPaint::kFill_Style) {
- return false;
- }
-
- if (viewMatrix.hasPerspective()) {
- if (!options.fDistanceFieldVerticesAlwaysHaveW) {
- return false;
- }
- } else {
- SkScalar maxScale = viewMatrix.getMaxScale();
- SkScalar scaledTextSize = maxScale * font.getSize();
- // Hinted text looks far better at small resolutions
- // Scaling up beyond 2x yields undesireable artifacts
- if (scaledTextSize < options.fMinDistanceFieldFontSize ||
- scaledTextSize > options.fMaxDistanceFieldFontSize) {
- return false;
- }
-
- bool useDFT = props.isUseDeviceIndependentFonts();
-#if SK_FORCE_DISTANCE_FIELD_TEXT
- useDFT = true;
-#endif
-
- if (!useDFT && scaledTextSize < kLargeDFFontSize) {
- return false;
- }
- }
-
- return true;
-}
-
-SkScalar scaled_text_size(const SkScalar textSize, const SkMatrix& viewMatrix) {
- SkScalar scaledTextSize = textSize;
-
- if (viewMatrix.hasPerspective()) {
- // for perspective, we simply force to the medium size
- // TODO: compute a size based on approximate screen area
- scaledTextSize = kMediumDFFontLimit;
- } else {
- SkScalar maxScale = viewMatrix.getMaxScale();
- // if we have non-unity scale, we need to choose our base text size
- // based on the SkPaint's text size multiplied by the max scale factor
- // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)?
- if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) {
- scaledTextSize *= maxScale;
- }
- }
-
- return scaledTextSize;
-}
-
-SkFont GrTextContext::InitDistanceFieldFont(const SkFont& font,
- const SkMatrix& viewMatrix,
- const Options& options,
- SkScalar* textRatio) {
- SkScalar textSize = font.getSize();
- SkScalar scaledTextSize = scaled_text_size(textSize, viewMatrix);
-
- SkFont dfFont{font};
-
- if (scaledTextSize <= kSmallDFFontLimit) {
- *textRatio = textSize / kSmallDFFontSize;
- dfFont.setSize(SkIntToScalar(kSmallDFFontSize));
- } else if (scaledTextSize <= kMediumDFFontLimit) {
- *textRatio = textSize / kMediumDFFontSize;
- dfFont.setSize(SkIntToScalar(kMediumDFFontSize));
-#ifdef SK_BUILD_FOR_MAC
- } else if (scaledTextSize <= kLargeDFFontLimit) {
- *textRatio = textSize / kLargeDFFontSize;
- dfFont.setSize(SkIntToScalar(kLargeDFFontSize));
- } else {
- *textRatio = textSize / kExtraLargeDFFontSize;
- dfFont.setSize(SkIntToScalar(kExtraLargeDFFontSize));
- }
-#else
- } else {
- *textRatio = textSize / kLargeDFFontSize;
- dfFont.setSize(SkIntToScalar(kLargeDFFontSize));
- }
-#endif
-
- dfFont.setEdging(SkFont::Edging::kAntiAlias);
- dfFont.setForceAutoHinting(false);
- dfFont.setHinting(SkFontHinting::kNormal);
-
- // The sub-pixel position will always happen when transforming to the screen.
- dfFont.setSubpixel(false);
- return dfFont;
-}
-
-std::pair<SkScalar, SkScalar> GrTextContext::InitDistanceFieldMinMaxScale(
- SkScalar textSize,
- const SkMatrix& viewMatrix,
- const GrTextContext::Options& options) {
-
- SkScalar scaledTextSize = scaled_text_size(textSize, viewMatrix);
-
- // We have three sizes of distance field text, and within each size 'bucket' there is a floor
- // and ceiling. A scale outside of this range would require regenerating the distance fields
- SkScalar dfMaskScaleFloor;
- SkScalar dfMaskScaleCeil;
- if (scaledTextSize <= kSmallDFFontLimit) {
- dfMaskScaleFloor = options.fMinDistanceFieldFontSize;
- dfMaskScaleCeil = kSmallDFFontLimit;
- } else if (scaledTextSize <= kMediumDFFontLimit) {
- dfMaskScaleFloor = kSmallDFFontLimit;
- dfMaskScaleCeil = kMediumDFFontLimit;
- } else {
- dfMaskScaleFloor = kMediumDFFontLimit;
- dfMaskScaleCeil = options.fMaxDistanceFieldFontSize;
- }
-
- // Because there can be multiple runs in the blob, we want the overall maxMinScale, and
- // minMaxScale to make regeneration decisions. Specifically, we want the maximum minimum scale
- // we can tolerate before we'd drop to a lower mip size, and the minimum maximum scale we can
- // tolerate before we'd have to move to a large mip size. When we actually test these values
- // we look at the delta in scale between the new viewmatrix and the old viewmatrix, and test
- // against these values to decide if we can reuse or not(ie, will a given scale change our mip
- // level)
- SkASSERT(dfMaskScaleFloor <= scaledTextSize && scaledTextSize <= dfMaskScaleCeil);
-
- return std::make_pair(dfMaskScaleFloor / scaledTextSize, dfMaskScaleCeil / scaledTextSize);
-}
-
-SkPaint GrTextContext::InitDistanceFieldPaint(const SkPaint& paint) {
- SkPaint dfPaint{paint};
- dfPaint.setMaskFilter(GrSDFMaskFilter::Make());
- return dfPaint;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#if GR_TEST_UTILS
-
-#include "src/gpu/GrRenderTargetContext.h"
-
-GR_DRAW_OP_TEST_DEFINE(GrAtlasTextOp) {
- static uint32_t gContextID = SK_InvalidGenID;
- static std::unique_ptr<GrTextContext> gTextContext;
- static SkSurfaceProps gSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType);
-
- if (context->priv().contextID() != gContextID) {
- gContextID = context->priv().contextID();
- gTextContext = GrTextContext::Make(GrTextContext::Options());
- }
-
- // Setup dummy SkPaint / GrPaint / GrRenderTargetContext
- auto rtc = GrRenderTargetContext::Make(
- context, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kApprox, {1024, 1024});
-
- SkSimpleMatrixProvider matrixProvider(GrTest::TestMatrixInvertible(random));
-
- SkPaint skPaint;
- skPaint.setColor(random->nextU());
-
- SkFont font;
- if (random->nextBool()) {
- font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
- } else {
- font.setEdging(random->nextBool() ? SkFont::Edging::kAntiAlias : SkFont::Edging::kAlias);
- }
- font.setSubpixel(random->nextBool());
-
- const char* text = "The quick brown fox jumps over the lazy dog.";
-
- // create some random x/y offsets, including negative offsets
- static const int kMaxTrans = 1024;
- int xPos = (random->nextU() % 2) * 2 - 1;
- int yPos = (random->nextU() % 2) * 2 - 1;
- int xInt = (random->nextU() % kMaxTrans) * xPos;
- int yInt = (random->nextU() % kMaxTrans) * yPos;
-
- return gTextContext->createOp_TestingOnly(context, gTextContext.get(), rtc.get(), skPaint, font,
- matrixProvider, text, xInt, yInt);
-}
-
-#endif
diff --git a/chromium/third_party/skia/src/gpu/text/GrTextContext.h b/chromium/third_party/skia/src/gpu/text/GrTextContext.h
deleted file mode 100644
index 4b902393e29..00000000000
--- a/chromium/third_party/skia/src/gpu/text/GrTextContext.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrTextContext_DEFINED
-#define GrTextContext_DEFINED
-
-#include "src/core/SkGlyphRun.h"
-#include "src/gpu/GrGeometryProcessor.h"
-#include "src/gpu/text/GrTextTarget.h"
-
-#if GR_TEST_UTILS
-#include "src/gpu/GrDrawOpTest.h"
-#endif
-
-class GrDrawOp;
-class GrRecordingContext;
-class GrRenderTargetContext;
-class GrTextBlobCache;
-class SkGlyph;
-class GrTextBlob;
-
-/*
- * Renders text using some kind of an atlas, ie BitmapText or DistanceField text
- */
-class GrTextContext {
-public:
- struct Options {
- /**
- * Below this size (in device space) distance field text will not be used. Negative means
- * use a default value.
- */
- SkScalar fMinDistanceFieldFontSize = -1.f;
- /**
- * Above this size (in device space) distance field text will not be used and glyphs will
- * be rendered from outline as individual paths. Negative means use a default value.
- */
- SkScalar fMaxDistanceFieldFontSize = -1.f;
- /** Forces all distance field vertices to use 3 components, not just when in perspective. */
- bool fDistanceFieldVerticesAlwaysHaveW = false;
- };
-
- static std::unique_ptr<GrTextContext> Make(const Options& options);
-
- void drawGlyphRunList(GrRecordingContext*,
- GrTextTarget*,
- const GrClip&,
- const SkMatrixProvider&,
- const SkSurfaceProps&,
- const SkGlyphRunList&) const;
-
-#if GR_TEST_UTILS
- std::unique_ptr<GrDrawOp> createOp_TestingOnly(GrRecordingContext*,
- GrTextContext*,
- GrRenderTargetContext*,
- const SkPaint&,
- const SkFont&,
- const SkMatrixProvider&,
- const char* text,
- int x,
- int y);
-#endif
-
- static void SanitizeOptions(Options* options);
- static bool CanDrawAsDistanceFields(const SkPaint&, const SkFont&, const SkMatrix& viewMatrix,
- const SkSurfaceProps& props,
- bool contextSupportsDistanceFieldText,
- const Options& options);
-
- static SkFont InitDistanceFieldFont(const SkFont& font,
- const SkMatrix& viewMatrix,
- const Options& options,
- SkScalar* textRatio);
-
- static SkPaint InitDistanceFieldPaint(const SkPaint& paint);
-
- static std::pair<SkScalar, SkScalar> InitDistanceFieldMinMaxScale(SkScalar textSize,
- const SkMatrix& viewMatrix,
- const Options& options);
-
-private:
- GrTextContext(const Options& options);
-
- // sets up the descriptor on the blob and returns a detached cache. Client must attach
- static SkColor ComputeCanonicalColor(const SkPaint&, bool lcd);
- // Determines if we need to use fake gamma (and contrast boost):
- static SkScalerContextFlags ComputeScalerContextFlags(const GrColorInfo&);
-
- Options fOptions;
-
-#if GR_TEST_UTILS
- static const SkScalerContextFlags kTextBlobOpScalerContextFlags =
- SkScalerContextFlags::kFakeGammaAndBoostContrast;
- GR_DRAW_OP_TEST_FRIEND(GrAtlasTextOp);
-#endif
-};
-
-#endif // GrTextContext_DEFINED
diff --git a/chromium/third_party/skia/src/gpu/text/GrTextTarget.h b/chromium/third_party/skia/src/gpu/text/GrTextTarget.h
index 9f88eb72044..7a834ccc5f6 100644
--- a/chromium/third_party/skia/src/gpu/text/GrTextTarget.h
+++ b/chromium/third_party/skia/src/gpu/text/GrTextTarget.h
@@ -31,9 +31,9 @@ public:
const GrColorInfo& colorInfo() const { return fColorInfo; }
- virtual void addDrawOp(const GrClip&, std::unique_ptr<GrAtlasTextOp> op) = 0;
+ virtual void addDrawOp(const GrClip*, std::unique_ptr<GrAtlasTextOp> op) = 0;
- virtual void drawShape(const GrClip&,
+ virtual void drawShape(const GrClip*,
const SkPaint&,
const SkMatrixProvider&,
const GrStyledShape&) = 0;
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.cpp
index a1339537d6c..03467a24af2 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.cpp
@@ -98,8 +98,8 @@ GrVkAMDMemoryAllocator::~GrVkAMDMemoryAllocator() {
fAllocator = VK_NULL_HANDLE;
}
-bool GrVkAMDMemoryAllocator::allocateMemoryForImage(VkImage image, AllocationPropertyFlags flags,
- GrVkBackendMemory* backendMemory) {
+VkResult GrVkAMDMemoryAllocator::allocateImageMemory(VkImage image, AllocationPropertyFlags flags,
+ GrVkBackendMemory* backendMemory) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
VmaAllocationCreateInfo info;
info.flags = 0;
@@ -124,16 +124,15 @@ bool GrVkAMDMemoryAllocator::allocateMemoryForImage(VkImage image, AllocationPro
VmaAllocation allocation;
VkResult result = vmaAllocateMemoryForImage(fAllocator, image, &info, &allocation, nullptr);
- if (VK_SUCCESS != result) {
- return false;
+ if (VK_SUCCESS == result) {
+ *backendMemory = (GrVkBackendMemory)allocation;
}
- *backendMemory = (GrVkBackendMemory)allocation;
- return true;
+ return result;
}
-bool GrVkAMDMemoryAllocator::allocateMemoryForBuffer(VkBuffer buffer, BufferUsage usage,
- AllocationPropertyFlags flags,
- GrVkBackendMemory* backendMemory) {
+VkResult GrVkAMDMemoryAllocator::allocateBufferMemory(VkBuffer buffer, BufferUsage usage,
+ AllocationPropertyFlags flags,
+ GrVkBackendMemory* backendMemory) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
VmaAllocationCreateInfo info;
info.flags = 0;
@@ -187,12 +186,11 @@ bool GrVkAMDMemoryAllocator::allocateMemoryForBuffer(VkBuffer buffer, BufferUsag
result = vmaAllocateMemoryForBuffer(fAllocator, buffer, &info, &allocation, nullptr);
}
}
- if (VK_SUCCESS != result) {
- return false;
+ if (VK_SUCCESS == result) {
+ *backendMemory = (GrVkBackendMemory)allocation;
}
- *backendMemory = (GrVkBackendMemory)allocation;
- return true;
+ return result;
}
void GrVkAMDMemoryAllocator::freeMemory(const GrVkBackendMemory& memoryHandle) {
@@ -225,12 +223,10 @@ void GrVkAMDMemoryAllocator::getAllocInfo(const GrVkBackendMemory& memoryHandle,
alloc->fBackendMemory = memoryHandle;
}
-void* GrVkAMDMemoryAllocator::mapMemory(const GrVkBackendMemory& memoryHandle) {
+VkResult GrVkAMDMemoryAllocator::mapMemory(const GrVkBackendMemory& memoryHandle, void** data) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
- void* mapPtr;
- vmaMapMemory(fAllocator, allocation, &mapPtr);
- return mapPtr;
+ return vmaMapMemory(fAllocator, allocation, data);
}
void GrVkAMDMemoryAllocator::unmapMemory(const GrVkBackendMemory& memoryHandle) {
@@ -239,18 +235,18 @@ void GrVkAMDMemoryAllocator::unmapMemory(const GrVkBackendMemory& memoryHandle)
vmaUnmapMemory(fAllocator, allocation);
}
-void GrVkAMDMemoryAllocator::flushMappedMemory(const GrVkBackendMemory& memoryHandle,
- VkDeviceSize offset, VkDeviceSize size) {
+VkResult GrVkAMDMemoryAllocator::flushMemory(const GrVkBackendMemory& memoryHandle,
+ VkDeviceSize offset, VkDeviceSize size) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
- vmaFlushAllocation(fAllocator, allocation, offset, size);
+ return vmaFlushAllocation(fAllocator, allocation, offset, size);
}
-void GrVkAMDMemoryAllocator::invalidateMappedMemory(const GrVkBackendMemory& memoryHandle,
- VkDeviceSize offset, VkDeviceSize size) {
+VkResult GrVkAMDMemoryAllocator::invalidateMemory(const GrVkBackendMemory& memoryHandle,
+ VkDeviceSize offset, VkDeviceSize size) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
- vmaFlushAllocation(fAllocator, allocation, offset, size);
+ return vmaFlushAllocation(fAllocator, allocation, offset, size);
}
uint64_t GrVkAMDMemoryAllocator::totalUsedMemory() const {
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.h b/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.h
index 5957cd5944f..82a3e31c29c 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkAMDMemoryAllocator.h
@@ -39,23 +39,22 @@ public:
~GrVkAMDMemoryAllocator() override;
- bool allocateMemoryForImage(VkImage image, AllocationPropertyFlags flags,
- GrVkBackendMemory*) override;
+ VkResult allocateImageMemory(VkImage image, AllocationPropertyFlags flags,
+ GrVkBackendMemory*) override;
- bool allocateMemoryForBuffer(VkBuffer buffer, BufferUsage usage,
- AllocationPropertyFlags flags, GrVkBackendMemory*) override;
+ VkResult allocateBufferMemory(VkBuffer buffer, BufferUsage usage,
+ AllocationPropertyFlags flags, GrVkBackendMemory*) override;
void freeMemory(const GrVkBackendMemory&) override;
void getAllocInfo(const GrVkBackendMemory&, GrVkAlloc*) const override;
- void* mapMemory(const GrVkBackendMemory&) override;
+ VkResult mapMemory(const GrVkBackendMemory&, void** data) override;
void unmapMemory(const GrVkBackendMemory&) override;
- void flushMappedMemory(const GrVkBackendMemory&, VkDeviceSize offset,
- VkDeviceSize size) override;
- void invalidateMappedMemory(const GrVkBackendMemory&, VkDeviceSize offset,
- VkDeviceSize size) override;
+ VkResult flushMemory(const GrVkBackendMemory&, VkDeviceSize offset, VkDeviceSize size) override;
+ VkResult invalidateMemory(const GrVkBackendMemory&, VkDeviceSize offset,
+ VkDeviceSize size) override;
uint64_t totalUsedMemory() const override;
uint64_t totalAllocatedMemory() const override;
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkCaps.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkCaps.cpp
index eacce98fc74..5dc79fbd250 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkCaps.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkCaps.cpp
@@ -9,6 +9,7 @@
#include "include/gpu/vk/GrVkBackendContext.h"
#include "include/gpu/vk/GrVkExtensions.h"
#include "src/core/SkCompressedDataUtils.h"
+#include "src/gpu/GrBackendUtils.h"
#include "src/gpu/GrProgramDesc.h"
#include "src/gpu/GrRenderTarget.h"
#include "src/gpu/GrRenderTargetProxy.h"
@@ -516,14 +517,20 @@ void GrVkCaps::initGrCaps(const GrVkInterface* vkInterface,
static const uint32_t kMaxVertexAttributes = 64;
fMaxVertexAttributes = std::min(properties.limits.maxVertexInputAttributes, kMaxVertexAttributes);
+ // GrCaps::fSampleLocationsSupport refers to the ability to *query* the sample locations (not
+ // program them). For now we just set this to true if the device uses standard locations, and
+ // return the standard locations back when queried.
if (properties.limits.standardSampleLocations) {
fSampleLocationsSupport = true;
}
+ // See skbug.com/10346
+#if 0
if (extensions.hasExtension(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME, 1)) {
// We "disable" multisample by colocating all samples at pixel center.
fMultisampleDisableSupport = true;
}
+#endif
if (extensions.hasExtension(VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME, 1)) {
fMixedSamplesSupport = true;
@@ -1318,22 +1325,6 @@ bool GrVkCaps::isFormatSRGB(const GrBackendFormat& format) const {
return format_is_srgb(vkFormat);
}
-SkImage::CompressionType GrVkCaps::compressionType(const GrBackendFormat& format) const {
- VkFormat vkFormat;
- if (!format.asVkFormat(&vkFormat)) {
- return SkImage::CompressionType::kNone;
- }
-
- switch (vkFormat) {
- case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: return SkImage::CompressionType::kETC2_RGB8_UNORM;
- case VK_FORMAT_BC1_RGB_UNORM_BLOCK: return SkImage::CompressionType::kBC1_RGB8_UNORM;
- case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: return SkImage::CompressionType::kBC1_RGBA8_UNORM;
- default: return SkImage::CompressionType::kNone;
- }
-
- SkUNREACHABLE;
-}
-
bool GrVkCaps::isFormatTexturable(const GrBackendFormat& format) const {
VkFormat vkFormat;
if (!format.asVkFormat(&vkFormat)) {
@@ -1531,12 +1522,6 @@ bool GrVkCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
return false;
}
- SkImage::CompressionType compression = GrVkFormatToCompressionType(vkFormat);
- if (compression != SkImage::CompressionType::kNone) {
- return ct == (SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
- : GrColorType::kRGBA_8888);
- }
-
const auto& info = this->getFormatInfo(vkFormat);
for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
if (info.fColorTypeInfos[i].fColorType == ct) {
@@ -1579,7 +1564,7 @@ GrBackendFormat GrVkCaps::getBackendFormatFromCompressionType(
SkUNREACHABLE;
}
-GrSwizzle GrVkCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
+GrSwizzle GrVkCaps::onGetReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
VkFormat vkFormat;
SkAssertResult(format.asVkFormat(&vkFormat));
const auto* ycbcrInfo = format.getVkYcbcrConversionInfo();
@@ -1589,6 +1574,7 @@ GrSwizzle GrVkCaps::getReadSwizzle(const GrBackendFormat& format, GrColorType co
// onAreColorTypeAndFormatCompatible.
return GrSwizzle{"rgba"};
}
+
const auto& info = this->getFormatInfo(vkFormat);
for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
const auto& ctInfo = info.fColorTypeInfos[i];
@@ -1641,7 +1627,7 @@ GrCaps::SupportedRead GrVkCaps::onSupportedReadPixelsColorType(
return {GrColorType::kUnknown, 0};
}
- SkImage::CompressionType compression = GrVkFormatToCompressionType(vkFormat);
+ SkImage::CompressionType compression = GrBackendFormatToCompressionType(srcBackendFormat);
if (compression != SkImage::CompressionType::kNone) {
return { SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
: GrColorType::kRGBA_8888, 0 };
@@ -1716,9 +1702,12 @@ GrProgramDesc GrVkCaps::makeDesc(const GrRenderTarget* rt, const GrProgramInfo&
b.add32(GrVkGpu::kShader_PersistentCacheKeyType);
GrVkRenderTarget* vkRT = (GrVkRenderTarget*) rt;
+
+ bool needsStencil = programInfo.numStencilSamples() || programInfo.isStencilEnabled();
// TODO: support failure in getSimpleRenderPass
- SkASSERT(vkRT->getSimpleRenderPass());
- vkRT->getSimpleRenderPass()->genKey(&b);
+ const GrVkRenderPass* rp = vkRT->getSimpleRenderPass(needsStencil);
+ SkASSERT(rp);
+ rp->genKey(&b);
GrStencilSettings stencil = programInfo.nonGLStencilSettings();
stencil.genKey(&b, true);
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkCaps.h b/chromium/third_party/skia/src/gpu/vk/GrVkCaps.h
index f136817b2ff..57787c2db42 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkCaps.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkCaps.h
@@ -33,7 +33,6 @@ public:
const GrVkExtensions& extensions, GrProtected isProtected = GrProtected::kNo);
bool isFormatSRGB(const GrBackendFormat&) const override;
- SkImage::CompressionType compressionType(const GrBackendFormat&) const override;
bool isFormatTexturable(const GrBackendFormat&) const override;
bool isVkFormatTexturable(VkFormat) const;
@@ -189,7 +188,6 @@ public:
return fColorTypeToFormatTable[idx];
}
- GrSwizzle getReadSwizzle(const GrBackendFormat&, GrColorType) const override;
GrSwizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override;
uint64_t computeFormatKey(const GrBackendFormat&) const override;
@@ -243,6 +241,9 @@ private:
SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&,
GrColorType) const override;
+ GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override;
+
+
// ColorTypeInfo for a specific format
struct ColorTypeInfo {
GrColorType fColorType = GrColorType::kUnknown;
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkCommandBuffer.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkCommandBuffer.cpp
index e23459b496a..c1dfe13fc52 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkCommandBuffer.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkCommandBuffer.cpp
@@ -308,6 +308,7 @@ void GrVkCommandBuffer::drawIndirect(const GrVkGpu* gpu,
SkASSERT(fActiveRenderPass);
SkASSERT(!indirectBuffer->isCpuBuffer());
this->addingWork(gpu);
+ this->addResource(indirectBuffer->resource());
GR_VK_CALL(gpu->vkInterface(), CmdDrawIndirect(fCmdBuffer,
indirectBuffer->buffer(),
offset,
@@ -324,6 +325,7 @@ void GrVkCommandBuffer::drawIndexedIndirect(const GrVkGpu* gpu,
SkASSERT(fActiveRenderPass);
SkASSERT(!indirectBuffer->isCpuBuffer());
this->addingWork(gpu);
+ this->addResource(indirectBuffer->resource());
GR_VK_CALL(gpu->vkInterface(), CmdDrawIndexedIndirect(fCmdBuffer,
indirectBuffer->buffer(),
offset,
@@ -472,7 +474,7 @@ bool GrVkPrimaryCommandBuffer::beginRenderPass(GrVkGpu* gpu,
SkASSERT(!fActiveRenderPass);
SkASSERT(renderPass->isCompatible(*target));
- const GrVkFramebuffer* framebuffer = target->getFramebuffer();
+ const GrVkFramebuffer* framebuffer = target->getFramebuffer(renderPass->hasStencilAttachment());
if (!framebuffer) {
return false;
}
@@ -499,7 +501,7 @@ bool GrVkPrimaryCommandBuffer::beginRenderPass(GrVkGpu* gpu,
GR_VK_CALL(gpu->vkInterface(), CmdBeginRenderPass(fCmdBuffer, &beginInfo, contents));
fActiveRenderPass = renderPass;
this->addResource(renderPass);
- target->addResources(*this);
+ target->addResources(*this, renderPass->hasStencilAttachment());
return true;
}
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkGpu.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkGpu.cpp
index f2ab8104ac8..6bec1c977e9 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkGpu.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkGpu.cpp
@@ -14,6 +14,7 @@
#include "src/core/SkCompressedDataUtils.h"
#include "src/core/SkConvertPixels.h"
#include "src/core/SkMipMap.h"
+#include "src/gpu/GrBackendUtils.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrDataUtils.h"
#include "src/gpu/GrGeometryProcessor.h"
@@ -241,7 +242,6 @@ void GrVkGpu::destroyResources() {
fMainCmdPool->getPrimaryCommandBuffer()->end(this);
fMainCmdPool->close();
}
- SkASSERT(!fTempCmdPool);
// wait for all commands to finish
VkResult res = VK_CALL(QueueWaitIdle(fQueue));
@@ -286,9 +286,11 @@ void GrVkGpu::destroyResources() {
GrVkGpu::~GrVkGpu() {
if (!fDisconnected) {
this->destroyResources();
- fMemoryAllocator.reset();
}
delete fCompiler;
+ // We don't delete the memory allocator until the very end of the GrVkGpu lifetime so that
+ // clients can continue to delete backend textures even after a context has been abandoned.
+ fMemoryAllocator.reset();
}
@@ -296,12 +298,10 @@ void GrVkGpu::disconnect(DisconnectType type) {
INHERITED::disconnect(type);
if (!fDisconnected) {
this->destroyResources();
- fMemoryAllocator.reset();
fSemaphoresToWaitOn.reset();
fSemaphoresToSignal.reset();
fMainCmdBuffer = nullptr;
- SkASSERT(!fTempCmdBuffer);
fDisconnected = true;
}
}
@@ -309,7 +309,8 @@ void GrVkGpu::disconnect(DisconnectType type) {
///////////////////////////////////////////////////////////////////////////////
GrOpsRenderPass* GrVkGpu::getOpsRenderPass(
- GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
+ GrRenderTarget* rt, GrStencilAttachment* stencil,
+ GrSurfaceOrigin origin, const SkIRect& bounds,
const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
@@ -317,49 +318,18 @@ GrOpsRenderPass* GrVkGpu::getOpsRenderPass(
fCachedOpsRenderPass.reset(new GrVkOpsRenderPass(this));
}
- if (!fCachedOpsRenderPass->set(rt, origin, bounds, colorInfo, stencilInfo, sampledProxies)) {
+ if (!fCachedOpsRenderPass->set(rt, stencil, origin, bounds,
+ colorInfo, stencilInfo, sampledProxies)) {
return nullptr;
}
return fCachedOpsRenderPass.get();
}
-GrVkPrimaryCommandBuffer* GrVkGpu::getTempCommandBuffer() {
- SkASSERT(!fTempCmdPool && !fTempCmdBuffer);
- fTempCmdPool = fResourceProvider.findOrCreateCommandPool();
- if (!fTempCmdPool) {
- return nullptr;
- }
- fTempCmdBuffer = fTempCmdPool->getPrimaryCommandBuffer();
- SkASSERT(fTempCmdBuffer);
- fTempCmdBuffer->begin(this);
- return fTempCmdBuffer;
-}
-
-bool GrVkGpu::submitTempCommandBuffer(SyncQueue sync, sk_sp<GrRefCntedCallback> finishedCallback) {
- SkASSERT(fTempCmdBuffer);
-
- fTempCmdBuffer->end(this);
- fTempCmdPool->close();
-
- SkASSERT(fMainCmdBuffer->validateNoSharedImageResources(fTempCmdBuffer));
-
- fTempCmdBuffer->addFinishedProc(std::move(finishedCallback));
-
- SkTArray<GrVkSemaphore::Resource*, false> fEmptySemaphores;
- bool didSubmit = fTempCmdBuffer->submitToQueue(this, fQueue, fEmptySemaphores,
- fEmptySemaphores);
- if (didSubmit && sync == kForce_SyncQueue) {
- fTempCmdBuffer->forceSync(this);
- }
- fTempCmdPool->unref();
- fTempCmdPool = nullptr;
- fTempCmdBuffer = nullptr;
- return didSubmit;
-}
-
bool GrVkGpu::submitCommandBuffer(SyncQueue sync) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
- SkASSERT(this->currentCommandBuffer());
+ if (!this->currentCommandBuffer()) {
+ return false;
+ }
SkASSERT(!fCachedOpsRenderPass || !fCachedOpsRenderPass->isActive());
if (!this->currentCommandBuffer()->hasWork() && kForce_SyncQueue != sync &&
@@ -510,6 +480,9 @@ bool GrVkGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt
GrColorType surfaceColorType, GrColorType bufferColorType,
GrGpuBuffer* transferBuffer, size_t bufferOffset,
size_t rowBytes) {
+ if (!this->currentCommandBuffer()) {
+ return false;
+ }
if (surfaceColorType != bufferColorType) {
return false;
}
@@ -574,6 +547,9 @@ bool GrVkGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int widt
bool GrVkGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
GrColorType surfaceColorType, GrColorType bufferColorType,
GrGpuBuffer* transferBuffer, size_t offset) {
+ if (!this->currentCommandBuffer()) {
+ return false;
+ }
SkASSERT(surface);
SkASSERT(transferBuffer);
if (fProtectedContext == GrProtected::kYes) {
@@ -635,6 +611,10 @@ bool GrVkGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int wi
void GrVkGpu::resolveImage(GrSurface* dst, GrVkRenderTarget* src, const SkIRect& srcRect,
const SkIPoint& dstPoint) {
+ if (!this->currentCommandBuffer()) {
+ return;
+ }
+
SkASSERT(dst);
SkASSERT(src && src->numSamples() > 1 && src->msaaImage());
@@ -741,10 +721,9 @@ bool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex, int left, int top, int width
// 'individualMipOffsets' is filled in as a side-effect.
static size_t fill_in_regions(GrVkCaps* vkCaps, SkTArray<VkBufferImageCopy>* regions,
SkTArray<size_t>* individualMipOffsets,
+ SkImage::CompressionType compression,
VkFormat vkFormat, SkISize dimensions, GrMipMapped mipMapped,
VkDeviceSize bufferOffset) {
- SkImage::CompressionType compression = GrVkFormatToCompressionType(vkFormat);
-
int numMipLevels = 1;
if (mipMapped == GrMipMapped::kYes) {
numMipLevels = SkMipMap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
@@ -788,6 +767,10 @@ static size_t fill_in_regions(GrVkCaps* vkCaps, SkTArray<VkBufferImageCopy>* reg
bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, int left, int top, int width, int height,
GrColorType dataColorType, const GrMipLevel texels[],
int mipLevelCount) {
+ if (!this->currentCommandBuffer()) {
+ return false;
+ }
+
SkASSERT(!tex->isLinearTiled());
// The assumption is either that we have no mipmaps, or that our rect is the entire texture
SkASSERT(1 == mipLevelCount ||
@@ -972,9 +955,13 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, int left, int top, int widt
// It's probably possible to roll this into uploadTexDataOptimal,
// but for now it's easier to maintain as a separate entity.
-bool GrVkGpu::uploadTexDataCompressed(GrVkTexture* uploadTexture, VkFormat vkFormat,
+bool GrVkGpu::uploadTexDataCompressed(GrVkTexture* uploadTexture,
+ SkImage::CompressionType compression, VkFormat vkFormat,
SkISize dimensions, GrMipMapped mipMapped,
const void* data, size_t dataSize) {
+ if (!this->currentCommandBuffer()) {
+ return false;
+ }
SkASSERT(data);
SkASSERT(!uploadTexture->isLinearTiled());
// For now the assumption is that our rect is the entire texture.
@@ -1009,9 +996,9 @@ bool GrVkGpu::uploadTexDataCompressed(GrVkTexture* uploadTexture, VkFormat vkFor
SkTArray<VkBufferImageCopy> regions;
SkTArray<size_t> individualMipOffsets;
SkDEBUGCODE(size_t combinedBufferSize =) fill_in_regions(fVkCaps.get(), &regions,
- &individualMipOffsets,
- vkFormat, dimensions,
- mipMapped, bufferOffset);
+ &individualMipOffsets, compression,
+ vkFormat, dimensions, mipMapped,
+ bufferOffset);
SkASSERT(dataSize == combinedBufferSize);
// Change layout of our target so it can be copied to
@@ -1090,6 +1077,9 @@ sk_sp<GrTexture> GrVkGpu::onCreateTexture(SkISize dimensions,
}
if (levelClearMask) {
+ if (!this->currentCommandBuffer()) {
+ return nullptr;
+ }
SkSTArray<1, VkImageSubresourceRange> ranges;
bool inRange = false;
for (uint32_t i = 0; i < tex->mipLevels(); ++i) {
@@ -1165,7 +1155,8 @@ sk_sp<GrTexture> GrVkGpu::onCreateCompressedTexture(SkISize dimensions,
return nullptr;
}
- if (!this->uploadTexDataCompressed(tex.get(), pixelFormat, dimensions, mipMapped,
+ SkImage::CompressionType compression = GrBackendFormatToCompressionType(format);
+ if (!this->uploadTexDataCompressed(tex.get(), compression, pixelFormat, dimensions, mipMapped,
data, dataSize)) {
return nullptr;
}
@@ -1177,6 +1168,9 @@ sk_sp<GrTexture> GrVkGpu::onCreateCompressedTexture(SkISize dimensions,
void GrVkGpu::copyBuffer(GrVkBuffer* srcBuffer, GrVkBuffer* dstBuffer, VkDeviceSize srcOffset,
VkDeviceSize dstOffset, VkDeviceSize size) {
+ if (!this->currentCommandBuffer()) {
+ return;
+ }
VkBufferCopy copyRegion;
copyRegion.srcOffset = srcOffset;
copyRegion.dstOffset = dstOffset;
@@ -1186,6 +1180,9 @@ void GrVkGpu::copyBuffer(GrVkBuffer* srcBuffer, GrVkBuffer* dstBuffer, VkDeviceS
bool GrVkGpu::updateBuffer(GrVkBuffer* buffer, const void* src,
VkDeviceSize offset, VkDeviceSize size) {
+ if (!this->currentCommandBuffer()) {
+ return false;
+ }
// Update the buffer
this->currentCommandBuffer()->updateBuffer(this, buffer, offset, size, src);
@@ -1196,7 +1193,8 @@ bool GrVkGpu::updateBuffer(GrVkBuffer* buffer, const void* src,
static bool check_image_info(const GrVkCaps& caps,
const GrVkImageInfo& info,
- bool needsAllocation) {
+ bool needsAllocation,
+ uint32_t graphicsQueueIndex) {
if (VK_NULL_HANDLE == info.fImage) {
return false;
}
@@ -1209,6 +1207,18 @@ static bool check_image_info(const GrVkCaps& caps,
return false;
}
+ if (info.fCurrentQueueFamily != VK_QUEUE_FAMILY_IGNORED &&
+ info.fCurrentQueueFamily != VK_QUEUE_FAMILY_EXTERNAL &&
+ info.fCurrentQueueFamily != VK_QUEUE_FAMILY_FOREIGN_EXT) {
+ if (info.fSharingMode == VK_SHARING_MODE_EXCLUSIVE) {
+ if (info.fCurrentQueueFamily != graphicsQueueIndex) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
if (info.fYcbcrConversionInfo.isValid()) {
if (!caps.supportsYcbcrConversion()) {
return false;
@@ -1254,7 +1264,8 @@ sk_sp<GrTexture> GrVkGpu::onWrapBackendTexture(const GrBackendTexture& backendTe
return nullptr;
}
- if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership)) {
+ if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership,
+ this->queueIndex())) {
return nullptr;
}
@@ -1266,10 +1277,10 @@ sk_sp<GrTexture> GrVkGpu::onWrapBackendTexture(const GrBackendTexture& backendTe
return nullptr;
}
- sk_sp<GrVkImageLayout> layout = backendTex.getGrVkImageLayout();
- SkASSERT(layout);
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = backendTex.getMutableState();
+ SkASSERT(mutableState);
return GrVkTexture::MakeWrappedTexture(this, backendTex.dimensions(), ownership, cacheable,
- ioType, imageInfo, std::move(layout));
+ ioType, imageInfo, std::move(mutableState));
}
sk_sp<GrTexture> GrVkGpu::onWrapCompressedBackendTexture(const GrBackendTexture& beTex,
@@ -1280,7 +1291,8 @@ sk_sp<GrTexture> GrVkGpu::onWrapCompressedBackendTexture(const GrBackendTexture&
return nullptr;
}
- if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership)) {
+ if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership,
+ this->queueIndex())) {
return nullptr;
}
@@ -1292,10 +1304,10 @@ sk_sp<GrTexture> GrVkGpu::onWrapCompressedBackendTexture(const GrBackendTexture&
return nullptr;
}
- sk_sp<GrVkImageLayout> layout = beTex.getGrVkImageLayout();
- SkASSERT(layout);
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = beTex.getMutableState();
+ SkASSERT(mutableState);
return GrVkTexture::MakeWrappedTexture(this, beTex.dimensions(), ownership, cacheable,
- kRead_GrIOType, imageInfo, std::move(layout));
+ kRead_GrIOType, imageInfo, std::move(mutableState));
}
sk_sp<GrTexture> GrVkGpu::onWrapRenderableBackendTexture(const GrBackendTexture& backendTex,
@@ -1307,7 +1319,8 @@ sk_sp<GrTexture> GrVkGpu::onWrapRenderableBackendTexture(const GrBackendTexture&
return nullptr;
}
- if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership)) {
+ if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership,
+ this->queueIndex())) {
return nullptr;
}
@@ -1324,12 +1337,13 @@ sk_sp<GrTexture> GrVkGpu::onWrapRenderableBackendTexture(const GrBackendTexture&
sampleCnt = this->vkCaps().getRenderTargetSampleCount(sampleCnt, imageInfo.fFormat);
- sk_sp<GrVkImageLayout> layout = backendTex.getGrVkImageLayout();
- SkASSERT(layout);
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = backendTex.getMutableState();
+ SkASSERT(mutableState);
return GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(this, backendTex.dimensions(),
sampleCnt, ownership, cacheable,
- imageInfo, std::move(layout));
+ imageInfo,
+ std::move(mutableState));
}
sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
@@ -1346,7 +1360,7 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTa
return nullptr;
}
- if (!check_image_info(this->vkCaps(), info, false)) {
+ if (!check_image_info(this->vkCaps(), info, false, this->queueIndex())) {
return nullptr;
}
@@ -1358,10 +1372,11 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTa
return nullptr;
}
- sk_sp<GrVkImageLayout> layout = backendRT.getGrVkImageLayout();
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = backendRT.getMutableState();
+ SkASSERT(mutableState);
sk_sp<GrVkRenderTarget> tgt = GrVkRenderTarget::MakeWrappedRenderTarget(
- this, backendRT.dimensions(), 1, info, std::move(layout));
+ this, backendRT.dimensions(), 1, info, std::move(mutableState));
// We don't allow the client to supply a premade stencil buffer. We always create one if needed.
SkASSERT(!backendRT.stencilBits());
@@ -1378,7 +1393,7 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendTextureAsRenderTarget(const GrBacken
if (!tex.getVkImageInfo(&imageInfo)) {
return nullptr;
}
- if (!check_image_info(this->vkCaps(), imageInfo, false)) {
+ if (!check_image_info(this->vkCaps(), imageInfo, false, this->queueIndex())) {
return nullptr;
}
@@ -1395,11 +1410,11 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendTextureAsRenderTarget(const GrBacken
return nullptr;
}
- sk_sp<GrVkImageLayout> layout = tex.getGrVkImageLayout();
- SkASSERT(layout);
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = tex.getMutableState();
+ SkASSERT(mutableState);
return GrVkRenderTarget::MakeWrappedRenderTarget(this, tex.dimensions(), sampleCnt, imageInfo,
- std::move(layout));
+ std::move(mutableState));
}
sk_sp<GrRenderTarget> GrVkGpu::onWrapVulkanSecondaryCBAsRenderTarget(
@@ -1422,6 +1437,9 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapVulkanSecondaryCBAsRenderTarget(
}
bool GrVkGpu::onRegenerateMipMapLevels(GrTexture* tex) {
+ if (!this->currentCommandBuffer()) {
+ return false;
+ }
auto* vkTex = static_cast<GrVkTexture*>(tex);
// don't do anything for linearly tiled textures (can't have mipmaps)
if (vkTex->isLinearTiled()) {
@@ -1628,17 +1646,17 @@ bool GrVkGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
GrVkImageInfo info;
SkAssertResult(backendTexture.getVkImageInfo(&info));
- sk_sp<GrVkImageLayout> layout = backendTexture.getGrVkImageLayout();
- SkASSERT(layout);
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState = backendTexture.getMutableState();
+ SkASSERT(mutableState);
sk_sp<GrVkTexture> texture =
GrVkTexture::MakeWrappedTexture(this, backendTexture.dimensions(),
kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
- kRW_GrIOType, info, layout);
+ kRW_GrIOType, info, std::move(mutableState));
if (!texture) {
return false;
}
- GrVkPrimaryCommandBuffer* cmdBuffer = this->getTempCommandBuffer();
+ GrVkPrimaryCommandBuffer* cmdBuffer = this->currentCommandBuffer();
if (!cmdBuffer) {
return false;
}
@@ -1668,10 +1686,14 @@ bool GrVkGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
range.levelCount = info.fLevelCount;
cmdBuffer->clearColorImage(this, texture.get(), &vkColor, 1, &range);
} else {
+ SkImage::CompressionType compression = GrBackendFormatToCompressionType(
+ backendTexture.getBackendFormat());
+
SkTArray<VkBufferImageCopy> regions;
SkTArray<size_t> individualMipOffsets;
size_t combinedBufferSize = fill_in_regions(fVkCaps.get(), &regions, &individualMipOffsets,
- info.fFormat, backendTexture.dimensions(),
+ compression, info.fFormat,
+ backendTexture.dimensions(),
backendTexture.fMipMapped, 0);
sk_sp<GrVkTransferBuffer> transferBuffer =
@@ -1689,8 +1711,6 @@ bool GrVkGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
data->compressedData(), data->compressedSize());
} else {
SkASSERT(data->type() == BackendTextureData::Type::kColor);
- SkImage::CompressionType compression = GrVkFormatToCompressionType(info.fFormat);
-
result = generate_compressed_data(this, (char*)transferBuffer->map(), compression,
backendTexture.dimensions(),
backendTexture.fMipMapped, data->color());
@@ -1707,7 +1727,10 @@ bool GrVkGpu::onUpdateBackendTexture(const GrBackendTexture& backendTexture,
VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
false);
- return this->submitTempCommandBuffer(kSkip_SyncQueue, std::move(finishedCallback));
+ if (finishedCallback) {
+ this->addFinishedCallback(std::move(finishedCallback));
+ }
+ return true;
}
GrBackendTexture GrVkGpu::onCreateBackendTexture(SkISize dimensions,
@@ -1791,6 +1814,56 @@ GrBackendTexture GrVkGpu::onCreateCompressedBackendTexture(
return beTex;
}
+void set_layout_and_queue_from_mutable_state(GrVkGpu* gpu, GrVkImage* image,
+ const GrVkSharedImageInfo& newInfo) {
+ // Even though internally we use this helper for getting src access flags and stages they
+ // can also be used for general dst flags since we don't know exactly what the client
+ // plans on using the image for.
+ VkImageLayout newLayout = newInfo.getImageLayout();
+ VkPipelineStageFlags dstStage = GrVkImage::LayoutToPipelineSrcStageFlags(newLayout);
+ VkAccessFlags dstAccess = GrVkImage::LayoutToSrcAccessMask(newLayout);
+ image->setImageLayoutAndQueueIndex(gpu, newLayout, dstAccess, dstStage, false,
+ newInfo.getQueueFamilyIndex());
+}
+
+bool GrVkGpu::setBackendSurfaceState(GrVkImageInfo info,
+ sk_sp<GrBackendSurfaceMutableStateImpl> currentState,
+ SkISize dimensions,
+ const GrVkSharedImageInfo& newInfo) {
+ sk_sp<GrVkTexture> texture = GrVkTexture::MakeWrappedTexture(
+ this, dimensions, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType, info,
+ std::move(currentState));
+ SkASSERT(texture);
+ if (!texture) {
+ return false;
+ }
+ set_layout_and_queue_from_mutable_state(this, texture.get(), newInfo);
+ return true;
+}
+
+bool GrVkGpu::setBackendTextureState(const GrBackendTexture& backendTeture,
+ const GrBackendSurfaceMutableState& newState,
+ sk_sp<GrRefCntedCallback> finishedCallback) {
+ GrVkImageInfo info;
+ SkAssertResult(backendTeture.getVkImageInfo(&info));
+ sk_sp<GrBackendSurfaceMutableStateImpl> currentState = backendTeture.getMutableState();
+ SkASSERT(currentState);
+ SkASSERT(newState.fBackend == GrBackend::kVulkan);
+ return this->setBackendSurfaceState(info, std::move(currentState), backendTeture.dimensions(),
+ newState.fVkState);
+}
+
+bool GrVkGpu::setBackendRenderTargetState(const GrBackendRenderTarget& backendRenderTarget,
+ const GrBackendSurfaceMutableState& newState,
+ sk_sp<GrRefCntedCallback> finishedCallback) {
+ GrVkImageInfo info;
+ SkAssertResult(backendRenderTarget.getVkImageInfo(&info));
+ sk_sp<GrBackendSurfaceMutableStateImpl> currentState = backendRenderTarget.getMutableState();
+ SkASSERT(currentState);
+ SkASSERT(newState.fBackend == GrBackend::kVulkan);
+ return this->setBackendSurfaceState(info, std::move(currentState),
+ backendRenderTarget.dimensions(), newState.fVkState);
+}
void GrVkGpu::querySampleLocations(GrRenderTarget* renderTarget,
SkTArray<SkPoint>* sampleLocations) {
@@ -1923,7 +1996,9 @@ void GrVkGpu::addBufferMemoryBarrier(const GrManagedResource* resource,
VkPipelineStageFlags dstStageMask,
bool byRegion,
VkBufferMemoryBarrier* barrier) const {
- SkASSERT(this->currentCommandBuffer());
+ if (!this->currentCommandBuffer()) {
+ return;
+ }
SkASSERT(resource);
this->currentCommandBuffer()->pipelineBarrier(this,
resource,
@@ -1956,14 +2031,16 @@ void GrVkGpu::addImageMemoryBarrier(const GrManagedResource* resource,
barrier);
}
-void GrVkGpu::prepareSurfacesForBackendAccessAndExternalIO(
- GrSurfaceProxy* proxies[], int numProxies, SkSurface::BackendSurfaceAccess access,
- const GrPrepareForExternalIORequests& externalRequests) {
+void GrVkGpu::prepareSurfacesForBackendAccessAndStateUpdates(
+ GrSurfaceProxy* proxies[],
+ int numProxies,
+ SkSurface::BackendSurfaceAccess access,
+ const GrBackendSurfaceMutableState* newState) {
SkASSERT(numProxies >= 0);
SkASSERT(!numProxies || proxies);
// Submit the current command buffer to the Queue. Whether we inserted semaphores or not does
// not effect what we do here.
- if (numProxies && access == SkSurface::BackendSurfaceAccess::kPresent) {
+ if (numProxies && (access == SkSurface::BackendSurfaceAccess::kPresent || newState)) {
GrVkImage* image;
for (int i = 0; i < numProxies; ++i) {
SkASSERT(proxies[i]->isInstantiated());
@@ -1974,57 +2051,11 @@ void GrVkGpu::prepareSurfacesForBackendAccessAndExternalIO(
SkASSERT(rt);
image = static_cast<GrVkRenderTarget*>(rt);
}
- image->prepareForPresent(this);
- }
- }
-
- // Handle requests for preparing for external IO
- for (int i = 0; i < externalRequests.fNumImages; ++i) {
- SkImage* image = externalRequests.fImages[i];
- if (!image->isTextureBacked()) {
- continue;
- }
- SkImage_GpuBase* gpuImage = static_cast<SkImage_GpuBase*>(as_IB(image));
- const GrSurfaceProxyView* view = gpuImage->view(this->getContext());
- SkASSERT(view && *view);
-
- if (!view->proxy()->isInstantiated()) {
- auto resourceProvider = this->getContext()->priv().resourceProvider();
- if (!view->proxy()->instantiate(resourceProvider)) {
- continue;
- }
- }
-
- GrTexture* tex = view->proxy()->peekTexture();
- if (!tex) {
- continue;
- }
- GrVkTexture* vkTex = static_cast<GrVkTexture*>(tex);
- vkTex->prepareForExternal(this);
- }
- for (int i = 0; i < externalRequests.fNumSurfaces; ++i) {
- SkSurface* surface = externalRequests.fSurfaces[i];
- if (!surface->getCanvas()->getGrContext()) {
- continue;
- }
- SkSurface_Gpu* gpuSurface = static_cast<SkSurface_Gpu*>(surface);
- auto* rtc = gpuSurface->getDevice()->accessRenderTargetContext();
- sk_sp<GrRenderTargetProxy> proxy = rtc->asRenderTargetProxyRef();
- if (!proxy->isInstantiated()) {
- auto resourceProvider = this->getContext()->priv().resourceProvider();
- if (!proxy->instantiate(resourceProvider)) {
- continue;
+ if (newState) {
+ const GrVkSharedImageInfo& newInfo = newState->fVkState;
+ set_layout_and_queue_from_mutable_state(this, image, newInfo);
}
- }
-
- GrRenderTarget* rt = proxy->peekRenderTarget();
- SkASSERT(rt);
- GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);
- if (externalRequests.fPrepareSurfaceForPresent &&
- externalRequests.fPrepareSurfaceForPresent[i]) {
- vkRT->prepareForPresent(this);
- } else {
- vkRT->prepareForExternal(this);
+ image->prepareForPresent(this);
}
}
}
@@ -2032,7 +2063,14 @@ void GrVkGpu::prepareSurfacesForBackendAccessAndExternalIO(
void GrVkGpu::addFinishedProc(GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) {
SkASSERT(finishedProc);
- fResourceProvider.addFinishedProcToActiveCommandBuffers(finishedProc, finishedContext);
+ sk_sp<GrRefCntedCallback> finishedCallback(
+ new GrRefCntedCallback(finishedProc, finishedContext));
+ this->addFinishedCallback(std::move(finishedCallback));
+}
+
+void GrVkGpu::addFinishedCallback(sk_sp<GrRefCntedCallback> finishedCallback) {
+ SkASSERT(finishedCallback);
+ fResourceProvider.addFinishedProcToActiveCommandBuffers(std::move(finishedCallback));
}
bool GrVkGpu::onSubmitToGpu(bool syncCpu) {
@@ -2053,6 +2091,10 @@ static int get_surface_sample_cnt(GrSurface* surf) {
void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst, GrSurface* src, GrVkImage* dstImage,
GrVkImage* srcImage, const SkIRect& srcRect,
const SkIPoint& dstPoint) {
+ if (!this->currentCommandBuffer()) {
+ return;
+ }
+
#ifdef SK_DEBUG
int dstSampleCnt = get_surface_sample_cnt(dst);
int srcSampleCnt = get_surface_sample_cnt(src);
@@ -2108,6 +2150,10 @@ void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst, GrSurface* src, GrVkImage*
void GrVkGpu::copySurfaceAsBlit(GrSurface* dst, GrSurface* src, GrVkImage* dstImage,
GrVkImage* srcImage, const SkIRect& srcRect,
const SkIPoint& dstPoint) {
+ if (!this->currentCommandBuffer()) {
+ return;
+ }
+
#ifdef SK_DEBUG
int dstSampleCnt = get_surface_sample_cnt(dst);
int srcSampleCnt = get_surface_sample_cnt(src);
@@ -2255,6 +2301,10 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int
return false;
}
+ if (!this->currentCommandBuffer()) {
+ return false;
+ }
+
GrVkImage* image = nullptr;
GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(surface->asRenderTarget());
if (rt) {
@@ -2443,6 +2493,9 @@ bool GrVkGpu::beginRenderPass(const GrVkRenderPass* renderPass,
const VkClearValue* colorClear,
GrVkRenderTarget* target, GrSurfaceOrigin origin,
const SkIRect& bounds, bool forSecondaryCB) {
+ if (!this->currentCommandBuffer()) {
+ return false;
+ }
SkASSERT (!target->wrapsSecondaryCommandBuffer());
auto nativeBounds = GrNativeRect::MakeRelativeTo(origin, target->height(), bounds);
@@ -2478,11 +2531,16 @@ bool GrVkGpu::beginRenderPass(const GrVkRenderPass* renderPass,
void GrVkGpu::endRenderPass(GrRenderTarget* target, GrSurfaceOrigin origin,
const SkIRect& bounds) {
+ // We had a command buffer when we started the render pass, we should have one now as well.
+ SkASSERT(this->currentCommandBuffer());
this->currentCommandBuffer()->endRenderPass(this);
this->didWriteToSurface(target, origin, &bounds);
}
void GrVkGpu::submitSecondaryCommandBuffer(std::unique_ptr<GrVkSecondaryCommandBuffer> buffer) {
+ if (!this->currentCommandBuffer()) {
+ return;
+ }
this->currentCommandBuffer()->executeCommands(this, std::move(buffer));
}
@@ -2540,6 +2598,8 @@ std::unique_ptr<GrSemaphore> GrVkGpu::wrapBackendSemaphore(
}
void GrVkGpu::insertSemaphore(GrSemaphore* semaphore) {
+ SkASSERT(semaphore);
+
GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore);
GrVkSemaphore::Resource* resource = vkSem->getResource();
@@ -2550,6 +2610,8 @@ void GrVkGpu::insertSemaphore(GrSemaphore* semaphore) {
}
void GrVkGpu::waitSemaphore(GrSemaphore* semaphore) {
+ SkASSERT(semaphore);
+
GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore);
GrVkSemaphore::Resource* resource = vkSem->getResource();
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkGpu.h b/chromium/third_party/skia/src/gpu/vk/GrVkGpu.h
index be7a03c12d0..312792ba9d4 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkGpu.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkGpu.h
@@ -56,9 +56,7 @@ public:
VkDevice device() const { return fDevice; }
VkQueue queue() const { return fQueue; }
uint32_t queueIndex() const { return fQueueIndex; }
- GrVkCommandPool* cmdPool() const {
- return fTempCmdPool ? fTempCmdPool : fMainCmdPool;
- }
+ GrVkCommandPool* cmdPool() const { return fMainCmdPool; }
const VkPhysicalDeviceProperties& physicalDeviceProperties() const {
return fPhysDevProps;
}
@@ -69,14 +67,20 @@ public:
GrVkResourceProvider& resourceProvider() { return fResourceProvider; }
- GrVkPrimaryCommandBuffer* currentCommandBuffer() const {
- return fTempCmdBuffer ? fTempCmdBuffer : fMainCmdBuffer;
- }
+ GrVkPrimaryCommandBuffer* currentCommandBuffer() const { return fMainCmdBuffer; }
void querySampleLocations(GrRenderTarget*, SkTArray<SkPoint>*) override;
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
+ bool setBackendTextureState(const GrBackendTexture&,
+ const GrBackendSurfaceMutableState&,
+ sk_sp<GrRefCntedCallback> finishedCallback) override;
+
+ bool setBackendRenderTargetState(const GrBackendRenderTarget&,
+ const GrBackendSurfaceMutableState&,
+ sk_sp<GrRefCntedCallback> finishedCallback) override;
+
void deleteBackendTexture(const GrBackendTexture&) override;
bool compile(const GrProgramDesc&, const GrProgramInfo&) override;
@@ -98,7 +102,8 @@ public:
const GrRenderTarget*, int width, int height, int numStencilSamples) override;
GrOpsRenderPass* getOpsRenderPass(
- GrRenderTarget*, GrSurfaceOrigin, const SkIRect&,
+ GrRenderTarget*, GrStencilAttachment*,
+ GrSurfaceOrigin, const SkIRect&,
const GrOpsRenderPass::LoadAndStoreInfo&,
const GrOpsRenderPass::StencilLoadAndStoreInfo&,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies) override;
@@ -166,6 +171,8 @@ public:
const SkIRect& bounds, bool forSecondaryCB);
void endRenderPass(GrRenderTarget* target, GrSurfaceOrigin origin, const SkIRect& bounds);
+ using GrGpu::setOOMed;
+
private:
enum SyncQueue {
kForce_SyncQueue,
@@ -196,6 +203,11 @@ private:
sk_sp<GrRefCntedCallback> finishedCallback,
const BackendTextureData*) override;
+ bool setBackendSurfaceState(GrVkImageInfo info,
+ sk_sp<GrBackendSurfaceMutableStateImpl> currentState,
+ SkISize dimensions,
+ const GrVkSharedImageInfo& newInfo);
+
sk_sp<GrTexture> onCreateTexture(SkISize,
const GrBackendFormat&,
GrRenderable,
@@ -255,9 +267,13 @@ private:
void addFinishedProc(GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext) override;
- void prepareSurfacesForBackendAccessAndExternalIO(
- GrSurfaceProxy* proxies[], int numProxies, SkSurface::BackendSurfaceAccess access,
- const GrPrepareForExternalIORequests& externalRequests) override;
+ void addFinishedCallback(sk_sp<GrRefCntedCallback> finishedCallback);
+
+ void prepareSurfacesForBackendAccessAndStateUpdates(
+ GrSurfaceProxy* proxies[],
+ int numProxies,
+ SkSurface::BackendSurfaceAccess access,
+ const GrBackendSurfaceMutableState* newState) override;
bool onSubmitToGpu(bool syncCpu) override;
@@ -284,8 +300,9 @@ private:
GrColorType colorType, const void* data, size_t rowBytes);
bool uploadTexDataOptimal(GrVkTexture* tex, int left, int top, int width, int height,
GrColorType colorType, const GrMipLevel texels[], int mipLevelCount);
- bool uploadTexDataCompressed(GrVkTexture* tex, VkFormat vkFormat, SkISize dimensions,
- GrMipMapped mipMapped, const void* data, size_t dataSize);
+ bool uploadTexDataCompressed(GrVkTexture* tex, SkImage::CompressionType compression,
+ VkFormat vkFormat, SkISize dimensions, GrMipMapped mipMapped,
+ const void* data, size_t dataSize);
void resolveImage(GrSurface* dst, GrVkRenderTarget* src, const SkIRect& srcRect,
const SkIPoint& dstPoint);
@@ -297,18 +314,6 @@ private:
GrVkImageInfo*,
GrProtected);
- // Creates a new temporary primary command buffer that will be target of all subsequent commands
- // until it is submitted via submitTempCommandBuffer. When the temp command buffer gets
- // submitted the main command buffer will begin being the target of commands again. When using a
- // a temp command buffer, the caller should not use any resources that may have been used by the
- // unsubmitted main command buffer. The reason for this is we've already updated state, like
- // image layout, for the resources on the main command buffer even though we haven't submitted
- // it yet. Thus if the same resource gets used on the temp our tracking will get thosse state
- // updates out of order. It is legal to use a resource on either the temp or main command buffer
- // that was used on a previously submitted command buffer;
- GrVkPrimaryCommandBuffer* getTempCommandBuffer();
- bool submitTempCommandBuffer(SyncQueue sync, sk_sp<GrRefCntedCallback> finishedCallback);
-
sk_sp<const GrVkInterface> fInterface;
sk_sp<GrVkMemoryAllocator> fMemoryAllocator;
sk_sp<GrVkCaps> fVkCaps;
@@ -326,10 +331,6 @@ private:
// just a raw pointer; object's lifespan is managed by fCmdPool
GrVkPrimaryCommandBuffer* fMainCmdBuffer;
- GrVkCommandPool* fTempCmdPool = nullptr;
- // just a raw pointer; object's lifespan is managed by fCmdPool
- GrVkPrimaryCommandBuffer* fTempCmdBuffer = nullptr;
-
SkSTArray<1, GrVkSemaphore::Resource*> fSemaphoresToWaitOn;
SkSTArray<1, GrVkSemaphore::Resource*> fSemaphoresToSignal;
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkImage.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkImage.cpp
index 5022f1c54d0..98b24db5b0d 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkImage.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkImage.cpp
@@ -13,6 +13,43 @@
#define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
+GrVkImage::GrVkImage(const GrVkGpu* gpu,
+ const GrVkImageInfo& info,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
+ GrBackendObjectOwnership ownership,
+ bool forSecondaryCB)
+ : fInfo(info)
+ , fInitialQueueFamily(info.fCurrentQueueFamily)
+ , fMutableState(std::move(mutableState))
+ , fIsBorrowed(GrBackendObjectOwnership::kBorrowed == ownership) {
+ SkASSERT(fMutableState->getImageLayout() == fInfo.fImageLayout);
+ SkASSERT(fMutableState->getQueueFamilyIndex() == fInfo.fCurrentQueueFamily);
+#ifdef SK_DEBUG
+ // We can't transfer from the non graphics queue to the graphics queue since we can't
+ // release the image from the original queue without having that queue. This limits us in terms
+ // of the types of queue indices we can handle.
+ if (info.fCurrentQueueFamily != VK_QUEUE_FAMILY_IGNORED &&
+ info.fCurrentQueueFamily != VK_QUEUE_FAMILY_EXTERNAL &&
+ info.fCurrentQueueFamily != VK_QUEUE_FAMILY_FOREIGN_EXT) {
+ if (info.fSharingMode == VK_SHARING_MODE_EXCLUSIVE) {
+ if (info.fCurrentQueueFamily != gpu->queueIndex()) {
+ SkASSERT(false);
+ }
+ } else {
+ SkASSERT(false);
+ }
+ }
+#endif
+ if (forSecondaryCB) {
+ fResource = nullptr;
+ } else if (fIsBorrowed) {
+ fResource = new BorrowedResource(gpu, info.fImage, info.fAlloc, info.fImageTiling);
+ } else {
+ SkASSERT(VK_NULL_HANDLE != info.fAlloc.fMemory);
+ fResource = new Resource(gpu, info.fImage, info.fAlloc, info.fImageTiling);
+ }
+}
+
VkPipelineStageFlags GrVkImage::LayoutToPipelineSrcStageFlags(const VkImageLayout layout) {
if (VK_IMAGE_LAYOUT_GENERAL == layout) {
return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
@@ -82,26 +119,58 @@ VkImageAspectFlags vk_format_to_aspect_flags(VkFormat format) {
}
}
-void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout,
- VkAccessFlags dstAccessMask,
- VkPipelineStageFlags dstStageMask,
- bool byRegion, bool releaseFamilyQueue) {
+void GrVkImage::setImageLayoutAndQueueIndex(const GrVkGpu* gpu,
+ VkImageLayout newLayout,
+ VkAccessFlags dstAccessMask,
+ VkPipelineStageFlags dstStageMask,
+ bool byRegion,
+ uint32_t newQueueFamilyIndex) {
SkASSERT(!gpu->isDeviceLost());
- SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED != newLayout &&
- VK_IMAGE_LAYOUT_PREINITIALIZED != newLayout);
+ SkASSERT(newLayout == this->currentLayout() ||
+ (VK_IMAGE_LAYOUT_UNDEFINED != newLayout &&
+ VK_IMAGE_LAYOUT_PREINITIALIZED != newLayout));
VkImageLayout currentLayout = this->currentLayout();
+ uint32_t currentQueueIndex = this->currentQueueFamilyIndex();
+
+#ifdef SK_DEBUG
+ if (fInfo.fSharingMode == VK_SHARING_MODE_CONCURRENT) {
+ if (newQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED) {
+ SkASSERT(currentQueueIndex == VK_QUEUE_FAMILY_IGNORED ||
+ currentQueueIndex == VK_QUEUE_FAMILY_EXTERNAL ||
+ currentQueueIndex == VK_QUEUE_FAMILY_FOREIGN_EXT);
+ } else {
+ SkASSERT(newQueueFamilyIndex == VK_QUEUE_FAMILY_EXTERNAL ||
+ newQueueFamilyIndex == VK_QUEUE_FAMILY_FOREIGN_EXT);
+ SkASSERT(currentQueueIndex == VK_QUEUE_FAMILY_IGNORED);
+ }
+ } else {
+ SkASSERT(fInfo.fSharingMode == VK_SHARING_MODE_EXCLUSIVE);
+ if (newQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED ||
+ currentQueueIndex == gpu->queueIndex()) {
+ SkASSERT(currentQueueIndex == VK_QUEUE_FAMILY_IGNORED ||
+ currentQueueIndex == VK_QUEUE_FAMILY_EXTERNAL ||
+ currentQueueIndex == VK_QUEUE_FAMILY_FOREIGN_EXT ||
+ currentQueueIndex == gpu->queueIndex());
+ } else if (newQueueFamilyIndex == VK_QUEUE_FAMILY_EXTERNAL ||
+ newQueueFamilyIndex == VK_QUEUE_FAMILY_FOREIGN_EXT) {
+ SkASSERT(currentQueueIndex == VK_QUEUE_FAMILY_IGNORED ||
+ currentQueueIndex == gpu->queueIndex());
+ }
+ }
+#endif
- if (releaseFamilyQueue && fInfo.fCurrentQueueFamily == fInitialQueueFamily &&
- newLayout == currentLayout) {
- // We never transfered the image to this queue and we are releasing it so don't do anything.
- return;
+ if (fInfo.fSharingMode == VK_SHARING_MODE_EXCLUSIVE) {
+ if (newQueueFamilyIndex == VK_QUEUE_FAMILY_IGNORED) {
+ newQueueFamilyIndex = gpu->queueIndex();
+ }
+ if (currentQueueIndex == VK_QUEUE_FAMILY_IGNORED) {
+ currentQueueIndex = gpu->queueIndex();
+ }
}
// If the old and new layout are the same and the layout is a read only layout, there is no need
// to put in a barrier unless we also need to switch queues.
- if (newLayout == currentLayout && !releaseFamilyQueue &&
- (fInfo.fCurrentQueueFamily == VK_QUEUE_FAMILY_IGNORED ||
- fInfo.fCurrentQueueFamily == gpu->queueIndex()) &&
+ if (newLayout == currentLayout && currentQueueIndex == newQueueFamilyIndex &&
(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL == currentLayout ||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == currentLayout ||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == currentLayout)) {
@@ -113,26 +182,6 @@ void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout,
VkImageAspectFlags aspectFlags = vk_format_to_aspect_flags(fInfo.fFormat);
- uint32_t srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- uint32_t dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- if (fInfo.fCurrentQueueFamily != VK_QUEUE_FAMILY_IGNORED &&
- gpu->queueIndex() != fInfo.fCurrentQueueFamily) {
- // The image still is owned by its original queue family and we need to transfer it into
- // ours.
- SkASSERT(!releaseFamilyQueue);
- SkASSERT(fInfo.fCurrentQueueFamily == fInitialQueueFamily);
-
- srcQueueFamilyIndex = fInfo.fCurrentQueueFamily;
- dstQueueFamilyIndex = gpu->queueIndex();
- fInfo.fCurrentQueueFamily = gpu->queueIndex();
- } else if (releaseFamilyQueue) {
- // We are releasing the image so we must transfer the image back to its original queue
- // family.
- srcQueueFamilyIndex = fInfo.fCurrentQueueFamily;
- dstQueueFamilyIndex = fInitialQueueFamily;
- fInfo.fCurrentQueueFamily = fInitialQueueFamily;
- }
-
VkImageMemoryBarrier imageMemoryBarrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
nullptr, // pNext
@@ -140,8 +189,8 @@ void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout,
dstAccessMask, // dstAccessMask
currentLayout, // oldLayout
newLayout, // newLayout
- srcQueueFamilyIndex, // srcQueueFamilyIndex
- dstQueueFamilyIndex, // dstQueueFamilyIndex
+ currentQueueIndex, // srcQueueFamilyIndex
+ newQueueFamilyIndex, // dstQueueFamilyIndex
fInfo.fImage, // image
{ aspectFlags, 0, fInfo.fLevelCount, 0, 1 } // subresourceRange
};
@@ -150,6 +199,7 @@ void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout,
&imageMemoryBarrier);
this->updateImageLayout(newLayout);
+ this->setQueueFamilyIndex(newQueueFamilyIndex);
}
bool GrVkImage::InitImageInfo(GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo* info) {
@@ -217,6 +267,7 @@ bool GrVkImage::InitImageInfo(GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImag
info->fCurrentQueueFamily = VK_QUEUE_FAMILY_IGNORED;
info->fProtected =
(createflags & VK_IMAGE_CREATE_PROTECTED_BIT) ? GrProtected::kYes : GrProtected::kNo;
+ info->fSharingMode = VK_SHARING_MODE_EXCLUSIVE;
return true;
}
@@ -239,24 +290,17 @@ void GrVkImage::prepareForPresent(GrVkGpu* gpu) {
layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
}
}
- this->setImageLayout(gpu, layout, 0, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, false, true);
+ this->setImageLayoutAndQueueIndex(gpu, layout, 0, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, false,
+ fInitialQueueFamily);
}
void GrVkImage::prepareForExternal(GrVkGpu* gpu) {
- this->setImageLayout(gpu, this->currentLayout(), 0, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, false,
- true);
+ this->setImageLayoutAndQueueIndex(gpu, this->currentLayout(), 0,
+ VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, false,
+ fInitialQueueFamily);
}
-void GrVkImage::releaseImage(GrVkGpu* gpu) {
- if (!gpu->isDeviceLost() && fInfo.fCurrentQueueFamily != fInitialQueueFamily) {
- // The Vulkan spec is vague on what to put for the dstStageMask here. The spec for image
- // memory barrier says the dstStageMask must not be zero. However, in the spec when it talks
- // about family queue transfers it says the dstStageMask is ignored and should be set to
- // zero. Assuming it really is ignored we set it to VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT here
- // since it makes the Vulkan validation layers happy.
- this->setImageLayout(gpu, this->currentLayout(), 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
- false, true);
- }
+void GrVkImage::releaseImage() {
if (fResource) {
fResource->removeOwningTexture();
fResource->unref();
@@ -283,7 +327,7 @@ void GrVkImage::BorrowedResource::freeGPUData() const {
#if GR_TEST_UTILS
void GrVkImage::setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu) {
- fInfo.fCurrentQueueFamily = gpu->queueIndex();
+ fMutableState->setQueueFamilyIndex(gpu->queueIndex());
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkImage.h b/chromium/third_party/skia/src/gpu/vk/GrVkImage.h
index fbd15767569..dc4d0531563 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkImage.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkImage.h
@@ -12,9 +12,10 @@
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/vk/GrVkTypes.h"
#include "include/private/GrTypesPriv.h"
+#include "include/private/GrVkTypesPriv.h"
+#include "src/gpu/GrBackendSurfaceMutableStateImpl.h"
#include "src/gpu/GrManagedResource.h"
#include "src/gpu/GrTexture.h"
-#include "src/gpu/vk/GrVkImageLayout.h"
class GrVkGpu;
class GrVkTexture;
@@ -24,22 +25,12 @@ private:
class Resource;
public:
- GrVkImage(const GrVkGpu* gpu, const GrVkImageInfo& info, sk_sp<GrVkImageLayout> layout,
- GrBackendObjectOwnership ownership, bool forSecondaryCB = false)
- : fInfo(info)
- , fInitialQueueFamily(info.fCurrentQueueFamily)
- , fLayout(std::move(layout))
- , fIsBorrowed(GrBackendObjectOwnership::kBorrowed == ownership) {
- SkASSERT(fLayout->getImageLayout() == fInfo.fImageLayout);
- if (forSecondaryCB) {
- fResource = nullptr;
- } else if (fIsBorrowed) {
- fResource = new BorrowedResource(gpu, info.fImage, info.fAlloc, info.fImageTiling);
- } else {
- SkASSERT(VK_NULL_HANDLE != info.fAlloc.fMemory);
- fResource = new Resource(gpu, info.fImage, info.fAlloc, info.fImageTiling);
- }
- }
+ GrVkImage(const GrVkGpu* gpu,
+ const GrVkImageInfo& info,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
+ GrBackendObjectOwnership ownership,
+ bool forSecondaryCB = false);
+
virtual ~GrVkImage();
VkImage image() const {
@@ -82,18 +73,31 @@ public:
}
bool isBorrowed() const { return fIsBorrowed; }
- sk_sp<GrVkImageLayout> grVkImageLayout() const { return fLayout; }
+ sk_sp<GrBackendSurfaceMutableStateImpl> getMutableState() const { return fMutableState; }
- VkImageLayout currentLayout() const {
- return fLayout->getImageLayout();
- }
+ VkImageLayout currentLayout() const { return fMutableState->getImageLayout(); }
+
+ void setImageLayoutAndQueueIndex(const GrVkGpu* gpu,
+ VkImageLayout newLayout,
+ VkAccessFlags dstAccessMask,
+ VkPipelineStageFlags dstStageMask,
+ bool byRegion,
+ uint32_t newQueueFamilyIndex);
void setImageLayout(const GrVkGpu* gpu,
VkImageLayout newLayout,
VkAccessFlags dstAccessMask,
VkPipelineStageFlags dstStageMask,
- bool byRegion,
- bool releaseFamilyQueue = false);
+ bool byRegion) {
+ this->setImageLayoutAndQueueIndex(gpu, newLayout, dstAccessMask, dstStageMask, byRegion,
+ VK_QUEUE_FAMILY_IGNORED);
+ }
+
+ uint32_t currentQueueFamilyIndex() const { return fMutableState->getQueueFamilyIndex(); }
+
+ void setQueueFamilyIndex(uint32_t queueFamilyIndex) {
+ fMutableState->setQueueFamilyIndex(queueFamilyIndex);
+ }
// Returns the image to its original queue family and changes the layout to present if the queue
// family is not external or foreign.
@@ -109,7 +113,7 @@ public:
// Should only be called when we have a real fResource object, i.e. never when being used as
// a RT in an external secondary command buffer.
SkASSERT(fResource);
- fLayout->setImageLayout(newLayout);
+ fMutableState->setImageLayout(newLayout);
}
struct ImageDesc {
@@ -156,13 +160,13 @@ public:
#endif
protected:
- void releaseImage(GrVkGpu* gpu);
+ void releaseImage();
bool hasResource() const { return fResource; }
- GrVkImageInfo fInfo;
- uint32_t fInitialQueueFamily;
- sk_sp<GrVkImageLayout> fLayout;
- bool fIsBorrowed;
+ GrVkImageInfo fInfo;
+ uint32_t fInitialQueueFamily;
+ sk_sp<GrBackendSurfaceMutableStateImpl> fMutableState;
+ bool fIsBorrowed;
private:
class Resource : public GrTextureResource {
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkMemory.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkMemory.cpp
index ff07d3ba0a2..08cee6e3462 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkMemory.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkMemory.cpp
@@ -31,6 +31,16 @@ static BufferUsage get_buffer_usage(GrVkBuffer::Type type, bool dynamic) {
SK_ABORT("Invalid GrVkBuffer::Type");
}
+static bool check_result(GrVkGpu* gpu, VkResult result) {
+ if (result != VK_SUCCESS) {
+ if (result == VK_ERROR_DEVICE_LOST) {
+ gpu->setDeviceLost();
+ }
+ return false;
+ }
+ return true;
+}
+
bool GrVkMemory::AllocAndBindBufferMemory(GrVkGpu* gpu,
VkBuffer buffer,
GrVkBuffer::Type type,
@@ -57,7 +67,8 @@ bool GrVkMemory::AllocAndBindBufferMemory(GrVkGpu* gpu,
propFlags = AllocationPropertyFlags::kNone;
}
- if (!allocator->allocateMemoryForBuffer(buffer, usage, propFlags, &memory)) {
+ VkResult result = allocator->allocateBufferMemory(buffer, usage, propFlags, &memory);
+ if (!check_result(gpu, result)) {
return false;
}
allocator->getAllocInfo(memory, alloc);
@@ -76,12 +87,9 @@ bool GrVkMemory::AllocAndBindBufferMemory(GrVkGpu* gpu,
void GrVkMemory::FreeBufferMemory(const GrVkGpu* gpu, GrVkBuffer::Type type,
const GrVkAlloc& alloc) {
- if (alloc.fBackendMemory) {
- GrVkMemoryAllocator* allocator = gpu->memoryAllocator();
- allocator->freeMemory(alloc.fBackendMemory);
- } else {
- GR_VK_CALL(gpu->vkInterface(), FreeMemory(gpu->device(), alloc.fMemory, nullptr));
- }
+ SkASSERT(alloc.fBackendMemory);
+ GrVkMemoryAllocator* allocator = gpu->memoryAllocator();
+ allocator->freeMemory(alloc.fBackendMemory);
}
const VkDeviceSize kMaxSmallImageSize = 256 * 1024;
@@ -109,9 +117,11 @@ bool GrVkMemory::AllocAndBindImageMemory(GrVkGpu* gpu,
propFlags |= AllocationPropertyFlags::kProtected;
}
- if (!allocator->allocateMemoryForImage(image, propFlags, &memory)) {
+ VkResult result = allocator->allocateImageMemory(image, propFlags, &memory);
+ if (!check_result(gpu, result)) {
return false;
}
+
allocator->getAllocInfo(memory, alloc);
// Bind buffer
@@ -128,38 +138,27 @@ bool GrVkMemory::AllocAndBindImageMemory(GrVkGpu* gpu,
void GrVkMemory::FreeImageMemory(const GrVkGpu* gpu, bool linearTiling,
const GrVkAlloc& alloc) {
- if (alloc.fBackendMemory) {
- GrVkMemoryAllocator* allocator = gpu->memoryAllocator();
- allocator->freeMemory(alloc.fBackendMemory);
- } else {
- GR_VK_CALL(gpu->vkInterface(), FreeMemory(gpu->device(), alloc.fMemory, nullptr));
- }
+ SkASSERT(alloc.fBackendMemory);
+ GrVkMemoryAllocator* allocator = gpu->memoryAllocator();
+ allocator->freeMemory(alloc.fBackendMemory);
}
void* GrVkMemory::MapAlloc(GrVkGpu* gpu, const GrVkAlloc& alloc) {
SkASSERT(GrVkAlloc::kMappable_Flag & alloc.fFlags);
- if (alloc.fBackendMemory) {
- GrVkMemoryAllocator* allocator = gpu->memoryAllocator();
- return allocator->mapMemory(alloc.fBackendMemory);
- }
-
+ SkASSERT(alloc.fBackendMemory);
+ GrVkMemoryAllocator* allocator = gpu->memoryAllocator();
void* mapPtr;
- VkResult err;
- GR_VK_CALL_RESULT(gpu, err, MapMemory(gpu->device(), alloc.fMemory, alloc.fOffset, alloc.fSize,
- 0, &mapPtr));
- if (err) {
- mapPtr = nullptr;
+ VkResult result = allocator->mapMemory(alloc.fBackendMemory, &mapPtr);
+ if (!check_result(gpu, result)) {
+ return nullptr;
}
return mapPtr;
}
void GrVkMemory::UnmapAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc) {
- if (alloc.fBackendMemory) {
- GrVkMemoryAllocator* allocator = gpu->memoryAllocator();
- allocator->unmapMemory(alloc.fBackendMemory);
- } else {
- GR_VK_CALL(gpu->vkInterface(), UnmapMemory(gpu->device(), alloc.fMemory));
- }
+ SkASSERT(alloc.fBackendMemory);
+ GrVkMemoryAllocator* allocator = gpu->memoryAllocator();
+ allocator->unmapMemory(alloc.fBackendMemory);
}
void GrVkMemory::GetNonCoherentMappedMemoryRange(const GrVkAlloc& alloc, VkDeviceSize offset,
@@ -185,41 +184,27 @@ void GrVkMemory::GetNonCoherentMappedMemoryRange(const GrVkAlloc& alloc, VkDevic
range->size = size;
}
-void GrVkMemory::FlushMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc, VkDeviceSize offset,
+void GrVkMemory::FlushMappedAlloc(GrVkGpu* gpu, const GrVkAlloc& alloc, VkDeviceSize offset,
VkDeviceSize size) {
if (alloc.fFlags & GrVkAlloc::kNoncoherent_Flag) {
SkASSERT(offset == 0);
SkASSERT(size <= alloc.fSize);
- if (alloc.fBackendMemory) {
- GrVkMemoryAllocator* allocator = gpu->memoryAllocator();
- allocator->flushMappedMemory(alloc.fBackendMemory, offset, size);
- } else {
- VkDeviceSize alignment = gpu->physicalDeviceProperties().limits.nonCoherentAtomSize;
- VkMappedMemoryRange mappedMemoryRange;
- GrVkMemory::GetNonCoherentMappedMemoryRange(alloc, offset, size, alignment,
- &mappedMemoryRange);
- GR_VK_CALL(gpu->vkInterface(), FlushMappedMemoryRanges(gpu->device(), 1,
- &mappedMemoryRange));
- }
+ SkASSERT(alloc.fBackendMemory);
+ GrVkMemoryAllocator* allocator = gpu->memoryAllocator();
+ VkResult result = allocator->flushMemory(alloc.fBackendMemory, offset, size);
+ check_result(gpu, result);
}
}
-void GrVkMemory::InvalidateMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc,
+void GrVkMemory::InvalidateMappedAlloc(GrVkGpu* gpu, const GrVkAlloc& alloc,
VkDeviceSize offset, VkDeviceSize size) {
if (alloc.fFlags & GrVkAlloc::kNoncoherent_Flag) {
SkASSERT(offset == 0);
SkASSERT(size <= alloc.fSize);
- if (alloc.fBackendMemory) {
- GrVkMemoryAllocator* allocator = gpu->memoryAllocator();
- allocator->invalidateMappedMemory(alloc.fBackendMemory, offset, size);
- } else {
- VkDeviceSize alignment = gpu->physicalDeviceProperties().limits.nonCoherentAtomSize;
- VkMappedMemoryRange mappedMemoryRange;
- GrVkMemory::GetNonCoherentMappedMemoryRange(alloc, offset, size, alignment,
- &mappedMemoryRange);
- GR_VK_CALL(gpu->vkInterface(), InvalidateMappedMemoryRanges(gpu->device(), 1,
- &mappedMemoryRange));
- }
+ SkASSERT(alloc.fBackendMemory);
+ GrVkMemoryAllocator* allocator = gpu->memoryAllocator();
+ VkResult result = allocator->invalidateMemory(alloc.fBackendMemory, offset, size);
+ check_result(gpu, result);
}
}
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkMemory.h b/chromium/third_party/skia/src/gpu/vk/GrVkMemory.h
index db2c0e66062..2cb91fd7b2b 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkMemory.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkMemory.h
@@ -42,9 +42,9 @@ namespace GrVkMemory {
// For the Flush and Invalidate calls, the offset should be relative to the GrVkAlloc. Thus this
// will often be 0. The client does not need to make sure the offset and size are aligned to the
// nonCoherentAtomSize, the internal calls will handle that.
- void FlushMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc, VkDeviceSize offset,
+ void FlushMappedAlloc(GrVkGpu* gpu, const GrVkAlloc& alloc, VkDeviceSize offset,
VkDeviceSize size);
- void InvalidateMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc, VkDeviceSize offset,
+ void InvalidateMappedAlloc(GrVkGpu* gpu, const GrVkAlloc& alloc, VkDeviceSize offset,
VkDeviceSize size);
// Helper for aligning and setting VkMappedMemoryRange for flushing/invalidating noncoherent
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.cpp
index 3327cf8c8ed..00f54b9008d 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.cpp
@@ -11,7 +11,6 @@
#include "include/core/SkRect.h"
#include "include/gpu/GrBackendDrawableInfo.h"
#include "src/gpu/GrContextPriv.h"
-#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrPipeline.h"
#include "src/gpu/GrRenderTargetPriv.h"
@@ -61,7 +60,8 @@ GrVkOpsRenderPass::GrVkOpsRenderPass(GrVkGpu* gpu) : fGpu(gpu) {}
bool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
- const SkPMColor4f& clearColor) {
+ const SkPMColor4f& clearColor,
+ bool withStencil) {
VkAttachmentLoadOp loadOp;
VkAttachmentStoreOp storeOp;
@@ -87,8 +87,11 @@ bool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
false);
// If we are using a stencil attachment we also need to update its layout
- if (GrStencilAttachment* stencil = fRenderTarget->renderTargetPriv().getStencilAttachment()) {
- GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
+ if (withStencil) {
+ GrVkStencilAttachment* vkStencil =
+ (GrVkStencilAttachment*) fRenderTarget->renderTargetPriv().getStencilAttachment();
+ SkASSERT(vkStencil);
+
// We need the write and read access bits since we may load and store the stencil.
// The initial load happens in the VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT so we
// wait there.
@@ -101,7 +104,7 @@ bool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
}
const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
- vkRT->compatibleRenderPassHandle();
+ vkRT->compatibleRenderPassHandle(withStencil);
if (rpHandle.isValid()) {
fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
vkColorOps,
@@ -109,7 +112,9 @@ bool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
} else {
fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(vkRT,
vkColorOps,
- vkStencilOps);
+ vkStencilOps,
+ nullptr,
+ withStencil);
}
if (!fCurrentRenderPass) {
return false;
@@ -128,7 +133,8 @@ bool GrVkOpsRenderPass::init(const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
fCurrentRenderPass = nullptr;
return false;
}
- fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->getFramebuffer(), fCurrentRenderPass);
+ fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->getFramebuffer(withStencil),
+ fCurrentRenderPass);
}
if (!fGpu->beginRenderPass(fCurrentRenderPass, &vkClearColor, vkRT, fOrigin, fBounds,
@@ -168,6 +174,9 @@ GrVkCommandBuffer* GrVkOpsRenderPass::currentCommandBuffer() {
if (fCurrentSecondaryCommandBuffer) {
return fCurrentSecondaryCommandBuffer.get();
}
+ // We checked this when we setup the GrVkOpsRenderPass and it should not have changed while we
+ // are still using this object.
+ SkASSERT(fGpu->currentCommandBuffer());
return fGpu->currentCommandBuffer();
}
@@ -196,7 +205,8 @@ void GrVkOpsRenderPass::submit() {
fGpu->endRenderPass(fRenderTarget, fOrigin, fBounds);
}
-bool GrVkOpsRenderPass::set(GrRenderTarget* rt, GrSurfaceOrigin origin, const SkIRect& bounds,
+bool GrVkOpsRenderPass::set(GrRenderTarget* rt, GrStencilAttachment* stencil,
+ GrSurfaceOrigin origin, const SkIRect& bounds,
const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies) {
@@ -207,6 +217,13 @@ bool GrVkOpsRenderPass::set(GrRenderTarget* rt, GrSurfaceOrigin origin, const Sk
fIsActive = true;
#endif
+ // We check to make sure the GrVkGpu has a valid current command buffer instead of each time we
+ // access it. If the command buffer is valid here should be valid throughout the use of the
+ // render pass since nothing should trigger a submit while this render pass is active.
+ if (!fGpu->currentCommandBuffer()) {
+ return false;
+ }
+
this->INHERITED::set(rt, origin);
for (int i = 0; i < sampledProxies.count(); ++i) {
@@ -227,7 +244,7 @@ bool GrVkOpsRenderPass::set(GrRenderTarget* rt, GrSurfaceOrigin origin, const Sk
return this->initWrapped();
}
- return this->init(colorInfo, stencilInfo, colorInfo.fClearColor);
+ return this->init(colorInfo, stencilInfo, colorInfo.fClearColor, SkToBool(stencil));
}
void GrVkOpsRenderPass::reset() {
@@ -257,14 +274,12 @@ bool GrVkOpsRenderPass::wrapsSecondaryCommandBuffer() const {
////////////////////////////////////////////////////////////////////////////////
-void GrVkOpsRenderPass::onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
+void GrVkOpsRenderPass::onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) {
if (!fCurrentRenderPass) {
SkASSERT(fGpu->isDeviceLost());
return;
}
- SkASSERT(!clip.hasWindowRectangles());
-
GrStencilAttachment* sb = fRenderTarget->renderTargetPriv().getStencilAttachment();
// this should only be called internally when we know we have a
// stencil buffer.
@@ -285,14 +300,13 @@ void GrVkOpsRenderPass::onClearStencilClip(const GrFixedClip& clip, bool insideS
VkClearRect clearRect;
// Flip rect if necessary
SkIRect vkRect;
- if (!clip.scissorEnabled()) {
+ if (!scissor.enabled()) {
vkRect.setXYWH(0, 0, fRenderTarget->width(), fRenderTarget->height());
} else if (kBottomLeft_GrSurfaceOrigin != fOrigin) {
- vkRect = clip.scissorRect();
+ vkRect = scissor.rect();
} else {
- const SkIRect& scissor = clip.scissorRect();
- vkRect.setLTRB(scissor.fLeft, fRenderTarget->height() - scissor.fBottom,
- scissor.fRight, fRenderTarget->height() - scissor.fTop);
+ vkRect.setLTRB(scissor.rect().fLeft, fRenderTarget->height() - scissor.rect().fBottom,
+ scissor.rect().fRight, fRenderTarget->height() - scissor.rect().fTop);
}
clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
@@ -313,15 +327,12 @@ void GrVkOpsRenderPass::onClearStencilClip(const GrFixedClip& clip, bool insideS
fCurrentCBIsEmpty = false;
}
-void GrVkOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& color) {
+void GrVkOpsRenderPass::onClear(const GrScissorState& scissor, const SkPMColor4f& color) {
if (!fCurrentRenderPass) {
SkASSERT(fGpu->isDeviceLost());
return;
}
- // parent class should never let us get here with no RT
- SkASSERT(!clip.hasWindowRectangles());
-
VkClearColorValue vkColor = {{color.fR, color.fG, color.fB, color.fA}};
// If we end up in a situation where we are calling clear without a scissior then in general it
@@ -330,20 +341,19 @@ void GrVkOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& colo
// load op (e.g. if we needed to execute a wait op). Thus we also have the empty check here.
// TODO: Make the waitOp a RenderTask instead so we can clear out the GrOpsTask for a clear. We
// can then reenable this assert assuming we can't get messed up by a waitOp.
- //SkASSERT(!fCurrentCBIsEmpty || clip.scissorEnabled());
+ //SkASSERT(!fCurrentCBIsEmpty || scissor);
// We always do a sub rect clear with clearAttachments since we are inside a render pass
VkClearRect clearRect;
// Flip rect if necessary
SkIRect vkRect;
- if (!clip.scissorEnabled()) {
+ if (!scissor.enabled()) {
vkRect.setXYWH(0, 0, fRenderTarget->width(), fRenderTarget->height());
} else if (kBottomLeft_GrSurfaceOrigin != fOrigin) {
- vkRect = clip.scissorRect();
+ vkRect = scissor.rect();
} else {
- const SkIRect& scissor = clip.scissorRect();
- vkRect.setLTRB(scissor.fLeft, fRenderTarget->height() - scissor.fBottom,
- scissor.fRight, fRenderTarget->height() - scissor.fTop);
+ vkRect.setLTRB(scissor.rect().fLeft, fRenderTarget->height() - scissor.rect().fBottom,
+ scissor.rect().fRight, fRenderTarget->height() - scissor.rect().fTop);
}
clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
@@ -374,8 +384,10 @@ void GrVkOpsRenderPass::addAdditionalRenderPass(bool mustUseSecondaryCommandBuff
GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE);
+ bool withStencil = fCurrentRenderPass->hasStencilAttachment();
+
const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
- vkRT->compatibleRenderPassHandle();
+ vkRT->compatibleRenderPassHandle(withStencil);
SkASSERT(fCurrentRenderPass);
fCurrentRenderPass->unref();
if (rpHandle.isValid()) {
@@ -385,7 +397,9 @@ void GrVkOpsRenderPass::addAdditionalRenderPass(bool mustUseSecondaryCommandBuff
} else {
fCurrentRenderPass = fGpu->resourceProvider().findRenderPass(vkRT,
vkColorOps,
- vkStencilOps);
+ vkStencilOps,
+ nullptr,
+ withStencil);
}
if (!fCurrentRenderPass) {
return;
@@ -402,7 +416,8 @@ void GrVkOpsRenderPass::addAdditionalRenderPass(bool mustUseSecondaryCommandBuff
fCurrentRenderPass = nullptr;
return;
}
- fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->getFramebuffer(), fCurrentRenderPass);
+ fCurrentSecondaryCommandBuffer->begin(fGpu, vkRT->getFramebuffer(withStencil),
+ fCurrentRenderPass);
}
// We use the same fBounds as the whole GrVkOpsRenderPass since we have no way of tracking the
@@ -669,4 +684,3 @@ void GrVkOpsRenderPass::onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHan
drawable->draw(info);
fGpu->addDrawable(std::move(drawable));
}
-
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.h b/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.h
index 195bb922c02..ef666ec334b 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkOpsRenderPass.h
@@ -32,7 +32,8 @@ public:
void onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) override;
- bool set(GrRenderTarget*, GrSurfaceOrigin, const SkIRect& bounds,
+ bool set(GrRenderTarget*, GrStencilAttachment*,
+ GrSurfaceOrigin, const SkIRect& bounds,
const GrOpsRenderPass::LoadAndStoreInfo&,
const GrOpsRenderPass::StencilLoadAndStoreInfo&,
const SkTArray<GrSurfaceProxy*, true>& sampledProxies);
@@ -47,7 +48,8 @@ public:
private:
bool init(const GrOpsRenderPass::LoadAndStoreInfo&,
const GrOpsRenderPass::StencilLoadAndStoreInfo&,
- const SkPMColor4f& clearColor);
+ const SkPMColor4f& clearColor,
+ bool withStencil);
// Called instead of init when we are drawing to a render target that already wraps a secondary
// command buffer.
@@ -82,9 +84,9 @@ private:
void onDrawIndexedIndirect(const GrBuffer* drawIndirectBuffer, size_t offset,
int drawCount) override;
- void onClear(const GrFixedClip&, const SkPMColor4f& color) override;
+ void onClear(const GrScissorState& scissor, const SkPMColor4f& color) override;
- void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) override;
+ void onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) override;
void addAdditionalRenderPass(bool mustUseSecondaryCommandBuffer);
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.cpp
index 4347cf4034a..1e04c61a5b6 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.cpp
@@ -19,8 +19,6 @@
#include "src/gpu/vk/GrVkRenderPass.h"
#include "src/gpu/vk/GrVkRenderTarget.h"
-typedef size_t shader_size;
-
GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState(
GrVkGpu* gpu,
GrRenderTarget* renderTarget,
@@ -100,39 +98,49 @@ bool GrVkPipelineStateBuilder::installVkShaderModule(VkShaderStageFlagBits stage
static constexpr SkFourByteTag kSPIRV_Tag = SkSetFourByteTag('S', 'P', 'R', 'V');
static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
-int GrVkPipelineStateBuilder::loadShadersFromCache(SkReader32* cached,
+int GrVkPipelineStateBuilder::loadShadersFromCache(SkReadBuffer* cached,
VkShaderModule outShaderModules[],
VkPipelineShaderStageCreateInfo* outStageInfo) {
SkSL::String shaders[kGrShaderTypeCount];
SkSL::Program::Inputs inputs[kGrShaderTypeCount];
- GrPersistentCacheUtils::UnpackCachedShaders(cached, shaders, inputs, kGrShaderTypeCount);
+ if (!GrPersistentCacheUtils::UnpackCachedShaders(cached, shaders, inputs, kGrShaderTypeCount)) {
+ return 0;
+ }
- SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
+ bool success = this->installVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
fVS,
&outShaderModules[kVertex_GrShaderType],
&outStageInfo[0],
shaders[kVertex_GrShaderType],
- inputs[kVertex_GrShaderType]));
+ inputs[kVertex_GrShaderType]);
- SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
- fFS,
- &outShaderModules[kFragment_GrShaderType],
- &outStageInfo[1],
- shaders[kFragment_GrShaderType],
- inputs[kFragment_GrShaderType]));
+ success = success && this->installVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
+ fFS,
+ &outShaderModules[kFragment_GrShaderType],
+ &outStageInfo[1],
+ shaders[kFragment_GrShaderType],
+ inputs[kFragment_GrShaderType]);
if (!shaders[kGeometry_GrShaderType].empty()) {
- SkAssertResult(this->installVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
- fGS,
- &outShaderModules[kGeometry_GrShaderType],
- &outStageInfo[2],
- shaders[kGeometry_GrShaderType],
- inputs[kGeometry_GrShaderType]));
- return 3;
- } else {
- return 2;
+ success = success && this->installVkShaderModule(VK_SHADER_STAGE_GEOMETRY_BIT,
+ fGS,
+ &outShaderModules[kGeometry_GrShaderType],
+ &outStageInfo[2],
+ shaders[kGeometry_GrShaderType],
+ inputs[kGeometry_GrShaderType]);
+ }
+
+ if (!success) {
+ for (int i = 0; i < kGrShaderTypeCount; ++i) {
+ if (outShaderModules[i]) {
+ GR_VK_CALL(fGpu->vkInterface(),
+ DestroyShaderModule(fGpu->device(), outShaderModules[i], nullptr));
+ }
+ }
+ return 0;
}
+ return shaders[kGeometry_GrShaderType].empty() ? 2 : 3;
}
void GrVkPipelineStateBuilder::storeShadersInCache(const SkSL::String shaders[],
@@ -211,7 +219,7 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrProgramDesc& desc,
SkASSERT(!this->fragColorIsInOut());
sk_sp<SkData> cached;
- SkReader32 reader;
+ SkReadBuffer reader;
SkFourByteTag shaderType = 0;
auto persistentCache = fGpu->getContext()->priv().getPersistentCache();
if (persistentCache) {
@@ -231,7 +239,10 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrProgramDesc& desc,
int numShaderStages = 0;
if (kSPIRV_Tag == shaderType) {
numShaderStages = this->loadShadersFromCache(&reader, shaderModules, shaderStageInfo);
- } else {
+ }
+
+ // Proceed from sources if we didn't get a SPIRV cache (or the cache was invalid)
+ if (!numShaderStages) {
numShaderStages = 2; // We always have at least vertex and fragment stages.
SkSL::String shaders[kGrShaderTypeCount];
SkSL::Program::Inputs inputs[kGrShaderTypeCount];
@@ -243,10 +254,11 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrProgramDesc& desc,
};
SkSL::String cached_sksl[kGrShaderTypeCount];
if (kSKSL_Tag == shaderType) {
- GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, inputs,
- kGrShaderTypeCount);
- for (int i = 0; i < kGrShaderTypeCount; ++i) {
- sksl[i] = &cached_sksl[i];
+ if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, inputs,
+ kGrShaderTypeCount)) {
+ for (int i = 0; i < kGrShaderTypeCount; ++i) {
+ sksl[i] = &cached_sksl[i];
+ }
}
}
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.h b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.h
index 1eb5290f6a0..d13f47bee3e 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateBuilder.h
@@ -19,7 +19,7 @@
class GrProgramDesc;
class GrVkGpu;
class GrVkRenderPass;
-class SkReader32;
+class SkReadBuffer;
class GrVkPipelineStateBuilder : public GrGLSLProgramBuilder {
public:
@@ -48,7 +48,7 @@ private:
GrVkPipelineState* finalize(const GrProgramDesc&, VkRenderPass compatibleRenderPass);
// returns number of shader stages
- int loadShadersFromCache(SkReader32* cached, VkShaderModule outShaderModules[],
+ int loadShadersFromCache(SkReadBuffer* cached, VkShaderModule outShaderModules[],
VkPipelineShaderStageCreateInfo* outStageInfo);
void storeShadersInCache(const SkSL::String shaders[], const SkSL::Program::Inputs inputs[],
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.cpp
index bd0c8d460f6..8377437afe7 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.cpp
@@ -12,11 +12,8 @@
GrVkPipelineStateDataManager::GrVkPipelineStateDataManager(const UniformInfoArray& uniforms,
uint32_t uniformSize)
- : fUniformSize(uniformSize)
- , fUniformsDirty(false) {
- fUniformData.reset(uniformSize);
- fUniforms.push_back_n(uniforms.count());
- // We must add uniforms in same order is the UniformInfoArray so that UniformHandles already
+ : INHERITED(uniforms.count(), uniformSize) {
+ // We must add uniforms in same order as the UniformInfoArray so that UniformHandles already
// owned by other objects will still match up here.
int i = 0;
for (const auto& uniformInfo : uniforms.items()) {
@@ -33,306 +30,6 @@ GrVkPipelineStateDataManager::GrVkPipelineStateDataManager(const UniformInfoArra
}
}
-void* GrVkPipelineStateDataManager::getBufferPtrAndMarkDirty(const Uniform& uni) const {
- fUniformsDirty = true;
- return static_cast<char*>(fUniformData.get())+uni.fOffset;
-}
-
-void GrVkPipelineStateDataManager::set1i(UniformHandle u, int32_t i) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
- SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- memcpy(buffer, &i, sizeof(int32_t));
-}
-
-void GrVkPipelineStateDataManager::set1iv(UniformHandle u,
- int arrayCount,
- const int32_t v[]) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
- SkASSERT(arrayCount > 0);
- SkASSERT(arrayCount <= uni.fArrayCount ||
- (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
-
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- SkASSERT(sizeof(int32_t) == 4);
- for (int i = 0; i < arrayCount; ++i) {
- const int32_t* curVec = &v[i];
- memcpy(buffer, curVec, sizeof(int32_t));
- buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t);
- }
-}
-
-void GrVkPipelineStateDataManager::set1f(UniformHandle u, float v0) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kFloat_GrSLType || uni.fType == kHalf_GrSLType);
- SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- SkASSERT(sizeof(float) == 4);
- memcpy(buffer, &v0, sizeof(float));
-}
-
-void GrVkPipelineStateDataManager::set1fv(UniformHandle u,
- int arrayCount,
- const float v[]) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kFloat_GrSLType || uni.fType == kHalf_GrSLType);
- SkASSERT(arrayCount > 0);
- SkASSERT(arrayCount <= uni.fArrayCount ||
- (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
-
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- SkASSERT(sizeof(float) == 4);
- for (int i = 0; i < arrayCount; ++i) {
- const float* curVec = &v[i];
- memcpy(buffer, curVec, sizeof(float));
- buffer = static_cast<char*>(buffer) + 4*sizeof(float);
- }
-}
-
-void GrVkPipelineStateDataManager::set2i(UniformHandle u, int32_t i0, int32_t i1) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kInt2_GrSLType || uni.fType == kShort2_GrSLType);
- SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- int32_t v[2] = { i0, i1 };
- memcpy(buffer, v, 2 * sizeof(int32_t));
-}
-
-void GrVkPipelineStateDataManager::set2iv(UniformHandle u,
- int arrayCount,
- const int32_t v[]) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kInt2_GrSLType || uni.fType == kShort2_GrSLType);
- SkASSERT(arrayCount > 0);
- SkASSERT(arrayCount <= uni.fArrayCount ||
- (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
-
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- SkASSERT(sizeof(int32_t) == 4);
- for (int i = 0; i < arrayCount; ++i) {
- const int32_t* curVec = &v[2 * i];
- memcpy(buffer, curVec, 2 * sizeof(int32_t));
- buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t);
- }
-}
-
-void GrVkPipelineStateDataManager::set2f(UniformHandle u, float v0, float v1) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
- SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- SkASSERT(sizeof(float) == 4);
- float v[2] = { v0, v1 };
- memcpy(buffer, v, 2 * sizeof(float));
-}
-
-void GrVkPipelineStateDataManager::set2fv(UniformHandle u,
- int arrayCount,
- const float v[]) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
- SkASSERT(arrayCount > 0);
- SkASSERT(arrayCount <= uni.fArrayCount ||
- (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
-
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- SkASSERT(sizeof(float) == 4);
- for (int i = 0; i < arrayCount; ++i) {
- const float* curVec = &v[2 * i];
- memcpy(buffer, curVec, 2 * sizeof(float));
- buffer = static_cast<char*>(buffer) + 4*sizeof(float);
- }
-}
-
-void GrVkPipelineStateDataManager::set3i(UniformHandle u,
- int32_t i0,
- int32_t i1,
- int32_t i2) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kInt3_GrSLType || uni.fType == kShort3_GrSLType);
- SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- int32_t v[3] = { i0, i1, i2 };
- memcpy(buffer, v, 3 * sizeof(int32_t));
-}
-
-void GrVkPipelineStateDataManager::set3iv(UniformHandle u,
- int arrayCount,
- const int32_t v[]) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kInt3_GrSLType || uni.fType == kShort3_GrSLType);
- SkASSERT(arrayCount > 0);
- SkASSERT(arrayCount <= uni.fArrayCount ||
- (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
-
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- SkASSERT(sizeof(int32_t) == 4);
- for (int i = 0; i < arrayCount; ++i) {
- const int32_t* curVec = &v[3 * i];
- memcpy(buffer, curVec, 3 * sizeof(int32_t));
- buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t);
- }
-}
-
-void GrVkPipelineStateDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
- SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- SkASSERT(sizeof(float) == 4);
- float v[3] = { v0, v1, v2 };
- memcpy(buffer, v, 3 * sizeof(float));
-}
-
-void GrVkPipelineStateDataManager::set3fv(UniformHandle u,
- int arrayCount,
- const float v[]) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
- SkASSERT(arrayCount > 0);
- SkASSERT(arrayCount <= uni.fArrayCount ||
- (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
-
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- SkASSERT(sizeof(float) == 4);
- for (int i = 0; i < arrayCount; ++i) {
- const float* curVec = &v[3 * i];
- memcpy(buffer, curVec, 3 * sizeof(float));
- buffer = static_cast<char*>(buffer) + 4*sizeof(float);
- }
-}
-
-void GrVkPipelineStateDataManager::set4i(UniformHandle u,
- int32_t i0,
- int32_t i1,
- int32_t i2,
- int32_t i3) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kInt4_GrSLType || uni.fType == kShort4_GrSLType);
- SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- int32_t v[4] = { i0, i1, i2, i3 };
- memcpy(buffer, v, 4 * sizeof(int32_t));
-}
-
-void GrVkPipelineStateDataManager::set4iv(UniformHandle u,
- int arrayCount,
- const int32_t v[]) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kInt4_GrSLType || uni.fType == kShort4_GrSLType);
- SkASSERT(arrayCount > 0);
- SkASSERT(arrayCount <= uni.fArrayCount ||
- (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
-
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- SkASSERT(sizeof(int32_t) == 4);
- for (int i = 0; i < arrayCount; ++i) {
- const int32_t* curVec = &v[4 * i];
- memcpy(buffer, curVec, 4 * sizeof(int32_t));
- buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t);
- }
-}
-
-void GrVkPipelineStateDataManager::set4f(UniformHandle u,
- float v0,
- float v1,
- float v2,
- float v3) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
- SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- SkASSERT(sizeof(float) == 4);
- float v[4] = { v0, v1, v2, v3 };
- memcpy(buffer, v, 4 * sizeof(float));
-}
-
-void GrVkPipelineStateDataManager::set4fv(UniformHandle u,
- int arrayCount,
- const float v[]) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
- SkASSERT(arrayCount > 0);
- SkASSERT(arrayCount <= uni.fArrayCount ||
- (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
-
- void* buffer = this->getBufferPtrAndMarkDirty(uni);
- SkASSERT(sizeof(float) == 4);
- memcpy(buffer, v, arrayCount * 4 * sizeof(float));
-}
-
-void GrVkPipelineStateDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const {
- this->setMatrices<2>(u, 1, matrix);
-}
-
-void GrVkPipelineStateDataManager::setMatrix2fv(UniformHandle u,
- int arrayCount,
- const float m[]) const {
- this->setMatrices<2>(u, arrayCount, m);
-}
-
-void GrVkPipelineStateDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const {
- this->setMatrices<3>(u, 1, matrix);
-}
-
-void GrVkPipelineStateDataManager::setMatrix3fv(UniformHandle u,
- int arrayCount,
- const float m[]) const {
- this->setMatrices<3>(u, arrayCount, m);
-}
-
-void GrVkPipelineStateDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const {
- this->setMatrices<4>(u, 1, matrix);
-}
-
-void GrVkPipelineStateDataManager::setMatrix4fv(UniformHandle u,
- int arrayCount,
- const float m[]) const {
- this->setMatrices<4>(u, arrayCount, m);
-}
-
-template<int N> struct set_uniform_matrix;
-
-template<int N> inline void GrVkPipelineStateDataManager::setMatrices(UniformHandle u,
- int arrayCount,
- const float matrices[]) const {
- const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kFloat2x2_GrSLType + (N - 2) ||
- uni.fType == kHalf2x2_GrSLType + (N - 2));
- SkASSERT(arrayCount > 0);
- SkASSERT(arrayCount <= uni.fArrayCount ||
- (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
-
- void* buffer = fUniformData.get();
- fUniformsDirty = true;
-
- set_uniform_matrix<N>::set(buffer, uni.fOffset, arrayCount, matrices);
-}
-
-template<int N> struct set_uniform_matrix {
- inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) {
- static_assert(sizeof(float) == 4);
- buffer = static_cast<char*>(buffer) + uniformOffset;
- for (int i = 0; i < count; ++i) {
- const float* matrix = &matrices[N * N * i];
- for (int j = 0; j < N; ++j) {
- memcpy(buffer, &matrix[j * N], N * sizeof(float));
- buffer = static_cast<char*>(buffer) + 4 * sizeof(float);
- }
- }
- }
-};
-
-template<> struct set_uniform_matrix<4> {
- inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) {
- static_assert(sizeof(float) == 4);
- buffer = static_cast<char*>(buffer) + uniformOffset;
- memcpy(buffer, matrices, count * 16 * sizeof(float));
- }
-};
-
bool GrVkPipelineStateDataManager::uploadUniformBuffers(GrVkGpu* gpu,
GrVkUniformBuffer* buffer) const {
bool updatedBuffer = false;
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.h b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.h
index 91d50924b68..b090dd6f56c 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkPipelineStateDataManager.h
@@ -8,78 +8,28 @@
#ifndef GrVkPipelineStateDataManager_DEFINED
#define GrVkPipelineStateDataManager_DEFINED
-#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
+#include "src/gpu/GrUniformDataManager.h"
#include "include/gpu/vk/GrVkTypes.h"
-#include "src/core/SkAutoMalloc.h"
#include "src/gpu/vk/GrVkUniformHandler.h"
class GrVkGpu;
class GrVkUniformBuffer;
-class GrVkPipelineStateDataManager : public GrGLSLProgramDataManager {
+class GrVkPipelineStateDataManager : public GrUniformDataManager {
public:
typedef GrVkUniformHandler::UniformInfoArray UniformInfoArray;
GrVkPipelineStateDataManager(const UniformInfoArray&,
uint32_t uniformSize);
- void set1i(UniformHandle, int32_t) const override;
- void set1iv(UniformHandle, int arrayCount, const int32_t v[]) const override;
- void set1f(UniformHandle, float v0) const override;
- void set1fv(UniformHandle, int arrayCount, const float v[]) const override;
- void set2i(UniformHandle, int32_t, int32_t) const override;
- void set2iv(UniformHandle, int arrayCount, const int32_t v[]) const override;
- void set2f(UniformHandle, float, float) const override;
- void set2fv(UniformHandle, int arrayCount, const float v[]) const override;
- void set3i(UniformHandle, int32_t, int32_t, int32_t) const override;
- void set3iv(UniformHandle, int arrayCount, const int32_t v[]) const override;
- void set3f(UniformHandle, float, float, float) const override;
- void set3fv(UniformHandle, int arrayCount, const float v[]) const override;
- void set4i(UniformHandle, int32_t, int32_t, int32_t, int32_t) const override;
- void set4iv(UniformHandle, int arrayCount, const int32_t v[]) const override;
- void set4f(UniformHandle, float, float, float, float) const override;
- void set4fv(UniformHandle, int arrayCount, const float v[]) const override;
- // matrices are column-major, the first two upload a single matrix, the latter two upload
- // arrayCount matrices into a uniform array.
- void setMatrix2f(UniformHandle, const float matrix[]) const override;
- void setMatrix3f(UniformHandle, const float matrix[]) const override;
- void setMatrix4f(UniformHandle, const float matrix[]) const override;
- void setMatrix2fv(UniformHandle, int arrayCount, const float matrices[]) const override;
- void setMatrix3fv(UniformHandle, int arrayCount, const float matrices[]) const override;
- void setMatrix4fv(UniformHandle, int arrayCount, const float matrices[]) const override;
-
- // for nvpr only
- void setPathFragmentInputTransform(VaryingHandle u, int components,
- const SkMatrix& matrix) const override {
- SK_ABORT("Only supported in NVPR, which is not in vulkan");
- }
-
// Returns true if either the geometry or fragment buffers needed to generate a new underlying
// VkBuffer object in order upload data. If true is returned, this is a signal to the caller
// that they will need to update the descriptor set that is using these buffers.
bool uploadUniformBuffers(GrVkGpu* gpu,
GrVkUniformBuffer* buffer) const;
private:
- struct Uniform {
- uint32_t fOffset;
- SkDEBUGCODE(
- GrSLType fType;
- int fArrayCount;
- );
- };
-
- template<int N> inline void setMatrices(UniformHandle, int arrayCount,
- const float matrices[]) const;
-
- void* getBufferPtrAndMarkDirty(const Uniform& uni) const;
-
- uint32_t fUniformSize;
-
- SkTArray<Uniform, true> fUniforms;
-
- mutable SkAutoMalloc fUniformData;
- mutable bool fUniformsDirty;
+ typedef GrUniformDataManager INHERITED;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.cpp
index 627eb2253e2..281983f8451 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.cpp
@@ -234,7 +234,7 @@ bool GrVkRenderPass::isCompatible(const GrVkRenderTarget& target) const {
AttachmentsDescriptor desc;
AttachmentFlags flags;
- target.getAttachmentsDescriptor(&desc, &flags);
+ target.getAttachmentsDescriptor(&desc, &flags, this->hasStencilAttachment());
return this->isCompatible(desc, flags);
}
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.h b/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.h
index 8b8c641b18b..5009e1ec3bb 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkRenderPass.h
@@ -94,6 +94,7 @@ public:
// index value.
bool colorAttachmentIndex(uint32_t* index) const;
bool stencilAttachmentIndex(uint32_t* index) const;
+ bool hasStencilAttachment() const { return fAttachmentFlags & kStencil_AttachmentFlag; }
// Returns whether or not the structure of a RenderTarget matches that of the VkRenderPass in
// this object. Specifically this compares that the number of attachments, format of
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.cpp
index 3021298c700..c2afefc6a17 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.cpp
@@ -26,21 +26,23 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
SkISize dimensions,
int sampleCnt,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageInfo& msaaInfo,
- sk_sp<GrVkImageLayout> msaaLayout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState,
const GrVkImageView* colorAttachmentView,
const GrVkImageView* resolveAttachmentView)
: GrSurface(gpu, dimensions, info.fProtected)
- , GrVkImage(gpu, info, std::move(layout), GrBackendObjectOwnership::kBorrowed)
+ , GrVkImage(gpu, info, std::move(mutableState), GrBackendObjectOwnership::kBorrowed)
// for the moment we only support 1:1 color to stencil
, GrRenderTarget(gpu, dimensions, sampleCnt, info.fProtected)
, fColorAttachmentView(colorAttachmentView)
- , fMSAAImage(new GrVkImage(gpu, msaaInfo, std::move(msaaLayout),
+ , fMSAAImage(new GrVkImage(gpu, msaaInfo, std::move(msaaMutableState),
GrBackendObjectOwnership::kOwned))
, fResolveAttachmentView(resolveAttachmentView)
, fCachedFramebuffer(nullptr)
- , fCachedSimpleRenderPass(nullptr) {
+ , fCachedStencilFramebuffer(nullptr)
+ , fCachedSimpleRenderPass(nullptr)
+ , fCachedStencilRenderPass(nullptr) {
SkASSERT(info.fProtected == msaaInfo.fProtected);
SkASSERT(sampleCnt > 1);
this->registerWithCacheWrapped(GrWrapCacheable::kNo);
@@ -52,22 +54,24 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
SkISize dimensions,
int sampleCnt,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageInfo& msaaInfo,
- sk_sp<GrVkImageLayout> msaaLayout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState,
const GrVkImageView* colorAttachmentView,
const GrVkImageView* resolveAttachmentView,
GrBackendObjectOwnership ownership)
: GrSurface(gpu, dimensions, info.fProtected)
- , GrVkImage(gpu, info, std::move(layout), ownership)
+ , GrVkImage(gpu, info, std::move(mutableState), ownership)
// for the moment we only support 1:1 color to stencil
, GrRenderTarget(gpu, dimensions, sampleCnt, info.fProtected)
, fColorAttachmentView(colorAttachmentView)
- , fMSAAImage(new GrVkImage(gpu, msaaInfo, std::move(msaaLayout),
+ , fMSAAImage(new GrVkImage(gpu, msaaInfo, std::move(msaaMutableState),
GrBackendObjectOwnership::kOwned))
, fResolveAttachmentView(resolveAttachmentView)
, fCachedFramebuffer(nullptr)
- , fCachedSimpleRenderPass(nullptr) {
+ , fCachedStencilFramebuffer(nullptr)
+ , fCachedSimpleRenderPass(nullptr)
+ , fCachedStencilRenderPass(nullptr) {
SkASSERT(info.fProtected == msaaInfo.fProtected);
SkASSERT(sampleCnt > 1);
}
@@ -77,16 +81,18 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
SkISize dimensions,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageView* colorAttachmentView)
: GrSurface(gpu, dimensions, info.fProtected)
- , GrVkImage(gpu, info, std::move(layout), GrBackendObjectOwnership::kBorrowed)
+ , GrVkImage(gpu, info, std::move(mutableState), GrBackendObjectOwnership::kBorrowed)
, GrRenderTarget(gpu, dimensions, 1, info.fProtected)
, fColorAttachmentView(colorAttachmentView)
, fMSAAImage(nullptr)
, fResolveAttachmentView(nullptr)
, fCachedFramebuffer(nullptr)
- , fCachedSimpleRenderPass(nullptr) {
+ , fCachedStencilFramebuffer(nullptr)
+ , fCachedSimpleRenderPass(nullptr)
+ , fCachedStencilRenderPass(nullptr) {
this->registerWithCacheWrapped(GrWrapCacheable::kNo);
}
@@ -95,42 +101,44 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
SkISize dimensions,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageView* colorAttachmentView,
GrBackendObjectOwnership ownership)
: GrSurface(gpu, dimensions, info.fProtected)
- , GrVkImage(gpu, info, std::move(layout), ownership)
+ , GrVkImage(gpu, info, std::move(mutableState), ownership)
, GrRenderTarget(gpu, dimensions, 1, info.fProtected)
, fColorAttachmentView(colorAttachmentView)
, fMSAAImage(nullptr)
, fResolveAttachmentView(nullptr)
, fCachedFramebuffer(nullptr)
- , fCachedSimpleRenderPass(nullptr) {}
+ , fCachedStencilFramebuffer(nullptr)
+ , fCachedSimpleRenderPass(nullptr)
+ , fCachedStencilRenderPass(nullptr) {}
GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
SkISize dimensions,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkRenderPass* renderPass,
VkCommandBuffer secondaryCommandBuffer)
: GrSurface(gpu, dimensions, info.fProtected)
- , GrVkImage(gpu, info, std::move(layout), GrBackendObjectOwnership::kBorrowed, true)
+ , GrVkImage(gpu, info, std::move(mutableState), GrBackendObjectOwnership::kBorrowed, true)
, GrRenderTarget(gpu, dimensions, 1, info.fProtected)
, fColorAttachmentView(nullptr)
, fMSAAImage(nullptr)
, fResolveAttachmentView(nullptr)
, fCachedFramebuffer(nullptr)
+ , fCachedStencilFramebuffer(nullptr)
, fCachedSimpleRenderPass(renderPass)
+ , fCachedStencilRenderPass(nullptr)
, fSecondaryCommandBuffer(secondaryCommandBuffer) {
SkASSERT(fSecondaryCommandBuffer != VK_NULL_HANDLE);
this->registerWithCacheWrapped(GrWrapCacheable::kNo);
}
-sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(GrVkGpu* gpu,
- SkISize dimensions,
- int sampleCnt,
- const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout) {
+sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(
+ GrVkGpu* gpu, SkISize dimensions, int sampleCnt, const GrVkImageInfo& info,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState) {
SkASSERT(VK_NULL_HANDLE != info.fImage);
SkASSERT(1 == info.fLevelCount);
@@ -140,7 +148,7 @@ sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(GrVkGpu* gpu,
// create msaa surface if necessary
GrVkImageInfo msInfo;
- sk_sp<GrVkImageLayout> msLayout;
+ sk_sp<GrBackendSurfaceMutableStateImpl> msMutableState;
const GrVkImageView* resolveAttachmentView = nullptr;
if (sampleCnt > 1) {
GrVkImage::ImageDesc msImageDesc;
@@ -172,7 +180,8 @@ sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(GrVkGpu* gpu,
GrVkImage::DestroyImageInfo(gpu, &msInfo);
return nullptr;
}
- msLayout.reset(new GrVkImageLayout(msInfo.fImageLayout));
+ msMutableState.reset(new GrBackendSurfaceMutableStateImpl(msInfo.fImageLayout,
+ msInfo.fCurrentQueueFamily));
} else {
// Set color attachment image
colorImage = info.fImage;
@@ -192,11 +201,12 @@ sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(GrVkGpu* gpu,
GrVkRenderTarget* vkRT;
if (sampleCnt > 1) {
- vkRT = new GrVkRenderTarget(gpu, dimensions, sampleCnt, info, std::move(layout), msInfo,
- std::move(msLayout), colorAttachmentView,
+ vkRT = new GrVkRenderTarget(gpu, dimensions, sampleCnt, info, std::move(mutableState),
+ msInfo, std::move(msMutableState), colorAttachmentView,
resolveAttachmentView);
} else {
- vkRT = new GrVkRenderTarget(gpu, dimensions, info, std::move(layout), colorAttachmentView);
+ vkRT = new GrVkRenderTarget(gpu, dimensions, info, std::move(mutableState),
+ colorAttachmentView);
}
return sk_sp<GrVkRenderTarget>(vkRT);
@@ -204,14 +214,6 @@ sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(GrVkGpu* gpu,
sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeSecondaryCBRenderTarget(
GrVkGpu* gpu, SkISize dimensions, const GrVkDrawableInfo& vkInfo) {
- // We only set the few properties of the GrVkImageInfo that we know like layout and format. The
- // others we keep at the default "null" values.
- GrVkImageInfo info;
- info.fImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- info.fFormat = vkInfo.fFormat;
-
- sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
-
const GrVkRenderPass* rp =
gpu->resourceProvider().findCompatibleExternalRenderPass(vkInfo.fCompatibleRenderPass,
vkInfo.fColorAttachmentIndex);
@@ -223,78 +225,108 @@ sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeSecondaryCBRenderTarget(
return nullptr;
}
- GrVkRenderTarget* vkRT = new GrVkRenderTarget(gpu, dimensions, info, std::move(layout), rp,
- vkInfo.fSecondaryCommandBuffer);
+ // We only set the few properties of the GrVkImageInfo that we know like layout and format. The
+ // others we keep at the default "null" values.
+ GrVkImageInfo info;
+ info.fImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ info.fFormat = vkInfo.fFormat;
+
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState(new GrBackendSurfaceMutableStateImpl(
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_IGNORED));
+
+ GrVkRenderTarget* vkRT = new GrVkRenderTarget(gpu, dimensions, info, std::move(mutableState),
+ rp, vkInfo.fSecondaryCommandBuffer);
return sk_sp<GrVkRenderTarget>(vkRT);
}
bool GrVkRenderTarget::completeStencilAttachment() {
SkASSERT(!this->wrapsSecondaryCommandBuffer());
- // If we have a previous renderpass or framebuffer it will have been made without stencil, so
- // we set it to null to trigger creating a new one the next time we need it.
- if (fCachedSimpleRenderPass) {
- fCachedSimpleRenderPass->unref();
- fCachedSimpleRenderPass = nullptr;
- }
- if (fCachedFramebuffer) {
- fCachedFramebuffer->unref();
- fCachedFramebuffer = nullptr;
- }
- fCompatibleRPHandle = GrVkResourceProvider::CompatibleRPHandle();
return true;
}
-const GrVkRenderPass* GrVkRenderTarget::getSimpleRenderPass() {
- if (fCachedSimpleRenderPass) {
- return fCachedSimpleRenderPass;
+const GrVkRenderPass* GrVkRenderTarget::getSimpleRenderPass(bool withStencil) {
+ if (withStencil) {
+ if (fCachedStencilRenderPass) {
+ return fCachedStencilRenderPass;
+ }
+ } else {
+ if (fCachedSimpleRenderPass) {
+ return fCachedSimpleRenderPass;
+ }
}
- return this->createSimpleRenderPass();
+
+ return this->createSimpleRenderPass(withStencil);
}
-const GrVkRenderPass* GrVkRenderTarget::createSimpleRenderPass() {
+const GrVkRenderPass* GrVkRenderTarget::createSimpleRenderPass(bool withStencil) {
SkASSERT(!this->wrapsSecondaryCommandBuffer());
- SkASSERT(!fCachedSimpleRenderPass);
- fCachedSimpleRenderPass =
- this->getVkGpu()->resourceProvider().findCompatibleRenderPass(*this, &fCompatibleRPHandle);
- return fCachedSimpleRenderPass;
+ GrVkResourceProvider& rp = this->getVkGpu()->resourceProvider();
+ if (withStencil) {
+ SkASSERT(!fCachedStencilRenderPass);
+ fCachedStencilRenderPass = rp.findCompatibleRenderPass(*this, &fCompatibleStencilRPHandle,
+ withStencil);
+ return fCachedStencilRenderPass;
+ } else {
+ SkASSERT(!fCachedSimpleRenderPass);
+ fCachedSimpleRenderPass = rp.findCompatibleRenderPass(*this, &fCompatibleRPHandle,
+ withStencil);
+ return fCachedSimpleRenderPass;
+ }
}
-const GrVkFramebuffer* GrVkRenderTarget::getFramebuffer() {
- if (fCachedFramebuffer) {
- return fCachedFramebuffer;
+const GrVkFramebuffer* GrVkRenderTarget::getFramebuffer(bool withStencil) {
+ if (withStencil) {
+ if (fCachedStencilFramebuffer) {
+ return fCachedStencilFramebuffer;
+ }
+ } else {
+ if (fCachedFramebuffer) {
+ return fCachedFramebuffer;
+ }
}
- return this->createFramebuffer();
+ return this->createFramebuffer(withStencil);
}
-const GrVkFramebuffer* GrVkRenderTarget::createFramebuffer() {
+const GrVkFramebuffer* GrVkRenderTarget::createFramebuffer(bool withStencil) {
SkASSERT(!this->wrapsSecondaryCommandBuffer());
- SkASSERT(!fCachedFramebuffer);
-
GrVkGpu* gpu = this->getVkGpu();
- // Stencil attachment view is stored in the base RT stencil attachment
- const GrVkImageView* stencilView = this->stencilAttachmentView();
- const GrVkRenderPass* renderPass = this->getSimpleRenderPass();
+
+ const GrVkRenderPass* renderPass = this->getSimpleRenderPass(withStencil);
if (!renderPass) {
return nullptr;
}
- fCachedFramebuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(), renderPass,
- fColorAttachmentView, stencilView);
- return fCachedFramebuffer;
+
+ // Stencil attachment view is stored in the base RT stencil attachment
+ const GrVkImageView* stencilView = withStencil ? this->stencilAttachmentView() : nullptr;
+ GrVkFramebuffer* frameBuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(),
+ renderPass, fColorAttachmentView,
+ stencilView);
+
+ if (withStencil) {
+ SkASSERT(!fCachedStencilFramebuffer);
+ fCachedStencilFramebuffer = frameBuffer;
+ } else {
+ SkASSERT(!fCachedFramebuffer);
+ fCachedFramebuffer = frameBuffer;
+ }
+
+ return frameBuffer;
}
-void GrVkRenderTarget::getAttachmentsDescriptor(
- GrVkRenderPass::AttachmentsDescriptor* desc,
- GrVkRenderPass::AttachmentFlags* attachmentFlags) const {
+void GrVkRenderTarget::getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor* desc,
+ GrVkRenderPass::AttachmentFlags* attachmentFlags,
+ bool withStencil) const {
SkASSERT(!this->wrapsSecondaryCommandBuffer());
desc->fColor.fFormat = this->imageFormat();
desc->fColor.fSamples = this->numSamples();
*attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
uint32_t attachmentCount = 1;
- const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
- if (stencil) {
+ if (withStencil) {
+ const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
+ SkASSERT(stencil);
const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
desc->fStencil.fFormat = vkStencil->imageFormat();
desc->fStencil.fSamples = vkStencil->numSamples();
@@ -317,11 +349,13 @@ GrVkRenderTarget::~GrVkRenderTarget() {
SkASSERT(!fResolveAttachmentView);
SkASSERT(!fColorAttachmentView);
SkASSERT(!fCachedFramebuffer);
+ SkASSERT(!fCachedStencilFramebuffer);
SkASSERT(!fCachedSimpleRenderPass);
+ SkASSERT(!fCachedStencilRenderPass);
}
-void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) {
- commandBuffer.addResource(this->getFramebuffer());
+void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer, bool withStencil) {
+ commandBuffer.addResource(this->getFramebuffer(withStencil));
commandBuffer.addResource(this->colorAttachmentView());
commandBuffer.addResource(this->msaaImageResource() ? this->msaaImageResource()
: this->resource());
@@ -332,10 +366,8 @@ void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) {
}
void GrVkRenderTarget::releaseInternalObjects() {
- GrVkGpu* gpu = this->getVkGpu();
-
if (fMSAAImage) {
- fMSAAImage->releaseImage(gpu);
+ fMSAAImage->releaseImage();
fMSAAImage.reset();
}
@@ -351,10 +383,18 @@ void GrVkRenderTarget::releaseInternalObjects() {
fCachedFramebuffer->unref();
fCachedFramebuffer = nullptr;
}
+ if (fCachedStencilFramebuffer) {
+ fCachedStencilFramebuffer->unref();
+ fCachedStencilFramebuffer = nullptr;
+ }
if (fCachedSimpleRenderPass) {
fCachedSimpleRenderPass->unref();
fCachedSimpleRenderPass = nullptr;
}
+ if (fCachedStencilRenderPass) {
+ fCachedStencilRenderPass->unref();
+ fCachedStencilRenderPass = nullptr;
+ }
for (int i = 0; i < fGrSecondaryCommandBuffers.count(); ++i) {
SkASSERT(fGrSecondaryCommandBuffers[i]);
fGrSecondaryCommandBuffers[i]->releaseResources();
@@ -364,20 +404,20 @@ void GrVkRenderTarget::releaseInternalObjects() {
void GrVkRenderTarget::onRelease() {
this->releaseInternalObjects();
- this->releaseImage(this->getVkGpu());
+ this->releaseImage();
GrRenderTarget::onRelease();
}
void GrVkRenderTarget::onAbandon() {
this->releaseInternalObjects();
- this->releaseImage(this->getVkGpu());
+ this->releaseImage();
GrRenderTarget::onAbandon();
}
GrBackendRenderTarget GrVkRenderTarget::getBackendRenderTarget() const {
SkASSERT(!this->wrapsSecondaryCommandBuffer());
return GrBackendRenderTarget(this->width(), this->height(), this->numSamples(), fInfo,
- this->grVkImageLayout());
+ this->getMutableState());
}
const GrManagedResource* GrVkRenderTarget::stencilImageResource() const {
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.h b/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.h
index daae1a04a7d..94ad40f353b 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkRenderTarget.h
@@ -34,7 +34,7 @@ class GrVkRenderTarget: public GrRenderTarget, public virtual GrVkImage {
public:
static sk_sp<GrVkRenderTarget> MakeWrappedRenderTarget(GrVkGpu*, SkISize, int sampleCnt,
const GrVkImageInfo&,
- sk_sp<GrVkImageLayout>);
+ sk_sp<GrBackendSurfaceMutableStateImpl>);
static sk_sp<GrVkRenderTarget> MakeSecondaryCBRenderTarget(GrVkGpu*, SkISize,
const GrVkDrawableInfo& vkInfo);
@@ -43,7 +43,7 @@ public:
GrBackendFormat backendFormat() const override { return this->getBackendFormat(); }
- const GrVkFramebuffer* getFramebuffer();
+ const GrVkFramebuffer* getFramebuffer(bool withStencil);
const GrVkImageView* colorAttachmentView() const { return fColorAttachmentView; }
const GrManagedResource* msaaImageResource() const {
if (fMSAAImage) {
@@ -56,15 +56,26 @@ public:
const GrManagedResource* stencilImageResource() const;
const GrVkImageView* stencilAttachmentView() const;
- const GrVkRenderPass* getSimpleRenderPass();
- GrVkResourceProvider::CompatibleRPHandle compatibleRenderPassHandle() {
+ const GrVkRenderPass* getSimpleRenderPass(bool withStencil);
+ GrVkResourceProvider::CompatibleRPHandle compatibleRenderPassHandle(bool withStencil) {
SkASSERT(!this->wrapsSecondaryCommandBuffer());
- if (!fCompatibleRPHandle.isValid()) {
- SkASSERT(!fCachedSimpleRenderPass);
- this->createSimpleRenderPass();
+
+ auto pRPHandle = withStencil ? &fCompatibleStencilRPHandle : &fCompatibleRPHandle;
+ if (!pRPHandle->isValid()) {
+ this->createSimpleRenderPass(withStencil);
+ }
+
+#ifdef SK_DEBUG
+ if (withStencil) {
+ SkASSERT(pRPHandle->isValid() == SkToBool(fCachedStencilRenderPass));
+ SkASSERT(fCachedStencilRenderPass->hasStencilAttachment());
+ } else {
+ SkASSERT(pRPHandle->isValid() == SkToBool(fCachedSimpleRenderPass));
+ SkASSERT(!fCachedSimpleRenderPass->hasStencilAttachment());
}
- SkASSERT(fCompatibleRPHandle.isValid() == SkToBool(fCachedSimpleRenderPass));
- return fCompatibleRPHandle;
+#endif
+
+ return *pRPHandle;
}
const GrVkRenderPass* externalRenderPass() const {
SkASSERT(this->wrapsSecondaryCommandBuffer());
@@ -86,9 +97,10 @@ public:
GrBackendRenderTarget getBackendRenderTarget() const override;
void getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor* desc,
- GrVkRenderPass::AttachmentFlags* flags) const;
+ GrVkRenderPass::AttachmentFlags* flags,
+ bool withStencil) const;
- void addResources(GrVkCommandBuffer& commandBuffer);
+ void addResources(GrVkCommandBuffer& commandBuffer, bool withStencil);
void addWrappedGrSecondaryCommandBuffer(std::unique_ptr<GrVkSecondaryCommandBuffer> cmdBuffer) {
fGrSecondaryCommandBuffers.push_back(std::move(cmdBuffer));
@@ -99,9 +111,9 @@ protected:
SkISize dimensions,
int sampleCnt,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageInfo& msaaInfo,
- sk_sp<GrVkImageLayout> msaaLayout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState,
const GrVkImageView* colorAttachmentView,
const GrVkImageView* resolveAttachmentView,
GrBackendObjectOwnership);
@@ -109,7 +121,7 @@ protected:
GrVkRenderTarget(GrVkGpu* gpu,
SkISize dimensions,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageView* colorAttachmentView,
GrBackendObjectOwnership);
@@ -133,29 +145,29 @@ private:
SkISize dimensions,
int sampleCnt,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageInfo& msaaInfo,
- sk_sp<GrVkImageLayout> msaaLayout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState,
const GrVkImageView* colorAttachmentView,
const GrVkImageView* resolveAttachmentView);
GrVkRenderTarget(GrVkGpu* gpu,
SkISize dimensions,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageView* colorAttachmentView);
GrVkRenderTarget(GrVkGpu* gpu,
SkISize dimensions,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkRenderPass* renderPass,
VkCommandBuffer secondaryCommandBuffer);
GrVkGpu* getVkGpu() const;
- const GrVkRenderPass* createSimpleRenderPass();
- const GrVkFramebuffer* createFramebuffer();
+ const GrVkRenderPass* createSimpleRenderPass(bool withStencil);
+ const GrVkFramebuffer* createFramebuffer(bool withStencil);
bool completeStencilAttachment() override;
@@ -173,12 +185,18 @@ private:
const GrVkImageView* fResolveAttachmentView;
const GrVkFramebuffer* fCachedFramebuffer;
+ const GrVkFramebuffer* fCachedStencilFramebuffer;
- // This is a cached pointer to a simple render pass. The render target should unref it
- // once it is done with it.
+ // Cached pointers to a simple and stencil render passes. The render target should unref them
+ // once it is done with them.
const GrVkRenderPass* fCachedSimpleRenderPass;
- // This is a handle to be used to quickly get compatible GrVkRenderPasses for this render target
+ const GrVkRenderPass* fCachedStencilRenderPass;
+
+ // This is a handle to be used to quickly get a GrVkRenderPass that is compatible with
+ // this render target if its stencil buffer is ignored.
GrVkResourceProvider::CompatibleRPHandle fCompatibleRPHandle;
+ // Same as above but taking the render target's stencil buffer into account
+ GrVkResourceProvider::CompatibleRPHandle fCompatibleStencilRPHandle;
// If this render target wraps an external VkCommandBuffer, then this handle will be that
// VkCommandBuffer and not VK_NULL_HANDLE. In this case the render target will not be backed by
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.cpp
index 017310a8419..e5c2785335b 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.cpp
@@ -102,12 +102,13 @@ GrVkPipeline* GrVkResourceProvider::createPipeline(const GrProgramInfo& programI
// RenderPasses as needed that are compatible with the framebuffer.
const GrVkRenderPass*
GrVkResourceProvider::findCompatibleRenderPass(const GrVkRenderTarget& target,
- CompatibleRPHandle* compatibleHandle) {
+ CompatibleRPHandle* compatibleHandle,
+ bool withStencil) {
// Get attachment information from render target. This includes which attachments the render
// target has (color, stencil) and the attachments format and sample count.
GrVkRenderPass::AttachmentFlags attachmentFlags;
GrVkRenderPass::AttachmentsDescriptor attachmentsDesc;
- target.getAttachmentsDescriptor(&attachmentsDesc, &attachmentFlags);
+ target.getAttachmentsDescriptor(&attachmentsDesc, &attachmentFlags, withStencil);
return this->findCompatibleRenderPass(&attachmentsDesc, attachmentFlags, compatibleHandle);
}
@@ -164,11 +165,12 @@ const GrVkRenderPass* GrVkResourceProvider::findRenderPass(
GrVkRenderTarget* target,
const GrVkRenderPass::LoadStoreOps& colorOps,
const GrVkRenderPass::LoadStoreOps& stencilOps,
- CompatibleRPHandle* compatibleHandle) {
+ CompatibleRPHandle* compatibleHandle,
+ bool withStencil) {
GrVkResourceProvider::CompatibleRPHandle tempRPHandle;
GrVkResourceProvider::CompatibleRPHandle* pRPHandle = compatibleHandle ? compatibleHandle
: &tempRPHandle;
- *pRPHandle = target->compatibleRenderPassHandle();
+ *pRPHandle = target->compatibleRenderPassHandle(withStencil);
if (!pRPHandle->isValid()) {
return nullptr;
}
@@ -363,12 +365,11 @@ void GrVkResourceProvider::checkCommandBuffers() {
}
void GrVkResourceProvider::addFinishedProcToActiveCommandBuffers(
- GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) {
- sk_sp<GrRefCntedCallback> procRef(new GrRefCntedCallback(finishedProc, finishedContext));
+ sk_sp<GrRefCntedCallback> finishedCallback) {
for (int i = 0; i < fActiveCommandPools.count(); ++i) {
GrVkCommandPool* pool = fActiveCommandPools[i];
GrVkPrimaryCommandBuffer* buffer = pool->getPrimaryCommandBuffer();
- buffer->addFinishedProc(procRef);
+ buffer->addFinishedProc(finishedCallback);
}
}
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.h b/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.h
index d4ef8632aef..a3d72cf8b98 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkResourceProvider.h
@@ -57,7 +57,8 @@ public:
// non null it will be set to a handle that can be used in the furutre to quickly return a
// compatible GrVkRenderPasses without the need inspecting a GrVkRenderTarget.
const GrVkRenderPass* findCompatibleRenderPass(const GrVkRenderTarget& target,
- CompatibleRPHandle* compatibleHandle = nullptr);
+ CompatibleRPHandle* compatibleHandle,
+ bool withStencil);
const GrVkRenderPass* findCompatibleRenderPass(GrVkRenderPass::AttachmentsDescriptor*,
GrVkRenderPass::AttachmentFlags,
CompatibleRPHandle* compatibleHandle = nullptr);
@@ -73,7 +74,8 @@ public:
const GrVkRenderPass* findRenderPass(GrVkRenderTarget* target,
const GrVkRenderPass::LoadStoreOps& colorOps,
const GrVkRenderPass::LoadStoreOps& stencilOps,
- CompatibleRPHandle* compatibleHandle = nullptr);
+ CompatibleRPHandle* compatibleHandle,
+ bool withStencil);
// The CompatibleRPHandle must be a valid handle previously set by a call to findRenderPass or
// findCompatibleRenderPass.
@@ -89,8 +91,7 @@ public:
// that the client cares about before they explicitly called flush and the GPU may reorder
// command execution. So we make sure all previously submitted work finishes before we call the
// finishedProc.
- void addFinishedProcToActiveCommandBuffers(GrGpuFinishedProc finishedProc,
- GrGpuFinishedContext finishedContext);
+ void addFinishedProcToActiveCommandBuffers(sk_sp<GrRefCntedCallback> finishedCallback);
// Finds or creates a compatible GrVkDescriptorPool for the requested type and count.
// The refcount is incremented and a pointer returned.
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.h b/chromium/third_party/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.h
index 05c10b848ba..829129841ff 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.h
@@ -23,7 +23,7 @@ public:
struct Key {
Key() : fVkFormat(VK_FORMAT_UNDEFINED), fExternalFormat(0), fConversionKey(0) {}
- Key(VkFormat vkFormat, uint64_t externalFormat, uint8_t conversionKey) {
+ Key(VkFormat vkFormat, int64_t externalFormat, uint8_t conversionKey) {
memset(this, 0, sizeof(Key));
fVkFormat = vkFormat;
fExternalFormat = externalFormat;
@@ -31,7 +31,7 @@ public:
}
VkFormat fVkFormat;
- uint64_t fExternalFormat;
+ int64_t fExternalFormat;
uint8_t fConversionKey;
bool operator==(const Key& that) const {
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkSemaphore.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkSemaphore.cpp
index ee68cdd68a3..23bf656bf86 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkSemaphore.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkSemaphore.cpp
@@ -38,6 +38,7 @@ std::unique_ptr<GrVkSemaphore> GrVkSemaphore::MakeWrapped(GrVkGpu* gpu,
WrapType wrapType,
GrWrapOwnership ownership) {
if (VK_NULL_HANDLE == semaphore) {
+ SkDEBUGFAIL("Trying to wrap an invalid VkSemaphore");
return nullptr;
}
bool prohibitSignal = WrapType::kWillWait == wrapType;
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.cpp
index 3236ac2a0b8..63a90ddb647 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.cpp
@@ -17,10 +17,10 @@ GrVkStencilAttachment::GrVkStencilAttachment(GrVkGpu* gpu,
const Format& format,
const GrVkImage::ImageDesc& desc,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageView* stencilView)
: GrStencilAttachment(gpu, desc.fWidth, desc.fHeight, format.fStencilBits, desc.fSamples)
- , GrVkImage(gpu, info, std::move(layout), GrBackendObjectOwnership::kOwned)
+ , GrVkImage(gpu, info, std::move(mutableState), GrBackendObjectOwnership::kOwned)
, fStencilView(stencilView) {
this->registerWithCache(SkBudgeted::kYes);
stencilView->ref();
@@ -57,9 +57,11 @@ GrVkStencilAttachment* GrVkStencilAttachment::Create(GrVkGpu* gpu,
return nullptr;
}
- sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(info.fImageLayout));
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState(new GrBackendSurfaceMutableStateImpl(
+ info.fImageLayout, info.fCurrentQueueFamily));
GrVkStencilAttachment* stencil = new GrVkStencilAttachment(gpu, format, imageDesc,
- info, std::move(layout), imageView);
+ info, std::move(mutableState),
+ imageView);
imageView->unref();
return stencil;
@@ -79,8 +81,7 @@ size_t GrVkStencilAttachment::onGpuMemorySize() const {
}
void GrVkStencilAttachment::onRelease() {
- GrVkGpu* gpu = this->getVkGpu();
- this->releaseImage(gpu);
+ this->releaseImage();
fStencilView->unref();
fStencilView = nullptr;
@@ -88,8 +89,7 @@ void GrVkStencilAttachment::onRelease() {
}
void GrVkStencilAttachment::onAbandon() {
- GrVkGpu* gpu = this->getVkGpu();
- this->releaseImage(gpu);
+ this->releaseImage();
fStencilView->unref();
fStencilView = nullptr;
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.h b/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.h
index 8accd289fa4..ad96fae5178 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkStencilAttachment.h
@@ -41,7 +41,7 @@ private:
const Format& format,
const GrVkImage::ImageDesc&,
const GrVkImageInfo&,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageView* stencilView);
GrVkGpu* getVkGpu() const;
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkTexture.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkTexture.cpp
index ce3f49a0dd1..c930a288a59 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkTexture.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkTexture.cpp
@@ -23,11 +23,11 @@ GrVkTexture::GrVkTexture(GrVkGpu* gpu,
SkBudgeted budgeted,
SkISize dimensions,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageView* view,
GrMipMapsStatus mipMapsStatus)
: GrSurface(gpu, dimensions, info.fProtected)
- , GrVkImage(gpu, info, std::move(layout), GrBackendObjectOwnership::kOwned)
+ , GrVkImage(gpu, info, std::move(mutableState), GrBackendObjectOwnership::kOwned)
, INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus)
, fTextureView(view)
, fDescSetCache(kMaxCachedDescSets) {
@@ -41,11 +41,12 @@ GrVkTexture::GrVkTexture(GrVkGpu* gpu,
}
GrVkTexture::GrVkTexture(GrVkGpu* gpu, SkISize dimensions, const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout, const GrVkImageView* view,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
+ const GrVkImageView* view,
GrMipMapsStatus mipMapsStatus, GrBackendObjectOwnership ownership,
GrWrapCacheable cacheable, GrIOType ioType, bool isExternal)
: GrSurface(gpu, dimensions, info.fProtected)
- , GrVkImage(gpu, info, std::move(layout), ownership)
+ , GrVkImage(gpu, info, std::move(mutableState), ownership)
, INHERITED(gpu, dimensions, info.fProtected,
isExternal ? GrTextureType::kExternal : GrTextureType::k2D, mipMapsStatus)
, fTextureView(view)
@@ -61,12 +62,12 @@ GrVkTexture::GrVkTexture(GrVkGpu* gpu, SkISize dimensions, const GrVkImageInfo&
GrVkTexture::GrVkTexture(GrVkGpu* gpu,
SkISize dimensions,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageView* view,
GrMipMapsStatus mipMapsStatus,
GrBackendObjectOwnership ownership)
: GrSurface(gpu, dimensions, info.fProtected)
- , GrVkImage(gpu, info, layout, ownership)
+ , GrVkImage(gpu, info, std::move(mutableState), ownership)
, INHERITED(gpu, dimensions, info.fProtected, GrTextureType::k2D, mipMapsStatus)
, fTextureView(view)
, fDescSetCache(kMaxCachedDescSets) {
@@ -94,19 +95,16 @@ sk_sp<GrVkTexture> GrVkTexture::MakeNewTexture(GrVkGpu* gpu, SkBudgeted budgeted
GrVkImage::DestroyImageInfo(gpu, &info);
return nullptr;
}
- sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(info.fImageLayout));
-
- return sk_sp<GrVkTexture>(new GrVkTexture(gpu, budgeted, dimensions, info, std::move(layout),
- imageView, mipMapsStatus));
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState(
+ new GrBackendSurfaceMutableStateImpl(info.fImageLayout, info.fCurrentQueueFamily));
+ return sk_sp<GrVkTexture>(new GrVkTexture(gpu, budgeted, dimensions, info,
+ std::move(mutableState), imageView, mipMapsStatus));
}
-sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu,
- SkISize dimensions,
- GrWrapOwnership wrapOwnership,
- GrWrapCacheable cacheable,
- GrIOType ioType,
- const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout) {
+sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(
+ GrVkGpu* gpu, SkISize dimensions, GrWrapOwnership wrapOwnership, GrWrapCacheable cacheable,
+ GrIOType ioType, const GrVkImageInfo& info,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState) {
// Adopted textures require both image and allocation because we're responsible for freeing
SkASSERT(VK_NULL_HANDLE != info.fImage &&
(kBorrow_GrWrapOwnership == wrapOwnership || VK_NULL_HANDLE != info.fAlloc.fMemory));
@@ -125,9 +123,9 @@ sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu,
? GrBackendObjectOwnership::kBorrowed : GrBackendObjectOwnership::kOwned;
bool isExternal = info.fYcbcrConversionInfo.isValid() &&
(info.fYcbcrConversionInfo.fExternalFormat != 0);
- return sk_sp<GrVkTexture>(new GrVkTexture(gpu, dimensions, info, std::move(layout), imageView,
- mipMapsStatus, ownership, cacheable, ioType,
- isExternal));
+ return sk_sp<GrVkTexture>(new GrVkTexture(gpu, dimensions, info, std::move(mutableState),
+ imageView, mipMapsStatus, ownership, cacheable,
+ ioType, isExternal));
}
GrVkTexture::~GrVkTexture() {
@@ -151,7 +149,7 @@ void GrVkTexture::onRelease() {
fDescSetCache.reset();
- this->releaseImage(this->getVkGpu());
+ this->releaseImage();
INHERITED::onRelease();
}
@@ -185,12 +183,12 @@ void GrVkTexture::onAbandon() {
fDescSetCache.reset();
- this->releaseImage(this->getVkGpu());
+ this->releaseImage();
INHERITED::onAbandon();
}
GrBackendTexture GrVkTexture::getBackendTexture() const {
- return GrBackendTexture(this->width(), this->height(), fInfo, this->grVkImageLayout());
+ return GrBackendTexture(this->width(), this->height(), fInfo, this->getMutableState());
}
GrVkGpu* GrVkTexture::getVkGpu() const {
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkTexture.h b/chromium/third_party/skia/src/gpu/vk/GrVkTexture.h
index 6a13f5af3a0..d719ef16973 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkTexture.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkTexture.h
@@ -33,7 +33,7 @@ public:
GrWrapCacheable,
GrIOType,
const GrVkImageInfo&,
- sk_sp<GrVkImageLayout>);
+ sk_sp<GrBackendSurfaceMutableStateImpl>);
~GrVkTexture() override;
@@ -61,7 +61,7 @@ protected:
GrVkTexture(GrVkGpu*,
SkISize dimensions,
const GrVkImageInfo&,
- sk_sp<GrVkImageLayout>,
+ sk_sp<GrBackendSurfaceMutableStateImpl>,
const GrVkImageView*,
GrMipMapsStatus,
GrBackendObjectOwnership);
@@ -78,9 +78,10 @@ protected:
void willRemoveLastRef() override;
private:
- GrVkTexture(GrVkGpu*, SkBudgeted, SkISize, const GrVkImageInfo&, sk_sp<GrVkImageLayout> layout,
- const GrVkImageView* imageView, GrMipMapsStatus);
- GrVkTexture(GrVkGpu*, SkISize, const GrVkImageInfo&, sk_sp<GrVkImageLayout>,
+ GrVkTexture(GrVkGpu*, SkBudgeted, SkISize, const GrVkImageInfo&,
+ sk_sp<GrBackendSurfaceMutableStateImpl>, const GrVkImageView* imageView,
+ GrMipMapsStatus);
+ GrVkTexture(GrVkGpu*, SkISize, const GrVkImageInfo&, sk_sp<GrBackendSurfaceMutableStateImpl>,
const GrVkImageView*, GrMipMapsStatus, GrBackendObjectOwnership, GrWrapCacheable,
GrIOType, bool isExternal);
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.cpp
index 0ce652a4ba0..39d87d33bc0 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.cpp
@@ -18,82 +18,87 @@
#define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
-GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu,
- SkBudgeted budgeted,
- SkISize dimensions,
- int sampleCnt,
- const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
- const GrVkImageView* texView,
- const GrVkImageInfo& msaaInfo,
- sk_sp<GrVkImageLayout> msaaLayout,
- const GrVkImageView* colorAttachmentView,
- const GrVkImageView* resolveAttachmentView,
- GrMipMapsStatus mipMapsStatus)
+GrVkTextureRenderTarget::GrVkTextureRenderTarget(
+ GrVkGpu* gpu,
+ SkBudgeted budgeted,
+ SkISize dimensions,
+ int sampleCnt,
+ const GrVkImageInfo& info,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
+ const GrVkImageView* texView,
+ const GrVkImageInfo& msaaInfo,
+ sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState,
+ const GrVkImageView* colorAttachmentView,
+ const GrVkImageView* resolveAttachmentView,
+ GrMipMapsStatus mipMapsStatus)
: GrSurface(gpu, dimensions, info.fProtected)
- , GrVkImage(gpu, info, layout, GrBackendObjectOwnership::kOwned)
- , GrVkTexture(gpu, dimensions, info, layout, texView, mipMapsStatus,
+ , GrVkImage(gpu, info, mutableState, GrBackendObjectOwnership::kOwned)
+ , GrVkTexture(gpu, dimensions, info, mutableState, texView, mipMapsStatus,
GrBackendObjectOwnership::kOwned)
- , GrVkRenderTarget(gpu, dimensions, sampleCnt, info, layout, msaaInfo,
- std::move(msaaLayout), colorAttachmentView, resolveAttachmentView,
+ , GrVkRenderTarget(gpu, dimensions, sampleCnt, info, std::move(mutableState), msaaInfo,
+ std::move(msaaMutableState), colorAttachmentView, resolveAttachmentView,
GrBackendObjectOwnership::kOwned) {
SkASSERT(info.fProtected == msaaInfo.fProtected);
this->registerWithCache(budgeted);
}
-GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu,
- SkBudgeted budgeted,
- SkISize dimensions,
- const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
- const GrVkImageView* texView,
- const GrVkImageView* colorAttachmentView,
- GrMipMapsStatus mipMapsStatus)
+GrVkTextureRenderTarget::GrVkTextureRenderTarget(
+ GrVkGpu* gpu,
+ SkBudgeted budgeted,
+ SkISize dimensions,
+ const GrVkImageInfo& info,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
+ const GrVkImageView* texView,
+ const GrVkImageView* colorAttachmentView,
+ GrMipMapsStatus mipMapsStatus)
: GrSurface(gpu, dimensions, info.fProtected)
- , GrVkImage(gpu, info, layout, GrBackendObjectOwnership::kOwned)
- , GrVkTexture(gpu, dimensions, info, layout, texView, mipMapsStatus,
+ , GrVkImage(gpu, info, mutableState, GrBackendObjectOwnership::kOwned)
+ , GrVkTexture(gpu, dimensions, info, mutableState, texView, mipMapsStatus,
GrBackendObjectOwnership::kOwned)
- , GrVkRenderTarget(gpu, dimensions, info, layout, colorAttachmentView,
+ , GrVkRenderTarget(gpu, dimensions, info, std::move(mutableState), colorAttachmentView,
GrBackendObjectOwnership::kOwned) {
this->registerWithCache(budgeted);
}
-GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu,
- SkISize dimensions,
- int sampleCnt,
- const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
- const GrVkImageView* texView,
- const GrVkImageInfo& msaaInfo,
- sk_sp<GrVkImageLayout> msaaLayout,
- const GrVkImageView* colorAttachmentView,
- const GrVkImageView* resolveAttachmentView,
- GrMipMapsStatus mipMapsStatus,
- GrBackendObjectOwnership ownership,
- GrWrapCacheable cacheable)
+GrVkTextureRenderTarget::GrVkTextureRenderTarget(
+ GrVkGpu* gpu,
+ SkISize dimensions,
+ int sampleCnt,
+ const GrVkImageInfo& info,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
+ const GrVkImageView* texView,
+ const GrVkImageInfo& msaaInfo,
+ sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState,
+ const GrVkImageView* colorAttachmentView,
+ const GrVkImageView* resolveAttachmentView,
+ GrMipMapsStatus mipMapsStatus,
+ GrBackendObjectOwnership ownership,
+ GrWrapCacheable cacheable)
: GrSurface(gpu, dimensions, info.fProtected)
- , GrVkImage(gpu, info, layout, ownership)
- , GrVkTexture(gpu, dimensions, info, layout, texView, mipMapsStatus, ownership)
- , GrVkRenderTarget(gpu, dimensions, sampleCnt, info, layout, msaaInfo,
- std::move(msaaLayout), colorAttachmentView, resolveAttachmentView,
+ , GrVkImage(gpu, info, mutableState, ownership)
+ , GrVkTexture(gpu, dimensions, info, mutableState, texView, mipMapsStatus, ownership)
+ , GrVkRenderTarget(gpu, dimensions, sampleCnt, info, std::move(mutableState), msaaInfo,
+ std::move(msaaMutableState), colorAttachmentView, resolveAttachmentView,
ownership) {
SkASSERT(info.fProtected == msaaInfo.fProtected);
this->registerWithCacheWrapped(cacheable);
}
-GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu,
- SkISize dimensions,
- const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
- const GrVkImageView* texView,
- const GrVkImageView* colorAttachmentView,
- GrMipMapsStatus mipMapsStatus,
- GrBackendObjectOwnership ownership,
- GrWrapCacheable cacheable)
+GrVkTextureRenderTarget::GrVkTextureRenderTarget(
+ GrVkGpu* gpu,
+ SkISize dimensions,
+ const GrVkImageInfo& info,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
+ const GrVkImageView* texView,
+ const GrVkImageView* colorAttachmentView,
+ GrMipMapsStatus mipMapsStatus,
+ GrBackendObjectOwnership ownership,
+ GrWrapCacheable cacheable)
: GrSurface(gpu, dimensions, info.fProtected)
- , GrVkImage(gpu, info, layout, ownership)
- , GrVkTexture(gpu, dimensions, info, layout, texView, mipMapsStatus, ownership)
- , GrVkRenderTarget(gpu, dimensions, info, layout, colorAttachmentView, ownership) {
+ , GrVkImage(gpu, info, mutableState, ownership)
+ , GrVkTexture(gpu, dimensions, info, mutableState, texView, mipMapsStatus, ownership)
+ , GrVkRenderTarget(gpu, dimensions, info, std::move(mutableState), colorAttachmentView,
+ ownership) {
this->registerWithCacheWrapped(cacheable);
}
@@ -103,7 +108,7 @@ struct Views {
const GrVkImageView* colorAttachmentView = nullptr;
const GrVkImageView* resolveAttachmentView = nullptr;
GrVkImageInfo msInfo;
- sk_sp<GrVkImageLayout> msLayout;
+ sk_sp<GrBackendSurfaceMutableStateImpl> msMutableState;
};
} // anonymous namespace
@@ -154,7 +159,8 @@ static Views create_views(GrVkGpu* gpu, SkISize dimensions, int sampleCnt,
views.imageView->unref();
return {};
}
- views.msLayout.reset(new GrVkImageLayout(views.msInfo.fImageLayout));
+ views.msMutableState.reset(new GrBackendSurfaceMutableStateImpl(
+ views.msInfo.fImageLayout, views.msInfo.fCurrentQueueFamily));
} else {
// Set color attachment image
colorImage = info.fImage;
@@ -187,7 +193,8 @@ sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeNewTextureRenderTarg
if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
return nullptr;
}
- sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(info.fImageLayout));
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState(
+ new GrBackendSurfaceMutableStateImpl(info.fImageLayout, info.fCurrentQueueFamily));
Views views = create_views(gpu, dimensions, sampleCnt, info);
if (!views.colorAttachmentView) {
@@ -196,12 +203,12 @@ sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeNewTextureRenderTarg
}
if (sampleCnt > 1) {
return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(
- gpu, budgeted, dimensions, sampleCnt, info, std::move(layout), views.imageView,
- views.msInfo, std::move(views.msLayout), views.colorAttachmentView,
- views.resolveAttachmentView, mipMapsStatus));
+ gpu, budgeted, dimensions, sampleCnt, info, std::move(mutableState),
+ views.imageView, views.msInfo, std::move(views.msMutableState),
+ views.colorAttachmentView, views.resolveAttachmentView, mipMapsStatus));
} else {
return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(
- gpu, budgeted, dimensions, info, std::move(layout), views.imageView,
+ gpu, budgeted, dimensions, info, std::move(mutableState), views.imageView,
views.colorAttachmentView, mipMapsStatus));
}
}
@@ -213,7 +220,7 @@ sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeWrappedTextureRender
GrWrapOwnership wrapOwnership,
GrWrapCacheable cacheable,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout) {
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState) {
// Adopted textures require both image and allocation because we're responsible for freeing
SkASSERT(VK_NULL_HANDLE != info.fImage &&
(kBorrow_GrWrapOwnership == wrapOwnership || VK_NULL_HANDLE != info.fAlloc.fMemory));
@@ -229,12 +236,12 @@ sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeWrappedTextureRender
}
if (sampleCnt > 1) {
return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(
- gpu, dimensions, sampleCnt, info, std::move(layout), views.imageView, views.msInfo,
- std::move(views.msLayout), views.colorAttachmentView, views.resolveAttachmentView,
- mipMapsStatus, ownership, cacheable));
+ gpu, dimensions, sampleCnt, info, std::move(mutableState), views.imageView,
+ views.msInfo, std::move(views.msMutableState), views.colorAttachmentView,
+ views.resolveAttachmentView, mipMapsStatus, ownership, cacheable));
} else {
return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(
- gpu, dimensions, info, std::move(layout), views.imageView,
+ gpu, dimensions, info, std::move(mutableState), views.imageView,
views.colorAttachmentView, mipMapsStatus, ownership, cacheable));
}
}
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.h b/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.h
index e3191751819..adc352d48fa 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkTextureRenderTarget.h
@@ -32,13 +32,14 @@ public:
const GrVkImage::ImageDesc&,
GrMipMapsStatus);
- static sk_sp<GrVkTextureRenderTarget> MakeWrappedTextureRenderTarget(GrVkGpu*,
- SkISize dimensions,
- int sampleCnt,
- GrWrapOwnership,
- GrWrapCacheable,
- const GrVkImageInfo&,
- sk_sp<GrVkImageLayout>);
+ static sk_sp<GrVkTextureRenderTarget> MakeWrappedTextureRenderTarget(
+ GrVkGpu*,
+ SkISize dimensions,
+ int sampleCnt,
+ GrWrapOwnership,
+ GrWrapCacheable,
+ const GrVkImageInfo&,
+ sk_sp<GrBackendSurfaceMutableStateImpl>);
GrBackendFormat backendFormat() const override { return this->getBackendFormat(); }
@@ -62,10 +63,10 @@ private:
SkISize dimensions,
int sampleCnt,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageView* texView,
const GrVkImageInfo& msaaInfo,
- sk_sp<GrVkImageLayout> msaaLayout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState,
const GrVkImageView* colorAttachmentView,
const GrVkImageView* resolveAttachmentView,
GrMipMapsStatus);
@@ -75,7 +76,7 @@ private:
SkBudgeted budgeted,
SkISize dimensions,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageView* texView,
const GrVkImageView* colorAttachmentView,
GrMipMapsStatus);
@@ -85,10 +86,10 @@ private:
SkISize dimensions,
int sampleCnt,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageView* texView,
const GrVkImageInfo& msaaInfo,
- sk_sp<GrVkImageLayout> msaaLayout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> msaaMutableState,
const GrVkImageView* colorAttachmentView,
const GrVkImageView* resolveAttachmentView,
GrMipMapsStatus,
@@ -99,7 +100,7 @@ private:
GrVkTextureRenderTarget(GrVkGpu* gpu,
SkISize dimensions,
const GrVkImageInfo& info,
- sk_sp<GrVkImageLayout> layout,
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
const GrVkImageView* texView,
const GrVkImageView* colorAttachmentView,
GrMipMapsStatus,
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkTypesPriv.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkTypesPriv.cpp
index 6f5d0b27f23..5360ab46b5d 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkTypesPriv.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkTypesPriv.cpp
@@ -7,44 +7,32 @@
#include "include/private/GrVkTypesPriv.h"
+#include "src/gpu/GrBackendSurfaceMutableStateImpl.h"
#include "src/gpu/vk/GrVkImageLayout.h"
-void GrVkBackendSurfaceInfo::cleanup() {
- SkSafeUnref(fLayout);
- fLayout = nullptr;
-};
+void GrVkBackendSurfaceInfo::cleanup() {};
void GrVkBackendSurfaceInfo::assign(const GrVkBackendSurfaceInfo& that, bool isThisValid) {
fImageInfo = that.fImageInfo;
- GrVkImageLayout* oldLayout = fLayout;
- fLayout = SkSafeRef(that.fLayout);
- if (isThisValid) {
- SkSafeUnref(oldLayout);
- }
}
-void GrVkBackendSurfaceInfo::setImageLayout(VkImageLayout layout) {
- SkASSERT(fLayout);
- fLayout->setImageLayout(layout);
-}
-
-sk_sp<GrVkImageLayout> GrVkBackendSurfaceInfo::getGrVkImageLayout() const {
- SkASSERT(fLayout);
- return sk_ref_sp(fLayout);
-}
-
-GrVkImageInfo GrVkBackendSurfaceInfo::snapImageInfo() const {
- return GrVkImageInfo(fImageInfo, fLayout->getImageLayout());
+GrVkImageInfo GrVkBackendSurfaceInfo::snapImageInfo(
+ const GrBackendSurfaceMutableStateImpl* mutableState) const {
+ SkASSERT(mutableState);
+ return GrVkImageInfo(fImageInfo, mutableState->getImageLayout(),
+ mutableState->getQueueFamilyIndex());
}
#if GR_TEST_UTILS
bool GrVkBackendSurfaceInfo::operator==(const GrVkBackendSurfaceInfo& that) const {
GrVkImageInfo cpyInfoThis = fImageInfo;
GrVkImageInfo cpyInfoThat = that.fImageInfo;
- // We don't care about the fImageLayout here since we require they use the same
- // GrVkImageLayout.
+ // We don't care about the fImageLayout or fCurrentQueueFamily here since we require they use
+ // the same mutableState.
cpyInfoThis.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
cpyInfoThat.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- return cpyInfoThis == cpyInfoThat && fLayout == that.fLayout;
+ cpyInfoThis.fCurrentQueueFamily = VK_QUEUE_FAMILY_IGNORED;
+ cpyInfoThat.fCurrentQueueFamily = VK_QUEUE_FAMILY_IGNORED;
+ return cpyInfoThis == cpyInfoThat;
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkUtil.cpp b/chromium/third_party/skia/src/gpu/vk/GrVkUtil.cpp
index bd73858bd65..892d6055831 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkUtil.cpp
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkUtil.cpp
@@ -151,12 +151,3 @@ bool GrVkFormatIsCompressed(VkFormat vkFormat) {
SkUNREACHABLE;
}
-SkImage::CompressionType GrVkFormatToCompressionType(VkFormat vkFormat) {
- switch (vkFormat) {
- case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: return SkImage::CompressionType::kETC2_RGB8_UNORM;
- case VK_FORMAT_BC1_RGB_UNORM_BLOCK: return SkImage::CompressionType::kBC1_RGB8_UNORM;
- case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: return SkImage::CompressionType::kBC1_RGBA8_UNORM;
- default: return SkImage::CompressionType::kNone;
- }
- SkUNREACHABLE;
-}
diff --git a/chromium/third_party/skia/src/gpu/vk/GrVkUtil.h b/chromium/third_party/skia/src/gpu/vk/GrVkUtil.h
index e66cd81fc9f..ba24ea4d2d6 100644
--- a/chromium/third_party/skia/src/gpu/vk/GrVkUtil.h
+++ b/chromium/third_party/skia/src/gpu/vk/GrVkUtil.h
@@ -21,25 +21,31 @@ class GrVkGpu;
// makes a Vk call on the interface
#define GR_VK_CALL(IFACE, X) (IFACE)->fFunctions.f##X
-#define GR_VK_CALL_RESULT(GPU, RESULT, X) \
- do { \
- (RESULT) = GR_VK_CALL(GPU->vkInterface(), X); \
- SkASSERT(VK_SUCCESS == RESULT || VK_ERROR_DEVICE_LOST == RESULT); \
- if (RESULT != VK_SUCCESS && !GPU->isDeviceLost()) { \
- SkDebugf("Failed vulkan call. Error: %d\n", RESULT); \
- } \
- if (VK_ERROR_DEVICE_LOST == RESULT) { \
- GPU->setDeviceLost(); \
- } \
- } while(false)
-
-#define GR_VK_CALL_RESULT_NOCHECK(GPU, RESULT, X) \
- do { \
- (RESULT) = GR_VK_CALL(GPU->vkInterface(), X); \
- if (VK_ERROR_DEVICE_LOST == RESULT) { \
- GPU->setDeviceLost(); \
- } \
- } while(false)
+#define GR_VK_CALL_RESULT(GPU, RESULT, X) \
+ do { \
+ (RESULT) = GR_VK_CALL(GPU->vkInterface(), X); \
+ SkASSERT(VK_SUCCESS == RESULT || VK_ERROR_DEVICE_LOST == RESULT); \
+ if (RESULT != VK_SUCCESS && !GPU->isDeviceLost()) { \
+ SkDebugf("Failed vulkan call. Error: %d," #X "\n", RESULT); \
+ } \
+ if (RESULT == VK_ERROR_DEVICE_LOST) { \
+ GPU->setDeviceLost(); \
+ } else if (RESULT == VK_ERROR_OUT_OF_HOST_MEMORY || \
+ RESULT == VK_ERROR_OUT_OF_DEVICE_MEMORY) { \
+ GPU->setOOMed(); \
+ } \
+ } while (false)
+
+#define GR_VK_CALL_RESULT_NOCHECK(GPU, RESULT, X) \
+ do { \
+ (RESULT) = GR_VK_CALL(GPU->vkInterface(), X); \
+ if (RESULT == VK_ERROR_DEVICE_LOST) { \
+ GPU->setDeviceLost(); \
+ } else if (RESULT == VK_ERROR_OUT_OF_HOST_MEMORY || \
+ RESULT == VK_ERROR_OUT_OF_DEVICE_MEMORY) { \
+ GPU->setOOMed(); \
+ } \
+ } while (false)
// same as GR_VK_CALL but checks for success
#define GR_VK_CALL_ERRCHECK(GPU, X) \
@@ -101,11 +107,6 @@ bool GrInstallVkShaderModule(GrVkGpu* gpu,
*/
bool GrVkFormatIsCompressed(VkFormat);
-/**
- * Maps a vk format into the CompressionType enum if applicable.
- */
-SkImage::CompressionType GrVkFormatToCompressionType(VkFormat vkFormat);
-
#if GR_TEST_UTILS
static constexpr const char* GrVkFormatToStr(VkFormat vkFormat) {
switch (vkFormat) {