summaryrefslogtreecommitdiff
path: root/chromium/third_party/skia/src
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/third_party/skia/src
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-85-based.tar.gz
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/skia/src')
-rw-r--r--chromium/third_party/skia/src/android/SkAnimatedImage.cpp4
-rw-r--r--chromium/third_party/skia/src/android/SkBitmapRegionCodec.cpp118
-rw-r--r--chromium/third_party/skia/src/android/SkBitmapRegionCodec.h49
-rw-r--r--chromium/third_party/skia/src/android/SkBitmapRegionDecoder.cpp47
-rw-r--r--chromium/third_party/skia/src/android/SkBitmapRegionDecoderPriv.h61
-rw-r--r--chromium/third_party/skia/src/atlastext/SkAtlasTextContext.cpp17
-rw-r--r--chromium/third_party/skia/src/atlastext/SkAtlasTextTarget.cpp264
-rw-r--r--chromium/third_party/skia/src/atlastext/SkInternalAtlasTextContext.cpp126
-rw-r--r--chromium/third_party/skia/src/atlastext/SkInternalAtlasTextContext.h82
-rw-r--r--chromium/third_party/skia/src/codec/SkBmpCodec.cpp2
-rw-r--r--chromium/third_party/skia/src/codec/SkCodecPriv.h6
-rw-r--r--chromium/third_party/skia/src/codec/SkIcoCodec.cpp55
-rw-r--r--chromium/third_party/skia/src/codec/SkIcoCodec.h3
-rw-r--r--chromium/third_party/skia/src/codec/SkPngCodec.cpp3
-rw-r--r--chromium/third_party/skia/src/codec/SkWebpCodec.cpp4
-rw-r--r--chromium/third_party/skia/src/codec/SkWuffsCodec.cpp137
-rw-r--r--chromium/third_party/skia/src/core/SkArenaAlloc.h35
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapDevice.cpp107
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapDevice.h3
-rwxr-xr-xchromium/third_party/skia/src/core/SkBitmapProcState_matrixProcs.cpp4
-rw-r--r--chromium/third_party/skia/src/core/SkBlitter.cpp37
-rw-r--r--chromium/third_party/skia/src/core/SkBlitter_Sprite.cpp5
-rw-r--r--chromium/third_party/skia/src/core/SkBlurMF.cpp34
-rw-r--r--chromium/third_party/skia/src/core/SkCanvas.cpp49
-rw-r--r--chromium/third_party/skia/src/core/SkClipStack.cpp75
-rw-r--r--chromium/third_party/skia/src/core/SkClipStack.h25
-rw-r--r--chromium/third_party/skia/src/core/SkClipStackDevice.cpp6
-rw-r--r--chromium/third_party/skia/src/core/SkClipStackDevice.h1
-rw-r--r--chromium/third_party/skia/src/core/SkColorFilter.cpp97
-rw-r--r--chromium/third_party/skia/src/core/SkColorFilterBase.h108
-rw-r--r--chromium/third_party/skia/src/core/SkColorFilter_Matrix.cpp25
-rw-r--r--chromium/third_party/skia/src/core/SkColorFilter_Matrix.h9
-rw-r--r--chromium/third_party/skia/src/core/SkColorSpaceXformSteps.cpp32
-rw-r--r--chromium/third_party/skia/src/core/SkColorSpaceXformSteps.h8
-rw-r--r--chromium/third_party/skia/src/core/SkConvertPixels.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkCoreBlitters.h4
-rw-r--r--chromium/third_party/skia/src/core/SkDeferredDisplayList.cpp4
-rw-r--r--chromium/third_party/skia/src/core/SkDeferredDisplayListPriv.h4
-rw-r--r--chromium/third_party/skia/src/core/SkDeferredDisplayListRecorder.cpp16
-rw-r--r--chromium/third_party/skia/src/core/SkDevice.cpp7
-rw-r--r--chromium/third_party/skia/src/core/SkDevice.h3
-rw-r--r--chromium/third_party/skia/src/core/SkDraw.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkDraw.h1
-rw-r--r--chromium/third_party/skia/src/core/SkDraw_atlas.cpp33
-rw-r--r--chromium/third_party/skia/src/core/SkDraw_text.cpp4
-rw-r--r--chromium/third_party/skia/src/core/SkDraw_vertices.cpp64
-rw-r--r--chromium/third_party/skia/src/core/SkDrawable.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkFont.cpp4
-rw-r--r--chromium/third_party/skia/src/core/SkFontPriv.h2
-rw-r--r--chromium/third_party/skia/src/core/SkGlyphBuffer.cpp42
-rw-r--r--chromium/third_party/skia/src/core/SkGlyphBuffer.h32
-rw-r--r--chromium/third_party/skia/src/core/SkGlyphRunPainter.cpp178
-rw-r--r--chromium/third_party/skia/src/core/SkGlyphRunPainter.h7
-rw-r--r--chromium/third_party/skia/src/core/SkGpuBlurUtils.cpp560
-rw-r--r--chromium/third_party/skia/src/core/SkGpuBlurUtils.h47
-rw-r--r--chromium/third_party/skia/src/core/SkImageFilter.cpp17
-rw-r--r--chromium/third_party/skia/src/core/SkImageFilterTypes.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkImageInfo.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkLegacyGpuBlurUtils.cpp485
-rw-r--r--chromium/third_party/skia/src/core/SkLocalMatrixImageFilter.cpp12
-rw-r--r--chromium/third_party/skia/src/core/SkLocalMatrixImageFilter.h2
-rw-r--r--chromium/third_party/skia/src/core/SkMaskFilter.cpp4
-rw-r--r--chromium/third_party/skia/src/core/SkMaskFilterBase.h2
-rw-r--r--chromium/third_party/skia/src/core/SkMatrixProvider.h20
-rw-r--r--chromium/third_party/skia/src/core/SkMipMap.h1
-rw-r--r--chromium/third_party/skia/src/core/SkModeColorFilter.cpp6
-rw-r--r--chromium/third_party/skia/src/core/SkModeColorFilter.h13
-rw-r--r--chromium/third_party/skia/src/core/SkOSFile.h11
-rw-r--r--chromium/third_party/skia/src/core/SkOpts.cpp5
-rw-r--r--chromium/third_party/skia/src/core/SkOpts.h3
-rw-r--r--chromium/third_party/skia/src/core/SkOpts_skx.cpp63
-rw-r--r--chromium/third_party/skia/src/core/SkOverdrawCanvas.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkPaint.cpp8
-rw-r--r--chromium/third_party/skia/src/core/SkPaintPriv.cpp4
-rw-r--r--chromium/third_party/skia/src/core/SkPath.cpp14
-rw-r--r--chromium/third_party/skia/src/core/SkPathBuilder.cpp358
-rw-r--r--chromium/third_party/skia/src/core/SkPathRef.cpp10
-rw-r--r--chromium/third_party/skia/src/core/SkPath_serial.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkPicture.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkPictureData.cpp7
-rw-r--r--chromium/third_party/skia/src/core/SkPictureData.h1
-rw-r--r--chromium/third_party/skia/src/core/SkPictureFlat.h4
-rw-r--r--chromium/third_party/skia/src/core/SkPicturePlayback.cpp13
-rw-r--r--chromium/third_party/skia/src/core/SkPicturePriv.h4
-rw-r--r--chromium/third_party/skia/src/core/SkPictureRecord.cpp18
-rw-r--r--chromium/third_party/skia/src/core/SkPixmap.cpp1
-rw-r--r--chromium/third_party/skia/src/core/SkRasterPipeline.cpp1
-rw-r--r--chromium/third_party/skia/src/core/SkRasterPipeline.h2
-rw-r--r--chromium/third_party/skia/src/core/SkRasterPipelineBlitter.cpp53
-rw-r--r--chromium/third_party/skia/src/core/SkReadBuffer.cpp96
-rw-r--r--chromium/third_party/skia/src/core/SkReadBuffer.h143
-rw-r--r--chromium/third_party/skia/src/core/SkReader32.h169
-rw-r--r--chromium/third_party/skia/src/core/SkRecord.h13
-rw-r--r--chromium/third_party/skia/src/core/SkRecordDraw.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkRecordOpts.cpp4
-rw-r--r--chromium/third_party/skia/src/core/SkRecorder.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkRecords.h23
-rw-r--r--chromium/third_party/skia/src/core/SkRemoteGlyphCache.cpp8
-rw-r--r--chromium/third_party/skia/src/core/SkRuntimeEffect.cpp218
-rw-r--r--chromium/third_party/skia/src/core/SkSpecialImage.cpp112
-rw-r--r--chromium/third_party/skia/src/core/SkSpecialImage.h7
-rw-r--r--chromium/third_party/skia/src/core/SkStrikeSpec.cpp14
-rw-r--r--chromium/third_party/skia/src/core/SkStrikeSpec.h4
-rw-r--r--chromium/third_party/skia/src/core/SkString.cpp163
-rw-r--r--chromium/third_party/skia/src/core/SkVM.cpp30
-rw-r--r--chromium/third_party/skia/src/core/SkVM.h31
-rw-r--r--chromium/third_party/skia/src/core/SkVMBlitter.cpp68
-rw-r--r--chromium/third_party/skia/src/core/SkVM_fwd.h1
-rw-r--r--chromium/third_party/skia/src/core/SkValidatingReadBuffer.h23
-rw-r--r--chromium/third_party/skia/src/core/SkWriteBuffer.cpp21
-rw-r--r--chromium/third_party/skia/src/core/SkWriteBuffer.h3
-rw-r--r--chromium/third_party/skia/src/core/SkWriter32.cpp30
-rw-r--r--chromium/third_party/skia/src/core/SkWriter32.h13
-rw-r--r--chromium/third_party/skia/src/effects/Sk1DPathEffect.cpp2
-rw-r--r--chromium/third_party/skia/src/effects/SkHighContrastFilter.cpp8
-rw-r--r--chromium/third_party/skia/src/effects/SkLumaColorFilter.cpp70
-rw-r--r--chromium/third_party/skia/src/effects/SkOpPE.h15
-rw-r--r--chromium/third_party/skia/src/effects/SkOpPathEffect.cpp55
-rw-r--r--chromium/third_party/skia/src/effects/SkTableColorFilter.cpp112
-rw-r--r--chromium/third_party/skia/src/effects/imagefilters/SkAlphaThresholdFilter.cpp21
-rw-r--r--chromium/third_party/skia/src/effects/imagefilters/SkArithmeticImageFilter.cpp9
-rw-r--r--chromium/third_party/skia/src/effects/imagefilters/SkColorFilterImageFilter.cpp7
-rw-r--r--chromium/third_party/skia/src/effects/imagefilters/SkDisplacementMapEffect.cpp24
-rw-r--r--chromium/third_party/skia/src/effects/imagefilters/SkLightingImageFilter.cpp35
-rw-r--r--chromium/third_party/skia/src/effects/imagefilters/SkMagnifierImageFilter.cpp7
-rw-r--r--chromium/third_party/skia/src/effects/imagefilters/SkMorphologyImageFilter.cpp260
-rw-r--r--chromium/third_party/skia/src/effects/imagefilters/SkXfermodeImageFilter.cpp9
-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
-rw-r--r--chromium/third_party/skia/src/image/SkImage.cpp18
-rw-r--r--chromium/third_party/skia/src/image/SkImage_Gpu.cpp65
-rw-r--r--chromium/third_party/skia/src/image/SkImage_GpuBase.cpp15
-rw-r--r--chromium/third_party/skia/src/image/SkImage_GpuBase.h3
-rw-r--r--chromium/third_party/skia/src/image/SkImage_GpuYUVA.cpp18
-rw-r--r--chromium/third_party/skia/src/image/SkImage_Lazy.cpp1
-rw-r--r--chromium/third_party/skia/src/image/SkImage_Lazy.h2
-rw-r--r--chromium/third_party/skia/src/image/SkSurface.cpp48
-rw-r--r--chromium/third_party/skia/src/image/SkSurface_Base.h3
-rw-r--r--chromium/third_party/skia/src/image/SkSurface_Gpu.cpp54
-rw-r--r--chromium/third_party/skia/src/image/SkSurface_Gpu.h3
-rw-r--r--chromium/third_party/skia/src/images/SkWebpEncoder.cpp116
-rw-r--r--chromium/third_party/skia/src/opts/SkChecksum_opts.h4
-rw-r--r--chromium/third_party/skia/src/opts/SkOpts_avx.cpp13
-rw-r--r--chromium/third_party/skia/src/opts/SkOpts_hsw.cpp10
-rw-r--r--chromium/third_party/skia/src/opts/SkOpts_skx.cpp27
-rw-r--r--chromium/third_party/skia/src/opts/SkOpts_sse41.cpp25
-rw-r--r--chromium/third_party/skia/src/opts/SkRasterPipeline_opts.h163
-rw-r--r--chromium/third_party/skia/src/opts/SkSwizzler_opts.h1044
-rw-r--r--chromium/third_party/skia/src/opts/SkVM_opts.h1
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsCubic.cpp5
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFDevice.cpp11
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFDevice.h3
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFDocument.cpp17
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFDocumentPriv.h10
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFTag.cpp243
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFTag.h24
-rw-r--r--chromium/third_party/skia/src/ports/SkFontHost_FreeType.cpp2
-rw-r--r--chromium/third_party/skia/src/ports/SkFontHost_mac.cpp3226
-rw-r--r--chromium/third_party/skia/src/ports/SkFontMgr_custom_directory_factory.cpp4
-rw-r--r--chromium/third_party/skia/src/ports/SkFontMgr_custom_embedded.cpp2
-rw-r--r--chromium/third_party/skia/src/ports/SkFontMgr_mac_ct.cpp669
-rw-r--r--chromium/third_party/skia/src/ports/SkFontMgr_mac_ct_factory.cpp18
-rw-r--r--chromium/third_party/skia/src/ports/SkGlobalInitialization_default.cpp5
-rw-r--r--chromium/third_party/skia/src/ports/SkScalerContext_mac_ct.cpp721
-rw-r--r--chromium/third_party/skia/src/ports/SkScalerContext_mac_ct.h118
-rw-r--r--chromium/third_party/skia/src/ports/SkScalerContext_win_dw.cpp9
-rw-r--r--chromium/third_party/skia/src/ports/SkTypeface_mac_ct.cpp1470
-rw-r--r--chromium/third_party/skia/src/ports/SkTypeface_mac_ct.h128
-rw-r--r--chromium/third_party/skia/src/sfnt/SkOTTable_name.cpp1
-rw-r--r--chromium/third_party/skia/src/shaders/SkColorFilterShader.cpp16
-rw-r--r--chromium/third_party/skia/src/shaders/SkColorFilterShader.h12
-rw-r--r--chromium/third_party/skia/src/shaders/SkColorShader.cpp15
-rw-r--r--chromium/third_party/skia/src/shaders/SkColorShader.h8
-rw-r--r--chromium/third_party/skia/src/shaders/SkComposeShader.cpp18
-rw-r--r--chromium/third_party/skia/src/shaders/SkComposeShader.h8
-rw-r--r--chromium/third_party/skia/src/shaders/SkEmptyShader.h7
-rwxr-xr-xchromium/third_party/skia/src/shaders/SkImageShader.cpp86
-rw-r--r--chromium/third_party/skia/src/shaders/SkImageShader.h20
-rw-r--r--chromium/third_party/skia/src/shaders/SkLocalMatrixShader.cpp43
-rw-r--r--chromium/third_party/skia/src/shaders/SkLocalMatrixShader.h4
-rw-r--r--chromium/third_party/skia/src/shaders/SkPerlinNoiseShader.cpp383
-rw-r--r--chromium/third_party/skia/src/shaders/SkPictureShader.cpp12
-rw-r--r--chromium/third_party/skia/src/shaders/SkPictureShader.h4
-rw-r--r--chromium/third_party/skia/src/shaders/SkShader.cpp53
-rw-r--r--chromium/third_party/skia/src/shaders/SkShaderBase.h11
-rw-r--r--chromium/third_party/skia/src/shaders/gradients/Sk4fLinearGradient.cpp10
-rw-r--r--chromium/third_party/skia/src/shaders/gradients/SkGradientShader.cpp14
-rw-r--r--chromium/third_party/skia/src/shaders/gradients/SkGradientShaderPriv.h6
-rw-r--r--chromium/third_party/skia/src/shaders/gradients/SkLinearGradient.cpp4
-rw-r--r--chromium/third_party/skia/src/shaders/gradients/SkLinearGradient.h2
-rw-r--r--chromium/third_party/skia/src/shaders/gradients/SkRadialGradient.cpp4
-rw-r--r--chromium/third_party/skia/src/shaders/gradients/SkRadialGradient.h2
-rw-r--r--chromium/third_party/skia/src/shaders/gradients/SkSweepGradient.cpp17
-rw-r--r--chromium/third_party/skia/src/shaders/gradients/SkSweepGradient.h2
-rw-r--r--chromium/third_party/skia/src/shaders/gradients/SkTwoPointConicalGradient.cpp9
-rw-r--r--chromium/third_party/skia/src/shaders/gradients/SkTwoPointConicalGradient.h2
-rw-r--r--chromium/third_party/skia/src/sksl/README10
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLASTNode.cpp7
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLByteCode.cpp335
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLByteCode.h29
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLByteCodeGenerator.cpp228
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLByteCodeGenerator.h13
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLCPPCodeGenerator.cpp152
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLCPPCodeGenerator.h4
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLCPPUniformCTypes.cpp2
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLCompiler.cpp211
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLCompiler.h4
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLContext.h28
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLDefines.h3
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLGLSLCodeGenerator.cpp20
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLHCodeGenerator.cpp81
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLIRGenerator.cpp487
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLIRGenerator.h18
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLMetalCodeGenerator.cpp458
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLMetalCodeGenerator.h10
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLParser.cpp9
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLSPIRVCodeGenerator.cpp225
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLSPIRVCodeGenerator.h2
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLSampleMatrix.cpp194
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLSampleMatrix.h36
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLSectionAndParameterHelper.cpp166
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLSectionAndParameterHelper.h9
-rw-r--r--chromium/third_party/skia/src/sksl/SkSLUtil.h7
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLBinaryExpression.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLBlock.h20
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLBoolLiteral.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLBreakStatement.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLConstructor.h8
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLContinueStatement.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLDiscardStatement.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLDoStatement.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLExpressionStatement.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLExternalFunctionCall.h8
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLExternalValueReference.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLFieldAccess.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLFloatLiteral.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLForStatement.h26
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLFunctionCall.h16
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLFunctionDeclaration.h11
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLFunctionDefinition.h5
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLIRNode.h6
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLIfStatement.h5
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLIndexExpression.h12
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLIntLiteral.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLNop.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLNullLiteral.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLPostfixExpression.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLPrefixExpression.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLProgram.h17
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLReturnStatement.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLSetting.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLStatement.h1
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLSwitchCase.h11
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLSwitchStatement.h8
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLSwizzle.h10
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLSymbol.h2
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLSymbolTable.cpp10
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLSymbolTable.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLTernaryExpression.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLType.cpp32
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLType.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLVarDeclarations.h32
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLVarDeclarationsStatement.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLVariableReference.h4
-rw-r--r--chromium/third_party/skia/src/sksl/ir/SkSLWhileStatement.h4
-rw-r--r--chromium/third_party/skia/src/sksl/lex/RegexParser.cpp4
-rw-r--r--chromium/third_party/skia/src/sksl/sksl_blend.inc7
-rw-r--r--chromium/third_party/skia/src/sksl/sksl_enums.inc6
-rw-r--r--chromium/third_party/skia/src/sksl/sksl_gpu.inc18
-rw-r--r--chromium/third_party/skia/src/sksl/sksl_interp.inc6
-rw-r--r--chromium/third_party/skia/src/sksl/sksl_pipeline.inc1
-rw-r--r--chromium/third_party/skia/src/svg/SkSVGDevice.cpp3
-rw-r--r--chromium/third_party/skia/src/utils/SkCamera.cpp238
-rw-r--r--chromium/third_party/skia/src/utils/SkClipStackUtils.cpp5
-rw-r--r--chromium/third_party/skia/src/utils/SkCustomTypeface.cpp118
-rw-r--r--chromium/third_party/skia/src/utils/SkJSON.cpp46
-rw-r--r--chromium/third_party/skia/src/utils/SkJSON.h72
-rw-r--r--chromium/third_party/skia/src/utils/SkLuaCanvas.cpp4
-rw-r--r--chromium/third_party/skia/src/utils/SkParseColor.cpp363
-rw-r--r--chromium/third_party/skia/src/utils/SkParsePath.cpp2
-rw-r--r--chromium/third_party/skia/src/utils/SkShadowUtils.cpp11
-rw-r--r--chromium/third_party/skia/src/utils/mac/SkCGBase.h37
-rw-r--r--chromium/third_party/skia/src/utils/mac/SkCGGeometry.h52
-rw-r--r--chromium/third_party/skia/src/utils/mac/SkCTFontSmoothBehavior.cpp271
-rw-r--r--chromium/third_party/skia/src/utils/mac/SkCTFontSmoothBehavior.h23
-rw-r--r--chromium/third_party/skia/src/utils/mac/SkStream_mac.cpp8
-rw-r--r--chromium/third_party/skia/src/xps/SkXPSDevice.cpp18
-rw-r--r--chromium/third_party/skia/src/xps/SkXPSDevice.h1
687 files changed, 23977 insertions, 17351 deletions
diff --git a/chromium/third_party/skia/src/android/SkAnimatedImage.cpp b/chromium/third_party/skia/src/android/SkAnimatedImage.cpp
index 3ae8a843ba4..966f150aa89 100644
--- a/chromium/third_party/skia/src/android/SkAnimatedImage.cpp
+++ b/chromium/third_party/skia/src/android/SkAnimatedImage.cpp
@@ -92,10 +92,10 @@ SkAnimatedImage::SkAnimatedImage(std::unique_ptr<SkAndroidCodec> codec, SkISize
}
if (!fSimple) {
- fMatrix = SkMatrix::MakeTrans(-fCropRect.fLeft, -fCropRect.fTop);
+ fMatrix = SkMatrix::Translate(-fCropRect.fLeft, -fCropRect.fTop);
float scaleX = (float) fScaledSize.width() / fDecodeInfo.width();
float scaleY = (float) fScaledSize.height() / fDecodeInfo.height();
- fMatrix.preConcat(SkMatrix::MakeScale(scaleX, scaleY));
+ fMatrix.preConcat(SkMatrix::Scale(scaleX, scaleY));
}
this->decodeNextFrame();
}
diff --git a/chromium/third_party/skia/src/android/SkBitmapRegionCodec.cpp b/chromium/third_party/skia/src/android/SkBitmapRegionCodec.cpp
deleted file mode 100644
index 081d0bbf3bc..00000000000
--- a/chromium/third_party/skia/src/android/SkBitmapRegionCodec.cpp
+++ /dev/null
@@ -1,118 +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 "include/codec/SkAndroidCodec.h"
-#include "src/android/SkBitmapRegionCodec.h"
-#include "src/android/SkBitmapRegionDecoderPriv.h"
-#include "src/codec/SkCodecPriv.h"
-
-SkBitmapRegionCodec::SkBitmapRegionCodec(SkAndroidCodec* codec)
- : INHERITED(codec->getInfo().width(), codec->getInfo().height())
- , fCodec(codec)
-{}
-
-bool SkBitmapRegionCodec::decodeRegion(SkBitmap* bitmap, SkBRDAllocator* allocator,
- const SkIRect& desiredSubset, int sampleSize, SkColorType dstColorType,
- bool requireUnpremul, sk_sp<SkColorSpace> dstColorSpace) {
-
- // Fix the input sampleSize if necessary.
- if (sampleSize < 1) {
- sampleSize = 1;
- }
-
- // The size of the output bitmap is determined by the size of the
- // requested subset, not by the size of the intersection of the subset
- // and the image dimensions.
- // If inputX is negative, we will need to place decoded pixels into the
- // output bitmap starting at a left offset. Call this outX.
- // If outX is non-zero, subsetX must be zero.
- // If inputY is negative, we will need to place decoded pixels into the
- // output bitmap starting at a top offset. Call this outY.
- // If outY is non-zero, subsetY must be zero.
- int outX;
- int outY;
- SkIRect subset = desiredSubset;
- SubsetType type = adjust_subset_rect(fCodec->getInfo().dimensions(), &subset, &outX, &outY);
- if (SubsetType::kOutside_SubsetType == type) {
- return false;
- }
-
- // Ask the codec for a scaled subset
- if (!fCodec->getSupportedSubset(&subset)) {
- SkCodecPrintf("Error: Could not get subset.\n");
- return false;
- }
- SkISize scaledSize = fCodec->getSampledSubsetDimensions(sampleSize, subset);
-
- // Create the image info for the decode
- SkAlphaType dstAlphaType = fCodec->computeOutputAlphaType(requireUnpremul);
- SkImageInfo decodeInfo =
- SkImageInfo::Make(scaledSize, dstColorType, dstAlphaType, dstColorSpace);
-
- // Initialize the destination bitmap
- int scaledOutX = 0;
- int scaledOutY = 0;
- int scaledOutWidth = scaledSize.width();
- int scaledOutHeight = scaledSize.height();
- if (SubsetType::kPartiallyInside_SubsetType == type) {
- scaledOutX = outX / sampleSize;
- scaledOutY = outY / sampleSize;
- // We need to be safe here because getSupportedSubset() may have modified the subset.
- const int extraX = std::max(0, desiredSubset.width() - outX - subset.width());
- const int extraY = std::max(0, desiredSubset.height() - outY - subset.height());
- const int scaledExtraX = extraX / sampleSize;
- const int scaledExtraY = extraY / sampleSize;
- scaledOutWidth += scaledOutX + scaledExtraX;
- scaledOutHeight += scaledOutY + scaledExtraY;
- }
- SkImageInfo outInfo = decodeInfo.makeWH(scaledOutWidth, scaledOutHeight);
- if (kGray_8_SkColorType == dstColorType) {
- // The legacy implementations of BitmapFactory and BitmapRegionDecoder
- // used kAlpha8 for grayscale images (before kGray8 existed). While
- // the codec recognizes kGray8, we need to decode into a kAlpha8
- // bitmap in order to avoid a behavior change.
- outInfo = outInfo.makeColorType(kAlpha_8_SkColorType).makeAlphaType(kPremul_SkAlphaType);
- }
- bitmap->setInfo(outInfo);
- if (!bitmap->tryAllocPixels(allocator)) {
- SkCodecPrintf("Error: Could not allocate pixels.\n");
- return false;
- }
-
- // Zero the bitmap if the region is not completely within the image.
- // TODO (msarett): Can we make this faster by implementing it to only
- // zero parts of the image that we won't overwrite with
- // pixels?
- SkCodec::ZeroInitialized zeroInit = allocator ? allocator->zeroInit() :
- SkCodec::kNo_ZeroInitialized;
- if (SubsetType::kPartiallyInside_SubsetType == type &&
- SkCodec::kNo_ZeroInitialized == zeroInit) {
- void* pixels = bitmap->getPixels();
- size_t bytes = outInfo.computeByteSize(bitmap->rowBytes());
- memset(pixels, 0, bytes);
- }
-
- // Decode into the destination bitmap
- SkAndroidCodec::AndroidOptions options;
- options.fSampleSize = sampleSize;
- options.fSubset = &subset;
- options.fZeroInitialized = zeroInit;
- void* dst = bitmap->getAddr(scaledOutX, scaledOutY);
-
- SkCodec::Result result = fCodec->getAndroidPixels(decodeInfo, dst, bitmap->rowBytes(),
- &options);
- switch (result) {
- case SkCodec::kSuccess:
- case SkCodec::kIncompleteInput:
- case SkCodec::kErrorInInput:
- return true;
- default:
- SkCodecPrintf("Error: Could not get pixels with message \"%s\".\n",
- SkCodec::ResultToString(result));
- return false;
- }
-}
diff --git a/chromium/third_party/skia/src/android/SkBitmapRegionCodec.h b/chromium/third_party/skia/src/android/SkBitmapRegionCodec.h
deleted file mode 100644
index 21859514af9..00000000000
--- a/chromium/third_party/skia/src/android/SkBitmapRegionCodec.h
+++ /dev/null
@@ -1,49 +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 SkBitmapRegionCodec_DEFINED
-#define SkBitmapRegionCodec_DEFINED
-
-#include "include/android/SkBitmapRegionDecoder.h"
-#include "include/codec/SkAndroidCodec.h"
-#include "include/core/SkBitmap.h"
-
-/*
- * This class implements SkBitmapRegionDecoder using an SkAndroidCodec.
- */
-class SkBitmapRegionCodec : public SkBitmapRegionDecoder {
-public:
-
- /*
- * Takes ownership of pointer to codec
- */
- SkBitmapRegionCodec(SkAndroidCodec* codec);
-
- bool decodeRegion(SkBitmap* bitmap, SkBRDAllocator* allocator,
- const SkIRect& desiredSubset, int sampleSize,
- SkColorType colorType, bool requireUnpremul,
- sk_sp<SkColorSpace> prefColorSpace) override;
-
- SkEncodedImageFormat getEncodedFormat() override { return fCodec->getEncodedFormat(); }
-
- SkColorType computeOutputColorType(SkColorType requestedColorType) override {
- return fCodec->computeOutputColorType(requestedColorType);
- }
-
- sk_sp<SkColorSpace> computeOutputColorSpace(SkColorType outputColorType,
- sk_sp<SkColorSpace> prefColorSpace = nullptr) override {
- return fCodec->computeOutputColorSpace(outputColorType, prefColorSpace);
- }
-
-private:
-
- std::unique_ptr<SkAndroidCodec> fCodec;
-
- typedef SkBitmapRegionDecoder INHERITED;
-
-};
-#endif // SkBitmapRegionCodec_DEFINED
diff --git a/chromium/third_party/skia/src/android/SkBitmapRegionDecoder.cpp b/chromium/third_party/skia/src/android/SkBitmapRegionDecoder.cpp
deleted file mode 100644
index 328daa3bc97..00000000000
--- a/chromium/third_party/skia/src/android/SkBitmapRegionDecoder.cpp
+++ /dev/null
@@ -1,47 +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 "include/android/SkBitmapRegionDecoder.h"
-#include "include/codec/SkAndroidCodec.h"
-#include "include/codec/SkCodec.h"
-#include "src/android/SkBitmapRegionCodec.h"
-#include "src/codec/SkCodecPriv.h"
-
-SkBitmapRegionDecoder* SkBitmapRegionDecoder::Create(
- sk_sp<SkData> data, Strategy strategy) {
- return SkBitmapRegionDecoder::Create(new SkMemoryStream(data),
- strategy);
-}
-
-SkBitmapRegionDecoder* SkBitmapRegionDecoder::Create(
- SkStreamRewindable* stream, Strategy strategy) {
- std::unique_ptr<SkStreamRewindable> streamDeleter(stream);
- switch (strategy) {
- case kAndroidCodec_Strategy: {
- auto codec = SkAndroidCodec::MakeFromStream(std::move(streamDeleter));
- if (nullptr == codec) {
- SkCodecPrintf("Error: Failed to create codec.\n");
- return nullptr;
- }
-
- switch ((SkEncodedImageFormat)codec->getEncodedFormat()) {
- case SkEncodedImageFormat::kJPEG:
- case SkEncodedImageFormat::kPNG:
- case SkEncodedImageFormat::kWEBP:
- case SkEncodedImageFormat::kHEIF:
- break;
- default:
- return nullptr;
- }
-
- return new SkBitmapRegionCodec(codec.release());
- }
- default:
- SkASSERT(false);
- return nullptr;
- }
-}
diff --git a/chromium/third_party/skia/src/android/SkBitmapRegionDecoderPriv.h b/chromium/third_party/skia/src/android/SkBitmapRegionDecoderPriv.h
deleted file mode 100644
index 905d460c5c6..00000000000
--- a/chromium/third_party/skia/src/android/SkBitmapRegionDecoderPriv.h
+++ /dev/null
@@ -1,61 +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 SkBitmapRegionDecoderPriv_DEFINED
-#define SkBitmapRegionDecoderPriv_DEFINED
-
-#include "include/core/SkRect.h"
-
-enum SubsetType {
- kFullyInside_SubsetType,
- kPartiallyInside_SubsetType,
- kOutside_SubsetType,
-};
-
-/*
- * Corrects image subset offsets and dimensions in order to perform a valid decode.
- * Also indicates if the image subset should be placed at an offset within the
- * output bitmap.
- *
- * Values of output variables are undefined if the SubsetType is kInvalid.
- *
- * @param imageDims Original image dimensions.
- * @param subset As input, the subset that the client requested.
- * As output, the image subset that we will decode.
- * @param outX The left offset of the image subset within the output bitmap.
- * @param outY The top offset of the image subset within the output bitmap.
- *
- * @return An indication of how the subset is contained in the image.
- * If the return value is kInvalid, values of output variables are undefined.
- */
-inline SubsetType adjust_subset_rect(const SkISize& imageDims, SkIRect* subset, int* outX,
- int* outY) {
- // These must be at least zero, we can't start decoding the image at a negative coordinate.
- int left = std::max(0, subset->fLeft);
- int top = std::max(0, subset->fTop);
-
- // If input offsets are less than zero, we decode to an offset location in the output bitmap.
- *outX = left - subset->fLeft;
- *outY = top - subset->fTop;
-
- // Make sure we don't decode pixels past the edge of the image or past the edge of the subset.
- int width = std::min(imageDims.width() - left, subset->width() - *outX);
- int height = std::min(imageDims.height() - top, subset->height() - *outY);
- if (width <= 0 || height <= 0) {
- return SubsetType::kOutside_SubsetType;
- }
-
- subset->setXYWH(left, top, width, height);
- if ((*outX != 0) || (*outY != 0) || (width != subset->width()) ||
- (height != subset->height())) {
- return SubsetType::kPartiallyInside_SubsetType;
- }
-
- return SubsetType::kFullyInside_SubsetType;
-}
-
-#endif // SkBitmapRegionDecoderPriv_DEFINED
diff --git a/chromium/third_party/skia/src/atlastext/SkAtlasTextContext.cpp b/chromium/third_party/skia/src/atlastext/SkAtlasTextContext.cpp
deleted file mode 100644
index 91e7713c125..00000000000
--- a/chromium/third_party/skia/src/atlastext/SkAtlasTextContext.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "include/atlastext/SkAtlasTextContext.h"
-#include "include/atlastext/SkAtlasTextRenderer.h"
-#include "src/atlastext/SkInternalAtlasTextContext.h"
-
-sk_sp<SkAtlasTextContext> SkAtlasTextContext::Make(sk_sp<SkAtlasTextRenderer> renderer) {
- return sk_sp<SkAtlasTextContext>(new SkAtlasTextContext(std::move(renderer)));
-}
-
-SkAtlasTextContext::SkAtlasTextContext(sk_sp<SkAtlasTextRenderer> renderer)
- : fInternalContext(SkInternalAtlasTextContext::Make(std::move(renderer))) {}
diff --git a/chromium/third_party/skia/src/atlastext/SkAtlasTextTarget.cpp b/chromium/third_party/skia/src/atlastext/SkAtlasTextTarget.cpp
deleted file mode 100644
index d541f38fb33..00000000000
--- a/chromium/third_party/skia/src/atlastext/SkAtlasTextTarget.cpp
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "include/atlastext/SkAtlasTextTarget.h"
-
-#include "include/atlastext/SkAtlasTextContext.h"
-#include "include/atlastext/SkAtlasTextFont.h"
-#include "include/atlastext/SkAtlasTextRenderer.h"
-#include "src/atlastext/SkInternalAtlasTextContext.h"
-#include "src/core/SkGlyphRunPainter.h"
-#include "src/core/SkMatrixProvider.h"
-#include "src/gpu/GrClip.h"
-#include "src/gpu/GrContextPriv.h"
-#include "src/gpu/GrDrawingManager.h"
-#include "src/gpu/GrMemoryPool.h"
-#include "src/gpu/GrRecordingContextPriv.h"
-#include "src/gpu/SkGr.h"
-#include "src/gpu/ops/GrAtlasTextOp.h"
-#include "src/gpu/text/GrAtlasManager.h"
-#include "src/gpu/text/GrTextContext.h"
-
-static constexpr int kMaxBatchLookBack = 10;
-
-SkAtlasTextTarget::SkAtlasTextTarget(sk_sp<SkAtlasTextContext> context, int width, int height,
- void* handle)
- : fHandle(handle)
- , fContext(std::move(context))
- , fWidth(width)
- , fHeight(height)
- , fMatrixStack(sizeof(SkMatrix), 4)
- , fSaveCnt(0) {
- fMatrixStack.push_back();
- this->accessCTM()->reset();
-}
-
-SkAtlasTextTarget::~SkAtlasTextTarget() { fContext->renderer()->targetDeleted(fHandle); }
-
-int SkAtlasTextTarget::save() {
- const auto& currCTM = this->ctm();
- *static_cast<SkMatrix*>(fMatrixStack.push_back()) = currCTM;
- return fSaveCnt++;
-}
-
-void SkAtlasTextTarget::restore() {
- if (fSaveCnt) {
- fMatrixStack.pop_back();
- fSaveCnt--;
- }
-}
-
-void SkAtlasTextTarget::restoreToCount(int count) {
- while (fSaveCnt > count) {
- this->restore();
- }
-}
-
-void SkAtlasTextTarget::translate(SkScalar dx, SkScalar dy) {
- this->accessCTM()->preTranslate(dx, dy);
-}
-
-void SkAtlasTextTarget::scale(SkScalar sx, SkScalar sy) { this->accessCTM()->preScale(sx, sy); }
-
-void SkAtlasTextTarget::rotate(SkScalar degrees) { this->accessCTM()->preRotate(degrees); }
-
-void SkAtlasTextTarget::rotate(SkScalar degrees, SkScalar px, SkScalar py) {
- this->accessCTM()->preRotate(degrees, px, py);
-}
-
-void SkAtlasTextTarget::skew(SkScalar sx, SkScalar sy) { this->accessCTM()->preSkew(sx, sy); }
-
-void SkAtlasTextTarget::concat(const SkMatrix& matrix) { this->accessCTM()->preConcat(matrix); }
-
-//////////////////////////////////////////////////////////////////////////////
-
-static const GrColorInfo kColorInfo(GrColorType::kRGBA_8888, kPremul_SkAlphaType, nullptr);
-static const SkSurfaceProps kProps(
- SkSurfaceProps::kUseDistanceFieldFonts_Flag, kUnknown_SkPixelGeometry);
-
-//////////////////////////////////////////////////////////////////////////////
-
-class SkInternalAtlasTextTarget : public GrTextTarget, public SkAtlasTextTarget {
-public:
- SkInternalAtlasTextTarget(sk_sp<SkAtlasTextContext> context, int width, int height,
- void* handle)
- : GrTextTarget(width, height, kColorInfo)
- , SkAtlasTextTarget(std::move(context), width, height, handle)
- , fGlyphPainter(kProps, kColorInfo) {}
-
- ~SkInternalAtlasTextTarget() override {
- this->deleteOps();
- }
-
- /** GrTextTarget overrides */
-
- void addDrawOp(const GrClip&, std::unique_ptr<GrAtlasTextOp> op) override;
-
- void drawShape(const GrClip&,
- const SkPaint&,
- const SkMatrixProvider&,
- const GrStyledShape&) override {
- SkDebugf("Path glyph??");
- }
-
- void makeGrPaint(GrMaskFormat,
- const SkPaint& skPaint,
- const SkMatrixProvider&,
- GrPaint* grPaint) override {
- grPaint->setColor4f(skPaint.getColor4f().premul());
- }
-
- GrContext* getContext() override {
- return this->context()->internal().grContext();
- }
-
- SkGlyphRunListPainter* glyphPainter() override {
- return &fGlyphPainter;
- }
-
- /** SkAtlasTextTarget overrides */
-
- void drawText(const SkGlyphID[], const SkPoint[], int glyphCnt, uint32_t color,
- const SkAtlasTextFont&) override;
- void flush() override;
-
-private:
- void deleteOps();
-
- GrRecordingContext::Arenas arenas() {
- return fContext->internal().grContext()->GrRecordingContext::priv().arenas();
- }
-
- uint32_t fColor;
- using SkAtlasTextTarget::fWidth;
- using SkAtlasTextTarget::fHeight;
- SkTArray<std::unique_ptr<GrAtlasTextOp>, true> fOps;
- SkGlyphRunListPainter fGlyphPainter;
-};
-
-//////////////////////////////////////////////////////////////////////////////
-
-std::unique_ptr<SkAtlasTextTarget> SkAtlasTextTarget::Make(sk_sp<SkAtlasTextContext> context,
- int width, int height, void* handle) {
- return std::unique_ptr<SkAtlasTextTarget>(
- new SkInternalAtlasTextTarget(std::move(context), width, height, handle));
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void SkInternalAtlasTextTarget::drawText(const SkGlyphID glyphs[], const SkPoint positions[],
- int glyphCnt, uint32_t color,
- const SkAtlasTextFont& font) {
- SkPaint paint;
- paint.setAntiAlias(true);
-
- // The atlas text context does munging of the paint color. We store the client's color here
- // and then overwrite the generated op's color when addDrawOp() is called.
- fColor = color;
-
- SkSurfaceProps props(SkSurfaceProps::kUseDistanceFieldFonts_Flag, kUnknown_SkPixelGeometry);
- auto grContext = this->context()->internal().grContext();
- auto atlasTextContext = grContext->priv().drawingManager()->getTextContext();
- SkGlyphRunBuilder builder;
- builder.drawGlyphsWithPositions(paint, font.makeFont(),
- SkSpan<const SkGlyphID>{glyphs, SkTo<size_t>(glyphCnt)},
- positions);
- auto glyphRunList = builder.useGlyphRunList();
- if (!glyphRunList.empty()) {
- SkSimpleMatrixProvider matrixProvider(this->ctm());
- atlasTextContext->drawGlyphRunList(grContext, this, GrNoClip(), matrixProvider, props,
- glyphRunList);
- }
-}
-
-void SkInternalAtlasTextTarget::addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) {
- SkASSERT(clip.quickContains(SkRect::MakeIWH(fWidth, fHeight)));
- // The SkAtlasTextRenderer currently only handles grayscale SDF glyphs.
- if (op->maskType() != GrAtlasTextOp::kGrayscaleDistanceField_MaskType) {
- return;
- }
- const GrCaps& caps = *this->context()->internal().grContext()->priv().caps();
- op->finalizeForTextTarget(fColor, caps);
- int n = std::min(kMaxBatchLookBack, fOps.count());
-
- GrRecordingContext::Arenas arenas = this->arenas();
- for (int i = 0; i < n; ++i) {
- GrAtlasTextOp* other = fOps.fromBack(i).get();
- if (other->combineIfPossible(op.get(), &arenas, caps) == GrOp::CombineResult::kMerged) {
- arenas.opMemoryPool()->release(std::move(op));
- return;
- }
- if (GrRectsOverlap(op->bounds(), other->bounds())) {
- break;
- }
- }
- fOps.emplace_back(std::move(op));
-}
-
-void SkInternalAtlasTextTarget::deleteOps() {
- GrOpMemoryPool* pool = this->arenas().opMemoryPool();
- for (int i = 0; i < fOps.count(); ++i) {
- if (fOps[i]) {
- pool->release(std::move(fOps[i]));
- }
- }
- fOps.reset();
-}
-
-void SkInternalAtlasTextTarget::flush() {
- for (int i = 0; i < fOps.count(); ++i) {
- fOps[i]->executeForTextTarget(this);
- }
- this->context()->internal().flush();
- this->deleteOps();
-}
-
-void GrAtlasTextOp::finalizeForTextTarget(uint32_t color, const GrCaps& caps) {
- // TODO4F: Odd handling of client colors among AtlasTextTarget and AtlasTextRenderer
- SkPMColor4f color4f = SkPMColor4f::FromBytes_RGBA(color);
- for (int i = 0; i < fGeoCount; ++i) {
- fGeoData[i].fColor = color4f;
- }
- // Atlas text doesn't use MSAA, so no need to handle mixed samples.
- // Also, no need to support normalized F16 with manual clamp?
- this->finalize(caps, nullptr /* applied clip */, false /* mixed samples */, GrClampType::kAuto);
-}
-
-void GrAtlasTextOp::executeForTextTarget(SkAtlasTextTarget* target) {
- auto& context = target->context()->internal();
- auto atlasManager = context.grContext()->priv().getAtlasManager();
- auto resourceProvider = context.grContext()->priv().resourceProvider();
-
- unsigned int numProxies;
- if (!atlasManager->getViews(kA8_GrMaskFormat, &numProxies)) {
- return;
- }
-
- for (int i = 0; i < fGeoCount; ++i) {
- auto subRun = fGeoData[i].fSubRunPtr;
- subRun->prepareGrGlyphs(context.grContext()->priv().getGrStrikeCache());
- // TODO4F: Preserve float colors
- subRun->updateVerticesColorIfNeeded(fGeoData[i].fColor.toBytes_RGBA());
- subRun->translateVerticesIfNeeded(fGeoData[i].fDrawMatrix, fGeoData[i].fDrawOrigin);
- GrTextBlob::VertexRegenerator regenerator(resourceProvider, subRun, &context, atlasManager);
- int subRunEnd = subRun->fGlyphs.count();
- for (int subRunIndex = 0; subRunIndex < subRunEnd;) {
- auto [ok, glyphsRegenerated] = regenerator.regenerate(subRunIndex, subRunEnd);
- if (!ok) {
- break;
- }
-
- context.recordDraw(subRun->quadStart(subRunIndex), glyphsRegenerated,
- fGeoData[i].fDrawMatrix, target->handle());
- subRunIndex += glyphsRegenerated;
- if (subRunIndex != subRunEnd) {
- // Make space in the atlas so we can continue generating vertices.
- context.flush();
- }
- }
- }
-}
diff --git a/chromium/third_party/skia/src/atlastext/SkInternalAtlasTextContext.cpp b/chromium/third_party/skia/src/atlastext/SkInternalAtlasTextContext.cpp
deleted file mode 100644
index afab657f748..00000000000
--- a/chromium/third_party/skia/src/atlastext/SkInternalAtlasTextContext.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "include/atlastext/SkAtlasTextContext.h"
-#include "include/atlastext/SkAtlasTextRenderer.h"
-#include "include/gpu/GrContext.h"
-#include "src/atlastext/SkInternalAtlasTextContext.h"
-#include "src/gpu/GrContextPriv.h"
-#include "src/gpu/text/GrAtlasManager.h"
-#include "src/gpu/text/GrStrikeCache.h"
-
-SkAtlasTextRenderer* SkGetAtlasTextRendererFromInternalContext(
- class SkInternalAtlasTextContext& internal) {
- return internal.renderer();
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-std::unique_ptr<SkInternalAtlasTextContext> SkInternalAtlasTextContext::Make(
- sk_sp<SkAtlasTextRenderer> renderer) {
- return std::unique_ptr<SkInternalAtlasTextContext>(
- new SkInternalAtlasTextContext(std::move(renderer)));
-}
-
-SkInternalAtlasTextContext::SkInternalAtlasTextContext(sk_sp<SkAtlasTextRenderer> renderer)
- : fRenderer(std::move(renderer)) {
- GrContextOptions options;
- options.fAllowMultipleGlyphCacheTextures = GrContextOptions::Enable::kNo;
- options.fMinDistanceFieldFontSize = 0.f;
- options.fGlyphsAsPathsFontSize = SK_ScalarInfinity;
- options.fDistanceFieldGlyphVerticesAlwaysHaveW = GrContextOptions::Enable::kYes;
- fGrContext = GrContext::MakeMock(nullptr, options);
-}
-
-SkInternalAtlasTextContext::~SkInternalAtlasTextContext() {
- if (fDistanceFieldAtlas.fProxy) {
-#ifdef SK_DEBUG
- auto atlasManager = fGrContext->priv().getAtlasManager();
- if (atlasManager) {
- unsigned int numProxies;
- atlasManager->getViews(kA8_GrMaskFormat, &numProxies);
- SkASSERT(1 == numProxies);
- }
-#endif
- fRenderer->deleteTexture(fDistanceFieldAtlas.fTextureHandle);
- }
-}
-
-GrTextBlobCache* SkInternalAtlasTextContext::textBlobCache() {
- return fGrContext->priv().getTextBlobCache();
-}
-
-GrDeferredUploadToken SkInternalAtlasTextContext::addInlineUpload(
- GrDeferredTextureUploadFn&& upload) {
- auto token = fTokenTracker.nextDrawToken();
- fInlineUploads.append(&fArena, InlineUpload{std::move(upload), token});
- return token;
-}
-
-GrDeferredUploadToken SkInternalAtlasTextContext::addASAPUpload(
- GrDeferredTextureUploadFn&& upload) {
- fASAPUploads.append(&fArena, std::move(upload));
- return fTokenTracker.nextTokenToFlush();
-}
-
-void SkInternalAtlasTextContext::recordDraw(const void* srcVertexData, int glyphCnt,
- const SkMatrix& matrix, void* targetHandle) {
- auto vertexDataSize = sizeof(SkAtlasTextRenderer::SDFVertex) * 4 * glyphCnt;
- auto vertexData = fArena.makeArrayDefault<char>(vertexDataSize);
- memcpy(vertexData, srcVertexData, vertexDataSize);
- for (int i = 0; i < 4 * glyphCnt; ++i) {
- auto* vertex = reinterpret_cast<SkAtlasTextRenderer::SDFVertex*>(vertexData) + i;
- // GrTextContext encodes a texture index into the lower bit of each texture coord.
- // This isn't expected by SkAtlasTextRenderer subclasses.
- vertex->fTextureCoordX /= 2;
- vertex->fTextureCoordY /= 2;
- matrix.mapHomogeneousPoints(&vertex->fPosition, &vertex->fPosition, 1);
- }
- fDraws.append(&fArena,
- Draw{glyphCnt, fTokenTracker.issueDrawToken(), targetHandle, vertexData});
-}
-
-void SkInternalAtlasTextContext::flush() {
- auto* atlasManager = fGrContext->priv().getAtlasManager();
- if (!fDistanceFieldAtlas.fProxy) {
- unsigned int numProxies;
- fDistanceFieldAtlas.fProxy =
- atlasManager->getViews(kA8_GrMaskFormat, &numProxies)->asTextureProxy();
- SkASSERT(1 == numProxies);
- fDistanceFieldAtlas.fTextureHandle =
- fRenderer->createTexture(SkAtlasTextRenderer::AtlasFormat::kA8,
- fDistanceFieldAtlas.fProxy->width(),
- fDistanceFieldAtlas.fProxy->height());
- }
- GrDeferredTextureUploadWritePixelsFn writePixelsFn =
- [this](GrTextureProxy* proxy, int left, int top, int width, int height,
- GrColorType colorType, const void* data, size_t rowBytes) -> bool {
- SkASSERT(GrColorType::kAlpha_8 == colorType);
- SkASSERT(proxy == this->fDistanceFieldAtlas.fProxy);
- void* handle = fDistanceFieldAtlas.fTextureHandle;
- this->fRenderer->setTextureData(handle, data, left, top, width, height, rowBytes);
- return true;
- };
- for (const auto& upload : fASAPUploads) {
- upload(writePixelsFn);
- }
- auto inlineUpload = fInlineUploads.begin();
- for (const auto& draw : fDraws) {
- while (inlineUpload != fInlineUploads.end() && inlineUpload->fToken == draw.fToken) {
- inlineUpload->fUpload(writePixelsFn);
- ++inlineUpload;
- }
- auto vertices = reinterpret_cast<const SkAtlasTextRenderer::SDFVertex*>(draw.fVertexData);
- fRenderer->drawSDFGlyphs(draw.fTargetHandle, fDistanceFieldAtlas.fTextureHandle, vertices,
- draw.fGlyphCnt);
- fTokenTracker.flushToken();
- }
- fASAPUploads.reset();
- fInlineUploads.reset();
- fDraws.reset();
- fArena.reset();
-}
diff --git a/chromium/third_party/skia/src/atlastext/SkInternalAtlasTextContext.h b/chromium/third_party/skia/src/atlastext/SkInternalAtlasTextContext.h
deleted file mode 100644
index 81b6df02e54..00000000000
--- a/chromium/third_party/skia/src/atlastext/SkInternalAtlasTextContext.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkInternalAtlasTextContext_DEFINED
-#define SkInternalAtlasTextContext_DEFINED
-
-#include "include/core/SkRefCnt.h"
-#include "src/core/SkArenaAlloc.h"
-#include "src/core/SkArenaAllocList.h"
-#include "src/gpu/GrDeferredUpload.h"
-
-class GrContext;
-class GrStrikeCache;
-class GrTextBlobCache;
-
-class SkAtlasTextRenderer;
-class SkMatrix;
-
-/**
- * The implementation of SkAtlasTextContext. This exists to hide the details from the public class.
- * and to be able to use other private types.
- */
-class SkInternalAtlasTextContext : public GrDeferredUploadTarget {
-public:
- static std::unique_ptr<SkInternalAtlasTextContext> Make(sk_sp<SkAtlasTextRenderer>);
-
- ~SkInternalAtlasTextContext() override;
-
- SkAtlasTextRenderer* renderer() const { return fRenderer.get(); }
-
- GrContext* grContext() const { return fGrContext.get(); }
- GrTextBlobCache* textBlobCache();
-
- const GrTokenTracker* tokenTracker() final { return &fTokenTracker; }
- GrDeferredUploadToken addInlineUpload(GrDeferredTextureUploadFn&&) final;
- GrDeferredUploadToken addASAPUpload(GrDeferredTextureUploadFn&&) final;
-
- void recordDraw(const void* vertexData, int glyphCnt, const SkMatrix&, void* targetHandle);
-
- void flush();
-
-private:
- class DeferredUploader;
- SkInternalAtlasTextContext() = delete;
- SkInternalAtlasTextContext(const SkInternalAtlasTextContext&) = delete;
- SkInternalAtlasTextContext& operator=(const SkInternalAtlasTextContext&) = delete;
-
- SkInternalAtlasTextContext(sk_sp<SkAtlasTextRenderer>);
-
- sk_sp<SkAtlasTextRenderer> fRenderer;
-
- struct AtlasTexture {
- void* fTextureHandle = nullptr;
- GrTextureProxy* fProxy = nullptr;
- };
-
- struct Draw {
- int fGlyphCnt;
- GrDeferredUploadToken fToken;
- void* fTargetHandle;
- const void* fVertexData;
- };
-
- struct InlineUpload {
- GrDeferredTextureUploadFn fUpload;
- GrDeferredUploadToken fToken;
- };
-
- GrTokenTracker fTokenTracker;
- SkArenaAllocList<InlineUpload> fInlineUploads;
- SkArenaAllocList<Draw> fDraws;
- SkArenaAllocList<GrDeferredTextureUploadFn> fASAPUploads;
- SkArenaAlloc fArena{1024 * 40};
- sk_sp<GrContext> fGrContext;
- AtlasTexture fDistanceFieldAtlas;
-};
-
-#endif
diff --git a/chromium/third_party/skia/src/codec/SkBmpCodec.cpp b/chromium/third_party/skia/src/codec/SkBmpCodec.cpp
index 615c8a42125..c113f6da153 100644
--- a/chromium/third_party/skia/src/codec/SkBmpCodec.cpp
+++ b/chromium/third_party/skia/src/codec/SkBmpCodec.cpp
@@ -394,7 +394,7 @@ SkCodec::Result SkBmpCodec::ReadHeader(SkStream* stream, bool inIco,
inputFormat = kRLE_BmpInputFormat;
break;
}
- // Fall through
+ [[fallthrough]];
case kPng_BmpCompressionMethod:
// TODO: Decide if we intend to support this.
// It is unsupported in the previous version and
diff --git a/chromium/third_party/skia/src/codec/SkCodecPriv.h b/chromium/third_party/skia/src/codec/SkCodecPriv.h
index 2f77fc70e22..b371a31483d 100644
--- a/chromium/third_party/skia/src/codec/SkCodecPriv.h
+++ b/chromium/third_party/skia/src/codec/SkCodecPriv.h
@@ -141,7 +141,7 @@ static inline size_t compute_row_bytes(int width, uint32_t bitsPerPixel) {
* Get a byte from a buffer
* This method is unsafe, the caller is responsible for performing a check
*/
-static inline uint8_t get_byte(uint8_t* buffer, uint32_t i) {
+static inline uint8_t get_byte(const uint8_t* buffer, uint32_t i) {
return buffer[i];
}
@@ -149,7 +149,7 @@ static inline uint8_t get_byte(uint8_t* buffer, uint32_t i) {
* Get a short from a buffer
* This method is unsafe, the caller is responsible for performing a check
*/
-static inline uint16_t get_short(uint8_t* buffer, uint32_t i) {
+static inline uint16_t get_short(const uint8_t* buffer, uint32_t i) {
uint16_t result;
memcpy(&result, &(buffer[i]), 2);
#ifdef SK_CPU_BENDIAN
@@ -163,7 +163,7 @@ static inline uint16_t get_short(uint8_t* buffer, uint32_t i) {
* Get an int from a buffer
* This method is unsafe, the caller is responsible for performing a check
*/
-static inline uint32_t get_int(uint8_t* buffer, uint32_t i) {
+static inline uint32_t get_int(const uint8_t* buffer, uint32_t i) {
uint32_t result;
memcpy(&result, &(buffer[i]), 4);
#ifdef SK_CPU_BENDIAN
diff --git a/chromium/third_party/skia/src/codec/SkIcoCodec.cpp b/chromium/third_party/skia/src/codec/SkIcoCodec.cpp
index e70a9cded42..0aaf5e0aa18 100644
--- a/chromium/third_party/skia/src/codec/SkIcoCodec.cpp
+++ b/chromium/third_party/skia/src/codec/SkIcoCodec.cpp
@@ -13,6 +13,7 @@
#include "src/codec/SkCodecPriv.h"
#include "src/codec/SkIcoCodec.h"
#include "src/codec/SkPngCodec.h"
+#include "src/core/SkStreamPriv.h"
#include "src/core/SkTSort.h"
/*
@@ -28,20 +29,35 @@ bool SkIcoCodec::IsIco(const void* buffer, size_t bytesRead) {
std::unique_ptr<SkCodec> SkIcoCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
Result* result) {
+ // It is helpful to have the entire stream in a contiguous buffer. In some cases,
+ // this is already the case anyway, so this method is faster. In others, this is
+ // safer than the old method, which required allocating a block of memory whose
+ // byte size is stored in the stream as a uint32_t, and may result in a large or
+ // failed allocation.
+ sk_sp<SkData> data = nullptr;
+ if (stream->getMemoryBase()) {
+ // It is safe to make without copy because we'll hold onto the stream.
+ data = SkData::MakeWithoutCopy(stream->getMemoryBase(), stream->getLength());
+ } else {
+ data = SkCopyStreamToData(stream.get());
+
+ // If we are forced to copy the stream to a data, we can go ahead and delete the stream.
+ stream.reset(nullptr);
+ }
+
// Header size constants
constexpr uint32_t kIcoDirectoryBytes = 6;
constexpr uint32_t kIcoDirEntryBytes = 16;
// Read the directory header
- std::unique_ptr<uint8_t[]> dirBuffer(new uint8_t[kIcoDirectoryBytes]);
- if (stream->read(dirBuffer.get(), kIcoDirectoryBytes) != kIcoDirectoryBytes) {
+ if (data->size() < kIcoDirectoryBytes) {
SkCodecPrintf("Error: unable to read ico directory header.\n");
*result = kIncompleteInput;
return nullptr;
}
// Process the directory header
- const uint16_t numImages = get_short(dirBuffer.get(), 4);
+ const uint16_t numImages = get_short(data->bytes(), 4);
if (0 == numImages) {
SkCodecPrintf("Error: No images embedded in ico.\n");
*result = kInvalidInput;
@@ -66,8 +82,8 @@ std::unique_ptr<SkCodec> SkIcoCodec::MakeFromStream(std::unique_ptr<SkStream> st
// Iterate over directory entries
for (uint32_t i = 0; i < numImages; i++) {
- uint8_t entryBuffer[kIcoDirEntryBytes];
- if (stream->read(entryBuffer, kIcoDirEntryBytes) != kIcoDirEntryBytes) {
+ const uint8_t* entryBuffer = data->bytes() + kIcoDirectoryBytes + i * kIcoDirEntryBytes;
+ if (data->size() < kIcoDirectoryBytes + (i+1) * kIcoDirEntryBytes) {
SkCodecPrintf("Error: Dir entries truncated in ico.\n");
*result = kIncompleteInput;
return nullptr;
@@ -123,45 +139,36 @@ std::unique_ptr<SkCodec> SkIcoCodec::MakeFromStream(std::unique_ptr<SkStream> st
// If we cannot skip, assume we have reached the end of the stream and
// stop trying to make codecs
- if (stream->skip(offset - bytesRead) != offset - bytesRead) {
+ if (offset >= data->size()) {
SkCodecPrintf("Warning: could not skip to ico offset.\n");
break;
}
bytesRead = offset;
- // Create a new stream for the embedded codec
- SkAutoFree buffer(sk_malloc_canfail(size));
- if (!buffer) {
- SkCodecPrintf("Warning: OOM trying to create embedded stream.\n");
- break;
- }
-
- if (stream->read(buffer.get(), size) != size) {
+ if (offset + size > data->size()) {
SkCodecPrintf("Warning: could not create embedded stream.\n");
*result = kIncompleteInput;
break;
}
- sk_sp<SkData> data(SkData::MakeFromMalloc(buffer.release(), size));
- auto embeddedStream = SkMemoryStream::Make(data);
+ sk_sp<SkData> embeddedData(SkData::MakeSubset(data.get(), offset, size));
+ auto embeddedStream = SkMemoryStream::Make(embeddedData);
bytesRead += size;
// Check if the embedded codec is bmp or png and create the codec
std::unique_ptr<SkCodec> codec;
Result dummyResult;
- if (SkPngCodec::IsPng((const char*) data->bytes(), data->size())) {
+ if (SkPngCodec::IsPng(embeddedData->bytes(), embeddedData->size())) {
codec = SkPngCodec::MakeFromStream(std::move(embeddedStream), &dummyResult);
} else {
codec = SkBmpCodec::MakeFromIco(std::move(embeddedStream), &dummyResult);
}
- // Save a valid codec
if (nullptr != codec) {
codecs->push_back().reset(codec.release());
}
}
- // Recognize if there are no valid codecs
if (0 == codecs->count()) {
SkCodecPrintf("Error: could not find any valid embedded ico codecs.\n");
return nullptr;
@@ -183,15 +190,15 @@ std::unique_ptr<SkCodec> SkIcoCodec::MakeFromStream(std::unique_ptr<SkStream> st
auto maxInfo = codecs->operator[](maxIndex)->getEncodedInfo().copy();
*result = kSuccess;
- // The original stream is no longer needed, because the embedded codecs own their
- // own streams.
- return std::unique_ptr<SkCodec>(new SkIcoCodec(std::move(maxInfo), codecs.release()));
+ return std::unique_ptr<SkCodec>(new SkIcoCodec(std::move(maxInfo), std::move(stream),
+ codecs.release()));
}
-SkIcoCodec::SkIcoCodec(SkEncodedInfo&& info, SkTArray<std::unique_ptr<SkCodec>, true>* codecs)
+SkIcoCodec::SkIcoCodec(SkEncodedInfo&& info, std::unique_ptr<SkStream> stream,
+ SkTArray<std::unique_ptr<SkCodec>, true>* codecs)
// The source skcms_PixelFormat will not be used. The embedded
// codec's will be used instead.
- : INHERITED(std::move(info), skcms_PixelFormat(), nullptr)
+ : INHERITED(std::move(info), skcms_PixelFormat(), std::move(stream))
, fEmbeddedCodecs(codecs)
, fCurrCodec(nullptr)
{}
diff --git a/chromium/third_party/skia/src/codec/SkIcoCodec.h b/chromium/third_party/skia/src/codec/SkIcoCodec.h
index c1b27dc50d8..9888dc2b3b9 100644
--- a/chromium/third_party/skia/src/codec/SkIcoCodec.h
+++ b/chromium/third_party/skia/src/codec/SkIcoCodec.h
@@ -86,7 +86,8 @@ private:
* Constructor called by NewFromStream
* @param embeddedCodecs codecs for the embedded images, takes ownership
*/
- SkIcoCodec(SkEncodedInfo&& info, SkTArray<std::unique_ptr<SkCodec>, true>* embeddedCodecs);
+ SkIcoCodec(SkEncodedInfo&& info, std::unique_ptr<SkStream>,
+ SkTArray<std::unique_ptr<SkCodec>, true>* embeddedCodecs);
std::unique_ptr<SkTArray<std::unique_ptr<SkCodec>, true>> fEmbeddedCodecs;
diff --git a/chromium/third_party/skia/src/codec/SkPngCodec.cpp b/chromium/third_party/skia/src/codec/SkPngCodec.cpp
index c17070c07c0..df77b3aac09 100644
--- a/chromium/third_party/skia/src/codec/SkPngCodec.cpp
+++ b/chromium/third_party/skia/src/codec/SkPngCodec.cpp
@@ -1018,8 +1018,7 @@ SkCodec::Result SkPngCodec::initializeXforms(const SkImageInfo& dstInfo, const O
if (this->getEncodedInfo().bitsPerComponent() != 16) {
break;
}
-
- // Fall through
+ [[fallthrough]];
case SkEncodedInfo::kRGBA_Color:
case SkEncodedInfo::kGray_Color:
skipFormatConversion = this->colorXform();
diff --git a/chromium/third_party/skia/src/codec/SkWebpCodec.cpp b/chromium/third_party/skia/src/codec/SkWebpCodec.cpp
index 6cea0c621c5..e9019572cdf 100644
--- a/chromium/third_party/skia/src/codec/SkWebpCodec.cpp
+++ b/chromium/third_party/skia/src/codec/SkWebpCodec.cpp
@@ -143,7 +143,7 @@ std::unique_ptr<SkCodec> SkWebpCodec::MakeFromStream(std::unique_ptr<SkStream> s
// sense to guess kBGRA which is likely closer to the final
// output. Otherwise, we might end up converting
// BGRA->YUVA->BGRA.
- // Fallthrough:
+ [[fallthrough]];
case 2:
// This is the lossless format (BGRA).
if (hasAlpha) {
@@ -224,9 +224,7 @@ int SkWebpCodec::onGetRepetitionCount() {
return kRepetitionCountInfinite;
}
-#ifndef SK_LEGACY_WEBP_LOOP_COUNT
loopCount--;
-#endif
return loopCount;
}
diff --git a/chromium/third_party/skia/src/codec/SkWuffsCodec.cpp b/chromium/third_party/skia/src/codec/SkWuffsCodec.cpp
index 88394b3c80b..d7e11eba242 100644
--- a/chromium/third_party/skia/src/codec/SkWuffsCodec.cpp
+++ b/chromium/third_party/skia/src/codec/SkWuffsCodec.cpp
@@ -35,7 +35,11 @@
#if defined(WUFFS_IMPLEMENTATION)
#error "SkWuffsCodec should not #define WUFFS_IMPLEMENTATION"
#endif
+#ifdef SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2
+#include "wuffs-v0.3.c"
+#else
#include "wuffs-v0.2.c"
+#endif
#if WUFFS_VERSION_BUILD_METADATA_COMMIT_COUNT < 1942
#error "Wuffs version is too old. Upgrade to the latest version."
#endif
@@ -84,6 +88,8 @@ static bool seek_buffer(wuffs_base__io_buffer* b, SkStream* s, uint64_t pos) {
return true;
}
+#ifdef SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2
+#else
static SkEncodedInfo::Alpha wuffs_blend_to_skia_alpha(wuffs_base__animation_blend w) {
return (w == WUFFS_BASE__ANIMATION_BLEND__OPAQUE) ? SkEncodedInfo::kOpaque_Alpha
: SkEncodedInfo::kUnpremul_Alpha;
@@ -93,6 +99,7 @@ static SkCodecAnimation::Blend wuffs_blend_to_skia_blend(wuffs_base__animation_b
return (w == WUFFS_BASE__ANIMATION_BLEND__SRC) ? SkCodecAnimation::Blend::kBG
: SkCodecAnimation::Blend::kPriorFrame;
}
+#endif
static SkCodecAnimation::DisposalMethod wuffs_disposal_to_skia_disposal(
wuffs_base__animation_disposal w) {
@@ -116,8 +123,25 @@ static SkCodec::Result reset_and_decode_image_config(wuffs_gif__decoder* d
SkStream* s) {
// Calling decoder->initialize will memset most or all of it to zero,
// depending on SK_WUFFS_INITIALIZE_FLAGS.
- const char* status =
+ wuffs_base__status status =
decoder->initialize(sizeof__wuffs_gif__decoder(), WUFFS_VERSION, SK_WUFFS_INITIALIZE_FLAGS);
+#ifdef SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2
+ if (status.repr != nullptr) {
+ SkCodecPrintf("initialize: %s", status.message());
+ return SkCodec::kInternalError;
+ }
+ while (true) {
+ status = decoder->decode_image_config(imgcfg, b);
+ if (status.repr == nullptr) {
+ break;
+ } else if (status.repr != wuffs_base__suspension__short_read) {
+ SkCodecPrintf("decode_image_config: %s", status.message());
+ return SkCodec::kErrorInInput;
+ } else if (!fill_buffer(b, s)) {
+ return SkCodec::kIncompleteInput;
+ }
+ }
+#else
if (status != nullptr) {
SkCodecPrintf("initialize: %s", status);
return SkCodec::kInternalError;
@@ -133,12 +157,13 @@ static SkCodec::Result reset_and_decode_image_config(wuffs_gif__decoder* d
return SkCodec::kIncompleteInput;
}
}
+#endif
// A GIF image's natural color model is indexed color: 1 byte per pixel,
// indexing a 256-element palette.
//
// For Skia, we override that to decode to 4 bytes per pixel, BGRA or RGBA.
- wuffs_base__pixel_format pixfmt = 0;
+ uint32_t pixfmt = WUFFS_BASE__PIXEL_FORMAT__INVALID;
switch (kN32_SkColorType) {
case kBGRA_8888_SkColorType:
pixfmt = WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL;
@@ -266,12 +291,12 @@ private:
// RGB565). But as an optimization, we use one pass decoding (it's faster
// and uses less memory) if applicable (see the assignment to
// fIncrDecOnePass that calculates when we can do so).
- Result onStartIncrementalDecodeOnePass(const SkImageInfo& dstInfo,
- uint8_t* dst,
- size_t rowBytes,
- const SkCodec::Options& options,
- wuffs_base__pixel_format pixelFormat,
- size_t bytesPerPixel);
+ Result onStartIncrementalDecodeOnePass(const SkImageInfo& dstInfo,
+ uint8_t* dst,
+ size_t rowBytes,
+ const SkCodec::Options& options,
+ uint32_t pixelFormat,
+ size_t bytesPerPixel);
Result onStartIncrementalDecodeTwoPass();
Result onIncrementalDecodeOnePass();
Result onIncrementalDecodeTwoPass();
@@ -334,12 +359,23 @@ private:
SkWuffsFrame::SkWuffsFrame(wuffs_base__frame_config* fc)
: INHERITED(fc->index()),
fIOPosition(fc->io_position()),
- fReportedAlpha(wuffs_blend_to_skia_alpha(fc->blend())) {
+#ifdef SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2
+ fReportedAlpha(fc->opaque_within_bounds() ? SkEncodedInfo::kOpaque_Alpha
+ : SkEncodedInfo::kUnpremul_Alpha)
+#else
+ fReportedAlpha(wuffs_blend_to_skia_alpha(fc->blend()))
+#endif
+{
wuffs_base__rect_ie_u32 r = fc->bounds();
this->setXYWH(r.min_incl_x, r.min_incl_y, r.width(), r.height());
this->setDisposalMethod(wuffs_disposal_to_skia_disposal(fc->disposal()));
this->setDuration(fc->duration() / WUFFS_BASE__FLICKS_PER_MILLISECOND);
+#ifdef SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2
+ this->setBlend(fc->overwrite_instead_of_blend() ? SkCodecAnimation::Blend::kBG
+ : SkCodecAnimation::Blend::kPriorFrame);
+#else
this->setBlend(wuffs_blend_to_skia_blend(fc->blend()));
+#endif
}
SkCodec::FrameInfo SkWuffsFrame::frameInfo(bool fullyReceived) const {
@@ -482,8 +518,8 @@ SkCodec::Result SkWuffsCodec::onStartIncrementalDecode(const SkImageInfo& d
return SkCodec::kErrorInInput;
}
- wuffs_base__pixel_format pixelFormat = WUFFS_BASE__PIXEL_FORMAT__INVALID;
- size_t bytesPerPixel = 0;
+ uint32_t pixelFormat = WUFFS_BASE__PIXEL_FORMAT__INVALID;
+ size_t bytesPerPixel = 0;
switch (dstInfo.colorType()) {
case kBGRA_8888_SkColorType:
@@ -527,11 +563,11 @@ SkCodec::Result SkWuffsCodec::onStartIncrementalDecode(const SkImageInfo& d
return SkCodec::kSuccess;
}
-SkCodec::Result SkWuffsCodec::onStartIncrementalDecodeOnePass(const SkImageInfo& dstInfo,
- uint8_t* dst,
- size_t rowBytes,
- const SkCodec::Options& options,
- wuffs_base__pixel_format pixelFormat,
+SkCodec::Result SkWuffsCodec::onStartIncrementalDecodeOnePass(const SkImageInfo& dstInfo,
+ uint8_t* dst,
+ size_t rowBytes,
+ const SkCodec::Options& options,
+ uint32_t pixelFormat,
size_t bytesPerPixel) {
wuffs_base__pixel_config pixelConfig;
pixelConfig.set(pixelFormat, WUFFS_BASE__PIXEL_SUBSAMPLING__NONE, dstInfo.width(),
@@ -543,11 +579,18 @@ SkCodec::Result SkWuffsCodec::onStartIncrementalDecodeOnePass(const SkImageInfo&
table.height = dstInfo.height();
table.stride = rowBytes;
- const char* status = fPixelBuffer.set_from_table(&pixelConfig, table);
+ wuffs_base__status status = fPixelBuffer.set_from_table(&pixelConfig, table);
+#ifdef SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2
+ if (status.repr != nullptr) {
+ SkCodecPrintf("set_from_table: %s", status.message());
+ return SkCodec::kInternalError;
+ }
+#else
if (status != nullptr) {
SkCodecPrintf("set_from_table: %s", status);
return SkCodec::kInternalError;
}
+#endif
SkSampler::Fill(dstInfo, dst, rowBytes, options.fZeroInitialized);
return SkCodec::kSuccess;
@@ -571,16 +614,27 @@ SkCodec::Result SkWuffsCodec::onStartIncrementalDecodeTwoPass() {
already_zeroed = true;
}
- const char* status = fPixelBuffer.set_from_slice(
+ wuffs_base__status status = fPixelBuffer.set_from_slice(
&fPixelConfig, wuffs_base__make_slice_u8(fTwoPassPixbufPtr.get(), fTwoPassPixbufLen));
+#ifdef SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2
+ if (status.repr != nullptr) {
+ SkCodecPrintf("set_from_slice: %s", status.message());
+ return SkCodec::kInternalError;
+ }
+#else
if (status != nullptr) {
SkCodecPrintf("set_from_slice: %s", status);
return SkCodec::kInternalError;
}
+#endif
if (!already_zeroed) {
+#ifdef SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2
+ uint32_t src_bits_per_pixel = fPixelConfig.pixel_format().bits_per_pixel();
+#else
uint32_t src_bits_per_pixel =
wuffs_base__pixel_format__bits_per_pixel(fPixelConfig.pixel_format());
+#endif
if ((src_bits_per_pixel == 0) || (src_bits_per_pixel % 8 != 0)) {
return SkCodec::kInternalError;
}
@@ -683,8 +737,12 @@ SkCodec::Result SkWuffsCodec::onIncrementalDecodeTwoPass() {
}
}
+#ifdef SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2
+ uint32_t src_bits_per_pixel = fPixelBuffer.pixcfg.pixel_format().bits_per_pixel();
+#else
uint32_t src_bits_per_pixel =
wuffs_base__pixel_format__bits_per_pixel(fPixelBuffer.pixcfg.pixel_format());
+#endif
if ((src_bits_per_pixel == 0) || (src_bits_per_pixel % 8 != 0)) {
return SkCodec::kInternalError;
}
@@ -755,7 +813,7 @@ SkCodec::Result SkWuffsCodec::onIncrementalDecodeTwoPass() {
SkRasterClip rc(SkIRect::MakeSize(this->dstInfo().dimensions()));
draw.fRC = &rc;
- SkMatrix translate = SkMatrix::MakeTrans(dirty_rect.min_incl_x, dirty_rect.min_incl_y);
+ SkMatrix translate = SkMatrix::Translate(dirty_rect.min_incl_x, dirty_rect.min_incl_y);
draw.drawBitmap(src, translate, nullptr, paint);
}
@@ -821,7 +879,11 @@ void SkWuffsCodec::onGetFrameCountInternal() {
const char* status = this->decodeFrameConfig(WhichDecoder::kFrameCount);
if (status == nullptr) {
// No-op.
+#ifdef SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2
+ } else if (status == wuffs_base__note__end_of_data) {
+#else
} else if (status == wuffs_base__warning__end_of_data) {
+#endif
break;
} else {
return;
@@ -893,11 +955,17 @@ SkCodec::Result SkWuffsCodec::seekFrame(WhichDecoder which, int frameIndex) {
if (!seek_buffer(&fIOBuffer, fStream.get(), pos)) {
return SkCodec::kInternalError;
}
- const char* status =
+ wuffs_base__status status =
fDecoders[which]->restart_frame(frameIndex, fIOBuffer.reader_io_position());
+#ifdef SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2
+ if (status.repr != nullptr) {
+ return SkCodec::kInternalError;
+ }
+#else
if (status != nullptr) {
return SkCodec::kInternalError;
}
+#endif
return SkCodec::kSuccess;
}
@@ -921,8 +989,17 @@ SkCodec::Result SkWuffsCodec::resetDecoder(WhichDecoder which) {
const char* SkWuffsCodec::decodeFrameConfig(WhichDecoder which) {
while (true) {
- const char* status =
+ wuffs_base__status status =
fDecoders[which]->decode_frame_config(&fFrameConfigs[which], &fIOBuffer);
+#ifdef SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2
+ if ((status.repr == wuffs_base__suspension__short_read) &&
+ fill_buffer(&fIOBuffer, fStream.get())) {
+ continue;
+ }
+ fDecoderIsSuspended[which] = !status.is_complete();
+ this->updateNumFullyReceivedFrames(which);
+ return status.repr;
+#else
if ((status == wuffs_base__suspension__short_read) &&
fill_buffer(&fIOBuffer, fStream.get())) {
continue;
@@ -930,11 +1007,24 @@ const char* SkWuffsCodec::decodeFrameConfig(WhichDecoder which) {
fDecoderIsSuspended[which] = !wuffs_base__status__is_complete(status);
this->updateNumFullyReceivedFrames(which);
return status;
+#endif
}
}
const char* SkWuffsCodec::decodeFrame(WhichDecoder which) {
while (true) {
+#ifdef SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2
+ wuffs_base__status status = fDecoders[which]->decode_frame(
+ &fPixelBuffer, &fIOBuffer, WUFFS_BASE__PIXEL_BLEND__SRC,
+ wuffs_base__make_slice_u8(fWorkbufPtr.get(), fWorkbufLen), NULL);
+ if ((status.repr == wuffs_base__suspension__short_read) &&
+ fill_buffer(&fIOBuffer, fStream.get())) {
+ continue;
+ }
+ fDecoderIsSuspended[which] = !status.is_complete();
+ this->updateNumFullyReceivedFrames(which);
+ return status.repr;
+#else
const char* status = fDecoders[which]->decode_frame(
&fPixelBuffer, &fIOBuffer, wuffs_base__make_slice_u8(fWorkbufPtr.get(), fWorkbufLen),
NULL);
@@ -945,6 +1035,7 @@ const char* SkWuffsCodec::decodeFrame(WhichDecoder which) {
fDecoderIsSuspended[which] = !wuffs_base__status__is_complete(status);
this->updateNumFullyReceivedFrames(which);
return status;
+#endif
}
}
@@ -1028,7 +1119,11 @@ std::unique_ptr<SkCodec> SkWuffsCodec_MakeFromStream(std::unique_ptr<SkStream> s
reinterpret_cast<uint8_t*>(workbuf_ptr_raw), &sk_free);
SkEncodedInfo::Color color =
+#ifdef SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2
+ (imgcfg.pixcfg.pixel_format().repr == WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL)
+#else
(imgcfg.pixcfg.pixel_format() == WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL)
+#endif
? SkEncodedInfo::kBGRA_Color
: SkEncodedInfo::kRGBA_Color;
diff --git a/chromium/third_party/skia/src/core/SkArenaAlloc.h b/chromium/third_party/skia/src/core/SkArenaAlloc.h
index 6ff7c6be9f6..22aecb52de6 100644
--- a/chromium/third_party/skia/src/core/SkArenaAlloc.h
+++ b/chromium/third_party/skia/src/core/SkArenaAlloc.h
@@ -101,12 +101,9 @@ public:
template <typename T>
T* makeArrayDefault(size_t count) {
- AssertRelease(SkTFitsIn<uint32_t>(count));
- uint32_t safeCount = ToU32(count);
- T* array = (T*)this->commonArrayAlloc<T>(safeCount);
-
- // If T is primitive then no initialization takes place.
- for (size_t i = 0; i < safeCount; i++) {
+ T* array = this->allocUninitializedArray<T>(count);
+ for (size_t i = 0; i < count; i++) {
+ // Default initialization: if T is primitive then the value is left uninitialized.
new (&array[i]) T;
}
return array;
@@ -114,18 +111,23 @@ public:
template <typename T>
T* makeArray(size_t count) {
- AssertRelease(SkTFitsIn<uint32_t>(count));
- uint32_t safeCount = ToU32(count);
- T* array = (T*)this->commonArrayAlloc<T>(safeCount);
-
- // If T is primitive then the memory is initialized. For example, an array of chars will
- // be zeroed.
- for (size_t i = 0; i < safeCount; i++) {
+ T* array = this->allocUninitializedArray<T>(count);
+ for (size_t i = 0; i < count; i++) {
+ // Value initialization: if T is primitive then the value is zero-initialized.
new (&array[i]) T();
}
return array;
}
+ template <typename T, typename Initializer>
+ T* makeInitializedArray(size_t count, Initializer initializer) {
+ T* array = this->allocUninitializedArray<T>(count);
+ for (size_t i = 0; i < count; i++) {
+ new (&array[i]) T(initializer(i));
+ }
+ return array;
+ }
+
// Only use makeBytesAlignedTo if none of the typed variants are impractical to use.
void* makeBytesAlignedTo(size_t size, size_t align) {
AssertRelease(SkTFitsIn<uint32_t>(size));
@@ -172,7 +174,10 @@ private:
char* allocObjectWithFooter(uint32_t sizeIncludingFooter, uint32_t alignment);
template <typename T>
- char* commonArrayAlloc(uint32_t count) {
+ T* allocUninitializedArray(size_t countZ) {
+ AssertRelease(SkTFitsIn<uint32_t>(countZ));
+ uint32_t count = ToU32(countZ);
+
char* objStart;
AssertRelease(count <= std::numeric_limits<uint32_t>::max() / sizeof(T));
uint32_t arraySize = ToU32(count * sizeof(T));
@@ -208,7 +213,7 @@ private:
padding);
}
- return objStart;
+ return (T*)objStart;
}
char* fDtorCursor;
diff --git a/chromium/third_party/skia/src/core/SkBitmapDevice.cpp b/chromium/third_party/skia/src/core/SkBitmapDevice.cpp
index 190182f390d..96e28a5d9f5 100644
--- a/chromium/third_party/skia/src/core/SkBitmapDevice.cpp
+++ b/chromium/third_party/skia/src/core/SkBitmapDevice.cpp
@@ -54,9 +54,9 @@ class SkDrawTiler {
SkDraw fDraw;
// fCurr... are only used if fNeedTiling
- SkTLazy<SkPostConcatMatrixProvider> fTileMatrixProvider;
- SkRasterClip fTileRC;
- SkIPoint fOrigin;
+ SkTLazy<SkPostTranslateMatrixProvider> fTileMatrixProvider;
+ SkRasterClip fTileRC;
+ SkIPoint fOrigin;
bool fDone, fNeedsTiling;
@@ -164,9 +164,9 @@ private:
SkASSERT_RELEASE(success);
// now don't use bounds, since fDst has the clipped dimensions.
- fDraw.fMatrixProvider = fTileMatrixProvider.init(
- fDevice->asMatrixProvider(),
- SkMatrix::MakeTrans(SkIntToScalar(-fOrigin.x()), SkIntToScalar(-fOrigin.y())));
+ fDraw.fMatrixProvider = fTileMatrixProvider.init(fDevice->asMatrixProvider(),
+ SkIntToScalar(-fOrigin.x()),
+ SkIntToScalar(-fOrigin.y()));
fDevice->fRCStack.rc().translate(-fOrigin.x(), -fOrigin.y(), &fTileRC);
fTileRC.op(SkIRect::MakeWH(fDraw.fDst.width(), fDraw.fDst.height()),
SkRegion::kIntersect_Op);
@@ -574,7 +574,7 @@ void SkBitmapDevice::drawDevice(SkBaseDevice* device, int x, int y, const SkPain
draw.fRC = &fRCStack.rc();
paint.writable()->setShader(src->fBitmap.makeShader());
draw.drawBitmap(*src->fCoverage.get(),
- SkMatrix::MakeTrans(SkIntToScalar(x),SkIntToScalar(y)), nullptr, *paint);
+ SkMatrix::Translate(SkIntToScalar(x),SkIntToScalar(y)), nullptr, *paint);
} else {
BDDraw(this).drawSprite(src->fBitmap, x, y, *paint);
}
@@ -593,32 +593,7 @@ void SkBitmapDevice::drawAtlas(const SkImage* atlas, const SkRSXform xform[],
///////////////////////////////////////////////////////////////////////////////
-namespace {
-
-class SkAutoDeviceClipRestore {
-public:
- SkAutoDeviceClipRestore(SkBaseDevice* device, const SkIRect& clip)
- : fDevice(device)
- , fPrevLocalToDevice(device->localToDevice44()) {
- fDevice->save();
- fDevice->setLocalToDevice(SkM44());
- fDevice->clipRect(SkRect::Make(clip), SkClipOp::kIntersect, false);
- fDevice->setLocalToDevice(fPrevLocalToDevice);
- }
-
- ~SkAutoDeviceClipRestore() {
- fDevice->restoreLocal(fPrevLocalToDevice);
- }
-
-private:
- SkBaseDevice* fDevice;
- const SkM44 fPrevLocalToDevice;
-};
-
-} // anonymous ns
-
-void SkBitmapDevice::drawSpecial(SkSpecialImage* src, int x, int y, const SkPaint& origPaint,
- SkImage* clipImage, const SkMatrix& clipMatrix) {
+void SkBitmapDevice::drawSpecial(SkSpecialImage* src, int x, int y, const SkPaint& origPaint) {
SkASSERT(!src->isTextureBacked());
SkASSERT(!origPaint.getMaskFilter());
@@ -628,7 +603,7 @@ void SkBitmapDevice::drawSpecial(SkSpecialImage* src, int x, int y, const SkPain
if (SkImageFilter* filter = paint->getImageFilter()) {
SkIPoint offset = SkIPoint::Make(0, 0);
const SkMatrix matrix = SkMatrix::Concat(
- SkMatrix::MakeTrans(SkIntToScalar(-x), SkIntToScalar(-y)), this->localToDevice());
+ SkMatrix::Translate(SkIntToScalar(-x), SkIntToScalar(-y)), this->localToDevice());
const SkIRect clipBounds = fRCStack.rc().getBounds().makeOffset(-x, -y);
sk_sp<SkImageFilterCache> cache(this->getImageFilterCache());
SkImageFilter_Base::Context ctx(matrix, clipBounds, cache.get(), fBitmap.colorType(),
@@ -645,68 +620,10 @@ void SkBitmapDevice::drawSpecial(SkSpecialImage* src, int x, int y, const SkPain
y += offset.y();
}
- if (!clipImage) {
- SkBitmap resultBM;
- if (src->getROPixels(&resultBM)) {
- BDDraw(this).drawSprite(resultBM, x, y, *paint);
- }
- return;
+ SkBitmap resultBM;
+ if (src->getROPixels(&resultBM)) {
+ BDDraw(this).drawSprite(resultBM, x, y, *paint);
}
-
- // Clip image case.
- sk_sp<SkImage> srcImage(src->asImage());
- if (!srcImage) {
- return;
- }
-
- const SkMatrix totalMatrix = SkMatrix::Concat(this->localToDevice(), clipMatrix);
- SkRect clipBounds;
- totalMatrix.mapRect(&clipBounds, SkRect::Make(clipImage->bounds()));
- const SkIRect srcBounds = srcImage->bounds().makeOffset(x, y);
-
- SkIRect maskBounds = fRCStack.rc().getBounds();
- if (!maskBounds.intersect(clipBounds.roundOut()) || !maskBounds.intersect(srcBounds)) {
- return;
- }
-
- sk_sp<SkImage> mask;
- SkMatrix maskMatrix, shaderMatrix;
- SkTLazy<SkAutoDeviceClipRestore> autoClipRestore;
-
- SkMatrix totalInverse;
- if (clipImage->isAlphaOnly() && totalMatrix.invert(&totalInverse)) {
- // If the mask is already in A8 format, we can draw it directly
- // (while compensating in the shader matrix).
- mask = sk_ref_sp(clipImage);
- maskMatrix = totalMatrix;
- shaderMatrix = SkMatrix::Concat(totalInverse, SkMatrix::MakeTrans(x, y));
-
- // If the mask is not fully contained within the src layer, we must clip.
- if (!srcBounds.contains(clipBounds)) {
- autoClipRestore.init(this, srcBounds);
- }
-
- maskBounds.offsetTo(0, 0);
- } else {
- // Otherwise, we convert the mask to A8 explicitly.
- sk_sp<SkSurface> surf = SkSurface::MakeRaster(SkImageInfo::MakeA8(maskBounds.width(),
- maskBounds.height()));
- SkCanvas* canvas = surf->getCanvas();
- canvas->translate(-maskBounds.x(), -maskBounds.y());
- canvas->concat(totalMatrix);
- canvas->drawImage(clipImage, 0, 0);
-
- mask = surf->makeImageSnapshot();
- maskMatrix = SkMatrix::I();
- shaderMatrix = SkMatrix::MakeTrans(x - maskBounds.x(), y - maskBounds.y());
- }
-
- SkAutoDeviceTransformRestore adr(this, maskMatrix);
- paint.writable()->setShader(srcImage->makeShader(&shaderMatrix));
- this->drawImageRect(mask.get(), nullptr,
- SkRect::MakeXYWH(maskBounds.x(), maskBounds.y(),
- mask->width(), mask->height()),
- *paint, SkCanvas::kFast_SrcRectConstraint);
}
sk_sp<SkSpecialImage> SkBitmapDevice::makeSpecial(const SkBitmap& bitmap) {
diff --git a/chromium/third_party/skia/src/core/SkBitmapDevice.h b/chromium/third_party/skia/src/core/SkBitmapDevice.h
index f6e14216ee3..7c359ea886a 100644
--- a/chromium/third_party/skia/src/core/SkBitmapDevice.h
+++ b/chromium/third_party/skia/src/core/SkBitmapDevice.h
@@ -101,8 +101,7 @@ protected:
///////////////////////////////////////////////////////////////////////////
- void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
- SkImage*, const SkMatrix&) override;
+ void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&) override;
sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override;
sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override;
sk_sp<SkSpecialImage> snapSpecial(const SkIRect&, bool = false) override;
diff --git a/chromium/third_party/skia/src/core/SkBitmapProcState_matrixProcs.cpp b/chromium/third_party/skia/src/core/SkBitmapProcState_matrixProcs.cpp
index d444b56c913..8fa1a0ba871 100755
--- a/chromium/third_party/skia/src/core/SkBitmapProcState_matrixProcs.cpp
+++ b/chromium/third_party/skia/src/core/SkBitmapProcState_matrixProcs.cpp
@@ -64,7 +64,7 @@ static void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int cou
SkASSERT(count <= 2);
switch (count) {
- case 2: ((uint16_t*)dst)[1] = SkToU16((fx + dx) >> 16);
+ case 2: ((uint16_t*)dst)[1] = SkToU16((fx + dx) >> 16); [[fallthrough]];
case 1: ((uint16_t*)dst)[0] = SkToU16((fx + 0) >> 16);
}
}
@@ -475,7 +475,7 @@ SkBitmapProcState::MatrixProc SkBitmapProcState::chooseMatrixProc(bool translate
// Check for our special case translate methods when there is no scale/affine/perspective.
if (translate_only_matrix && kNone_SkFilterQuality == fFilterQuality) {
switch (fTileModeX) {
- default: SkASSERT(false);
+ default: SkASSERT(false); [[fallthrough]];
case SkTileMode::kClamp: return clampx_nofilter_trans<int_clamp>;
case SkTileMode::kRepeat: return repeatx_nofilter_trans<int_repeat>;
case SkTileMode::kMirror: return mirrorx_nofilter_trans<int_mirror>;
diff --git a/chromium/third_party/skia/src/core/SkBlitter.cpp b/chromium/third_party/skia/src/core/SkBlitter.cpp
index 23373abe769..55fb32602d5 100644
--- a/chromium/third_party/skia/src/core/SkBlitter.cpp
+++ b/chromium/third_party/skia/src/core/SkBlitter.cpp
@@ -655,10 +655,7 @@ bool SkBlitter::UseRasterPipelineBlitter(const SkPixmap& device, const SkPaint&
// The legacy blitters cannot handle any of these complex features (anymore).
if (device.alphaType() == kUnpremul_SkAlphaType ||
- matrix.hasPerspective() ||
- paint.getColorFilter() ||
paint.getBlendMode() > SkBlendMode::kLastCoeffMode ||
- paint.getFilterQuality() == kHigh_SkFilterQuality ||
(mf && mf->getFormat() == SkMask::k3D_Format)) {
return true;
}
@@ -739,19 +736,31 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device,
paint.writable()->setDither(false);
}
- SkMatrix ctm = matrixProvider.localToDevice();
if (gUseSkVMBlitter) {
- if (auto blitter = SkCreateSkVMBlitter(device, *paint, ctm, alloc, clipShader)) {
+ if (auto blitter = SkCreateSkVMBlitter(device, *paint, matrixProvider,
+ alloc, clipShader)) {
return blitter;
}
}
+ // Same basic idea used a few times: try SkRP, then try SkVM, then give up with a null-blitter.
+ // (Setting gUseSkVMBlitter is the only way we prefer SkVM over SkRP at the moment.)
+ auto create_SkRP_or_SkVMBlitter = [&]() -> SkBlitter* {
+ if (auto blitter = SkCreateRasterPipelineBlitter(device, *paint, matrixProvider,
+ alloc, clipShader)) {
+ return blitter;
+ }
+ if (auto blitter = SkCreateSkVMBlitter(device, *paint, matrixProvider,
+ alloc, clipShader)) {
+ return blitter;
+ }
+ return alloc->make<SkNullBlitter>();
+ };
+
+ SkMatrix ctm = matrixProvider.localToDevice();
// We'll end here for many interesting cases: color spaces, color filters, most color types.
if (UseRasterPipelineBlitter(device, *paint, ctm) || clipShader) {
- auto blitter =
- SkCreateRasterPipelineBlitter(device, *paint, matrixProvider, alloc, clipShader);
- SkASSERT(blitter);
- return blitter;
+ return create_SkRP_or_SkVMBlitter();
}
// Everything but legacy kN32_SkColorType and kRGB_565_SkColorType should already be handled.
@@ -768,12 +777,9 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device,
{*paint, ctm, nullptr, device.colorType(), device.colorSpace()},
alloc);
- // Creating the context isn't always possible... we'll just fall back to raster pipeline.
+ // Creating the context isn't always possible... try fallbacks before giving up.
if (!shaderContext) {
- auto blitter = SkCreateRasterPipelineBlitter(device, *paint, matrixProvider, alloc,
- clipShader);
- SkASSERT(blitter);
- return blitter;
+ return create_SkRP_or_SkVMBlitter();
}
}
@@ -793,8 +799,7 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device,
if (shaderContext && SkRGB565_Shader_Blitter::Supports(device, *paint)) {
return alloc->make<SkRGB565_Shader_Blitter>(device, *paint, shaderContext);
} else {
- return SkCreateRasterPipelineBlitter(device, *paint, matrixProvider, alloc,
- clipShader);
+ return create_SkRP_or_SkVMBlitter();
}
default:
diff --git a/chromium/third_party/skia/src/core/SkBlitter_Sprite.cpp b/chromium/third_party/skia/src/core/SkBlitter_Sprite.cpp
index df7d9a70258..05f25bec16c 100644
--- a/chromium/third_party/skia/src/core/SkBlitter_Sprite.cpp
+++ b/chromium/third_party/skia/src/core/SkBlitter_Sprite.cpp
@@ -134,7 +134,7 @@ public:
: kPremul_SkAlphaType;
fAlloc->make<SkColorSpaceXformSteps>(srcCS, srcAT,
dstCS, kPremul_SkAlphaType)
- ->apply(&p, fSource.colorType());
+ ->apply(&p);
}
if (fPaintColor.fA != 1.0f) {
p.append(SkRasterPipeline::scale_1_float, &fPaintColor.fA);
@@ -142,6 +142,9 @@ public:
bool is_opaque = fSource.isOpaque() && fPaintColor.fA == 1.0f;
fBlitter = SkCreateRasterPipelineBlitter(fDst, paint, p, is_opaque, fAlloc, fClipShader);
+ if (!fBlitter) {
+ fBlitter = fAlloc->make<SkNullBlitter>();
+ }
}
void blitRect(int x, int y, int width, int height) override {
diff --git a/chromium/third_party/skia/src/core/SkBlurMF.cpp b/chromium/third_party/skia/src/core/SkBlurMF.cpp
index 14be316a231..9665ab4d6eb 100644
--- a/chromium/third_party/skia/src/core/SkBlurMF.cpp
+++ b/chromium/third_party/skia/src/core/SkBlurMF.cpp
@@ -21,7 +21,6 @@
#if SK_SUPPORT_GPU
#include "include/private/GrRecordingContext.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrFragmentProcessor.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
@@ -58,7 +57,7 @@ public:
bool directFilterMaskGPU(GrRecordingContext*,
GrRenderTargetContext* renderTargetContext,
GrPaint&&,
- const GrClip&,
+ const GrClip*,
const SkMatrix& viewMatrix,
const GrStyledShape& shape) const override;
GrSurfaceProxyView filterMaskGPU(GrRecordingContext*,
@@ -437,7 +436,7 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma
case SkRRect::kRect_Type:
// We should have caught this earlier.
SkASSERT(false);
- // Fall through.
+ [[fallthrough]];
case SkRRect::kOval_Type:
// The nine patch special case does not handle ovals, and we
// already have code for rectangles.
@@ -722,7 +721,7 @@ void SkBlurMaskFilterImpl::flatten(SkWriteBuffer& buffer) const {
bool SkBlurMaskFilterImpl::directFilterMaskGPU(GrRecordingContext* context,
GrRenderTargetContext* renderTargetContext,
GrPaint&& paint,
- const GrClip& clip,
+ const GrClip* clip,
const SkMatrix& viewMatrix,
const GrStyledShape& shape) const {
SkASSERT(renderTargetContext);
@@ -764,10 +763,12 @@ bool SkBlurMaskFilterImpl::directFilterMaskGPU(GrRecordingContext* context,
if (devRRect.isRect() || SkRRectPriv::IsCircle(devRRect)) {
if (devRRect.isRect()) {
- fp = GrRectBlurEffect::Make(context, *context->priv().caps()->shaderCaps(),
- devRRect.rect(), xformedSigma);
+ fp = GrRectBlurEffect::Make(
+ /*inputFP=*/nullptr, context, *context->priv().caps()->shaderCaps(),
+ devRRect.rect(), xformedSigma);
} else {
- fp = GrCircleBlurFragmentProcessor::Make(context, devRRect.rect(), xformedSigma);
+ fp = GrCircleBlurFragmentProcessor::Make(/*inputFP=*/nullptr, context, devRRect.rect(),
+ xformedSigma);
}
if (!fp) {
@@ -791,7 +792,8 @@ bool SkBlurMaskFilterImpl::directFilterMaskGPU(GrRecordingContext* context,
return true;
}
- fp = GrRRectBlurEffect::Make(context, fSigma, xformedSigma, srcRRect, devRRect);
+ fp = GrRRectBlurEffect::Make(/*inputFP=*/nullptr, context, fSigma, xformedSigma,
+ srcRRect, devRRect);
if (!fp) {
return false;
}
@@ -854,15 +856,13 @@ bool SkBlurMaskFilterImpl::canFilterMaskGPU(const GrStyledShape& shape,
}
// We prefer to blur paths with small blur radii on the CPU.
- if (ctm.rectStaysRect()) {
- static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64);
- static const SkScalar kMIN_GPU_BLUR_SIGMA = SkIntToScalar(32);
+ static const SkScalar kMIN_GPU_BLUR_SIZE = SkIntToScalar(64);
+ static const SkScalar kMIN_GPU_BLUR_SIGMA = SkIntToScalar(32);
- if (devSpaceShapeBounds.width() <= kMIN_GPU_BLUR_SIZE &&
- devSpaceShapeBounds.height() <= kMIN_GPU_BLUR_SIZE &&
- xformedSigma <= kMIN_GPU_BLUR_SIGMA) {
- return false;
- }
+ if (devSpaceShapeBounds.width() <= kMIN_GPU_BLUR_SIZE &&
+ devSpaceShapeBounds.height() <= kMIN_GPU_BLUR_SIZE &&
+ xformedSigma <= kMIN_GPU_BLUR_SIGMA) {
+ return false;
}
return true;
@@ -917,7 +917,7 @@ GrSurfaceProxyView SkBlurMaskFilterImpl::filterMaskGPU(GrRecordingContext* conte
paint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);
}
- renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+ renderTargetContext->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
SkRect::Make(clipRect));
}
diff --git a/chromium/third_party/skia/src/core/SkCanvas.cpp b/chromium/third_party/skia/src/core/SkCanvas.cpp
index 2d73b3e06c9..8f7d2eac457 100644
--- a/chromium/third_party/skia/src/core/SkCanvas.cpp
+++ b/chromium/third_party/skia/src/core/SkCanvas.cpp
@@ -191,17 +191,12 @@ struct DeviceCM {
SkRasterClip fClip;
std::unique_ptr<const SkPaint> fPaint; // may be null (in the future)
SkMatrix fStashedMatrix; // original CTM; used by imagefilter in saveLayer
- sk_sp<SkImage> fClipImage;
- SkMatrix fClipMatrix;
- DeviceCM(sk_sp<SkBaseDevice> device, const SkPaint* paint, const SkMatrix& stashed,
- const SkImage* clipImage, const SkMatrix* clipMatrix)
+ DeviceCM(sk_sp<SkBaseDevice> device, const SkPaint* paint, const SkMatrix& stashed)
: fNext(nullptr)
, fDevice(std::move(device))
, fPaint(paint ? std::make_unique<SkPaint>(*paint) : nullptr)
, fStashedMatrix(stashed)
- , fClipImage(sk_ref_sp(const_cast<SkImage*>(clipImage)))
- , fClipMatrix(clipMatrix ? *clipMatrix : SkMatrix::I())
{}
void reset(const SkIRect& bounds) {
@@ -506,11 +501,12 @@ void SkCanvas::init(sk_sp<SkBaseDevice> device) {
SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
- new (fDeviceCMStorage) DeviceCM(device, nullptr, fMCRec->fMatrix.asM33(), nullptr, nullptr);
+ new (fDeviceCMStorage) DeviceCM(device, nullptr, fMCRec->fMatrix.asM33());
fMCRec->fTopLayer = fMCRec->fLayer;
fSurfaceBase = nullptr;
+ fDeviceClipBounds = {0, 0, 0, 0};
if (device) {
// The root device and the canvas should always have the same pixel geometry
@@ -917,7 +913,7 @@ void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filt
if (special) {
// The image is drawn at 1-1 scale with integer translation, so no filtering is needed.
SkPaint p;
- dst->drawSpecial(special.get(), 0, 0, p, nullptr, SkMatrix::I());
+ dst->drawSpecial(special.get(), 0, 0, p);
}
return;
}
@@ -930,7 +926,7 @@ void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filt
toRoot = SkMatrix::I();
layerMatrix = ctm;
} else if (ctm.decomposeScale(&scale, &toRoot)) {
- layerMatrix = SkMatrix::MakeScale(scale.fWidth, scale.fHeight);
+ layerMatrix = SkMatrix::Scale(scale.fWidth, scale.fHeight);
} else {
// Perspective, for now, do no scaling of the layer itself.
// TODO (michaelludwig) - perhaps it'd be better to explore a heuristic scale pulled from
@@ -1176,7 +1172,7 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
}
newDevice->setMarkerStack(fMarkerStack.get());
}
- DeviceCM* layer = new DeviceCM(newDevice, paint, stashedMatrix, rec.fClipMask, rec.fClipMatrix);
+ DeviceCM* layer = new DeviceCM(newDevice, paint, stashedMatrix);
// only have a "next" if this new layer doesn't affect the clip (rare)
layer->fNext = BoundsAffectsClip(saveLayerFlags) ? nullptr : fMCRec->fTopLayer;
@@ -1280,8 +1276,7 @@ void SkCanvas::internalRestore() {
paint.setBlendMode(SkBlendMode::kDstOver);
const int x = backImage->fLoc.x();
const int y = backImage->fLoc.y();
- this->getTopDevice()->drawSpecial(backImage->fImage.get(), x, y, paint,
- nullptr, SkMatrix::I());
+ this->getTopDevice()->drawSpecial(backImage->fImage.get(), x, y, paint);
}
/* Time to draw the layer's offscreen. We can't call the public drawSprite,
@@ -1293,8 +1288,7 @@ void SkCanvas::internalRestore() {
layer->fDevice->setImmutable();
// At this point, 'layer' has been removed from the device stack, so the devices that
// internalDrawDevice sees are the destinations that 'layer' is drawn into.
- this->internalDrawDevice(layer->fDevice.get(), layer->fPaint.get(),
- layer->fClipImage.get(), layer->fClipMatrix);
+ this->internalDrawDevice(layer->fDevice.get(), layer->fPaint.get());
// restore what we smashed in internalSaveLayer
this->internalSetMatrix(layer->fStashedMatrix);
delete layer;
@@ -1404,8 +1398,7 @@ static void check_drawdevice_colorspaces(SkColorSpace* src, SkColorSpace* dst) {
SkASSERT(src == dst);
}
-void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, const SkPaint* paint,
- SkImage* clipImage, const SkMatrix& clipMatrix) {
+void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, const SkPaint* paint) {
SkPaint tmp;
if (nullptr == paint) {
paint = &tmp;
@@ -1423,13 +1416,12 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, const SkPaint* paint,
// so it should always be possible to use the relative origin. Once drawDevice() and
// drawSpecial() take an SkMatrix, this can switch to getRelativeTransform() instead.
SkIPoint pos = srcDev->getOrigin() - dstDev->getOrigin();
- if (filter || clipImage) {
+ if (filter) {
sk_sp<SkSpecialImage> specialImage = srcDev->snapSpecial();
if (specialImage) {
check_drawdevice_colorspaces(dstDev->imageInfo().colorSpace(),
specialImage->getColorSpace());
- dstDev->drawSpecial(specialImage.get(), pos.x(), pos.y(), *paint,
- clipImage, clipMatrix);
+ dstDev->drawSpecial(specialImage.get(), pos.x(), pos.y(), *paint);
}
} else {
dstDev->drawDevice(srcDev, pos.x(), pos.y(), *paint);
@@ -1659,6 +1651,7 @@ void SkCanvas::clipShader(sk_sp<SkShader> sh, SkClipOp op) {
this->clipRect({0,0,0,0});
}
} else {
+ this->checkForDeferredSave();
this->onClipShader(std::move(sh), op);
}
}
@@ -1967,6 +1960,17 @@ void SkCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const
}
}
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+ // Preserve legacy behavior for Android: ignore the SkShader if there are no texCoords present
+ if (paint.getShader() &&
+ !(vertices->priv().hasTexCoords() || vertices->priv().hasCustomData())) {
+ SkPaint noShaderPaint(paint);
+ noShaderPaint.setShader(nullptr);
+ this->onDrawVerticesObject(vertices, mode, noShaderPaint);
+ return;
+ }
+#endif
+
this->onDrawVerticesObject(vertices, mode, paint);
}
@@ -2497,8 +2501,7 @@ void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const S
iter.fDevice->localToDevice().mapXY(x, y, &pt);
iter.fDevice->drawSpecial(special.get(),
SkScalarRoundToInt(pt.fX),
- SkScalarRoundToInt(pt.fY), pnt,
- nullptr, SkMatrix::I());
+ SkScalarRoundToInt(pt.fY), pnt);
} else {
iter.fDevice->drawImageRect(
image, nullptr, SkRect::MakeXYWH(x, y, image->width(), image->height()), pnt,
@@ -2682,7 +2685,7 @@ void SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
#endif
RETURN_ON_NULL(dr);
if (x || y) {
- SkMatrix matrix = SkMatrix::MakeTrans(x, y);
+ SkMatrix matrix = SkMatrix::Translate(x, y);
this->onDrawDrawable(dr, &matrix);
} else {
this->onDrawDrawable(dr, nullptr);
@@ -2816,7 +2819,7 @@ void SkCanvas::onDrawEdgeAAImageSet(const ImageSetEntry imageSet[], int count,
// methods, rather than actually drawing themselves.
//////////////////////////////////////////////////////////////////////////////
-void SkCanvas::drawColor(SkColor c, SkBlendMode mode) {
+void SkCanvas::drawColor(const SkColor4f& c, SkBlendMode mode) {
SkPaint paint;
paint.setColor(c);
paint.setBlendMode(mode);
diff --git a/chromium/third_party/skia/src/core/SkClipStack.cpp b/chromium/third_party/skia/src/core/SkClipStack.cpp
index 349fdc6758f..0556b28313a 100644
--- a/chromium/third_party/skia/src/core/SkClipStack.cpp
+++ b/chromium/third_party/skia/src/core/SkClipStack.cpp
@@ -9,6 +9,9 @@
#include "include/core/SkPath.h"
#include "src/core/SkClipOpPriv.h"
#include "src/core/SkClipStack.h"
+#include "src/core/SkRectPriv.h"
+#include "src/shaders/SkShaderBase.h"
+
#include <atomic>
#include <new>
@@ -21,15 +24,22 @@ SkClipStack::Element::Element(const Element& that) {
case DeviceSpaceType::kEmpty:
fDeviceSpaceRRect.setEmpty();
fDeviceSpacePath.reset();
+ fShader.reset();
break;
case DeviceSpaceType::kRect: // Rect uses rrect
case DeviceSpaceType::kRRect:
fDeviceSpacePath.reset();
+ fShader.reset();
fDeviceSpaceRRect = that.fDeviceSpaceRRect;
break;
case DeviceSpaceType::kPath:
+ fShader.reset();
fDeviceSpacePath.set(that.getDeviceSpacePath());
break;
+ case DeviceSpaceType::kShader:
+ fDeviceSpacePath.reset();
+ fShader = that.fShader;
+ break;
}
fSaveCount = that.fSaveCount;
@@ -60,6 +70,8 @@ bool SkClipStack::Element::operator== (const Element& element) const {
return false;
}
switch (fDeviceSpaceType) {
+ case DeviceSpaceType::kShader:
+ return this->getShader() == element.getShader();
case DeviceSpaceType::kPath:
return this->getDeviceSpacePath() == element.getDeviceSpacePath();
case DeviceSpaceType::kRRect:
@@ -76,12 +88,18 @@ bool SkClipStack::Element::operator== (const Element& element) const {
const SkRect& SkClipStack::Element::getBounds() const {
static const SkRect kEmpty = {0, 0, 0, 0};
+ static const SkRect kInfinite = SkRectPriv::MakeLargeS32();
switch (fDeviceSpaceType) {
case DeviceSpaceType::kRect: // fallthrough
case DeviceSpaceType::kRRect:
return fDeviceSpaceRRect.getBounds();
case DeviceSpaceType::kPath:
return fDeviceSpacePath.get()->getBounds();
+ case DeviceSpaceType::kShader:
+ // Shaders have infinite bounds since any pixel could have clipped or full coverage
+ // (which is different from wide-open, where every pixel has 1.0 coverage, or empty
+ // where every pixel has 0.0 coverage).
+ return kInfinite;
case DeviceSpaceType::kEmpty:
return kEmpty;
default:
@@ -99,6 +117,7 @@ bool SkClipStack::Element::contains(const SkRect& rect) const {
case DeviceSpaceType::kPath:
return fDeviceSpacePath.get()->conservativelyContainsRect(rect);
case DeviceSpaceType::kEmpty:
+ case DeviceSpaceType::kShader:
return false;
default:
SkDEBUGFAIL("Unexpected type.");
@@ -116,6 +135,7 @@ bool SkClipStack::Element::contains(const SkRRect& rrect) const {
case DeviceSpaceType::kPath:
return fDeviceSpacePath.get()->conservativelyContainsRect(rrect.getBounds());
case DeviceSpaceType::kEmpty:
+ case DeviceSpaceType::kShader:
return false;
default:
SkDEBUGFAIL("Unexpected type.");
@@ -140,6 +160,9 @@ void SkClipStack::Element::invertShapeFillType() {
case DeviceSpaceType::kPath:
fDeviceSpacePath.get()->toggleInverseFillType();
break;
+ case DeviceSpaceType::kShader:
+ fShader = as_SB(fShader)->makeInvertAlpha();
+ break;
case DeviceSpaceType::kEmpty:
// Should this set to an empty, inverse filled path?
break;
@@ -219,6 +242,13 @@ void SkClipStack::Element::initAsPath(int saveCount, const SkPath& path, const S
this->initCommon(saveCount, op, doAA);
}
+void SkClipStack::Element::initShader(int saveCount, sk_sp<SkShader> shader) {
+ SkASSERT(shader);
+ fDeviceSpaceType = DeviceSpaceType::kShader;
+ fShader = std::move(shader);
+ this->initCommon(saveCount, SkClipOp::kIntersect, false);
+}
+
void SkClipStack::Element::asDeviceSpacePath(SkPath* path) const {
switch (fDeviceSpaceType) {
case DeviceSpaceType::kEmpty:
@@ -235,6 +265,10 @@ void SkClipStack::Element::asDeviceSpacePath(SkPath* path) const {
case DeviceSpaceType::kPath:
*path = *fDeviceSpacePath.get();
break;
+ case DeviceSpaceType::kShader:
+ path->reset();
+ path->addRect(SkRectPriv::MakeLargeS32());
+ break;
}
path->setIsVolatile(true);
}
@@ -246,6 +280,7 @@ void SkClipStack::Element::setEmpty() {
fIsIntersectionOfRects = false;
fDeviceSpaceRRect.setEmpty();
fDeviceSpacePath.reset();
+ fShader.reset();
fGenID = kEmptyGenID;
SkDEBUGCODE(this->checkEmpty();)
}
@@ -257,6 +292,7 @@ void SkClipStack::Element::checkEmpty() const {
SkASSERT(kEmptyGenID == fGenID);
SkASSERT(fDeviceSpaceRRect.isEmpty());
SkASSERT(!fDeviceSpacePath.isValid());
+ SkASSERT(!fShader);
}
bool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkClipOp op) const {
@@ -356,7 +392,7 @@ void SkClipStack::Element::combineBoundsXOR(int combination, const SkRect& prevF
// The only pixels that can survive are within the
// union of the two bounding boxes since the extensions
// to infinity of both clips cancel out
- // fall through!
+ [[fallthrough]];
case kPrev_Cur_FillCombo:
// The most conservative bound for xor is the
// union of the two bounds. If the two clips exactly overlapped
@@ -501,6 +537,14 @@ void SkClipStack::Element::updateBoundAndGenID(const Element* prior) {
fFiniteBoundType = kNormal_BoundsType;
}
break;
+ case DeviceSpaceType::kShader:
+ // A shader is infinite. We don't act as wide-open here (which is an empty bounds with
+ // the inside out type). This is because when the bounds is empty and inside-out, we
+ // know there's full coverage everywhere. With a shader, there's *unknown* coverage
+ // everywhere.
+ fFiniteBound = SkRectPriv::MakeLargeS32();
+ fFiniteBoundType = kNormal_BoundsType;
+ break;
case DeviceSpaceType::kEmpty:
SkDEBUGFAIL("We shouldn't get here with an empty element.");
break;
@@ -758,6 +802,15 @@ void SkClipStack::pushElement(const Element& element) {
case Element::DeviceSpaceType::kEmpty:
SkDEBUGCODE(prior->checkEmpty();)
return;
+ case Element::DeviceSpaceType::kShader:
+ if (Element::DeviceSpaceType::kShader == element.getDeviceSpaceType()) {
+ prior->fShader = SkShaders::Blend(SkBlendMode::kSrcIn,
+ element.fShader, prior->fShader);
+ Element* priorPrior = (Element*) iter.prev();
+ prior->updateBoundAndGenID(priorPrior);
+ return;
+ }
+ break;
case Element::DeviceSpaceType::kRect:
if (Element::DeviceSpaceType::kRect == element.getDeviceSpaceType()) {
if (prior->rectRectIntersectAllowed(element.getDeviceSpaceRect(),
@@ -777,7 +830,7 @@ void SkClipStack::pushElement(const Element& element) {
}
break;
}
- // fallthrough
+ [[fallthrough]];
default:
if (!SkRect::Intersects(prior->getBounds(), element.getBounds())) {
prior->setEmpty();
@@ -827,6 +880,14 @@ void SkClipStack::clipPath(const SkPath& path, const SkMatrix& matrix, SkClipOp
}
}
+void SkClipStack::clipShader(sk_sp<SkShader> shader) {
+ Element element(fSaveCount, std::move(shader));
+ this->pushElement(element);
+ // clipShader should not be used with expanding clip ops, so we shouldn't need to worry about
+ // the clip restriction rect either.
+ SkASSERT(fClipRestrictionRect.isEmpty());
+}
+
void SkClipStack::clipEmpty() {
Element* element = (Element*) fDeque.back();
@@ -1002,7 +1063,8 @@ uint32_t SkClipStack::getTopmostGenID() const {
}
const Element* back = static_cast<const Element*>(fDeque.back());
- if (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBound.isEmpty()) {
+ if (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBound.isEmpty() &&
+ Element::DeviceSpaceType::kShader != back->fDeviceSpaceType) {
return kWideOpenGenID;
}
@@ -1015,12 +1077,14 @@ void SkClipStack::Element::dump() const {
"empty",
"rect",
"rrect",
- "path"
+ "path",
+ "shader"
};
static_assert(0 == static_cast<int>(DeviceSpaceType::kEmpty), "enum mismatch");
static_assert(1 == static_cast<int>(DeviceSpaceType::kRect), "enum mismatch");
static_assert(2 == static_cast<int>(DeviceSpaceType::kRRect), "enum mismatch");
static_assert(3 == static_cast<int>(DeviceSpaceType::kPath), "enum mismatch");
+ static_assert(4 == static_cast<int>(DeviceSpaceType::kShader), "enum mismatch");
static_assert(SK_ARRAY_COUNT(kTypeStrings) == kTypeCnt, "enum mismatch");
static const char* kOpStrings[] = {
@@ -1056,6 +1120,9 @@ void SkClipStack::Element::dump() const {
case DeviceSpaceType::kPath:
this->getDeviceSpacePath().dump(nullptr, true, false);
break;
+ case DeviceSpaceType::kShader:
+ // SkShaders don't provide much introspection that's worth while.
+ break;
}
}
diff --git a/chromium/third_party/skia/src/core/SkClipStack.h b/chromium/third_party/skia/src/core/SkClipStack.h
index 6a12c2fdb93..fdbc59b72c9 100644
--- a/chromium/third_party/skia/src/core/SkClipStack.h
+++ b/chromium/third_party/skia/src/core/SkClipStack.h
@@ -13,6 +13,7 @@
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkRegion.h"
+#include "include/core/SkShader.h"
#include "include/private/SkDeque.h"
#include "src/core/SkClipOpPriv.h"
#include "src/core/SkMessageBus.h"
@@ -59,8 +60,10 @@ public:
kRRect,
//!< This element combines a device space path with the current clip.
kPath,
+ //!< This element does not have geometry, but applies a shader to the clip
+ kShader,
- kLastType = kPath
+ kLastType = kShader
};
static const int kTypeCnt = (int)DeviceSpaceType::kLastType + 1;
@@ -83,6 +86,10 @@ public:
this->initPath(0, path, m, op, doAA);
}
+ Element(sk_sp<SkShader> shader) {
+ this->initShader(0, std::move(shader));
+ }
+
~Element();
bool operator== (const Element& element) const;
@@ -113,6 +120,14 @@ public:
return fDeviceSpaceRRect.getBounds();
}
+ //!<Call if getDeviceSpaceType() is kShader to get a reference to the clip shader.
+ sk_sp<SkShader> refShader() const {
+ return fShader;
+ }
+ const SkShader* getShader() const {
+ return fShader.get();
+ }
+
//!< Call if getDeviceSpaceType() is not kEmpty to get the set operation used to combine
//!< this element.
SkClipOp getOp() const { return fOp; }
@@ -195,6 +210,7 @@ public:
SkTLazy<SkPath> fDeviceSpacePath;
SkRRect fDeviceSpaceRRect;
+ sk_sp<SkShader> fShader;
int fSaveCount; // save count of stack when this element was added.
SkClipOp fOp;
DeviceSpaceType fDeviceSpaceType;
@@ -239,11 +255,16 @@ public:
this->initPath(saveCount, path, m, op, doAA);
}
+ Element(int saveCount, sk_sp<SkShader> shader) {
+ this->initShader(saveCount, std::move(shader));
+ }
+
void initCommon(int saveCount, SkClipOp op, bool doAA);
void initRect(int saveCount, const SkRect&, const SkMatrix&, SkClipOp, bool doAA);
void initRRect(int saveCount, const SkRRect&, const SkMatrix&, SkClipOp, bool doAA);
void initPath(int saveCount, const SkPath&, const SkMatrix&, SkClipOp, bool doAA);
void initAsPath(int saveCount, const SkPath&, const SkMatrix&, SkClipOp, bool doAA);
+ void initShader(int saveCount, sk_sp<SkShader>);
void setEmpty();
@@ -345,6 +366,7 @@ public:
void clipRect(const SkRect&, const SkMatrix& matrix, SkClipOp, bool doAA);
void clipRRect(const SkRRect&, const SkMatrix& matrix, SkClipOp, bool doAA);
void clipPath(const SkPath&, const SkMatrix& matrix, SkClipOp, bool doAA);
+ void clipShader(sk_sp<SkShader>);
// An optimized version of clipDevRect(emptyRect, kIntersect, ...)
void clipEmpty();
void setDeviceClipRestriction(const SkIRect& rect) {
@@ -513,4 +535,3 @@ private:
};
#endif
-
diff --git a/chromium/third_party/skia/src/core/SkClipStackDevice.cpp b/chromium/third_party/skia/src/core/SkClipStackDevice.cpp
index ab2fcd85ac2..2021852f363 100644
--- a/chromium/third_party/skia/src/core/SkClipStackDevice.cpp
+++ b/chromium/third_party/skia/src/core/SkClipStackDevice.cpp
@@ -39,12 +39,16 @@ void SkClipStackDevice::onClipPath(const SkPath& path, SkClipOp op, bool aa) {
fClipStack.clipPath(path, this->localToDevice(), op, aa);
}
+void SkClipStackDevice::onClipShader(sk_sp<SkShader> shader) {
+ fClipStack.clipShader(std::move(shader));
+}
+
void SkClipStackDevice::onClipRegion(const SkRegion& rgn, SkClipOp op) {
SkIPoint origin = this->getOrigin();
SkRegion tmp;
SkPath path;
rgn.getBoundaryPath(&path);
- path.transform(SkMatrix::MakeTrans(-origin));
+ path.transform(SkMatrix::Translate(-origin));
fClipStack.clipPath(path, SkMatrix::I(), op, false);
}
diff --git a/chromium/third_party/skia/src/core/SkClipStackDevice.h b/chromium/third_party/skia/src/core/SkClipStackDevice.h
index e7fb96a4055..7cbf2133949 100644
--- a/chromium/third_party/skia/src/core/SkClipStackDevice.h
+++ b/chromium/third_party/skia/src/core/SkClipStackDevice.h
@@ -27,6 +27,7 @@ protected:
void onClipRect(const SkRect& rect, SkClipOp, bool aa) override;
void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) override;
void onClipPath(const SkPath& path, SkClipOp, bool aa) override;
+ void onClipShader(sk_sp<SkShader>) override;
void onClipRegion(const SkRegion& deviceRgn, SkClipOp) override;
void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) override;
bool onClipIsAA() const override;
diff --git a/chromium/third_party/skia/src/core/SkColorFilter.cpp b/chromium/third_party/skia/src/core/SkColorFilter.cpp
index e3af3f46feb..829a56957a2 100644
--- a/chromium/third_party/skia/src/core/SkColorFilter.cpp
+++ b/chromium/third_party/skia/src/core/SkColorFilter.cpp
@@ -5,13 +5,13 @@
* found in the LICENSE file.
*/
-#include "include/core/SkColorFilter.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkString.h"
#include "include/core/SkUnPreMultiply.h"
#include "include/private/SkNx.h"
#include "include/private/SkTDArray.h"
#include "src/core/SkArenaAlloc.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkColorSpaceXformSteps.h"
#include "src/core/SkMatrixProvider.h"
@@ -26,28 +26,48 @@
#include "src/gpu/effects/generated/GrMixerEffect.h"
#endif
-bool SkColorFilter::onAsAColorMode(SkColor*, SkBlendMode*) const {
+bool SkColorFilter::asColorMode(SkColor* color, SkBlendMode* mode) const {
+ return as_CFB(this)->onAsAColorMode(color, mode);
+}
+
+bool SkColorFilter::asAColorMode(SkColor* color, SkBlendMode* mode) const {
+ return as_CFB(this)->onAsAColorMode(color, mode);
+}
+
+bool SkColorFilter::asAColorMatrix(float matrix[20]) const {
+ return as_CFB(this)->onAsAColorMatrix(matrix);
+}
+
+uint32_t SkColorFilter::getFlags() const { return as_CFB(this)->onGetFlags(); }
+
+bool SkColorFilter::isAlphaUnchanged() const {
+ return SkToBool(this->getFlags() & kAlphaUnchanged_Flag);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool SkColorFilterBase::onAsAColorMode(SkColor*, SkBlendMode*) const {
return false;
}
-bool SkColorFilter::onAsAColorMatrix(float matrix[20]) const {
+bool SkColorFilterBase::onAsAColorMatrix(float matrix[20]) const {
return false;
}
#if SK_SUPPORT_GPU
-std::unique_ptr<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(GrRecordingContext*,
+std::unique_ptr<GrFragmentProcessor> SkColorFilterBase::asFragmentProcessor(GrRecordingContext*,
const GrColorInfo&) const {
return nullptr;
}
#endif
-bool SkColorFilter::appendStages(const SkStageRec& rec, bool shaderIsOpaque) const {
+bool SkColorFilterBase::appendStages(const SkStageRec& rec, bool shaderIsOpaque) const {
return this->onAppendStages(rec, shaderIsOpaque);
}
-skvm::Color SkColorFilter::program(skvm::Builder* p, skvm::Color c,
- SkColorSpace* dstCS,
- skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
+skvm::Color SkColorFilterBase::program(skvm::Builder* p, skvm::Color c,
+ SkColorSpace* dstCS,
+ skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
skvm::F32 original = c.a;
if ((c = this->onProgram(p,c, dstCS, uniforms,alloc))) {
if (this->getFlags() & kAlphaUnchanged_Flag) {
@@ -80,7 +100,7 @@ SkColor4f SkColorFilter::filterColor4f(const SkColor4f& origSrcColor, SkColorSpa
SkStageRec rec = {
&pipeline, &alloc, kRGBA_F32_SkColorType, dstCS, dummyPaint, nullptr, matrixProvider
};
- this->onAppendStages(rec, color.fA == 1);
+ as_CFB(this)->onAppendStages(rec, color.fA == 1);
SkPMColor4f dst;
SkRasterPipeline_MemoryCtx dstPtr = { &dst, 0 };
@@ -91,16 +111,16 @@ SkColor4f SkColorFilter::filterColor4f(const SkColor4f& origSrcColor, SkColorSpa
///////////////////////////////////////////////////////////////////////////////////////////////////
-class SkComposeColorFilter : public SkColorFilter {
+class SkComposeColorFilter : public SkColorFilterBase {
public:
- uint32_t getFlags() const override {
+ uint32_t onGetFlags() const override {
// Can only claim alphaunchanged support if both our proxys do.
- return fOuter->getFlags() & fInner->getFlags();
+ return fOuter->onGetFlags() & fInner->onGetFlags();
}
bool onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const override {
bool innerIsOpaque = shaderIsOpaque;
- if (!(fInner->getFlags() & kAlphaUnchanged_Flag)) {
+ if (!fInner->isAlphaUnchanged()) {
innerIsOpaque = false;
}
return fInner->appendStages(rec, shaderIsOpaque) &&
@@ -127,6 +147,8 @@ public:
}
#endif
+ SK_FLATTENABLE_HOOKS(SkComposeColorFilter)
+
protected:
void flatten(SkWriteBuffer& buffer) const override {
buffer.writeFlattenable(fOuter.get());
@@ -134,14 +156,13 @@ protected:
}
private:
- SK_FLATTENABLE_HOOKS(SkComposeColorFilter)
-
SkComposeColorFilter(sk_sp<SkColorFilter> outer, sk_sp<SkColorFilter> inner)
- : fOuter(std::move(outer))
- , fInner(std::move(inner)) {}
+ : fOuter(as_CFB_sp(std::move(outer)))
+ , fInner(as_CFB_sp(std::move(inner)))
+ {}
- sk_sp<SkColorFilter> fOuter;
- sk_sp<SkColorFilter> fInner;
+ sk_sp<SkColorFilterBase> fOuter;
+ sk_sp<SkColorFilterBase> fInner;
friend class SkColorFilter;
@@ -164,7 +185,7 @@ sk_sp<SkColorFilter> SkColorFilter::makeComposed(sk_sp<SkColorFilter> inner) con
///////////////////////////////////////////////////////////////////////////////////////////////////
-class SkSRGBGammaColorFilter : public SkColorFilter {
+class SkSRGBGammaColorFilter : public SkColorFilterBase {
public:
enum class Direction {
kLinearToSRGB,
@@ -203,9 +224,7 @@ public:
rec.fPipeline->append(SkRasterPipeline::unpremul);
}
- // TODO: is it valuable to thread this through appendStages()?
- bool shaderIsNormalized = false;
- fSteps.apply(rec.fPipeline, shaderIsNormalized);
+ fSteps.apply(rec.fPipeline);
if (!shaderIsOpaque) {
rec.fPipeline->append(SkRasterPipeline::premul);
@@ -218,19 +237,19 @@ public:
return premul(fSteps.program(p, uniforms, unpremul(c)));
}
+ SK_FLATTENABLE_HOOKS(SkSRGBGammaColorFilter)
+
protected:
void flatten(SkWriteBuffer& buffer) const override {
buffer.write32(static_cast<uint32_t>(fDir));
}
private:
- SK_FLATTENABLE_HOOKS(SkSRGBGammaColorFilter)
-
const Direction fDir;
SkColorSpaceXformSteps fSteps;
friend class SkColorFilter;
- typedef SkColorFilter INHERITED;
+ typedef SkColorFilterBase INHERITED;
};
sk_sp<SkFlattenable> SkSRGBGammaColorFilter::CreateProc(SkReadBuffer& buffer) {
@@ -257,18 +276,20 @@ sk_sp<SkColorFilter> SkColorFilters::SRGBToLinearGamma() {
///////////////////////////////////////////////////////////////////////////////////////////////////
-class SkMixerColorFilter : public SkColorFilter {
+class SkMixerColorFilter : public SkColorFilterBase {
public:
SkMixerColorFilter(sk_sp<SkColorFilter> cf0, sk_sp<SkColorFilter> cf1, float weight)
- : fCF0(std::move(cf0)), fCF1(std::move(cf1)), fWeight(weight)
+ : fCF0(as_CFB_sp(std::move(cf0)))
+ , fCF1(as_CFB_sp(std::move(cf1)))
+ , fWeight(weight)
{
SkASSERT(fCF0);
SkASSERT(fWeight >= 0 && fWeight <= 1);
}
- uint32_t getFlags() const override {
- uint32_t f0 = fCF0->getFlags();
- uint32_t f1 = fCF1 ? fCF1->getFlags() : ~0U;
+ uint32_t onGetFlags() const override {
+ uint32_t f0 = fCF0->onGetFlags();
+ uint32_t f1 = fCF1 ? fCF1->onGetFlags() : ~0U;
return f0 & f1;
}
@@ -321,6 +342,8 @@ public:
}
#endif
+ SK_FLATTENABLE_HOOKS(SkMixerColorFilter)
+
protected:
void flatten(SkWriteBuffer& buffer) const override {
buffer.writeFlattenable(fCF0.get());
@@ -329,15 +352,13 @@ protected:
}
private:
- SK_FLATTENABLE_HOOKS(SkMixerColorFilter)
-
- sk_sp<SkColorFilter> fCF0;
- sk_sp<SkColorFilter> fCF1;
- const float fWeight;
+ sk_sp<SkColorFilterBase> fCF0;
+ sk_sp<SkColorFilterBase> fCF1;
+ const float fWeight;
friend class SkColorFilter;
- typedef SkColorFilter INHERITED;
+ typedef SkColorFilterBase INHERITED;
};
sk_sp<SkFlattenable> SkMixerColorFilter::CreateProc(SkReadBuffer& buffer) {
@@ -376,7 +397,7 @@ sk_sp<SkColorFilter> SkColorFilters::Lerp(float weight, sk_sp<SkColorFilter> cf0
#include "src/core/SkModeColorFilter.h"
-void SkColorFilter::RegisterFlattenables() {
+void SkColorFilterBase::RegisterFlattenables() {
SK_REGISTER_FLATTENABLE(SkComposeColorFilter);
SK_REGISTER_FLATTENABLE(SkModeColorFilter);
SK_REGISTER_FLATTENABLE(SkSRGBGammaColorFilter);
diff --git a/chromium/third_party/skia/src/core/SkColorFilterBase.h b/chromium/third_party/skia/src/core/SkColorFilterBase.h
new file mode 100644
index 00000000000..8d2fd7053b2
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkColorFilterBase.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColorFilterBase_DEFINED
+#define SkColorFilterBase_DEFINED
+
+#include "include/core/SkColorFilter.h"
+
+class GrColorInfo;
+class GrFragmentProcessor;
+class GrRecordingContext;
+class SkArenaAlloc;
+class SkBitmap;
+class SkColorSpace;
+struct SkStageRec;
+using GrFPResult = std::tuple<bool, std::unique_ptr<GrFragmentProcessor>>;
+
+namespace skvm {
+ class Builder;
+ struct F32;
+ struct Uniforms;
+ struct Color;
+}
+
+class SkColorFilterBase : public SkColorFilter {
+public:
+ bool appendStages(const SkStageRec& rec, bool shaderIsOpaque) const;
+
+ skvm::Color program(skvm::Builder*, skvm::Color,
+ SkColorSpace* dstCS, skvm::Uniforms*, SkArenaAlloc*) const;
+
+ /** Returns the flags for this filter. Override in subclasses to return custom flags.
+ */
+ virtual uint32_t onGetFlags() const { return 0; }
+
+#if SK_SUPPORT_GPU
+ /**
+ * A subclass may implement this factory function to work with the GPU backend. It returns
+ * a GrFragmentProcessor that implements the color filter in GPU shader code.
+ *
+ * The fragment processor receives a premultiplied input color and produces a premultiplied
+ * output color.
+ *
+ * A null return indicates that the color filter isn't implemented for the GPU backend.
+ */
+ virtual std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
+ GrRecordingContext*, const GrColorInfo& dstColorInfo) const;
+#endif
+
+ bool affectsTransparentBlack() const {
+ return this->filterColor(SK_ColorTRANSPARENT) != SK_ColorTRANSPARENT;
+ }
+
+ static void RegisterFlattenables();
+
+ static SkFlattenable::Type GetFlattenableType() {
+ return kSkColorFilter_Type;
+ }
+
+ SkFlattenable::Type getFlattenableType() const override {
+ return kSkColorFilter_Type;
+ }
+
+ static sk_sp<SkColorFilter> Deserialize(const void* data, size_t size,
+ const SkDeserialProcs* procs = nullptr) {
+ return sk_sp<SkColorFilter>(static_cast<SkColorFilter*>(
+ SkFlattenable::Deserialize(
+ kSkColorFilter_Type, data, size, procs).release()));
+ }
+
+protected:
+ SkColorFilterBase() {}
+
+ virtual bool onAsAColorMatrix(float[20]) const;
+ virtual bool onAsAColorMode(SkColor* color, SkBlendMode* bmode) const;
+
+private:
+ virtual bool onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const = 0;
+
+ virtual skvm::Color onProgram(skvm::Builder*, skvm::Color,
+ SkColorSpace* dstCS, skvm::Uniforms*, SkArenaAlloc*) const = 0;
+
+ friend class SkColorFilter;
+
+ typedef SkFlattenable INHERITED;
+};
+
+static inline SkColorFilterBase* as_CFB(SkColorFilter* filter) {
+ return static_cast<SkColorFilterBase*>(filter);
+}
+
+static inline const SkColorFilterBase* as_CFB(const SkColorFilter* filter) {
+ return static_cast<const SkColorFilterBase*>(filter);
+}
+
+static inline const SkColorFilterBase* as_CFB(const sk_sp<SkColorFilter>& filter) {
+ return static_cast<SkColorFilterBase*>(filter.get());
+}
+
+static inline sk_sp<SkColorFilterBase> as_CFB_sp(sk_sp<SkColorFilter> filter) {
+ return sk_sp<SkColorFilterBase>(static_cast<SkColorFilterBase*>(filter.release()));
+}
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkColorFilter_Matrix.cpp b/chromium/third_party/skia/src/core/SkColorFilter_Matrix.cpp
index 89544188c1b..83b2cb297b4 100644
--- a/chromium/third_party/skia/src/core/SkColorFilter_Matrix.cpp
+++ b/chromium/third_party/skia/src/core/SkColorFilter_Matrix.cpp
@@ -26,7 +26,7 @@ static uint16_t ComputeFlags(const float matrix[20]) {
&& SkScalarNearlyZero (srcA[2])
&& SkScalarNearlyEqual(srcA[3], 1)
&& SkScalarNearlyZero (srcA[4])
- ? SkColorFilter::kAlphaUnchanged_Flag : 0;
+ ? SkColorFilterBase::kAlphaUnchanged_Flag : 0;
}
SkColorFilter_Matrix::SkColorFilter_Matrix(const float array[20], Domain domain)
@@ -35,8 +35,8 @@ SkColorFilter_Matrix::SkColorFilter_Matrix(const float array[20], Domain domain)
memcpy(fMatrix, array, 20 * sizeof(float));
}
-uint32_t SkColorFilter_Matrix::getFlags() const {
- return this->INHERITED::getFlags() | fFlags;
+uint32_t SkColorFilter_Matrix::onGetFlags() const {
+ return this->INHERITED::onGetFlags() | fFlags;
}
void SkColorFilter_Matrix::flatten(SkWriteBuffer& buffer) const {
@@ -131,20 +131,19 @@ std::unique_ptr<GrFragmentProcessor> SkColorFilter_Matrix::asFragmentProcessor(
GrRecordingContext*, const GrColorInfo&) const {
switch (fDomain) {
case Domain::kRGBA:
- return GrColorMatrixFragmentProcessor::Make(fMatrix,
+ return GrColorMatrixFragmentProcessor::Make(/* inputFP = */ nullptr,
+ fMatrix,
/* premulInput = */ true,
/* clampRGBOutput = */ true,
/* premulOutput = */ true);
case Domain::kHSLA: {
- std::unique_ptr<GrFragmentProcessor> series[] = {
- GrRGBToHSLFilterEffect::Make(),
- GrColorMatrixFragmentProcessor::Make(fMatrix,
- /* premulInput = */ false,
- /* clampRGBOutput = */ false,
- /* premulOutput = */ false),
- GrHSLToRGBFilterEffect::Make(),
- };
- return GrFragmentProcessor::RunInSeries(series, SK_ARRAY_COUNT(series));
+ auto fp = GrRGBToHSLFilterEffect::Make(/* inputFP = */ nullptr);
+ fp = GrColorMatrixFragmentProcessor::Make(std::move(fp), fMatrix,
+ /* premulInput = */ false,
+ /* clampRGBOutput = */ false,
+ /* premulOutput = */ false);
+ fp = GrHSLToRGBFilterEffect::Make(std::move(fp));
+ return fp;
}
}
diff --git a/chromium/third_party/skia/src/core/SkColorFilter_Matrix.h b/chromium/third_party/skia/src/core/SkColorFilter_Matrix.h
index a2a3e664e71..401919af227 100644
--- a/chromium/third_party/skia/src/core/SkColorFilter_Matrix.h
+++ b/chromium/third_party/skia/src/core/SkColorFilter_Matrix.h
@@ -8,16 +8,15 @@
#ifndef SkColorFilter_Matrix_DEFINED
#define SkColorFilter_Matrix_DEFINED
-#include "include/core/SkColorFilter.h"
-#include "include/core/SkFlattenable.h"
+#include "src/core/SkColorFilterBase.h"
-class SkColorFilter_Matrix : public SkColorFilter {
+class SkColorFilter_Matrix : public SkColorFilterBase {
public:
enum class Domain : uint8_t { kRGBA, kHSLA };
explicit SkColorFilter_Matrix(const float array[20], Domain);
- uint32_t getFlags() const override;
+ uint32_t onGetFlags() const override;
#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrRecordingContext*,
@@ -41,7 +40,7 @@ private:
uint16_t fFlags;
Domain fDomain;
- typedef SkColorFilter INHERITED;
+ typedef SkColorFilterBase INHERITED;
};
#endif
diff --git a/chromium/third_party/skia/src/core/SkColorSpaceXformSteps.cpp b/chromium/third_party/skia/src/core/SkColorSpaceXformSteps.cpp
index 133d661f4d7..1d90dc2cd28 100644
--- a/chromium/third_party/skia/src/core/SkColorSpaceXformSteps.cpp
+++ b/chromium/third_party/skia/src/core/SkColorSpaceXformSteps.cpp
@@ -65,9 +65,6 @@ SkColorSpaceXformSteps::SkColorSpaceXformSteps(const SkColorSpace* src, SkAlphaT
src-> transferFn(&this->srcTF );
dst->invTransferFn(&this->dstTFInv);
- this->srcTF_is_sRGB = src->gammaCloseToSRGB();
- this->dstTF_is_sRGB = dst->gammaCloseToSRGB();
-
// If we linearize then immediately reencode with the same transfer function, skip both.
if ( this->flags.linearize &&
!this->flags.gamut_transform &&
@@ -131,29 +128,12 @@ void SkColorSpaceXformSteps::apply(float* rgba) const {
}
}
-void SkColorSpaceXformSteps::apply(SkRasterPipeline* p, bool src_is_normalized) const {
-#if defined(SK_LEGACY_SRGB_STAGE_CHOICE)
- src_is_normalized = true;
-#endif
- if (flags.unpremul) { p->append(SkRasterPipeline::unpremul); }
- if (flags.linearize) {
- if (src_is_normalized && srcTF_is_sRGB) {
- p->append(SkRasterPipeline::from_srgb);
- } else {
- p->append_transfer_function(srcTF);
- }
- }
- if (flags.gamut_transform) {
- p->append(SkRasterPipeline::matrix_3x3, &src_to_dst_matrix);
- }
- if (flags.encode) {
- if (src_is_normalized && dstTF_is_sRGB) {
- p->append(SkRasterPipeline::to_srgb);
- } else {
- p->append_transfer_function(dstTFInv);
- }
- }
- if (flags.premul) { p->append(SkRasterPipeline::premul); }
+void SkColorSpaceXformSteps::apply(SkRasterPipeline* p) const {
+ if (flags.unpremul) { p->append(SkRasterPipeline::unpremul); }
+ if (flags.linearize) { p->append_transfer_function(srcTF); }
+ if (flags.gamut_transform) { p->append(SkRasterPipeline::matrix_3x3, &src_to_dst_matrix); }
+ if (flags.encode) { p->append_transfer_function(dstTFInv); }
+ if (flags.premul) { p->append(SkRasterPipeline::premul); }
}
skvm::Color sk_program_transfer_fn(skvm::Builder* p, skvm::Uniforms* uniforms,
diff --git a/chromium/third_party/skia/src/core/SkColorSpaceXformSteps.h b/chromium/third_party/skia/src/core/SkColorSpaceXformSteps.h
index 7d15259e30f..03c9aab638d 100644
--- a/chromium/third_party/skia/src/core/SkColorSpaceXformSteps.h
+++ b/chromium/third_party/skia/src/core/SkColorSpaceXformSteps.h
@@ -42,17 +42,11 @@ struct SkColorSpaceXformSteps {
dst.colorSpace(), dst.alphaType()) {}
void apply(float rgba[4]) const;
- void apply(SkRasterPipeline*, bool src_is_normalized) const;
+ void apply(SkRasterPipeline*) const;
skvm::Color program(skvm::Builder*, skvm::Uniforms*, skvm::Color) const;
- void apply(SkRasterPipeline* p, SkColorType srcCT) const {
- return this->apply(p, SkColorTypeIsNormalized(srcCT));
- }
-
Flags flags;
- bool srcTF_is_sRGB,
- dstTF_is_sRGB;
skcms_TransferFunction srcTF, // Apply for linearize.
dstTFInv; // Apply for encode.
float src_to_dst_matrix[9]; // Apply this 3x3 column-major matrix for gamut_transform.
diff --git a/chromium/third_party/skia/src/core/SkConvertPixels.cpp b/chromium/third_party/skia/src/core/SkConvertPixels.cpp
index 2eb840c3ace..c3dd1d2236f 100644
--- a/chromium/third_party/skia/src/core/SkConvertPixels.cpp
+++ b/chromium/third_party/skia/src/core/SkConvertPixels.cpp
@@ -211,7 +211,7 @@ static void convert_with_pipeline(const SkImageInfo& dstInfo, void* dstRow, size
SkRasterPipeline_<256> pipeline;
pipeline.append_load(srcInfo.colorType(), &src);
- steps.apply(&pipeline, srcInfo.colorType());
+ steps.apply(&pipeline);
pipeline.append_gamut_clamp_if_normalized(dstInfo);
diff --git a/chromium/third_party/skia/src/core/SkCoreBlitters.h b/chromium/third_party/skia/src/core/SkCoreBlitters.h
index 700ca64ab7e..18d468be639 100644
--- a/chromium/third_party/skia/src/core/SkCoreBlitters.h
+++ b/chromium/third_party/skia/src/core/SkCoreBlitters.h
@@ -164,12 +164,10 @@ private:
///////////////////////////////////////////////////////////////////////////////
-// Neither of these ever returns nullptr, but this first factory may return a SkNullBlitter.
SkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap&, const SkPaint&,
const SkMatrixProvider& matrixProvider, SkArenaAlloc*,
sk_sp<SkShader> clipShader);
// Use this if you've pre-baked a shader pipeline, including modulating with paint alpha.
-// This factory never returns an SkNullBlitter.
SkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap&, const SkPaint&,
const SkRasterPipeline& shaderPipeline,
bool shader_is_opaque,
@@ -177,7 +175,7 @@ SkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap&, const SkPaint&,
SkBlitter* SkCreateSkVMBlitter(const SkPixmap&,
const SkPaint&,
- const SkMatrix& ctm,
+ const SkMatrixProvider&,
SkArenaAlloc*,
sk_sp<SkShader> clipShader);
diff --git a/chromium/third_party/skia/src/core/SkDeferredDisplayList.cpp b/chromium/third_party/skia/src/core/SkDeferredDisplayList.cpp
index 5f892241acd..961bc00c682 100644
--- a/chromium/third_party/skia/src/core/SkDeferredDisplayList.cpp
+++ b/chromium/third_party/skia/src/core/SkDeferredDisplayList.cpp
@@ -20,10 +20,12 @@ class SkSurfaceCharacterization;
#endif
SkDeferredDisplayList::SkDeferredDisplayList(const SkSurfaceCharacterization& characterization,
+ sk_sp<GrRenderTargetProxy> targetProxy,
sk_sp<LazyProxyData> lazyProxyData)
: fCharacterization(characterization)
#if SK_SUPPORT_GPU
- , fLazyProxyData(std::move(lazyProxyData))
+ , fTargetProxy(std::move(targetProxy))
+ , fLazyProxyData(std::move(lazyProxyData))
#endif
{
}
diff --git a/chromium/third_party/skia/src/core/SkDeferredDisplayListPriv.h b/chromium/third_party/skia/src/core/SkDeferredDisplayListPriv.h
index 271a69bea69..5c8ceb11cb5 100644
--- a/chromium/third_party/skia/src/core/SkDeferredDisplayListPriv.h
+++ b/chromium/third_party/skia/src/core/SkDeferredDisplayListPriv.h
@@ -22,6 +22,10 @@ public:
return fDDL->fRenderTasks.count();
}
+ GrRenderTargetProxy* targetProxy() const {
+ return fDDL->fTargetProxy.get();
+ }
+
const SkDeferredDisplayList::LazyProxyData* lazyProxyData() const {
return fDDL->fLazyProxyData.get();
}
diff --git a/chromium/third_party/skia/src/core/SkDeferredDisplayListRecorder.cpp b/chromium/third_party/skia/src/core/SkDeferredDisplayListRecorder.cpp
index 1b284527803..cbe1f84edf6 100644
--- a/chromium/third_party/skia/src/core/SkDeferredDisplayListRecorder.cpp
+++ b/chromium/third_party/skia/src/core/SkDeferredDisplayListRecorder.cpp
@@ -97,6 +97,7 @@ SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() {
bool SkDeferredDisplayListRecorder::init() {
SkASSERT(fContext);
+ SkASSERT(!fTargetProxy);
SkASSERT(!fLazyProxyData);
SkASSERT(!fSurface);
@@ -141,6 +142,9 @@ bool SkDeferredDisplayListRecorder::init() {
GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone;
if (usesGLFBO0) {
surfaceFlags |= GrInternalSurfaceFlags::kGLRTFBOIDIs0;
+ } else if (fCharacterization.sampleCount() > 1 && !caps->msaaResolvesAutomatically() &&
+ fCharacterization.isTextureable()) {
+ surfaceFlags |= GrInternalSurfaceFlags::kRequiresManualMSAAResolve;
}
// FIXME: Why do we use GrMipMapped::kNo instead of SkSurfaceCharacterization::fIsMipMapped?
static constexpr GrProxyProvider::TextureInfo kTextureInfo{GrMipMapped::kNo,
@@ -152,7 +156,7 @@ bool SkDeferredDisplayListRecorder::init() {
GrSwizzle readSwizzle = caps->getReadSwizzle(fCharacterization.backendFormat(), grColorType);
- sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
+ fTargetProxy = proxyProvider->createLazyRenderTargetProxy(
[lazyProxyData](GrResourceProvider* resourceProvider,
const GrSurfaceProxy::LazySurfaceDesc&) {
// The proxy backing the destination surface had better have been instantiated
@@ -174,14 +178,14 @@ bool SkDeferredDisplayListRecorder::init() {
fCharacterization.vulkanSecondaryCBCompatible(),
GrSurfaceProxy::UseAllocator::kYes);
- if (!proxy) {
+ if (!fTargetProxy) {
return false;
}
GrSwizzle writeSwizzle = caps->getWriteSwizzle(fCharacterization.backendFormat(), grColorType);
- GrSurfaceProxyView readView(proxy, fCharacterization.origin(), readSwizzle);
- GrSurfaceProxyView writeView(std::move(proxy), fCharacterization.origin(), writeSwizzle);
+ GrSurfaceProxyView readView(fTargetProxy, fCharacterization.origin(), readSwizzle);
+ GrSurfaceProxyView writeView(fTargetProxy, fCharacterization.origin(), writeSwizzle);
auto rtc = std::make_unique<GrRenderTargetContext>(fContext.get(), std::move(readView),
std::move(writeView), grColorType,
@@ -215,7 +219,9 @@ std::unique_ptr<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() {
}
auto ddl = std::unique_ptr<SkDeferredDisplayList>(
- new SkDeferredDisplayList(fCharacterization, std::move(fLazyProxyData)));
+ new SkDeferredDisplayList(fCharacterization,
+ std::move(fTargetProxy),
+ std::move(fLazyProxyData)));
fContext->priv().moveRenderTasksToDDL(ddl.get());
diff --git a/chromium/third_party/skia/src/core/SkDevice.cpp b/chromium/third_party/skia/src/core/SkDevice.cpp
index ca253822d1e..148ab89599a 100644
--- a/chromium/third_party/skia/src/core/SkDevice.cpp
+++ b/chromium/third_party/skia/src/core/SkDevice.cpp
@@ -96,8 +96,10 @@ bool SkBaseDevice::getLocalToMarker(uint32_t id, SkM44* localToMarker) const {
// The marker stack stores CTM snapshots, which are "marker to global" matrices.
// We ask for the (cached) inverse, which is a "global to marker" matrix.
SkM44 globalToMarker;
- if (fMarkerStack && fMarkerStack->findMarkerInverse(id, &globalToMarker)) {
+ // ID 0 is special, and refers to the CTM (local-to-global)
+ if (fMarkerStack && (id == 0 || fMarkerStack->findMarkerInverse(id, &globalToMarker))) {
if (localToMarker) {
+ // globalToMarker will still be the identity if id is zero
*localToMarker = globalToMarker * SkM44(fDeviceToGlobal) * fLocalToDevice;
}
return true;
@@ -313,8 +315,7 @@ void SkBaseDevice::drawDrawable(SkDrawable* drawable, const SkMatrix* matrix, Sk
///////////////////////////////////////////////////////////////////////////////////////////////////
-void SkBaseDevice::drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
- SkImage*, const SkMatrix&) {}
+void SkBaseDevice::drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&) {}
sk_sp<SkSpecialImage> SkBaseDevice::makeSpecial(const SkBitmap&) { return nullptr; }
sk_sp<SkSpecialImage> SkBaseDevice::makeSpecial(const SkImage*) { return nullptr; }
sk_sp<SkSpecialImage> SkBaseDevice::snapSpecial(const SkIRect&, bool) { return nullptr; }
diff --git a/chromium/third_party/skia/src/core/SkDevice.h b/chromium/third_party/skia/src/core/SkDevice.h
index 58be51f985e..b46b3a4257a 100644
--- a/chromium/third_party/skia/src/core/SkDevice.h
+++ b/chromium/third_party/skia/src/core/SkDevice.h
@@ -295,8 +295,7 @@ protected:
virtual void drawDrawable(SkDrawable*, const SkMatrix*, SkCanvas*);
- virtual void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
- SkImage* clipImage, const SkMatrix& clipMatrix);
+ virtual void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&);
virtual sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&);
virtual sk_sp<SkSpecialImage> makeSpecial(const SkImage*);
// Get a view of the entire device's current contents as an image.
diff --git a/chromium/third_party/skia/src/core/SkDraw.cpp b/chromium/third_party/skia/src/core/SkDraw.cpp
index 99c8bd82840..48858d1c9b2 100644
--- a/chromium/third_party/skia/src/core/SkDraw.cpp
+++ b/chromium/third_party/skia/src/core/SkDraw.cpp
@@ -511,7 +511,7 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
break;
}
}
- // couldn't take fast path so fall through!
+ [[fallthrough]]; // couldn't take fast path
case SkCanvas::kPolygon_PointMode: {
count -= 1;
SkPath path;
diff --git a/chromium/third_party/skia/src/core/SkDraw.h b/chromium/third_party/skia/src/core/SkDraw.h
index a9f778ad705..f7ed596dbcf 100644
--- a/chromium/third_party/skia/src/core/SkDraw.h
+++ b/chromium/third_party/skia/src/core/SkDraw.h
@@ -82,6 +82,7 @@ public:
void paintPaths(SkDrawableGlyphBuffer* drawables,
SkScalar scale,
+ SkPoint origin,
const SkPaint& paint) const override;
void paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint) const override;
diff --git a/chromium/third_party/skia/src/core/SkDraw_atlas.cpp b/chromium/third_party/skia/src/core/SkDraw_atlas.cpp
index fbc934690aa..077486f926b 100644
--- a/chromium/third_party/skia/src/core/SkDraw_atlas.cpp
+++ b/chromium/third_party/skia/src/core/SkDraw_atlas.cpp
@@ -101,24 +101,25 @@ void SkDraw::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRe
isOpaque = false;
}
- auto blitter = SkCreateRasterPipelineBlitter(fDst, p, pipeline, isOpaque, &alloc,
- fRC->clipShader());
- SkPath scratchPath;
-
- for (int i = 0; i < count; ++i) {
- if (colors) {
- SkColor4f c4 = SkColor4f::FromColor(colors[i]);
- steps.apply(c4.vec());
- load_color(uniformCtx, c4.premul().vec());
- }
+ if (auto blitter = SkCreateRasterPipelineBlitter(fDst, p, pipeline, isOpaque, &alloc,
+ fRC->clipShader())) {
+ SkPath scratchPath;
- SkMatrix mx;
- mx.setRSXform(xform[i]);
- mx.preTranslate(-textures[i].fLeft, -textures[i].fTop);
- mx.postConcat(fMatrixProvider->localToDevice());
+ for (int i = 0; i < count; ++i) {
+ if (colors) {
+ SkColor4f c4 = SkColor4f::FromColor(colors[i]);
+ steps.apply(c4.vec());
+ load_color(uniformCtx, c4.premul().vec());
+ }
- if (updator->update(mx, nullptr)) {
- fill_rect(mx, *fRC, textures[i], blitter, &scratchPath);
+ SkMatrix mx;
+ mx.setRSXform(xform[i]);
+ mx.preTranslate(-textures[i].fLeft, -textures[i].fTop);
+ mx.postConcat(fMatrixProvider->localToDevice());
+
+ if (updator->update(mx, nullptr)) {
+ fill_rect(mx, *fRC, textures[i], blitter, &scratchPath);
+ }
}
}
}
diff --git a/chromium/third_party/skia/src/core/SkDraw_text.cpp b/chromium/third_party/skia/src/core/SkDraw_text.cpp
index 1d138c43be8..953be1a9b27 100644
--- a/chromium/third_party/skia/src/core/SkDraw_text.cpp
+++ b/chromium/third_party/skia/src/core/SkDraw_text.cpp
@@ -112,11 +112,13 @@ void SkDraw::paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint)
void SkDraw::paintPaths(SkDrawableGlyphBuffer* drawables,
SkScalar scale,
+ SkPoint origin,
const SkPaint& paint) const {
for (auto [variant, pos] : drawables->drawable()) {
const SkPath* path = variant.path();
SkMatrix m;
- m.setScaleTranslate(scale, scale, pos.x(), pos.y());
+ SkPoint translate = origin + pos;
+ m.setScaleTranslate(scale, scale, translate.x(), translate.y());
this->drawPath(*path, paint, &m, false);
}
}
diff --git a/chromium/third_party/skia/src/core/SkDraw_vertices.cpp b/chromium/third_party/skia/src/core/SkDraw_vertices.cpp
index 9f605db64a8..fe8d496f48e 100644
--- a/chromium/third_party/skia/src/core/SkDraw_vertices.cpp
+++ b/chromium/third_party/skia/src/core/SkDraw_vertices.cpp
@@ -268,11 +268,13 @@ void SkDraw::draw_fixed_vertices(const SkVertices* vertices, SkBlendMode bmode,
const uint16_t* indices = info.indices();
const SkColor* colors = info.colors();
- // make textures and shader mutually consistent
+ // No need for texCoords without shader. If shader is present without explicit texCoords,
+ // use positions instead.
SkShader* shader = paint.getShader();
- if (!(shader && textures)) {
- shader = nullptr;
+ if (!shader) {
textures = nullptr;
+ } else if (!textures) {
+ textures = positions;
}
// We can simplify things for certain blendmodes. This is for speed, and SkComposeShader
@@ -328,14 +330,16 @@ void SkDraw::draw_fixed_vertices(const SkVertices* vertices, SkBlendMode bmode,
p.setShader(sk_ref_sp(shader));
if (!textures) { // only tricolor shader
- auto blitter = SkCreateRasterPipelineBlitter(fDst, p, *fMatrixProvider, outerAlloc,
- this->fRC->clipShader());
- while (vertProc(&state)) {
- if (triShader &&
- !triShader->update(ctmInv, positions, dstColors, state.f0, state.f1, state.f2)) {
- continue;
+ if (auto blitter = SkCreateRasterPipelineBlitter(fDst, p, *fMatrixProvider, outerAlloc,
+ this->fRC->clipShader())) {
+ while (vertProc(&state)) {
+ if (triShader &&
+ !triShader->update(ctmInv, positions, dstColors,
+ state.f0, state.f1, state.f2)) {
+ continue;
+ }
+ fill_triangle(state, blitter, *fRC, dev2, dev3);
}
- fill_triangle(state, blitter, *fRC, dev2, dev3);
}
return;
}
@@ -351,19 +355,28 @@ void SkDraw::draw_fixed_vertices(const SkVertices* vertices, SkBlendMode bmode,
// all opaque (and the blendmode will keep them that way
}
- auto blitter = SkCreateRasterPipelineBlitter(fDst, p, pipeline, isOpaque, outerAlloc,
- fRC->clipShader());
- while (vertProc(&state)) {
- if (triShader && !triShader->update(ctmInv, positions, dstColors,
- state.f0, state.f1, state.f2)) {
- continue;
+ // Positions as texCoords? The local matrix is always identity, so update once
+ if (textures == positions) {
+ SkMatrix localM;
+ if (!updater->update(ctm, &localM)) {
+ return;
}
+ }
- SkMatrix localM;
- if (texture_to_matrix(state, positions, textures, &localM) &&
- updater->update(ctm, &localM))
- {
- fill_triangle(state, blitter, *fRC, dev2, dev3);
+ if (auto blitter = SkCreateRasterPipelineBlitter(fDst, p, pipeline, isOpaque, outerAlloc,
+ fRC->clipShader())) {
+ while (vertProc(&state)) {
+ if (triShader && !triShader->update(ctmInv, positions, dstColors,
+ state.f0, state.f1, state.f2)) {
+ continue;
+ }
+
+ SkMatrix localM;
+ if ((textures == positions) ||
+ (texture_to_matrix(state, positions, textures, &localM) &&
+ updater->update(ctm, &localM))) {
+ fill_triangle(state, blitter, *fRC, dev2, dev3);
+ }
}
}
} else {
@@ -378,7 +391,7 @@ void SkDraw::draw_fixed_vertices(const SkVertices* vertices, SkBlendMode bmode,
const SkMatrixProvider* matrixProvider = fMatrixProvider;
SkTLazy<SkPreConcatMatrixProvider> preConcatMatrixProvider;
- if (textures) {
+ if (textures && (textures != positions)) {
SkMatrix localM;
if (!texture_to_matrix(state, positions, textures, &localM)) {
continue;
@@ -386,9 +399,10 @@ void SkDraw::draw_fixed_vertices(const SkVertices* vertices, SkBlendMode bmode,
matrixProvider = preConcatMatrixProvider.init(*matrixProvider, localM);
}
- auto blitter = SkCreateRasterPipelineBlitter(fDst, p, *matrixProvider, &innerAlloc,
- this->fRC->clipShader());
- fill_triangle(state, blitter, *fRC, dev2, dev3);
+ if (auto blitter = SkCreateRasterPipelineBlitter(fDst, p, *matrixProvider, &innerAlloc,
+ this->fRC->clipShader())) {
+ fill_triangle(state, blitter, *fRC, dev2, dev3);
+ }
}
}
}
diff --git a/chromium/third_party/skia/src/core/SkDrawable.cpp b/chromium/third_party/skia/src/core/SkDrawable.cpp
index 62b02729726..5e12fa59131 100644
--- a/chromium/third_party/skia/src/core/SkDrawable.cpp
+++ b/chromium/third_party/skia/src/core/SkDrawable.cpp
@@ -43,7 +43,7 @@ void SkDrawable::draw(SkCanvas* canvas, const SkMatrix* matrix) {
}
void SkDrawable::draw(SkCanvas* canvas, SkScalar x, SkScalar y) {
- SkMatrix matrix = SkMatrix::MakeTrans(x, y);
+ SkMatrix matrix = SkMatrix::Translate(x, y);
this->draw(canvas, &matrix);
}
diff --git a/chromium/third_party/skia/src/core/SkFont.cpp b/chromium/third_party/skia/src/core/SkFont.cpp
index 9a4767520c6..6e066dd4157 100644
--- a/chromium/third_party/skia/src/core/SkFont.cpp
+++ b/chromium/third_party/skia/src/core/SkFont.cpp
@@ -270,7 +270,7 @@ void SkFont::getWidthsBounds(const SkGlyphID glyphIDs[],
SkScalar scale = strikeSpec.strikeToSourceRatio();
if (bounds) {
- SkMatrix scaleMat = SkMatrix::MakeScale(scale);
+ SkMatrix scaleMat = SkMatrix::Scale(scale, scale);
SkRect* cursor = bounds;
for (auto glyph : glyphs) {
scaleMat.mapRectScaleTranslate(cursor++, glyph->rect());
@@ -316,7 +316,7 @@ void SkFont::getPaths(const SkGlyphID glyphIDs[], int count,
void (*proc)(const SkPath*, const SkMatrix&, void*), void* ctx) const {
SkFont font(*this);
SkScalar scale = font.setupForAsPaths(nullptr);
- const SkMatrix mx = SkMatrix::MakeScale(scale);
+ const SkMatrix mx = SkMatrix::Scale(scale, scale);
SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice(font);
SkBulkGlyphMetricsAndPaths paths{strikeSpec};
diff --git a/chromium/third_party/skia/src/core/SkFontPriv.h b/chromium/third_party/skia/src/core/SkFontPriv.h
index 6b7bd862b8d..5d07909440c 100644
--- a/chromium/third_party/skia/src/core/SkFontPriv.h
+++ b/chromium/third_party/skia/src/core/SkFontPriv.h
@@ -37,7 +37,7 @@ public:
* Return a matrix that applies the paint's text values: size, scale, skew
*/
static SkMatrix MakeTextMatrix(SkScalar size, SkScalar scaleX, SkScalar skewX) {
- SkMatrix m = SkMatrix::MakeScale(size * scaleX, size);
+ SkMatrix m = SkMatrix::Scale(size * scaleX, size);
if (skewX) {
m.postSkew(skewX, 0);
}
diff --git a/chromium/third_party/skia/src/core/SkGlyphBuffer.cpp b/chromium/third_party/skia/src/core/SkGlyphBuffer.cpp
index 5cc0de8c3de..6a8e0c59a4f 100644
--- a/chromium/third_party/skia/src/core/SkGlyphBuffer.cpp
+++ b/chromium/third_party/skia/src/core/SkGlyphBuffer.cpp
@@ -25,15 +25,12 @@ void SkDrawableGlyphBuffer::ensureSize(size_t size) {
fDrawableSize = 0;
}
-void SkDrawableGlyphBuffer::startSource(
- const SkZip<const SkGlyphID, const SkPoint>& source, SkPoint origin) {
+void SkDrawableGlyphBuffer::startSource(const SkZip<const SkGlyphID, const SkPoint>& source) {
fInputSize = source.size();
fDrawableSize = 0;
- // Map all the positions.
auto positions = source.get<1>();
- SkMatrix::MakeTrans(origin.x(), origin.y()).mapPoints(
- fPositions, positions.data(), positions.size());
+ memcpy(fPositions, positions.data(), positions.size() * sizeof(SkPoint));
// Convert from SkGlyphIDs to SkPackedGlyphIDs.
SkGlyphVariant* packedIDCursor = fMultiBuffer;
@@ -43,22 +40,35 @@ void SkDrawableGlyphBuffer::startSource(
SkDEBUGCODE(fPhase = kInput);
}
-void SkDrawableGlyphBuffer::startPaths(const SkZip<const SkGlyphID, const SkPoint> &source) {
+void SkDrawableGlyphBuffer::startBitmapDevice(
+ const SkZip<const SkGlyphID, const SkPoint>& source,
+ SkPoint origin, const SkMatrix& viewMatrix,
+ const SkGlyphPositionRoundingSpec& roundingSpec) {
fInputSize = source.size();
fDrawableSize = 0;
+ // Map the positions including subpixel position.
auto positions = source.get<1>();
- memcpy(fPositions, positions.data(), positions.size() * sizeof(SkPoint));
+ SkMatrix matrix = viewMatrix;
+ matrix.preTranslate(origin.x(), origin.y());
+ SkPoint halfSampleFreq = roundingSpec.halfAxisSampleFreq;
+ matrix.postTranslate(halfSampleFreq.x(), halfSampleFreq.y());
+ matrix.mapPoints(fPositions, positions.data(), positions.size());
- // Convert from SkGlyphIDs to SkPackedGlyphIDs.
+ // Mask for controlling axis alignment.
+ SkIPoint mask = roundingSpec.ignorePositionFieldMask;
+
+ // Convert glyph ids and positions to packed glyph ids.
+ SkZip<const SkGlyphID, const SkPoint> withMappedPos =
+ SkMakeZip(source.get<0>(), fPositions.get());
SkGlyphVariant* packedIDCursor = fMultiBuffer;
- for (auto t : source) {
- *packedIDCursor++ = SkPackedGlyphID{std::get<0>(t)};
+ for (auto [glyphID, pos] : withMappedPos) {
+ *packedIDCursor++ = SkPackedGlyphID{glyphID, pos, mask};
}
SkDEBUGCODE(fPhase = kInput);
}
-void SkDrawableGlyphBuffer::startDevice(
+void SkDrawableGlyphBuffer::startGPUDevice(
const SkZip<const SkGlyphID, const SkPoint>& source,
SkPoint origin, const SkMatrix& viewMatrix,
const SkGlyphPositionRoundingSpec& roundingSpec) {
@@ -69,6 +79,9 @@ void SkDrawableGlyphBuffer::startDevice(
auto positions = source.get<1>();
SkMatrix matrix = viewMatrix;
matrix.preTranslate(origin.x(), origin.y());
+
+ // Q = [M][T](0,0).
+ SkPoint Q = matrix.mapXY(0, 0);
SkPoint halfSampleFreq = roundingSpec.halfAxisSampleFreq;
matrix.postTranslate(halfSampleFreq.x(), halfSampleFreq.y());
matrix.mapPoints(fPositions, positions.data(), positions.size());
@@ -83,9 +96,16 @@ void SkDrawableGlyphBuffer::startDevice(
for (auto [glyphID, pos] : withMappedPos) {
*packedIDCursor++ = SkPackedGlyphID{glyphID, pos, mask};
}
+
+ for (SkPoint& pos : SkSpan<SkPoint>(fPositions, source.size())) {
+ SkPoint P = SkPoint::Make(SkScalarFloorToScalar(pos.x()), SkScalarFloorToScalar(pos.y()));
+ pos = P - Q;
+ }
+
SkDEBUGCODE(fPhase = kInput);
}
+
void SkDrawableGlyphBuffer::reset() {
SkDEBUGCODE(fPhase = kReset);
if (fMaxSize > 200) {
diff --git a/chromium/third_party/skia/src/core/SkGlyphBuffer.h b/chromium/third_party/skia/src/core/SkGlyphBuffer.h
index fe4da38c910..8458afdbc52 100644
--- a/chromium/third_party/skia/src/core/SkGlyphBuffer.h
+++ b/chromium/third_party/skia/src/core/SkGlyphBuffer.h
@@ -143,14 +143,34 @@ class SkDrawableGlyphBuffer {
public:
void ensureSize(size_t size);
- // Load the buffer with SkPackedGlyphIDs and positions in source space.
- void startSource(const SkZip<const SkGlyphID, const SkPoint>& source, SkPoint origin);
-
- // Use the original glyphIDs and positions.
- void startPaths(const SkZip<const SkGlyphID, const SkPoint>& source);
+ // Load the buffer with SkPackedGlyphIDs and positions at (0, 0) ready to finish positioning
+ // during drawing.
+ void startSource(const SkZip<const SkGlyphID, const SkPoint>& source);
// Load the buffer with SkPackedGlyphIDs and positions using the device transform.
- void startDevice(
+ void startBitmapDevice(
+ const SkZip<const SkGlyphID, const SkPoint>& source,
+ SkPoint origin, const SkMatrix& viewMatrix,
+ const SkGlyphPositionRoundingSpec& roundingSpec);
+
+ // Load the buffer with SkPackedGlyphIDs, calculating positions so they can be constant.
+ //
+ // A final device position is computed in the following manner:
+ // [x,y] = Floor[M][T][x',y']^t
+ // M is complicated but includes the rounding offsets for subpixel positioning.
+ // T is the translation matrix derived from the text blob origin.
+ // The final position is {Floor(x), Floor(y)}. If we want to move this position around in
+ // device space given a start origin T in source space and a end position T' in source space
+ // and new device matrix M', we need to calculate a suitable device space translation V. We
+ // know that V must be integer.
+ // V = [M'][T'](0,0)^t - [M][T](0,0)^t.
+ // V = Q' - Q
+ // So all the positions Ps are translated by V to translate from T to T' in source space. We can
+ // generate Ps such that we just need to add any Q' to the constant Ps to get a final positions.
+ // So, a single point P = {Floor(x)-Q_x, Floor(y)-Q_y}; this does not have to be integer.
+ // This allows positioning to be P + Q', which given ideal numbers would be an integer. Since
+ // the addition is done with floating point, it must be rounded.
+ void startGPUDevice(
const SkZip<const SkGlyphID, const SkPoint>& source,
SkPoint origin, const SkMatrix& viewMatrix,
const SkGlyphPositionRoundingSpec& roundingSpec);
diff --git a/chromium/third_party/skia/src/core/SkGlyphRunPainter.cpp b/chromium/third_party/skia/src/core/SkGlyphRunPainter.cpp
index 8ef928db375..a8227f93437 100644
--- a/chromium/third_party/skia/src/core/SkGlyphRunPainter.cpp
+++ b/chromium/third_party/skia/src/core/SkGlyphRunPainter.cpp
@@ -15,8 +15,9 @@
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/SkGr.h"
+#include "src/gpu/ops/GrAtlasTextOp.h"
+#include "src/gpu/text/GrSDFTOptions.h"
#include "src/gpu/text/GrTextBlobCache.h"
-#include "src/gpu/text/GrTextContext.h"
#endif
#include "include/core/SkColorFilter.h"
@@ -47,7 +48,7 @@ SkGlyphRunListPainter::SkGlyphRunListPainter(const SkSurfaceProps& props,
, fColorType{colorType}, fScalerContextFlags{flags}
, fStrikeCache{strikeCache} {}
-// TODO: unify with code in GrTextContext.cpp
+// TODO: unify with code in GrSDFTOptions.cpp
static SkScalerContextFlags compute_scaler_context_flags(const SkColorSpace* cs) {
// 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:
@@ -106,7 +107,7 @@ void SkGlyphRunListPainter::drawForBitmapDevice(
auto strike = strikeSpec.findOrCreateStrike();
- fDrawable.startSource(fRejects.source(), drawOrigin);
+ fDrawable.startSource(fRejects.source());
strike->prepareForPathDrawing(&fDrawable, &fRejects);
fRejects.flipRejectsToSource();
@@ -115,7 +116,8 @@ void SkGlyphRunListPainter::drawForBitmapDevice(
SkPaint pathPaint = runPaint;
pathPaint.setAntiAlias(runFont.hasSomeAntiAliasing());
- bitmapDevice->paintPaths(&fDrawable, strikeSpec.strikeToSourceRatio(), pathPaint);
+ bitmapDevice->paintPaths(
+ &fDrawable, strikeSpec.strikeToSourceRatio(), drawOrigin, pathPaint);
}
if (!fRejects.source().empty()) {
SkStrikeSpec strikeSpec = SkStrikeSpec::MakeMask(
@@ -123,7 +125,7 @@ void SkGlyphRunListPainter::drawForBitmapDevice(
auto strike = strikeSpec.findOrCreateStrike();
- fDrawable.startDevice(
+ fDrawable.startBitmapDevice(
fRejects.source(), drawOrigin, deviceMatrix, strike->roundingSpec());
strike->prepareForDrawingMasksCPU(&fDrawable);
bitmapDevice->paintMasks(&fDrawable, runPaint);
@@ -139,7 +141,7 @@ void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunLi
const SkMatrix& drawMatrix,
const SkSurfaceProps& props,
bool contextSupportsDistanceFieldText,
- const GrTextContext::Options& options,
+ const GrSDFTOptions& options,
SkGlyphRunPainterInterface* process) {
SkPoint origin = glyphRunList.origin();
@@ -151,8 +153,8 @@ void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunLi
const SkFont& runFont = glyphRun.font();
- bool useSDFT = GrTextContext::CanDrawAsDistanceFields(
- runPaint, runFont, drawMatrix, props, contextSupportsDistanceFieldText, options);
+ bool useSDFT = options.canDrawAsDistanceFields(
+ runPaint, runFont, drawMatrix, props, contextSupportsDistanceFieldText);
bool usePaths =
useSDFT ? false : SkStrikeSpec::ShouldDrawAsPath(runPaint, runFont, drawMatrix);
@@ -167,7 +169,7 @@ void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunLi
if (!strikeSpec.isEmpty()) {
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
- fDrawable.startSource(fRejects.source(), origin);
+ fDrawable.startSource(fRejects.source());
strike->prepareForSDFTDrawing(&fDrawable, &fRejects);
fRejects.flipRejectsToSource();
@@ -188,7 +190,7 @@ void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunLi
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
- fDrawable.startDevice(fRejects.source(), origin, drawMatrix, strike->roundingSpec());
+ fDrawable.startGPUDevice(fRejects.source(), origin, drawMatrix, strike->roundingSpec());
strike->prepareForMaskDrawing(&fDrawable, &fRejects);
fRejects.flipRejectsToSource();
@@ -212,7 +214,7 @@ void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunLi
if (!strikeSpec.isEmpty()) {
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
- fDrawable.startPaths(fRejects.source());
+ fDrawable.startSource(fRejects.source());
strike->prepareForPathDrawing(&fDrawable, &fRejects);
fRejects.flipRejectsToSource();
maxDimensionInSourceSpace =
@@ -235,7 +237,7 @@ void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunLi
if (!strikeSpec.isEmpty()) {
SkScopedStrikeForGPU strike = strikeSpec.findOrCreateScopedStrike(fStrikeCache);
- fDrawable.startSource(fRejects.source(), origin);
+ fDrawable.startSource(fRejects.source());
strike->prepareForMaskDrawing(&fDrawable, &fRejects);
fRejects.flipRejectsToSource();
SkASSERT(fRejects.source().empty());
@@ -257,158 +259,6 @@ auto SkGlyphRunListPainter::ensureBuffers(const SkGlyphRunList& glyphRunList) ->
return ScopedBuffers(this, size);
}
-#if SK_SUPPORT_GPU
-// -- GrTextContext --------------------------------------------------------------------------------
-SkPMColor4f generate_filtered_color(const SkPaint& paint, const GrColorInfo& colorInfo) {
- SkColor4f filteredColor = paint.getColor4f();
- if (auto* xform = colorInfo.colorSpaceXformFromSRGB()) {
- filteredColor = xform->apply(filteredColor);
- }
- if (paint.getColorFilter() != nullptr) {
- filteredColor = paint.getColorFilter()->filterColor4f(filteredColor, colorInfo.colorSpace(),
- colorInfo.colorSpace());
- }
- return filteredColor.premul();
-}
-
-void GrTextContext::drawGlyphRunList(GrRecordingContext* context,
- GrTextTarget* target,
- const GrClip& clip,
- const SkMatrixProvider& matrixProvider,
- const SkSurfaceProps& props,
- const SkGlyphRunList& glyphRunList) const {
- auto contextPriv = context->priv();
- // If we have been abandoned, then don't draw
- if (contextPriv.abandoned()) {
- return;
- }
- GrTextBlobCache* textBlobCache = contextPriv.getTextBlobCache();
-
- // Get the first paint to use as the key paint.
- const SkPaint& blobPaint = glyphRunList.paint();
-
- const GrColorInfo& colorInfo = target->colorInfo();
- // This is the color the op will use to draw.
- SkPMColor4f drawingColor = generate_filtered_color(blobPaint, colorInfo);
- // When creating the a new blob, use the GrColor calculated from the drawingColor.
- GrColor initialVertexColor = drawingColor.toBytes_RGBA();
-
- SkPoint drawOrigin = glyphRunList.origin();
-
- 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)));
- SkScalerContextFlags scalerContextFlags = ComputeScalerContextFlags(colorInfo);
-
- sk_sp<GrTextBlob> cachedBlob;
- GrTextBlob::Key key;
- if (canCache) {
- bool hasLCD = glyphRunList.anyRunsLCD();
-
- // We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry
- SkPixelGeometry pixelGeometry = hasLCD ? props.pixelGeometry() : kUnknown_SkPixelGeometry;
-
- // TODO we want to figure out a way to be able to use the canonical color on LCD text,
- // see the note on ComputeCanonicalColor above. We pick a dummy value for LCD text to
- // ensure we always match the same key
- GrColor canonicalColor = hasLCD ? SK_ColorTRANSPARENT :
- ComputeCanonicalColor(blobPaint, hasLCD);
-
- key.fPixelGeometry = pixelGeometry;
- key.fUniqueID = glyphRunList.uniqueID();
- key.fStyle = blobPaint.getStyle();
- key.fHasBlur = SkToBool(mf);
- key.fCanonicalColor = canonicalColor;
- key.fScalerContextFlags = scalerContextFlags;
- cachedBlob = textBlobCache->find(key);
- }
-
- bool forceW = fOptions.fDistanceFieldVerticesAlwaysHaveW;
- bool supportsSDFT = context->priv().caps()->shaderCaps()->supportsDistanceFieldText();
- SkGlyphRunListPainter* painter = target->glyphPainter();
- const SkMatrix& drawMatrix(matrixProvider.localToDevice());
- if (cachedBlob) {
- if (cachedBlob->mustRegenerate(blobPaint, glyphRunList.anyRunsSubpixelPositioned(),
- blurRec, drawMatrix, drawOrigin)) {
- // We have to remake the blob because changes may invalidate our masks.
- // TODO we could probably get away reuse most of the time if the pointer is unique,
- // but we'd have to clear the subrun information
- textBlobCache->remove(cachedBlob.get());
- cachedBlob = textBlobCache->makeCachedBlob(glyphRunList, key, blurRec, drawMatrix,
- initialVertexColor, forceW);
-
- painter->processGlyphRunList(
- glyphRunList, drawMatrix, props, supportsSDFT, fOptions, cachedBlob.get());
- } else {
- textBlobCache->makeMRU(cachedBlob.get());
- }
- } else {
- if (canCache) {
- cachedBlob = textBlobCache->makeCachedBlob(glyphRunList, key, blurRec, drawMatrix,
- initialVertexColor, forceW);
- } else {
- cachedBlob = textBlobCache->makeBlob(glyphRunList, drawMatrix,
- initialVertexColor, forceW);
- }
- painter->processGlyphRunList(
- glyphRunList, drawMatrix, props, supportsSDFT, fOptions, cachedBlob.get());
- }
-
- cachedBlob->addOp(target, props, blobPaint, drawingColor, clip, matrixProvider, drawOrigin);
-}
-
-#if GR_TEST_UTILS
-
-#include "src/gpu/GrRecordingContextPriv.h"
-#include "src/gpu/GrRenderTargetContext.h"
-
-std::unique_ptr<GrDrawOp> GrTextContext::createOp_TestingOnly(GrRecordingContext* context,
- GrTextContext* textContext,
- GrRenderTargetContext* rtc,
- const SkPaint& skPaint,
- const SkFont& font,
- const SkMatrixProvider& mtxProvider,
- const char* text,
- int x,
- int y) {
- auto direct = context->priv().asDirectContext();
- if (!direct) {
- return nullptr;
- }
-
- static SkSurfaceProps surfaceProps(SkSurfaceProps::kLegacyFontHost_InitType);
-
- size_t textLen = (int)strlen(text);
-
- SkPMColor4f filteredColor = generate_filtered_color(skPaint, rtc->colorInfo());
- GrColor color = filteredColor.toBytes_RGBA();
- const SkMatrix& drawMatrix(mtxProvider.localToDevice());
-
- auto drawOrigin = SkPoint::Make(x, y);
- SkGlyphRunBuilder builder;
- builder.drawTextUTF8(skPaint, font, text, textLen, drawOrigin);
-
- auto glyphRunList = builder.useGlyphRunList();
- sk_sp<GrTextBlob> blob;
- if (!glyphRunList.empty()) {
- blob = direct->priv().getTextBlobCache()->makeBlob(glyphRunList, drawMatrix, color, false);
- SkGlyphRunListPainter* painter = rtc->textTarget()->glyphPainter();
- painter->processGlyphRunList(
- glyphRunList, drawMatrix, surfaceProps,
- context->priv().caps()->shaderCaps()->supportsDistanceFieldText(),
- textContext->fOptions, blob.get());
- }
-
- return blob->test_makeOp(mtxProvider, drawOrigin, skPaint, filteredColor, surfaceProps,
- rtc->textTarget());
-}
-
-#endif // GR_TEST_UTILS
-#endif // SK_SUPPORT_GPU
-
SkGlyphRunListPainter::ScopedBuffers::ScopedBuffers(SkGlyphRunListPainter* painter, size_t size)
: fPainter{painter} {
fPainter->fDrawable.ensureSize(size);
diff --git a/chromium/third_party/skia/src/core/SkGlyphRunPainter.h b/chromium/third_party/skia/src/core/SkGlyphRunPainter.h
index 6b64566b9e1..3394239533b 100644
--- a/chromium/third_party/skia/src/core/SkGlyphRunPainter.h
+++ b/chromium/third_party/skia/src/core/SkGlyphRunPainter.h
@@ -16,7 +16,7 @@
#include "src/core/SkTextBlobPriv.h"
#if SK_SUPPORT_GPU
-#include "src/gpu/text/GrTextContext.h"
+#include "src/gpu/text/GrSDFTOptions.h"
class GrColorInfo;
class GrRenderTargetContext;
#endif
@@ -70,7 +70,8 @@ public:
virtual ~BitmapDevicePainter() = default;
virtual void paintPaths(
- SkDrawableGlyphBuffer* drawables, SkScalar scale, const SkPaint& paint) const = 0;
+ SkDrawableGlyphBuffer* drawables, SkScalar scale, SkPoint origin,
+ const SkPaint& paint) const = 0;
virtual void paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint) const = 0;
};
@@ -86,7 +87,7 @@ public:
const SkMatrix& drawMatrix,
const SkSurfaceProps& props,
bool contextSupportsDistanceFieldText,
- const GrTextContext::Options& options,
+ const GrSDFTOptions& options,
SkGlyphRunPainterInterface* process);
#endif // SK_SUPPORT_GPU
diff --git a/chromium/third_party/skia/src/core/SkGpuBlurUtils.cpp b/chromium/third_party/skia/src/core/SkGpuBlurUtils.cpp
index e578ad6d7b8..2dadacc68e0 100644
--- a/chromium/third_party/skia/src/core/SkGpuBlurUtils.cpp
+++ b/chromium/third_party/skia/src/core/SkGpuBlurUtils.cpp
@@ -12,7 +12,6 @@
#if SK_SUPPORT_GPU
#include "include/private/GrRecordingContext.h"
#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrRenderTargetContextPriv.h"
@@ -25,50 +24,9 @@
using Direction = GrGaussianConvolutionFragmentProcessor::Direction;
-static void scale_irect_roundout(SkIRect* rect, float xScale, float yScale) {
- rect->fLeft = SkScalarFloorToInt(rect->fLeft * xScale);
- rect->fTop = SkScalarFloorToInt(rect->fTop * yScale);
- rect->fRight = SkScalarCeilToInt(rect->fRight * xScale);
- rect->fBottom = SkScalarCeilToInt(rect->fBottom * yScale);
-}
-
-static void scale_irect(SkIRect* rect, int xScale, int yScale) {
- rect->fLeft *= xScale;
- rect->fTop *= yScale;
- rect->fRight *= xScale;
- rect->fBottom *= yScale;
-}
-
-#ifdef SK_DEBUG
-static inline int is_even(int x) { return !(x & 1); }
-#endif
-
-static void shrink_irect_by_2(SkIRect* rect, bool xAxis, bool yAxis) {
- if (xAxis) {
- SkASSERT(is_even(rect->fLeft) && is_even(rect->fRight));
- rect->fLeft /= 2;
- rect->fRight /= 2;
- }
- if (yAxis) {
- SkASSERT(is_even(rect->fTop) && is_even(rect->fBottom));
- rect->fTop /= 2;
- rect->fBottom /= 2;
- }
-}
-
-static float adjust_sigma(float sigma, int maxTextureSize, int *scaleFactor, int *radius) {
- *scaleFactor = 1;
- while (sigma > MAX_BLUR_SIGMA) {
- *scaleFactor *= 2;
- sigma *= 0.5f;
- if (*scaleFactor > maxTextureSize) {
- *scaleFactor = maxTextureSize;
- sigma = MAX_BLUR_SIGMA;
- }
- }
- *radius = static_cast<int>(ceilf(sigma * 3.0f));
- SkASSERT(*radius <= GrGaussianConvolutionFragmentProcessor::kMaxKernelRadius);
- return sigma;
+static int sigma_radius(float sigma) {
+ SkASSERT(sigma >= 0);
+ return static_cast<int>(ceilf(sigma * 3.0f));
}
/**
@@ -77,32 +35,24 @@ static float adjust_sigma(float sigma, int maxTextureSize, int *scaleFactor, int
*/
static void convolve_gaussian_1d(GrRenderTargetContext* renderTargetContext,
GrSurfaceProxyView srcView,
+ const SkIRect srcSubset,
SkIVector rtcToSrcOffset,
const SkIRect& rtcRect,
SkAlphaType srcAlphaType,
Direction direction,
int radius,
float sigma,
- SkTileMode mode,
- int bounds[2]) {
+ SkTileMode mode) {
GrPaint paint;
auto wm = SkTileModeToWrapMode(mode);
- int realBounds[2];
- if (bounds) {
- realBounds[0] = bounds[0]; realBounds[1] = bounds[1];
- } else {
- auto proxy = srcView.proxy();
- realBounds[0] = 0;
- realBounds[1] = direction == Direction::kX ? proxy->width() : proxy->height();
- }
+ auto srcRect = rtcRect.makeOffset(rtcToSrcOffset);
std::unique_ptr<GrFragmentProcessor> conv(GrGaussianConvolutionFragmentProcessor::Make(
- std::move(srcView), srcAlphaType, direction, radius, sigma, wm, realBounds,
+ std::move(srcView), srcAlphaType, direction, radius, sigma, wm, srcSubset, &srcRect,
*renderTargetContext->caps()));
paint.addColorFragmentProcessor(std::move(conv));
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
- auto srcRect = SkRect::Make(rtcRect.makeOffset(rtcToSrcOffset));
- renderTargetContext->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
- SkRect::Make(rtcRect), srcRect);
+ renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
+ SkRect::Make(rtcRect), SkRect::Make(srcRect));
}
static std::unique_ptr<GrRenderTargetContext> convolve_gaussian_2d(GrRecordingContext* context,
@@ -138,7 +88,7 @@ static std::unique_ptr<GrRenderTargetContext> convolve_gaussian_2d(GrRecordingCo
// 'dstBounds' is actually in 'srcView' proxy space. It represents the blurred area from src
// space that we want to capture in the new RTC at {0, 0}. Hence, we use its size as the rect to
// draw and it directly as the local rect.
- renderTargetContext->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+ renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
SkRect::Make(dstBounds.size()), SkRect::Make(dstBounds));
return renderTargetContext;
@@ -148,7 +98,7 @@ static std::unique_ptr<GrRenderTargetContext> convolve_gaussian(GrRecordingConte
GrSurfaceProxyView srcView,
GrColorType srcColorType,
SkAlphaType srcAlphaType,
- SkIRect* contentRect,
+ SkIRect srcBounds,
SkIRect dstBounds,
Direction direction,
int radius,
@@ -156,7 +106,7 @@ static std::unique_ptr<GrRenderTargetContext> convolve_gaussian(GrRecordingConte
SkTileMode mode,
sk_sp<SkColorSpace> finalCS,
SkBackingFit fit) {
- // Logically we're creating an infinite blur of 'contentRect' of 'srcView' with 'mode' tiling
+ // Logically we're creating an infinite blur of 'srcBounds' of 'srcView' with 'mode' tiling
// and then capturing the 'dstBounds' portion in a new RTC where the top left of 'dstBounds' is
// at {0, 0} in the new RTC.
auto dstRenderTargetContext = GrRenderTargetContext::Make(
@@ -165,193 +115,138 @@ static std::unique_ptr<GrRenderTargetContext> convolve_gaussian(GrRecordingConte
if (!dstRenderTargetContext) {
return nullptr;
}
-
// This represents the translation from 'dstRenderTargetContext' coords to 'srcView' coords.
auto rtcToSrcOffset = dstBounds.topLeft();
- if (SkTileMode::kClamp == mode &&
- contentRect->contains(SkIRect::MakeSize(srcView.proxy()->backingStoreDimensions()))) {
+ auto srcBackingBounds = SkIRect::MakeSize(srcView.proxy()->backingStoreDimensions());
+ // We've implemented splitting the dst bounds up into areas that do and do not need to
+ // use shader based tiling but only for some modes...
+ bool canSplit = mode == SkTileMode::kDecal || mode == SkTileMode::kClamp;
+ // ...but it's not worth doing the splitting if we'll get HW tiling instead of shader tiling.
+ bool canHWTile =
+ srcBounds.contains(srcBackingBounds) &&
+ !(mode == SkTileMode::kDecal && !context->priv().caps()->clampToBorderSupport());
+ if (!canSplit || canHWTile) {
auto dstRect = SkIRect::MakeSize(dstBounds.size());
- convolve_gaussian_1d(dstRenderTargetContext.get(), std::move(srcView), rtcToSrcOffset,
- dstRect, srcAlphaType, direction, radius, sigma, SkTileMode::kClamp,
- nullptr);
- *contentRect = dstRect;
+ convolve_gaussian_1d(dstRenderTargetContext.get(), std::move(srcView), srcBounds,
+ rtcToSrcOffset, dstRect, srcAlphaType, direction, radius, sigma, mode);
return dstRenderTargetContext;
}
- // 'left' and 'right' are the sub rects of 'contentTect' where 'mode' must be enforced.
+ // 'left' and 'right' are the sub rects of 'srcBounds' where 'mode' must be enforced.
// 'mid' is the area where we can ignore the mode because the kernel does not reach to the
- // edge of 'contentRect'. The names are derived from the Direction::kX case.
- // TODO: When mode is kMirror or kRepeat it makes more sense to think of 'contentRect'
- // as a tile and figure out the collection of mid/left/right rects that cover 'dstBounds'.
- // Also if 'mid' is small and 'left' or 'right' is non-empty we should probably issue one
- // draw that implements the mode in the shader rather than break it up in this fashion.
+ // edge of 'srcBounds'.
SkIRect mid, left, right;
- // 'top' and 'bottom' are areas of 'dstBounds' that are entirely above/below
- // 'contentRect'. These are areas that we can simply clear in the dst. If 'contentRect'
+ // 'top' and 'bottom' are areas of 'dstBounds' that are entirely above/below 'srcBounds'.
+ // These are areas that we can simply clear in the dst in kDecal mode. If 'srcBounds'
// straddles the top edge of 'dstBounds' then 'top' will be inverted and we will skip
- // the clear. Similar for 'bottom'. The positional/directional labels above refer to the
- // Direction::kX case and one should think of these as 'left' and 'right' for Direction::kY.
+ // processing for the rect. Similar for 'bottom'. The positional/directional labels above refer
+ // to the Direction::kX case and one should think of these as 'left' and 'right' for
+ // Direction::kY.
SkIRect top, bottom;
- int bounds[2];
if (Direction::kX == direction) {
- bounds[0] = contentRect->left();
- bounds[1] = contentRect->right();
-
- top = {dstBounds.left(), dstBounds.top() , dstBounds.right(), contentRect->top()};
- bottom = {dstBounds.left(), contentRect->bottom(), dstBounds.right(), dstBounds.bottom()};
-
- // Inset for sub-rect of 'contentRect' where the x-dir kernel doesn't reach the edges.
- // TODO: Consider clipping mid/left/right to dstBounds to increase likelihood of doing
- // fewer draws below.
- mid = contentRect->makeInset(radius, 0);
-
- left = {dstBounds.left(), mid.top(), mid.left() , mid.bottom()};
- right = {mid.right(), mid.top(), dstBounds.right(), mid.bottom()};
-
- // The new 'contentRect' when we're done will be the area between the clears in the dst.
- *contentRect = {dstBounds.left(),
- std::max(contentRect->top(), dstBounds.top()),
- dstBounds.right(),
- std::min(dstBounds.bottom(), contentRect->bottom())};
+ top = {dstBounds.left(), dstBounds.top() , dstBounds.right(), srcBounds.top() };
+ bottom = {dstBounds.left(), srcBounds.bottom(), dstBounds.right(), dstBounds.bottom()};
+
+ // Inset for sub-rect of 'srcBounds' where the x-dir kernel doesn't reach the edges, clipped
+ // vertically to dstBounds.
+ int midA = std::max(srcBounds.top() , dstBounds.top() );
+ int midB = std::min(srcBounds.bottom(), dstBounds.bottom());
+ mid = {srcBounds.left() + radius, midA, srcBounds.right() - radius, midB};
+ if (mid.isEmpty()) {
+ // There is no middle where the bounds can be ignored. Make the left span the whole
+ // width of dst and we will not draw mid or right.
+ left = {dstBounds.left(), mid.top(), dstBounds.right(), mid.bottom()};
+ } else {
+ left = {dstBounds.left(), mid.top(), mid.left() , mid.bottom()};
+ right = {mid.right(), mid.top(), dstBounds.right(), mid.bottom()};
+ }
} else {
// This is the same as the x direction code if you turn your head 90 degrees CCW. Swap x and
// y and swap top/bottom with left/right.
- bounds[0] = contentRect->top();
- bounds[1] = contentRect->bottom();
-
- top = {dstBounds.left(), dstBounds.top() , contentRect->left(), dstBounds.bottom()};
- bottom = {contentRect->right(), dstBounds.top() , dstBounds.right() , dstBounds.bottom()};
+ top = {dstBounds.left(), dstBounds.top(), srcBounds.left() , dstBounds.bottom()};
+ bottom = {srcBounds.right(), dstBounds.top(), dstBounds.right(), dstBounds.bottom()};
- mid = contentRect->makeInset(0, radius);
+ int midA = std::max(srcBounds.left() , dstBounds.left() );
+ int midB = std::min(srcBounds.right(), dstBounds.right());
+ mid = {midA, srcBounds.top() + radius, midB, srcBounds.bottom() - radius};
- left = {mid.left(), dstBounds.top(), mid.right(), mid.top() };
- right = {mid.left(), mid.bottom() , mid.right(), dstBounds.bottom()};
-
- *contentRect = {std::max(contentRect->left(), dstBounds.left()),
- dstBounds.top(),
- std::min(contentRect->right(), dstBounds.right()),
- dstBounds.bottom()};
+ if (mid.isEmpty()) {
+ left = {mid.left(), dstBounds.top(), mid.right(), dstBounds.bottom()};
+ } else {
+ left = {mid.left(), dstBounds.top(), mid.right(), mid.top() };
+ right = {mid.left(), mid.bottom() , mid.right(), dstBounds.bottom()};
+ }
}
- // Move all the rects from 'srcView' coord system to 'dstRenderTargetContext' coord system.
- mid .offset(-rtcToSrcOffset);
- top .offset(-rtcToSrcOffset);
- bottom.offset(-rtcToSrcOffset);
- left .offset(-rtcToSrcOffset);
- right .offset(-rtcToSrcOffset);
- contentRect->offset(-rtcToSrcOffset);
+ auto convolve = [&](SkIRect rect) {
+ // Transform rect into the render target's coord system.
+ rect.offset(-rtcToSrcOffset);
+ convolve_gaussian_1d(dstRenderTargetContext.get(), srcView, srcBounds, rtcToSrcOffset, rect,
+ srcAlphaType, direction, radius, sigma, mode);
+ };
+ auto clear = [&](SkIRect rect) {
+ // Transform rect into the render target's coord system.
+ rect.offset(-rtcToSrcOffset);
+ dstRenderTargetContext->priv().clearAtLeast(rect, SK_PMColor4fTRANSPARENT);
+ };
+
+ // Doing mid separately will cause two draws to occur (left and right batch together). At
+ // small sizes of mid it is worse to issue more draws than to just execute the slightly
+ // more complicated shader that implements the tile mode across mid. This threshold is
+ // very arbitrary right now. It is believed that a 21x44 mid on a Moto G4 is a significant
+ // regression compared to doing one draw but it has not been locally evaluated or tuned.
+ // The optimal cutoff is likely to vary by GPU.
+ if (!mid.isEmpty() && mid.width()*mid.height() < 256*256) {
+ left.join(mid);
+ left.join(right);
+ mid = SkIRect::MakeEmpty();
+ right = SkIRect::MakeEmpty();
+ // It's unknown whether for kDecal it'd be better to expand the draw rather than a draw and
+ // up to two clears.
+ if (mode == SkTileMode::kClamp) {
+ left.join(top);
+ left.join(bottom);
+ top = SkIRect::MakeEmpty();
+ bottom = SkIRect::MakeEmpty();
+ }
+ }
if (!top.isEmpty()) {
- dstRenderTargetContext->clear(&top, SK_PMColor4fTRANSPARENT,
- GrRenderTargetContext::CanClearFullscreen::kYes);
+ if (mode == SkTileMode::kDecal) {
+ clear(top);
+ } else {
+ convolve(top);
+ }
}
if (!bottom.isEmpty()) {
- dstRenderTargetContext->clear(&bottom, SK_PMColor4fTRANSPARENT,
- GrRenderTargetContext::CanClearFullscreen::kYes);
+ if (mode == SkTileMode::kDecal) {
+ clear(bottom);
+ } else {
+ convolve(bottom);
+ }
}
if (mid.isEmpty()) {
- convolve_gaussian_1d(dstRenderTargetContext.get(), std::move(srcView), rtcToSrcOffset,
- *contentRect, srcAlphaType, direction, radius, sigma, mode, bounds);
+ convolve(left);
} else {
- // Draw right and left margins with bounds; middle without.
- convolve_gaussian_1d(dstRenderTargetContext.get(), srcView, rtcToSrcOffset, left,
- srcAlphaType, direction, radius, sigma, mode, bounds);
- convolve_gaussian_1d(dstRenderTargetContext.get(), srcView, rtcToSrcOffset, right,
- srcAlphaType, direction, radius, sigma, mode, bounds);
- convolve_gaussian_1d(dstRenderTargetContext.get(), std::move(srcView), rtcToSrcOffset, mid,
- srcAlphaType, direction, radius, sigma, SkTileMode::kClamp, nullptr);
+ convolve(left);
+ convolve(right);
+ convolve(mid);
}
-
return dstRenderTargetContext;
}
-// Returns a high quality scaled-down version of src. This is used to create an intermediate,
-// shrunken version of the source image in the event that the requested blur sigma exceeds
-// MAX_BLUR_SIGMA.
-static GrSurfaceProxyView decimate(GrRecordingContext* context,
- GrSurfaceProxyView srcView,
- GrColorType srcColorType,
- SkAlphaType srcAlphaType,
- SkIPoint srcOffset,
- SkIRect* contentRect,
- int scaleFactorX,
- int scaleFactorY,
- SkTileMode mode,
- sk_sp<SkColorSpace> finalCS) {
- SkASSERT(SkIsPow2(scaleFactorX) && SkIsPow2(scaleFactorY));
- SkASSERT(scaleFactorX > 1 || scaleFactorY > 1);
-
- SkIRect srcRect = contentRect->makeOffset(srcOffset);
-
- scale_irect_roundout(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
- scale_irect(&srcRect, scaleFactorX, scaleFactorY);
-
- SkIRect dstRect(srcRect);
-
- std::unique_ptr<GrRenderTargetContext> dstRenderTargetContext;
-
- for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
- shrink_irect_by_2(&dstRect, i < scaleFactorX, i < scaleFactorY);
-
- dstRenderTargetContext = GrRenderTargetContext::Make(
- context, srcColorType, finalCS, SkBackingFit::kApprox,
- {dstRect.fRight, dstRect.fBottom}, 1, GrMipMapped::kNo,
- srcView.proxy()->isProtected(), srcView.origin());
- if (!dstRenderTargetContext) {
- return {};
- }
-
- GrPaint paint;
- std::unique_ptr<GrFragmentProcessor> fp;
- if (i == 1) {
- GrSamplerState::WrapMode wrapMode = SkTileModeToWrapMode(mode);
- const auto& caps = *context->priv().caps();
- GrSamplerState sampler(wrapMode, GrSamplerState::Filter::kBilerp);
- fp = GrTextureEffect::MakeSubset(std::move(srcView), srcAlphaType, SkMatrix::I(),
- sampler, SkRect::Make(*contentRect), caps);
- srcRect.offset(-srcOffset);
- } else {
- fp = GrTextureEffect::Make(std::move(srcView), srcAlphaType, SkMatrix::I(),
- GrSamplerState::Filter::kBilerp);
- }
- paint.addColorFragmentProcessor(std::move(fp));
- paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-
- dstRenderTargetContext->fillRectToRect(GrFixedClip::Disabled(), std::move(paint), GrAA::kNo,
- SkMatrix::I(), SkRect::Make(dstRect),
- SkRect::Make(srcRect));
-
- srcView = dstRenderTargetContext->readSurfaceView();
- if (!srcView.asTextureProxy()) {
- return {};
- }
- srcRect = dstRect;
- }
-
- *contentRect = dstRect;
-
- SkASSERT(dstRenderTargetContext);
- SkASSERT(srcView == dstRenderTargetContext->readSurfaceView());
-
- return srcView;
-}
-
// Expand the contents of 'srcRenderTargetContext' to fit in 'dstII'. At this point, we are
// expanding an intermediate image, so there's no need to account for a proxy offset from the
// original input.
static std::unique_ptr<GrRenderTargetContext> reexpand(GrRecordingContext* context,
std::unique_ptr<GrRenderTargetContext> src,
- const SkIRect& srcBounds,
- int scaleFactorX,
- int scaleFactorY,
+ const SkRect& srcBounds,
SkISize dstSize,
sk_sp<SkColorSpace> colorSpace,
SkBackingFit fit) {
- const SkIRect srcRect = SkIRect::MakeWH(src->width(), src->height());
-
GrSurfaceProxyView srcView = src->readSurfaceView();
if (!srcView.asTextureProxy()) {
return nullptr;
@@ -370,20 +265,14 @@ static std::unique_ptr<GrRenderTargetContext> reexpand(GrRecordingContext* conte
}
GrPaint paint;
- const auto& caps = *context->priv().caps();
auto fp = GrTextureEffect::MakeSubset(std::move(srcView), srcAlphaType, SkMatrix::I(),
- GrSamplerState::Filter::kBilerp, SkRect::Make(srcBounds),
- caps);
+ GrSamplerState::Filter::kBilerp, srcBounds, srcBounds,
+ *context->priv().caps());
paint.addColorFragmentProcessor(std::move(fp));
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
- GrFixedClip clip(SkIRect::MakeSize(dstSize));
-
- // TODO: using dstII as dstRect results in some image diffs - why?
- SkIRect dstRect(srcRect);
- scale_irect(&dstRect, scaleFactorX, scaleFactorY);
- dstRenderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
- SkRect::Make(dstRect), SkRect::Make(srcRect));
+ dstRenderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
+ SkRect::Make(dstSize), srcBounds);
return dstRenderTargetContext;
}
@@ -393,7 +282,7 @@ static std::unique_ptr<GrRenderTargetContext> two_pass_gaussian(GrRecordingConte
GrColorType srcColorType,
SkAlphaType srcAlphaType,
sk_sp<SkColorSpace> colorSpace,
- SkIRect* srcBounds,
+ SkIRect srcBounds,
SkIRect dstBounds,
float sigmaX,
float sigmaY,
@@ -401,17 +290,90 @@ static std::unique_ptr<GrRenderTargetContext> two_pass_gaussian(GrRecordingConte
int radiusY,
SkTileMode mode,
SkBackingFit fit) {
+ SkASSERT(sigmaX || sigmaY);
std::unique_ptr<GrRenderTargetContext> dstRenderTargetContext;
if (sigmaX > 0.0f) {
SkBackingFit xFit = sigmaY > 0 ? SkBackingFit::kApprox : fit;
+ // Expand the dstBounds vertically to produce necessary content for the y-pass. Then we will
+ // clip these in a tile-mode dependent way to ensure the tile-mode gets implemented
+ // correctly. However, if we're not going to do a y-pass then we must use the original
+ // dstBounds without clipping to produce the correct output size.
+ SkIRect xPassDstBounds = dstBounds;
+ if (sigmaY) {
+ xPassDstBounds.outset(0, radiusY);
+ if (mode == SkTileMode::kRepeat || mode == SkTileMode::kMirror) {
+ int srcH = srcBounds.height();
+ int srcTop = srcBounds.top();
+ if (mode == SkTileMode::kMirror) {
+ srcTop -= srcH;
+ srcH *= 2;
+ }
+
+ float floatH = srcH;
+ // First row above the dst rect where we should restart the tile mode.
+ int n = sk_float_floor2int_no_saturate((xPassDstBounds.top() - srcTop)/floatH);
+ int topClip = srcTop + n*srcH;
+
+ // First row above below the dst rect where we should restart the tile mode.
+ n = sk_float_ceil2int_no_saturate(
+ (xPassDstBounds.bottom() - srcBounds.bottom())/floatH);
+ int bottomClip = srcBounds.bottom() + n*srcH;
+
+ xPassDstBounds.fTop = std::max(xPassDstBounds.top(), topClip);
+ xPassDstBounds.fBottom = std::min(xPassDstBounds.bottom(), bottomClip);
+ } else {
+ if (xPassDstBounds.fBottom <= srcBounds.top()) {
+ if (mode == SkTileMode::kDecal) {
+ return nullptr;
+ }
+ xPassDstBounds.fTop = srcBounds.top();
+ xPassDstBounds.fBottom = xPassDstBounds.fTop + 1;
+ } else if (xPassDstBounds.fTop >= srcBounds.bottom()) {
+ if (mode == SkTileMode::kDecal) {
+ return nullptr;
+ }
+ xPassDstBounds.fBottom = srcBounds.bottom();
+ xPassDstBounds.fTop = xPassDstBounds.fBottom - 1;
+ } else {
+ xPassDstBounds.fTop = std::max(xPassDstBounds.fTop, srcBounds.top());
+ xPassDstBounds.fBottom = std::min(xPassDstBounds.fBottom, srcBounds.bottom());
+ }
+ int leftSrcEdge = srcBounds.fLeft - radiusX ;
+ int rightSrcEdge = srcBounds.fRight + radiusX;
+ if (mode == SkTileMode::kClamp) {
+ // In clamp the column just outside the src bounds has the same value as the
+ // column just inside, unlike decal.
+ leftSrcEdge += 1;
+ rightSrcEdge -= 1;
+ }
+ if (xPassDstBounds.fRight <= leftSrcEdge) {
+ if (mode == SkTileMode::kDecal) {
+ return nullptr;
+ }
+ xPassDstBounds.fLeft = xPassDstBounds.fRight - 1;
+ } else {
+ xPassDstBounds.fLeft = std::max(xPassDstBounds.fLeft, leftSrcEdge);
+ }
+ if (xPassDstBounds.fLeft >= rightSrcEdge) {
+ if (mode == SkTileMode::kDecal) {
+ return nullptr;
+ }
+ xPassDstBounds.fRight = xPassDstBounds.fLeft + 1;
+ } else {
+ xPassDstBounds.fRight = std::min(xPassDstBounds.fRight, rightSrcEdge);
+ }
+ }
+ }
dstRenderTargetContext = convolve_gaussian(
- context, std::move(srcView), srcColorType, srcAlphaType, srcBounds, dstBounds,
+ context, std::move(srcView), srcColorType, srcAlphaType, srcBounds, xPassDstBounds,
Direction::kX, radiusX, sigmaX, mode, colorSpace, xFit);
if (!dstRenderTargetContext) {
return nullptr;
}
srcView = dstRenderTargetContext->readSurfaceView();
- dstBounds = SkIRect::MakeSize(dstBounds.size());
+ SkIVector newDstBoundsOffset = dstBounds.topLeft() - xPassDstBounds.topLeft();
+ dstBounds = SkIRect::MakeSize(dstBounds.size()).makeOffset(newDstBoundsOffset);
+ srcBounds = SkIRect::MakeSize(xPassDstBounds.size());
}
if (sigmaY == 0.0f) {
@@ -424,17 +386,33 @@ static std::unique_ptr<GrRenderTargetContext> two_pass_gaussian(GrRecordingConte
namespace SkGpuBlurUtils {
+std::unique_ptr<GrRenderTargetContext> LegacyGaussianBlur(GrRecordingContext* context,
+ GrSurfaceProxyView srcView,
+ GrColorType srcColorType,
+ SkAlphaType srcAlphaType,
+ sk_sp<SkColorSpace> colorSpace,
+ const SkIRect& dstBounds,
+ const SkIRect& srcBounds,
+ float sigmaX,
+ float sigmaY,
+ SkTileMode mode,
+ SkBackingFit fit);
+
std::unique_ptr<GrRenderTargetContext> GaussianBlur(GrRecordingContext* context,
GrSurfaceProxyView srcView,
GrColorType srcColorType,
SkAlphaType srcAlphaType,
sk_sp<SkColorSpace> colorSpace,
- const SkIRect& dstBounds,
- const SkIRect& srcBounds,
+ SkIRect dstBounds,
+ SkIRect srcBounds,
float sigmaX,
float sigmaY,
SkTileMode mode,
SkBackingFit fit) {
+#ifdef SK_USE_LEGACY_GPU_BLUR
+ return LegacyGaussianBlur(context, srcView, srcColorType, srcAlphaType, std::move(colorSpace),
+ dstBounds, srcBounds, sigmaX, sigmaY, mode, fit);
+#endif
SkASSERT(context);
TRACE_EVENT2("skia.gpu", "GaussianBlur", "sigmaX", sigmaX, "sigmaY", sigmaY);
@@ -442,16 +420,72 @@ std::unique_ptr<GrRenderTargetContext> GaussianBlur(GrRecordingContext* context,
return nullptr;
}
- int scaleFactorX, radiusX;
- int scaleFactorY, radiusY;
- int maxTextureSize = context->priv().caps()->maxTextureSize();
- sigmaX = adjust_sigma(sigmaX, maxTextureSize, &scaleFactorX, &radiusX);
- sigmaY = adjust_sigma(sigmaY, maxTextureSize, &scaleFactorY, &radiusY);
- SkASSERT(sigmaX || sigmaY);
+ int maxRenderTargetSize = context->priv().caps()->maxRenderTargetSize();
+ if (dstBounds.width() > maxRenderTargetSize || dstBounds.height() > maxRenderTargetSize) {
+ return nullptr;
+ }
- auto localSrcBounds = srcBounds;
+ // Attempt to reduce the srcBounds in order to detect that we can set the sigmas to zero or
+ // to reduce the amount of work to rescale the source if sigmas are large. TODO: Could consider
+ // how to minimize the required source bounds for repeat/mirror modes.
+ if (mode == SkTileMode::kClamp || mode == SkTileMode::kDecal) {
+ int radiusX = sigma_radius(sigmaX);
+ int radiusY = sigma_radius(sigmaY);
+ SkIRect reach = dstBounds.makeOutset(radiusX, radiusY);
+ SkIRect intersection;
+ if (!intersection.intersect(reach, srcBounds)) {
+ if (mode == SkTileMode::kDecal) {
+ return nullptr;
+ } else {
+ if (reach.fLeft >= srcBounds.fRight) {
+ srcBounds.fLeft = srcBounds.fRight - 1;
+ } else if (reach.fRight <= srcBounds.fLeft) {
+ srcBounds.fRight = srcBounds.fLeft + 1;
+ }
+ if (reach.fTop >= srcBounds.fBottom) {
+ srcBounds.fTop = srcBounds.fBottom - 1;
+ } else if (reach.fBottom <= srcBounds.fTop) {
+ srcBounds.fBottom = srcBounds.fTop + 1;
+ }
+ }
+ } else {
+ srcBounds = intersection;
+ }
+ }
- if (scaleFactorX == 1 && scaleFactorY == 1) {
+ if (mode != SkTileMode::kDecal) {
+ // All non-decal tile modes are equivalent for one pixel width/height src and amount to a
+ // single color value repeated at each column/row. Applying the normalized kernel to that
+ // column/row yields that same color. So no blurring is necessary.
+ if (srcBounds.width() == 1) {
+ sigmaX = 0.f;
+ }
+ if (srcBounds.height() == 1) {
+ sigmaY = 0.f;
+ }
+ }
+
+ // If we determined that there is no blurring necessary in either direction then just do a
+ // a draw that applies the tile mode.
+ if (!sigmaX && !sigmaY) {
+ auto result = GrRenderTargetContext::Make(context, srcColorType, std::move(colorSpace), fit,
+ dstBounds.size());
+ GrSamplerState sampler(SkTileModeToWrapMode(mode), GrSamplerState::Filter::kNearest);
+ auto fp = GrTextureEffect::MakeSubset(std::move(srcView), srcAlphaType, SkMatrix::I(),
+ sampler, SkRect::Make(srcBounds),
+ SkRect::Make(dstBounds), *context->priv().caps());
+ GrPaint paint;
+ paint.addColorFragmentProcessor(std::move(fp));
+ result->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
+ SkRect::Make(dstBounds.size()));
+ return result;
+ }
+
+ if (sigmaX <= MAX_BLUR_SIGMA && sigmaY <= MAX_BLUR_SIGMA) {
+ int radiusX = sigma_radius(sigmaX);
+ int radiusY = sigma_radius(sigmaY);
+ SkASSERT(radiusX <= GrGaussianConvolutionFragmentProcessor::kMaxKernelRadius);
+ SkASSERT(radiusY <= GrGaussianConvolutionFragmentProcessor::kMaxKernelRadius);
// For really small blurs (certainly no wider than 5x5 on desktop GPUs) it is faster to just
// launch a single non separable kernel vs two launches.
const int kernelSize = (2 * radiusX + 1) * (2 * radiusY + 1);
@@ -459,32 +493,64 @@ std::unique_ptr<GrRenderTargetContext> GaussianBlur(GrRecordingContext* context,
// Apply the proxy offset to src bounds and offset directly
return convolve_gaussian_2d(context, std::move(srcView), srcColorType, srcBounds,
dstBounds, radiusX, radiusY, sigmaX, sigmaY, mode,
- colorSpace, fit);
+ std::move(colorSpace), fit);
}
return two_pass_gaussian(context, std::move(srcView), srcColorType, srcAlphaType,
- std::move(colorSpace), &localSrcBounds, dstBounds, sigmaX, sigmaY,
+ std::move(colorSpace), srcBounds, dstBounds, sigmaX, sigmaY,
radiusX, radiusY, mode, fit);
}
- auto srcOffset = -dstBounds.topLeft();
- srcView = decimate(context, std::move(srcView), srcColorType, srcAlphaType, srcOffset,
- &localSrcBounds, scaleFactorX, scaleFactorY, mode, colorSpace);
- if (!srcView.proxy()) {
+ float scaleX = sigmaX > MAX_BLUR_SIGMA ? MAX_BLUR_SIGMA/sigmaX : 1.f;
+ float scaleY = sigmaY > MAX_BLUR_SIGMA ? MAX_BLUR_SIGMA/sigmaY : 1.f;
+ // We round down here so that when we recalculate sigmas we know they will be below
+ // MAX_BLUR_SIGMA.
+ SkISize rescaledSize = {sk_float_floor2int(srcBounds.width() *scaleX),
+ sk_float_floor2int(srcBounds.height()*scaleY)};
+ if (rescaledSize.isEmpty()) {
+ // TODO: Handle this degenerate case.
+ return nullptr;
+ }
+ // Compute the sigmas using the actual scale factors used once we integerized the rescaledSize.
+ scaleX = static_cast<float>(rescaledSize.width()) /srcBounds.width();
+ scaleY = static_cast<float>(rescaledSize.height())/srcBounds.height();
+ sigmaX *= scaleX;
+ sigmaY *= scaleY;
+
+ auto srcCtx = GrSurfaceContext::Make(context, srcView, srcColorType, srcAlphaType, colorSpace);
+ SkASSERT(srcCtx);
+ GrImageInfo rescaledII(srcColorType, srcAlphaType, colorSpace, rescaledSize);
+ srcCtx = srcCtx->rescale(rescaledII, srcCtx->origin(), srcBounds, SkSurface::RescaleGamma::kSrc,
+ kLow_SkFilterQuality);
+ if (!srcCtx) {
return nullptr;
}
- SkASSERT(srcView.asTextureProxy());
- auto scaledDstBounds = SkIRect::MakeWH(sk_float_ceil(dstBounds.width() / (float)scaleFactorX),
- sk_float_ceil(dstBounds.height() / (float)scaleFactorY));
- auto rtc = two_pass_gaussian(context, std::move(srcView), srcColorType, srcAlphaType,
- colorSpace, &localSrcBounds, scaledDstBounds, sigmaX, sigmaY,
- radiusX, radiusY, mode, SkBackingFit::kApprox);
+ srcView = srcCtx->readSurfaceView();
+ // Drop the context so we don't hold the proxy longer than necessary.
+ srcCtx.reset();
+
+ // Compute the dst bounds in the scaled down space. First move the origin to be at the top
+ // left since we trimmed off everything above and to the left of the original src bounds during
+ // the rescale.
+ SkRect scaledDstBounds = SkRect::Make(dstBounds.makeOffset(-srcBounds.topLeft()));
+ scaledDstBounds.fLeft *= scaleX;
+ scaledDstBounds.fTop *= scaleY;
+ scaledDstBounds.fRight *= scaleX;
+ scaledDstBounds.fBottom *= scaleY;
+ // Turn the scaled down dst bounds into an integer pixel rect.
+ auto scaledDstBoundsI = scaledDstBounds.roundOut();
+
+ auto rtc = GaussianBlur(context, std::move(srcView), srcColorType, srcAlphaType, colorSpace,
+ scaledDstBoundsI, SkIRect::MakeSize(rescaledSize), sigmaX, sigmaY, mode,
+ fit);
if (!rtc) {
return nullptr;
}
- return reexpand(context, std::move(rtc), localSrcBounds, scaleFactorX, scaleFactorY,
- dstBounds.size(), std::move(colorSpace), fit);
+ // We rounded out the integer scaled dst bounds. Select the fractional dst bounds from the
+ // integer dimension blurred result when we scale back up.
+ scaledDstBounds.offset(-scaledDstBoundsI.left(), -scaledDstBoundsI.top());
+ return reexpand(context, std::move(rtc), scaledDstBounds, dstBounds.size(),
+ std::move(colorSpace), fit);
}
-
}
#endif
diff --git a/chromium/third_party/skia/src/core/SkGpuBlurUtils.h b/chromium/third_party/skia/src/core/SkGpuBlurUtils.h
index 3e78c4ceeca..63d8fedea19 100644
--- a/chromium/third_party/skia/src/core/SkGpuBlurUtils.h
+++ b/chromium/third_party/skia/src/core/SkGpuBlurUtils.h
@@ -18,36 +18,33 @@ struct SkRect;
namespace SkGpuBlurUtils {
/**
- * Applies a 2D Gaussian blur to a given texture. The blurred result is returned
- * as a renderTargetContext in case the caller wishes to draw into the result.
- *
- * The 'proxyOffset' is kept separate form 'srcBounds' because they exist in different
- * coordinate spaces. 'srcBounds' exists in the content space of the special image, and
- * 'proxyOffset' maps from the content space to the proxy's space.
- *
- * Note: one of sigmaX and sigmaY should be non-zero!
- * @param context The GPU context
- * @param srcView The source to be blurred.
- * @param srcColorType The colorType of srcProxy
- * @param srcAlphaType The alphaType of srcProxy
- * @param colorSpace Color space of the source (used for the renderTargetContext result,
- * too).
- * @param dstBounds The destination bounds, relative to the source texture.
- * @param srcBounds The source bounds, relative to the source texture's offset. No pixels
- * will be sampled outside of this rectangle.
- * @param sigmaX The blur's standard deviation in X.
- * @param sigmaY The blur's standard deviation in Y.
- * @param tileMode The mode to handle samples outside bounds.
- * @param fit backing fit for the returned render target context
- * @return The renderTargetContext containing the blurred result.
- */
+ * Applies a 2D Gaussian blur to a given texture. The blurred result is returned
+ * as a renderTargetContext in case the caller wishes to draw into the result.
+ * The GrSurfaceOrigin of the result will watch the GrSurfaceOrigin of srcView. The output
+ * color type, color space, and alpha type will be the same as the src.
+ *
+ * Note: one of sigmaX and sigmaY should be non-zero!
+ * @param context The GPU context
+ * @param srcView The source to be blurred.
+ * @param srcColorType The colorType of srcProxy
+ * @param srcAlphaType The alphaType of srcProxy
+ * @param colorSpace Color space of the source.
+ * @param dstBounds The destination bounds, relative to the source texture.
+ * @param srcBounds The source bounds, relative to the source texture's offset. No pixels
+ * will be sampled outside of this rectangle.
+ * @param sigmaX The blur's standard deviation in X.
+ * @param sigmaY The blur's standard deviation in Y.
+ * @param tileMode The mode to handle samples outside bounds.
+ * @param fit backing fit for the returned render target context
+ * @return The renderTargetContext containing the blurred result.
+ */
std::unique_ptr<GrRenderTargetContext> GaussianBlur(GrRecordingContext* context,
GrSurfaceProxyView srcView,
GrColorType srcColorType,
SkAlphaType srcAlphaType,
sk_sp<SkColorSpace> colorSpace,
- const SkIRect& dstBounds,
- const SkIRect& srcBounds,
+ SkIRect dstBounds,
+ SkIRect srcBounds,
float sigmaX,
float sigmaY,
SkTileMode mode,
diff --git a/chromium/third_party/skia/src/core/SkImageFilter.cpp b/chromium/third_party/skia/src/core/SkImageFilter.cpp
index 80f4d0b62d6..f9a85ffa4db 100644
--- a/chromium/third_party/skia/src/core/SkImageFilter.cpp
+++ b/chromium/third_party/skia/src/core/SkImageFilter.cpp
@@ -26,7 +26,6 @@
#include "include/private/GrRecordingContext.h"
#include "src/gpu/GrColorSpaceXform.h"
#include "src/gpu/GrContextPriv.h"
-#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrTextureProxy.h"
@@ -114,7 +113,7 @@ bool SkImageFilter::asAColorFilter(SkColorFilter** filterPtr) const {
if (!this->isColorFilterNode(filterPtr)) {
return false;
}
- if (nullptr != this->getInput(0) || (*filterPtr)->affectsTransparentBlack()) {
+ if (nullptr != this->getInput(0) || as_CFB(*filterPtr)->affectsTransparentBlack()) {
(*filterPtr)->unref();
return false;
}
@@ -231,14 +230,9 @@ skif::FilterResult<For::kOutput> SkImageFilter_Base::filterImage(const skif::Con
result = this->onFilterImage(context);
-#if SK_SUPPORT_GPU
- if (context.gpuBacked() && result.image() && !result.image()->isTextureBacked()) {
- // Keep the result on the GPU - this is still required for some
- // image filters that don't support GPU in all cases
- auto asTexture = result.image()->makeTextureImage(context.getContext());
- result = skif::FilterResult<For::kOutput>(std::move(asTexture), result.layerOrigin());
+ if (context.gpuBacked()) {
+ SkASSERT(!result.image() || result.image()->isTextureBacked());
}
-#endif
if (context.cache()) {
context.cache()->set(key, this, result);
@@ -586,9 +580,8 @@ sk_sp<SkSpecialImage> SkImageFilter_Base::DrawWithFP(GrRecordingContext* context
SkIRect dstIRect = SkIRect::MakeWH(bounds.width(), bounds.height());
SkRect srcRect = SkRect::Make(bounds);
SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
- GrFixedClip clip(dstIRect);
- renderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
- srcRect);
+ renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
+ dstRect, srcRect);
return SkSpecialImage::MakeDeferredFromGpu(
context, dstIRect, kNeedNewImageUniqueID_SpecialImage,
diff --git a/chromium/third_party/skia/src/core/SkImageFilterTypes.cpp b/chromium/third_party/skia/src/core/SkImageFilterTypes.cpp
index f2f6667967c..ab967239e58 100644
--- a/chromium/third_party/skia/src/core/SkImageFilterTypes.cpp
+++ b/chromium/third_party/skia/src/core/SkImageFilterTypes.cpp
@@ -37,7 +37,7 @@ Mapping Mapping::Make(const SkMatrix& ctm, const SkImageFilter* filter) {
// TODO (michaelludwig) - Should maybe strip out any fractional part of the translation in
// 'ctm' so that can be incorporated during regular drawing, instead of by resampling the
// filtered image.
- layer = SkMatrix::MakeScale(scale.fWidth, scale.fHeight);
+ layer = SkMatrix::Scale(scale.fWidth, scale.fHeight);
} else {
// Perspective
// TODO (michaelludwig) - Should investigate choosing a scale factor for the layer matrix
diff --git a/chromium/third_party/skia/src/core/SkImageInfo.cpp b/chromium/third_party/skia/src/core/SkImageInfo.cpp
index 11789d10be3..81994fb6ef4 100644
--- a/chromium/third_party/skia/src/core/SkImageInfo.cpp
+++ b/chromium/third_party/skia/src/core/SkImageInfo.cpp
@@ -90,7 +90,7 @@ bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
if (kUnpremul_SkAlphaType == alphaType) {
alphaType = kPremul_SkAlphaType;
}
- // fall-through
+ [[fallthrough]];
case kARGB_4444_SkColorType:
case kRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType:
diff --git a/chromium/third_party/skia/src/core/SkLegacyGpuBlurUtils.cpp b/chromium/third_party/skia/src/core/SkLegacyGpuBlurUtils.cpp
new file mode 100644
index 00000000000..461da44cf28
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkLegacyGpuBlurUtils.cpp
@@ -0,0 +1,485 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/core/SkGpuBlurUtils.h"
+
+#include "include/core/SkRect.h"
+
+#if SK_SUPPORT_GPU
+#include "include/private/GrRecordingContext.h"
+#include "src/gpu/GrCaps.h"
+#include "src/gpu/GrRecordingContextPriv.h"
+#include "src/gpu/GrRenderTargetContext.h"
+#include "src/gpu/GrRenderTargetContextPriv.h"
+#include "src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h"
+#include "src/gpu/effects/GrMatrixConvolutionEffect.h"
+
+#include "src/gpu/SkGr.h"
+
+#define MAX_BLUR_SIGMA 4.0f
+
+using Direction = GrGaussianConvolutionFragmentProcessor::Direction;
+
+static void scale_irect_roundout(SkIRect* rect, float xScale, float yScale) {
+ rect->fLeft = SkScalarFloorToInt(rect->fLeft * xScale);
+ rect->fTop = SkScalarFloorToInt(rect->fTop * yScale);
+ rect->fRight = SkScalarCeilToInt(rect->fRight * xScale);
+ rect->fBottom = SkScalarCeilToInt(rect->fBottom * yScale);
+}
+
+static void scale_irect(SkIRect* rect, int xScale, int yScale) {
+ rect->fLeft *= xScale;
+ rect->fTop *= yScale;
+ rect->fRight *= xScale;
+ rect->fBottom *= yScale;
+}
+
+#ifdef SK_DEBUG
+static inline int is_even(int x) { return !(x & 1); }
+#endif
+
+static void shrink_irect_by_2(SkIRect* rect, bool xAxis, bool yAxis) {
+ if (xAxis) {
+ SkASSERT(is_even(rect->fLeft) && is_even(rect->fRight));
+ rect->fLeft /= 2;
+ rect->fRight /= 2;
+ }
+ if (yAxis) {
+ SkASSERT(is_even(rect->fTop) && is_even(rect->fBottom));
+ rect->fTop /= 2;
+ rect->fBottom /= 2;
+ }
+}
+
+static float adjust_sigma(float sigma, int maxTextureSize, int *scaleFactor, int *radius) {
+ *scaleFactor = 1;
+ while (sigma > MAX_BLUR_SIGMA) {
+ *scaleFactor *= 2;
+ sigma *= 0.5f;
+ if (*scaleFactor > maxTextureSize) {
+ *scaleFactor = maxTextureSize;
+ sigma = MAX_BLUR_SIGMA;
+ }
+ }
+ *radius = static_cast<int>(ceilf(sigma * 3.0f));
+ SkASSERT(*radius <= GrGaussianConvolutionFragmentProcessor::kMaxKernelRadius);
+ return sigma;
+}
+
+/**
+ * Draws 'rtcRect' into 'renderTargetContext' evaluating a 1D Gaussian over 'srcView'. The src rect
+ * is 'rtcRect' offset by 'rtcToSrcOffset'. 'mode' and 'bounds' are applied to the src coords.
+ */
+static void convolve_gaussian_1d(GrRenderTargetContext* renderTargetContext,
+ GrSurfaceProxyView srcView,
+ SkIVector rtcToSrcOffset,
+ const SkIRect& rtcRect,
+ SkAlphaType srcAlphaType,
+ Direction direction,
+ int radius,
+ float sigma,
+ SkTileMode mode,
+ int bounds[2]) {
+ GrPaint paint;
+ auto wm = SkTileModeToWrapMode(mode);
+ auto subset = SkIRect::MakeSize(srcView.dimensions());
+ if (bounds) {
+ switch (direction) {
+ case Direction::kX: subset.fLeft = bounds[0]; subset.fRight = bounds[1]; break;
+ case Direction::kY: subset.fTop = bounds[0]; subset.fBottom = bounds[1]; break;
+ }
+ }
+ std::unique_ptr<GrFragmentProcessor> conv(GrGaussianConvolutionFragmentProcessor::Make(
+ std::move(srcView), srcAlphaType, direction, radius, sigma, wm, subset, nullptr,
+ *renderTargetContext->caps()));
+ paint.addColorFragmentProcessor(std::move(conv));
+ paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
+ auto srcRect = SkRect::Make(rtcRect.makeOffset(rtcToSrcOffset));
+ renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
+ SkRect::Make(rtcRect), srcRect);
+}
+
+static std::unique_ptr<GrRenderTargetContext> convolve_gaussian_2d(GrRecordingContext* context,
+ GrSurfaceProxyView srcView,
+ GrColorType srcColorType,
+ const SkIRect& srcBounds,
+ const SkIRect& dstBounds,
+ int radiusX,
+ int radiusY,
+ SkScalar sigmaX,
+ SkScalar sigmaY,
+ SkTileMode mode,
+ sk_sp<SkColorSpace> finalCS,
+ SkBackingFit dstFit) {
+ auto renderTargetContext = GrRenderTargetContext::Make(
+ context, srcColorType, std::move(finalCS), dstFit, dstBounds.size(), 1,
+ GrMipMapped::kNo, srcView.proxy()->isProtected(), srcView.origin());
+ if (!renderTargetContext) {
+ return nullptr;
+ }
+
+ SkISize size = SkISize::Make(2 * radiusX + 1, 2 * radiusY + 1);
+ SkIPoint kernelOffset = SkIPoint::Make(radiusX, radiusY);
+ GrPaint paint;
+ auto wm = SkTileModeToWrapMode(mode);
+ auto conv = GrMatrixConvolutionEffect::MakeGaussian(context, std::move(srcView), srcBounds,
+ size, 1.0, 0.0, kernelOffset, wm, true,
+ sigmaX, sigmaY,
+ *renderTargetContext->caps());
+ paint.addColorFragmentProcessor(std::move(conv));
+ paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
+
+ // 'dstBounds' is actually in 'srcView' proxy space. It represents the blurred area from src
+ // space that we want to capture in the new RTC at {0, 0}. Hence, we use its size as the rect to
+ // draw and it directly as the local rect.
+ renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
+ SkRect::Make(dstBounds.size()), SkRect::Make(dstBounds));
+
+ return renderTargetContext;
+}
+
+static std::unique_ptr<GrRenderTargetContext> convolve_gaussian(GrRecordingContext* context,
+ GrSurfaceProxyView srcView,
+ GrColorType srcColorType,
+ SkAlphaType srcAlphaType,
+ SkIRect* contentRect,
+ SkIRect dstBounds,
+ Direction direction,
+ int radius,
+ float sigma,
+ SkTileMode mode,
+ sk_sp<SkColorSpace> finalCS,
+ SkBackingFit fit) {
+ // Logically we're creating an infinite blur of 'contentRect' of 'srcView' with 'mode' tiling
+ // and then capturing the 'dstBounds' portion in a new RTC where the top left of 'dstBounds' is
+ // at {0, 0} in the new RTC.
+ auto dstRenderTargetContext = GrRenderTargetContext::Make(
+ context, srcColorType, std::move(finalCS), fit, dstBounds.size(), 1, GrMipMapped::kNo,
+ srcView.proxy()->isProtected(), srcView.origin());
+ if (!dstRenderTargetContext) {
+ return nullptr;
+ }
+
+ // This represents the translation from 'dstRenderTargetContext' coords to 'srcView' coords.
+ auto rtcToSrcOffset = dstBounds.topLeft();
+
+ if (SkTileMode::kClamp == mode &&
+ contentRect->contains(SkIRect::MakeSize(srcView.proxy()->backingStoreDimensions()))) {
+ auto dstRect = SkIRect::MakeSize(dstBounds.size());
+ convolve_gaussian_1d(dstRenderTargetContext.get(), std::move(srcView), rtcToSrcOffset,
+ dstRect, srcAlphaType, direction, radius, sigma, SkTileMode::kClamp,
+ nullptr);
+ *contentRect = dstRect;
+ return dstRenderTargetContext;
+ }
+
+ // 'left' and 'right' are the sub rects of 'contentTect' where 'mode' must be enforced.
+ // 'mid' is the area where we can ignore the mode because the kernel does not reach to the
+ // edge of 'contentRect'. The names are derived from the Direction::kX case.
+ // TODO: When mode is kMirror or kRepeat it makes more sense to think of 'contentRect'
+ // as a tile and figure out the collection of mid/left/right rects that cover 'dstBounds'.
+ // Also if 'mid' is small and 'left' or 'right' is non-empty we should probably issue one
+ // draw that implements the mode in the shader rather than break it up in this fashion.
+ SkIRect mid, left, right;
+ // 'top' and 'bottom' are areas of 'dstBounds' that are entirely above/below
+ // 'contentRect'. These are areas that we can simply clear in the dst. If 'contentRect'
+ // straddles the top edge of 'dstBounds' then 'top' will be inverted and we will skip
+ // the clear. Similar for 'bottom'. The positional/directional labels above refer to the
+ // Direction::kX case and one should think of these as 'left' and 'right' for Direction::kY.
+ SkIRect top, bottom;
+ int bounds[2];
+ if (Direction::kX == direction) {
+ bounds[0] = contentRect->left();
+ bounds[1] = contentRect->right();
+
+ top = {dstBounds.left(), dstBounds.top() , dstBounds.right(), contentRect->top()};
+ bottom = {dstBounds.left(), contentRect->bottom(), dstBounds.right(), dstBounds.bottom()};
+
+ // Inset for sub-rect of 'contentRect' where the x-dir kernel doesn't reach the edges.
+ // TODO: Consider clipping mid/left/right to dstBounds to increase likelihood of doing
+ // fewer draws below.
+ mid = contentRect->makeInset(radius, 0);
+
+ left = {dstBounds.left(), mid.top(), mid.left() , mid.bottom()};
+ right = {mid.right(), mid.top(), dstBounds.right(), mid.bottom()};
+
+ // The new 'contentRect' when we're done will be the area between the clears in the dst.
+ *contentRect = {dstBounds.left(),
+ std::max(contentRect->top(), dstBounds.top()),
+ dstBounds.right(),
+ std::min(dstBounds.bottom(), contentRect->bottom())};
+ } else {
+ // This is the same as the x direction code if you turn your head 90 degrees CCW. Swap x and
+ // y and swap top/bottom with left/right.
+ bounds[0] = contentRect->top();
+ bounds[1] = contentRect->bottom();
+
+ top = {dstBounds.left(), dstBounds.top() , contentRect->left(), dstBounds.bottom()};
+ bottom = {contentRect->right(), dstBounds.top() , dstBounds.right() , dstBounds.bottom()};
+
+ mid = contentRect->makeInset(0, radius);
+
+ left = {mid.left(), dstBounds.top(), mid.right(), mid.top() };
+ right = {mid.left(), mid.bottom() , mid.right(), dstBounds.bottom()};
+
+ *contentRect = {std::max(contentRect->left(), dstBounds.left()),
+ dstBounds.top(),
+ std::min(contentRect->right(), dstBounds.right()),
+ dstBounds.bottom()};
+ }
+ // Move all the rects from 'srcView' coord system to 'dstRenderTargetContext' coord system.
+ mid .offset(-rtcToSrcOffset);
+ top .offset(-rtcToSrcOffset);
+ bottom.offset(-rtcToSrcOffset);
+ left .offset(-rtcToSrcOffset);
+ right .offset(-rtcToSrcOffset);
+
+ contentRect->offset(-rtcToSrcOffset);
+
+ if (!top.isEmpty()) {
+ dstRenderTargetContext->priv().clearAtLeast(top, SK_PMColor4fTRANSPARENT);
+ }
+
+ if (!bottom.isEmpty()) {
+ dstRenderTargetContext->priv().clearAtLeast(bottom, SK_PMColor4fTRANSPARENT);
+ }
+
+ if (mid.isEmpty()) {
+ convolve_gaussian_1d(dstRenderTargetContext.get(), std::move(srcView), rtcToSrcOffset,
+ *contentRect, srcAlphaType, direction, radius, sigma, mode, bounds);
+ } else {
+ // Draw right and left margins with bounds; middle without.
+ convolve_gaussian_1d(dstRenderTargetContext.get(), srcView, rtcToSrcOffset, left,
+ srcAlphaType, direction, radius, sigma, mode, bounds);
+ convolve_gaussian_1d(dstRenderTargetContext.get(), srcView, rtcToSrcOffset, right,
+ srcAlphaType, direction, radius, sigma, mode, bounds);
+ convolve_gaussian_1d(dstRenderTargetContext.get(), std::move(srcView), rtcToSrcOffset, mid,
+ srcAlphaType, direction, radius, sigma, SkTileMode::kClamp, nullptr);
+ }
+
+ return dstRenderTargetContext;
+}
+
+// Returns a high quality scaled-down version of src. This is used to create an intermediate,
+// shrunken version of the source image in the event that the requested blur sigma exceeds
+// MAX_BLUR_SIGMA.
+static GrSurfaceProxyView decimate(GrRecordingContext* context,
+ GrSurfaceProxyView srcView,
+ GrColorType srcColorType,
+ SkAlphaType srcAlphaType,
+ SkIPoint srcOffset,
+ SkIRect* contentRect,
+ int scaleFactorX,
+ int scaleFactorY,
+ SkTileMode mode,
+ sk_sp<SkColorSpace> finalCS) {
+ SkASSERT(SkIsPow2(scaleFactorX) && SkIsPow2(scaleFactorY));
+ SkASSERT(scaleFactorX > 1 || scaleFactorY > 1);
+
+ SkIRect srcRect = contentRect->makeOffset(srcOffset);
+
+ scale_irect_roundout(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
+ scale_irect(&srcRect, scaleFactorX, scaleFactorY);
+
+ SkIRect dstRect(srcRect);
+
+ std::unique_ptr<GrRenderTargetContext> dstRenderTargetContext;
+
+ for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
+ shrink_irect_by_2(&dstRect, i < scaleFactorX, i < scaleFactorY);
+
+ dstRenderTargetContext = GrRenderTargetContext::Make(
+ context, srcColorType, finalCS, SkBackingFit::kApprox,
+ {dstRect.fRight, dstRect.fBottom}, 1, GrMipMapped::kNo,
+ srcView.proxy()->isProtected(), srcView.origin());
+ if (!dstRenderTargetContext) {
+ return {};
+ }
+
+ GrPaint paint;
+ std::unique_ptr<GrFragmentProcessor> fp;
+ if (i == 1) {
+ GrSamplerState::WrapMode wrapMode = SkTileModeToWrapMode(mode);
+ const auto& caps = *context->priv().caps();
+ GrSamplerState sampler(wrapMode, GrSamplerState::Filter::kBilerp);
+ fp = GrTextureEffect::MakeSubset(std::move(srcView), srcAlphaType, SkMatrix::I(),
+ sampler, SkRect::Make(*contentRect), caps);
+ srcRect.offset(-srcOffset);
+ } else {
+ fp = GrTextureEffect::Make(std::move(srcView), srcAlphaType, SkMatrix::I(),
+ GrSamplerState::Filter::kBilerp);
+ }
+ paint.addColorFragmentProcessor(std::move(fp));
+ paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
+
+ dstRenderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo,
+ SkMatrix::I(), SkRect::Make(dstRect),
+ SkRect::Make(srcRect));
+
+ srcView = dstRenderTargetContext->readSurfaceView();
+ if (!srcView.asTextureProxy()) {
+ return {};
+ }
+ srcRect = dstRect;
+ }
+
+ *contentRect = dstRect;
+
+ SkASSERT(dstRenderTargetContext);
+ SkASSERT(srcView == dstRenderTargetContext->readSurfaceView());
+
+ return srcView;
+}
+
+// Expand the contents of 'srcRenderTargetContext' to fit in 'dstII'. At this point, we are
+// expanding an intermediate image, so there's no need to account for a proxy offset from the
+// original input.
+static std::unique_ptr<GrRenderTargetContext> reexpand(GrRecordingContext* context,
+ std::unique_ptr<GrRenderTargetContext> src,
+ const SkIRect& srcBounds,
+ int scaleFactorX,
+ int scaleFactorY,
+ SkISize dstSize,
+ sk_sp<SkColorSpace> colorSpace,
+ SkBackingFit fit) {
+ const SkIRect srcRect = SkIRect::MakeWH(src->width(), src->height());
+
+ GrSurfaceProxyView srcView = src->readSurfaceView();
+ if (!srcView.asTextureProxy()) {
+ return nullptr;
+ }
+
+ GrColorType srcColorType = src->colorInfo().colorType();
+ SkAlphaType srcAlphaType = src->colorInfo().alphaType();
+
+ src.reset(); // no longer needed
+
+ auto dstRenderTargetContext = GrRenderTargetContext::Make(
+ context, srcColorType, std::move(colorSpace), fit, dstSize, 1, GrMipMapped::kNo,
+ srcView.proxy()->isProtected(), srcView.origin());
+ if (!dstRenderTargetContext) {
+ return nullptr;
+ }
+
+ GrPaint paint;
+ const auto& caps = *context->priv().caps();
+ auto fp = GrTextureEffect::MakeSubset(std::move(srcView), srcAlphaType, SkMatrix::I(),
+ GrSamplerState::Filter::kBilerp, SkRect::Make(srcBounds),
+ caps);
+ paint.addColorFragmentProcessor(std::move(fp));
+ paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
+
+ // TODO: using dstII as dstRect results in some image diffs - why?
+ SkIRect dstRect(srcRect);
+ scale_irect(&dstRect, scaleFactorX, scaleFactorY);
+
+ dstRenderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
+ SkRect::Make(dstRect), SkRect::Make(srcRect));
+
+ return dstRenderTargetContext;
+}
+
+static std::unique_ptr<GrRenderTargetContext> two_pass_gaussian(GrRecordingContext* context,
+ GrSurfaceProxyView srcView,
+ GrColorType srcColorType,
+ SkAlphaType srcAlphaType,
+ sk_sp<SkColorSpace> colorSpace,
+ SkIRect* srcBounds,
+ SkIRect dstBounds,
+ float sigmaX,
+ float sigmaY,
+ int radiusX,
+ int radiusY,
+ SkTileMode mode,
+ SkBackingFit fit) {
+ std::unique_ptr<GrRenderTargetContext> dstRenderTargetContext;
+ if (sigmaX > 0.0f) {
+ SkBackingFit xFit = sigmaY > 0 ? SkBackingFit::kApprox : fit;
+ dstRenderTargetContext = convolve_gaussian(
+ context, std::move(srcView), srcColorType, srcAlphaType, srcBounds, dstBounds,
+ Direction::kX, radiusX, sigmaX, mode, colorSpace, xFit);
+ if (!dstRenderTargetContext) {
+ return nullptr;
+ }
+ srcView = dstRenderTargetContext->readSurfaceView();
+ dstBounds = SkIRect::MakeSize(dstBounds.size());
+ }
+
+ if (sigmaY == 0.0f) {
+ return dstRenderTargetContext;
+ }
+
+ return convolve_gaussian(context, std::move(srcView), srcColorType, srcAlphaType, srcBounds,
+ dstBounds, Direction::kY, radiusY, sigmaY, mode, colorSpace, fit);
+}
+
+namespace SkGpuBlurUtils {
+
+std::unique_ptr<GrRenderTargetContext> LegacyGaussianBlur(GrRecordingContext* context,
+ GrSurfaceProxyView srcView,
+ GrColorType srcColorType,
+ SkAlphaType srcAlphaType,
+ sk_sp<SkColorSpace> colorSpace,
+ const SkIRect& dstBounds,
+ const SkIRect& srcBounds,
+ float sigmaX,
+ float sigmaY,
+ SkTileMode mode,
+ SkBackingFit fit) {
+ SkASSERT(context);
+ TRACE_EVENT2("skia.gpu", "GaussianBlur", "sigmaX", sigmaX, "sigmaY", sigmaY);
+
+ if (!srcView.asTextureProxy()) {
+ return nullptr;
+ }
+
+ int scaleFactorX, radiusX;
+ int scaleFactorY, radiusY;
+ int maxTextureSize = context->priv().caps()->maxTextureSize();
+ sigmaX = adjust_sigma(sigmaX, maxTextureSize, &scaleFactorX, &radiusX);
+ sigmaY = adjust_sigma(sigmaY, maxTextureSize, &scaleFactorY, &radiusY);
+ SkASSERT(sigmaX || sigmaY);
+
+ auto localSrcBounds = srcBounds;
+
+ if (scaleFactorX == 1 && scaleFactorY == 1) {
+ // For really small blurs (certainly no wider than 5x5 on desktop GPUs) it is faster to just
+ // launch a single non separable kernel vs two launches.
+ const int kernelSize = (2 * radiusX + 1) * (2 * radiusY + 1);
+ if (sigmaX > 0 && sigmaY > 0 && kernelSize <= GrMatrixConvolutionEffect::kMaxUniformSize) {
+ // Apply the proxy offset to src bounds and offset directly
+ return convolve_gaussian_2d(context, std::move(srcView), srcColorType, srcBounds,
+ dstBounds, radiusX, radiusY, sigmaX, sigmaY, mode,
+ colorSpace, fit);
+ }
+ return two_pass_gaussian(context, std::move(srcView), srcColorType, srcAlphaType,
+ std::move(colorSpace), &localSrcBounds, dstBounds, sigmaX, sigmaY,
+ radiusX, radiusY, mode, fit);
+ }
+
+ auto srcOffset = -dstBounds.topLeft();
+ srcView = decimate(context, std::move(srcView), srcColorType, srcAlphaType, srcOffset,
+ &localSrcBounds, scaleFactorX, scaleFactorY, mode, colorSpace);
+ if (!srcView.proxy()) {
+ return nullptr;
+ }
+ SkASSERT(srcView.asTextureProxy());
+ auto scaledDstBounds = SkIRect::MakeWH(sk_float_ceil(dstBounds.width() / (float)scaleFactorX),
+ sk_float_ceil(dstBounds.height() / (float)scaleFactorY));
+ auto rtc = two_pass_gaussian(context, std::move(srcView), srcColorType, srcAlphaType,
+ colorSpace, &localSrcBounds, scaledDstBounds, sigmaX, sigmaY,
+ radiusX, radiusY, mode, SkBackingFit::kApprox);
+ if (!rtc) {
+ return nullptr;
+ }
+ return reexpand(context, std::move(rtc), localSrcBounds, scaleFactorX, scaleFactorY,
+ dstBounds.size(), std::move(colorSpace), fit);
+}
+
+}
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkLocalMatrixImageFilter.cpp b/chromium/third_party/skia/src/core/SkLocalMatrixImageFilter.cpp
index bb6dc3f13fa..19ea376deb3 100644
--- a/chromium/third_party/skia/src/core/SkLocalMatrixImageFilter.cpp
+++ b/chromium/third_party/skia/src/core/SkLocalMatrixImageFilter.cpp
@@ -53,3 +53,15 @@ SkIRect SkLocalMatrixImageFilter::onFilterBounds(const SkIRect& src, const SkMat
MapDirection dir, const SkIRect* inputRect) const {
return this->getInput(0)->filterBounds(src, SkMatrix::Concat(ctm, fLocalM), dir, inputRect);
}
+
+SkRect SkLocalMatrixImageFilter::computeFastBounds(const SkRect& bounds) const {
+ // In order to match the behavior of onFilterBounds, we map 'bounds' by the inverse of our
+ // local matrix, pass that to our child, and then map the result by our local matrix.
+ SkMatrix localInv;
+ if (!fLocalM.invert(&localInv)) {
+ return this->getInput(0)->computeFastBounds(bounds);
+ }
+
+ SkRect localBounds = localInv.mapRect(bounds);
+ return fLocalM.mapRect(this->getInput(0)->computeFastBounds(localBounds));
+}
diff --git a/chromium/third_party/skia/src/core/SkLocalMatrixImageFilter.h b/chromium/third_party/skia/src/core/SkLocalMatrixImageFilter.h
index f20773ca0a5..2a8db26155a 100644
--- a/chromium/third_party/skia/src/core/SkLocalMatrixImageFilter.h
+++ b/chromium/third_party/skia/src/core/SkLocalMatrixImageFilter.h
@@ -19,6 +19,8 @@ class SkLocalMatrixImageFilter : public SkImageFilter_Base {
public:
static sk_sp<SkImageFilter> Make(const SkMatrix& localM, sk_sp<SkImageFilter> input);
+ SkRect computeFastBounds(const SkRect&) const override;
+
protected:
void flatten(SkWriteBuffer&) const override;
sk_sp<SkSpecialImage> onFilterImage(const Context&, SkIPoint* offset) const override;
diff --git a/chromium/third_party/skia/src/core/SkMaskFilter.cpp b/chromium/third_party/skia/src/core/SkMaskFilter.cpp
index c840a68a032..222a5943e1c 100644
--- a/chromium/third_party/skia/src/core/SkMaskFilter.cpp
+++ b/chromium/third_party/skia/src/core/SkMaskFilter.cpp
@@ -255,7 +255,7 @@ bool SkMaskFilterBase::filterPath(const SkPath& devPath, const SkMatrix& matrix,
case kUnimplemented_FilterReturn:
SkASSERT(nullptr == patch.fMask.fImage);
- // fall through
+ // fall out
break;
}
}
@@ -335,7 +335,7 @@ bool SkMaskFilterBase::canFilterMaskGPU(const GrStyledShape& shape,
bool SkMaskFilterBase::directFilterMaskGPU(GrRecordingContext*,
GrRenderTargetContext*,
GrPaint&&,
- const GrClip&,
+ const GrClip*,
const SkMatrix& viewMatrix,
const GrStyledShape&) const {
return false;
diff --git a/chromium/third_party/skia/src/core/SkMaskFilterBase.h b/chromium/third_party/skia/src/core/SkMaskFilterBase.h
index 1d8ecb157c2..5ac10de24a6 100644
--- a/chromium/third_party/skia/src/core/SkMaskFilterBase.h
+++ b/chromium/third_party/skia/src/core/SkMaskFilterBase.h
@@ -116,7 +116,7 @@ public:
virtual bool directFilterMaskGPU(GrRecordingContext*,
GrRenderTargetContext*,
GrPaint&& paint,
- const GrClip&,
+ const GrClip*,
const SkMatrix& viewMatrix,
const GrStyledShape& shape) const;
diff --git a/chromium/third_party/skia/src/core/SkMatrixProvider.h b/chromium/third_party/skia/src/core/SkMatrixProvider.h
index e4e902b26c3..2033ec2aa82 100644
--- a/chromium/third_party/skia/src/core/SkMatrixProvider.h
+++ b/chromium/third_party/skia/src/core/SkMatrixProvider.h
@@ -51,35 +51,25 @@ private:
const SkMatrixProvider& fParent;
};
-class SkPostConcatMatrixProvider : public SkMatrixProvider {
+class SkPostTranslateMatrixProvider : public SkMatrixProvider {
public:
- SkPostConcatMatrixProvider(const SkMatrixProvider& parent, const SkMatrix& postMatrix)
-#if defined(SK_SUPPORT_LEGACY_MATRIX44)
- : SkMatrixProvider(SkMatrix::Concat(postMatrix, parent.localToDevice()))
-#else
- : SkMatrixProvider(SkM44(postMatrix) * parent.localToDevice44())
-#endif
- , fParent(parent)
- , fPostMatrix(postMatrix) {}
+ SkPostTranslateMatrixProvider(const SkMatrixProvider& parent, SkScalar dx, SkScalar dy)
+ : SkMatrixProvider(SkM44::Translate(dx, dy) * parent.localToDevice44())
+ , fParent(parent) {}
- // Assume that the post-matrix doesn't apply to any marked matrices
+ // Assume that the post-translation doesn't apply to any marked matrices
bool getLocalToMarker(uint32_t id, SkM44* localToMarker) const override {
return fParent.getLocalToMarker(id, localToMarker);
}
private:
const SkMatrixProvider& fParent;
- const SkMatrix fPostMatrix;
};
class SkPreConcatMatrixProvider : public SkMatrixProvider {
public:
SkPreConcatMatrixProvider(const SkMatrixProvider& parent, const SkMatrix& preMatrix)
-#if defined(SK_SUPPORT_LEGACY_MATRIX44)
- : SkMatrixProvider(SkMatrix::Concat(parent.localToDevice(), preMatrix))
-#else
: SkMatrixProvider(parent.localToDevice44() * SkM44(preMatrix))
-#endif
, fParent(parent)
, fPreMatrix(preMatrix) {}
diff --git a/chromium/third_party/skia/src/core/SkMipMap.h b/chromium/third_party/skia/src/core/SkMipMap.h
index 9aa43d265e3..89312b9dec5 100644
--- a/chromium/third_party/skia/src/core/SkMipMap.h
+++ b/chromium/third_party/skia/src/core/SkMipMap.h
@@ -36,6 +36,7 @@ public:
// This does not include the base mipmap level that the user provided when
// creating the SkMipMap.
static int ComputeLevelCount(int baseWidth, int baseHeight);
+ static int ComputeLevelCount(SkISize s) { return ComputeLevelCount(s.width(), s.height()); }
// Determines the size of a given mipmap level.
// |level| is an index into the generated mipmap levels. It does not include
diff --git a/chromium/third_party/skia/src/core/SkModeColorFilter.cpp b/chromium/third_party/skia/src/core/SkModeColorFilter.cpp
index 1927c0f9dca..721cc468073 100644
--- a/chromium/third_party/skia/src/core/SkModeColorFilter.cpp
+++ b/chromium/third_party/skia/src/core/SkModeColorFilter.cpp
@@ -38,12 +38,13 @@ bool SkModeColorFilter::onAsAColorMode(SkColor* color, SkBlendMode* mode) const
return true;
}
-uint32_t SkModeColorFilter::getFlags() const {
+uint32_t SkModeColorFilter::onGetFlags() const {
uint32_t flags = 0;
switch (fMode) {
case SkBlendMode::kDst: //!< [Da, Dc]
case SkBlendMode::kSrcATop: //!< [Da, Sc * Da + (1 - Sa) * Dc]
flags |= kAlphaUnchanged_Flag;
+ break;
default:
break;
}
@@ -93,7 +94,8 @@ std::unique_ptr<GrFragmentProcessor> SkModeColorFilter::asFragmentProcessor(
return nullptr;
}
- auto constFP = GrConstColorProcessor::Make(SkColorToPMColor4f(fColor, dstColorInfo),
+ auto constFP = GrConstColorProcessor::Make(/*inputFP=*/nullptr,
+ SkColorToPMColor4f(fColor, dstColorInfo),
GrConstColorProcessor::InputMode::kIgnore);
auto fp = GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(constFP), fMode);
if (!fp) {
diff --git a/chromium/third_party/skia/src/core/SkModeColorFilter.h b/chromium/third_party/skia/src/core/SkModeColorFilter.h
index b1a48f6d2ca..e2aa599971d 100644
--- a/chromium/third_party/skia/src/core/SkModeColorFilter.h
+++ b/chromium/third_party/skia/src/core/SkModeColorFilter.h
@@ -8,22 +8,23 @@
#ifndef SkModeColorFilter_DEFINED
#define SkModeColorFilter_DEFINED
-#include "include/core/SkColorFilter.h"
-#include "include/core/SkFlattenable.h"
+#include "src/core/SkColorFilterBase.h"
-class SkModeColorFilter : public SkColorFilter {
+class SkModeColorFilter : public SkColorFilterBase {
public:
static sk_sp<SkColorFilter> Make(SkColor color, SkBlendMode mode) {
return sk_sp<SkColorFilter>(new SkModeColorFilter(color, mode));
}
- uint32_t getFlags() const override;
+ uint32_t onGetFlags() const override;
#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrRecordingContext*,
const GrColorInfo&) const override;
#endif
+ SK_FLATTENABLE_HOOKS(SkModeColorFilter)
+
protected:
SkModeColorFilter(SkColor color, SkBlendMode mode);
@@ -35,14 +36,12 @@ protected:
SkColorSpace*, skvm::Uniforms*, SkArenaAlloc*) const override;
private:
- SK_FLATTENABLE_HOOKS(SkModeColorFilter)
-
SkColor fColor;
SkBlendMode fMode;
friend class SkColorFilter;
- typedef SkColorFilter INHERITED;
+ typedef SkColorFilterBase INHERITED;
};
#endif
diff --git a/chromium/third_party/skia/src/core/SkOSFile.h b/chromium/third_party/skia/src/core/SkOSFile.h
index 082f7b8f108..d96f11fc581 100644
--- a/chromium/third_party/skia/src/core/SkOSFile.h
+++ b/chromium/third_party/skia/src/core/SkOSFile.h
@@ -80,16 +80,17 @@ class SkOSFile {
public:
class Iter {
public:
- Iter();
- Iter(const char path[], const char suffix[] = nullptr);
- ~Iter();
+ // SPI for module use.
+ SK_SPI Iter();
+ SK_SPI Iter(const char path[], const char suffix[] = nullptr);
+ SK_SPI ~Iter();
- void reset(const char path[], const char suffix[] = nullptr);
+ SK_SPI void reset(const char path[], const char suffix[] = nullptr);
/** If getDir is true, only returns directories.
Results are undefined if true and false calls are
interleaved on a single iterator.
*/
- bool next(SkString* name, bool getDir = false);
+ SK_SPI bool next(SkString* name, bool getDir = false);
static const size_t kStorageSize = 40;
private:
diff --git a/chromium/third_party/skia/src/core/SkOpts.cpp b/chromium/third_party/skia/src/core/SkOpts.cpp
index 08f758e552b..b847c3022a5 100644
--- a/chromium/third_party/skia/src/core/SkOpts.cpp
+++ b/chromium/third_party/skia/src/core/SkOpts.cpp
@@ -107,7 +107,6 @@ namespace SkOpts {
// Each Init_foo() is defined in src/opts/SkOpts_foo.cpp.
void Init_ssse3();
- void Init_sse41();
void Init_sse42();
void Init_avx();
void Init_hsw();
@@ -121,10 +120,6 @@ namespace SkOpts {
if (SkCpu::Supports(SkCpu::SSSE3)) { Init_ssse3(); }
#endif
- #if SK_CPU_SSE_LEVEL < SK_CPU_SSE_LEVEL_SSE41
- if (SkCpu::Supports(SkCpu::SSE41)) { Init_sse41(); }
- #endif
-
#if SK_CPU_SSE_LEVEL < SK_CPU_SSE_LEVEL_SSE42
if (SkCpu::Supports(SkCpu::SSE42)) { Init_sse42(); }
#endif
diff --git a/chromium/third_party/skia/src/core/SkOpts.h b/chromium/third_party/skia/src/core/SkOpts.h
index 5b8e7739d90..04aee49b4ae 100644
--- a/chromium/third_party/skia/src/core/SkOpts.h
+++ b/chromium/third_party/skia/src/core/SkOpts.h
@@ -9,6 +9,7 @@
#define SkOpts_DEFINED
#include "include/core/SkTypes.h"
+#include "include/private/SkOpts_spi.h"
#include "src/core/SkRasterPipeline.h"
#include "src/core/SkXfermodePriv.h"
@@ -55,8 +56,6 @@ namespace SkOpts {
extern float (*cubic_solver)(float, float, float, float);
- // The fastest high quality 32-bit hash we can provide on this platform.
- extern uint32_t (*hash_fn)(const void*, size_t, uint32_t seed);
static inline uint32_t hash(const void* data, size_t bytes, uint32_t seed=0) {
return hash_fn(data, bytes, seed);
}
diff --git a/chromium/third_party/skia/src/core/SkOpts_skx.cpp b/chromium/third_party/skia/src/core/SkOpts_skx.cpp
deleted file mode 100644
index 9341406bc2c..00000000000
--- a/chromium/third_party/skia/src/core/SkOpts_skx.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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/core/SkOpts.h"
-
-#if defined(SK_CPU_X86)
-
- // Turn on SKX feature set.
- #if defined(__clang__)
- #pragma clang attribute push(__attribute__((target("avx512f,avx512dq,avx512cd,avx512bw,avx512vl"))), apply_to=function)
- #elif defined(__GNUC__)
- #pragma GCC push_options
- #pragma GCC target("avx512f,avx512dq,avx512cd,avx512bw,avx512vl")
- #endif
-
- // Let our code in *_opts.h know we want SKX features.
- #undef SK_CPU_SSE_LEVEL
- #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SKX
-
- #if defined(__clang__) && defined(_MSC_VER)
- // clang-cl's immintrin.h is bizarrely annoying, not including the
- // various foointrin.h unless the __FOO__ flag is also defined (i.e.
- // you used command-line flags to set the features instead of attributes).
- // MSVC itself doesn't work this way, nor does non-_MSC_VER clang. :/
- #define __SSE__ 1
- #define __SSE2__ 1
- #define __SSE3__ 1
- #define __SSSE3__ 1
- #define __SSE4_1__ 1
- #define __SSE4_2__ 1
- #define __AVX__ 1
- #define __F16C__ 1
- #define __AVX2__ 1
- #define __FMA__ 1
- #define __AVX512F__ 1
- #define __AVX512DQ__ 1
- #define __AVX512CD__ 1
- #define __AVX512BW__ 1
- #define __AVX512VL__ 1
- #endif
-
- #define SK_OPTS_NS skx
- #include "src/opts/SkBlitRow_opts.h"
- #include "src/opts/SkVM_opts.h"
-
- namespace SkOpts {
- void Init_skx() {
- blit_row_s32a_opaque = SK_OPTS_NS::blit_row_s32a_opaque;
- interpret_skvm = SK_OPTS_NS::interpret_skvm;
- }
- }
-
- #if defined(__clang__)
- #pragma clang attribute pop
- #elif defined(__GNUC__)
- #pragma GCC pop_options
- #endif
-
-#endif//defined(SK_CPU_X86)
diff --git a/chromium/third_party/skia/src/core/SkOverdrawCanvas.cpp b/chromium/third_party/skia/src/core/SkOverdrawCanvas.cpp
index 0297a973404..f606ac7dcb8 100644
--- a/chromium/third_party/skia/src/core/SkOverdrawCanvas.cpp
+++ b/chromium/third_party/skia/src/core/SkOverdrawCanvas.cpp
@@ -50,7 +50,7 @@ public:
fOverdrawCanvas{overdrawCanvas},
fPainter{props, kN32_SkColorType, nullptr, SkStrikeCache::GlobalStrikeCache()} {}
- void paintPaths(SkDrawableGlyphBuffer*, SkScalar scale, const SkPaint& paint) const override {}
+ void paintPaths(SkDrawableGlyphBuffer*, SkScalar, SkPoint, const SkPaint&) const override {}
void paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint) const override {
for (auto t : drawables->drawable()) {
diff --git a/chromium/third_party/skia/src/core/SkPaint.cpp b/chromium/third_party/skia/src/core/SkPaint.cpp
index f294dbe4a09..2451fcefe6b 100644
--- a/chromium/third_party/skia/src/core/SkPaint.cpp
+++ b/chromium/third_party/skia/src/core/SkPaint.cpp
@@ -7,7 +7,6 @@
#include "include/core/SkPaint.h"
-#include "include/core/SkColorFilter.h"
#include "include/core/SkData.h"
#include "include/core/SkGraphics.h"
#include "include/core/SkImageFilter.h"
@@ -19,6 +18,7 @@
#include "include/core/SkTypeface.h"
#include "include/private/SkMutex.h"
#include "include/private/SkTo.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkColorSpaceXformSteps.h"
#include "src/core/SkDraw.h"
@@ -109,6 +109,10 @@ void SkPaint::setStyle(Style style) {
}
}
+void SkPaint::setStroke(bool isStroke) {
+ fBitfields.fStyle = isStroke ? kStroke_Style : kFill_Style;
+}
+
void SkPaint::setColor(SkColor color) {
fColor4f = SkColor4f::FromColor(color);
}
@@ -513,7 +517,7 @@ const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
// return true if the filter exists, and may affect alpha
static bool affects_alpha(const SkColorFilter* cf) {
- return cf && !(cf->getFlags() & SkColorFilter::kAlphaUnchanged_Flag);
+ return cf && !as_CFB(cf)->isAlphaUnchanged();
}
// return true if the filter exists, and may affect alpha
diff --git a/chromium/third_party/skia/src/core/SkPaintPriv.cpp b/chromium/third_party/skia/src/core/SkPaintPriv.cpp
index 4bf00023586..7ad907ba5b8 100644
--- a/chromium/third_party/skia/src/core/SkPaintPriv.cpp
+++ b/chromium/third_party/skia/src/core/SkPaintPriv.cpp
@@ -5,8 +5,8 @@
* found in the LICENSE file.
*/
-#include "include/core/SkColorFilter.h"
#include "include/core/SkPaint.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkPaintPriv.h"
#include "src/core/SkXfermodePriv.h"
@@ -15,7 +15,7 @@
static bool changes_alpha(const SkPaint& paint) {
SkColorFilter* cf = paint.getColorFilter();
- return cf && !(cf->getFlags() & SkColorFilter::kAlphaUnchanged_Flag);
+ return cf && !(as_CFB(cf)->getFlags() & SkColorFilterBase::kAlphaUnchanged_Flag);
}
bool SkPaintPriv::Overwrites(const SkPaint* paint, ShaderOverrideOpacity overrideOpacity) {
diff --git a/chromium/third_party/skia/src/core/SkPath.cpp b/chromium/third_party/skia/src/core/SkPath.cpp
index 09c061de51a..95bb11b57c4 100644
--- a/chromium/third_party/skia/src/core/SkPath.cpp
+++ b/chromium/third_party/skia/src/core/SkPath.cpp
@@ -148,6 +148,15 @@ SkPath::SkPath()
fIsVolatile = false;
}
+SkPath::SkPath(sk_sp<SkPathRef> pr, SkPathFillType ft, bool isVolatile)
+ : fPathRef(std::move(pr))
+ , fLastMoveToIndex(INITIAL_LASTMOVETOINDEX_VALUE)
+ , fConvexity((uint8_t)SkPathConvexityType::kUnknown)
+ , fFirstDirection(SkPathPriv::kUnknown_FirstDirection)
+ , fFillType((unsigned)ft)
+ , fIsVolatile(isVolatile)
+{}
+
void SkPath::resetFields() {
//fPathRef is assumed to have been emptied by the caller.
fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE;
@@ -1815,7 +1824,7 @@ SkPath::Verb SkPath::Iter::next(SkPoint ptsParam[4]) {
break;
case kConic_Verb:
fConicWeights += 1;
- // fall-through
+ [[fallthrough]];
case kQuad_Verb:
pts[0] = this->cons_moveTo();
memcpy(&pts[1], srcPts, 2 * sizeof(SkPoint));
@@ -2351,7 +2360,7 @@ void ContourIter::next() {
break;
case SkPath::kConic_Verb:
fCurrConicWeight += 1;
- // fall-through
+ [[fallthrough]];
case SkPath::kQuad_Verb:
ptCount += 2;
break;
@@ -3348,6 +3357,7 @@ bool SkPathPriv::IsRectContour(const SkPath& path, bool allowPartial, int* currV
savePts = pts;
autoClose = true;
insertClose = false;
+ [[fallthrough]];
case SkPath::kLine_Verb: {
if (SkPath::kClose_Verb != verb) {
lastPt = pts;
diff --git a/chromium/third_party/skia/src/core/SkPathBuilder.cpp b/chromium/third_party/skia/src/core/SkPathBuilder.cpp
new file mode 100644
index 00000000000..d5b21472681
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkPathBuilder.cpp
@@ -0,0 +1,358 @@
+/*
+ * 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 "include/core/SkPathBuilder.h"
+#include "include/core/SkRRect.h"
+#include "include/private/SkPathRef.h"
+#include "include/private/SkSafe32.h"
+
+SkPathBuilder::SkPathBuilder() {
+ this->reset();
+}
+
+SkPathBuilder::~SkPathBuilder() {
+}
+
+SkPathBuilder& SkPathBuilder::reset() {
+ fPts.reset();
+ fVerbs.reset();
+ fConicWeights.reset();
+ fFillType = SkPathFillType::kWinding;
+ fIsVolatile = false;
+
+ // these are internal state
+
+ fSegmentMask = 0;
+ fLastMovePoint = {0, 0};
+ fNeedsMoveVerb = true;
+
+ return *this;
+}
+
+void SkPathBuilder::incReserve(int extraPtCount, int extraVbCount) {
+ fPts.setReserve( Sk32_sat_add(fPts.count(), extraPtCount));
+ fVerbs.setReserve(Sk32_sat_add(fVerbs.count(), extraVbCount));
+}
+
+/*
+ * Some old behavior in SkPath -- should we keep it?
+ *
+ * After each edit (i.e. adding a verb)
+ this->setConvexityType(SkPathConvexityType::kUnknown);
+ this->setFirstDirection(SkPathPriv::kUnknown_FirstDirection);
+ */
+
+SkPathBuilder& SkPathBuilder::moveTo(SkPoint pt) {
+ fPts.push_back(pt);
+ fVerbs.push_back((uint8_t)SkPathVerb::kMove);
+
+ fLastMovePoint = pt;
+ fNeedsMoveVerb = false;
+ return *this;
+}
+
+SkPathBuilder& SkPathBuilder::lineTo(SkPoint pt) {
+ this->ensureMove();
+
+ fPts.push_back(pt);
+ fVerbs.push_back((uint8_t)SkPathVerb::kLine);
+
+ fSegmentMask |= kLine_SkPathSegmentMask;
+ return *this;
+}
+
+SkPathBuilder& SkPathBuilder::quadTo(SkPoint pt1, SkPoint pt2) {
+ this->ensureMove();
+
+ SkPoint* p = fPts.append(2);
+ p[0] = pt1;
+ p[1] = pt2;
+ fVerbs.push_back((uint8_t)SkPathVerb::kQuad);
+
+ fSegmentMask |= kQuad_SkPathSegmentMask;
+ return *this;
+}
+
+SkPathBuilder& SkPathBuilder::conicTo(SkPoint pt1, SkPoint pt2, SkScalar w) {
+ this->ensureMove();
+
+ SkPoint* p = fPts.append(2);
+ p[0] = pt1;
+ p[1] = pt2;
+ fVerbs.push_back((uint8_t)SkPathVerb::kConic);
+ fConicWeights.push_back(w);
+
+ fSegmentMask |= kConic_SkPathSegmentMask;
+ return *this;
+}
+
+SkPathBuilder& SkPathBuilder::cubicTo(SkPoint pt1, SkPoint pt2, SkPoint pt3) {
+ this->ensureMove();
+
+ SkPoint* p = fPts.append(3);
+ p[0] = pt1;
+ p[1] = pt2;
+ p[2] = pt3;
+ fVerbs.push_back((uint8_t)SkPathVerb::kCubic);
+
+ fSegmentMask |= kCubic_SkPathSegmentMask;
+ return *this;
+}
+
+SkPathBuilder& SkPathBuilder::close() {
+ this->ensureMove();
+
+ fVerbs.push_back((uint8_t)SkPathVerb::kClose);
+
+ // fLastMovePoint stays where it is -- the previous moveTo
+ fNeedsMoveVerb = true;
+ return *this;
+}
+
+SkPath SkPathBuilder::snapshot() {
+ return SkPath(sk_sp<SkPathRef>(new SkPathRef(fPts, fVerbs, fConicWeights, fSegmentMask)),
+ fFillType, fIsVolatile);
+}
+
+SkPath SkPathBuilder::detach() {
+ auto path = SkPath(sk_sp<SkPathRef>(new SkPathRef(std::move(fPts),
+ std::move(fVerbs),
+ std::move(fConicWeights),
+ fSegmentMask)),
+ fFillType, fIsVolatile);
+ this->reset();
+ return path;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+namespace {
+ template <unsigned N> class PointIterator {
+ public:
+ PointIterator(SkPathDirection dir, unsigned startIndex)
+ : fCurrent(startIndex % N)
+ , fAdvance(dir == SkPathDirection::kCW ? 1 : N - 1)
+ {}
+
+ const SkPoint& current() const {
+ SkASSERT(fCurrent < N);
+ return fPts[fCurrent];
+ }
+
+ const SkPoint& next() {
+ fCurrent = (fCurrent + fAdvance) % N;
+ return this->current();
+ }
+
+ protected:
+ SkPoint fPts[N];
+
+ private:
+ unsigned fCurrent;
+ unsigned fAdvance;
+ };
+
+ class RectPointIterator : public PointIterator<4> {
+ public:
+ RectPointIterator(const SkRect& rect, SkPathDirection dir, unsigned startIndex)
+ : PointIterator(dir, startIndex) {
+
+ fPts[0] = SkPoint::Make(rect.fLeft, rect.fTop);
+ fPts[1] = SkPoint::Make(rect.fRight, rect.fTop);
+ fPts[2] = SkPoint::Make(rect.fRight, rect.fBottom);
+ fPts[3] = SkPoint::Make(rect.fLeft, rect.fBottom);
+ }
+ };
+
+ class OvalPointIterator : public PointIterator<4> {
+ public:
+ OvalPointIterator(const SkRect& oval, SkPathDirection dir, unsigned startIndex)
+ : PointIterator(dir, startIndex) {
+
+ const SkScalar cx = oval.centerX();
+ const SkScalar cy = oval.centerY();
+
+ fPts[0] = SkPoint::Make(cx, oval.fTop);
+ fPts[1] = SkPoint::Make(oval.fRight, cy);
+ fPts[2] = SkPoint::Make(cx, oval.fBottom);
+ fPts[3] = SkPoint::Make(oval.fLeft, cy);
+ }
+ };
+
+ class RRectPointIterator : public PointIterator<8> {
+ public:
+ RRectPointIterator(const SkRRect& rrect, SkPathDirection dir, unsigned startIndex)
+ : PointIterator(dir, startIndex)
+ {
+ const SkRect& bounds = rrect.getBounds();
+ const SkScalar L = bounds.fLeft;
+ const SkScalar T = bounds.fTop;
+ const SkScalar R = bounds.fRight;
+ const SkScalar B = bounds.fBottom;
+
+ fPts[0] = SkPoint::Make(L + rrect.radii(SkRRect::kUpperLeft_Corner).fX, T);
+ fPts[1] = SkPoint::Make(R - rrect.radii(SkRRect::kUpperRight_Corner).fX, T);
+ fPts[2] = SkPoint::Make(R, T + rrect.radii(SkRRect::kUpperRight_Corner).fY);
+ fPts[3] = SkPoint::Make(R, B - rrect.radii(SkRRect::kLowerRight_Corner).fY);
+ fPts[4] = SkPoint::Make(R - rrect.radii(SkRRect::kLowerRight_Corner).fX, B);
+ fPts[5] = SkPoint::Make(L + rrect.radii(SkRRect::kLowerLeft_Corner).fX, B);
+ fPts[6] = SkPoint::Make(L, B - rrect.radii(SkRRect::kLowerLeft_Corner).fY);
+ fPts[7] = SkPoint::Make(L, T + rrect.radii(SkRRect::kUpperLeft_Corner).fY);
+ }
+ };
+} // anonymous namespace
+
+
+SkPathBuilder& SkPathBuilder::addRect(const SkRect& rect, SkPathDirection dir, unsigned index) {
+ const int kPts = 4; // moveTo + 3 lines
+ const int kVerbs = 5; // moveTo + 3 lines + close
+ this->incReserve(kPts, kVerbs);
+
+ RectPointIterator iter(rect, dir, index);
+
+ this->moveTo(iter.current());
+ this->lineTo(iter.next());
+ this->lineTo(iter.next());
+ this->lineTo(iter.next());
+ return this->close();
+}
+
+SkPathBuilder& SkPathBuilder::addOval(const SkRect& oval, SkPathDirection dir, unsigned index) {
+ const int kPts = 9; // moveTo + 4 conics(2 pts each)
+ const int kVerbs = 6; // moveTo + 4 conics + close
+ this->incReserve(kPts, kVerbs);
+
+ OvalPointIterator ovalIter(oval, dir, index);
+ RectPointIterator rectIter(oval, dir, index + (dir == SkPathDirection::kCW ? 0 : 1));
+
+ // The corner iterator pts are tracking "behind" the oval/radii pts.
+
+ this->moveTo(ovalIter.current());
+ for (unsigned i = 0; i < 4; ++i) {
+ this->conicTo(rectIter.next(), ovalIter.next(), SK_ScalarRoot2Over2);
+ }
+ return this->close();
+}
+
+SkPathBuilder& SkPathBuilder::addRRect(const SkRRect& rrect, SkPathDirection dir, unsigned index) {
+ const SkRect& bounds = rrect.getBounds();
+
+ if (rrect.isRect() || rrect.isEmpty()) {
+ // degenerate(rect) => radii points are collapsing
+ this->addRect(bounds, dir, (index + 1) / 2);
+ } else if (rrect.isOval()) {
+ // degenerate(oval) => line points are collapsing
+ this->addOval(bounds, dir, index / 2);
+ } else {
+ // we start with a conic on odd indices when moving CW vs. even indices when moving CCW
+ const bool startsWithConic = ((index & 1) == (dir == SkPathDirection::kCW));
+ const SkScalar weight = SK_ScalarRoot2Over2;
+
+ const int kVerbs = startsWithConic
+ ? 9 // moveTo + 4x conicTo + 3x lineTo + close
+ : 10; // moveTo + 4x lineTo + 4x conicTo + close
+ this->incReserve(kVerbs);
+
+ RRectPointIterator rrectIter(rrect, dir, index);
+ // Corner iterator indices follow the collapsed radii model,
+ // adjusted such that the start pt is "behind" the radii start pt.
+ const unsigned rectStartIndex = index / 2 + (dir == SkPathDirection::kCW ? 0 : 1);
+ RectPointIterator rectIter(bounds, dir, rectStartIndex);
+
+ this->moveTo(rrectIter.current());
+ if (startsWithConic) {
+ for (unsigned i = 0; i < 3; ++i) {
+ this->conicTo(rectIter.next(), rrectIter.next(), weight);
+ this->lineTo(rrectIter.next());
+ }
+ this->conicTo(rectIter.next(), rrectIter.next(), weight);
+ // final lineTo handled by close().
+ } else {
+ for (unsigned i = 0; i < 4; ++i) {
+ this->lineTo(rrectIter.next());
+ this->conicTo(rectIter.next(), rrectIter.next(), weight);
+ }
+ }
+ this->close();
+ }
+ return *this;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+struct PathInfo {
+ bool valid;
+ int points, weights;
+ unsigned segmentMask;
+};
+
+static PathInfo validate_verbs(const uint8_t vbs[], int verbCount) {
+ PathInfo info = {false, 0, 0, 0};
+
+ bool needMove = true;
+ bool invalid = false;
+ for (int i = 0; i < verbCount; ++i) {
+ switch ((SkPathVerb)vbs[i]) {
+ case SkPathVerb::kMove:
+ needMove = false;
+ info.points += 1;
+ break;
+ case SkPathVerb::kLine:
+ invalid |= needMove;
+ info.segmentMask |= kLine_SkPathSegmentMask;
+ info.points += 1;
+ break;
+ case SkPathVerb::kQuad:
+ invalid |= needMove;
+ info.segmentMask |= kQuad_SkPathSegmentMask;
+ info.points += 2;
+ break;
+ case SkPathVerb::kConic:
+ invalid |= needMove;
+ info.segmentMask |= kConic_SkPathSegmentMask;
+ info.points += 2;
+ info.weights += 1;
+ break;
+ case SkPathVerb::kCubic:
+ invalid |= needMove;
+ info.segmentMask |= kCubic_SkPathSegmentMask;
+ info.points += 3;
+ break;
+ case SkPathVerb::kClose:
+ invalid |= needMove;
+ needMove = true;
+ break;
+ default:
+ invalid = true;
+ break;
+ }
+ }
+ info.valid = !invalid;
+ return info;
+}
+
+SkPath SkPathBuilder::Make(const SkPoint pts[], int pointCount,
+ const uint8_t vbs[], int verbCount,
+ const SkScalar ws[], int wCount,
+ SkPathFillType ft, bool isVolatile) {
+ if (verbCount <= 0) {
+ return SkPath();
+ }
+
+ const auto info = validate_verbs(vbs, verbCount);
+ if (!info.valid || info.points > pointCount || info.weights > wCount) {
+ SkDEBUGFAIL("invalid verbs and number of points/weights");
+ return SkPath();
+ }
+
+ return SkPath(sk_sp<SkPathRef>(new SkPathRef(SkTDArray<SkPoint>(pts, info.points),
+ SkTDArray<uint8_t>(vbs, verbCount),
+ SkTDArray<SkScalar>(ws, info.weights),
+ info.segmentMask)),
+ ft, isVolatile);
+}
+
diff --git a/chromium/third_party/skia/src/core/SkPathRef.cpp b/chromium/third_party/skia/src/core/SkPathRef.cpp
index 68c8970b07a..dca2b329d89 100644
--- a/chromium/third_party/skia/src/core/SkPathRef.cpp
+++ b/chromium/third_party/skia/src/core/SkPathRef.cpp
@@ -394,10 +394,12 @@ SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb,
break;
case SkPath::kDone_Verb:
SkDEBUGFAIL("growForRepeatedVerb called for kDone");
- // fall through
+ pCnt = 0;
+ break;
default:
SkDEBUGFAIL("default should not be reached");
pCnt = 0;
+ break;
}
fBoundsIsDirty = true; // this also invalidates fIsFinite
@@ -444,10 +446,12 @@ SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb, SkScalar weight) {
break;
case SkPath::kDone_Verb:
SkDEBUGFAIL("growForVerb called for kDone");
- // fall through
+ pCnt = 0;
+ break;
default:
SkDEBUGFAIL("default is not reached");
pCnt = 0;
+ break;
}
fSegmentMask |= mask;
@@ -596,7 +600,7 @@ uint8_t SkPathRef::Iter::next(SkPoint pts[4]) {
break;
case SkPath::kConic_Verb:
fConicWeights += 1;
- // fall-through
+ [[fallthrough]];
case SkPath::kQuad_Verb:
pts[0] = srcPts[-1];
pts[1] = srcPts[0];
diff --git a/chromium/third_party/skia/src/core/SkPath_serial.cpp b/chromium/third_party/skia/src/core/SkPath_serial.cpp
index b1d85f451cd..694ce77315c 100644
--- a/chromium/third_party/skia/src/core/SkPath_serial.cpp
+++ b/chromium/third_party/skia/src/core/SkPath_serial.cpp
@@ -211,7 +211,7 @@ size_t SkPath::readFromMemory_EQ4Or5(const void* storage, size_t length) {
case SerializationType::kRRect:
return this->readAsRRect(storage, length);
case SerializationType::kGeneral:
- break; // fall through
+ break; // fall out
default:
return 0;
}
diff --git a/chromium/third_party/skia/src/core/SkPicture.cpp b/chromium/third_party/skia/src/core/SkPicture.cpp
index e041ba64f0c..dbfb7aa69cb 100644
--- a/chromium/third_party/skia/src/core/SkPicture.cpp
+++ b/chromium/third_party/skia/src/core/SkPicture.cpp
@@ -185,7 +185,7 @@ sk_sp<SkPicture> SkPicture::MakeFromStream(SkStream* stream, const SkDeserialPro
}
return procs.fPictureProc(data->data(), size, procs.fPictureCtx);
}
- default: // fall through to error return
+ default: // fall out to error return
break;
}
return nullptr;
diff --git a/chromium/third_party/skia/src/core/SkPictureData.cpp b/chromium/third_party/skia/src/core/SkPictureData.cpp
index c4ae9a002ee..611c5f2b9f0 100644
--- a/chromium/third_party/skia/src/core/SkPictureData.cpp
+++ b/chromium/third_party/skia/src/core/SkPictureData.cpp
@@ -315,7 +315,12 @@ bool SkPictureData::parseStreamTag(SkStream* stream,
case SK_PICT_TYPEFACE_TAG: {
fTFPlayback.setCount(size);
for (uint32_t i = 0; i < size; ++i) {
- sk_sp<SkTypeface> tf(SkTypeface::MakeDeserialize(stream));
+ sk_sp<SkTypeface> tf;
+ if (procs.fTypefaceProc) {
+ tf = procs.fTypefaceProc(&stream, sizeof(stream), procs.fTypefaceCtx);
+ } else {
+ tf = SkTypeface::MakeDeserialize(stream);
+ }
if (!tf.get()) { // failed to deserialize
// fTFPlayback asserts it never has a null, so we plop in
// the default here.
diff --git a/chromium/third_party/skia/src/core/SkPictureData.h b/chromium/third_party/skia/src/core/SkPictureData.h
index 25c9a7acc4b..f820ca7a158 100644
--- a/chromium/third_party/skia/src/core/SkPictureData.h
+++ b/chromium/third_party/skia/src/core/SkPictureData.h
@@ -18,7 +18,6 @@
class SkData;
class SkPictureRecord;
-class SkReader32;
struct SkSerialProcs;
class SkStream;
class SkWStream;
diff --git a/chromium/third_party/skia/src/core/SkPictureFlat.h b/chromium/third_party/skia/src/core/SkPictureFlat.h
index 2f551f20665..4bb87e7f0bf 100644
--- a/chromium/third_party/skia/src/core/SkPictureFlat.h
+++ b/chromium/third_party/skia/src/core/SkPictureFlat.h
@@ -132,8 +132,8 @@ enum SaveLayerRecFlatFlags {
SAVELAYERREC_HAS_PAINT = 1 << 1,
SAVELAYERREC_HAS_BACKDROP = 1 << 2,
SAVELAYERREC_HAS_FLAGS = 1 << 3,
- SAVELAYERREC_HAS_CLIPMASK = 1 << 4,
- SAVELAYERREC_HAS_CLIPMATRIX = 1 << 5,
+ SAVELAYERREC_HAS_CLIPMASK_OBSOLETE = 1 << 4, // 6/13/2020
+ SAVELAYERREC_HAS_CLIPMATRIX_OBSOLETE = 1 << 5, // 6/13/2020
};
enum SaveBehindFlatFlags {
diff --git a/chromium/third_party/skia/src/core/SkPicturePlayback.cpp b/chromium/third_party/skia/src/core/SkPicturePlayback.cpp
index 07ea8cd3bfe..9d7209297ae 100644
--- a/chromium/third_party/skia/src/core/SkPicturePlayback.cpp
+++ b/chromium/third_party/skia/src/core/SkPicturePlayback.cpp
@@ -601,8 +601,7 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags));
} break;
case SAVE_LAYER_SAVELAYERREC: {
- SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, nullptr, nullptr, 0);
- SkMatrix clipMatrix;
+ SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, 0);
const uint32_t flatFlags = reader->readInt();
SkRect bounds;
if (flatFlags & SAVELAYERREC_HAS_BOUNDS) {
@@ -620,12 +619,12 @@ void SkPicturePlayback::handleOp(SkReadBuffer* reader,
if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
rec.fSaveLayerFlags = reader->readInt();
}
- if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) {
- rec.fClipMask = fPictureData->getImage(reader);
+ if (flatFlags & SAVELAYERREC_HAS_CLIPMASK_OBSOLETE) {
+ (void)fPictureData->getImage(reader);
}
- if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) {
- reader->readMatrix(&clipMatrix);
- rec.fClipMatrix = &clipMatrix;
+ if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX_OBSOLETE) {
+ SkMatrix clipMatrix_ignored;
+ reader->readMatrix(&clipMatrix_ignored);
}
BREAK_ON_READ_ERROR(reader);
diff --git a/chromium/third_party/skia/src/core/SkPicturePriv.h b/chromium/third_party/skia/src/core/SkPicturePriv.h
index 16f0e42e1c2..67cb931ba3e 100644
--- a/chromium/third_party/skia/src/core/SkPicturePriv.h
+++ b/chromium/third_party/skia/src/core/SkPicturePriv.h
@@ -76,6 +76,7 @@ public:
// V73: Use SkColor4f in per-edge AA quad API
// V74: MorphologyImageFilter internal radius is SkScaler
// V75: SkVertices switched from unsafe use of SkReader32 to SkReadBuffer (like everything else)
+ // V76: Add filtering enum to ImageShader
enum Version {
kTileModeInBlurImageFilter_Version = 56,
@@ -98,10 +99,11 @@ public:
kEdgeAAQuadColor4f_Version = 73,
kMorphologyTakesScalar_Version = 74,
kVerticesUseReadBuffer_Version = 75,
+ kFilteringInImageShader_Version = 76,
// Only SKPs within the min/current picture version range (inclusive) can be read.
kMin_Version = kTileModeInBlurImageFilter_Version,
- kCurrent_Version = kVerticesUseReadBuffer_Version
+ kCurrent_Version = kFilteringInImageShader_Version
};
static_assert(kMin_Version <= 62, "Remove kFontAxes_bad from SkFontDescriptor.cpp");
diff --git a/chromium/third_party/skia/src/core/SkPictureRecord.cpp b/chromium/third_party/skia/src/core/SkPictureRecord.cpp
index a9e053eb4a2..50ffb99079b 100644
--- a/chromium/third_party/skia/src/core/SkPictureRecord.cpp
+++ b/chromium/third_party/skia/src/core/SkPictureRecord.cpp
@@ -129,14 +129,6 @@ void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
flatFlags |= SAVELAYERREC_HAS_FLAGS;
size += sizeof(uint32_t);
}
- if (rec.fClipMask) {
- flatFlags |= SAVELAYERREC_HAS_CLIPMASK;
- size += sizeof(uint32_t); // clip image index
- }
- if (rec.fClipMatrix) {
- flatFlags |= SAVELAYERREC_HAS_CLIPMATRIX;
- size += SkMatrixPriv::WriteToMemory(*rec.fClipMatrix, nullptr);
- }
const size_t initialOffset = this->addDraw(SAVE_LAYER_SAVELAYERREC, &size);
this->addInt(flatFlags);
@@ -155,12 +147,6 @@ void SkPictureRecord::recordSaveLayer(const SaveLayerRec& rec) {
if (flatFlags & SAVELAYERREC_HAS_FLAGS) {
this->addInt(rec.fSaveLayerFlags);
}
- if (flatFlags & SAVELAYERREC_HAS_CLIPMASK) {
- this->addImage(rec.fClipMask);
- }
- if (flatFlags & SAVELAYERREC_HAS_CLIPMATRIX) {
- this->addMatrix(*rec.fClipMatrix);
- }
this->validate(initialOffset, size);
}
@@ -241,11 +227,11 @@ void SkPictureRecord::didConcat44(const SkM44& m) {
}
void SkPictureRecord::didScale(SkScalar x, SkScalar y) {
- this->didConcat(SkMatrix::MakeScale(x, y));
+ this->didConcat(SkMatrix::Scale(x, y));
}
void SkPictureRecord::didTranslate(SkScalar x, SkScalar y) {
- this->didConcat(SkMatrix::MakeTrans(x, y));
+ this->didConcat(SkMatrix::Translate(x, y));
}
void SkPictureRecord::didConcat(const SkMatrix& matrix) {
diff --git a/chromium/third_party/skia/src/core/SkPixmap.cpp b/chromium/third_party/skia/src/core/SkPixmap.cpp
index 49ba4228718..0364a32fb86 100644
--- a/chromium/third_party/skia/src/core/SkPixmap.cpp
+++ b/chromium/third_party/skia/src/core/SkPixmap.cpp
@@ -243,6 +243,7 @@ bool SkPixmap::scalePixels(const SkPixmap& actualDst, SkFilterQuality quality) c
SkTileMode::kClamp,
SkTileMode::kClamp,
&scale,
+ (SkImageShader::FilterEnum)quality,
clampAsIfUnpremul);
sk_sp<SkSurface> surface = SkSurface::MakeRasterDirect(dst.info(),
diff --git a/chromium/third_party/skia/src/core/SkRasterPipeline.cpp b/chromium/third_party/skia/src/core/SkRasterPipeline.cpp
index 2a4fbd0439f..f1bce40b41c 100644
--- a/chromium/third_party/skia/src/core/SkRasterPipeline.cpp
+++ b/chromium/third_party/skia/src/core/SkRasterPipeline.cpp
@@ -6,6 +6,7 @@
*/
#include "include/private/SkImageInfoPriv.h"
+#include "include/private/SkNx.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkOpts.h"
#include "src/core/SkRasterPipeline.h"
diff --git a/chromium/third_party/skia/src/core/SkRasterPipeline.h b/chromium/third_party/skia/src/core/SkRasterPipeline.h
index 316e8846293..4ec07de8709 100644
--- a/chromium/third_party/skia/src/core/SkRasterPipeline.h
+++ b/chromium/third_party/skia/src/core/SkRasterPipeline.h
@@ -14,7 +14,6 @@
#include "include/core/SkRefCnt.h"
#include "include/core/SkTileMode.h"
#include "include/core/SkTypes.h"
-#include "include/private/SkNx.h"
#include "include/private/SkTArray.h"
#include "src/core/SkArenaAlloc.h"
#include <functional>
@@ -44,7 +43,6 @@ class SkData;
M(unpremul) M(premul) M(premul_dst) \
M(force_opaque) M(force_opaque_dst) \
M(set_rgb) M(unbounded_set_rgb) M(swap_rb) M(swap_rb_dst) \
- M(from_srgb) M(to_srgb) \
M(black_color) M(white_color) \
M(uniform_color) M(unbounded_uniform_color) M(uniform_color_dst) \
M(seed_shader) M(dither) \
diff --git a/chromium/third_party/skia/src/core/SkRasterPipelineBlitter.cpp b/chromium/third_party/skia/src/core/SkRasterPipelineBlitter.cpp
index 6db71082b5e..4fdcffd3b94 100644
--- a/chromium/third_party/skia/src/core/SkRasterPipelineBlitter.cpp
+++ b/chromium/third_party/skia/src/core/SkRasterPipelineBlitter.cpp
@@ -6,13 +6,13 @@
*/
#include "include/core/SkColor.h"
-#include "include/core/SkColorFilter.h"
#include "include/core/SkPaint.h"
#include "include/core/SkShader.h"
#include "include/private/SkTo.h"
#include "src/core/SkArenaAlloc.h"
#include "src/core/SkBlendModePriv.h"
#include "src/core/SkBlitter.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkColorSpaceXformSteps.h"
#include "src/core/SkMatrixProvider.h"
@@ -90,13 +90,7 @@ SkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap& dst,
const SkMatrixProvider& matrixProvider,
SkArenaAlloc* alloc,
sk_sp<SkShader> clipShader) {
- // For legacy to keep working, we need to sometimes still distinguish null dstCS from sRGB.
-#if 0
- SkColorSpace* dstCS = dst.colorSpace() ? dst.colorSpace()
- : sk_srgb_singleton();
-#else
SkColorSpace* dstCS = dst.colorSpace();
-#endif
SkColorType dstCT = dst.colorType();
SkColor4f paintColor = paint.getColor4f();
SkColorSpaceXformSteps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
@@ -129,8 +123,8 @@ SkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap& dst,
std::move(clipShader));
}
- // The shader has opted out of drawing anything.
- return alloc->make<SkNullBlitter>();
+ // The shader can't draw with SkRasterPipeline.
+ return nullptr;
}
SkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap& dst,
@@ -190,10 +184,12 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst,
SkStageRec rec = {
colorPipeline, alloc, dst.colorType(), dst.colorSpace(), paint, nullptr, matrixProvider
};
- colorFilter->appendStages(rec, is_opaque);
- is_opaque = is_opaque && (colorFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag);
+ as_CFB(colorFilter)->appendStages(rec, is_opaque);
+ is_opaque = is_opaque
+ && (as_CFB(colorFilter)->getFlags() & SkColorFilterBase::kAlphaUnchanged_Flag);
}
+#if defined(SK_LATE_DITHER)
// Not all formats make sense to dither (think, F16). We set their dither rate
// to zero. We need to decide if we're going to dither now to keep is_constant accurate.
if (paint.isDither()) {
@@ -226,6 +222,39 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst,
// could disable it (for speed, by not adding the stage).
}
is_constant = is_constant && (blitter->fDitherRate == 0.0f);
+#else
+ // Not all formats make sense to dither (think, F16). We set their dither rate
+ // to zero. We only dither non-constant shaders, so is_constant won't change here.
+ if (paint.isDither() && !is_constant) {
+ switch (dst.info().colorType()) {
+ case kARGB_4444_SkColorType: blitter->fDitherRate = 1/15.0f; break;
+ case kRGB_565_SkColorType: blitter->fDitherRate = 1/63.0f; break;
+ case kGray_8_SkColorType:
+ case kRGB_888x_SkColorType:
+ case kRGBA_8888_SkColorType:
+ case kBGRA_8888_SkColorType: blitter->fDitherRate = 1/255.0f; break;
+ case kRGB_101010x_SkColorType:
+ case kRGBA_1010102_SkColorType:
+ case kBGR_101010x_SkColorType:
+ case kBGRA_1010102_SkColorType: blitter->fDitherRate = 1/1023.0f; break;
+
+ case kUnknown_SkColorType:
+ case kAlpha_8_SkColorType:
+ case kRGBA_F16_SkColorType:
+ case kRGBA_F16Norm_SkColorType:
+ case kRGBA_F32_SkColorType:
+ case kR8G8_unorm_SkColorType:
+ case kA16_float_SkColorType:
+ case kA16_unorm_SkColorType:
+ case kR16G16_float_SkColorType:
+ case kR16G16_unorm_SkColorType:
+ case kR16G16B16A16_unorm_SkColorType: blitter->fDitherRate = 0.0f; break;
+ }
+ if (blitter->fDitherRate > 0.0f) {
+ colorPipeline->append(SkRasterPipeline::dither, &blitter->fDitherRate);
+ }
+ }
+#endif
// We're logically done here. The code between here and return blitter is all optimization.
@@ -303,9 +332,11 @@ void SkRasterPipelineBlitter::append_store(SkRasterPipeline* p) const {
if (fDst.info().alphaType() == kUnpremul_SkAlphaType) {
p->append(SkRasterPipeline::unpremul);
}
+#if defined(SK_LATE_DITHER)
if (fDitherRate > 0.0f) {
p->append(SkRasterPipeline::dither, &fDitherRate);
}
+#endif
p->append_store(fDst.info().colorType(), &fDstPtr);
}
diff --git a/chromium/third_party/skia/src/core/SkReadBuffer.cpp b/chromium/third_party/skia/src/core/SkReadBuffer.cpp
index c7e26df8d4d..61867776ca5 100644
--- a/chromium/third_party/skia/src/core/SkReadBuffer.cpp
+++ b/chromium/third_party/skia/src/core/SkReadBuffer.cpp
@@ -17,8 +17,6 @@
#include "src/core/SkReadBuffer.h"
#include "src/core/SkSafeMath.h"
-#ifndef SK_DISABLE_READBUFFER
-
namespace {
// This generator intentionally should always fail on all attempts to get its pixels,
// simulating a bad or empty codec stream.
@@ -37,38 +35,18 @@ namespace {
} // anonymous namespace
-
-SkReadBuffer::SkReadBuffer() {
- fVersion = 0;
-
- fTFArray = nullptr;
- fTFCount = 0;
-
- fFactoryArray = nullptr;
- fFactoryCount = 0;
-}
-
-SkReadBuffer::SkReadBuffer(const void* data, size_t size) {
- fVersion = 0;
- this->setMemory(data, size);
-
- fTFArray = nullptr;
- fTFCount = 0;
-
- fFactoryArray = nullptr;
- fFactoryCount = 0;
-}
-
void SkReadBuffer::setMemory(const void* data, size_t size) {
this->validate(IsPtrAlign4(data) && (SkAlign4(size) == size));
if (!fError) {
- fReader.setMemory(data, size);
+ fBase = fCurr = (const char*)data;
+ fStop = fBase + size;
}
}
+
void SkReadBuffer::setInvalid() {
if (!fError) {
// When an error is found, send the read cursor to the end of the stream
- fReader.skip(fReader.available());
+ fCurr = fStop;
fError = true;
}
}
@@ -76,13 +54,13 @@ void SkReadBuffer::setInvalid() {
const void* SkReadBuffer::skip(size_t size) {
size_t inc = SkAlign4(size);
this->validate(inc >= size);
- const void* addr = fReader.peek();
- this->validate(IsPtrAlign4(addr) && fReader.isAvailable(inc));
+ const void* addr = fCurr;
+ this->validate(IsPtrAlign4(addr) && this->isAvailable(inc));
if (fError) {
return nullptr;
}
- fReader.skip(size);
+ fCurr += inc;
return addr;
}
@@ -107,14 +85,22 @@ SkColor SkReadBuffer::readColor() {
int32_t SkReadBuffer::readInt() {
const size_t inc = sizeof(int32_t);
- this->validate(IsPtrAlign4(fReader.peek()) && fReader.isAvailable(inc));
- return fError ? 0 : fReader.readInt();
+ if (!this->validate(IsPtrAlign4(fCurr) && this->isAvailable(inc))) {
+ return 0;
+ }
+ int32_t value = *((const int32_t*)fCurr);
+ fCurr += inc;
+ return value;
}
SkScalar SkReadBuffer::readScalar() {
const size_t inc = sizeof(SkScalar);
- this->validate(IsPtrAlign4(fReader.peek()) && fReader.isAvailable(inc));
- return fError ? 0 : fReader.readScalar();
+ if (!this->validate(IsPtrAlign4(fCurr) && this->isAvailable(inc))) {
+ return 0;
+ }
+ SkScalar value = *((const SkScalar*)fCurr);
+ fCurr += inc;
+ return value;
}
uint32_t SkReadBuffer::readUInt() {
@@ -126,11 +112,11 @@ int32_t SkReadBuffer::read32() {
}
uint8_t SkReadBuffer::peekByte() {
- if (fReader.available() <= 0) {
+ if (this->available() <= 0) {
fError = true;
return 0;
}
- return *((uint8_t*) fReader.peek());
+ return *((uint8_t*)fCurr);
}
bool SkReadBuffer::readPad32(void* buffer, size_t bytes) {
@@ -182,7 +168,7 @@ void SkReadBuffer::readPoint3(SkPoint3* point) {
void SkReadBuffer::readMatrix(SkMatrix* matrix) {
size_t size = 0;
if (this->isValid()) {
- size = SkMatrixPriv::ReadFromMemory(matrix, fReader.peek(), fReader.available());
+ size = SkMatrixPriv::ReadFromMemory(matrix, fCurr, this->available());
(void)this->validate((SkAlign4(size) == size) && (0 != size));
}
if (!this->isValid()) {
@@ -204,15 +190,20 @@ void SkReadBuffer::readRect(SkRect* rect) {
}
void SkReadBuffer::readRRect(SkRRect* rrect) {
- if (!this->validate(fReader.readRRect(rrect))) {
- rrect->setEmpty();
+ size_t size = 0;
+ if (!fError) {
+ size = rrect->readFromMemory(fCurr, this->available());
+ if (!this->validate((SkAlign4(size) == size) && (0 != size))) {
+ rrect->setEmpty();
+ }
}
+ (void)this->skip(size);
}
void SkReadBuffer::readRegion(SkRegion* region) {
size_t size = 0;
if (!fError) {
- size = region->readFromMemory(fReader.peek(), fReader.available());
+ size = region->readFromMemory(fCurr, this->available());
if (!this->validate((SkAlign4(size) == size) && (0 != size))) {
region->setEmpty();
}
@@ -223,7 +214,7 @@ void SkReadBuffer::readRegion(SkRegion* region) {
void SkReadBuffer::readPath(SkPath* path) {
size_t size = 0;
if (!fError) {
- size = path->readFromMemory(fReader.peek(), fReader.available());
+ size = path->readFromMemory(fCurr, this->available());
if (!this->validate((SkAlign4(size) == size) && (0 != size))) {
path->reset();
}
@@ -261,9 +252,18 @@ bool SkReadBuffer::readScalarArray(SkScalar* values, size_t size) {
return this->readArray(values, size, sizeof(SkScalar));
}
+const void* SkReadBuffer::skipByteArray(size_t* size) {
+ const uint32_t count = this->readUInt();
+ const void* buf = this->skip(count);
+ if (size) {
+ *size = this->isValid() ? count : 0;
+ }
+ return buf;
+}
+
sk_sp<SkData> SkReadBuffer::readByteArrayAsData() {
size_t numBytes = this->getArrayCount();
- if (!this->validate(fReader.isAvailable(numBytes))) {
+ if (!this->validate(this->isAvailable(numBytes))) {
return nullptr;
}
@@ -276,8 +276,10 @@ sk_sp<SkData> SkReadBuffer::readByteArrayAsData() {
uint32_t SkReadBuffer::getArrayCount() {
const size_t inc = sizeof(uint32_t);
- fError = fError || !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc);
- return fError ? 0 : *(uint32_t*)fReader.peek();
+ if (!this->validate(IsPtrAlign4(fCurr) && this->isAvailable(inc))) {
+ return 0;
+ }
+ return *((uint32_t*)fCurr);
}
/* Format:
@@ -424,10 +426,10 @@ SkFlattenable* SkReadBuffer::readFlattenable(SkFlattenable::Type ft) {
sk_sp<SkFlattenable> obj;
uint32_t sizeRecorded = this->read32();
if (factory) {
- size_t offset = fReader.offset();
+ size_t offset = this->offset();
obj = (*factory)(*this);
// check that we read the amount we expected
- size_t sizeRead = fReader.offset() - offset;
+ size_t sizeRead = this->offset() - offset;
if (sizeRecorded != sizeRead) {
this->validate(false);
return nullptr;
@@ -438,7 +440,7 @@ SkFlattenable* SkReadBuffer::readFlattenable(SkFlattenable::Type ft) {
}
} else {
// we must skip the remaining data
- fReader.skip(sizeRecorded);
+ this->skip(sizeRecorded);
}
if (!this->isValid()) {
return nullptr;
@@ -461,5 +463,3 @@ int32_t SkReadBuffer::checkInt(int32_t min, int32_t max) {
SkFilterQuality SkReadBuffer::checkFilterQuality() {
return this->checkRange<SkFilterQuality>(kNone_SkFilterQuality, kLast_SkFilterQuality);
}
-
-#endif // #ifndef SK_DISABLE_READBUFFER
diff --git a/chromium/third_party/skia/src/core/SkReadBuffer.h b/chromium/third_party/skia/src/core/SkReadBuffer.h
index 0bc91a09e0a..59be7fc70dc 100644
--- a/chromium/third_party/skia/src/core/SkReadBuffer.h
+++ b/chromium/third_party/skia/src/core/SkReadBuffer.h
@@ -8,7 +8,6 @@
#ifndef SkReadBuffer_DEFINED
#define SkReadBuffer_DEFINED
-#include "include/core/SkColorFilter.h"
#include "include/core/SkDrawLooper.h"
#include "include/core/SkFont.h"
#include "include/core/SkImageFilter.h"
@@ -16,23 +15,26 @@
#include "include/core/SkPathEffect.h"
#include "include/core/SkPicture.h"
#include "include/core/SkRefCnt.h"
+#include "include/core/SkScalar.h"
#include "include/core/SkSerialProcs.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/core/SkMaskFilterBase.h"
#include "src/core/SkPaintPriv.h"
#include "src/core/SkPicturePriv.h"
-#include "src/core/SkReader32.h"
#include "src/core/SkWriteBuffer.h"
#include "src/shaders/SkShaderBase.h"
class SkData;
class SkImage;
-#ifndef SK_DISABLE_READBUFFER
-
class SkReadBuffer {
public:
- SkReadBuffer();
- SkReadBuffer(const void* data, size_t size);
+ SkReadBuffer() = default;
+ SkReadBuffer(const void* data, size_t size) {
+ this->setMemory(data, size);
+ }
+
+ void setMemory(const void*, size_t);
/**
* Returns true IFF the version is older than the specified version.
@@ -50,12 +52,12 @@ public:
fVersion = version;
}
- size_t size() const { return fReader.size(); }
- size_t offset() const { return fReader.offset(); }
- bool eof() { return fReader.eof(); }
+ size_t size() const { return fStop - fBase; }
+ size_t offset() const { return fCurr - fBase; }
+ bool eof() { return fCurr >= fStop; }
const void* skip(size_t size);
const void* skip(size_t count, size_t size); // does safe multiply
- size_t available() const { return fReader.available(); }
+ size_t available() const { return fStop - fCurr; }
template <typename T> const T* skipT() {
return static_cast<const T*>(this->skip(sizeof(T)));
@@ -106,7 +108,7 @@ public:
template <typename T> sk_sp<T> readFlattenable() {
return sk_sp<T>((T*)this->readFlattenable(T::GetFlattenableType()));
}
- sk_sp<SkColorFilter> readColorFilter() { return this->readFlattenable<SkColorFilter>(); }
+ sk_sp<SkColorFilter> readColorFilter() { return this->readFlattenable<SkColorFilterBase>(); }
sk_sp<SkDrawLooper> readDrawLooper() { return this->readFlattenable<SkDrawLooper>(); }
sk_sp<SkImageFilter> readImageFilter() { return this->readFlattenable<SkImageFilter>(); }
sk_sp<SkMaskFilter> readMaskFilter() { return this->readFlattenable<SkMaskFilterBase>(); }
@@ -124,6 +126,8 @@ public:
bool readPointArray(SkPoint* points, size_t size);
bool readScalarArray(SkScalar* values, size_t size);
+ const void* skipByteArray(size_t* size);
+
sk_sp<SkData> readByteArrayAsData();
// helpers to get info about arrays and binary data
@@ -170,7 +174,7 @@ public:
*/
template <typename T>
bool validateCanReadN(size_t n) {
- return this->validate(n <= (fReader.available() / sizeof(T)));
+ return this->validate(n <= (this->available() / sizeof(T)));
}
bool isValid() const { return !fError; }
@@ -196,20 +200,23 @@ private:
void setInvalid();
bool readArray(void* value, size_t size, size_t elementSize);
- void setMemory(const void*, size_t);
+ bool isAvailable(size_t size) const { return size <= this->available(); }
- SkReader32 fReader;
+ // These are always 4-byte aligned
+ const char* fCurr = nullptr; // current position within buffer
+ const char* fStop = nullptr; // end of buffer
+ const char* fBase = nullptr; // beginning of buffer
// Only used if we do not have an fFactoryArray.
SkTHashMap<uint32_t, SkFlattenable::Factory> fFlattenableDict;
- int fVersion;
+ int fVersion = 0;
- sk_sp<SkTypeface>* fTFArray;
- int fTFCount;
+ sk_sp<SkTypeface>* fTFArray = nullptr;
+ int fTFCount = 0;
- SkFlattenable::Factory* fFactoryArray;
- int fFactoryCount;
+ SkFlattenable::Factory* fFactoryArray = nullptr;
+ int fFactoryCount = 0;
SkDeserialProcs fProcs;
@@ -220,102 +227,4 @@ private:
bool fError = false;
};
-#else // #ifndef SK_DISABLE_READBUFFER
-
-class SkReadBuffer {
-public:
- SkReadBuffer() {}
- SkReadBuffer(const void*, size_t) {}
-
- bool isVersionLT(SkPicturePriv::Version) const { return false; }
- uint32_t getVersion() const { return 0xffffffff; }
- void setVersion(int) {}
-
- size_t size() const { return 0; }
- size_t offset() const { return 0; }
- bool eof() { return true; }
- size_t available() const { return 0; }
-
- const void* skip(size_t) { return nullptr; }
- const void* skip(size_t, size_t) { return nullptr; }
- template <typename T> const T* skipT() { return nullptr; }
- template <typename T> const T* skipT(size_t) { return nullptr; }
-
- bool readBool() { return 0; }
- SkColor readColor() { return 0; }
- int32_t readInt() { return 0; }
- SkScalar readScalar() { return 0; }
- uint32_t readUInt() { return 0; }
- int32_t read32() { return 0; }
-
- template <typename T> T read32LE(T max) { return max; }
-
- uint8_t peekByte() { return 0; }
-
- void readColor4f(SkColor4f* out) { *out = SkColor4f{0,0,0,0}; }
- void readPoint (SkPoint* out) { *out = SkPoint{0,0}; }
- void readPoint3 (SkPoint3* out) { *out = SkPoint3{0,0,0}; }
- void readMatrix (SkMatrix* out) { *out = SkMatrix::I(); }
- void readIRect (SkIRect* out) { *out = SkIRect{0,0,0,0}; }
- void readRect (SkRect* out) { *out = SkRect{0,0,0,0}; }
- void readRRect (SkRRect* out) { *out = SkRRect(); }
- void readRegion (SkRegion* out) { *out = SkRegion(); }
- void readString (SkString* out) { *out = SkString(); }
- void readPath (SkPath* out) { *out = SkPath(); }
- SkReadPaintResult readPaint (SkPaint* out, SkFont* font) {
- *out = SkPaint();
- if (font) {
- *font = SkFont();
- }
- return kFailed_ReadPaint;
- }
-
- SkPoint readPoint() { return {0,0}; }
-
- SkFlattenable* readFlattenable(SkFlattenable::Type) { return nullptr; }
-
- template <typename T> sk_sp<T> readFlattenable() { return nullptr; }
- sk_sp<SkColorFilter> readColorFilter() { return nullptr; }
- sk_sp<SkDrawLooper> readDrawLooper() { return nullptr; }
- sk_sp<SkImageFilter> readImageFilter() { return nullptr; }
- sk_sp<SkMaskFilter> readMaskFilter() { return nullptr; }
- sk_sp<SkPathEffect> readPathEffect() { return nullptr; }
- sk_sp<SkShader> readShader() { return nullptr; }
-
- bool readPad32 (void*, size_t) { return false; }
- bool readByteArray (void*, size_t) { return false; }
- bool readColorArray (SkColor*, size_t) { return false; }
- bool readColor4fArray(SkColor4f*, size_t) { return false; }
- bool readIntArray (int32_t*, size_t) { return false; }
- bool readPointArray (SkPoint*, size_t) { return false; }
- bool readScalarArray (SkScalar*, size_t) { return false; }
-
- sk_sp<SkData> readByteArrayAsData() { return nullptr; }
- uint32_t getArrayCount() { return 0; }
-
- sk_sp<SkImage> readImage() { return nullptr; }
- sk_sp<SkTypeface> readTypeface() { return nullptr; }
-
- bool validate(bool) { return false; }
- template <typename T> bool validateCanReadN(size_t) { return false; }
- bool isValid() const { return false; }
- bool validateIndex(int, int) { return false; }
-
- int32_t checkInt(int min, int) { return min; }
- template <typename T> T checkRange(T min, T) { return min; }
-
- SkFilterQuality checkFilterQuality() { return SkFilterQuality::kNone_SkFilterQuality; }
-
- void setTypefaceArray(sk_sp<SkTypeface>[], int) {}
- void setFactoryPlayback(SkFlattenable::Factory[], int) {}
- void setDeserialProcs(const SkDeserialProcs&) {}
-
- const SkDeserialProcs& getDeserialProcs() const {
- static const SkDeserialProcs procs;
- return procs;
- }
-};
-
-#endif // #ifndef SK_DISABLE_READBUFFER
-
#endif // SkReadBuffer_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkReader32.h b/chromium/third_party/skia/src/core/SkReader32.h
deleted file mode 100644
index ff2b820de6d..00000000000
--- a/chromium/third_party/skia/src/core/SkReader32.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright 2008 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#ifndef SkReader32_DEFINED
-#define SkReader32_DEFINED
-
-#include "include/core/SkData.h"
-#include "include/core/SkMatrix.h"
-#include "include/core/SkPath.h"
-#include "include/core/SkRRect.h"
-#include "include/core/SkRegion.h"
-#include "include/core/SkScalar.h"
-#include "include/private/SkNoncopyable.h"
-
-class SkString;
-
-class SkReader32 : SkNoncopyable {
-public:
- SkReader32() : fCurr(nullptr), fStop(nullptr), fBase(nullptr) {}
- SkReader32(const void* data, size_t size) {
- this->setMemory(data, size);
- }
-
- void setMemory(const void* data, size_t size) {
- SkASSERT(ptr_align_4(data));
- SkASSERT(SkAlign4(size) == size);
-
- fBase = fCurr = (const char*)data;
- fStop = (const char*)data + size;
- }
-
- size_t size() const { return fStop - fBase; }
- size_t offset() const { return fCurr - fBase; }
- bool eof() const { return fCurr >= fStop; }
- const void* base() const { return fBase; }
- const void* peek() const { return fCurr; }
-
- size_t available() const { return fStop - fCurr; }
- bool isAvailable(size_t size) const { return size <= this->available(); }
-
- void rewind() { fCurr = fBase; }
-
- void setOffset(size_t offset) {
- SkASSERT(SkAlign4(offset) == offset);
- SkASSERT(offset <= this->size());
- fCurr = fBase + offset;
- }
-
- bool readBool() { return this->readInt() != 0; }
-
- int32_t readInt() {
- SkASSERT(ptr_align_4(fCurr));
- int32_t value = *(const int32_t*)fCurr;
- fCurr += sizeof(value);
- SkASSERT(fCurr <= fStop);
- return value;
- }
-
- void* readPtr() {
- void* ptr;
- // we presume this "if" is resolved at compile-time
- if (4 == sizeof(void*)) {
- ptr = *(void**)fCurr;
- } else {
- memcpy(&ptr, fCurr, sizeof(void*));
- }
- fCurr += sizeof(void*);
- return ptr;
- }
-
- SkScalar readScalar() {
- SkASSERT(ptr_align_4(fCurr));
- SkScalar value = *(const SkScalar*)fCurr;
- fCurr += sizeof(value);
- SkASSERT(fCurr <= fStop);
- return value;
- }
-
- const void* skip(size_t size) {
- SkASSERT(ptr_align_4(fCurr));
- const void* addr = fCurr;
- fCurr += SkAlign4(size);
- SkASSERT(fCurr <= fStop);
- return addr;
- }
-
- template <typename T> const T& skipT() {
- SkASSERT(SkAlign4(sizeof(T)) == sizeof(T));
- return *(const T*)this->skip(sizeof(T));
- }
-
- void read(void* dst, size_t size) {
- SkASSERT(0 == size || dst != nullptr);
- SkASSERT(ptr_align_4(fCurr));
- sk_careful_memcpy(dst, fCurr, size);
- fCurr += SkAlign4(size);
- SkASSERT(fCurr <= fStop);
- }
-
- uint8_t readU8() { return (uint8_t)this->readInt(); }
- uint16_t readU16() { return (uint16_t)this->readInt(); }
- int32_t readS32() { return this->readInt(); }
- uint32_t readU32() { return this->readInt(); }
-
- bool readPath(SkPath* path) {
- return this->readObjectFromMemory(path);
- }
-
- bool readMatrix(SkMatrix* matrix) {
- return this->readObjectFromMemory(matrix);
- }
-
- bool readRRect(SkRRect* rrect) {
- return this->readObjectFromMemory(rrect);
- }
-
- bool readRegion(SkRegion* rgn) {
- return this->readObjectFromMemory(rgn);
- }
-
- /**
- * Read the length of a string (written by SkWriter32::writeString) into
- * len (if len is not nullptr) and return the null-ternimated address of the
- * string within the reader's buffer.
- */
- const char* readString(size_t* len = nullptr);
-
- /**
- * Read the string (written by SkWriter32::writeString) and return it in
- * copy (if copy is not null). Return the length of the string.
- */
- size_t readIntoString(SkString* copy);
-
- sk_sp<SkData> readData() {
- uint32_t byteLength = this->readU32();
- if (0 == byteLength) {
- return SkData::MakeEmpty();
- }
- return SkData::MakeWithCopy(this->skip(byteLength), byteLength);
- }
-
-private:
- template <typename T> bool readObjectFromMemory(T* obj) {
- size_t size = obj->readFromMemory(this->peek(), this->available());
- // If readFromMemory() fails (which means that available() was too small), it returns 0
- bool success = (size > 0) && (size <= this->available()) && (SkAlign4(size) == size);
- // In case of failure, we want to skip to the end
- (void)this->skip(success ? size : this->available());
- return success;
- }
-
- // these are always 4-byte aligned
- const char* fCurr; // current position within buffer
- const char* fStop; // end of buffer
- const char* fBase; // beginning of buffer
-
-#ifdef SK_DEBUG
- static bool ptr_align_4(const void* ptr) {
- return (((const char*)ptr - (const char*)nullptr) & 3) == 0;
- }
-#endif
-};
-
-#endif
diff --git a/chromium/third_party/skia/src/core/SkRecord.h b/chromium/third_party/skia/src/core/SkRecord.h
index 37cc0583b31..10a385fdf1e 100644
--- a/chromium/third_party/skia/src/core/SkRecord.h
+++ b/chromium/third_party/skia/src/core/SkRecord.h
@@ -85,19 +85,6 @@ public:
return fRecords[i].set(this->allocCommand<T>());
}
- // Replace the i-th command with a new command of type T.
- // You are expected to placement new an object of type T onto this pointer.
- // You must show proof that you've already adopted the existing command.
- template <typename T, typename Existing>
- T* replace(int i, const SkRecords::Adopted<Existing>& proofOfAdoption) {
- SkASSERT(i < this->count());
-
- SkASSERT(Existing::kType == fRecords[i].type());
- SkASSERT(proofOfAdoption == fRecords[i].ptr());
-
- return fRecords[i].set(this->allocCommand<T>());
- }
-
// Does not return the bytes in any pointers embedded in the Records; callers
// need to iterate with a visitor to measure those they care for.
size_t bytesUsed() const;
diff --git a/chromium/third_party/skia/src/core/SkRecordDraw.cpp b/chromium/third_party/skia/src/core/SkRecordDraw.cpp
index a8d88dbc985..9a638471c8c 100644
--- a/chromium/third_party/skia/src/core/SkRecordDraw.cpp
+++ b/chromium/third_party/skia/src/core/SkRecordDraw.cpp
@@ -81,8 +81,6 @@ DRAW(Save, save());
DRAW(SaveLayer, saveLayer(SkCanvas::SaveLayerRec(r.bounds,
r.paint,
r.backdrop.get(),
- r.clipMask.get(),
- r.clipMatrix,
r.saveLayerFlags)));
template <> void Draw::draw(const SaveBehind& r) {
diff --git a/chromium/third_party/skia/src/core/SkRecordOpts.cpp b/chromium/third_party/skia/src/core/SkRecordOpts.cpp
index 127a9a861ee..45d5de3b58f 100644
--- a/chromium/third_party/skia/src/core/SkRecordOpts.cpp
+++ b/chromium/third_party/skia/src/core/SkRecordOpts.cpp
@@ -185,8 +185,8 @@ struct SaveLayerDrawRestoreNooper {
typedef Pattern<Is<SaveLayer>, IsDraw, Is<Restore>> Match;
bool onMatch(SkRecord* record, Match* match, int begin, int end) {
- if (match->first<SaveLayer>()->backdrop || match->first<SaveLayer>()->clipMask) {
- // can't throw away the layer if we have a backdrop or clip mask
+ if (match->first<SaveLayer>()->backdrop) {
+ // can't throw away the layer if we have a backdrop
return false;
}
diff --git a/chromium/third_party/skia/src/core/SkRecorder.cpp b/chromium/third_party/skia/src/core/SkRecorder.cpp
index b11bd1ae4b1..4ff6c1a3201 100644
--- a/chromium/third_party/skia/src/core/SkRecorder.cpp
+++ b/chromium/third_party/skia/src/core/SkRecorder.cpp
@@ -316,8 +316,6 @@ SkCanvas::SaveLayerStrategy SkRecorder::getSaveLayerStrategy(const SaveLayerRec&
this->append<SkRecords::SaveLayer>(this->copy(rec.fBounds)
, this->copy(rec.fPaint)
, sk_ref_sp(rec.fBackdrop)
- , sk_ref_sp(rec.fClipMask)
- , this->copy(rec.fClipMatrix)
, rec.fSaveLayerFlags);
return SkCanvas::kNoLayer_SaveLayerStrategy;
}
diff --git a/chromium/third_party/skia/src/core/SkRecords.h b/chromium/third_party/skia/src/core/SkRecords.h
index 8d89252e4b8..f44de620a7d 100644
--- a/chromium/third_party/skia/src/core/SkRecords.h
+++ b/chromium/third_party/skia/src/core/SkRecords.h
@@ -109,25 +109,6 @@ private:
Optional& operator=(const Optional&) = delete;
};
-// Like Optional, but ptr must not be NULL.
-template <typename T>
-class Adopted {
-public:
- Adopted(T* ptr) : fPtr(ptr) { SkASSERT(fPtr); }
- Adopted(Adopted* source) {
- // Transfer ownership from source to this.
- fPtr = source->fPtr;
- source->fPtr = NULL;
- }
- ~Adopted() { if (fPtr) fPtr->~T(); }
-
- ACT_AS_PTR(fPtr)
-private:
- T* fPtr;
- Adopted(const Adopted&) = delete;
- Adopted& operator=(const Adopted&) = delete;
-};
-
// PODArray doesn't own the pointer's memory, and we assume the data is POD.
template <typename T>
class PODArray {
@@ -185,8 +166,6 @@ RECORD(SaveLayer, kHasPaint_Tag,
Optional<SkRect> bounds;
Optional<SkPaint> paint;
sk_sp<const SkImageFilter> backdrop;
- sk_sp<const SkImage> clipMask;
- Optional<SkMatrix> clipMatrix;
SkCanvas::SaveLayerFlags saveLayerFlags);
RECORD(SaveBehind, 0,
@@ -299,7 +278,7 @@ RECORD(DrawPoints, kDraw_Tag|kHasPaint_Tag,
SkPaint paint;
SkCanvas::PointMode mode;
unsigned count;
- SkPoint* pts);
+ PODArray<SkPoint> pts);
RECORD(DrawRRect, kDraw_Tag|kHasPaint_Tag,
SkPaint paint;
SkRRect rrect);
diff --git a/chromium/third_party/skia/src/core/SkRemoteGlyphCache.cpp b/chromium/third_party/skia/src/core/SkRemoteGlyphCache.cpp
index d25a6c3daa7..ae4a83a3ccf 100644
--- a/chromium/third_party/skia/src/core/SkRemoteGlyphCache.cpp
+++ b/chromium/third_party/skia/src/core/SkRemoteGlyphCache.cpp
@@ -28,8 +28,9 @@
#include "src/core/SkZip.h"
#if SK_SUPPORT_GPU
+#include "include/gpu/GrContextOptions.h"
#include "src/gpu/GrDrawOpAtlas.h"
-#include "src/gpu/text/GrTextContext.h"
+#include "src/gpu/text/GrSDFTOptions.h"
#endif
static SkDescriptor* auto_descriptor_from_desc(const SkDescriptor* source_desc,
@@ -392,8 +393,9 @@ public:
protected:
void drawGlyphRunList(const SkGlyphRunList& glyphRunList) override {
#if SK_SUPPORT_GPU
- GrTextContext::Options options;
- GrTextContext::SanitizeOptions(&options);
+ GrContextOptions ctxOptions;
+ GrSDFTOptions options =
+ {ctxOptions.fMinDistanceFieldFontSize, ctxOptions.fGlyphsAsPathsFontSize};
#ifdef SK_CAPTURE_DRAW_TEXT_BLOB
if (SkTextBlobTrace::Capture* capture = fStrikeServer->fCapture.get()) {
diff --git a/chromium/third_party/skia/src/core/SkRuntimeEffect.cpp b/chromium/third_party/skia/src/core/SkRuntimeEffect.cpp
index ac5652bec4f..fb8d40e5c8f 100644
--- a/chromium/third_party/skia/src/core/SkRuntimeEffect.cpp
+++ b/chromium/third_party/skia/src/core/SkRuntimeEffect.cpp
@@ -11,6 +11,7 @@
#include "include/private/SkChecksum.h"
#include "include/private/SkMutex.h"
#include "src/core/SkCanvasPriv.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkColorSpaceXformSteps.h"
#include "src/core/SkMatrixProvider.h"
@@ -28,8 +29,8 @@
#include "include/private/GrRecordingContext.h"
#include "src/gpu/GrColorInfo.h"
#include "src/gpu/GrFPArgs.h"
+#include "src/gpu/effects/GrMatrixEffect.h"
#include "src/gpu/effects/GrSkSLFP.h"
-#include "src/gpu/effects/generated/GrMatrixEffect.h"
#endif
#include <algorithm>
@@ -411,7 +412,13 @@ SkRuntimeEffect::ByteCodeResult SkRuntimeEffect::toByteCode(const void* inputs)
static std::vector<skvm::F32> program_fn(skvm::Builder* p,
const SkSL::ByteCodeFunction& fn,
const std::vector<skvm::F32>& uniform,
- std::vector<skvm::F32> stack) {
+ const SkMatrixProvider& matrices,
+ std::vector<skvm::F32> stack,
+ /*these parameters are used to call program() on children*/
+ const std::vector<sk_sp<SkShader>>& children,
+ skvm::Coord device, skvm::Color paint,
+ SkFilterQuality quality, const SkColorInfo& dst,
+ skvm::Uniforms* uniforms, SkArenaAlloc* alloc) {
auto push = [&](skvm::F32 x) { stack.push_back(x); };
auto pop = [&]{ skvm::F32 x = stack.back(); stack.pop_back(); return x; };
@@ -466,6 +473,30 @@ static std::vector<skvm::F32> program_fn(skvm::Builder* p,
#endif
return {};
+ // TODO: Inst::kSampleMatrix, should look much like kSampleExplicit.
+
+ case Inst::kSampleExplicit: {
+ // Child shader to run.
+ int ix = u8();
+
+ // Stack contains x,y to sample at.
+ skvm::F32 y = pop(),
+ x = pop();
+
+ SkOverrideDeviceMatrixProvider mats{matrices, SkMatrix::I()};
+ skvm::Color c = as_SB(children[ix])->program(p, device, {x,y},paint,
+ mats, nullptr,
+ quality, dst,
+ uniforms, alloc);
+ if (!c) {
+ return {};
+ }
+ push(c.r);
+ push(c.g);
+ push(c.b);
+ push(c.a);
+ } break;
+
case Inst::kLoad: {
int ix = u8();
push(stack[ix + 0]);
@@ -518,6 +549,14 @@ static std::vector<skvm::F32> program_fn(skvm::Builder* p,
push(uniform[ix + 3]);
} break;
+ case Inst::kLoadFragCoord: {
+ // TODO: Actually supply Z and 1/W from the rasterizer?
+ push(device.x);
+ push(device.y);
+ push(p->splat(0.0f)); // Z
+ push(p->splat(1.0f)); // 1/W
+ } break;
+
case Inst::kStore: {
int ix = u8();
stack[ix + 0] = pop();
@@ -571,6 +610,16 @@ static std::vector<skvm::F32> program_fn(skvm::Builder* p,
push(stack[stack.size() - 4]);
} break;
+ case Inst::kSwizzle: {
+ skvm::F32 tmp[4];
+ for (int i = u8(); i --> 0;) {
+ tmp[i] = pop();
+ }
+ for (int i = u8(); i --> 0;) {
+ push(tmp[u8()]);
+ }
+ } break;
+
case Inst::kAddF:
case Inst::kAddF2:
case Inst::kAddF3:
@@ -591,11 +640,65 @@ static std::vector<skvm::F32> program_fn(skvm::Builder* p,
case Inst::kDivideF3:
case Inst::kDivideF4: binary(Inst::kDivideF, std::divides<>{}); break;
+ case Inst::kMinF:
+ case Inst::kMinF2:
+ case Inst::kMinF3:
+ case Inst::kMinF4:
+ binary(Inst::kMinF, [](skvm::F32 x, skvm::F32 y) { return skvm::min(x,y); });
+ break;
+
+ case Inst::kMaxF:
+ case Inst::kMaxF2:
+ case Inst::kMaxF3:
+ case Inst::kMaxF4:
+ binary(Inst::kMaxF, [](skvm::F32 x, skvm::F32 y) { return skvm::max(x,y); });
+ break;
+
+ case Inst::kNegateF:
+ case Inst::kNegateF2:
+ case Inst::kNegateF3:
+ case Inst::kNegateF4: unary(Inst::kNegateF, std::negate<>{}); break;
+
+ case Inst::kPow:
+ case Inst::kPow2:
+ case Inst::kPow3:
+ case Inst::kPow4:
+ binary(Inst::kPow, [](skvm::F32 x, skvm::F32 y) { return skvm::approx_powf(x,y); });
+ break;
+
+ case Inst::kLerp:
+ case Inst::kLerp2:
+ case Inst::kLerp3:
+ case Inst::kLerp4: {
+ int N = (int)Inst::kLerp - (int)inst + 1;
+
+ skvm::F32 t[4],
+ b[4],
+ a[4];
+ for (int i = N; i --> 0; ) { t[i] = pop(); }
+ for (int i = N; i --> 0; ) { b[i] = pop(); }
+ for (int i = N; i --> 0; ) { a[i] = pop(); }
+
+ for (int i = 0; i < N; i++) {
+ push(skvm::lerp(a[i], b[i], t[i]));
+ }
+ } break;
+
case Inst::kATan:
case Inst::kATan2:
case Inst::kATan3:
case Inst::kATan4: unary(Inst::kATan, skvm::approx_atan); break;
+ case Inst::kCeil:
+ case Inst::kCeil2:
+ case Inst::kCeil3:
+ case Inst::kCeil4: unary(Inst::kCeil, skvm::ceil); break;
+
+ case Inst::kFloor:
+ case Inst::kFloor2:
+ case Inst::kFloor3:
+ case Inst::kFloor4: unary(Inst::kFloor, skvm::floor); break;
+
case Inst::kFract:
case Inst::kFract2:
case Inst::kFract3:
@@ -611,6 +714,27 @@ static std::vector<skvm::F32> program_fn(skvm::Builder* p,
case Inst::kSin3:
case Inst::kSin4: unary(Inst::kSin, skvm::approx_sin); break;
+ case Inst::kMatrixMultiply: {
+ // Computes M = A*B (all stored column major)
+ int aCols = u8(),
+ aRows = u8(),
+ bCols = u8(),
+ bRows = aCols;
+ std::vector<skvm::F32> A(aCols*aRows),
+ B(bCols*bRows);
+ for (auto i = B.size(); i --> 0;) { B[i] = pop(); }
+ for (auto i = A.size(); i --> 0;) { A[i] = pop(); }
+
+ for (int c = 0; c < bCols; ++c)
+ for (int r = 0; r < aRows; ++r) {
+ skvm::F32 sum = p->splat(0.0f);
+ for (int j = 0; j < aCols; ++j) {
+ sum += A[j*aRows + r] * B[c*bRows + j];
+ }
+ push(sum);
+ }
+ } break;
+
// Baby steps... just leaving test conditions on the stack for now.
case Inst::kMaskPush: break;
case Inst::kMaskNegate: break;
@@ -647,27 +771,16 @@ static std::vector<skvm::F32> program_fn(skvm::Builder* p,
}
-class SkRuntimeColorFilter : public SkColorFilter {
+class SkRuntimeColorFilter : public SkColorFilterBase {
public:
- SkRuntimeColorFilter(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> inputs,
- sk_sp<SkColorFilter> children[], size_t childCount)
+ SkRuntimeColorFilter(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> inputs)
: fEffect(std::move(effect))
- , fInputs(std::move(inputs))
- , fChildren(children, children + childCount) {}
+ , fInputs(std::move(inputs)) {}
#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
GrRecordingContext* context, const GrColorInfo& colorInfo) const override {
- auto fp = GrSkSLFP::Make(context, fEffect, "Runtime_Color_Filter", fInputs);
- for (const auto& child : fChildren) {
- auto childFP = child ? child->asFragmentProcessor(context, colorInfo) : nullptr;
- if (!childFP) {
- // TODO: This is the case that should eventually mean "the original input color"
- return nullptr;
- }
- fp->addChild(std::move(childFP));
- }
- return std::move(fp);
+ return GrSkSLFP::Make(context, fEffect, "Runtime_Color_Filter", fInputs);
}
#endif
@@ -692,7 +805,7 @@ public:
ctx->shaderConvention = false;
ctx->byteCode = this->byteCode();
- if (!ctx->byteCode) {
+ if (!ctx->byteCode || !ctx->byteCode->canRun()) {
return false;
}
@@ -722,7 +835,9 @@ public:
}
std::vector<skvm::F32> stack =
- program_fn(p, *fn, uniform, {c.r, c.g, c.b, c.a});
+ program_fn(p, *fn, uniform, SkSimpleMatrixProvider{SkMatrix::I()}, {c.r, c.g, c.b, c.a},
+ /* the remaining parameters are for shaders only and won't be used here */
+ {},{},{},{},{},{},{});
if (stack.size() == 4) {
return {stack[0], stack[1], stack[2], stack[3]};
@@ -737,10 +852,6 @@ public:
} else {
buffer.writeByteArray(nullptr, 0);
}
- buffer.write32(fChildren.size());
- for (const auto& child : fChildren) {
- buffer.writeFlattenable(child.get());
- }
}
SK_FLATTENABLE_HOOKS(SkRuntimeColorFilter)
@@ -748,7 +859,6 @@ public:
private:
sk_sp<SkRuntimeEffect> fEffect;
sk_sp<SkData> fInputs;
- std::vector<sk_sp<SkColorFilter>> fChildren;
mutable SkMutex fByteCodeMutex;
mutable std::unique_ptr<SkSL::ByteCode> fByteCode;
@@ -765,19 +875,7 @@ sk_sp<SkFlattenable> SkRuntimeColorFilter::CreateProc(SkReadBuffer& buffer) {
return nullptr;
}
- size_t childCount = buffer.read32();
- if (childCount != effect->children().count()) {
- buffer.validate(false);
- return nullptr;
- }
-
- std::vector<sk_sp<SkColorFilter>> children;
- children.resize(childCount);
- for (size_t i = 0; i < children.size(); ++i) {
- children[i] = buffer.readColorFilter();
- }
-
- return effect->makeColorFilter(std::move(inputs), children.data(), children.size());
+ return effect->makeColorFilter(std::move(inputs));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -879,9 +977,7 @@ public:
fp->addChild(std::move(childFP));
}
std::unique_ptr<GrFragmentProcessor> result = std::move(fp);
- if (!matrix.isIdentity()) {
- result = GrMatrixEffect::Make(matrix, std::move(result));
- }
+ result = GrMatrixEffect::Make(matrix, std::move(result));
if (GrColorTypeClampType(args.fDstColorInfo->colorType()) != GrClampType::kNone) {
return GrFragmentProcessor::ClampPremulOutput(std::move(result));
} else {
@@ -920,7 +1016,7 @@ public:
ctx->shaderConvention = true;
ctx->byteCode = this->byteCode();
- if (!ctx->byteCode) {
+ if (!ctx->byteCode || !ctx->byteCode->canRun()) {
return false;
}
ctx->fn = ctx->byteCode->getFunction("main");
@@ -930,10 +1026,11 @@ public:
return true;
}
- skvm::Color onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
- SkFilterQuality, const SkColorInfo& dst,
- skvm::Uniforms* uniforms, SkArenaAlloc*) const override {
+ skvm::Color onProgram(skvm::Builder* p,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider& matrices, const SkMatrix* localM,
+ SkFilterQuality quality, const SkColorInfo& dst,
+ skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override {
const SkSL::ByteCode* bc = this->byteCode();
if (!bc) {
return {};
@@ -944,11 +1041,7 @@ public:
return {};
}
- // TODO: Eventually, plumb SkMatrixProvider here (instead of just ctm). For now, we will
- // simply fail if our effect requires any marked matrices (SkSimpleMatrixProvider always
- // returns false in getLocalToMarker).
- SkSimpleMatrixProvider matrixProvider(SkMatrix::I());
- sk_sp<SkData> inputs = this->getUniforms(matrixProvider, dst.colorSpace());
+ sk_sp<SkData> inputs = this->getUniforms(matrices, dst.colorSpace());
if (!inputs) {
return {};
}
@@ -961,13 +1054,16 @@ public:
}
SkMatrix inv;
- if (!this->computeTotalInverse(ctm, localM, &inv)) {
+ if (!this->computeTotalInverse(matrices.localToDevice(), localM, &inv)) {
return {};
}
- SkShaderBase::ApplyMatrix(p,inv, &x,&y,uniforms);
+ local = SkShaderBase::ApplyMatrix(p,inv,local,uniforms);
std::vector<skvm::F32> stack =
- program_fn(p, *fn, uniform, {x,y, paint.r, paint.g, paint.b, paint.a});
+ program_fn(p, *fn, uniform, matrices,
+ {local.x,local.y, paint.r, paint.g, paint.b, paint.a},
+ /*parameters for calling program() on children*/
+ fChildren, device,paint, quality,dst, uniforms,alloc);
if (stack.size() == 6) {
return {stack[2], stack[3], stack[4], stack[5]};
@@ -1069,22 +1165,18 @@ sk_sp<SkShader> SkRuntimeEffect::makeShader(sk_sp<SkData> inputs,
: nullptr;
}
-sk_sp<SkColorFilter> SkRuntimeEffect::makeColorFilter(sk_sp<SkData> inputs,
- sk_sp<SkColorFilter> children[],
- size_t childCount) {
+sk_sp<SkColorFilter> SkRuntimeEffect::makeColorFilter(sk_sp<SkData> inputs) {
+ if (!fChildren.empty()) {
+ return nullptr;
+ }
if (!inputs) {
inputs = SkData::MakeEmpty();
}
- return inputs && inputs->size() == this->inputSize() && childCount == fChildren.size()
- ? sk_sp<SkColorFilter>(new SkRuntimeColorFilter(sk_ref_sp(this), std::move(inputs),
- children, childCount))
+ return inputs->size() == this->inputSize()
+ ? sk_sp<SkColorFilter>(new SkRuntimeColorFilter(sk_ref_sp(this), std::move(inputs)))
: nullptr;
}
-sk_sp<SkColorFilter> SkRuntimeEffect::makeColorFilter(sk_sp<SkData> inputs) {
- return this->makeColorFilter(std::move(inputs), nullptr, 0);
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////////
void SkRuntimeEffect::RegisterFlattenables() {
diff --git a/chromium/third_party/skia/src/core/SkSpecialImage.cpp b/chromium/third_party/skia/src/core/SkSpecialImage.cpp
index 065d4fe542f..f434bd587b7 100644
--- a/chromium/third_party/skia/src/core/SkSpecialImage.cpp
+++ b/chromium/third_party/skia/src/core/SkSpecialImage.cpp
@@ -10,11 +10,9 @@
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkImage.h"
-#include "src/core/SkBitmapCache.h"
#include "src/core/SkSpecialSurface.h"
#include "src/core/SkSurfacePriv.h"
#include "src/image/SkImage_Base.h"
-#include <atomic>
#if SK_SUPPORT_GPU
#include "include/gpu/GrContext.h"
@@ -23,7 +21,6 @@
#include "src/gpu/GrImageInfo.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
-#include "src/gpu/GrSurfaceContext.h"
#include "src/gpu/GrTextureProxy.h"
#include "src/image/SkImage_Gpu.h"
#endif
@@ -88,52 +85,6 @@ SkSpecialImage::SkSpecialImage(const SkIRect& subset,
, fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID() : uniqueID) {
}
-sk_sp<SkSpecialImage> SkSpecialImage::makeTextureImage(GrRecordingContext* context) const {
-#if SK_SUPPORT_GPU
- if (!context) {
- return nullptr;
- }
- if (GrRecordingContext* curContext = as_SIB(this)->onGetContext()) {
- return curContext->priv().matches(context) ? sk_ref_sp(this) : nullptr;
- }
-
- SkBitmap bmp;
- // At this point, we are definitely not texture-backed, so we must be raster or generator
- // backed. If we remove the special-wrapping-an-image subclass, we may be able to assert that
- // we are strictly raster-backed (i.e. generator images become raster when they are specialized)
- // in which case getROPixels could turn into peekPixels...
- if (!this->getROPixels(&bmp)) {
- return nullptr;
- }
-
- if (bmp.empty()) {
- return SkSpecialImage::MakeFromRaster(SkIRect::MakeEmpty(), bmp, &this->props());
- }
-
- // TODO: this is a tight copy of 'bmp' but it doesn't have to be (given SkSpecialImage's
- // semantics). Since this is cached though we would have to bake the fit into the cache key.
- auto view = GrMakeCachedBitmapProxyView(context, bmp);
- if (!view.proxy()) {
- return nullptr;
- }
-
- const SkIRect rect = SkIRect::MakeSize(view.proxy()->dimensions());
-
- // GrMakeCachedBitmapProxyView has uploaded only the specified subset of 'bmp' so we need not
- // bother with SkBitmap::getSubset
- return SkSpecialImage::MakeDeferredFromGpu(context,
- rect,
- this->uniqueID(),
- std::move(view),
- SkColorTypeToGrColorType(bmp.colorType()),
- sk_ref_sp(this->getColorSpace()),
- &this->props(),
- this->alphaType());
-#else
- return nullptr;
-#endif
-}
-
void SkSpecialImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
return as_SIB(this)->onDraw(canvas, x, y, paint);
}
@@ -207,21 +158,17 @@ sk_sp<SkSpecialImage> SkSpecialImage::MakeFromImage(GrRecordingContext* context,
SkASSERT(rect_fits(subset, image->width(), image->height()));
#if SK_SUPPORT_GPU
- if (const GrSurfaceProxyView* view = as_IB(image)->view(context)) {
- if (!as_IB(image)->context()->priv().matches(context)) {
- return nullptr;
- }
-
- return MakeDeferredFromGpu(context, subset, image->uniqueID(), *view,
+ if (context) {
+ GrSurfaceProxyView view = as_IB(image)->refView(context, GrMipMapped::kNo);
+ return MakeDeferredFromGpu(context, subset, image->uniqueID(), view,
SkColorTypeToGrColorType(image->colorType()),
image->refColorSpace(), props);
- } else
+ }
#endif
- {
- SkBitmap bm;
- if (as_IB(image)->getROPixels(&bm)) {
- return MakeFromRaster(subset, bm, props);
- }
+
+ SkBitmap bm;
+ if (as_IB(image)->getROPixels(&bm)) {
+ return MakeFromRaster(subset, bm, props);
}
return nullptr;
}
@@ -385,14 +332,7 @@ public:
, fView(std::move(view))
, fColorType(ct)
, fAlphaType(at)
- , fColorSpace(std::move(colorSpace))
- , fAddedRasterVersionToCache(false) {
- }
-
- ~SkSpecialImage_Gpu() override {
- if (fAddedRasterVersionToCache.load()) {
- SkNotifyBitmapGenIDIsStale(this->uniqueID());
- }
+ , fColorSpace(std::move(colorSpace)) {
}
SkAlphaType alphaType() const override { return fAlphaType; }
@@ -426,35 +366,10 @@ public:
GrSurfaceProxyView onView(GrRecordingContext* context) const override { return fView; }
bool onGetROPixels(SkBitmap* dst) const override {
- const auto desc = SkBitmapCacheDesc::Make(this->uniqueID(), this->subset());
- if (SkBitmapCache::Find(desc, dst)) {
- SkASSERT(dst->getGenerationID() == this->uniqueID());
- SkASSERT(dst->isImmutable());
- SkASSERT(dst->getPixels());
- return true;
- }
-
- SkPixmap pmap;
- SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(),
- this->alphaType(), fColorSpace);
- auto rec = SkBitmapCache::Alloc(desc, info, &pmap);
- if (!rec) {
- return false;
- }
- auto sContext = GrSurfaceContext::Make(fContext, fView, fColorType, this->alphaType(),
- fColorSpace);
- if (!sContext) {
- return false;
- }
-
- if (!sContext->readPixels(info, pmap.writable_addr(), pmap.rowBytes(),
- {this->subset().left(), this->subset().top()})) {
- return false;
- }
-
- SkBitmapCache::Add(std::move(rec), dst);
- fAddedRasterVersionToCache.store(true);
- return true;
+ // This should never be called: All GPU image filters are implemented entirely on the GPU,
+ // so we never perform read-back.
+ SkASSERT(false);
+ return false;
}
SkColorSpace* onGetColorSpace() const override {
@@ -531,7 +446,6 @@ private:
const GrColorType fColorType;
const SkAlphaType fAlphaType;
sk_sp<SkColorSpace> fColorSpace;
- mutable std::atomic<bool> fAddedRasterVersionToCache;
typedef SkSpecialImage_Base INHERITED;
};
diff --git a/chromium/third_party/skia/src/core/SkSpecialImage.h b/chromium/third_party/skia/src/core/SkSpecialImage.h
index 9df11ab04c5..0dfed777123 100644
--- a/chromium/third_party/skia/src/core/SkSpecialImage.h
+++ b/chromium/third_party/skia/src/core/SkSpecialImage.h
@@ -62,13 +62,6 @@ public:
virtual size_t getSize() const = 0;
/**
- * Ensures that a special image is backed by a texture (when GrRecordingContext is non-null).
- * If no transformation is required, the returned image may be the same as this special image.
- * If this special image is from a different GrRecordingContext, this will fail.
- */
- sk_sp<SkSpecialImage> makeTextureImage(GrRecordingContext*) const;
-
- /**
* Draw this SpecialImage into the canvas, automatically taking into account the image's subset
*/
void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) const;
diff --git a/chromium/third_party/skia/src/core/SkStrikeSpec.cpp b/chromium/third_party/skia/src/core/SkStrikeSpec.cpp
index c5c46bf46c8..51b92e087b6 100644
--- a/chromium/third_party/skia/src/core/SkStrikeSpec.cpp
+++ b/chromium/third_party/skia/src/core/SkStrikeSpec.cpp
@@ -14,8 +14,9 @@
#include "src/core/SkTLazy.h"
#if SK_SUPPORT_GPU
+#include "src/gpu/text/GrSDFMaskFilter.h"
+#include "src/gpu/text/GrSDFTOptions.h"
#include "src/gpu/text/GrStrikeCache.h"
-#include "src/gpu/text/GrTextContext.h"
#endif
SkStrikeSpec SkStrikeSpec::MakeMask(const SkFont& font, const SkPaint& paint,
@@ -186,20 +187,19 @@ SkStrikeSpec SkStrikeSpec::MakePDFVector(const SkTypeface& typeface, int* size)
std::tuple<SkStrikeSpec, SkScalar, SkScalar>
SkStrikeSpec::MakeSDFT(const SkFont& font, const SkPaint& paint,
const SkSurfaceProps& surfaceProps, const SkMatrix& deviceMatrix,
- const GrTextContext::Options& options) {
+ const GrSDFTOptions& options) {
SkStrikeSpec storage;
- SkPaint dfPaint = GrTextContext::InitDistanceFieldPaint(paint);
- SkFont dfFont = GrTextContext::InitDistanceFieldFont(
- font, deviceMatrix, options, &storage.fStrikeToSourceRatio);
+ SkPaint dfPaint{paint};
+ dfPaint.setMaskFilter(GrSDFMaskFilter::Make());
+ SkFont dfFont = options.getSDFFont(font, deviceMatrix, &storage.fStrikeToSourceRatio);
// Fake-gamma and subpixel antialiasing are applied in the shader, so we ignore the
// passed-in scaler context flags. (It's only used when we fall-back to bitmap text).
SkScalerContextFlags flags = SkScalerContextFlags::kNone;
SkScalar minScale, maxScale;
- std::tie(minScale, maxScale) = GrTextContext::InitDistanceFieldMinMaxScale(
- font.getSize(), deviceMatrix, options);
+ std::tie(minScale, maxScale) = options.computeSDFMinMaxScale(font.getSize(), deviceMatrix);
storage.commonSetup(dfFont, dfPaint, surfaceProps, flags, SkMatrix::I());
diff --git a/chromium/third_party/skia/src/core/SkStrikeSpec.h b/chromium/third_party/skia/src/core/SkStrikeSpec.h
index de8731750b9..5b854118ea6 100644
--- a/chromium/third_party/skia/src/core/SkStrikeSpec.h
+++ b/chromium/third_party/skia/src/core/SkStrikeSpec.h
@@ -13,7 +13,7 @@
#include "src/core/SkStrikeForGPU.h"
#if SK_SUPPORT_GPU
-#include "src/gpu/text/GrTextContext.h"
+#include "src/gpu/text/GrSDFTOptions.h"
class GrStrikeCache;
class GrTextStrike;
#endif
@@ -67,7 +67,7 @@ public:
const SkPaint& paint,
const SkSurfaceProps& surfaceProps,
const SkMatrix& deviceMatrix,
- const GrTextContext::Options& options);
+ const GrSDFTOptions& options);
sk_sp<GrTextStrike> findOrCreateGrStrike(GrStrikeCache* cache) const;
#endif
diff --git a/chromium/third_party/skia/src/core/SkString.cpp b/chromium/third_party/skia/src/core/SkString.cpp
index d42ee6f07e9..13743b2212b 100644
--- a/chromium/third_party/skia/src/core/SkString.cpp
+++ b/chromium/third_party/skia/src/core/SkString.cpp
@@ -19,50 +19,38 @@
// number of bytes (on the stack) to receive the printf result
static const size_t kBufferSize = 1024;
-static const char* apply_format_string(const char* format, va_list args, char* stackBuffer,
- size_t stackBufferSize, int* length, SkString* heapBuffer) {
+struct StringBuffer {
+ char* fText;
+ int fLength;
+};
+
+template <int SIZE>
+static StringBuffer apply_format_string(const char* format, va_list args, char (&stackBuffer)[SIZE],
+ SkString* heapBuffer) {
+ // First, attempt to print directly to the stack buffer.
va_list argsCopy;
va_copy(argsCopy, args);
- *length = std::vsnprintf(stackBuffer, stackBufferSize, format, args);
- if (*length < 0) {
+ int outLength = std::vsnprintf(stackBuffer, SIZE, format, args);
+ if (outLength < 0) {
SkDebugf("SkString: vsnprintf reported error.");
va_end(argsCopy);
- *length = 0;
- return stackBuffer;
+ return {stackBuffer, 0};
}
- if (*length < SkToInt(stackBufferSize)) {
+ if (outLength < SIZE) {
va_end(argsCopy);
- return stackBuffer;
+ return {stackBuffer, outLength};
}
- heapBuffer->resize(*length);
- SkDEBUGCODE(int check =)
- std::vsnprintf(heapBuffer->writable_str(), *length + 1, format, argsCopy);
- SkASSERT(check == *length);
+
+ // Our text was too long to fit on the stack! However, we now know how much space we need to
+ // format it. Format the string into our heap buffer. `set` automatically reserves an extra
+ // byte at the end of the buffer for a null terminator, so we don't need to add one here.
+ heapBuffer->set(nullptr, outLength);
+ char* heapBufferDest = heapBuffer->writable_str();
+ SkDEBUGCODE(int checkLength =) std::vsnprintf(heapBufferDest, outLength + 1, format, argsCopy);
+ SkASSERT(checkLength == outLength);
va_end(argsCopy);
- return heapBuffer->c_str();
-}
-
-#define ARGS_TO_BUFFER(format, buffer, size, written, result) \
- SkString overflow; \
- do { \
- va_list args; \
- va_start(args, format); \
- result = apply_format_string(format, args, buffer, size, &written, &overflow); \
- va_end(args); \
- } while (0)
-
-#define V_SKSTRING_PRINTF(output, format) \
- do { \
- char buffer[kBufferSize]; \
- va_list args; \
- va_start(args, format); \
- int length; \
- auto result = apply_format_string(format, args, buffer, kBufferSize, &length, &output); \
- SkASSERT(result == output.c_str() || result == buffer); \
- if (result == buffer) { \
- output.set(buffer, length); \
- } \
- } while (0)
+ return {heapBufferDest, outLength};
+}
///////////////////////////////////////////////////////////////////////////////
@@ -339,31 +327,40 @@ char* SkString::writable_str() {
return fRec->data();
}
+void SkString::resize(size_t len) {
+ len = trim_size_t_to_u32(len);
+ if (0 == len) {
+ this->reset();
+ } else if (fRec->unique() && ((len >> 2) <= (fRec->fLength >> 2))) {
+ // Use less of the buffer we have without allocating a smaller one.
+ char* p = this->writable_str();
+ p[len] = '\0';
+ fRec->fLength = SkToU32(len);
+ } else {
+ SkString newString(len);
+ char* dest = newString.writable_str();
+ int copyLen = std::min<uint32_t>(len, this->size());
+ memcpy(dest, this->c_str(), copyLen);
+ dest[copyLen] = '\0';
+ this->swap(newString);
+ }
+}
+
void SkString::set(const char text[]) {
this->set(text, text ? strlen(text) : 0);
}
void SkString::set(const char text[], size_t len) {
len = trim_size_t_to_u32(len);
- bool unique = fRec->unique();
if (0 == len) {
this->reset();
- } else if (unique && len <= fRec->fLength) {
- // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))?
- // just use less of the buffer without allocating a smaller one
- char* p = this->writable_str();
- if (text) {
- memcpy(p, text, len);
- }
- p[len] = 0;
- fRec->fLength = SkToU32(len);
- } else if (unique && (fRec->fLength >> 2) == (len >> 2)) {
- // we have spare room in the current allocation, so don't alloc a larger one
+ } else if (fRec->unique() && ((len >> 2) <= (fRec->fLength >> 2))) {
+ // Use less of the buffer we have without allocating a smaller one.
char* p = this->writable_str();
if (text) {
memcpy(p, text, len);
}
- p[len] = 0;
+ p[len] = '\0';
fRec->fLength = SkToU32(len);
} else {
SkString tmp(text, len);
@@ -488,44 +485,63 @@ void SkString::insertScalar(size_t offset, SkScalar value) {
this->insert(offset, buffer, stop - buffer);
}
+///////////////////////////////////////////////////////////////////////////////
+
void SkString::printf(const char format[], ...) {
- V_SKSTRING_PRINTF((*this), format);
+ va_list args;
+ va_start(args, format);
+ this->printVAList(format, args);
+ va_end(args);
}
-void SkString::appendf(const char format[], ...) {
- char buffer[kBufferSize];
- int length;
- const char* result;
- ARGS_TO_BUFFER(format, buffer, kBufferSize, length, result);
+void SkString::printVAList(const char format[], va_list args) {
+ char stackBuffer[kBufferSize];
+ StringBuffer result = apply_format_string(format, args, stackBuffer, this);
+
+ if (result.fText == stackBuffer) {
+ this->set(result.fText, result.fLength);
+ }
+}
- this->append(result, length);
+void SkString::appendf(const char format[], ...) {
+ va_list args;
+ va_start(args, format);
+ this->appendVAList(format, args);
+ va_end(args);
}
void SkString::appendVAList(const char format[], va_list args) {
- char buffer[kBufferSize];
- int length = vsnprintf(buffer, kBufferSize, format, args);
- SkASSERT(length >= 0 && length < SkToInt(kBufferSize));
+ if (this->isEmpty()) {
+ this->printVAList(format, args);
+ return;
+ }
+
+ SkString overflow;
+ char stackBuffer[kBufferSize];
+ StringBuffer result = apply_format_string(format, args, stackBuffer, &overflow);
- this->append(buffer, length);
+ this->append(result.fText, result.fLength);
}
void SkString::prependf(const char format[], ...) {
- char buffer[kBufferSize];
- int length;
- const char* result;
- ARGS_TO_BUFFER(format, buffer, kBufferSize, length, result);
-
- this->prepend(result, length);
+ va_list args;
+ va_start(args, format);
+ this->prependVAList(format, args);
+ va_end(args);
}
void SkString::prependVAList(const char format[], va_list args) {
- char buffer[kBufferSize];
- int length = vsnprintf(buffer, kBufferSize, format, args);
- SkASSERT(length >= 0 && length < SkToInt(kBufferSize));
+ if (this->isEmpty()) {
+ this->printVAList(format, args);
+ return;
+ }
- this->prepend(buffer, length);
-}
+ SkString overflow;
+ char stackBuffer[kBufferSize];
+ StringBuffer result = apply_format_string(format, args, stackBuffer, &overflow);
+ this->prepend(result.fText, result.fLength);
+}
///////////////////////////////////////////////////////////////////////////////
@@ -568,7 +584,10 @@ void SkString::swap(SkString& other) {
SkString SkStringPrintf(const char* format, ...) {
SkString formattedOutput;
- V_SKSTRING_PRINTF(formattedOutput, format);
+ va_list args;
+ va_start(args, format);
+ formattedOutput.printVAList(format, args);
+ va_end(args);
return formattedOutput;
}
diff --git a/chromium/third_party/skia/src/core/SkVM.cpp b/chromium/third_party/skia/src/core/SkVM.cpp
index 2a7db341702..654ab8f97c3 100644
--- a/chromium/third_party/skia/src/core/SkVM.cpp
+++ b/chromium/third_party/skia/src/core/SkVM.cpp
@@ -250,6 +250,7 @@ namespace skvm {
case Op::select: write(o, V{id}, "=", op, V{x}, V{y}, V{z}, fs(id)...); break;
case Op::pack: write(o, V{id}, "=", op, V{x}, V{y}, Shift{immz}, fs(id)...); break;
+ case Op::ceil: write(o, V{id}, "=", op, V{x}, fs(id)...); break;
case Op::floor: write(o, V{id}, "=", op, V{x}, fs(id)...); break;
case Op::to_f32: write(o, V{id}, "=", op, V{x}, fs(id)...); break;
case Op::trunc: write(o, V{id}, "=", op, V{x}, fs(id)...); break;
@@ -369,6 +370,7 @@ namespace skvm {
case Op::select: write(o, R{d}, "=", op, R{x}, R{y}, R{z}); break;
case Op::pack: write(o, R{d}, "=", op, R{x}, R{y}, Shift{immz}); break;
+ case Op::ceil: write(o, R{d}, "=", op, R{x}); break;
case Op::floor: write(o, R{d}, "=", op, R{x}); break;
case Op::to_f32: write(o, R{d}, "=", op, R{x}); break;
case Op::trunc: write(o, R{d}, "=", op, R{x}); break;
@@ -738,6 +740,9 @@ namespace skvm {
}
F32 Builder::approx_powf(F32 x, F32 y) {
+ // TODO: assert this instead? Sometimes x is very slightly negative. See skia:10210.
+ x = max(0.0f, x);
+
auto is_x = bit_or(eq(x, 0.0f),
eq(x, 1.0f));
return select(is_x, x, approx_pow2(mul(approx_log2(x), y)));
@@ -1010,6 +1015,10 @@ namespace skvm {
return {this, this->push(Op::pack, x.id,y.id,NA, 0,bits)};
}
+ F32 Builder::ceil(F32 x) {
+ if (float X; this->allImm(x.id,&X)) { return splat(ceilf(X)); }
+ return {this, this->push(Op::ceil, x.id)};
+ }
F32 Builder::floor(F32 x) {
if (float X; this->allImm(x.id,&X)) { return splat(floorf(X)); }
return {this, this->push(Op::floor, x.id)};
@@ -1231,32 +1240,35 @@ namespace skvm {
};
switch (mode) {
- default: SkASSERT(false); /*but also, for safety, fallthrough*/
+ default:
+ SkASSERT(false);
+ [[fallthrough]]; /*but also, for safety, fallthrough*/
case SkBlendMode::kClear: return { splat(0.0f), splat(0.0f), splat(0.0f), splat(0.0f) };
case SkBlendMode::kSrc: return src;
case SkBlendMode::kDst: return dst;
- case SkBlendMode::kDstOver: std::swap(src, dst); // fall-through
+ case SkBlendMode::kDstOver: std::swap(src, dst); [[fallthrough]];
case SkBlendMode::kSrcOver:
return apply_rgba([&](auto s, auto d) {
return mad(d,1-src.a, s);
});
- case SkBlendMode::kDstIn: std::swap(src, dst); // fall-through
+ case SkBlendMode::kDstIn: std::swap(src, dst); [[fallthrough]];
case SkBlendMode::kSrcIn:
return apply_rgba([&](auto s, auto d) {
return s * dst.a;
});
- case SkBlendMode::kDstOut: std::swap(src, dst); // fall-through
+ case SkBlendMode::kDstOut: std::swap(src, dst); [[fallthrough]];
+
case SkBlendMode::kSrcOut:
return apply_rgba([&](auto s, auto d) {
return s * (1-dst.a);
});
- case SkBlendMode::kDstATop: std::swap(src, dst); // fall-through
+ case SkBlendMode::kDstATop: std::swap(src, dst); [[fallthrough]];
case SkBlendMode::kSrcATop:
return apply_rgba([&](auto s, auto d) {
return mma(s, dst.a, d, 1-src.a);
@@ -2346,6 +2358,9 @@ namespace skvm {
F(vals[z])}));
break;
+ case Op::ceil:
+ vals[i] = I(b->CreateUnaryIntrinsic(llvm::Intrinsic::ceil, F(vals[x])));
+ break;
case Op::floor:
vals[i] = I(b->CreateUnaryIntrinsic(llvm::Intrinsic::floor, F(vals[x])));
break;
@@ -3217,6 +3232,11 @@ namespace skvm {
a->vpor (dst(), dst(), any(x));
break;
+ case Op::ceil:
+ if (in_reg(x)) { a->vroundps(dst(x), r(x), Assembler::CEIL); }
+ else { a->vroundps(dst(), any(x), Assembler::CEIL); }
+ break;
+
case Op::floor:
if (in_reg(x)) { a->vroundps(dst(x), r(x), Assembler::FLOOR); }
else { a->vroundps(dst(), any(x), Assembler::FLOOR); }
diff --git a/chromium/third_party/skia/src/core/SkVM.h b/chromium/third_party/skia/src/core/SkVM.h
index 697337e1d4b..db5b273c45c 100644
--- a/chromium/third_party/skia/src/core/SkVM.h
+++ b/chromium/third_party/skia/src/core/SkVM.h
@@ -387,7 +387,8 @@ namespace skvm {
M(fma_f32) M(fms_f32) M(fnma_f32) \
M(sqrt_f32) \
M(shl_i32) M(shr_i32) M(sra_i32) \
- M(floor) M(trunc) M(round) M(to_f32) \
+ M(ceil) M(floor) M(trunc) M(round) \
+ M(to_f32) \
M( eq_f32) M( eq_i32) \
M(neq_f32) \
M( gt_f32) M( gt_i32) \
@@ -475,6 +476,12 @@ namespace skvm {
Builder* operator->() const { return a.operator->(); }
};
+ struct Coord {
+ F32 x,y;
+ explicit operator bool() const { return x && y; }
+ Builder* operator->() const { return x.operator->(); }
+ };
+
struct Uniform {
Arg ptr;
int offset;
@@ -642,6 +649,7 @@ namespace skvm {
F32 abs(F32 x) { return bit_cast(bit_and(bit_cast(x), 0x7fff'ffff)); }
F32 fract(F32 x) { return sub(x, floor(x)); }
+ F32 ceil(F32);
F32 floor(F32);
I32 is_NaN(F32 x) { return neq(x,x); }
@@ -871,11 +879,13 @@ namespace skvm {
static inline I32 max(I32 x, I32a y) { return x->max(x,y); }
static inline I32 max(int x, I32 y) { return y->max(x,y); }
- static inline I32 operator==(I32 x, I32a y) { return x->eq(x,y); }
- static inline I32 operator==(int x, I32 y) { return y->eq(x,y); }
+ static inline I32 operator==(I32 x, I32 y) { return x->eq(x,y); }
+ static inline I32 operator==(I32 x, int y) { return x->eq(x,y); }
+ static inline I32 operator==(int x, I32 y) { return y->eq(x,y); }
- static inline I32 operator!=(I32 x, I32a y) { return x->neq(x,y); }
- static inline I32 operator!=(int x, I32 y) { return y->neq(x,y); }
+ static inline I32 operator!=(I32 x, I32 y) { return x->neq(x,y); }
+ static inline I32 operator!=(I32 x, int y) { return x->neq(x,y); }
+ static inline I32 operator!=(int x, I32 y) { return y->neq(x,y); }
static inline I32 operator< (I32 x, I32a y) { return x->lt(x,y); }
static inline I32 operator< (int x, I32 y) { return y->lt(x,y); }
@@ -908,11 +918,13 @@ namespace skvm {
static inline F32 max(F32 x, F32a y) { return x->max(x,y); }
static inline F32 max(float x, F32 y) { return y->max(x,y); }
- static inline I32 operator==(F32 x, F32a y) { return x->eq(x,y); }
- static inline I32 operator==(float x, F32 y) { return y->eq(x,y); }
+ static inline I32 operator==(F32 x, F32 y) { return x->eq(x,y); }
+ static inline I32 operator==(F32 x, float y) { return x->eq(x,y); }
+ static inline I32 operator==(float x, F32 y) { return y->eq(x,y); }
- static inline I32 operator!=(F32 x, F32a y) { return x->neq(x,y); }
- static inline I32 operator!=(float x, F32 y) { return y->neq(x,y); }
+ static inline I32 operator!=(F32 x, F32 y) { return x->neq(x,y); }
+ static inline I32 operator!=(F32 x, float y) { return x->neq(x,y); }
+ static inline I32 operator!=(float x, F32 y) { return y->neq(x,y); }
static inline I32 operator< (F32 x, F32a y) { return x->lt(x,y); }
static inline I32 operator< (float x, F32 y) { return y->lt(x,y); }
@@ -974,6 +986,7 @@ namespace skvm {
static inline F32 clamp01(F32 x) { return x->clamp01(x); }
static inline F32 abs(F32 x) { return x-> abs(x); }
+ static inline F32 ceil(F32 x) { return x-> ceil(x); }
static inline F32 fract(F32 x) { return x-> fract(x); }
static inline F32 floor(F32 x) { return x-> floor(x); }
static inline I32 is_NaN(F32 x) { return x-> is_NaN(x); }
diff --git a/chromium/third_party/skia/src/core/SkVMBlitter.cpp b/chromium/third_party/skia/src/core/SkVMBlitter.cpp
index 37172c8b7f9..196fae8a5cc 100644
--- a/chromium/third_party/skia/src/core/SkVMBlitter.cpp
+++ b/chromium/third_party/skia/src/core/SkVMBlitter.cpp
@@ -9,6 +9,7 @@
#include "include/private/SkMacros.h"
#include "src/core/SkArenaAlloc.h"
#include "src/core/SkBlendModePriv.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkColorSpaceXformSteps.h"
#include "src/core/SkCoreBlitters.h"
@@ -34,13 +35,13 @@ namespace {
enum class Coverage { Full, UniformA8, MaskA8, MaskLCD16, Mask3D };
struct Params {
- sk_sp<SkShader> shader;
- sk_sp<SkShader> clip;
- SkColorInfo dst;
- SkBlendMode blendMode;
- Coverage coverage;
- SkFilterQuality quality;
- SkMatrix ctm;
+ sk_sp<SkShader> shader;
+ sk_sp<SkShader> clip;
+ SkColorInfo dst;
+ SkBlendMode blendMode;
+ Coverage coverage;
+ SkFilterQuality quality;
+ const SkMatrixProvider& matrices;
Params withCoverage(Coverage c) const {
Params p = *this;
@@ -59,7 +60,7 @@ namespace {
blendMode,
coverage;
uint32_t padding{0};
- // Params::quality and Params::ctm are only passed to {shader,clip}->program(),
+ // Params::quality and Params::matrices are only passed to {shader,clip}->program(),
// not used here by the blitter itself. No need to include them in the key;
// they'll be folded into the shader key if used.
@@ -117,8 +118,9 @@ namespace {
skvm::I32 dx = p.uniform32(uniforms->base, offsetof(BlitterUniforms, right))
- p.index(),
dy = p.uniform32(uniforms->base, offsetof(BlitterUniforms, y));
- skvm::F32 x = to_f32(dx) + 0.5f,
- y = to_f32(dy) + 0.5f;
+ skvm::Coord device = {to_f32(dx) + 0.5f,
+ to_f32(dy) + 0.5f},
+ local = device;
skvm::Color paint = {
p.uniformF(uniforms->base, offsetof(BlitterUniforms, paint.fR)),
@@ -129,8 +131,8 @@ namespace {
uint64_t hash = 0;
if (auto c = sb->program(&p,
- x,y, paint,
- params.ctm, /*localM=*/nullptr,
+ device,local, paint,
+ params.matrices, /*localM=*/nullptr,
params.quality, params.dst,
uniforms,alloc)) {
hash = p.hash();
@@ -197,8 +199,9 @@ namespace {
skvm::I32 dx = p->uniform32(uniforms->base, offsetof(BlitterUniforms, right))
- p->index(),
dy = p->uniform32(uniforms->base, offsetof(BlitterUniforms, y));
- skvm::F32 x = to_f32(dx) + 0.5f,
- y = to_f32(dy) + 0.5f;
+ skvm::Coord device = {to_f32(dx) + 0.5f,
+ to_f32(dy) + 0.5f},
+ local = device;
skvm::Color paint = {
p->uniformF(uniforms->base, offsetof(BlitterUniforms, paint.fR)),
@@ -207,8 +210,8 @@ namespace {
p->uniformF(uniforms->base, offsetof(BlitterUniforms, paint.fA)),
};
- skvm::Color src = as_SB(params.shader)->program(p, x,y, paint,
- params.ctm, /*localM=*/nullptr,
+ skvm::Color src = as_SB(params.shader)->program(p, device,local, paint,
+ params.matrices, /*localM=*/nullptr,
params.quality, params.dst,
uniforms, alloc);
SkASSERT(src);
@@ -274,8 +277,8 @@ namespace {
}
if (params.clip) {
- skvm::Color clip = as_SB(params.clip)->program(p, x,y, paint,
- params.ctm, /*localM=*/nullptr,
+ skvm::Color clip = as_SB(params.clip)->program(p, device,local, paint,
+ params.matrices, /*localM=*/nullptr,
params.quality, params.dst,
uniforms, alloc);
SkAssertResult(clip);
@@ -404,7 +407,7 @@ namespace {
}
- struct NoopColorFilter : public SkColorFilter {
+ struct NoopColorFilter : public SkColorFilterBase {
skvm::Color onProgram(skvm::Builder*, skvm::Color c,
SkColorSpace*, skvm::Uniforms*, SkArenaAlloc*) const override {
return c;
@@ -428,13 +431,14 @@ namespace {
bool isOpaque() const override { return fShader->isOpaque(); }
- skvm::Color onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Color onProgram(skvm::Builder* p,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider& matrices, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override {
// Run our wrapped shader.
- skvm::Color c = as_SB(fShader)->program(p, x,y, paint,
- ctm,localM, quality,dst, uniforms,alloc);
+ skvm::Color c = as_SB(fShader)->program(p, device,local, paint,
+ matrices,localM, quality,dst, uniforms,alloc);
if (!c) {
return {};
}
@@ -467,8 +471,10 @@ namespace {
// See SkRasterPipeline dither stage.
// This is 8x8 ordered dithering. From here we'll only need dx and dx^dy.
- skvm::I32 X = trunc(x - 0.5f),
- Y = X ^ trunc(y - 0.5f);
+ SkASSERT(local.x.id == device.x.id);
+ SkASSERT(local.y.id == device.y.id);
+ skvm::I32 X = trunc(device.x - 0.5f),
+ Y = X ^ trunc(device.y - 0.5f);
// If X's low bits are abc and Y's def, M is fcebda,
// 6 bits producing all values [0,63] shuffled over an 8x8 grid.
@@ -501,7 +507,7 @@ namespace {
static Params effective_params(const SkPixmap& device,
const SkPaint& paint,
- const SkMatrix& ctm,
+ const SkMatrixProvider& matrices,
sk_sp<SkShader> clip) {
// Color filters have been handled for us by SkBlitter::Choose().
SkASSERT(!paint.getColorFilter());
@@ -547,7 +553,7 @@ namespace {
blendMode,
Coverage::Full, // Placeholder... withCoverage() will change as needed.
paint.getFilterQuality(),
- ctm,
+ matrices,
};
}
@@ -555,12 +561,12 @@ namespace {
public:
Blitter(const SkPixmap& device,
const SkPaint& paint,
- const SkMatrix& ctm,
+ const SkMatrixProvider& matrices,
sk_sp<SkShader> clip,
bool* ok)
: fDevice(device)
, fUniforms(kBlitterUniformsCount)
- , fParams(effective_params(device, paint, ctm, std::move(clip)))
+ , fParams(effective_params(device, paint, matrices, std::move(clip)))
, fKey(cache_key(fParams, &fUniforms, &fAlloc, ok))
, fPaint([&]{
SkColor4f color = paint.getColor4f();
@@ -737,10 +743,10 @@ namespace {
SkBlitter* SkCreateSkVMBlitter(const SkPixmap& device,
const SkPaint& paint,
- const SkMatrix& ctm,
+ const SkMatrixProvider& matrices,
SkArenaAlloc* alloc,
sk_sp<SkShader> clip) {
bool ok = true;
- auto blitter = alloc->make<Blitter>(device, paint, ctm, std::move(clip), &ok);
+ auto blitter = alloc->make<Blitter>(device, paint, matrices, std::move(clip), &ok);
return ok ? blitter : nullptr;
}
diff --git a/chromium/third_party/skia/src/core/SkVM_fwd.h b/chromium/third_party/skia/src/core/SkVM_fwd.h
index 1442a9fa9d9..e8dc43f6e3f 100644
--- a/chromium/third_party/skia/src/core/SkVM_fwd.h
+++ b/chromium/third_party/skia/src/core/SkVM_fwd.h
@@ -16,6 +16,7 @@ namespace skvm {
struct I32;
struct F32;
struct Color;
+ struct Coord;
struct Uniforms;
}
diff --git a/chromium/third_party/skia/src/core/SkValidatingReadBuffer.h b/chromium/third_party/skia/src/core/SkValidatingReadBuffer.h
deleted file mode 100644
index 887c621f84d..00000000000
--- a/chromium/third_party/skia/src/core/SkValidatingReadBuffer.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkValidatingReadBuffer_DEFINED
-#define SkValidatingReadBuffer_DEFINED
-
-#include "include/core/SkPath.h"
-#include "include/core/SkPicture.h"
-#include "include/core/SkRefCnt.h"
-#include "src/core/SkReadBuffer.h"
-#include "src/core/SkReader32.h"
-#include "src/core/SkWriteBuffer.h"
-
-class SkBitmap;
-
-// DEPRECATED -- just use SkReadBuffer (so we can delete this header)
-typedef SkReadBuffer SkValidatingReadBuffer;
-
-#endif
diff --git a/chromium/third_party/skia/src/core/SkWriteBuffer.cpp b/chromium/third_party/skia/src/core/SkWriteBuffer.cpp
index f12099ab164..4e0424fac53 100644
--- a/chromium/third_party/skia/src/core/SkWriteBuffer.cpp
+++ b/chromium/third_party/skia/src/core/SkWriteBuffer.cpp
@@ -219,32 +219,29 @@ void SkBinaryWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) {
* already written the string, we write its index instead.
*/
- SkFlattenable::Factory factory = flattenable->getFactory();
- SkASSERT(factory);
if (fFactorySet) {
+ SkFlattenable::Factory factory = flattenable->getFactory();
+ SkASSERT(factory);
+
this->write32(fFactorySet->add(factory));
} else {
+ const char* name = flattenable->getTypeName();
+ SkASSERT(name);
+ SkASSERT(0 != strcmp("", name));
- if (uint32_t* indexPtr = fFlattenableDict.find(factory)) {
+ if (uint32_t* indexPtr = fFlattenableDict.find(name)) {
// We will write the index as a 32-bit int. We want the first byte
// that we send to be zero - this will act as a sentinel that we
// have an index (not a string). This means that we will send the
// the index shifted left by 8. The remaining 24-bits should be
// plenty to store the index. Note that this strategy depends on
- // being little endian.
+ // being little endian, and type names being non-empty.
SkASSERT(0 == *indexPtr >> 24);
this->write32(*indexPtr << 8);
} else {
- const char* name = flattenable->getTypeName();
- SkASSERT(name);
- // Otherwise write the string. Clients should not use the empty
- // string as a name, or we will have a problem.
- SkASSERT(0 != strcmp("", name));
this->writeString(name);
-
- // Add key to dictionary.
- fFlattenableDict.set(factory, fFlattenableDict.count() + 1);
+ fFlattenableDict.set(name, fFlattenableDict.count() + 1);
}
}
diff --git a/chromium/third_party/skia/src/core/SkWriteBuffer.h b/chromium/third_party/skia/src/core/SkWriteBuffer.h
index 5bd58e9156d..f962786d2a2 100644
--- a/chromium/third_party/skia/src/core/SkWriteBuffer.h
+++ b/chromium/third_party/skia/src/core/SkWriteBuffer.h
@@ -122,6 +122,7 @@ public:
bool writeToStream(SkWStream*) const;
void writeToMemory(void* dst) const { fWriter.flatten(dst); }
+ sk_sp<SkData> snapshotAsData() const { return fWriter.snapshotAsData(); }
void setFactoryRecorder(sk_sp<SkFactorySet>);
void setTypefaceRecorder(sk_sp<SkRefCntSet>);
@@ -133,7 +134,7 @@ private:
SkWriter32 fWriter;
// Only used if we do not have an fFactorySet
- SkTHashMap<SkFlattenable::Factory, uint32_t> fFlattenableDict;
+ SkTHashMap<const char*, uint32_t> fFlattenableDict;
};
#endif // SkWriteBuffer_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkWriter32.cpp b/chromium/third_party/skia/src/core/SkWriter32.cpp
index 589382b381c..aa96531dfcd 100644
--- a/chromium/third_party/skia/src/core/SkWriter32.cpp
+++ b/chromium/third_party/skia/src/core/SkWriter32.cpp
@@ -5,11 +5,8 @@
* found in the LICENSE file.
*/
-#include "include/core/SkString.h"
#include "include/private/SkTo.h"
#include "src/core/SkMatrixPriv.h"
-#include "src/core/SkReader32.h"
-
#include "src/core/SkWriter32.h"
void SkWriter32::writeMatrix(const SkMatrix& matrix) {
@@ -18,33 +15,6 @@ void SkWriter32::writeMatrix(const SkMatrix& matrix) {
SkMatrixPriv::WriteToMemory(matrix, this->reserve(size));
}
-/*
- * Strings are stored as: length[4-bytes] + string_data + '\0' + pad_to_mul_4
- */
-
-const char* SkReader32::readString(size_t* outLen) {
- size_t len = this->readU32();
- const void* ptr = this->peek();
-
- // skip over the string + '\0' and then pad to a multiple of 4
- size_t alignedSize = SkAlign4(len + 1);
- this->skip(alignedSize);
-
- if (outLen) {
- *outLen = len;
- }
- return (const char*)ptr;
-}
-
-size_t SkReader32::readIntoString(SkString* copy) {
- size_t len;
- const char* ptr = this->readString(&len);
- if (copy) {
- copy->set(ptr, len);
- }
- return len;
-}
-
void SkWriter32::writeString(const char str[], size_t len) {
if (nullptr == str) {
str = "";
diff --git a/chromium/third_party/skia/src/core/SkWriter32.h b/chromium/third_party/skia/src/core/SkWriter32.h
index ca0664e4012..8e2595873bf 100644
--- a/chromium/third_party/skia/src/core/SkWriter32.h
+++ b/chromium/third_party/skia/src/core/SkWriter32.h
@@ -110,12 +110,6 @@ public:
*(int32_t*)this->reserve(sizeof(value)) = value;
}
- void writePtr(void* value) {
- // this->reserve() only returns 4-byte aligned pointers,
- // so this may be an under-aligned write if we were to do this like the others.
- memcpy(this->reserve(sizeof(value)), &value, sizeof(value));
- }
-
void writeScalar(SkScalar value) {
*(SkScalar*)this->reserve(sizeof(value)) = value;
}
@@ -190,10 +184,9 @@ public:
}
/**
- * Writes a string to the writer, which can be retrieved with
- * SkReader32::readString().
- * The length can be specified, or if -1 is passed, it will be computed by
- * calling strlen(). The length must be < max size_t.
+ * Writes a string to the writer, which can be retrieved with SkReadBuffer::readString().
+ * The length can be specified, or if -1 is passed, it will be computed by calling strlen().
+ * The length must be < max size_t.
*
* If you write NULL, it will be read as "".
*/
diff --git a/chromium/third_party/skia/src/effects/Sk1DPathEffect.cpp b/chromium/third_party/skia/src/effects/Sk1DPathEffect.cpp
index 360179d6631..16dee4a90b6 100644
--- a/chromium/third_party/skia/src/effects/Sk1DPathEffect.cpp
+++ b/chromium/third_party/skia/src/effects/Sk1DPathEffect.cpp
@@ -127,7 +127,7 @@ static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
srcP[2] = srcP[1];
srcP[1].set(SkScalarAve(srcP[0].fX, srcP[2].fX),
SkScalarAve(srcP[0].fY, srcP[2].fY));
- // fall through to quad
+ [[fallthrough]];
case SkPath::kQuad_Verb:
if (morphpoints(dstP, &srcP[1], 2, meas, dist)) {
dst->quadTo(dstP[0], dstP[1]);
diff --git a/chromium/third_party/skia/src/effects/SkHighContrastFilter.cpp b/chromium/third_party/skia/src/effects/SkHighContrastFilter.cpp
index b97eabe0cf6..b670462166e 100644
--- a/chromium/third_party/skia/src/effects/SkHighContrastFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkHighContrastFilter.cpp
@@ -9,6 +9,7 @@
#include "include/effects/SkHighContrastFilter.h"
#include "include/private/SkColorData.h"
#include "src/core/SkArenaAlloc.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkEffectPriv.h"
#include "src/core/SkRasterPipeline.h"
@@ -25,7 +26,7 @@
using InvertStyle = SkHighContrastConfig::InvertStyle;
-class SkHighContrast_Filter : public SkColorFilter {
+class SkHighContrast_Filter : public SkColorFilterBase {
public:
SkHighContrast_Filter(const SkHighContrastConfig& config) {
fConfig = config;
@@ -305,9 +306,8 @@ void GLHighContrastFilterEffect::emitCode(EmitArgs& args) {
fragBuilder->codeAppendf("half4 color = %s;", args.fInputColor);
- // Unpremultiply. The max() is to guard against 0 / 0.
- fragBuilder->codeAppendf("half nonZeroAlpha = max(color.a, 0.0001);");
- fragBuilder->codeAppendf("color = half4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
+ // Unpremultiply.
+ fragBuilder->codeAppendf("color = unpremul(color);");
if (hcfe.linearize()) {
fragBuilder->codeAppend("color.rgb = color.rgb * color.rgb;");
diff --git a/chromium/third_party/skia/src/effects/SkLumaColorFilter.cpp b/chromium/third_party/skia/src/effects/SkLumaColorFilter.cpp
index 13efc7514b3..e246dae5e4a 100644
--- a/chromium/third_party/skia/src/effects/SkLumaColorFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkLumaColorFilter.cpp
@@ -8,6 +8,7 @@
#include "include/core/SkString.h"
#include "include/effects/SkLumaColorFilter.h"
#include "include/private/SkColorData.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/core/SkEffectPriv.h"
#include "src/core/SkRasterPipeline.h"
#include "src/core/SkVM.h"
@@ -19,39 +20,50 @@
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#endif
-bool SkLumaColorFilter::onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const {
- rec.fPipeline->append(SkRasterPipeline::bt709_luminance_or_luma_to_alpha);
- rec.fPipeline->append(SkRasterPipeline::clamp_0);
- rec.fPipeline->append(SkRasterPipeline::clamp_1);
- return true;
-}
+class SkLumaColorFilterImpl : public SkColorFilterBase {
+public:
+#if SK_SUPPORT_GPU
+ std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrRecordingContext*,
+ const GrColorInfo&) const override {
+ return GrLumaColorFilterEffect::Make(/*inputFP=*/nullptr);
+ }
+#endif
-skvm::Color SkLumaColorFilter::onProgram(skvm::Builder* p, skvm::Color c,
- SkColorSpace* dstCS,
- skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
- return {
- p->splat(0.0f),
- p->splat(0.0f),
- p->splat(0.0f),
- clamp01(c.r * 0.2126f + c.g * 0.7152f + c.b * 0.0722f),
- };
-}
+ static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&) {
+ return SkLumaColorFilter::Make();
+ }
-sk_sp<SkColorFilter> SkLumaColorFilter::Make() {
- return sk_sp<SkColorFilter>(new SkLumaColorFilter);
-}
+protected:
+ void flatten(SkWriteBuffer&) const override {}
-SkLumaColorFilter::SkLumaColorFilter() : INHERITED() {}
+private:
+ Factory getFactory() const override { return CreateProc; }
+ const char* getTypeName() const override { return "SkLumaColorFilter"; }
-sk_sp<SkFlattenable> SkLumaColorFilter::CreateProc(SkReadBuffer&) {
- return Make();
-}
+ bool onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const override {
+ rec.fPipeline->append(SkRasterPipeline::bt709_luminance_or_luma_to_alpha);
+ rec.fPipeline->append(SkRasterPipeline::clamp_0);
+ rec.fPipeline->append(SkRasterPipeline::clamp_1);
+ return true;
+ }
-void SkLumaColorFilter::flatten(SkWriteBuffer&) const {}
+ skvm::Color onProgram(skvm::Builder* p, skvm::Color c, SkColorSpace*, skvm::Uniforms*,
+ SkArenaAlloc*) const override {
+ return {
+ p->splat(0.0f),
+ p->splat(0.0f),
+ p->splat(0.0f),
+ clamp01(c.r * 0.2126f + c.g * 0.7152f + c.b * 0.0722f),
+ };
+ }
-#if SK_SUPPORT_GPU
-std::unique_ptr<GrFragmentProcessor> SkLumaColorFilter::asFragmentProcessor(
- GrRecordingContext*, const GrColorInfo&) const {
- return GrLumaColorFilterEffect::Make();
+ typedef SkColorFilterBase INHERITED;
+};
+
+sk_sp<SkColorFilter> SkLumaColorFilter::Make() {
+ return sk_sp<SkColorFilter>(new SkLumaColorFilterImpl);
+}
+
+void SkLumaColorFilter::RegisterFlattenable() {
+ SkFlattenable::Register("SkLumaColorFilter", SkLumaColorFilterImpl::CreateProc);
}
-#endif
diff --git a/chromium/third_party/skia/src/effects/SkOpPE.h b/chromium/third_party/skia/src/effects/SkOpPE.h
index 1f51579ebff..db87a052fe4 100644
--- a/chromium/third_party/skia/src/effects/SkOpPE.h
+++ b/chromium/third_party/skia/src/effects/SkOpPE.h
@@ -65,5 +65,20 @@ private:
typedef SkPathEffect INHERITED;
};
+class SkStrokeAndFillPE : public SkPathEffect {
+public:
+ SkStrokeAndFillPE() {}
+
+protected:
+ void flatten(SkWriteBuffer&) const override;
+ bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*) const override;
+ // TODO: override onComputeFastBounds (I think)
+
+private:
+ SK_FLATTENABLE_HOOKS(SkStrokeAndFillPE)
+
+ typedef SkPathEffect INHERITED;
+};
+
#endif
diff --git a/chromium/third_party/skia/src/effects/SkOpPathEffect.cpp b/chromium/third_party/skia/src/effects/SkOpPathEffect.cpp
index e7b8a604bd1..91d89532b0b 100644
--- a/chromium/third_party/skia/src/effects/SkOpPathEffect.cpp
+++ b/chromium/third_party/skia/src/effects/SkOpPathEffect.cpp
@@ -57,7 +57,7 @@ sk_sp<SkPathEffect> SkMatrixPathEffect::MakeTranslate(SkScalar dx, SkScalar dy)
if (!SkScalarsAreFinite(dx, dy)) {
return nullptr;
}
- return sk_sp<SkPathEffect>(new SkMatrixPE(SkMatrix::MakeTrans(dx, dy)));
+ return sk_sp<SkPathEffect>(new SkMatrixPE(SkMatrix::Translate(dx, dy)));
}
sk_sp<SkPathEffect> SkMatrixPathEffect::Make(const SkMatrix& matrix) {
@@ -121,4 +121,57 @@ sk_sp<SkFlattenable> SkStrokePE::CreateProc(SkReadBuffer& buffer) {
return buffer.isValid() ? SkStrokePathEffect::Make(width, join, cap, miter) : nullptr;
}
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include "include/effects/SkStrokeAndFillPathEffect.h"
+#include "src/core/SkPathPriv.h"
+
+sk_sp<SkPathEffect> SkStrokeAndFillPathEffect::Make() {
+ static SkPathEffect* strokeAndFill = new SkStrokeAndFillPE;
+ return sk_ref_sp(strokeAndFill);
+}
+
+void SkStrokeAndFillPE::flatten(SkWriteBuffer&) const {}
+
+static bool known_to_be_opposite_directions(const SkPath& a, const SkPath& b) {
+ auto a_dir = SkPathPriv::kUnknown_FirstDirection,
+ b_dir = SkPathPriv::kUnknown_FirstDirection;
+ (void)SkPathPriv::CheapComputeFirstDirection(a, &a_dir);
+ (void)SkPathPriv::CheapComputeFirstDirection(b, &b_dir);
+
+ return (a_dir == SkPathPriv::kCCW_FirstDirection &&
+ b_dir == SkPathPriv::kCW_FirstDirection)
+ ||
+ (a_dir == SkPathPriv::kCW_FirstDirection &&
+ b_dir == SkPathPriv::kCCW_FirstDirection);
+}
+
+bool SkStrokeAndFillPE::onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
+ const SkRect*) const {
+ // This one is weird, since we exist to allow this paint-style to go away. If we see it,
+ // just let the normal machine run its course.
+ if (rec->getStyle() == SkStrokeRec::kStrokeAndFill_Style) {
+ *dst = src;
+ return true;
+ }
+ if (rec->getStyle() == SkStrokeRec::kStroke_Style) {
+ if (!rec->applyToPath(dst, src)) {
+ return false;
+ }
+
+ if (known_to_be_opposite_directions(src, *dst)) {
+ dst->reverseAddPath(src);
+ } else {
+ dst->addPath(src);
+ }
+ } else {
+ *dst = src;
+ }
+ rec->setFillStyle();
+ return true;
+}
+
+sk_sp<SkFlattenable> SkStrokeAndFillPE::CreateProc(SkReadBuffer& buffer) {
+ return SkStrokeAndFillPathEffect::Make();
+}
diff --git a/chromium/third_party/skia/src/effects/SkTableColorFilter.cpp b/chromium/third_party/skia/src/effects/SkTableColorFilter.cpp
index 87e0bd2bbfc..39b706274cb 100644
--- a/chromium/third_party/skia/src/effects/SkTableColorFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkTableColorFilter.cpp
@@ -13,6 +13,7 @@
#include "include/private/SkColorData.h"
#include "include/private/SkTo.h"
#include "src/core/SkArenaAlloc.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/core/SkEffectPriv.h"
#include "src/core/SkRasterPipeline.h"
#include "src/core/SkReadBuffer.h"
@@ -54,7 +55,7 @@ static const uint8_t gIdentityTable[] = {
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};
-class SkTable_ColorFilter : public SkColorFilter {
+class SkTable_ColorFilter : public SkColorFilterBase {
public:
SkTable_ColorFilter(const uint8_t tableA[], const uint8_t tableR[],
const uint8_t tableG[], const uint8_t tableB[]) {
@@ -270,10 +271,9 @@ void SkTable_ColorFilter::getTableAsBitmap(SkBitmap* table) const {
#include "src/gpu/GrFragmentProcessor.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/SkGr.h"
+#include "src/gpu/effects/GrTextureEffect.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
-#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
-#include "src/gpu/glsl/GrGLSLUniformHandler.h"
class ColorTableEffect : public GrFragmentProcessor {
public:
@@ -285,89 +285,56 @@ public:
const char* name() const override { return "ColorTableEffect"; }
std::unique_ptr<GrFragmentProcessor> clone() const override {
- return std::unique_ptr<GrFragmentProcessor>(new ColorTableEffect(fTextureSampler.view()));
+ return std::unique_ptr<GrFragmentProcessor>(new ColorTableEffect(*this));
}
private:
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
- void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
+ void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
- ColorTableEffect(GrSurfaceProxyView view)
- : INHERITED(
- kColorTableEffect_ClassID,
- kNone_OptimizationFlags) // Not bothering with table-specific optimizations.
- , fTextureSampler(std::move(view)) {
- this->setTextureSamplerCnt(1);
- }
+ ColorTableEffect(GrSurfaceProxyView view);
- const TextureSampler& onTextureSampler(int) const override { return fTextureSampler; }
+ explicit ColorTableEffect(const ColorTableEffect& that);
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
- TextureSampler fTextureSampler;
-
typedef GrFragmentProcessor INHERITED;
};
-class GLColorTableEffect : public GrGLSLFragmentProcessor {
-public:
- void emitCode(EmitArgs&) override;
-
- static void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*) {}
-
-private:
- typedef GrGLSLFragmentProcessor INHERITED;
-};
-
-void GLColorTableEffect::emitCode(EmitArgs& args) {
- static const float kColorScaleFactor = 255.0f / 256.0f;
- static const float kColorOffsetFactor = 1.0f / 512.0f;
- GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
- if (nullptr == args.fInputColor) {
- // the input color is solid white (all ones).
- static const float kMaxValue = kColorScaleFactor + kColorOffsetFactor;
- fragBuilder->codeAppendf("\t\thalf4 coord = half4(%f, %f, %f, %f);\n",
- kMaxValue, kMaxValue, kMaxValue, kMaxValue);
-
- } else {
- fragBuilder->codeAppendf("\t\thalf nonZeroAlpha = max(%s.a, .0001);\n", args.fInputColor);
- fragBuilder->codeAppendf("\t\thalf4 coord = half4(%s.rgb / nonZeroAlpha, nonZeroAlpha);\n",
- args.fInputColor);
- fragBuilder->codeAppendf("\t\tcoord = coord * %f + half4(%f, %f, %f, %f);\n",
- kColorScaleFactor,
- kColorOffsetFactor, kColorOffsetFactor,
- kColorOffsetFactor, kColorOffsetFactor);
- }
-
- SkString coord;
-
- fragBuilder->codeAppendf("\t\t%s.a = ", args.fOutputColor);
- coord.printf("half2(coord.a, 0.125)");
- fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str());
- fragBuilder->codeAppend(".a;\n");
-
- fragBuilder->codeAppendf("\t\t%s.r = ", args.fOutputColor);
- coord.printf("half2(coord.r, 0.375)");
- fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str());
- fragBuilder->codeAppend(".a;\n");
-
- fragBuilder->codeAppendf("\t\t%s.g = ", args.fOutputColor);
- coord.printf("half2(coord.g, 0.625)");
- fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str());
- fragBuilder->codeAppend(".a;\n");
+ColorTableEffect::ColorTableEffect(GrSurfaceProxyView view)
+ // Not bothering with table-specific optimizations.
+ : INHERITED(kColorTableEffect_ClassID, kNone_OptimizationFlags) {
+ auto te = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
+ this->registerExplicitlySampledChild(std::move(te));
+}
- fragBuilder->codeAppendf("\t\t%s.b = ", args.fOutputColor);
- coord.printf("half2(coord.b, 0.875)");
- fragBuilder->appendTextureLookup(args.fTexSamplers[0], coord.c_str());
- fragBuilder->codeAppend(".a;\n");
+ColorTableEffect::ColorTableEffect(const ColorTableEffect& that)
+ : INHERITED(kColorTableEffect_ClassID, that.optimizationFlags()) {
+ this->cloneAndRegisterAllChildProcessors(that);
+}
- fragBuilder->codeAppendf("\t\t%s.rgb *= %s.a;\n", args.fOutputColor, args.fOutputColor);
+GrGLSLFragmentProcessor* ColorTableEffect::onCreateGLSLInstance() const {
+ class Impl : public GrGLSLFragmentProcessor {
+ public:
+ void emitCode(EmitArgs& args) override {
+ GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
+ fragBuilder->codeAppendf("\t\thalf4 coord = 255*unpremul(%s) + 0.5;\n",
+ args.fInputColor);
+ SkString a = this->invokeChild(0, args, "half2(coord.a, 0.5)");
+ SkString r = this->invokeChild(0, args, "half2(coord.r, 1.5)");
+ SkString g = this->invokeChild(0, args, "half2(coord.g, 2.5)");
+ SkString b = this->invokeChild(0, args, "half2(coord.b, 3.5)");
+ fragBuilder->codeAppendf("%s = half4(half3(%s.a, %s.a, %s.a) * %s.a, %s.a);",
+ args.fOutputColor, r.c_str(), g.c_str(), b.c_str(), a.c_str(),
+ a.c_str());
+ }
+ };
+ return new Impl;
}
-///////////////////////////////////////////////////////////////////////////////
std::unique_ptr<GrFragmentProcessor> ColorTableEffect::Make(GrRecordingContext* context,
const SkBitmap& bitmap) {
SkASSERT(kPremul_SkAlphaType == bitmap.alphaType());
@@ -381,15 +348,6 @@ std::unique_ptr<GrFragmentProcessor> ColorTableEffect::Make(GrRecordingContext*
return std::unique_ptr<GrFragmentProcessor>(new ColorTableEffect(std::move(view)));
}
-void ColorTableEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
- GrProcessorKeyBuilder* b) const {
- GLColorTableEffect::GenKey(*this, caps, b);
-}
-
-GrGLSLFragmentProcessor* ColorTableEffect::onCreateGLSLInstance() const {
- return new GLColorTableEffect;
-}
-
///////////////////////////////////////////////////////////////////////////////
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ColorTableEffect);
@@ -420,7 +378,7 @@ std::unique_ptr<GrFragmentProcessor> ColorTableEffect::TestCreate(GrProcessorTes
(flags & (1 << 3)) ? luts[3] : nullptr
));
sk_sp<SkColorSpace> colorSpace = GrTest::TestColorSpace(d->fRandom);
- auto fp = filter->asFragmentProcessor(
+ auto fp = as_CFB(filter)->asFragmentProcessor(
d->context(),
GrColorInfo(GrColorType::kRGBA_8888, kUnknown_SkAlphaType, std::move(colorSpace)));
SkASSERT(fp);
diff --git a/chromium/third_party/skia/src/effects/imagefilters/SkAlphaThresholdFilter.cpp b/chromium/third_party/skia/src/effects/imagefilters/SkAlphaThresholdFilter.cpp
index 9984491aabb..3f433732d6e 100644
--- a/chromium/third_party/skia/src/effects/imagefilters/SkAlphaThresholdFilter.cpp
+++ b/chromium/third_party/skia/src/effects/imagefilters/SkAlphaThresholdFilter.cpp
@@ -19,7 +19,6 @@
#include "include/private/GrRecordingContext.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrColorSpaceXform.h"
-#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrTextureProxy.h"
@@ -110,17 +109,15 @@ GrSurfaceProxyView SkAlphaThresholdFilterImpl::createMaskTexture(GrRecordingCont
}
SkRegion::Iterator iter(fRegion);
- rtContext->clear(nullptr, SK_PMColor4fTRANSPARENT,
- GrRenderTargetContext::CanClearFullscreen::kYes);
+ rtContext->clear(SK_PMColor4fTRANSPARENT);
- GrFixedClip clip(SkIRect::MakeWH(bounds.width(), bounds.height()));
while (!iter.done()) {
GrPaint paint;
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
SkRect rect = SkRect::Make(iter.rect());
- rtContext->drawRect(clip, std::move(paint), GrAA::kNo, inMatrix, rect);
+ rtContext->drawRect(nullptr, std::move(paint), GrAA::kNo, inMatrix, rect);
iter.next();
}
@@ -165,10 +162,12 @@ sk_sp<SkSpecialImage> SkAlphaThresholdFilterImpl::onFilterImage(const Context& c
if (!maskView) {
return nullptr;
}
+ auto maskFP = GrTextureEffect::Make(std::move(maskView), kPremul_SkAlphaType,
+ SkMatrix::Translate(-bounds.x(), -bounds.y()));
auto textureFP = GrTextureEffect::Make(
std::move(inputView), input->alphaType(),
- SkMatrix::MakeTrans(input->subset().x(), input->subset().y()));
+ SkMatrix::Translate(input->subset().x(), input->subset().y()));
textureFP = GrColorSpaceXformEffect::Make(std::move(textureFP), input->getColorSpace(),
input->alphaType(), ctx.colorSpace());
if (!textureFP) {
@@ -176,17 +175,13 @@ sk_sp<SkSpecialImage> SkAlphaThresholdFilterImpl::onFilterImage(const Context& c
}
auto thresholdFP = GrAlphaThresholdFragmentProcessor::Make(
- std::move(maskView), fInnerThreshold, fOuterThreshold, bounds);
+ std::move(textureFP), std::move(maskFP), fInnerThreshold, fOuterThreshold);
if (!thresholdFP) {
return nullptr;
}
- std::unique_ptr<GrFragmentProcessor> fpSeries[] = { std::move(textureFP),
- std::move(thresholdFP) };
- auto fp = GrFragmentProcessor::RunInSeries(fpSeries, 2);
-
- return DrawWithFP(context, std::move(fp), bounds, ctx.colorType(), ctx.colorSpace(),
- isProtected);
+ return DrawWithFP(context, std::move(thresholdFP), bounds, ctx.colorType(),
+ ctx.colorSpace(), isProtected);
}
#endif
diff --git a/chromium/third_party/skia/src/effects/imagefilters/SkArithmeticImageFilter.cpp b/chromium/third_party/skia/src/effects/imagefilters/SkArithmeticImageFilter.cpp
index b357cb8fefb..ae7ff489aa7 100644
--- a/chromium/third_party/skia/src/effects/imagefilters/SkArithmeticImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/imagefilters/SkArithmeticImageFilter.cpp
@@ -18,7 +18,6 @@
#if SK_SUPPORT_GPU
#include "include/effects/SkRuntimeEffect.h"
#include "include/private/GrRecordingContext.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrColorSpaceXform.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
@@ -354,7 +353,7 @@ sk_sp<SkSpecialImage> ArithmeticImageFilterImpl::filterImageGPU(
if (background) {
SkRect bgSubset = SkRect::Make(background->subset());
- SkMatrix backgroundMatrix = SkMatrix::MakeTrans(
+ SkMatrix backgroundMatrix = SkMatrix::Translate(
SkIntToScalar(bgSubset.left() - backgroundOffset.fX),
SkIntToScalar(bgSubset.top() - backgroundOffset.fY));
bgFP = GrTextureEffect::MakeSubset(std::move(backgroundView), background->alphaType(),
@@ -363,13 +362,13 @@ sk_sp<SkSpecialImage> ArithmeticImageFilterImpl::filterImageGPU(
background->alphaType(),
ctx.colorSpace());
} else {
- bgFP = GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
+ bgFP = GrConstColorProcessor::Make(/*inputFP=*/nullptr, SK_PMColor4fTRANSPARENT,
GrConstColorProcessor::InputMode::kIgnore);
}
if (foreground) {
SkRect fgSubset = SkRect::Make(foreground->subset());
- SkMatrix foregroundMatrix = SkMatrix::MakeTrans(
+ SkMatrix foregroundMatrix = SkMatrix::Translate(
SkIntToScalar(fgSubset.left() - foregroundOffset.fX),
SkIntToScalar(fgSubset.top() - foregroundOffset.fY));
auto fgFP = GrTextureEffect::MakeSubset(std::move(foregroundView), foreground->alphaType(),
@@ -403,7 +402,7 @@ sk_sp<SkSpecialImage> ArithmeticImageFilterImpl::filterImageGPU(
SkMatrix matrix;
matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
- renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix,
+ renderTargetContext->drawRect(nullptr, std::move(paint), GrAA::kNo, matrix,
SkRect::Make(bounds));
return SkSpecialImage::MakeDeferredFromGpu(context,
diff --git a/chromium/third_party/skia/src/effects/imagefilters/SkColorFilterImageFilter.cpp b/chromium/third_party/skia/src/effects/imagefilters/SkColorFilterImageFilter.cpp
index b9154431c68..32e7dc8cde9 100644
--- a/chromium/third_party/skia/src/effects/imagefilters/SkColorFilterImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/imagefilters/SkColorFilterImageFilter.cpp
@@ -9,6 +9,7 @@
#include "include/core/SkCanvas.h"
#include "include/core/SkColorFilter.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/core/SkImageFilter_Base.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkSpecialImage.h"
@@ -89,7 +90,7 @@ sk_sp<SkSpecialImage> SkColorFilterImageFilterImpl::onFilterImage(const Context&
sk_sp<SkSpecialImage> input(this->filterInput(0, ctx, &inputOffset));
SkIRect inputBounds;
- if (fColorFilter->affectsTransparentBlack()) {
+ if (as_CFB(fColorFilter)->affectsTransparentBlack()) {
// If the color filter affects transparent black, the bounds are the entire clip.
inputBounds = ctx.clipBounds();
} else if (!input) {
@@ -119,7 +120,7 @@ sk_sp<SkSpecialImage> SkColorFilterImageFilterImpl::onFilterImage(const Context&
// TODO: it may not be necessary to clear or drawPaint inside the input bounds
// (see skbug.com/5075)
- if (fColorFilter->affectsTransparentBlack()) {
+ if (as_CFB(fColorFilter)->affectsTransparentBlack()) {
// The subsequent input->draw() call may not fill the entire canvas. For filters which
// affect transparent black, ensure that the filter is applied everywhere.
paint.setColor(SK_ColorTRANSPARENT);
@@ -153,5 +154,5 @@ bool SkColorFilterImageFilterImpl::onIsColorFilterNode(SkColorFilter** filter) c
}
bool SkColorFilterImageFilterImpl::affectsTransparentBlack() const {
- return fColorFilter->affectsTransparentBlack();
+ return as_CFB(fColorFilter)->affectsTransparentBlack();
}
diff --git a/chromium/third_party/skia/src/effects/imagefilters/SkDisplacementMapEffect.cpp b/chromium/third_party/skia/src/effects/imagefilters/SkDisplacementMapEffect.cpp
index aa926f89051..fe5fe87ccd4 100644
--- a/chromium/third_party/skia/src/effects/imagefilters/SkDisplacementMapEffect.cpp
+++ b/chromium/third_party/skia/src/effects/imagefilters/SkDisplacementMapEffect.cpp
@@ -17,7 +17,6 @@
#if SK_SUPPORT_GPU
#include "include/private/GrRecordingContext.h"
#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrColorSpaceXform.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrRecordingContextPriv.h"
@@ -338,7 +337,7 @@ sk_sp<SkSpecialImage> SkDisplacementMapEffectImpl::onFilterImage(const Context&
}
const auto isProtected = colorView.proxy()->isProtected();
- SkMatrix offsetMatrix = SkMatrix::MakeTrans(SkIntToScalar(colorOffset.fX - displOffset.fX),
+ SkMatrix offsetMatrix = SkMatrix::Translate(SkIntToScalar(colorOffset.fX - displOffset.fX),
SkIntToScalar(colorOffset.fY - displOffset.fY));
std::unique_ptr<GrFragmentProcessor> fp =
@@ -367,7 +366,7 @@ sk_sp<SkSpecialImage> SkDisplacementMapEffectImpl::onFilterImage(const Context&
return nullptr;
}
- renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix,
+ renderTargetContext->drawRect(nullptr, std::move(paint), GrAA::kNo, matrix,
SkRect::Make(colorBounds));
offset->fX = bounds.left();
@@ -472,12 +471,12 @@ std::unique_ptr<GrFragmentProcessor> GrDisplacementMapEffect::Make(SkColorChanne
GrSamplerState::Filter::kNearest);
auto colorEffect = GrTextureEffect::MakeSubset(std::move(color),
kPremul_SkAlphaType,
- SkMatrix::MakeTrans(colorSubset.topLeft()),
+ SkMatrix::Translate(colorSubset.topLeft()),
kColorSampler,
SkRect::Make(colorSubset),
caps);
- auto dispM = SkMatrix::Concat(SkMatrix::MakeTrans(displSubset.topLeft()), offsetMatrix);
+ auto dispM = SkMatrix::Concat(SkMatrix::Translate(displSubset.topLeft()), offsetMatrix);
auto dispEffect = GrTextureEffect::Make(std::move(displacement),
kPremul_SkAlphaType,
dispM,
@@ -509,9 +508,8 @@ GrDisplacementMapEffect::GrDisplacementMapEffect(SkColorChannel xChannelSelector
, fXChannelSelector(xChannelSelector)
, fYChannelSelector(yChannelSelector)
, fScale(scale) {
- this->registerChildProcessor(std::move(displacement));
- color->setSampledWithExplicitCoords();
- this->registerChildProcessor(std::move(color));
+ this->registerChild(std::move(displacement));
+ this->registerExplicitlySampledChild(std::move(color));
this->addCoordTransform(&fCoordTransform);
}
@@ -520,15 +518,7 @@ GrDisplacementMapEffect::GrDisplacementMapEffect(const GrDisplacementMapEffect&
, fXChannelSelector(that.fXChannelSelector)
, fYChannelSelector(that.fYChannelSelector)
, fScale(that.fScale) {
- auto displacement = that.childProcessor(0).clone();
- if (that.childProcessor(0).isSampledWithExplicitCoords()) {
- displacement->setSampledWithExplicitCoords();
- }
- this->registerChildProcessor(std::move(displacement));
-
- auto color = that.childProcessor(1).clone();
- color->setSampledWithExplicitCoords();
- this->registerChildProcessor(std::move(color));
+ this->cloneAndRegisterAllChildProcessors(that);
this->addCoordTransform(&fCoordTransform);
}
diff --git a/chromium/third_party/skia/src/effects/imagefilters/SkLightingImageFilter.cpp b/chromium/third_party/skia/src/effects/imagefilters/SkLightingImageFilter.cpp
index 89984d91c59..5181f11d64f 100644
--- a/chromium/third_party/skia/src/effects/imagefilters/SkLightingImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/imagefilters/SkLightingImageFilter.cpp
@@ -19,7 +19,6 @@
#if SK_SUPPORT_GPU
#include "include/private/GrRecordingContext.h"
#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrFragmentProcessor.h"
#include "src/gpu/GrPaint.h"
#include "src/gpu/GrRecordingContextPriv.h"
@@ -444,7 +443,6 @@ private:
void drawRect(GrRenderTargetContext*,
GrSurfaceProxyView srcView,
const SkMatrix& matrix,
- const GrClip& clip,
const SkRect& dstRect,
BoundaryMode boundaryMode,
const SkIRect* srcBounds,
@@ -461,7 +459,6 @@ private:
void SkLightingImageFilterInternal::drawRect(GrRenderTargetContext* renderTargetContext,
GrSurfaceProxyView srcView,
const SkMatrix& matrix,
- const GrClip& clip,
const SkRect& dstRect,
BoundaryMode boundaryMode,
const SkIRect* srcBounds,
@@ -472,8 +469,8 @@ void SkLightingImageFilterInternal::drawRect(GrRenderTargetContext* renderTarget
*renderTargetContext->caps());
paint.addColorFragmentProcessor(std::move(fp));
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
- renderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
- srcRect);
+ renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
+ dstRect, srcRect);
}
sk_sp<SkSpecialImage> SkLightingImageFilterInternal::filterImageGPU(
@@ -499,9 +496,6 @@ sk_sp<SkSpecialImage> SkLightingImageFilterInternal::filterImageGPU(
SkIRect dstIRect = SkIRect::MakeWH(offsetBounds.width(), offsetBounds.height());
SkRect dstRect = SkRect::Make(dstIRect);
- // setup new clip
- GrFixedClip clip(dstIRect);
-
const SkIRect inputBounds = SkIRect::MakeWH(input->width(), input->height());
SkRect topLeft = SkRect::MakeXYWH(0, 0, 1, 1);
SkRect top = SkRect::MakeXYWH(1, 0, dstRect.width() - 2, 1);
@@ -514,23 +508,23 @@ sk_sp<SkSpecialImage> SkLightingImageFilterInternal::filterImageGPU(
SkRect bottomRight = SkRect::MakeXYWH(dstRect.width() - 1, dstRect.height() - 1, 1, 1);
const SkIRect* pSrcBounds = inputBounds.contains(offsetBounds) ? nullptr : &inputBounds;
- this->drawRect(renderTargetContext.get(), inputView, matrix, clip, topLeft,
+ this->drawRect(renderTargetContext.get(), inputView, matrix, topLeft,
kTopLeft_BoundaryMode, pSrcBounds, offsetBounds);
- this->drawRect(renderTargetContext.get(), inputView, matrix, clip, top,
+ this->drawRect(renderTargetContext.get(), inputView, matrix, top,
kTop_BoundaryMode, pSrcBounds, offsetBounds);
- this->drawRect(renderTargetContext.get(), inputView, matrix, clip, topRight,
+ this->drawRect(renderTargetContext.get(), inputView, matrix, topRight,
kTopRight_BoundaryMode, pSrcBounds, offsetBounds);
- this->drawRect(renderTargetContext.get(), inputView, matrix, clip, left,
+ this->drawRect(renderTargetContext.get(), inputView, matrix, left,
kLeft_BoundaryMode, pSrcBounds, offsetBounds);
- this->drawRect(renderTargetContext.get(), inputView, matrix, clip, interior,
+ this->drawRect(renderTargetContext.get(), inputView, matrix, interior,
kInterior_BoundaryMode, pSrcBounds, offsetBounds);
- this->drawRect(renderTargetContext.get(), inputView, matrix, clip, right,
+ this->drawRect(renderTargetContext.get(), inputView, matrix, right,
kRight_BoundaryMode, pSrcBounds, offsetBounds);
- this->drawRect(renderTargetContext.get(), inputView, matrix, clip, bottomLeft,
+ this->drawRect(renderTargetContext.get(), inputView, matrix, bottomLeft,
kBottomLeft_BoundaryMode, pSrcBounds, offsetBounds);
- this->drawRect(renderTargetContext.get(), inputView, matrix, clip, bottom,
+ this->drawRect(renderTargetContext.get(), inputView, matrix, bottom,
kBottom_BoundaryMode, pSrcBounds, offsetBounds);
- this->drawRect(renderTargetContext.get(), std::move(inputView), matrix, clip, bottomRight,
+ this->drawRect(renderTargetContext.get(), std::move(inputView), matrix, bottomRight,
kBottomRight_BoundaryMode, pSrcBounds, offsetBounds);
return SkSpecialImage::MakeDeferredFromGpu(
@@ -1638,8 +1632,7 @@ GrLightingEffect::GrLightingEffect(ClassID classID,
child = GrTextureEffect::Make(std::move(view), kPremul_SkAlphaType, SkMatrix::I(), kSampler,
caps);
}
- child->setSampledWithExplicitCoords();
- this->registerChildProcessor(std::move(child));
+ this->registerExplicitlySampledChild(std::move(child));
this->addCoordTransform(&fCoordTransform);
}
@@ -1649,9 +1642,7 @@ GrLightingEffect::GrLightingEffect(const GrLightingEffect& that)
, fSurfaceScale(that.fSurfaceScale)
, fFilterMatrix(that.fFilterMatrix)
, fBoundaryMode(that.fBoundaryMode) {
- auto child = that.childProcessor(0).clone();
- child->setSampledWithExplicitCoords();
- this->registerChildProcessor(std::move(child));
+ this->cloneAndRegisterAllChildProcessors(that);
this->addCoordTransform(&fCoordTransform);
}
diff --git a/chromium/third_party/skia/src/effects/imagefilters/SkMagnifierImageFilter.cpp b/chromium/third_party/skia/src/effects/imagefilters/SkMagnifierImageFilter.cpp
index 835dd1a2dcd..4300a390681 100644
--- a/chromium/third_party/skia/src/effects/imagefilters/SkMagnifierImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/imagefilters/SkMagnifierImageFilter.cpp
@@ -19,8 +19,7 @@
#if SK_SUPPORT_GPU
#include "include/gpu/GrContext.h"
#include "src/gpu/GrColorSpaceXform.h"
-#include "src/gpu/GrCoordTransform.h"
-#include "src/gpu/GrTexture.h"
+#include "src/gpu/effects/GrTextureEffect.h"
#include "src/gpu/effects/generated/GrMagnifierEffect.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
@@ -136,9 +135,9 @@ sk_sp<SkSpecialImage> SkMagnifierImageFilterImpl::onFilterImage(const Context& c
bounds.offset(input->subset().x(), input->subset().y());
SkRect srcRect = fSrcRect.makeOffset((1.f - invXZoom) * input->subset().x(),
(1.f - invYZoom) * input->subset().y());
+ auto inputFP = GrTextureEffect::Make(std::move(inputView), kPremul_SkAlphaType);
- // TODO: Update generated fp file Make functions to take views instead of proxies
- auto fp = GrMagnifierEffect::Make(std::move(inputView),
+ auto fp = GrMagnifierEffect::Make(std::move(inputFP),
bounds,
srcRect,
invXZoom,
diff --git a/chromium/third_party/skia/src/effects/imagefilters/SkMorphologyImageFilter.cpp b/chromium/third_party/skia/src/effects/imagefilters/SkMorphologyImageFilter.cpp
index 6e024137d6d..35f35d7f8d6 100644
--- a/chromium/third_party/skia/src/effects/imagefilters/SkMorphologyImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/imagefilters/SkMorphologyImageFilter.cpp
@@ -20,7 +20,6 @@
#include "include/private/GrRecordingContext.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrCoordTransform.h"
-#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrTexture.h"
@@ -229,13 +228,6 @@ public:
new GrMorphologyEffect(std::move(view), srcAlphaType, dir, radius, type, bounds));
}
- MorphType type() const { return fType; }
- bool useRange() const { return fUseRange; }
- const float* range() const { return fRange; }
- MorphDirection direction() const { return fDirection; }
- int radius() const { return fRadius; }
- int width() const { return 2 * fRadius + 1; }
-
const char* name() const override { return "Morphology"; }
std::unique_ptr<GrFragmentProcessor> clone() const override {
@@ -243,8 +235,9 @@ public:
}
private:
- GrCoordTransform fCoordTransform;
- TextureSampler fTextureSampler;
+ // We really just want the unaltered local coords, but the only way to get that right now is
+ // an identity coord transform.
+ GrCoordTransform fCoordTransform = {};
MorphDirection fDirection;
int fRadius;
MorphType fType;
@@ -256,9 +249,6 @@ private:
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
bool onIsEqual(const GrFragmentProcessor&) const override;
-
- const TextureSampler& onTextureSampler(int i) const override { return fTextureSampler; }
-
GrMorphologyEffect(GrSurfaceProxyView, SkAlphaType srcAlphaType, MorphDirection, int radius,
MorphType, const float range[2]);
explicit GrMorphologyEffect(const GrMorphologyEffect&);
@@ -268,138 +258,81 @@ private:
typedef GrFragmentProcessor INHERITED;
};
-///////////////////////////////////////////////////////////////////////////////
-
-class GrGLMorphologyEffect : public GrGLSLFragmentProcessor {
-public:
- void emitCode(EmitArgs&) override;
-
- static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
-
-protected:
- void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
-
-private:
- GrGLSLProgramDataManager::UniformHandle fPixelSizeUni;
- GrGLSLProgramDataManager::UniformHandle fRangeUni;
-
- typedef GrGLSLFragmentProcessor INHERITED;
-};
-
-void GrGLMorphologyEffect::emitCode(EmitArgs& args) {
- const GrMorphologyEffect& me = args.fFp.cast<GrMorphologyEffect>();
-
- GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
- fPixelSizeUni = uniformHandler->addUniform(&me, kFragment_GrShaderFlag, kHalf_GrSLType,
- "PixelSize");
- const char* pixelSizeInc = uniformHandler->getUniformCStr(fPixelSizeUni);
- fRangeUni = uniformHandler->addUniform(&me, kFragment_GrShaderFlag, kFloat2_GrSLType, "Range");
- const char* range = uniformHandler->getUniformCStr(fRangeUni);
-
- GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
- SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint,
- args.fFp.sampleMatrix());
- const char* func;
- switch (me.type()) {
- case MorphType::kErode:
- fragBuilder->codeAppendf("\t\t%s = half4(1, 1, 1, 1);\n", args.fOutputColor);
- func = "min";
- break;
- case MorphType::kDilate:
- fragBuilder->codeAppendf("\t\t%s = half4(0, 0, 0, 0);\n", args.fOutputColor);
- func = "max";
- break;
- default:
- SK_ABORT("Unexpected type");
- func = ""; // suppress warning
- break;
- }
+GrGLSLFragmentProcessor* GrMorphologyEffect::onCreateGLSLInstance() const {
+ class Impl : public GrGLSLFragmentProcessor {
+ public:
+ void emitCode(EmitArgs& args) override {
+ const GrMorphologyEffect& me = args.fFp.cast<GrMorphologyEffect>();
+
+ GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
+ fRangeUni = uniformHandler->addUniform(&me, kFragment_GrShaderFlag, kFloat2_GrSLType,
+ "Range");
+ const char* range = uniformHandler->getUniformCStr(fRangeUni);
+
+ GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
+ SkString coords2D = fragBuilder->ensureCoords2D(
+ args.fTransformedCoords[0].fVaryingPoint, args.fFp.sampleMatrix());
+
+ const char* func = me.fType == MorphType::kErode ? "min" : "max";
+
+ char initialValue = me.fType == MorphType::kErode ? '1' : '0';
+ fragBuilder->codeAppendf("%s = half4(%c);", args.fOutputColor, initialValue);
+
+ char dir = me.fDirection == MorphDirection::kX ? 'x' : 'y';
+
+ int width = 2 * me.fRadius + 1;
+
+ // float2 coord = coord2D;
+ fragBuilder->codeAppendf("float2 coord = %s;", coords2D.c_str());
+ // coord.x -= radius;
+ fragBuilder->codeAppendf("coord.%c -= %d;", dir, me.fRadius);
+ if (me.fUseRange) {
+ // highBound = min(highBound, coord.x + (width-1));
+ fragBuilder->codeAppendf("float highBound = min(%s.y, coord.%c + %f);", range, dir,
+ float(width - 1));
+ // coord.x = max(lowBound, coord.x);
+ fragBuilder->codeAppendf("coord.%c = max(%s.x, coord.%c);", dir, range, dir);
+ }
+ fragBuilder->codeAppendf("for (int i = 0; i < %d; i++) {", width);
+ SkString sample = this->invokeChild(0, args, "coord");
+ fragBuilder->codeAppendf(" %s = %s(%s, %s);", args.fOutputColor, func,
+ args.fOutputColor, sample.c_str());
+ // coord.x += 1;
+ fragBuilder->codeAppendf(" coord.%c += 1;", dir);
+ if (me.fUseRange) {
+ // coord.x = min(highBound, coord.x);
+ fragBuilder->codeAppendf(" coord.%c = min(highBound, coord.%c);", dir, dir);
+ }
+ fragBuilder->codeAppend("}");
+ fragBuilder->codeAppendf("%s *= %s;", args.fOutputColor, args.fInputColor);
+ }
- const char* dir;
- switch (me.direction()) {
- case MorphDirection::kX:
- dir = "x";
- break;
- case MorphDirection::kY:
- dir = "y";
- break;
- default:
- SK_ABORT("Unknown filter direction.");
- dir = ""; // suppress warning
- }
+ protected:
+ void onSetData(const GrGLSLProgramDataManager& pdman,
+ const GrFragmentProcessor& proc) override {
+ const GrMorphologyEffect& m = proc.cast<GrMorphologyEffect>();
+ if (m.fUseRange) {
+ pdman.set2f(fRangeUni, m.fRange[0], m.fRange[1]);
+ }
+ }
- int width = me.width();
-
- // float2 coord = coord2D;
- fragBuilder->codeAppendf("\t\tfloat2 coord = %s;\n", coords2D.c_str());
- // coord.x -= radius * pixelSize;
- fragBuilder->codeAppendf("\t\tcoord.%s -= %d.0 * %s; \n", dir, me.radius(), pixelSizeInc);
- if (me.useRange()) {
- // highBound = min(highBound, coord.x + (width-1) * pixelSize);
- fragBuilder->codeAppendf("\t\tfloat highBound = min(%s.y, coord.%s + %f * %s);",
- range, dir, float(width - 1), pixelSizeInc);
- // coord.x = max(lowBound, coord.x);
- fragBuilder->codeAppendf("\t\tcoord.%s = max(%s.x, coord.%s);", dir, range, dir);
- }
- fragBuilder->codeAppendf("\t\tfor (int i = 0; i < %d; i++) {\n", width);
- fragBuilder->codeAppendf("\t\t\t%s = %s(%s, ", args.fOutputColor, func, args.fOutputColor);
- fragBuilder->appendTextureLookup(args.fTexSamplers[0], "coord");
- fragBuilder->codeAppend(");\n");
- // coord.x += pixelSize;
- fragBuilder->codeAppendf("\t\t\tcoord.%s += %s;\n", dir, pixelSizeInc);
- if (me.useRange()) {
- // coord.x = min(highBound, coord.x);
- fragBuilder->codeAppendf("\t\t\tcoord.%s = min(highBound, coord.%s);", dir, dir);
- }
- fragBuilder->codeAppend("\t\t}\n");
- fragBuilder->codeAppendf("%s *= %s;\n", args.fOutputColor, args.fInputColor);
+ private:
+ GrGLSLProgramDataManager::UniformHandle fRangeUni;
+ };
+ return new Impl;
}
-void GrGLMorphologyEffect::GenKey(const GrProcessor& proc,
- const GrShaderCaps&, GrProcessorKeyBuilder* b) {
- const GrMorphologyEffect& m = proc.cast<GrMorphologyEffect>();
- uint32_t key = static_cast<uint32_t>(m.radius());
- key |= (static_cast<uint32_t>(m.type()) << 8);
- key |= (static_cast<uint32_t>(m.direction()) << 9);
- if (m.useRange()) {
+void GrMorphologyEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
+ GrProcessorKeyBuilder* b) const {
+ uint32_t key = static_cast<uint32_t>(fRadius);
+ key |= (static_cast<uint32_t>(fType) << 8);
+ key |= (static_cast<uint32_t>(fDirection) << 9);
+ if (fUseRange) {
key |= 1 << 10;
}
b->add32(key);
}
-void GrGLMorphologyEffect::onSetData(const GrGLSLProgramDataManager& pdman,
- const GrFragmentProcessor& proc) {
- const GrMorphologyEffect& m = proc.cast<GrMorphologyEffect>();
- const auto& view = m.textureSampler(0).view();
- GrSurfaceProxy* proxy = view.proxy();
- GrTexture& texture = *proxy->peekTexture();
-
- float pixelSize = 0.0f;
- switch (m.direction()) {
- case MorphDirection::kX:
- pixelSize = 1.0f / texture.width();
- break;
- case MorphDirection::kY:
- pixelSize = 1.0f / texture.height();
- break;
- default:
- SK_ABORT("Unknown filter direction.");
- }
- pdman.set1f(fPixelSizeUni, pixelSize);
-
- if (m.useRange()) {
- const float* range = m.range();
- if (MorphDirection::kY == m.direction() &&
- view.origin() == kBottomLeft_GrSurfaceOrigin) {
- pdman.set2f(fRangeUni, 1.0f - (range[1]*pixelSize), 1.0f - (range[0]*pixelSize));
- } else {
- pdman.set2f(fRangeUni, range[0] * pixelSize, range[1] * pixelSize);
- }
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
GrMorphologyEffect::GrMorphologyEffect(GrSurfaceProxyView view,
SkAlphaType srcAlphaType,
MorphDirection direction,
@@ -407,17 +340,13 @@ GrMorphologyEffect::GrMorphologyEffect(GrSurfaceProxyView view,
MorphType type,
const float range[2])
: INHERITED(kGrMorphologyEffect_ClassID, ModulateForClampedSamplerOptFlags(srcAlphaType))
- , fCoordTransform(view.proxy(), view.origin())
- , fTextureSampler(std::move(view))
, fDirection(direction)
, fRadius(radius)
, fType(type)
, fUseRange(SkToBool(range)) {
- // Make sure the sampler's ctor uses the clamp wrap mode
- SkASSERT(fTextureSampler.samplerState().wrapModeX() == GrSamplerState::WrapMode::kClamp &&
- fTextureSampler.samplerState().wrapModeY() == GrSamplerState::WrapMode::kClamp);
this->addCoordTransform(&fCoordTransform);
- this->setTextureSamplerCnt(1);
+ auto te = GrTextureEffect::Make(std::move(view), srcAlphaType);
+ this->registerExplicitlySampledChild(std::move(te));
if (fUseRange) {
fRange[0] = range[0];
fRange[1] = range[1];
@@ -426,34 +355,24 @@ GrMorphologyEffect::GrMorphologyEffect(GrSurfaceProxyView view,
GrMorphologyEffect::GrMorphologyEffect(const GrMorphologyEffect& that)
: INHERITED(kGrMorphologyEffect_ClassID, that.optimizationFlags())
- , fCoordTransform(that.fCoordTransform)
- , fTextureSampler(that.fTextureSampler)
, fDirection(that.fDirection)
, fRadius(that.fRadius)
, fType(that.fType)
, fUseRange(that.fUseRange) {
this->addCoordTransform(&fCoordTransform);
- this->setTextureSamplerCnt(1);
+ this->cloneAndRegisterAllChildProcessors(that);
if (that.fUseRange) {
fRange[0] = that.fRange[0];
fRange[1] = that.fRange[1];
}
}
-void GrMorphologyEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
- GrProcessorKeyBuilder* b) const {
- GrGLMorphologyEffect::GenKey(*this, caps, b);
-}
-
-GrGLSLFragmentProcessor* GrMorphologyEffect::onCreateGLSLInstance() const {
- return new GrGLMorphologyEffect;
-}
bool GrMorphologyEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
const GrMorphologyEffect& s = sBase.cast<GrMorphologyEffect>();
- return (this->radius() == s.radius() &&
- this->direction() == s.direction() &&
- this->useRange() == s.useRange() &&
- this->type() == s.type());
+ return this->fRadius == s.fRadius &&
+ this->fDirection == s.fDirection &&
+ this->fUseRange == s.fUseRange &&
+ this->fType == s.fType;
}
///////////////////////////////////////////////////////////////////////////////
@@ -473,7 +392,6 @@ std::unique_ptr<GrFragmentProcessor> GrMorphologyEffect::TestCreate(GrProcessorT
#endif
static void apply_morphology_rect(GrRenderTargetContext* renderTargetContext,
- const GrClip& clip,
GrSurfaceProxyView view,
SkAlphaType srcAlphaType,
const SkIRect& srcRect,
@@ -486,12 +404,11 @@ static void apply_morphology_rect(GrRenderTargetContext* renderTargetContext,
paint.addColorFragmentProcessor(GrMorphologyEffect::Make(std::move(view), srcAlphaType,
direction, radius, morphType, bounds));
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
- renderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
+ renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
SkRect::Make(dstRect), SkRect::Make(srcRect));
}
static void apply_morphology_rect_no_bounds(GrRenderTargetContext* renderTargetContext,
- const GrClip& clip,
GrSurfaceProxyView view,
SkAlphaType srcAlphaType,
const SkIRect& srcRect,
@@ -503,12 +420,11 @@ static void apply_morphology_rect_no_bounds(GrRenderTargetContext* renderTargetC
paint.addColorFragmentProcessor(
GrMorphologyEffect::Make(std::move(view), srcAlphaType, direction, radius, morphType));
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
- renderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(),
+ renderTargetContext->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
SkRect::Make(dstRect), SkRect::Make(srcRect));
}
static void apply_morphology_pass(GrRenderTargetContext* renderTargetContext,
- const GrClip& clip,
GrSurfaceProxyView view,
SkAlphaType srcAlphaType,
const SkIRect& srcRect,
@@ -541,17 +457,16 @@ static void apply_morphology_pass(GrRenderTargetContext* renderTargetContext,
}
if (middleSrcRect.width() <= 0) {
// radius covers srcRect; use bounds over entire draw
- apply_morphology_rect(renderTargetContext, clip, std::move(view), srcAlphaType, srcRect,
+ apply_morphology_rect(renderTargetContext, std::move(view), srcAlphaType, srcRect,
dstRect, radius, morphType, bounds, direction);
} else {
// Draw upper and lower margins with bounds; middle without.
- apply_morphology_rect(renderTargetContext, clip, view, srcAlphaType, lowerSrcRect,
+ apply_morphology_rect(renderTargetContext, view, srcAlphaType, lowerSrcRect,
lowerDstRect, radius, morphType, bounds, direction);
- apply_morphology_rect(renderTargetContext, clip, view, srcAlphaType, upperSrcRect,
+ apply_morphology_rect(renderTargetContext, view, srcAlphaType, upperSrcRect,
upperDstRect, radius, morphType, bounds, direction);
- apply_morphology_rect_no_bounds(renderTargetContext, clip, std::move(view),
- srcAlphaType, middleSrcRect, middleDstRect, radius,
- morphType, direction);
+ apply_morphology_rect_no_bounds(renderTargetContext, std::move(view), srcAlphaType,
+ middleSrcRect, middleDstRect, radius, morphType, direction);
}
}
@@ -566,9 +481,6 @@ static sk_sp<SkSpecialImage> apply_morphology(
GrSurfaceProxy* proxy = srcView.proxy();
- // setup new clip
- const GrFixedClip clip(SkIRect::MakeSize(proxy->dimensions()));
-
const SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height());
SkIRect srcRect = rect;
// Map into proxy space
@@ -583,13 +495,13 @@ static sk_sp<SkSpecialImage> apply_morphology(
return nullptr;
}
- apply_morphology_pass(dstRTContext.get(), clip, std::move(srcView), srcAlphaType,
+ apply_morphology_pass(dstRTContext.get(), std::move(srcView), srcAlphaType,
srcRect, dstRect, radius.fWidth, morphType, MorphDirection::kX);
SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom,
dstRect.width(), radius.fHeight);
SkPMColor4f clearColor = MorphType::kErode == morphType
? SK_PMColor4fWHITE : SK_PMColor4fTRANSPARENT;
- dstRTContext->clear(&clearRect, clearColor, GrRenderTargetContext::CanClearFullscreen::kNo);
+ dstRTContext->clear(clearRect, clearColor);
srcView = dstRTContext->readSurfaceView();
srcAlphaType = dstRTContext->colorInfo().alphaType();
@@ -603,7 +515,7 @@ static sk_sp<SkSpecialImage> apply_morphology(
return nullptr;
}
- apply_morphology_pass(dstRTContext.get(), clip, std::move(srcView), srcAlphaType,
+ apply_morphology_pass(dstRTContext.get(), std::move(srcView), srcAlphaType,
srcRect, dstRect, radius.fHeight, morphType, MorphDirection::kY);
srcView = dstRTContext->readSurfaceView();
diff --git a/chromium/third_party/skia/src/effects/imagefilters/SkXfermodeImageFilter.cpp b/chromium/third_party/skia/src/effects/imagefilters/SkXfermodeImageFilter.cpp
index 84a2764e2c4..7569e1726e4 100644
--- a/chromium/third_party/skia/src/effects/imagefilters/SkXfermodeImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/imagefilters/SkXfermodeImageFilter.cpp
@@ -17,7 +17,6 @@
#if SK_SUPPORT_GPU
#include "include/private/GrRecordingContext.h"
#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrColorSpaceXform.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
@@ -264,7 +263,7 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilterImpl::filterImageGPU(
if (backgroundView.asTextureProxy()) {
SkRect bgSubset = SkRect::Make(background->subset());
- SkMatrix bgMatrix = SkMatrix::MakeTrans(
+ SkMatrix bgMatrix = SkMatrix::Translate(
SkIntToScalar(bgSubset.left() - backgroundOffset.fX),
SkIntToScalar(bgSubset.top() - backgroundOffset.fY));
bgFP = GrTextureEffect::MakeSubset(std::move(backgroundView), background->alphaType(),
@@ -273,13 +272,13 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilterImpl::filterImageGPU(
background->alphaType(),
ctx.colorSpace());
} else {
- bgFP = GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
+ bgFP = GrConstColorProcessor::Make(/*inputFP=*/nullptr, SK_PMColor4fTRANSPARENT,
GrConstColorProcessor::InputMode::kIgnore);
}
if (foregroundView.asTextureProxy()) {
SkRect fgSubset = SkRect::Make(foreground->subset());
- SkMatrix fgMatrix = SkMatrix::MakeTrans(
+ SkMatrix fgMatrix = SkMatrix::Translate(
SkIntToScalar(fgSubset.left() - foregroundOffset.fX),
SkIntToScalar(fgSubset.top() - foregroundOffset.fY));
auto fgFP = GrTextureEffect::MakeSubset(std::move(foregroundView), foreground->alphaType(),
@@ -310,7 +309,7 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilterImpl::filterImageGPU(
SkMatrix matrix;
matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
- renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix,
+ renderTargetContext->drawRect(nullptr, std::move(paint), GrAA::kNo, matrix,
SkRect::Make(bounds));
return SkSpecialImage::MakeDeferredFromGpu(context,
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) {
diff --git a/chromium/third_party/skia/src/image/SkImage.cpp b/chromium/third_party/skia/src/image/SkImage.cpp
index cbfc769f1ed..4b5afd889e6 100644
--- a/chromium/third_party/skia/src/image/SkImage.cpp
+++ b/chromium/third_party/skia/src/image/SkImage.cpp
@@ -84,7 +84,14 @@ sk_sp<SkColorSpace> SkImage::refColorSpace() const { return fInfo.refColorSpace(
sk_sp<SkShader> SkImage::makeShader(SkTileMode tmx, SkTileMode tmy,
const SkMatrix* localMatrix) const {
- return SkImageShader::Make(sk_ref_sp(const_cast<SkImage*>(this)), tmx, tmy, localMatrix);
+ return SkImageShader::Make(sk_ref_sp(const_cast<SkImage*>(this)), tmx, tmy, localMatrix,
+ SkImageShader::kInheritFromPaint);
+}
+
+sk_sp<SkShader> SkImage::makeShader(SkTileMode tmx, SkTileMode tmy,
+ const SkMatrix* localMatrix, SkFilterQuality filtering) const {
+ return SkImageShader::Make(sk_ref_sp(const_cast<SkImage*>(this)), tmx, tmy, localMatrix,
+ SkImageShader::FilterEnum(filtering));
}
sk_sp<SkData> SkImage::encodeToData(SkEncodedImageFormat type, int quality) const {
@@ -160,7 +167,10 @@ GrSemaphoresSubmitted SkImage::flush(GrContext* context, const GrFlushInfo& flus
return as_IB(this)->onFlush(context, flushInfo);
}
-void SkImage::flush(GrContext* context) { as_IB(this)->onFlush(context, {}); }
+void SkImage::flushAndSubmit(GrContext* context) {
+ this->flush(context, {});
+ context->submit();
+}
#else
@@ -182,7 +192,7 @@ GrSemaphoresSubmitted SkImage::flush(GrContext*, const GrFlushInfo&) {
return GrSemaphoresSubmitted::kNo;
}
-void SkImage::flush(GrContext*) {}
+void SkImage::flushAndSubmit(GrContext*) {}
#endif
@@ -281,7 +291,7 @@ sk_sp<SkImage> SkImage::makeWithFilter(GrContext* grContext,
// subset's top left corner. But the clip bounds and any crop rects on the filters are in the
// original coordinate system, so configure the CTM to correct crop rects and explicitly adjust
// the clip bounds (since it is assumed to already be in image space).
- SkImageFilter_Base::Context context(SkMatrix::MakeTrans(-subset.x(), -subset.y()),
+ SkImageFilter_Base::Context context(SkMatrix::Translate(-subset.x(), -subset.y()),
clipBounds.makeOffset(-subset.topLeft()),
cache.get(), fInfo.colorType(), fInfo.colorSpace(),
srcSpecialImage.get());
diff --git a/chromium/third_party/skia/src/image/SkImage_Gpu.cpp b/chromium/third_party/skia/src/image/SkImage_Gpu.cpp
index 13b1917e191..ae1feee6e47 100644
--- a/chromium/third_party/skia/src/image/SkImage_Gpu.cpp
+++ b/chromium/third_party/skia/src/image/SkImage_Gpu.cpp
@@ -22,9 +22,9 @@
#include "src/gpu/GrAHardwareBufferImageGenerator.h"
#include "src/gpu/GrAHardwareBufferUtils.h"
#include "src/gpu/GrBackendTextureImageGenerator.h"
+#include "src/gpu/GrBackendUtils.h"
#include "src/gpu/GrBitmapTextureMaker.h"
#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrColorSpaceXform.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrDrawingManager.h"
@@ -67,6 +67,12 @@ SkImage_Gpu::~SkImage_Gpu() {}
GrSemaphoresSubmitted SkImage_Gpu::onFlush(GrContext* context, const GrFlushInfo& info) {
if (!context || !fContext->priv().matches(context) || fContext->abandoned()) {
+ if (info.fSubmittedProc) {
+ info.fSubmittedProc(info.fSubmittedContext, false);
+ }
+ if (info.fFinishedProc) {
+ info.fFinishedProc(info.fFinishedContext);
+ }
return GrSemaphoresSubmitted::kNo;
}
@@ -99,7 +105,7 @@ sk_sp<SkImage> SkImage_Gpu::onMakeColorTypeAndColorSpace(GrRecordingContext* con
paint.addColorFragmentProcessor(std::move(xform));
}
- renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+ renderTargetContext->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
SkRect::MakeIWH(this->width(), this->height()));
if (!renderTargetContext->asTextureProxy()) {
return nullptr;
@@ -124,15 +130,14 @@ static sk_sp<SkImage> new_wrapped_texture_common(GrContext* ctx,
GrColorType colorType, GrSurfaceOrigin origin,
SkAlphaType at, sk_sp<SkColorSpace> colorSpace,
GrWrapOwnership ownership,
- SkImage::TextureReleaseProc releaseProc,
- SkImage::ReleaseContext releaseCtx) {
+ sk_sp<GrRefCntedCallback> releaseHelper) {
if (!backendTex.isValid() || backendTex.width() <= 0 || backendTex.height() <= 0) {
return nullptr;
}
GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
sk_sp<GrTextureProxy> proxy = proxyProvider->wrapBackendTexture(
- backendTex, ownership, GrWrapCacheable::kNo, kRead_GrIOType, releaseProc, releaseCtx);
+ backendTex, ownership, GrWrapCacheable::kNo, kRead_GrIOType, std::move(releaseHelper));
if (!proxy) {
return nullptr;
}
@@ -150,6 +155,11 @@ sk_sp<SkImage> SkImage::MakeFromCompressedTexture(GrContext* ctx,
sk_sp<SkColorSpace> cs,
TextureReleaseProc releaseP,
ReleaseContext releaseC) {
+ sk_sp<GrRefCntedCallback> releaseHelper;
+ if (releaseP) {
+ releaseHelper.reset(new GrRefCntedCallback(releaseP, releaseC));
+ }
+
if (!ctx) {
return nullptr;
}
@@ -162,12 +172,12 @@ sk_sp<SkImage> SkImage::MakeFromCompressedTexture(GrContext* ctx,
GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
sk_sp<GrTextureProxy> proxy = proxyProvider->wrapCompressedBackendTexture(
- tex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, releaseP, releaseC);
+ tex, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, std::move(releaseHelper));
if (!proxy) {
return nullptr;
}
- CompressionType type = caps->compressionType(tex.getBackendFormat());
+ CompressionType type = GrBackendFormatToCompressionType(tex.getBackendFormat());
SkColorType ct = GrCompressionTypeToSkColorType(type);
GrSurfaceProxyView view(std::move(proxy), origin, GrSwizzle::RGBA());
@@ -179,6 +189,13 @@ sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
const GrBackendTexture& tex, GrSurfaceOrigin origin,
SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs,
TextureReleaseProc releaseP, ReleaseContext releaseC) {
+#ifndef SK_LEGACY_MAKEFROMTEXTURE_BEHAVIOR
+ sk_sp<GrRefCntedCallback> releaseHelper;
+ if (releaseP) {
+ releaseHelper.reset(new GrRefCntedCallback(releaseP, releaseC));
+ }
+#endif
+
if (!ctx) {
return nullptr;
}
@@ -194,8 +211,15 @@ sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
return nullptr;
}
+#ifdef SK_LEGACY_MAKEFROMTEXTURE_BEHAVIOR
+ sk_sp<GrRefCntedCallback> releaseHelper;
+ if (releaseP) {
+ releaseHelper.reset(new GrRefCntedCallback(releaseP, releaseC));
+ }
+#endif
+
return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
- kBorrow_GrWrapOwnership, releaseP, releaseC);
+ kBorrow_GrWrapOwnership, std::move(releaseHelper));
}
sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
@@ -219,7 +243,7 @@ sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
}
return new_wrapped_texture_common(ctx, tex, grColorType, origin, at, std::move(cs),
- kAdopt_GrWrapOwnership, nullptr, nullptr);
+ kAdopt_GrWrapOwnership, nullptr);
}
sk_sp<SkImage> SkImage::MakeTextureFromCompressed(GrContext* context, sk_sp<SkData> data,
@@ -267,7 +291,7 @@ sk_sp<SkImage> SkImage_Gpu::ConvertYUVATexturesToRGB(GrContext* ctx, SkYUVColorS
GrSurfaceProxyView tempViews[4];
if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, yuvaIndices,
- origin, tempViews)) {
+ origin, tempViews, nullptr)) {
return nullptr;
}
@@ -316,6 +340,11 @@ sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
ReleaseContext releaseContext) {
const GrCaps* caps = ctx->priv().caps();
+ sk_sp<GrRefCntedCallback> releaseHelper;
+ if (textureReleaseProc) {
+ releaseHelper.reset(new GrRefCntedCallback(textureReleaseProc, releaseContext));
+ }
+
GrColorType grColorType = SkColorTypeAndFormatToGrColorType(caps, kRGBA_8888_SkColorType,
backendTexture.getBackendFormat());
if (GrColorType::kUnknown == grColorType) {
@@ -332,7 +361,7 @@ sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
// in order to draw to it for the yuv->rgb conversion.
auto renderTargetContext = GrRenderTargetContext::MakeFromBackendTexture(
ctx, grColorType, std::move(imageColorSpace), backendTexture, 1, imageOrigin,
- nullptr, textureReleaseProc, releaseContext);
+ nullptr, std::move(releaseHelper));
if (!renderTargetContext) {
return nullptr;
}
@@ -517,6 +546,10 @@ sk_sp<SkImage> SkImage_Gpu::MakePromiseTexture(GrContext* context,
return nullptr;
}
+ if (!context->priv().caps()->areColorTypeAndFormatCompatible(grColorType, backendFormat)) {
+ return nullptr;
+ }
+
callDone.clear();
auto proxy = MakePromiseImageLazyProxy(context, width, height, backendFormat,
mipMapped, textureFulfillProc, textureReleaseProc,
@@ -634,6 +667,9 @@ sk_sp<SkImage> SkImage::MakeFromAHardwareBufferWithData(GrContext* context,
}
SkASSERT(deleteImageProc);
+ sk_sp<GrRefCntedCallback> releaseHelper(new GrRefCntedCallback(deleteImageProc,
+ deleteImageCtx));
+
SkColorType colorType =
GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
@@ -641,15 +677,13 @@ sk_sp<SkImage> SkImage::MakeFromAHardwareBufferWithData(GrContext* context,
GrProxyProvider* proxyProvider = context->priv().proxyProvider();
if (!proxyProvider) {
- deleteImageProc(deleteImageCtx);
return nullptr;
}
sk_sp<GrTextureProxy> proxy = proxyProvider->wrapBackendTexture(
backendTexture, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType,
- deleteImageProc, deleteImageCtx);
+ std::move(releaseHelper));
if (!proxy) {
- deleteImageProc(deleteImageCtx);
return nullptr;
}
@@ -680,8 +714,7 @@ sk_sp<SkImage> SkImage::MakeFromAHardwareBufferWithData(GrContext* context,
GrFlushInfo info;
info.fFlags = kSyncCpu_GrFlushFlag;
GrSurfaceProxy* p[1] = {surfaceContext.asSurfaceProxy()};
- drawingManager->flush(p, 1, SkSurface::BackendSurfaceAccess::kNoAccess, info,
- GrPrepareForExternalIORequests());
+ drawingManager->flush(p, 1, SkSurface::BackendSurfaceAccess::kNoAccess, info, nullptr);
return image;
}
diff --git a/chromium/third_party/skia/src/image/SkImage_GpuBase.cpp b/chromium/third_party/skia/src/image/SkImage_GpuBase.cpp
index e156e4e368f..07b8b8a4445 100644
--- a/chromium/third_party/skia/src/image/SkImage_GpuBase.cpp
+++ b/chromium/third_party/skia/src/image/SkImage_GpuBase.cpp
@@ -13,7 +13,6 @@
#include "include/private/GrRecordingContext.h"
#include "src/core/SkBitmapCache.h"
#include "src/core/SkTLList.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrImageInfo.h"
#include "src/gpu/GrProxyProvider.h"
@@ -262,10 +261,13 @@ bool SkImage_GpuBase::onIsValid(GrContext* context) const {
return true;
}
-bool SkImage_GpuBase::MakeTempTextureProxies(GrContext* ctx, const GrBackendTexture yuvaTextures[],
- int numTextures, const SkYUVAIndex yuvaIndices[4],
+bool SkImage_GpuBase::MakeTempTextureProxies(GrContext* ctx,
+ const GrBackendTexture yuvaTextures[],
+ int numTextures,
+ const SkYUVAIndex yuvaIndices[4],
GrSurfaceOrigin imageOrigin,
- GrSurfaceProxyView tempViews[4]) {
+ GrSurfaceProxyView tempViews[4],
+ sk_sp<GrRefCntedCallback> releaseHelper) {
GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
for (int textureIndex = 0; textureIndex < numTextures; ++textureIndex) {
const GrBackendFormat& backendFormat = yuvaTextures[textureIndex].getBackendFormat();
@@ -277,7 +279,8 @@ bool SkImage_GpuBase::MakeTempTextureProxies(GrContext* ctx, const GrBackendText
auto proxy = proxyProvider->wrapBackendTexture(yuvaTextures[textureIndex],
kBorrow_GrWrapOwnership,
- GrWrapCacheable::kNo, kRead_GrIOType);
+ GrWrapCacheable::kNo, kRead_GrIOType,
+ releaseHelper);
if (!proxy) {
return false;
}
@@ -323,7 +326,7 @@ bool SkImage_GpuBase::RenderYUVAToRGBA(GrContext* ctx, GrRenderTargetContext* re
}
paint.addColorFragmentProcessor(std::move(fp));
- renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect);
+ renderTargetContext->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(), rect);
return true;
}
diff --git a/chromium/third_party/skia/src/image/SkImage_GpuBase.h b/chromium/third_party/skia/src/image/SkImage_GpuBase.h
index 67b53c8eda9..ae332fc9722 100644
--- a/chromium/third_party/skia/src/image/SkImage_GpuBase.h
+++ b/chromium/third_party/skia/src/image/SkImage_GpuBase.h
@@ -55,7 +55,8 @@ public:
static bool MakeTempTextureProxies(GrContext* ctx, const GrBackendTexture yuvaTextures[],
int numTextures, const SkYUVAIndex [4],
GrSurfaceOrigin imageOrigin,
- GrSurfaceProxyView tempViews[4]);
+ GrSurfaceProxyView tempViews[4],
+ sk_sp<GrRefCntedCallback> releaseHelper);
static SkAlphaType GetAlphaTypeFromYUVAIndices(const SkYUVAIndex yuvaIndices[4]) {
return -1 != yuvaIndices[SkYUVAIndex::kA_Index].fIndex ? kPremul_SkAlphaType
diff --git a/chromium/third_party/skia/src/image/SkImage_GpuYUVA.cpp b/chromium/third_party/skia/src/image/SkImage_GpuYUVA.cpp
index 8aa15cbff39..0a76fedd1e7 100644
--- a/chromium/third_party/skia/src/image/SkImage_GpuYUVA.cpp
+++ b/chromium/third_party/skia/src/image/SkImage_GpuYUVA.cpp
@@ -117,6 +117,12 @@ bool SkImage_GpuYUVA::setupMipmapsForPlanes(GrRecordingContext* context) const {
GrSemaphoresSubmitted SkImage_GpuYUVA::onFlush(GrContext* context, const GrFlushInfo& info) {
if (!context || !fContext->priv().matches(context) || fContext->abandoned()) {
+ if (info.fSubmittedProc) {
+ info.fSubmittedProc(info.fSubmittedContext, false);
+ }
+ if (info.fFinishedProc) {
+ info.fFinishedProc(info.fFinishedContext);
+ }
return GrSemaphoresSubmitted::kNo;
}
@@ -229,7 +235,14 @@ sk_sp<SkImage> SkImage::MakeFromYUVATextures(GrContext* ctx,
const SkYUVAIndex yuvaIndices[4],
SkISize imageSize,
GrSurfaceOrigin imageOrigin,
- sk_sp<SkColorSpace> imageColorSpace) {
+ sk_sp<SkColorSpace> imageColorSpace,
+ TextureReleaseProc textureReleaseProc,
+ ReleaseContext releaseContext) {
+ sk_sp<GrRefCntedCallback> releaseHelper;
+ if (textureReleaseProc) {
+ releaseHelper.reset(new GrRefCntedCallback(textureReleaseProc, releaseContext));
+ }
+
int numTextures;
if (!SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures)) {
return nullptr;
@@ -237,7 +250,8 @@ sk_sp<SkImage> SkImage::MakeFromYUVATextures(GrContext* ctx,
GrSurfaceProxyView tempViews[4];
if (!SkImage_GpuBase::MakeTempTextureProxies(ctx, yuvaTextures, numTextures, yuvaIndices,
- imageOrigin, tempViews)) {
+ imageOrigin, tempViews,
+ std::move(releaseHelper))) {
return nullptr;
}
diff --git a/chromium/third_party/skia/src/image/SkImage_Lazy.cpp b/chromium/third_party/skia/src/image/SkImage_Lazy.cpp
index fbfaac6dfa5..47be6901c23 100644
--- a/chromium/third_party/skia/src/image/SkImage_Lazy.cpp
+++ b/chromium/third_party/skia/src/image/SkImage_Lazy.cpp
@@ -128,7 +128,6 @@ SkImage_Lazy::SkImage_Lazy(Validator* validator)
, fSharedGenerator(std::move(validator->fSharedGenerator))
, fOrigin(validator->fOrigin) {
SkASSERT(fSharedGenerator);
- fUniqueID = validator->fUniqueID;
}
diff --git a/chromium/third_party/skia/src/image/SkImage_Lazy.h b/chromium/third_party/skia/src/image/SkImage_Lazy.h
index f27881401d0..dd18780f8e5 100644
--- a/chromium/third_party/skia/src/image/SkImage_Lazy.h
+++ b/chromium/third_party/skia/src/image/SkImage_Lazy.h
@@ -82,8 +82,6 @@ private:
sk_sp<SharedGenerator> fSharedGenerator;
const SkIPoint fOrigin;
- uint32_t fUniqueID;
-
// Repeated calls to onMakeColorTypeAndColorSpace will result in a proliferation of unique IDs
// and SkImage_Lazy instances. Cache the result of the last successful call.
mutable SkMutex fOnMakeColorTypeAndSpaceMutex;
diff --git a/chromium/third_party/skia/src/image/SkSurface.cpp b/chromium/third_party/skia/src/image/SkSurface.cpp
index db8ec537862..18a125e11e3 100644
--- a/chromium/third_party/skia/src/image/SkSurface.cpp
+++ b/chromium/third_party/skia/src/image/SkSurface.cpp
@@ -444,43 +444,13 @@ bool SkSurface::replaceBackendTexture(const GrBackendTexture& backendTexture,
releaseContext);
}
-void SkSurface::flushAndSubmit() {
- this->flush(BackendSurfaceAccess::kNoAccess, GrFlushInfo());
-}
-
GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, const GrFlushInfo& flushInfo) {
- return asSB(this)->onFlush(access, flushInfo);
-}
-
-GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, GrFlushFlags flags,
- int numSemaphores, GrBackendSemaphore signalSemaphores[],
- GrGpuFinishedProc finishedProc,
- GrGpuFinishedContext finishedContext) {
- GrFlushInfo info;
- info.fFlags = flags;
- info.fNumSemaphores = numSemaphores;
- info.fSignalSemaphores = signalSemaphores;
- info.fFinishedProc = finishedProc;
- info.fFinishedContext = finishedContext;
- return this->flush(access, info);
+ return asSB(this)->onFlush(access, flushInfo, nullptr);
}
-GrSemaphoresSubmitted SkSurface::flush(BackendSurfaceAccess access, FlushFlags flags,
- int numSemaphores, GrBackendSemaphore signalSemaphores[]) {
- GrFlushFlags grFlags = flags == kSyncCpu_FlushFlag ? kSyncCpu_GrFlushFlag : kNone_GrFlushFlags;
- GrFlushInfo info;
- info.fFlags = grFlags;
- info.fNumSemaphores = numSemaphores;
- info.fSignalSemaphores = signalSemaphores;
- return this->flush(access, info);
-}
-
-GrSemaphoresSubmitted SkSurface::flushAndSignalSemaphores(int numSemaphores,
- GrBackendSemaphore signalSemaphores[]) {
- GrFlushInfo info;
- info.fNumSemaphores = numSemaphores;
- info.fSignalSemaphores = signalSemaphores;
- return this->flush(BackendSurfaceAccess::kNoAccess, info);
+GrSemaphoresSubmitted SkSurface::flush(const GrFlushInfo& info,
+ const GrBackendSurfaceMutableState* newState) {
+ return asSB(this)->onFlush(BackendSurfaceAccess::kNoAccess, info, newState);
}
bool SkSurface::wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
@@ -558,14 +528,8 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext*,
return nullptr;
}
-sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext*,
- const GrBackendTexture&,
- GrSurfaceOrigin origin,
- int sampleCnt,
- SkColorType,
- sk_sp<SkColorSpace>,
- const SkSurfaceProps*) {
- return nullptr;
+void SkSurface::flushAndSubmit() {
+ this->flush(BackendSurfaceAccess::kNoAccess, GrFlushInfo());
}
#endif
diff --git a/chromium/third_party/skia/src/image/SkSurface_Base.h b/chromium/third_party/skia/src/image/SkSurface_Base.h
index b38edd8d9f2..e4b750c6d03 100644
--- a/chromium/third_party/skia/src/image/SkSurface_Base.h
+++ b/chromium/third_party/skia/src/image/SkSurface_Base.h
@@ -107,7 +107,8 @@ public:
* Inserts the requested number of semaphores for the gpu to signal when work is complete on the
* gpu and inits the array of GrBackendSemaphores with the signaled semaphores.
*/
- virtual GrSemaphoresSubmitted onFlush(BackendSurfaceAccess access, const GrFlushInfo&) {
+ virtual GrSemaphoresSubmitted onFlush(BackendSurfaceAccess access, const GrFlushInfo&,
+ const GrBackendSurfaceMutableState*) {
return GrSemaphoresSubmitted::kNo;
}
diff --git a/chromium/third_party/skia/src/image/SkSurface_Gpu.cpp b/chromium/third_party/skia/src/image/SkSurface_Gpu.cpp
index 173af27fb99..3113b805bb4 100644
--- a/chromium/third_party/skia/src/image/SkSurface_Gpu.cpp
+++ b/chromium/third_party/skia/src/image/SkSurface_Gpu.cpp
@@ -5,12 +5,15 @@
* found in the LICENSE file.
*/
+#include "src/image/SkSurface_Gpu.h"
+
#include "include/core/SkCanvas.h"
#include "include/core/SkDeferredDisplayList.h"
#include "include/core/SkSurfaceCharacterization.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/private/GrRecordingContext.h"
#include "src/core/SkImagePriv.h"
+#include "src/core/SkScopeExit.h"
#include "src/gpu/GrAHardwareBufferUtils.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrContextPriv.h"
@@ -24,7 +27,6 @@
#include "src/image/SkImage_Base.h"
#include "src/image/SkImage_Gpu.h"
#include "src/image/SkSurface_Base.h"
-#include "src/image/SkSurface_Gpu.h"
#if SK_SUPPORT_GPU
@@ -54,7 +56,7 @@ static GrRenderTarget* prepare_rt_for_external_access(SkSurface_Gpu* surface,
}
// Grab the render target *after* firing notifications, as it may get switched if CoW kicks in.
- surface->getDevice()->flush(SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo());
+ surface->getDevice()->flush(SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo(), nullptr);
GrRenderTargetContext* rtc = surface->getDevice()->accessRenderTargetContext();
return rtc->accessRenderTarget();
}
@@ -185,9 +187,9 @@ void SkSurface_Gpu::onDiscard() {
fDevice->accessRenderTargetContext()->discard();
}
-GrSemaphoresSubmitted SkSurface_Gpu::onFlush(BackendSurfaceAccess access,
- const GrFlushInfo& info) {
- return fDevice->flush(access, info);
+GrSemaphoresSubmitted SkSurface_Gpu::onFlush(BackendSurfaceAccess access, const GrFlushInfo& info,
+ const GrBackendSurfaceMutableState* newState) {
+ return fDevice->flush(access, info, newState);
}
bool SkSurface_Gpu::onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) {
@@ -233,7 +235,6 @@ void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPai
// If the dst is also GPU we try to not force a new image snapshot (by calling the base class
// onDraw) since that may not always perform the copy-on-write optimization.
auto tryDraw = [&] {
- SkASSERT(fDevice->context()->priv().asDirectContext());
GrContext* context = fDevice->context();
GrContext* canvasContext = canvas->getGrContext();
if (!canvasContext) {
@@ -418,6 +419,11 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext* context,
const GrBackendTexture& backendTexture,
TextureReleaseProc textureReleaseProc,
ReleaseContext releaseContext) {
+ sk_sp<GrRefCntedCallback> releaseHelper;
+ if (textureReleaseProc) {
+ releaseHelper.reset(new GrRefCntedCallback(textureReleaseProc, releaseContext));
+ }
+
if (!context || !c.isValid()) {
return nullptr;
}
@@ -444,7 +450,7 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext* context,
auto rtc = GrRenderTargetContext::MakeFromBackendTexture(
context, grCT, c.refColorSpace(), backendTexture, c.sampleCount(), c.origin(),
- &c.surfaceProps(), textureReleaseProc, releaseContext);
+ &c.surfaceProps(), std::move(releaseHelper));
if (!rtc) {
return nullptr;
}
@@ -508,6 +514,11 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext* context, const GrB
const SkSurfaceProps* props,
SkSurface::TextureReleaseProc textureReleaseProc,
SkSurface::ReleaseContext releaseContext) {
+ sk_sp<GrRefCntedCallback> releaseHelper;
+ if (textureReleaseProc) {
+ releaseHelper.reset(new GrRefCntedCallback(textureReleaseProc, releaseContext));
+ }
+
if (!context) {
return nullptr;
}
@@ -525,7 +536,7 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext* context, const GrB
auto rtc = GrRenderTargetContext::MakeFromBackendTexture(
context, grColorType, std::move(colorSpace), tex, sampleCnt, origin, props,
- textureReleaseProc, releaseContext);
+ std::move(releaseHelper));
if (!rtc) {
return nullptr;
}
@@ -538,8 +549,15 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTexture(GrContext* context, const GrB
}
bool SkSurface_Gpu::onReplaceBackendTexture(const GrBackendTexture& backendTexture,
- GrSurfaceOrigin origin, ContentChangeMode mode, TextureReleaseProc releaseProc,
+ GrSurfaceOrigin origin,
+ ContentChangeMode mode,
+ TextureReleaseProc releaseProc,
ReleaseContext releaseContext) {
+ sk_sp<GrRefCntedCallback> releaseHelper;
+ if (releaseProc) {
+ releaseHelper.reset(new GrRefCntedCallback(releaseProc, releaseContext));
+ }
+
auto context = this->fDevice->context();
if (context->abandoned()) {
return false;
@@ -578,7 +596,7 @@ bool SkSurface_Gpu::onReplaceBackendTexture(const GrBackendTexture& backendTextu
}
auto rtc = GrRenderTargetContext::MakeFromBackendTexture(
context, oldRTC->colorInfo().colorType(), std::move(colorSpace), backendTexture,
- sampleCnt, origin, &this->props(), releaseProc, releaseContext);
+ sampleCnt, origin, &this->props(), std::move(releaseHelper));
if (!rtc) {
return false;
}
@@ -606,6 +624,12 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext* context,
const SkSurfaceProps* props,
SkSurface::RenderTargetReleaseProc relProc,
SkSurface::ReleaseContext releaseContext) {
+ SkScopeExit callProc([&] {
+ if (relProc) {
+ relProc(releaseContext);
+ }
+ });
+
if (!context) {
return nullptr;
}
@@ -626,6 +650,7 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext* context,
if (!rtc) {
return nullptr;
}
+ callProc.clear();
auto device = SkGpuDevice::Make(context, std::move(rtc), SkGpuDevice::kUninit_InitContents);
if (!device) {
@@ -635,6 +660,7 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendRenderTarget(GrContext* context,
return sk_make_sp<SkSurface_Gpu>(std::move(device));
}
+#if GR_TEST_UTILS
sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext* context,
const GrBackendTexture& tex,
GrSurfaceOrigin origin,
@@ -668,6 +694,7 @@ sk_sp<SkSurface> SkSurface::MakeFromBackendTextureAsRenderTarget(GrContext* cont
}
return sk_make_sp<SkSurface_Gpu>(std::move(device));
}
+#endif
#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
sk_sp<SkSurface> SkSurface::MakeFromAHardwareBuffer(GrContext* context,
@@ -732,4 +759,11 @@ sk_sp<SkSurface> SkSurface::MakeFromAHardwareBuffer(GrContext* context,
}
#endif
+void SkSurface::flushAndSubmit() {
+ this->flush(BackendSurfaceAccess::kNoAccess, GrFlushInfo());
+ if (this->getContext()) {
+ this->getContext()->submit();
+ }
+}
+
#endif
diff --git a/chromium/third_party/skia/src/image/SkSurface_Gpu.h b/chromium/third_party/skia/src/image/SkSurface_Gpu.h
index 9ee67dc360b..0667b33a1e7 100644
--- a/chromium/third_party/skia/src/image/SkSurface_Gpu.h
+++ b/chromium/third_party/skia/src/image/SkSurface_Gpu.h
@@ -51,7 +51,8 @@ public:
void onCopyOnWrite(ContentChangeMode) override;
void onDiscard() override;
- GrSemaphoresSubmitted onFlush(BackendSurfaceAccess access, const GrFlushInfo& info) override;
+ GrSemaphoresSubmitted onFlush(BackendSurfaceAccess access, const GrFlushInfo& info,
+ const GrBackendSurfaceMutableState*) override;
bool onWait(int numSemaphores, const GrBackendSemaphore* waitSemaphores) override;
bool onCharacterize(SkSurfaceCharacterization*) const override;
bool onIsCompatible(const SkSurfaceCharacterization&) const override;
diff --git a/chromium/third_party/skia/src/images/SkWebpEncoder.cpp b/chromium/third_party/skia/src/images/SkWebpEncoder.cpp
index de7aae353f3..07b8fa018e4 100644
--- a/chromium/third_party/skia/src/images/SkWebpEncoder.cpp
+++ b/chromium/third_party/skia/src/images/SkWebpEncoder.cpp
@@ -14,6 +14,7 @@
#include "include/core/SkUnPreMultiply.h"
#include "include/encode/SkWebpEncoder.h"
#include "include/private/SkColorData.h"
+#include "include/private/SkImageInfoPriv.h"
#include "include/private/SkTemplates.h"
#include "src/images/SkImageEncoderFns.h"
#include "src/utils/SkUTF.h"
@@ -32,85 +33,25 @@ extern "C" {
#include "webp/mux.h"
}
-static transform_scanline_proc choose_proc(const SkImageInfo& info) {
- switch (info.colorType()) {
- case kRGBA_8888_SkColorType:
- switch (info.alphaType()) {
- case kOpaque_SkAlphaType:
- return transform_scanline_RGBX;
- case kUnpremul_SkAlphaType:
- return transform_scanline_memcpy;
- case kPremul_SkAlphaType:
- return transform_scanline_rgbA;
- default:
- return nullptr;
- }
- case kBGRA_8888_SkColorType:
- switch (info.alphaType()) {
- case kOpaque_SkAlphaType:
- return transform_scanline_BGRX;
- case kUnpremul_SkAlphaType:
- return transform_scanline_BGRA;
- case kPremul_SkAlphaType:
- return transform_scanline_bgrA;
- default:
- return nullptr;
- }
- case kRGB_565_SkColorType:
- if (!info.isOpaque()) {
- return nullptr;
- }
-
- return transform_scanline_565;
- case kARGB_4444_SkColorType:
- switch (info.alphaType()) {
- case kOpaque_SkAlphaType:
- return transform_scanline_444;
- case kPremul_SkAlphaType:
- return transform_scanline_4444;
- default:
- return nullptr;
- }
- case kGray_8_SkColorType:
- return transform_scanline_gray;
- case kRGBA_F16_SkColorType:
- switch (info.alphaType()) {
- case kOpaque_SkAlphaType:
- case kUnpremul_SkAlphaType:
- return transform_scanline_F16_to_8888;
- case kPremul_SkAlphaType:
- return transform_scanline_F16_premul_to_8888;
- default:
- return nullptr;
- }
- default:
- return nullptr;
- }
-}
-
static int stream_writer(const uint8_t* data, size_t data_size,
const WebPPicture* const picture) {
SkWStream* const stream = (SkWStream*)picture->custom_ptr;
return stream->write(data, data_size) ? 1 : 0;
}
+using WebPPictureImportProc = int (*) (WebPPicture* picture, const uint8_t* pixels, int stride);
+
bool SkWebpEncoder::Encode(SkWStream* stream, const SkPixmap& pixmap, const Options& opts) {
if (!SkPixmapIsValid(pixmap)) {
return false;
}
- const transform_scanline_proc proc = choose_proc(pixmap.info());
- if (!proc) {
+ if (SkColorTypeIsAlphaOnly(pixmap.colorType())) {
+ // Maintain the existing behavior of not supporting encoding alpha-only images.
+ // TODO: Support encoding alpha only to an image with alpha but no color?
return false;
}
- int bpp;
- if (kRGBA_F16_SkColorType == pixmap.colorType()) {
- bpp = 4;
- } else {
- bpp = pixmap.isOpaque() ? 3 : 4;
- }
-
if (nullptr == pixmap.addr()) {
return false;
}
@@ -150,31 +91,32 @@ bool SkWebpEncoder::Encode(SkWStream* stream, const SkPixmap& pixmap, const Opti
SkDynamicMemoryWStream tmp;
pic.custom_ptr = icc ? (void*)&tmp : (void*)stream;
- const uint8_t* src = (uint8_t*)pixmap.addr();
- const int rgbStride = pic.width * bpp;
- const size_t rowBytes = pixmap.rowBytes();
-
- // Import (for each scanline) the bit-map image (in appropriate color-space)
- // to RGB color space.
- std::unique_ptr<uint8_t[]> rgb(new uint8_t[rgbStride * pic.height]);
- for (int y = 0; y < pic.height; ++y) {
- proc((char*) &rgb[y * rgbStride],
- (const char*) &src[y * rowBytes],
- pic.width,
- bpp);
- }
-
- auto importProc = WebPPictureImportRGB;
- if (3 != bpp) {
- if (pixmap.isOpaque()) {
- importProc = WebPPictureImportRGBX;
- } else {
+ {
+ const SkColorType ct = pixmap.colorType();
+ const bool premul = pixmap.alphaType() == kPremul_SkAlphaType;
+
+ SkBitmap tmpBm;
+ WebPPictureImportProc importProc = nullptr;
+ const SkPixmap* src = &pixmap;
+ if ( ct == kRGB_888x_SkColorType) { importProc = WebPPictureImportRGBX; }
+ else if (!premul && ct == kRGBA_8888_SkColorType) { importProc = WebPPictureImportRGBA; }
+#ifdef WebPPictureImportBGRA
+ else if (!premul && ct == kBGRA_8888_SkColorType) { importProc = WebPPictureImportBGRA; }
+#endif
+ else {
importProc = WebPPictureImportRGBA;
+ auto info = pixmap.info().makeColorType(kRGBA_8888_SkColorType)
+ .makeAlphaType(kUnpremul_SkAlphaType);
+ if (!tmpBm.tryAllocPixels(info)
+ || !pixmap.readPixels(tmpBm.info(), tmpBm.getPixels(), tmpBm.rowBytes())) {
+ return false;
+ }
+ src = &tmpBm.pixmap();
}
- }
- if (!importProc(&pic, &rgb[0], rgbStride)) {
- return false;
+ if (!importProc(&pic, reinterpret_cast<const uint8_t*>(src->addr()), src->rowBytes())) {
+ return false;
+ }
}
if (!WebPEncode(&webp_config, &pic)) {
diff --git a/chromium/third_party/skia/src/opts/SkChecksum_opts.h b/chromium/third_party/skia/src/opts/SkChecksum_opts.h
index 78808476ca7..67c3ba22bad 100644
--- a/chromium/third_party/skia/src/opts/SkChecksum_opts.h
+++ b/chromium/third_party/skia/src/opts/SkChecksum_opts.h
@@ -191,8 +191,8 @@ namespace SK_OPTS_NS {
// Handle last 0-3 bytes.
uint32_t k = 0;
switch (bytes & 3) {
- case 3: k ^= data[2] << 16;
- case 2: k ^= data[1] << 8;
+ case 3: k ^= data[2] << 16; [[fallthrough]];
+ case 2: k ^= data[1] << 8; [[fallthrough]];
case 1: k ^= data[0] << 0;
k *= 0xcc9e2d51;
k = (k << 15) | (k >> 17);
diff --git a/chromium/third_party/skia/src/opts/SkOpts_avx.cpp b/chromium/third_party/skia/src/opts/SkOpts_avx.cpp
index 80ccf54703a..99d828fd232 100644
--- a/chromium/third_party/skia/src/opts/SkOpts_avx.cpp
+++ b/chromium/third_party/skia/src/opts/SkOpts_avx.cpp
@@ -8,7 +8,6 @@
#include "src/core/SkOpts.h"
#define SK_OPTS_NS avx
-#include "src/opts/SkRasterPipeline_opts.h"
#include "src/opts/SkUtils_opts.h"
namespace SkOpts {
@@ -20,17 +19,5 @@ namespace SkOpts {
rect_memset16 = SK_OPTS_NS::rect_memset16;
rect_memset32 = SK_OPTS_NS::rect_memset32;
rect_memset64 = SK_OPTS_NS::rect_memset64;
-
- #define M(st) stages_highp[SkRasterPipeline::st] = (StageFn)SK_OPTS_NS::st;
- SK_RASTER_PIPELINE_STAGES(M)
- just_return_highp = (StageFn)SK_OPTS_NS::just_return;
- start_pipeline_highp = SK_OPTS_NS::start_pipeline;
- #undef M
-
- #define M(st) stages_lowp[SkRasterPipeline::st] = (StageFn)SK_OPTS_NS::lowp::st;
- SK_RASTER_PIPELINE_STAGES(M)
- just_return_lowp = (StageFn)SK_OPTS_NS::lowp::just_return;
- start_pipeline_lowp = SK_OPTS_NS::lowp::start_pipeline;
- #undef M
}
}
diff --git a/chromium/third_party/skia/src/opts/SkOpts_hsw.cpp b/chromium/third_party/skia/src/opts/SkOpts_hsw.cpp
index 21f4109f2a4..94c4ed26902 100644
--- a/chromium/third_party/skia/src/opts/SkOpts_hsw.cpp
+++ b/chromium/third_party/skia/src/opts/SkOpts_hsw.cpp
@@ -12,6 +12,7 @@
#include "src/opts/SkBitmapProcState_opts.h"
#include "src/opts/SkBlitRow_opts.h"
#include "src/opts/SkRasterPipeline_opts.h"
+#include "src/opts/SkSwizzler_opts.h"
#include "src/opts/SkUtils_opts.h"
#include "src/opts/SkVM_opts.h"
@@ -24,6 +25,15 @@ namespace SkOpts {
cubic_solver = SK_OPTS_NS::cubic_solver;
+ RGBA_to_BGRA = SK_OPTS_NS::RGBA_to_BGRA;
+ RGBA_to_rgbA = SK_OPTS_NS::RGBA_to_rgbA;
+ RGBA_to_bgrA = SK_OPTS_NS::RGBA_to_bgrA;
+ gray_to_RGB1 = SK_OPTS_NS::gray_to_RGB1;
+ grayA_to_RGBA = SK_OPTS_NS::grayA_to_RGBA;
+ grayA_to_rgbA = SK_OPTS_NS::grayA_to_rgbA;
+ inverted_CMYK_to_RGB1 = SK_OPTS_NS::inverted_CMYK_to_RGB1;
+ inverted_CMYK_to_BGR1 = SK_OPTS_NS::inverted_CMYK_to_BGR1;
+
#define M(st) stages_highp[SkRasterPipeline::st] = (StageFn)SK_OPTS_NS::st;
SK_RASTER_PIPELINE_STAGES(M)
just_return_highp = (StageFn)SK_OPTS_NS::just_return;
diff --git a/chromium/third_party/skia/src/opts/SkOpts_skx.cpp b/chromium/third_party/skia/src/opts/SkOpts_skx.cpp
new file mode 100644
index 00000000000..a13743c24b9
--- /dev/null
+++ b/chromium/third_party/skia/src/opts/SkOpts_skx.cpp
@@ -0,0 +1,27 @@
+/*
+ * 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/core/SkOpts.h"
+
+#define SK_OPTS_NS skx
+#include "src/opts/SkBlitRow_opts.h"
+#include "src/opts/SkSwizzler_opts.h"
+#include "src/opts/SkVM_opts.h"
+
+namespace SkOpts {
+ void Init_skx() {
+ blit_row_s32a_opaque = SK_OPTS_NS::blit_row_s32a_opaque;
+ interpret_skvm = SK_OPTS_NS::interpret_skvm;
+ RGBA_to_BGRA = SK_OPTS_NS::RGBA_to_BGRA;
+ RGBA_to_rgbA = SK_OPTS_NS::RGBA_to_rgbA;
+ RGBA_to_bgrA = SK_OPTS_NS::RGBA_to_bgrA;
+ grayA_to_RGBA = SK_OPTS_NS::grayA_to_RGBA;
+ grayA_to_rgbA = SK_OPTS_NS::grayA_to_rgbA;
+ inverted_CMYK_to_RGB1 = SK_OPTS_NS::inverted_CMYK_to_RGB1;
+ inverted_CMYK_to_BGR1 = SK_OPTS_NS::inverted_CMYK_to_BGR1;
+ }
+}
diff --git a/chromium/third_party/skia/src/opts/SkOpts_sse41.cpp b/chromium/third_party/skia/src/opts/SkOpts_sse41.cpp
index 8e525968dab..abd47969c4f 100644
--- a/chromium/third_party/skia/src/opts/SkOpts_sse41.cpp
+++ b/chromium/third_party/skia/src/opts/SkOpts_sse41.cpp
@@ -5,27 +5,4 @@
* found in the LICENSE file.
*/
-#include "src/core/SkOpts.h"
-
-#define SK_OPTS_NS sse41
-#include "src/opts/SkBlitRow_opts.h"
-#include "src/opts/SkRasterPipeline_opts.h"
-
-namespace SkOpts {
- void Init_sse41() {
- blit_row_color32 = sse41::blit_row_color32;
- blit_row_s32a_opaque = sse41::blit_row_s32a_opaque;
-
- #define M(st) stages_highp[SkRasterPipeline::st] = (StageFn)SK_OPTS_NS::st;
- SK_RASTER_PIPELINE_STAGES(M)
- just_return_highp = (StageFn)SK_OPTS_NS::just_return;
- start_pipeline_highp = SK_OPTS_NS::start_pipeline;
- #undef M
-
- #define M(st) stages_lowp[SkRasterPipeline::st] = (StageFn)SK_OPTS_NS::lowp::st;
- SK_RASTER_PIPELINE_STAGES(M)
- just_return_lowp = (StageFn)SK_OPTS_NS::lowp::just_return;
- start_pipeline_lowp = SK_OPTS_NS::lowp::start_pipeline;
- #undef M
- }
-}
+// Intentionally empty, to be cleaned up.
diff --git a/chromium/third_party/skia/src/opts/SkRasterPipeline_opts.h b/chromium/third_party/skia/src/opts/SkRasterPipeline_opts.h
index 7e9558efc71..ad745a6b5e3 100644
--- a/chromium/third_party/skia/src/opts/SkRasterPipeline_opts.h
+++ b/chromium/third_party/skia/src/opts/SkRasterPipeline_opts.h
@@ -625,13 +625,13 @@ namespace SK_OPTS_NS {
F _04, _15, _26, _37;
_04 = _15 = _26 = _37 = 0;
switch (tail) {
- case 0: _37 = _mm256_insertf128_ps(_37, _mm_loadu_ps(ptr+28), 1);
- case 7: _26 = _mm256_insertf128_ps(_26, _mm_loadu_ps(ptr+24), 1);
- case 6: _15 = _mm256_insertf128_ps(_15, _mm_loadu_ps(ptr+20), 1);
- case 5: _04 = _mm256_insertf128_ps(_04, _mm_loadu_ps(ptr+16), 1);
- case 4: _37 = _mm256_insertf128_ps(_37, _mm_loadu_ps(ptr+12), 0);
- case 3: _26 = _mm256_insertf128_ps(_26, _mm_loadu_ps(ptr+ 8), 0);
- case 2: _15 = _mm256_insertf128_ps(_15, _mm_loadu_ps(ptr+ 4), 0);
+ case 0: _37 = _mm256_insertf128_ps(_37, _mm_loadu_ps(ptr+28), 1); [[fallthrough]];
+ case 7: _26 = _mm256_insertf128_ps(_26, _mm_loadu_ps(ptr+24), 1); [[fallthrough]];
+ case 6: _15 = _mm256_insertf128_ps(_15, _mm_loadu_ps(ptr+20), 1); [[fallthrough]];
+ case 5: _04 = _mm256_insertf128_ps(_04, _mm_loadu_ps(ptr+16), 1); [[fallthrough]];
+ case 4: _37 = _mm256_insertf128_ps(_37, _mm_loadu_ps(ptr+12), 0); [[fallthrough]];
+ case 3: _26 = _mm256_insertf128_ps(_26, _mm_loadu_ps(ptr+ 8), 0); [[fallthrough]];
+ case 2: _15 = _mm256_insertf128_ps(_15, _mm_loadu_ps(ptr+ 4), 0); [[fallthrough]];
case 1: _04 = _mm256_insertf128_ps(_04, _mm_loadu_ps(ptr+ 0), 0);
}
@@ -978,11 +978,7 @@ SI F approx_exp(F x) {
}
SI F approx_powf(F x, F y) {
-#if defined(SK_LEGACY_APPROX_POWF_SPECIALCASE)
- return if_then_else((x == 0) , 0
-#else
return if_then_else((x == 0)|(x == 1), x
-#endif
, approx_pow2(approx_log2(x) * y));
}
@@ -1152,11 +1148,11 @@ SI V load(const T* src, size_t tail) {
if (__builtin_expect(tail, 0)) {
V v{}; // Any inactive lanes are zeroed.
switch (tail) {
- case 7: v[6] = src[6];
- case 6: v[5] = src[5];
- case 5: v[4] = src[4];
+ case 7: v[6] = src[6]; [[fallthrough]];
+ case 6: v[5] = src[5]; [[fallthrough]];
+ case 5: v[4] = src[4]; [[fallthrough]];
case 4: memcpy(&v, src, 4*sizeof(T)); break;
- case 3: v[2] = src[2];
+ case 3: v[2] = src[2]; [[fallthrough]];
case 2: memcpy(&v, src, 2*sizeof(T)); break;
case 1: memcpy(&v, src, 1*sizeof(T)); break;
}
@@ -1172,11 +1168,11 @@ SI void store(T* dst, V v, size_t tail) {
__builtin_assume(tail < N);
if (__builtin_expect(tail, 0)) {
switch (tail) {
- case 7: dst[6] = v[6];
- case 6: dst[5] = v[5];
- case 5: dst[4] = v[4];
+ case 7: dst[6] = v[6]; [[fallthrough]];
+ case 6: dst[5] = v[5]; [[fallthrough]];
+ case 5: dst[4] = v[4]; [[fallthrough]];
case 4: memcpy(dst, &v, 4*sizeof(T)); break;
- case 3: dst[2] = v[2];
+ case 3: dst[2] = v[2]; [[fallthrough]];
case 2: memcpy(dst, &v, 2*sizeof(T)); break;
case 1: memcpy(dst, &v, 1*sizeof(T)); break;
}
@@ -1916,45 +1912,6 @@ STAGE(HLGinvish, const skcms_TransferFunction* ctx) {
b = fn(b);
}
-STAGE(from_srgb, Ctx::None) {
- auto fn = [](F s) {
- U32 sign;
- s = strip_sign(s, &sign);
- auto lo = s * (1/12.92f);
- auto hi = mad(s*s, mad(s, 0.3000f, 0.6975f), 0.0025f);
- return apply_sign(if_then_else(s < 0.055f, lo, hi), sign);
- };
- r = fn(r);
- g = fn(g);
- b = fn(b);
-}
-STAGE(to_srgb, Ctx::None) {
- auto fn = [](F l) {
- U32 sign;
- l = strip_sign(l, &sign);
- // We tweak c and d for each instruction set to make sure fn(1) is exactly 1.
- #if defined(JUMPER_IS_SSE2) || defined(JUMPER_IS_SSE41) || \
- defined(JUMPER_IS_AVX ) || defined(JUMPER_IS_HSW ) || defined(JUMPER_IS_SKX)
- const float c = 1.130048394203f,
- d = 0.141357362270f;
- #elif defined(JUMPER_IS_NEON)
- const float c = 1.129999995232f,
- d = 0.141381442547f;
- #else
- const float c = 1.129999995232f,
- d = 0.141377761960f;
- #endif
- F t = rsqrt(l);
- auto lo = l * 12.92f;
- auto hi = mad(t, mad(t, -0.0024542345f, 0.013832027f), c)
- * rcp(d + t);
- return apply_sign(if_then_else(l < 0.00465985f, lo, hi), sign);
- };
- r = fn(r);
- g = fn(g);
- b = fn(b);
-}
-
STAGE(load_a8, const SkRasterPipeline_MemoryCtx* ctx) {
auto ptr = ptr_at_xy<const uint8_t>(ctx, dx,dy);
@@ -3446,20 +3403,20 @@ SI V load(const T* ptr, size_t tail) {
switch (tail & (N-1)) {
case 0: memcpy(&v, ptr, sizeof(v)); break;
#if defined(JUMPER_IS_HSW) || defined(JUMPER_IS_SKX)
- case 15: v[14] = ptr[14];
- case 14: v[13] = ptr[13];
- case 13: v[12] = ptr[12];
+ case 15: v[14] = ptr[14]; [[fallthrough]];
+ case 14: v[13] = ptr[13]; [[fallthrough]];
+ case 13: v[12] = ptr[12]; [[fallthrough]];
case 12: memcpy(&v, ptr, 12*sizeof(T)); break;
- case 11: v[10] = ptr[10];
- case 10: v[ 9] = ptr[ 9];
- case 9: v[ 8] = ptr[ 8];
+ case 11: v[10] = ptr[10]; [[fallthrough]];
+ case 10: v[ 9] = ptr[ 9]; [[fallthrough]];
+ case 9: v[ 8] = ptr[ 8]; [[fallthrough]];
case 8: memcpy(&v, ptr, 8*sizeof(T)); break;
#endif
- case 7: v[ 6] = ptr[ 6];
- case 6: v[ 5] = ptr[ 5];
- case 5: v[ 4] = ptr[ 4];
+ case 7: v[ 6] = ptr[ 6]; [[fallthrough]];
+ case 6: v[ 5] = ptr[ 5]; [[fallthrough]];
+ case 5: v[ 4] = ptr[ 4]; [[fallthrough]];
case 4: memcpy(&v, ptr, 4*sizeof(T)); break;
- case 3: v[ 2] = ptr[ 2];
+ case 3: v[ 2] = ptr[ 2]; [[fallthrough]];
case 2: memcpy(&v, ptr, 2*sizeof(T)); break;
case 1: v[ 0] = ptr[ 0];
}
@@ -3470,20 +3427,20 @@ SI void store(T* ptr, size_t tail, V v) {
switch (tail & (N-1)) {
case 0: memcpy(ptr, &v, sizeof(v)); break;
#if defined(JUMPER_IS_HSW) || defined(JUMPER_IS_SKX)
- case 15: ptr[14] = v[14];
- case 14: ptr[13] = v[13];
- case 13: ptr[12] = v[12];
+ case 15: ptr[14] = v[14]; [[fallthrough]];
+ case 14: ptr[13] = v[13]; [[fallthrough]];
+ case 13: ptr[12] = v[12]; [[fallthrough]];
case 12: memcpy(ptr, &v, 12*sizeof(T)); break;
- case 11: ptr[10] = v[10];
- case 10: ptr[ 9] = v[ 9];
- case 9: ptr[ 8] = v[ 8];
+ case 11: ptr[10] = v[10]; [[fallthrough]];
+ case 10: ptr[ 9] = v[ 9]; [[fallthrough]];
+ case 9: ptr[ 8] = v[ 8]; [[fallthrough]];
case 8: memcpy(ptr, &v, 8*sizeof(T)); break;
#endif
- case 7: ptr[ 6] = v[ 6];
- case 6: ptr[ 5] = v[ 5];
- case 5: ptr[ 4] = v[ 4];
+ case 7: ptr[ 6] = v[ 6]; [[fallthrough]];
+ case 6: ptr[ 5] = v[ 5]; [[fallthrough]];
+ case 5: ptr[ 4] = v[ 4]; [[fallthrough]];
case 4: memcpy(ptr, &v, 4*sizeof(T)); break;
- case 3: ptr[ 2] = v[ 2];
+ case 3: ptr[ 2] = v[ 2]; [[fallthrough]];
case 2: memcpy(ptr, &v, 2*sizeof(T)); break;
case 1: ptr[ 0] = v[ 0];
}
@@ -3556,12 +3513,12 @@ SI void load_8888_(const uint32_t* ptr, size_t tail, U16* r, U16* g, U16* b, U16
uint8x8x4_t rgba;
switch (tail & (N-1)) {
case 0: rgba = vld4_u8 ((const uint8_t*)(ptr+0) ); break;
- case 7: rgba = vld4_lane_u8((const uint8_t*)(ptr+6), rgba, 6);
- case 6: rgba = vld4_lane_u8((const uint8_t*)(ptr+5), rgba, 5);
- case 5: rgba = vld4_lane_u8((const uint8_t*)(ptr+4), rgba, 4);
- case 4: rgba = vld4_lane_u8((const uint8_t*)(ptr+3), rgba, 3);
- case 3: rgba = vld4_lane_u8((const uint8_t*)(ptr+2), rgba, 2);
- case 2: rgba = vld4_lane_u8((const uint8_t*)(ptr+1), rgba, 1);
+ case 7: rgba = vld4_lane_u8((const uint8_t*)(ptr+6), rgba, 6); [[fallthrough]];
+ case 6: rgba = vld4_lane_u8((const uint8_t*)(ptr+5), rgba, 5); [[fallthrough]];
+ case 5: rgba = vld4_lane_u8((const uint8_t*)(ptr+4), rgba, 4); [[fallthrough]];
+ case 4: rgba = vld4_lane_u8((const uint8_t*)(ptr+3), rgba, 3); [[fallthrough]];
+ case 3: rgba = vld4_lane_u8((const uint8_t*)(ptr+2), rgba, 2); [[fallthrough]];
+ case 2: rgba = vld4_lane_u8((const uint8_t*)(ptr+1), rgba, 1); [[fallthrough]];
case 1: rgba = vld4_lane_u8((const uint8_t*)(ptr+0), rgba, 0);
}
*r = cast<U16>(rgba.val[0]);
@@ -3582,12 +3539,12 @@ SI void store_8888_(uint32_t* ptr, size_t tail, U16 r, U16 g, U16 b, U16 a) {
}};
switch (tail & (N-1)) {
case 0: vst4_u8 ((uint8_t*)(ptr+0), rgba ); break;
- case 7: vst4_lane_u8((uint8_t*)(ptr+6), rgba, 6);
- case 6: vst4_lane_u8((uint8_t*)(ptr+5), rgba, 5);
- case 5: vst4_lane_u8((uint8_t*)(ptr+4), rgba, 4);
- case 4: vst4_lane_u8((uint8_t*)(ptr+3), rgba, 3);
- case 3: vst4_lane_u8((uint8_t*)(ptr+2), rgba, 2);
- case 2: vst4_lane_u8((uint8_t*)(ptr+1), rgba, 1);
+ case 7: vst4_lane_u8((uint8_t*)(ptr+6), rgba, 6); [[fallthrough]];
+ case 6: vst4_lane_u8((uint8_t*)(ptr+5), rgba, 5); [[fallthrough]];
+ case 5: vst4_lane_u8((uint8_t*)(ptr+4), rgba, 4); [[fallthrough]];
+ case 4: vst4_lane_u8((uint8_t*)(ptr+3), rgba, 3); [[fallthrough]];
+ case 3: vst4_lane_u8((uint8_t*)(ptr+2), rgba, 2); [[fallthrough]];
+ case 2: vst4_lane_u8((uint8_t*)(ptr+1), rgba, 1); [[fallthrough]];
case 1: vst4_lane_u8((uint8_t*)(ptr+0), rgba, 0);
}
#else
@@ -3712,12 +3669,12 @@ SI void load_88_(const uint16_t* ptr, size_t tail, U16* r, U16* g) {
uint8x8x2_t rg;
switch (tail & (N-1)) {
case 0: rg = vld2_u8 ((const uint8_t*)(ptr+0) ); break;
- case 7: rg = vld2_lane_u8((const uint8_t*)(ptr+6), rg, 6);
- case 6: rg = vld2_lane_u8((const uint8_t*)(ptr+5), rg, 5);
- case 5: rg = vld2_lane_u8((const uint8_t*)(ptr+4), rg, 4);
- case 4: rg = vld2_lane_u8((const uint8_t*)(ptr+3), rg, 3);
- case 3: rg = vld2_lane_u8((const uint8_t*)(ptr+2), rg, 2);
- case 2: rg = vld2_lane_u8((const uint8_t*)(ptr+1), rg, 1);
+ case 7: rg = vld2_lane_u8((const uint8_t*)(ptr+6), rg, 6); [[fallthrough]];
+ case 6: rg = vld2_lane_u8((const uint8_t*)(ptr+5), rg, 5); [[fallthrough]];
+ case 5: rg = vld2_lane_u8((const uint8_t*)(ptr+4), rg, 4); [[fallthrough]];
+ case 4: rg = vld2_lane_u8((const uint8_t*)(ptr+3), rg, 3); [[fallthrough]];
+ case 3: rg = vld2_lane_u8((const uint8_t*)(ptr+2), rg, 2); [[fallthrough]];
+ case 2: rg = vld2_lane_u8((const uint8_t*)(ptr+1), rg, 1); [[fallthrough]];
case 1: rg = vld2_lane_u8((const uint8_t*)(ptr+0), rg, 0);
}
*r = cast<U16>(rg.val[0]);
@@ -3735,12 +3692,12 @@ SI void store_88_(uint16_t* ptr, size_t tail, U16 r, U16 g) {
}};
switch (tail & (N-1)) {
case 0: vst2_u8 ((uint8_t*)(ptr+0), rg ); break;
- case 7: vst2_lane_u8((uint8_t*)(ptr+6), rg, 6);
- case 6: vst2_lane_u8((uint8_t*)(ptr+5), rg, 5);
- case 5: vst2_lane_u8((uint8_t*)(ptr+4), rg, 4);
- case 4: vst2_lane_u8((uint8_t*)(ptr+3), rg, 3);
- case 3: vst2_lane_u8((uint8_t*)(ptr+2), rg, 2);
- case 2: vst2_lane_u8((uint8_t*)(ptr+1), rg, 1);
+ case 7: vst2_lane_u8((uint8_t*)(ptr+6), rg, 6); [[fallthrough]];
+ case 6: vst2_lane_u8((uint8_t*)(ptr+5), rg, 5); [[fallthrough]];
+ case 5: vst2_lane_u8((uint8_t*)(ptr+4), rg, 4); [[fallthrough]];
+ case 4: vst2_lane_u8((uint8_t*)(ptr+3), rg, 3); [[fallthrough]];
+ case 3: vst2_lane_u8((uint8_t*)(ptr+2), rg, 2); [[fallthrough]];
+ case 2: vst2_lane_u8((uint8_t*)(ptr+1), rg, 1); [[fallthrough]];
case 1: vst2_lane_u8((uint8_t*)(ptr+0), rg, 0);
}
#else
@@ -4257,8 +4214,6 @@ STAGE_PP(swizzle, void* ctx) {
NOT_IMPLEMENTED(unbounded_uniform_color)
NOT_IMPLEMENTED(unpremul)
NOT_IMPLEMENTED(dither) // TODO
- NOT_IMPLEMENTED(from_srgb)
- NOT_IMPLEMENTED(to_srgb)
NOT_IMPLEMENTED(load_16161616)
NOT_IMPLEMENTED(load_16161616_dst)
NOT_IMPLEMENTED(store_16161616)
diff --git a/chromium/third_party/skia/src/opts/SkSwizzler_opts.h b/chromium/third_party/skia/src/opts/SkSwizzler_opts.h
index f7f7c254570..3ef8cc68109 100644
--- a/chromium/third_party/skia/src/opts/SkSwizzler_opts.h
+++ b/chromium/third_party/skia/src/opts/SkSwizzler_opts.h
@@ -65,41 +65,6 @@ static void RGBA_to_BGRA_portable(uint32_t* dst, const uint32_t* src, int count)
}
}
-static void RGB_to_RGB1_portable(uint32_t dst[], const uint8_t* src, int count) {
- for (int i = 0; i < count; i++) {
- uint8_t r = src[0],
- g = src[1],
- b = src[2];
- src += 3;
- dst[i] = (uint32_t)0xFF << 24
- | (uint32_t)b << 16
- | (uint32_t)g << 8
- | (uint32_t)r << 0;
- }
-}
-
-static void RGB_to_BGR1_portable(uint32_t dst[], const uint8_t* src, int count) {
- for (int i = 0; i < count; i++) {
- uint8_t r = src[0],
- g = src[1],
- b = src[2];
- src += 3;
- dst[i] = (uint32_t)0xFF << 24
- | (uint32_t)r << 16
- | (uint32_t)g << 8
- | (uint32_t)b << 0;
- }
-}
-
-static void gray_to_RGB1_portable(uint32_t dst[], const uint8_t* src, int count) {
- for (int i = 0; i < count; i++) {
- dst[i] = (uint32_t)0xFF << 24
- | (uint32_t)src[i] << 16
- | (uint32_t)src[i] << 8
- | (uint32_t)src[i] << 0;
- }
-}
-
static void grayA_to_RGBA_portable(uint32_t dst[], const uint8_t* src, int count) {
for (int i = 0; i < count; i++) {
uint8_t g = src[0],
@@ -189,8 +154,7 @@ static uint8x8_t scale(uint8x8_t x, uint8x8_t y) {
return div255_round(vmull_u8(x, y));
}
-template <bool kSwapRB>
-static void premul_should_swapRB(uint32_t* dst, const uint32_t* src, int count) {
+static void premul_should_swapRB(bool kSwapRB, uint32_t* dst, const uint32_t* src, int count) {
while (count >= 8) {
// Load 8 pixels.
uint8x8x4_t rgba = vld4_u8((const uint8_t*) src);
@@ -227,11 +191,11 @@ static void premul_should_swapRB(uint32_t* dst, const uint32_t* src, int count)
}
/*not static*/ inline void RGBA_to_rgbA(uint32_t* dst, const uint32_t* src, int count) {
- premul_should_swapRB<false>(dst, src, count);
+ premul_should_swapRB(false, dst, src, count);
}
/*not static*/ inline void RGBA_to_bgrA(uint32_t* dst, const uint32_t* src, int count) {
- premul_should_swapRB<true>(dst, src, count);
+ premul_should_swapRB(true, dst, src, count);
}
/*not static*/ inline void RGBA_to_BGRA(uint32_t* dst, const uint32_t* src, int count) {
@@ -267,109 +231,7 @@ static void premul_should_swapRB(uint32_t* dst, const uint32_t* src, int count)
RGBA_to_BGRA_portable(dst, src, count);
}
-template <bool kSwapRB>
-static void insert_alpha_should_swaprb(uint32_t dst[], const uint8_t* src, int count) {
- while (count >= 16) {
- // Load 16 pixels.
- uint8x16x3_t rgb = vld3q_u8(src);
-
- // Insert an opaque alpha channel and swap if needed.
- uint8x16x4_t rgba;
- if (kSwapRB) {
- rgba.val[0] = rgb.val[2];
- rgba.val[2] = rgb.val[0];
- } else {
- rgba.val[0] = rgb.val[0];
- rgba.val[2] = rgb.val[2];
- }
- rgba.val[1] = rgb.val[1];
- rgba.val[3] = vdupq_n_u8(0xFF);
-
- // Store 16 pixels.
- vst4q_u8((uint8_t*) dst, rgba);
- src += 16*3;
- dst += 16;
- count -= 16;
- }
-
- if (count >= 8) {
- // Load 8 pixels.
- uint8x8x3_t rgb = vld3_u8(src);
-
- // Insert an opaque alpha channel and swap if needed.
- uint8x8x4_t rgba;
- if (kSwapRB) {
- rgba.val[0] = rgb.val[2];
- rgba.val[2] = rgb.val[0];
- } else {
- rgba.val[0] = rgb.val[0];
- rgba.val[2] = rgb.val[2];
- }
- rgba.val[1] = rgb.val[1];
- rgba.val[3] = vdup_n_u8(0xFF);
-
- // Store 8 pixels.
- vst4_u8((uint8_t*) dst, rgba);
- src += 8*3;
- dst += 8;
- count -= 8;
- }
-
- // Call portable code to finish up the tail of [0,8) pixels.
- auto proc = kSwapRB ? RGB_to_BGR1_portable : RGB_to_RGB1_portable;
- proc(dst, src, count);
-}
-
-/*not static*/ inline void RGB_to_RGB1(uint32_t dst[], const uint8_t* src, int count) {
- insert_alpha_should_swaprb<false>(dst, src, count);
-}
-
-/*not static*/ inline void RGB_to_BGR1(uint32_t dst[], const uint8_t* src, int count) {
- insert_alpha_should_swaprb<true>(dst, src, count);
-}
-
-/*not static*/ inline void gray_to_RGB1(uint32_t dst[], const uint8_t* src, int count) {
- while (count >= 16) {
- // Load 16 pixels.
- uint8x16_t gray = vld1q_u8(src);
-
- // Set each of the color channels.
- uint8x16x4_t rgba;
- rgba.val[0] = gray;
- rgba.val[1] = gray;
- rgba.val[2] = gray;
- rgba.val[3] = vdupq_n_u8(0xFF);
-
- // Store 16 pixels.
- vst4q_u8((uint8_t*) dst, rgba);
- src += 16;
- dst += 16;
- count -= 16;
- }
-
- if (count >= 8) {
- // Load 8 pixels.
- uint8x8_t gray = vld1_u8(src);
-
- // Set each of the color channels.
- uint8x8x4_t rgba;
- rgba.val[0] = gray;
- rgba.val[1] = gray;
- rgba.val[2] = gray;
- rgba.val[3] = vdup_n_u8(0xFF);
-
- // Store 8 pixels.
- vst4_u8((uint8_t*) dst, rgba);
- src += 8;
- dst += 8;
- count -= 8;
- }
-
- gray_to_RGB1_portable(dst, src, count);
-}
-
-template <bool kPremul>
-static void expand_grayA(uint32_t dst[], const uint8_t* src, int count) {
+static void expand_grayA(bool kPremul, uint32_t dst[], const uint8_t* src, int count) {
while (count >= 16) {
// Load 16 pixels.
uint8x16x2_t ga = vld2q_u8(src);
@@ -423,16 +285,15 @@ static void expand_grayA(uint32_t dst[], const uint8_t* src, int count) {
}
/*not static*/ inline void grayA_to_RGBA(uint32_t dst[], const uint8_t* src, int count) {
- expand_grayA<false>(dst, src, count);
+ expand_grayA(false, dst, src, count);
}
/*not static*/ inline void grayA_to_rgbA(uint32_t dst[], const uint8_t* src, int count) {
- expand_grayA<true>(dst, src, count);
+ expand_grayA(true, dst, src, count);
}
enum Format { kRGB1, kBGR1 };
-template <Format format>
-static void inverted_cmyk_to(uint32_t* dst, const uint32_t* src, int count) {
+static void inverted_cmyk_to(Format format, uint32_t* dst, const uint32_t* src, int count) {
while (count >= 8) {
// Load 8 cmyk pixels.
uint8x8x4_t pixels = vld4_u8((const uint8_t*) src);
@@ -470,11 +331,540 @@ static void inverted_cmyk_to(uint32_t* dst, const uint32_t* src, int count) {
}
/*not static*/ inline void inverted_CMYK_to_RGB1(uint32_t dst[], const uint32_t* src, int count) {
- inverted_cmyk_to<kRGB1>(dst, src, count);
+ inverted_cmyk_to(kRGB1, dst, src, count);
}
/*not static*/ inline void inverted_CMYK_to_BGR1(uint32_t dst[], const uint32_t* src, int count) {
- inverted_cmyk_to<kBGR1>(dst, src, count);
+ inverted_cmyk_to(kBGR1, dst, src, count);
+}
+
+#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SKX
+// Scale a byte by another.
+// Inputs are stored in 16-bit lanes, but are not larger than 8-bits.
+static __m512i scale(__m512i x, __m512i y) {
+ const __m512i _128 = _mm512_set1_epi16(128);
+ const __m512i _257 = _mm512_set1_epi16(257);
+
+ // (x+127)/255 == ((x+128)*257)>>16 for 0 <= x <= 255*255.
+ return _mm512_mulhi_epu16(_mm512_add_epi16(_mm512_mullo_epi16(x, y), _128), _257);
+}
+
+static void premul_should_swapRB(bool kSwapRB, uint32_t* dst, const uint32_t* src, int count) {
+
+ auto premul8 = [=](__m512i* lo, __m512i* hi) {
+ const __m512i zeros = _mm512_setzero_si512();
+ skvx::Vec<64, uint8_t> mask;
+ if (kSwapRB) {
+ mask = { 2,6,10,14, 1,5,9,13, 0,4,8,12, 3,7,11,15,
+ 2,6,10,14, 1,5,9,13, 0,4,8,12, 3,7,11,15,
+ 2,6,10,14, 1,5,9,13, 0,4,8,12, 3,7,11,15,
+ 2,6,10,14, 1,5,9,13, 0,4,8,12, 3,7,11,15 };
+ } else {
+ mask = { 0,4,8,12, 1,5,9,13, 2,6,10,14, 3,7,11,15,
+ 0,4,8,12, 1,5,9,13, 2,6,10,14, 3,7,11,15,
+ 0,4,8,12, 1,5,9,13, 2,6,10,14, 3,7,11,15,
+ 0,4,8,12, 1,5,9,13, 2,6,10,14, 3,7,11,15 };
+ }
+ __m512i planar = skvx::bit_pun<__m512i>(mask);
+
+ // Swizzle the pixels to 8-bit planar.
+ *lo = _mm512_shuffle_epi8(*lo, planar);
+ *hi = _mm512_shuffle_epi8(*hi, planar);
+ __m512i rg = _mm512_unpacklo_epi32(*lo, *hi),
+ ba = _mm512_unpackhi_epi32(*lo, *hi);
+
+ // Unpack to 16-bit planar.
+ __m512i r = _mm512_unpacklo_epi8(rg, zeros),
+ g = _mm512_unpackhi_epi8(rg, zeros),
+ b = _mm512_unpacklo_epi8(ba, zeros),
+ a = _mm512_unpackhi_epi8(ba, zeros);
+
+ // Premultiply!
+ r = scale(r, a);
+ g = scale(g, a);
+ b = scale(b, a);
+
+ // Repack into interlaced pixels.
+ rg = _mm512_or_si512(r, _mm512_slli_epi16(g, 8));
+ ba = _mm512_or_si512(b, _mm512_slli_epi16(a, 8));
+ *lo = _mm512_unpacklo_epi16(rg, ba);
+ *hi = _mm512_unpackhi_epi16(rg, ba);
+ };
+
+ while (count >= 32) {
+ __m512i lo = _mm512_loadu_si512((const __m512i*) (src + 0)),
+ hi = _mm512_loadu_si512((const __m512i*) (src + 16));
+
+ premul8(&lo, &hi);
+
+ _mm512_storeu_si512((__m512i*) (dst + 0), lo);
+ _mm512_storeu_si512((__m512i*) (dst + 16), hi);
+
+ src += 32;
+ dst += 32;
+ count -= 32;
+ }
+
+ if (count >= 16) {
+ __m512i lo = _mm512_loadu_si512((const __m512i*) src),
+ hi = _mm512_setzero_si512();
+
+ premul8(&lo, &hi);
+
+ _mm512_storeu_si512((__m512i*) dst, lo);
+
+ src += 16;
+ dst += 16;
+ count -= 16;
+ }
+
+ // Call portable code to finish up the tail of [0,16) pixels.
+ auto proc = kSwapRB ? RGBA_to_bgrA_portable : RGBA_to_rgbA_portable;
+ proc(dst, src, count);
+}
+
+/*not static*/ inline void RGBA_to_rgbA(uint32_t* dst, const uint32_t* src, int count) {
+ premul_should_swapRB(false, dst, src, count);
+}
+
+/*not static*/ inline void RGBA_to_bgrA(uint32_t* dst, const uint32_t* src, int count) {
+ premul_should_swapRB(true, dst, src, count);
+}
+
+/*not static*/ inline void RGBA_to_BGRA(uint32_t* dst, const uint32_t* src, int count) {
+ const uint8_t mask[64] = { 2,1,0,3, 6,5,4,7, 10,9,8,11, 14,13,12,15,
+ 2,1,0,3, 6,5,4,7, 10,9,8,11, 14,13,12,15,
+ 2,1,0,3, 6,5,4,7, 10,9,8,11, 14,13,12,15,
+ 2,1,0,3, 6,5,4,7, 10,9,8,11, 14,13,12,15 };
+ const __m512i swapRB = _mm512_loadu_si512(mask);
+
+ while (count >= 16) {
+ __m512i rgba = _mm512_loadu_si512((const __m512i*) src);
+ __m512i bgra = _mm512_shuffle_epi8(rgba, swapRB);
+ _mm512_storeu_si512((__m512i*) dst, bgra);
+
+ src += 16;
+ dst += 16;
+ count -= 16;
+ }
+
+ RGBA_to_BGRA_portable(dst, src, count);
+}
+
+// Use SSSE3 impl as AVX2 / AVX-512 impl regresses performance for RGB_to_RGB1 / RGB_to_BGR1.
+
+// Use AVX2 impl as AVX-512 impl regresses performance for gray_to_RGB1.
+
+/*not static*/ inline void grayA_to_RGBA(uint32_t dst[], const uint8_t* src, int count) {
+ while (count >= 32) {
+ __m512i ga = _mm512_loadu_si512((const __m512i*) src);
+
+ __m512i gg = _mm512_or_si512(_mm512_and_si512(ga, _mm512_set1_epi16(0x00FF)),
+ _mm512_slli_epi16(ga, 8));
+
+ __m512i ggga_lo = _mm512_unpacklo_epi16(gg, ga);
+ __m512i ggga_hi = _mm512_unpackhi_epi16(gg, ga);
+
+ // 1st shuffle for pixel reorder.
+ // Note. 'p' stands for 'ggga'
+ // Before 1st shuffle:
+ // ggga_lo = p0 p1 p2 p3 | p8 p9 p10 p11 | p16 p17 p18 p19 | p24 p25 p26 p27
+ // ggga_hi = p4 p5 p6 p7 | p12 p13 p14 p15 | p20 p21 p22 p23 | p28 p29 p30 p31
+ //
+ // After 1st shuffle:
+ // ggga_lo_shuffle_1 =
+ // p0 p1 p2 p3 | p8 p9 p10 p11 | p4 p5 p6 p7 | p12 p13 p14 p15
+ // ggga_hi_shuffle_1 =
+ // p16 p17 p18 p19 | p24 p25 p26 p27 | p20 p21 p22 p23 | p28 p29 p30 p31
+ __m512i ggga_lo_shuffle_1 = _mm512_shuffle_i32x4(ggga_lo, ggga_hi, 0x44),
+ ggga_hi_shuffle_1 = _mm512_shuffle_i32x4(ggga_lo, ggga_hi, 0xee);
+
+ // 2nd shuffle for pixel reorder.
+ // After the 2nd shuffle:
+ // ggga_lo_shuffle_2 =
+ // p0 p1 p2 p3 | p4 p5 p6 p7 | p8 p9 p10 p11 | p12 p13 p14 p15
+ // ggga_hi_shuffle_2 =
+ // p16 p17 p18 p19 | p20 p21 p22 p23 | p24 p25 p26 p27 | p28 p29 p30 p31
+ __m512i ggga_lo_shuffle_2 = _mm512_shuffle_i32x4(ggga_lo_shuffle_1,
+ ggga_lo_shuffle_1, 0xd8),
+ ggga_hi_shuffle_2 = _mm512_shuffle_i32x4(ggga_hi_shuffle_1,
+ ggga_hi_shuffle_1, 0xd8);
+
+ _mm512_storeu_si512((__m512i*) (dst + 0), ggga_lo_shuffle_2);
+ _mm512_storeu_si512((__m512i*) (dst + 16), ggga_hi_shuffle_2);
+
+ src += 32*2;
+ dst += 32;
+ count -= 32;
+ }
+
+ grayA_to_RGBA_portable(dst, src, count);
+}
+
+/*not static*/ inline void grayA_to_rgbA(uint32_t dst[], const uint8_t* src, int count) {
+ while (count >= 32) {
+ __m512i grayA = _mm512_loadu_si512((const __m512i*) src);
+
+ __m512i g0 = _mm512_and_si512(grayA, _mm512_set1_epi16(0x00FF));
+ __m512i a0 = _mm512_srli_epi16(grayA, 8);
+
+ // Premultiply
+ g0 = scale(g0, a0);
+
+ __m512i gg = _mm512_or_si512(g0, _mm512_slli_epi16(g0, 8));
+ __m512i ga = _mm512_or_si512(g0, _mm512_slli_epi16(a0, 8));
+
+ __m512i ggga_lo = _mm512_unpacklo_epi16(gg, ga);
+ __m512i ggga_hi = _mm512_unpackhi_epi16(gg, ga);
+
+ // 1st shuffle for pixel reorder, same as grayA_to_RGBA.
+ __m512i ggga_lo_shuffle_1 = _mm512_shuffle_i32x4(ggga_lo, ggga_hi, 0x44),
+ ggga_hi_shuffle_1 = _mm512_shuffle_i32x4(ggga_lo, ggga_hi, 0xee);
+
+ // 2nd shuffle for pixel reorder, same as grayA_to_RGBA.
+ __m512i ggga_lo_shuffle_2 = _mm512_shuffle_i32x4(ggga_lo_shuffle_1,
+ ggga_lo_shuffle_1, 0xd8),
+ ggga_hi_shuffle_2 = _mm512_shuffle_i32x4(ggga_hi_shuffle_1,
+ ggga_hi_shuffle_1, 0xd8);
+
+ _mm512_storeu_si512((__m512i*) (dst + 0), ggga_lo_shuffle_2);
+ _mm512_storeu_si512((__m512i*) (dst + 16), ggga_hi_shuffle_2);
+
+ src += 32*2;
+ dst += 32;
+ count -= 32;
+ }
+
+ grayA_to_rgbA_portable(dst, src, count);
+}
+
+enum Format { kRGB1, kBGR1 };
+static void inverted_cmyk_to(Format format, uint32_t* dst, const uint32_t* src, int count) {
+ auto convert8 = [=](__m512i* lo, __m512i* hi) {
+ const __m512i zeros = _mm512_setzero_si512();
+ skvx::Vec<64, uint8_t> mask;
+ if (kBGR1 == format) {
+ mask = { 2,6,10,14, 1,5,9,13, 0,4,8,12, 3,7,11,15,
+ 2,6,10,14, 1,5,9,13, 0,4,8,12, 3,7,11,15,
+ 2,6,10,14, 1,5,9,13, 0,4,8,12, 3,7,11,15,
+ 2,6,10,14, 1,5,9,13, 0,4,8,12, 3,7,11,15 };
+ } else {
+ mask = { 0,4,8,12, 1,5,9,13, 2,6,10,14, 3,7,11,15,
+ 0,4,8,12, 1,5,9,13, 2,6,10,14, 3,7,11,15,
+ 0,4,8,12, 1,5,9,13, 2,6,10,14, 3,7,11,15,
+ 0,4,8,12, 1,5,9,13, 2,6,10,14, 3,7,11,15 };
+ }
+ __m512i planar = skvx::bit_pun<__m512i>(mask);
+
+ // Swizzle the pixels to 8-bit planar.
+ *lo = _mm512_shuffle_epi8(*lo, planar);
+ *hi = _mm512_shuffle_epi8(*hi, planar);
+ __m512i cm = _mm512_unpacklo_epi32(*lo, *hi),
+ yk = _mm512_unpackhi_epi32(*lo, *hi);
+
+ // Unpack to 16-bit planar.
+ __m512i c = _mm512_unpacklo_epi8(cm, zeros),
+ m = _mm512_unpackhi_epi8(cm, zeros),
+ y = _mm512_unpacklo_epi8(yk, zeros),
+ k = _mm512_unpackhi_epi8(yk, zeros);
+
+ // Scale to r, g, b.
+ __m512i r = scale(c, k),
+ g = scale(m, k),
+ b = scale(y, k);
+
+ // Repack into interlaced pixels.
+ __m512i rg = _mm512_or_si512(r, _mm512_slli_epi16(g, 8)),
+ ba = _mm512_or_si512(b, _mm512_set1_epi16((uint16_t) 0xFF00));
+ *lo = _mm512_unpacklo_epi16(rg, ba);
+ *hi = _mm512_unpackhi_epi16(rg, ba);
+ };
+
+ while (count >= 32) {
+ __m512i lo = _mm512_loadu_si512((const __m512i*) (src + 0)),
+ hi = _mm512_loadu_si512((const __m512i*) (src + 16));
+
+ convert8(&lo, &hi);
+
+ _mm512_storeu_si512((__m512i*) (dst + 0), lo);
+ _mm512_storeu_si512((__m512i*) (dst + 16), hi);
+
+ src += 32;
+ dst += 32;
+ count -= 32;
+ }
+
+ if (count >= 16) {
+ __m512i lo = _mm512_loadu_si512((const __m512i*) src),
+ hi = _mm512_setzero_si512();
+
+ convert8(&lo, &hi);
+
+ _mm512_storeu_si512((__m512i*) dst, lo);
+
+ src += 16;
+ dst += 16;
+ count -= 16;
+ }
+
+ auto proc = (kBGR1 == format) ? inverted_CMYK_to_BGR1_portable : inverted_CMYK_to_RGB1_portable;
+ proc(dst, src, count);
+}
+
+/*not static*/ inline void inverted_CMYK_to_RGB1(uint32_t dst[], const uint32_t* src, int count) {
+ inverted_cmyk_to(kRGB1, dst, src, count);
+}
+
+/*not static*/ inline void inverted_CMYK_to_BGR1(uint32_t dst[], const uint32_t* src, int count) {
+ inverted_cmyk_to(kBGR1, dst, src, count);
+}
+
+#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX2
+
+// Scale a byte by another.
+// Inputs are stored in 16-bit lanes, but are not larger than 8-bits.
+static __m256i scale(__m256i x, __m256i y) {
+ const __m256i _128 = _mm256_set1_epi16(128);
+ const __m256i _257 = _mm256_set1_epi16(257);
+
+ // (x+127)/255 == ((x+128)*257)>>16 for 0 <= x <= 255*255.
+ return _mm256_mulhi_epu16(_mm256_add_epi16(_mm256_mullo_epi16(x, y), _128), _257);
+}
+
+static void premul_should_swapRB(bool kSwapRB, uint32_t* dst, const uint32_t* src, int count) {
+
+ auto premul8 = [=](__m256i* lo, __m256i* hi) {
+ const __m256i zeros = _mm256_setzero_si256();
+ __m256i planar;
+ if (kSwapRB) {
+ planar = _mm256_setr_epi8(2,6,10,14, 1,5,9,13, 0,4,8,12, 3,7,11,15,
+ 2,6,10,14, 1,5,9,13, 0,4,8,12, 3,7,11,15);
+ } else {
+ planar = _mm256_setr_epi8(0,4,8,12, 1,5,9,13, 2,6,10,14, 3,7,11,15,
+ 0,4,8,12, 1,5,9,13, 2,6,10,14, 3,7,11,15);
+ }
+
+ // Swizzle the pixels to 8-bit planar.
+ *lo = _mm256_shuffle_epi8(*lo, planar); // rrrrgggg bbbbaaaa rrrrgggg bbbbaaaa
+ *hi = _mm256_shuffle_epi8(*hi, planar); // RRRRGGGG BBBBAAAA RRRRGGGG BBBBAAAA
+ __m256i rg = _mm256_unpacklo_epi32(*lo, *hi), // rrrrRRRR ggggGGGG rrrrRRRR ggggGGGG
+ ba = _mm256_unpackhi_epi32(*lo, *hi); // bbbbBBBB aaaaAAAA bbbbBBBB aaaaAAAA
+
+ // Unpack to 16-bit planar.
+ __m256i r = _mm256_unpacklo_epi8(rg, zeros), // r_r_r_r_ R_R_R_R_ r_r_r_r_ R_R_R_R_
+ g = _mm256_unpackhi_epi8(rg, zeros), // g_g_g_g_ G_G_G_G_ g_g_g_g_ G_G_G_G_
+ b = _mm256_unpacklo_epi8(ba, zeros), // b_b_b_b_ B_B_B_B_ b_b_b_b_ B_B_B_B_
+ a = _mm256_unpackhi_epi8(ba, zeros); // a_a_a_a_ A_A_A_A_ a_a_a_a_ A_A_A_A_
+
+ // Premultiply!
+ r = scale(r, a);
+ g = scale(g, a);
+ b = scale(b, a);
+
+ // Repack into interlaced pixels.
+ rg = _mm256_or_si256(r, _mm256_slli_epi16(g, 8)); // rgrgrgrg RGRGRGRG rgrgrgrg RGRGRGRG
+ ba = _mm256_or_si256(b, _mm256_slli_epi16(a, 8)); // babababa BABABABA babababa BABABABA
+ *lo = _mm256_unpacklo_epi16(rg, ba); // rgbargba rgbargba rgbargba rgbargba
+ *hi = _mm256_unpackhi_epi16(rg, ba); // RGBARGBA RGBARGBA RGBARGBA RGBARGBA
+ };
+
+ while (count >= 16) {
+ __m256i lo = _mm256_loadu_si256((const __m256i*) (src + 0)),
+ hi = _mm256_loadu_si256((const __m256i*) (src + 8));
+
+ premul8(&lo, &hi);
+
+ _mm256_storeu_si256((__m256i*) (dst + 0), lo);
+ _mm256_storeu_si256((__m256i*) (dst + 8), hi);
+
+ src += 16;
+ dst += 16;
+ count -= 16;
+ }
+
+ if (count >= 8) {
+ __m256i lo = _mm256_loadu_si256((const __m256i*) src),
+ hi = _mm256_setzero_si256();
+
+ premul8(&lo, &hi);
+
+ _mm256_storeu_si256((__m256i*) dst, lo);
+
+ src += 8;
+ dst += 8;
+ count -= 8;
+ }
+
+ // Call portable code to finish up the tail of [0,8) pixels.
+ auto proc = kSwapRB ? RGBA_to_bgrA_portable : RGBA_to_rgbA_portable;
+ proc(dst, src, count);
+}
+
+/*not static*/ inline void RGBA_to_rgbA(uint32_t* dst, const uint32_t* src, int count) {
+ premul_should_swapRB(false, dst, src, count);
+}
+
+/*not static*/ inline void RGBA_to_bgrA(uint32_t* dst, const uint32_t* src, int count) {
+ premul_should_swapRB(true, dst, src, count);
+}
+
+/*not static*/ inline void RGBA_to_BGRA(uint32_t* dst, const uint32_t* src, int count) {
+ const __m256i swapRB = _mm256_setr_epi8(2,1,0,3, 6,5,4,7, 10,9,8,11, 14,13,12,15,
+ 2,1,0,3, 6,5,4,7, 10,9,8,11, 14,13,12,15);
+
+ while (count >= 8) {
+ __m256i rgba = _mm256_loadu_si256((const __m256i*) src);
+ __m256i bgra = _mm256_shuffle_epi8(rgba, swapRB);
+ _mm256_storeu_si256((__m256i*) dst, bgra);
+
+ src += 8;
+ dst += 8;
+ count -= 8;
+ }
+
+ RGBA_to_BGRA_portable(dst, src, count);
+}
+
+/*not static*/ inline void grayA_to_RGBA(uint32_t dst[], const uint8_t* src, int count) {
+ while (count >= 16) {
+ __m256i ga = _mm256_loadu_si256((const __m256i*) src);
+
+ __m256i gg = _mm256_or_si256(_mm256_and_si256(ga, _mm256_set1_epi16(0x00FF)),
+ _mm256_slli_epi16(ga, 8));
+
+ __m256i ggga_lo = _mm256_unpacklo_epi16(gg, ga);
+ __m256i ggga_hi = _mm256_unpackhi_epi16(gg, ga);
+
+ // Shuffle for pixel reorder
+ // Note. 'p' stands for 'ggga'
+ // Before shuffle:
+ // ggga_lo = p0 p1 p2 p3 | p8 p9 p10 p11
+ // ggga_hi = p4 p5 p6 p7 | p12 p13 p14 p15
+ //
+ // After shuffle:
+ // ggga_lo_shuffle = p0 p1 p2 p3 | p4 p5 p6 p7
+ // ggga_hi_shuffle = p8 p9 p10 p11 | p12 p13 p14 p15
+ __m256i ggga_lo_shuffle = _mm256_permute2x128_si256(ggga_lo, ggga_hi, 0x20),
+ ggga_hi_shuffle = _mm256_permute2x128_si256(ggga_lo, ggga_hi, 0x31);
+
+ _mm256_storeu_si256((__m256i*) (dst + 0), ggga_lo_shuffle);
+ _mm256_storeu_si256((__m256i*) (dst + 8), ggga_hi_shuffle);
+
+ src += 16*2;
+ dst += 16;
+ count -= 16;
+ }
+
+ grayA_to_RGBA_portable(dst, src, count);
+}
+
+/*not static*/ inline void grayA_to_rgbA(uint32_t dst[], const uint8_t* src, int count) {
+ while (count >= 16) {
+ __m256i grayA = _mm256_loadu_si256((const __m256i*) src);
+
+ __m256i g0 = _mm256_and_si256(grayA, _mm256_set1_epi16(0x00FF));
+ __m256i a0 = _mm256_srli_epi16(grayA, 8);
+
+ // Premultiply
+ g0 = scale(g0, a0);
+
+ __m256i gg = _mm256_or_si256(g0, _mm256_slli_epi16(g0, 8));
+ __m256i ga = _mm256_or_si256(g0, _mm256_slli_epi16(a0, 8));
+
+ __m256i ggga_lo = _mm256_unpacklo_epi16(gg, ga);
+ __m256i ggga_hi = _mm256_unpackhi_epi16(gg, ga);
+
+ // Shuffle for pixel reorder, similar as grayA_to_RGBA
+ __m256i ggga_lo_shuffle = _mm256_permute2x128_si256(ggga_lo, ggga_hi, 0x20),
+ ggga_hi_shuffle = _mm256_permute2x128_si256(ggga_lo, ggga_hi, 0x31);
+
+ _mm256_storeu_si256((__m256i*) (dst + 0), ggga_lo_shuffle);
+ _mm256_storeu_si256((__m256i*) (dst + 8), ggga_hi_shuffle);
+
+ src += 16*2;
+ dst += 16;
+ count -= 16;
+ }
+
+ grayA_to_rgbA_portable(dst, src, count);
+}
+
+enum Format { kRGB1, kBGR1 };
+static void inverted_cmyk_to(Format format, uint32_t* dst, const uint32_t* src, int count) {
+ auto convert8 = [=](__m256i* lo, __m256i* hi) {
+ const __m256i zeros = _mm256_setzero_si256();
+ __m256i planar;
+ if (kBGR1 == format) {
+ planar = _mm256_setr_epi8(2,6,10,14, 1,5,9,13, 0,4,8,12, 3,7,11,15,
+ 2,6,10,14, 1,5,9,13, 0,4,8,12, 3,7,11,15);
+ } else {
+ planar = _mm256_setr_epi8(0,4,8,12, 1,5,9,13, 2,6,10,14, 3,7,11,15,
+ 0,4,8,12, 1,5,9,13, 2,6,10,14, 3,7,11,15);
+ }
+
+ // Swizzle the pixels to 8-bit planar.
+ *lo = _mm256_shuffle_epi8(*lo, planar); // ccccmmmm yyyykkkk ccccmmmm yyyykkkk
+ *hi = _mm256_shuffle_epi8(*hi, planar); // CCCCMMMM YYYYKKKK CCCCMMMM YYYYKKKK
+ __m256i cm = _mm256_unpacklo_epi32(*lo, *hi), // ccccCCCC mmmmMMMM ccccCCCC mmmmMMMM
+ yk = _mm256_unpackhi_epi32(*lo, *hi); // yyyyYYYY kkkkKKKK yyyyYYYY kkkkKKKK
+
+ // Unpack to 16-bit planar.
+ __m256i c = _mm256_unpacklo_epi8(cm, zeros), // c_c_c_c_ C_C_C_C_ c_c_c_c_ C_C_C_C_
+ m = _mm256_unpackhi_epi8(cm, zeros), // m_m_m_m_ M_M_M_M_ m_m_m_m_ M_M_M_M_
+ y = _mm256_unpacklo_epi8(yk, zeros), // y_y_y_y_ Y_Y_Y_Y_ y_y_y_y_ Y_Y_Y_Y_
+ k = _mm256_unpackhi_epi8(yk, zeros); // k_k_k_k_ K_K_K_K_ k_k_k_k_ K_K_K_K_
+
+ // Scale to r, g, b.
+ __m256i r = scale(c, k),
+ g = scale(m, k),
+ b = scale(y, k);
+
+ // Repack into interlaced pixels:
+ // rg = rgrgrgrg RGRGRGRG rgrgrgrg RGRGRGRG
+ // ba = b1b1b1b1 B1B1B1B1 b1b1b1b1 B1B1B1B1
+ __m256i rg = _mm256_or_si256(r, _mm256_slli_epi16(g, 8)),
+ ba = _mm256_or_si256(b, _mm256_set1_epi16((uint16_t) 0xFF00));
+ *lo = _mm256_unpacklo_epi16(rg, ba); // rgb1rgb1 rgb1rgb1 rgb1rgb1 rgb1rgb1
+ *hi = _mm256_unpackhi_epi16(rg, ba); // RGB1RGB1 RGB1RGB1 RGB1RGB1 RGB1RGB1
+ };
+
+ while (count >= 16) {
+ __m256i lo = _mm256_loadu_si256((const __m256i*) (src + 0)),
+ hi = _mm256_loadu_si256((const __m256i*) (src + 8));
+
+ convert8(&lo, &hi);
+
+ _mm256_storeu_si256((__m256i*) (dst + 0), lo);
+ _mm256_storeu_si256((__m256i*) (dst + 8), hi);
+
+ src += 16;
+ dst += 16;
+ count -= 16;
+ }
+
+ if (count >= 8) {
+ __m256i lo = _mm256_loadu_si256((const __m256i*) src),
+ hi = _mm256_setzero_si256();
+
+ convert8(&lo, &hi);
+
+ _mm256_storeu_si256((__m256i*) dst, lo);
+
+ src += 8;
+ dst += 8;
+ count -= 8;
+ }
+
+ auto proc = (kBGR1 == format) ? inverted_CMYK_to_BGR1_portable : inverted_CMYK_to_RGB1_portable;
+ proc(dst, src, count);
+}
+
+/*not static*/ inline void inverted_CMYK_to_RGB1(uint32_t dst[], const uint32_t* src, int count) {
+ inverted_cmyk_to(kRGB1, dst, src, count);
+}
+
+/*not static*/ inline void inverted_CMYK_to_BGR1(uint32_t dst[], const uint32_t* src, int count) {
+ inverted_cmyk_to(kBGR1, dst, src, count);
}
#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3
@@ -489,10 +879,9 @@ static __m128i scale(__m128i x, __m128i y) {
return _mm_mulhi_epu16(_mm_add_epi16(_mm_mullo_epi16(x, y), _128), _257);
}
-template <bool kSwapRB>
-static void premul_should_swapRB(uint32_t* dst, const uint32_t* src, int count) {
+static void premul_should_swapRB(bool kSwapRB, uint32_t* dst, const uint32_t* src, int count) {
- auto premul8 = [](__m128i* lo, __m128i* hi) {
+ auto premul8 = [=](__m128i* lo, __m128i* hi) {
const __m128i zeros = _mm_setzero_si128();
__m128i planar;
if (kSwapRB) {
@@ -558,11 +947,11 @@ static void premul_should_swapRB(uint32_t* dst, const uint32_t* src, int count)
}
/*not static*/ inline void RGBA_to_rgbA(uint32_t* dst, const uint32_t* src, int count) {
- premul_should_swapRB<false>(dst, src, count);
+ premul_should_swapRB(false, dst, src, count);
}
/*not static*/ inline void RGBA_to_bgrA(uint32_t* dst, const uint32_t* src, int count) {
- premul_should_swapRB<true>(dst, src, count);
+ premul_should_swapRB(true, dst, src, count);
}
/*not static*/ inline void RGBA_to_BGRA(uint32_t* dst, const uint32_t* src, int count) {
@@ -581,75 +970,6 @@ static void premul_should_swapRB(uint32_t* dst, const uint32_t* src, int count)
RGBA_to_BGRA_portable(dst, src, count);
}
-template <bool kSwapRB>
-static void insert_alpha_should_swaprb(uint32_t dst[], const uint8_t* src, int count) {
- const __m128i alphaMask = _mm_set1_epi32(0xFF000000);
- __m128i expand;
- const uint8_t X = 0xFF; // Used a placeholder. The value of X is irrelevant.
- if (kSwapRB) {
- expand = _mm_setr_epi8(2,1,0,X, 5,4,3,X, 8,7,6,X, 11,10,9,X);
- } else {
- expand = _mm_setr_epi8(0,1,2,X, 3,4,5,X, 6,7,8,X, 9,10,11,X);
- }
-
- while (count >= 6) {
- // Load a vector. While this actually contains 5 pixels plus an
- // extra component, we will discard all but the first four pixels on
- // this iteration.
- __m128i rgb = _mm_loadu_si128((const __m128i*) src);
-
- // Expand the first four pixels to RGBX and then mask to RGB(FF).
- __m128i rgba = _mm_or_si128(_mm_shuffle_epi8(rgb, expand), alphaMask);
-
- // Store 4 pixels.
- _mm_storeu_si128((__m128i*) dst, rgba);
-
- src += 4*3;
- dst += 4;
- count -= 4;
- }
-
- // Call portable code to finish up the tail of [0,4) pixels.
- auto proc = kSwapRB ? RGB_to_BGR1_portable : RGB_to_RGB1_portable;
- proc(dst, src, count);
-}
-
-/*not static*/ inline void RGB_to_RGB1(uint32_t dst[], const uint8_t* src, int count) {
- insert_alpha_should_swaprb<false>(dst, src, count);
-}
-
-/*not static*/ inline void RGB_to_BGR1(uint32_t dst[], const uint8_t* src, int count) {
- insert_alpha_should_swaprb<true>(dst, src, count);
-}
-
-/*not static*/ inline void gray_to_RGB1(uint32_t dst[], const uint8_t* src, int count) {
- const __m128i alphas = _mm_set1_epi8((uint8_t) 0xFF);
- while (count >= 16) {
- __m128i grays = _mm_loadu_si128((const __m128i*) src);
-
- __m128i gg_lo = _mm_unpacklo_epi8(grays, grays);
- __m128i gg_hi = _mm_unpackhi_epi8(grays, grays);
- __m128i ga_lo = _mm_unpacklo_epi8(grays, alphas);
- __m128i ga_hi = _mm_unpackhi_epi8(grays, alphas);
-
- __m128i ggga0 = _mm_unpacklo_epi16(gg_lo, ga_lo);
- __m128i ggga1 = _mm_unpackhi_epi16(gg_lo, ga_lo);
- __m128i ggga2 = _mm_unpacklo_epi16(gg_hi, ga_hi);
- __m128i ggga3 = _mm_unpackhi_epi16(gg_hi, ga_hi);
-
- _mm_storeu_si128((__m128i*) (dst + 0), ggga0);
- _mm_storeu_si128((__m128i*) (dst + 4), ggga1);
- _mm_storeu_si128((__m128i*) (dst + 8), ggga2);
- _mm_storeu_si128((__m128i*) (dst + 12), ggga3);
-
- src += 16;
- dst += 16;
- count -= 16;
- }
-
- gray_to_RGB1_portable(dst, src, count);
-}
-
/*not static*/ inline void grayA_to_RGBA(uint32_t dst[], const uint8_t* src, int count) {
while (count >= 8) {
__m128i ga = _mm_loadu_si128((const __m128i*) src);
@@ -700,9 +1020,8 @@ static void insert_alpha_should_swaprb(uint32_t dst[], const uint8_t* src, int c
}
enum Format { kRGB1, kBGR1 };
-template <Format format>
-static void inverted_cmyk_to(uint32_t* dst, const uint32_t* src, int count) {
- auto convert8 = [](__m128i* lo, __m128i* hi) {
+static void inverted_cmyk_to(Format format, uint32_t* dst, const uint32_t* src, int count) {
+ auto convert8 = [=](__m128i* lo, __m128i* hi) {
const __m128i zeros = _mm_setzero_si128();
__m128i planar;
if (kBGR1 == format) {
@@ -767,11 +1086,11 @@ static void inverted_cmyk_to(uint32_t* dst, const uint32_t* src, int count) {
}
/*not static*/ inline void inverted_CMYK_to_RGB1(uint32_t dst[], const uint32_t* src, int count) {
- inverted_cmyk_to<kRGB1>(dst, src, count);
+ inverted_cmyk_to(kRGB1, dst, src, count);
}
/*not static*/ inline void inverted_CMYK_to_BGR1(uint32_t dst[], const uint32_t* src, int count) {
- inverted_cmyk_to<kBGR1>(dst, src, count);
+ inverted_cmyk_to(kBGR1, dst, src, count);
}
#else
@@ -788,18 +1107,6 @@ static void inverted_cmyk_to(uint32_t* dst, const uint32_t* src, int count) {
RGBA_to_BGRA_portable(dst, src, count);
}
-/*not static*/ inline void RGB_to_RGB1(uint32_t dst[], const uint8_t* src, int count) {
- RGB_to_RGB1_portable(dst, src, count);
-}
-
-/*not static*/ inline void RGB_to_BGR1(uint32_t dst[], const uint8_t* src, int count) {
- RGB_to_BGR1_portable(dst, src, count);
-}
-
-/*not static*/ inline void gray_to_RGB1(uint32_t dst[], const uint8_t* src, int count) {
- gray_to_RGB1_portable(dst, src, count);
-}
-
/*not static*/ inline void grayA_to_RGBA(uint32_t dst[], const uint8_t* src, int count) {
grayA_to_RGBA_portable(dst, src, count);
}
@@ -818,6 +1125,265 @@ static void inverted_cmyk_to(uint32_t* dst, const uint32_t* src, int count) {
#endif
+// Basically as above, but we found no benefit from AVX-512 for gray_to_RGB1.
+static void gray_to_RGB1_portable(uint32_t dst[], const uint8_t* src, int count) {
+ for (int i = 0; i < count; i++) {
+ dst[i] = (uint32_t)0xFF << 24
+ | (uint32_t)src[i] << 16
+ | (uint32_t)src[i] << 8
+ | (uint32_t)src[i] << 0;
+ }
+}
+#if defined(SK_ARM_HAS_NEON)
+ /*not static*/ inline void gray_to_RGB1(uint32_t dst[], const uint8_t* src, int count) {
+ while (count >= 16) {
+ // Load 16 pixels.
+ uint8x16_t gray = vld1q_u8(src);
+
+ // Set each of the color channels.
+ uint8x16x4_t rgba;
+ rgba.val[0] = gray;
+ rgba.val[1] = gray;
+ rgba.val[2] = gray;
+ rgba.val[3] = vdupq_n_u8(0xFF);
+
+ // Store 16 pixels.
+ vst4q_u8((uint8_t*) dst, rgba);
+ src += 16;
+ dst += 16;
+ count -= 16;
+ }
+ if (count >= 8) {
+ // Load 8 pixels.
+ uint8x8_t gray = vld1_u8(src);
+
+ // Set each of the color channels.
+ uint8x8x4_t rgba;
+ rgba.val[0] = gray;
+ rgba.val[1] = gray;
+ rgba.val[2] = gray;
+ rgba.val[3] = vdup_n_u8(0xFF);
+
+ // Store 8 pixels.
+ vst4_u8((uint8_t*) dst, rgba);
+ src += 8;
+ dst += 8;
+ count -= 8;
+ }
+ gray_to_RGB1_portable(dst, src, count);
+ }
+#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX2
+ /*not static*/ inline void gray_to_RGB1(uint32_t dst[], const uint8_t* src, int count) {
+ const __m256i alphas = _mm256_set1_epi8((uint8_t) 0xFF);
+ while (count >= 32) {
+ __m256i grays = _mm256_loadu_si256((const __m256i*) src);
+
+ __m256i gg_lo = _mm256_unpacklo_epi8(grays, grays);
+ __m256i gg_hi = _mm256_unpackhi_epi8(grays, grays);
+ __m256i ga_lo = _mm256_unpacklo_epi8(grays, alphas);
+ __m256i ga_hi = _mm256_unpackhi_epi8(grays, alphas);
+
+ __m256i ggga0 = _mm256_unpacklo_epi16(gg_lo, ga_lo);
+ __m256i ggga1 = _mm256_unpackhi_epi16(gg_lo, ga_lo);
+ __m256i ggga2 = _mm256_unpacklo_epi16(gg_hi, ga_hi);
+ __m256i ggga3 = _mm256_unpackhi_epi16(gg_hi, ga_hi);
+
+ // Shuffle for pixel reorder.
+ // Note. 'p' stands for 'ggga'
+ // Before shuffle:
+ // ggga0 = p0 p1 p2 p3 | p16 p17 p18 p19
+ // ggga1 = p4 p5 p6 p7 | p20 p21 p22 p23
+ // ggga2 = p8 p9 p10 p11 | p24 p25 p26 p27
+ // ggga3 = p12 p13 p14 p15 | p28 p29 p30 p31
+ //
+ // After shuffle:
+ // ggga0_shuffle = p0 p1 p2 p3 | p4 p5 p6 p7
+ // ggga1_shuffle = p8 p9 p10 p11 | p12 p13 p14 p15
+ // ggga2_shuffle = p16 p17 p18 p19 | p20 p21 p22 p23
+ // ggga3_shuffle = p24 p25 p26 p27 | p28 p29 p30 p31
+ __m256i ggga0_shuffle = _mm256_permute2x128_si256(ggga0, ggga1, 0x20),
+ ggga1_shuffle = _mm256_permute2x128_si256(ggga2, ggga3, 0x20),
+ ggga2_shuffle = _mm256_permute2x128_si256(ggga0, ggga1, 0x31),
+ ggga3_shuffle = _mm256_permute2x128_si256(ggga2, ggga3, 0x31);
+
+ _mm256_storeu_si256((__m256i*) (dst + 0), ggga0_shuffle);
+ _mm256_storeu_si256((__m256i*) (dst + 8), ggga1_shuffle);
+ _mm256_storeu_si256((__m256i*) (dst + 16), ggga2_shuffle);
+ _mm256_storeu_si256((__m256i*) (dst + 24), ggga3_shuffle);
+
+ src += 32;
+ dst += 32;
+ count -= 32;
+ }
+ gray_to_RGB1_portable(dst, src, count);
+ }
+#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3 // TODO: just check >= SSE2?
+ /*not static*/ inline void gray_to_RGB1(uint32_t dst[], const uint8_t* src, int count) {
+ const __m128i alphas = _mm_set1_epi8((uint8_t) 0xFF);
+ while (count >= 16) {
+ __m128i grays = _mm_loadu_si128((const __m128i*) src);
+
+ __m128i gg_lo = _mm_unpacklo_epi8(grays, grays);
+ __m128i gg_hi = _mm_unpackhi_epi8(grays, grays);
+ __m128i ga_lo = _mm_unpacklo_epi8(grays, alphas);
+ __m128i ga_hi = _mm_unpackhi_epi8(grays, alphas);
+
+ __m128i ggga0 = _mm_unpacklo_epi16(gg_lo, ga_lo);
+ __m128i ggga1 = _mm_unpackhi_epi16(gg_lo, ga_lo);
+ __m128i ggga2 = _mm_unpacklo_epi16(gg_hi, ga_hi);
+ __m128i ggga3 = _mm_unpackhi_epi16(gg_hi, ga_hi);
+
+ _mm_storeu_si128((__m128i*) (dst + 0), ggga0);
+ _mm_storeu_si128((__m128i*) (dst + 4), ggga1);
+ _mm_storeu_si128((__m128i*) (dst + 8), ggga2);
+ _mm_storeu_si128((__m128i*) (dst + 12), ggga3);
+
+ src += 16;
+ dst += 16;
+ count -= 16;
+ }
+ gray_to_RGB1_portable(dst, src, count);
+ }
+#else
+ /*not static*/ inline void gray_to_RGB1(uint32_t dst[], const uint8_t* src, int count) {
+ gray_to_RGB1_portable(dst, src, count);
+ }
+#endif
+
+// Again as above, this time not even finding benefit from AVX2 for RGB_to_{RGB,BGR}1.
+static void RGB_to_RGB1_portable(uint32_t dst[], const uint8_t* src, int count) {
+ for (int i = 0; i < count; i++) {
+ uint8_t r = src[0],
+ g = src[1],
+ b = src[2];
+ src += 3;
+ dst[i] = (uint32_t)0xFF << 24
+ | (uint32_t)b << 16
+ | (uint32_t)g << 8
+ | (uint32_t)r << 0;
+ }
+}
+static void RGB_to_BGR1_portable(uint32_t dst[], const uint8_t* src, int count) {
+ for (int i = 0; i < count; i++) {
+ uint8_t r = src[0],
+ g = src[1],
+ b = src[2];
+ src += 3;
+ dst[i] = (uint32_t)0xFF << 24
+ | (uint32_t)r << 16
+ | (uint32_t)g << 8
+ | (uint32_t)b << 0;
+ }
+}
+#if defined(SK_ARM_HAS_NEON)
+ static void insert_alpha_should_swaprb(bool kSwapRB,
+ uint32_t dst[], const uint8_t* src, int count) {
+ while (count >= 16) {
+ // Load 16 pixels.
+ uint8x16x3_t rgb = vld3q_u8(src);
+
+ // Insert an opaque alpha channel and swap if needed.
+ uint8x16x4_t rgba;
+ if (kSwapRB) {
+ rgba.val[0] = rgb.val[2];
+ rgba.val[2] = rgb.val[0];
+ } else {
+ rgba.val[0] = rgb.val[0];
+ rgba.val[2] = rgb.val[2];
+ }
+ rgba.val[1] = rgb.val[1];
+ rgba.val[3] = vdupq_n_u8(0xFF);
+
+ // Store 16 pixels.
+ vst4q_u8((uint8_t*) dst, rgba);
+ src += 16*3;
+ dst += 16;
+ count -= 16;
+ }
+
+ if (count >= 8) {
+ // Load 8 pixels.
+ uint8x8x3_t rgb = vld3_u8(src);
+
+ // Insert an opaque alpha channel and swap if needed.
+ uint8x8x4_t rgba;
+ if (kSwapRB) {
+ rgba.val[0] = rgb.val[2];
+ rgba.val[2] = rgb.val[0];
+ } else {
+ rgba.val[0] = rgb.val[0];
+ rgba.val[2] = rgb.val[2];
+ }
+ rgba.val[1] = rgb.val[1];
+ rgba.val[3] = vdup_n_u8(0xFF);
+
+ // Store 8 pixels.
+ vst4_u8((uint8_t*) dst, rgba);
+ src += 8*3;
+ dst += 8;
+ count -= 8;
+ }
+
+ // Call portable code to finish up the tail of [0,8) pixels.
+ auto proc = kSwapRB ? RGB_to_BGR1_portable : RGB_to_RGB1_portable;
+ proc(dst, src, count);
+ }
+
+ /*not static*/ inline void RGB_to_RGB1(uint32_t dst[], const uint8_t* src, int count) {
+ insert_alpha_should_swaprb(false, dst, src, count);
+ }
+ /*not static*/ inline void RGB_to_BGR1(uint32_t dst[], const uint8_t* src, int count) {
+ insert_alpha_should_swaprb(true, dst, src, count);
+ }
+#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3
+ static void insert_alpha_should_swaprb(bool kSwapRB,
+ uint32_t dst[], const uint8_t* src, int count) {
+ const __m128i alphaMask = _mm_set1_epi32(0xFF000000);
+ __m128i expand;
+ const uint8_t X = 0xFF; // Used a placeholder. The value of X is irrelevant.
+ if (kSwapRB) {
+ expand = _mm_setr_epi8(2,1,0,X, 5,4,3,X, 8,7,6,X, 11,10,9,X);
+ } else {
+ expand = _mm_setr_epi8(0,1,2,X, 3,4,5,X, 6,7,8,X, 9,10,11,X);
+ }
+
+ while (count >= 6) {
+ // Load a vector. While this actually contains 5 pixels plus an
+ // extra component, we will discard all but the first four pixels on
+ // this iteration.
+ __m128i rgb = _mm_loadu_si128((const __m128i*) src);
+
+ // Expand the first four pixels to RGBX and then mask to RGB(FF).
+ __m128i rgba = _mm_or_si128(_mm_shuffle_epi8(rgb, expand), alphaMask);
+
+ // Store 4 pixels.
+ _mm_storeu_si128((__m128i*) dst, rgba);
+
+ src += 4*3;
+ dst += 4;
+ count -= 4;
+ }
+
+ // Call portable code to finish up the tail of [0,4) pixels.
+ auto proc = kSwapRB ? RGB_to_BGR1_portable : RGB_to_RGB1_portable;
+ proc(dst, src, count);
+ }
+
+ /*not static*/ inline void RGB_to_RGB1(uint32_t dst[], const uint8_t* src, int count) {
+ insert_alpha_should_swaprb(false, dst, src, count);
+ }
+ /*not static*/ inline void RGB_to_BGR1(uint32_t dst[], const uint8_t* src, int count) {
+ insert_alpha_should_swaprb(true, dst, src, count);
+ }
+#else
+ /*not static*/ inline void RGB_to_RGB1(uint32_t dst[], const uint8_t* src, int count) {
+ RGB_to_RGB1_portable(dst, src, count);
+ }
+ /*not static*/ inline void RGB_to_BGR1(uint32_t dst[], const uint8_t* src, int count) {
+ RGB_to_BGR1_portable(dst, src, count);
+ }
+#endif
+
}
#endif // SkSwizzler_opts_DEFINED
diff --git a/chromium/third_party/skia/src/opts/SkVM_opts.h b/chromium/third_party/skia/src/opts/SkVM_opts.h
index 2a953b76eb0..a4a719b8da1 100644
--- a/chromium/third_party/skia/src/opts/SkVM_opts.h
+++ b/chromium/third_party/skia/src/opts/SkVM_opts.h
@@ -229,6 +229,7 @@ namespace SK_OPTS_NS {
CASE(Op::pack): r(d).u32 = r(x).u32 | (r(y).u32 << immz); break;
+ CASE(Op::ceil): r(d).f32 = skvx::ceil(r(x).f32) ; break;
CASE(Op::floor): r(d).f32 = skvx::floor(r(x).f32) ; break;
CASE(Op::to_f32): r(d).f32 = skvx::cast<float>( r(x).i32 ); break;
CASE(Op::trunc): r(d).i32 = skvx::cast<int> ( r(x).f32 ); break;
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsCubic.cpp b/chromium/third_party/skia/src/pathops/SkPathOpsCubic.cpp
index ebf195d7b0a..1275fababd0 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsCubic.cpp
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsCubic.cpp
@@ -257,7 +257,7 @@ int SkDCubic::ComplexBreak(const SkPoint pointsPtr[4], SkScalar* t) {
return (int) (t[0] > 0 && t[0] < 1);
}
}
- // fall through if no t value found
+ [[fallthrough]]; // fall through if no t value found
case SkCubicType::kSerpentine:
case SkCubicType::kLocalCusp:
case SkCubicType::kCuspAtInfinity: {
@@ -313,9 +313,10 @@ int SkDCubic::ComplexBreak(const SkPoint pointsPtr[4], SkScalar* t) {
}
return resultCount;
}
+ break;
}
default:
- ;
+ break;
}
return 0;
}
diff --git a/chromium/third_party/skia/src/pdf/SkPDFDevice.cpp b/chromium/third_party/skia/src/pdf/SkPDFDevice.cpp
index c06bb27299e..b31ec0588b4 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFDevice.cpp
+++ b/chromium/third_party/skia/src/pdf/SkPDFDevice.cpp
@@ -75,7 +75,7 @@ public:
: fOut(out)
, fMarkId(-1) {
if (nodeId) {
- fMarkId = document->getMarkIdForNodeId(nodeId);
+ fMarkId = document->createMarkIdForNodeId(nodeId);
}
if (fMarkId != -1) {
@@ -740,7 +740,7 @@ struct PositionedGlyph {
static SkRect get_glyph_bounds_device_space(const SkGlyph* glyph,
SkScalar xScale, SkScalar yScale,
SkPoint xy, const SkMatrix& ctm) {
- SkRect glyphBounds = SkMatrix::MakeScale(xScale, yScale).mapRect(glyph->rect());
+ SkRect glyphBounds = SkMatrix::Scale(xScale, yScale).mapRect(glyph->rect());
glyphBounds.offset(xy);
ctm.mapRect(&glyphBounds); // now in dev space.
return glyphBounds;
@@ -1000,7 +1000,7 @@ void SkPDFDevice::drawDevice(SkBaseDevice* device, int x, int y, const SkPaint&
return;
}
- SkMatrix matrix = SkMatrix::MakeTrans(SkIntToScalar(x), SkIntToScalar(y));
+ SkMatrix matrix = SkMatrix::Translate(SkIntToScalar(x), SkIntToScalar(y));
ScopedContentEntry content(this, &this->cs(), matrix, paint);
if (!content) {
return;
@@ -1658,7 +1658,7 @@ void SkPDFDevice::internalDrawImageRect(SkKeyedImage imageSubset,
canvas->setMatrix(offsetMatrix);
canvas->drawImage(imageSubset.image(), 0, 0);
// Make sure the final bits are in the bitmap.
- surface->flush();
+ surface->flushAndSubmit();
// In the new space, we use the identity matrix translated
// and scaled to reflect DPI.
@@ -1722,8 +1722,7 @@ void SkPDFDevice::internalDrawImageRect(SkKeyedImage imageSubset,
#include "include/core/SkImageFilter.h"
#include "src/core/SkSpecialImage.h"
-void SkPDFDevice::drawSpecial(SkSpecialImage* srcImg, int x, int y, const SkPaint& paint,
- SkImage* clipImage, const SkMatrix& clipMatrix) {
+void SkPDFDevice::drawSpecial(SkSpecialImage* srcImg, int x, int y, const SkPaint& paint) {
if (this->hasEmptyClip()) {
return;
}
diff --git a/chromium/third_party/skia/src/pdf/SkPDFDevice.h b/chromium/third_party/skia/src/pdf/SkPDFDevice.h
index c0c2d7419f3..cee58904b7a 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFDevice.h
+++ b/chromium/third_party/skia/src/pdf/SkPDFDevice.h
@@ -111,8 +111,7 @@ protected:
void drawAnnotation(const SkRect&, const char key[], SkData* value) override;
- void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&,
- SkImage*, const SkMatrix&) override;
+ void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&) override;
sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override;
sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override;
SkImageFilterCache* getImageFilterCache() override;
diff --git a/chromium/third_party/skia/src/pdf/SkPDFDocument.cpp b/chromium/third_party/skia/src/pdf/SkPDFDocument.cpp
index f13ec2dc330..653fa221703 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFDocument.cpp
+++ b/chromium/third_party/skia/src/pdf/SkPDFDocument.cpp
@@ -334,10 +334,17 @@ std::unique_ptr<SkPDFArray> SkPDFDocument::getAnnotations() {
SkDEBUGFAIL("Unknown link type.");
}
+ if (link->fNodeId) {
+ int structParentKey = createStructParentKeyForNodeId(link->fNodeId);
+ if (structParentKey != -1) {
+ annotation.insertInt("StructParent", structParentKey);
+ }
+ }
+
SkPDFIndirectReference annotationRef = emit(annotation);
array->appendRef(annotationRef);
if (link->fNodeId) {
- fTagTree.addNodeAnnotation(link->fNodeId, annotationRef);
+ fTagTree.addNodeAnnotation(link->fNodeId, annotationRef, SkToUInt(this->currentPageIndex()));
}
}
return array;
@@ -519,8 +526,12 @@ const SkMatrix& SkPDFDocument::currentPageTransform() const {
return fPageDevice->initialTransform();
}
-int SkPDFDocument::getMarkIdForNodeId(int nodeId) {
- return fTagTree.getMarkIdForNodeId(nodeId, SkToUInt(this->currentPageIndex()));
+int SkPDFDocument::createMarkIdForNodeId(int nodeId) {
+ return fTagTree.createMarkIdForNodeId(nodeId, SkToUInt(this->currentPageIndex()));
+}
+
+int SkPDFDocument::createStructParentKeyForNodeId(int nodeId) {
+ return fTagTree.createStructParentKeyForNodeId(nodeId, SkToUInt(this->currentPageIndex()));
}
static std::vector<const SkPDFFont*> get_fonts(const SkPDFDocument& canon) {
diff --git a/chromium/third_party/skia/src/pdf/SkPDFDocumentPriv.h b/chromium/third_party/skia/src/pdf/SkPDFDocumentPriv.h
index 523eeb32777..6d9220d0fd5 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFDocumentPriv.h
+++ b/chromium/third_party/skia/src/pdf/SkPDFDocumentPriv.h
@@ -116,8 +116,14 @@ public:
SkPDFIndirectReference currentPage() const {
return SkASSERT(!fPageRefs.empty()), fPageRefs.back();
}
- // Returns -1 if no mark ID.
- int getMarkIdForNodeId(int nodeId);
+ // Used to allow marked content to refer to its corresponding structure
+ // tree node, via a page entry in the parent tree. Returns -1 if no
+ // mark ID.
+ int createMarkIdForNodeId(int nodeId);
+ // Used to allow annotations to refer to their corresponding structure
+ // tree node, via the struct parent tree. Returns -1 if no struct parent
+ // key.
+ int createStructParentKeyForNodeId(int nodeId);
std::unique_ptr<SkPDFArray> getAnnotations();
diff --git a/chromium/third_party/skia/src/pdf/SkPDFTag.cpp b/chromium/third_party/skia/src/pdf/SkPDFTag.cpp
index 90bafbb0e2a..44919de7089 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFTag.cpp
+++ b/chromium/third_party/skia/src/pdf/SkPDFTag.cpp
@@ -66,6 +66,56 @@ static const char* tag_name_from_type(SkPDF::DocumentStructureType type) {
SK_ABORT("bad tag");
}
+// The struct parent tree consists of one entry per page, followed by
+// entries for individual struct tree nodes corresponding to
+// annotations. Each entry is a key/value pair with an integer key
+// and an indirect reference key.
+//
+// The page entries get consecutive keys starting at 0. Since we don't
+// know the total number of pages in the document at the time we start
+// processing annotations, start the key for annotations with a large
+// number, which effectively becomes the maximum number of pages in a
+// PDF we can handle.
+const int kFirstAnnotationStructParentKey = 100000;
+
+struct SkPDFTagNode {
+ // Structure element nodes need a unique alphanumeric ID,
+ // and we need to be able to output them sorted in lexicographic
+ // order. This helper function takes one of our node IDs and
+ // builds an ID string that zero-pads the digits so that lexicographic
+ // order matches numeric order.
+ static SkString nodeIdToString(int nodeId) {
+ SkString idString;
+ idString.printf("node%08d", nodeId);
+ return idString;
+ }
+
+ SkPDFTagNode* fChildren = nullptr;
+ size_t fChildCount = 0;
+ struct MarkedContentInfo {
+ unsigned fPageIndex;
+ int fMarkId;
+ };
+ SkTArray<MarkedContentInfo> fMarkedContent;
+ int fNodeId;
+ SkPDF::DocumentStructureType fType;
+ SkString fTypeString;
+ SkString fAlt;
+ SkString fLang;
+ SkPDFIndirectReference fRef;
+ enum State {
+ kUnknown,
+ kYes,
+ kNo,
+ } fCanDiscard = kUnknown;
+ std::unique_ptr<SkPDFArray> fAttributes;
+ struct AnnotationInfo {
+ unsigned fPageIndex;
+ SkPDFIndirectReference fAnnotationRef;
+ };
+ std::vector<AnnotationInfo> fAnnotations;
+};
+
SkPDF::AttributeList::AttributeList() = default;
SkPDF::AttributeList::~AttributeList() = default;
@@ -90,7 +140,7 @@ void SkPDF::AttributeList::appendFloat(
fAttrs->appendObject(std::move(attrDict));
}
-void SkPDF::AttributeList::appendString(
+void SkPDF::AttributeList::appendName(
const char* owner, const char* name, const char* value) {
if (!fAttrs)
fAttrs = SkPDFMakeArray();
@@ -100,6 +150,16 @@ void SkPDF::AttributeList::appendString(
fAttrs->appendObject(std::move(attrDict));
}
+void SkPDF::AttributeList::appendString(
+ const char* owner, const char* name, const char* value) {
+ if (!fAttrs)
+ fAttrs = SkPDFMakeArray();
+ std::unique_ptr<SkPDFDict> attrDict = SkPDFMakeDict();
+ attrDict->insertName("O", owner);
+ attrDict->insertString(name, value);
+ fAttrs->appendObject(std::move(attrDict));
+}
+
void SkPDF::AttributeList::appendFloatArray(
const char* owner, const char* name, const std::vector<float>& value) {
if (!fAttrs)
@@ -114,45 +174,41 @@ void SkPDF::AttributeList::appendFloatArray(
fAttrs->appendObject(std::move(attrDict));
}
+// Deprecated.
void SkPDF::AttributeList::appendStringArray(
+ const char* owner,
+ const char* name,
+ const std::vector<SkString>& values) {
+ if (!fAttrs)
+ fAttrs = SkPDFMakeArray();
+ std::unique_ptr<SkPDFDict> attrDict = SkPDFMakeDict();
+ attrDict->insertName("O", owner);
+ std::unique_ptr<SkPDFArray> pdfArray = SkPDFMakeArray();
+ for (SkString element : values) {
+ pdfArray->appendString(element);
+ }
+ attrDict->insertObject(name, std::move(pdfArray));
+ fAttrs->appendObject(std::move(attrDict));
+}
+
+
+void SkPDF::AttributeList::appendNodeIdArray(
const char* owner,
const char* name,
- const std::vector<SkString>& value) {
+ const std::vector<int>& nodeIds) {
if (!fAttrs)
fAttrs = SkPDFMakeArray();
std::unique_ptr<SkPDFDict> attrDict = SkPDFMakeDict();
attrDict->insertName("O", owner);
std::unique_ptr<SkPDFArray> pdfArray = SkPDFMakeArray();
- for (SkString element : value) {
- pdfArray->appendName(element);
+ for (int nodeId : nodeIds) {
+ SkString idString = SkPDFTagNode::nodeIdToString(nodeId);
+ pdfArray->appendString(idString);
}
attrDict->insertObject(name, std::move(pdfArray));
fAttrs->appendObject(std::move(attrDict));
}
-struct SkPDFTagNode {
- SkPDFTagNode* fChildren = nullptr;
- size_t fChildCount = 0;
- struct MarkedContentInfo {
- unsigned fPageIndex;
- int fMarkId;
- };
- SkTArray<MarkedContentInfo> fMarkedContent;
- int fNodeId;
- SkPDF::DocumentStructureType fType;
- SkString fTypeString;
- SkString fAlt;
- SkString fLang;
- SkPDFIndirectReference fRef;
- enum State {
- kUnknown,
- kYes,
- kNo,
- } fCanDiscard = kUnknown;
- std::unique_ptr<SkPDFArray> fAttributes;
- std::vector<SkPDFIndirectReference> fAnnotations;
-};
-
SkPDFTagTree::SkPDFTagTree() : fArena(4 * sizeof(SkPDFTagNode)) {}
SkPDFTagTree::~SkPDFTagTree() = default;
@@ -173,23 +229,12 @@ void SkPDFTagTree::Copy(SkPDF::StructureElementNode& node,
dst->fAlt = node.fAlt;
dst->fLang = node.fLang;
- // Temporarily support both raw fChildren and fChildVector.
- if (node.fChildren) {
- size_t childCount = node.fChildCount;
- SkPDFTagNode* children = arena->makeArray<SkPDFTagNode>(childCount);
- dst->fChildCount = childCount;
- dst->fChildren = children;
- for (size_t i = 0; i < childCount; ++i) {
- Copy(node.fChildren[i], &children[i], arena, nodeMap);
- }
- } else {
- size_t childCount = node.fChildVector.size();
- SkPDFTagNode* children = arena->makeArray<SkPDFTagNode>(childCount);
- dst->fChildCount = childCount;
- dst->fChildren = children;
- for (size_t i = 0; i < childCount; ++i) {
- Copy(*node.fChildVector[i], &children[i], arena, nodeMap);
- }
+ size_t childCount = node.fChildVector.size();
+ SkPDFTagNode* children = arena->makeArray<SkPDFTagNode>(childCount);
+ dst->fChildCount = childCount;
+ dst->fChildren = children;
+ for (size_t i = 0; i < childCount; ++i) {
+ Copy(*node.fChildVector[i], &children[i], arena, nodeMap);
}
dst->fAttributes = std::move(node.fAttributes.fAttrs);
@@ -209,7 +254,7 @@ void SkPDFTagTree::reset() {
fRoot = nullptr;
}
-int SkPDFTagTree::getMarkIdForNodeId(int nodeId, unsigned pageIndex) {
+int SkPDFTagTree::createMarkIdForNodeId(int nodeId, unsigned pageIndex) {
if (!fRoot) {
return -1;
}
@@ -229,6 +274,25 @@ int SkPDFTagTree::getMarkIdForNodeId(int nodeId, unsigned pageIndex) {
return markId;
}
+int SkPDFTagTree::createStructParentKeyForNodeId(int nodeId, unsigned pageIndex) {
+ if (!fRoot) {
+ return -1;
+ }
+ SkPDFTagNode** tagPtr = fNodeMap.find(nodeId);
+ if (!tagPtr) {
+ return -1;
+ }
+ SkPDFTagNode* tag = *tagPtr;
+ SkASSERT(tag);
+
+ tag->fCanDiscard = SkPDFTagNode::kNo;
+
+ int nextStructParentKey = kFirstAnnotationStructParentKey +
+ static_cast<int>(fParentTreeAnnotationNodeIds.size());
+ fParentTreeAnnotationNodeIds.push_back(nodeId);
+ return nextStructParentKey;
+}
+
static bool can_discard(SkPDFTagNode* node) {
if (node->fCanDiscard == SkPDFTagNode::kYes) {
return true;
@@ -250,10 +314,9 @@ static bool can_discard(SkPDFTagNode* node) {
return true;
}
-
-SkPDFIndirectReference prepare_tag_tree_to_emit(SkPDFIndirectReference parent,
- SkPDFTagNode* node,
- SkPDFDocument* doc) {
+SkPDFIndirectReference SkPDFTagTree::PrepareTagTreeToEmit(SkPDFIndirectReference parent,
+ SkPDFTagNode* node,
+ SkPDFDocument* doc) {
SkPDFIndirectReference ref = doc->reserveRef();
std::unique_ptr<SkPDFArray> kids = SkPDFMakeArray();
SkPDFTagNode* children = node->fChildren;
@@ -261,7 +324,7 @@ SkPDFIndirectReference prepare_tag_tree_to_emit(SkPDFIndirectReference parent,
for (size_t i = 0; i < childCount; ++i) {
SkPDFTagNode* child = &children[i];
if (!(can_discard(child))) {
- kids->appendRef(prepare_tag_tree_to_emit(ref, child, doc));
+ kids->appendRef(PrepareTagTreeToEmit(ref, child, doc));
}
}
for (const SkPDFTagNode::MarkedContentInfo& info : node->fMarkedContent) {
@@ -270,9 +333,10 @@ SkPDFIndirectReference prepare_tag_tree_to_emit(SkPDFIndirectReference parent,
mcr->insertInt("MCID", info.fMarkId);
kids->appendObject(std::move(mcr));
}
- for (SkPDFIndirectReference annotationRef : node->fAnnotations) {
+ for (const SkPDFTagNode::AnnotationInfo& annotationInfo : node->fAnnotations) {
std::unique_ptr<SkPDFDict> annotationDict = SkPDFMakeDict("OBJR");
- annotationDict->insertRef("Obj", annotationRef);
+ annotationDict->insertRef("Obj", annotationInfo.fAnnotationRef);
+ annotationDict->insertRef("Pg", doc->getPage(annotationInfo.fPageIndex));
kids->appendObject(std::move(annotationDict));
}
node->fRef = ref;
@@ -290,17 +354,22 @@ SkPDFIndirectReference prepare_tag_tree_to_emit(SkPDFIndirectReference parent,
}
dict.insertRef("P", parent);
dict.insertObject("K", std::move(kids));
- SkString idString;
- idString.printf("%d", node->fNodeId);
- dict.insertName("ID", idString.c_str());
if (node->fAttributes) {
dict.insertObject("A", std::move(node->fAttributes));
}
+ // Each node has a unique ID that also needs to be referenced
+ // in a separate IDTree node, along with the lowest and highest
+ // unique ID string.
+ SkString idString = SkPDFTagNode::nodeIdToString(node->fNodeId);
+ dict.insertString("ID", idString.c_str());
+ IDTreeEntry idTreeEntry = {node->fNodeId, ref};
+ fIdTreeEntries.push_back(idTreeEntry);
+
return doc->emit(dict, ref);
}
-void SkPDFTagTree::addNodeAnnotation(int nodeId, SkPDFIndirectReference annotationRef) {
+void SkPDFTagTree::addNodeAnnotation(int nodeId, SkPDFIndirectReference annotationRef, unsigned pageIndex) {
if (!fRoot) {
return;
}
@@ -310,9 +379,10 @@ void SkPDFTagTree::addNodeAnnotation(int nodeId, SkPDFIndirectReference annotati
}
SkPDFTagNode* tag = *tagPtr;
SkASSERT(tag);
- tag->fAnnotations.push_back(annotationRef);
-}
+ SkPDFTagNode::AnnotationInfo annotationInfo = {pageIndex, annotationRef};
+ tag->fAnnotations.push_back(annotationInfo);
+}
SkPDFIndirectReference SkPDFTagTree::makeStructTreeRoot(SkPDFDocument* doc) {
if (!fRoot) {
@@ -327,14 +397,18 @@ SkPDFIndirectReference SkPDFTagTree::makeStructTreeRoot(SkPDFDocument* doc) {
// Build the StructTreeRoot.
SkPDFDict structTreeRoot("StructTreeRoot");
- structTreeRoot.insertRef("K", prepare_tag_tree_to_emit(ref, fRoot, doc));
+ structTreeRoot.insertRef("K", PrepareTagTreeToEmit(ref, fRoot, doc));
structTreeRoot.insertInt("ParentTreeNextKey", SkToInt(pageCount));
- // Build the parent tree, which is a mapping from the marked
- // content IDs on each page to their corressponding tags.
+ // Build the parent tree, which consists of two things:
+ // (1) For each page, a mapping from the marked content IDs on
+ // each page to their corresponding tags
+ // (2) For each annotation, an indirect reference to that
+ // annotation's struct tree element.
SkPDFDict parentTree("ParentTree");
auto parentTreeNums = SkPDFMakeArray();
+ // First, one entry per page.
SkASSERT(fMarksPerPage.size() <= pageCount);
for (size_t j = 0; j < fMarksPerPage.size(); ++j) {
const SkTArray<SkPDFTagNode*>& pageMarks = fMarksPerPage[j];
@@ -346,7 +420,54 @@ SkPDFIndirectReference SkPDFTagTree::makeStructTreeRoot(SkPDFDocument* doc) {
parentTreeNums->appendInt(j);
parentTreeNums->appendRef(doc->emit(markToTagArray));
}
+
+ // Then, one entry per annotation.
+ for (size_t j = 0; j < fParentTreeAnnotationNodeIds.size(); ++j) {
+ int nodeId = fParentTreeAnnotationNodeIds[j];
+ int structParentKey = kFirstAnnotationStructParentKey + static_cast<int>(j);
+
+ SkPDFTagNode** tagPtr = fNodeMap.find(nodeId);
+ if (!tagPtr) {
+ continue;
+ }
+ SkPDFTagNode* tag = *tagPtr;
+ parentTreeNums->appendInt(structParentKey);
+ parentTreeNums->appendRef(tag->fRef);
+ }
+
parentTree.insertObject("Nums", std::move(parentTreeNums));
structTreeRoot.insertRef("ParentTree", doc->emit(parentTree));
+
+ // Build the IDTree, a mapping from every unique ID string to
+ // a reference to its corresponding structure element node.
+ if (!fIdTreeEntries.empty()) {
+ std::sort(fIdTreeEntries.begin(), fIdTreeEntries.end(),
+ [](const IDTreeEntry& a, const IDTreeEntry& b) {
+ return a.nodeId < b.nodeId;
+ });
+
+ SkPDFDict idTree;
+ SkPDFDict idTreeLeaf;
+ auto limits = SkPDFMakeArray();
+ SkString lowestNodeIdString = SkPDFTagNode::nodeIdToString(
+ fIdTreeEntries.begin()->nodeId);
+ limits->appendString(lowestNodeIdString);
+ SkString highestNodeIdString = SkPDFTagNode::nodeIdToString(
+ fIdTreeEntries.rbegin()->nodeId);
+ limits->appendString(highestNodeIdString);
+ idTreeLeaf.insertObject("Limits", std::move(limits));
+ auto names = SkPDFMakeArray();
+ for (const IDTreeEntry& entry : fIdTreeEntries) {
+ SkString idString = SkPDFTagNode::nodeIdToString(entry.nodeId);
+ names->appendString(idString);
+ names->appendRef(entry.ref);
+ }
+ idTreeLeaf.insertObject("Names", std::move(names));
+ auto idTreeKids = SkPDFMakeArray();
+ idTreeKids->appendRef(doc->emit(idTreeLeaf));
+ idTree.insertObject("Kids", std::move(idTreeKids));
+ structTreeRoot.insertRef("IDTree", doc->emit(idTree));
+ }
+
return doc->emit(structTreeRoot, ref);
}
diff --git a/chromium/third_party/skia/src/pdf/SkPDFTag.h b/chromium/third_party/skia/src/pdf/SkPDFTag.h
index 00152290da6..63972ffe45a 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFTag.h
+++ b/chromium/third_party/skia/src/pdf/SkPDFTag.h
@@ -23,20 +23,40 @@ public:
~SkPDFTagTree();
void init(SkPDF::StructureElementNode*);
void reset();
- int getMarkIdForNodeId(int nodeId, unsigned pageIndex);
- void addNodeAnnotation(int nodeId, SkPDFIndirectReference annotationRef);
+ // Used to allow marked content to refer to its corresponding structure
+ // tree node, via a page entry in the parent tree. Returns -1 if no
+ // mark ID.
+ int createMarkIdForNodeId(int nodeId, unsigned pageIndex);
+ // Used to allow annotations to refer to their corresponding structure
+ // tree node, via the struct parent tree. Returns -1 if no struct parent
+ // key.
+ int createStructParentKeyForNodeId(int nodeId, unsigned pageIndex);
+
+ void addNodeAnnotation(int nodeId, SkPDFIndirectReference annotationRef, unsigned pageIndex);
SkPDFIndirectReference makeStructTreeRoot(SkPDFDocument* doc);
private:
+ // An entry in a map from a node ID to an indirect reference to its
+ // corresponding structure element node.
+ struct IDTreeEntry {
+ int nodeId;
+ SkPDFIndirectReference ref;
+ };
+
static void Copy(SkPDF::StructureElementNode& node,
SkPDFTagNode* dst,
SkArenaAlloc* arena,
SkTHashMap<int, SkPDFTagNode*>* nodeMap);
+ SkPDFIndirectReference PrepareTagTreeToEmit(SkPDFIndirectReference parent,
+ SkPDFTagNode* node,
+ SkPDFDocument* doc);
SkArenaAlloc fArena;
SkTHashMap<int, SkPDFTagNode*> fNodeMap;
SkPDFTagNode* fRoot = nullptr;
SkTArray<SkTArray<SkPDFTagNode*>> fMarksPerPage;
+ std::vector<IDTreeEntry> fIdTreeEntries;
+ std::vector<int> fParentTreeAnnotationNodeIds;
SkPDFTagTree(const SkPDFTagTree&) = delete;
SkPDFTagTree& operator=(const SkPDFTagTree&) = delete;
diff --git a/chromium/third_party/skia/src/ports/SkFontHost_FreeType.cpp b/chromium/third_party/skia/src/ports/SkFontHost_FreeType.cpp
index 35b87bb10f0..5a6f6d7c5f6 100644
--- a/chromium/third_party/skia/src/ports/SkFontHost_FreeType.cpp
+++ b/chromium/third_party/skia/src/ports/SkFontHost_FreeType.cpp
@@ -1817,7 +1817,7 @@ SkTypeface_FreeType::Scanner::~Scanner() {
FT_Face SkTypeface_FreeType::Scanner::openFace(SkStreamAsset* stream, int ttcIndex,
FT_Stream ftStream) const
{
- if (fLibrary == nullptr) {
+ if (fLibrary == nullptr || stream == nullptr) {
return nullptr;
}
diff --git a/chromium/third_party/skia/src/ports/SkFontHost_mac.cpp b/chromium/third_party/skia/src/ports/SkFontHost_mac.cpp
deleted file mode 100644
index 9e29b5cee6c..00000000000
--- a/chromium/third_party/skia/src/ports/SkFontHost_mac.cpp
+++ /dev/null
@@ -1,3226 +0,0 @@
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "include/core/SkTypes.h"
-#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
-
-#ifdef SK_BUILD_FOR_MAC
-#import <ApplicationServices/ApplicationServices.h>
-#endif
-
-#ifdef SK_BUILD_FOR_IOS
-#include <CoreText/CoreText.h>
-#include <CoreText/CTFontManager.h>
-#include <CoreGraphics/CoreGraphics.h>
-#include <CoreFoundation/CoreFoundation.h>
-#endif
-
-#include "include/core/SkFontMetrics.h"
-#include "include/core/SkFontMgr.h"
-#include "include/core/SkPaint.h"
-#include "include/core/SkPath.h"
-#include "include/core/SkStream.h"
-#include "include/core/SkString.h"
-#include "include/ports/SkTypeface_mac.h"
-#include "include/private/SkColorData.h"
-#include "include/private/SkFloatingPoint.h"
-#include "include/private/SkMutex.h"
-#include "include/private/SkOnce.h"
-#include "include/private/SkTemplates.h"
-#include "include/private/SkTo.h"
-#include "include/utils/mac/SkCGUtils.h"
-#include "src/core/SkAdvancedTypefaceMetrics.h"
-#include "src/core/SkAutoMalloc.h"
-#include "src/core/SkDescriptor.h"
-#include "src/core/SkEndian.h"
-#include "src/core/SkFontDescriptor.h"
-#include "src/core/SkGlyph.h"
-#include "src/core/SkMaskGamma.h"
-#include "src/core/SkMathPriv.h"
-#include "src/core/SkTypefaceCache.h"
-#include "src/core/SkUtils.h"
-#include "src/sfnt/SkOTTable_OS_2.h"
-#include "src/sfnt/SkOTUtils.h"
-#include "src/sfnt/SkSFNTHeader.h"
-#include "src/utils/SkUTF.h"
-#include "src/utils/mac/SkUniqueCFRef.h"
-
-#include <dlfcn.h>
-
-#include <utility>
-
-// Set to make glyph bounding boxes visible.
-#define SK_SHOW_TEXT_BLIT_COVERAGE 0
-
-CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face) {
- return face ? (CTFontRef)face->internal_private_getCTFontRef() : nullptr;
-}
-
-class SkScalerContext_Mac;
-
-static SkUniqueCFRef<CFStringRef> make_CFString(const char s[]) {
- return SkUniqueCFRef<CFStringRef>(CFStringCreateWithCString(nullptr, s, kCFStringEncodingUTF8));
-}
-
-// inline versions of these rect helpers
-
-static bool CGRectIsEmpty_inline(const CGRect& rect) {
- return rect.size.width <= 0 || rect.size.height <= 0;
-}
-
-static CGFloat CGRectGetMinX_inline(const CGRect& rect) {
- return rect.origin.x;
-}
-
-static CGFloat CGRectGetMaxX_inline(const CGRect& rect) {
- return rect.origin.x + rect.size.width;
-}
-
-static CGFloat CGRectGetMinY_inline(const CGRect& rect) {
- return rect.origin.y;
-}
-
-static CGFloat CGRectGetMaxY_inline(const CGRect& rect) {
- return rect.origin.y + rect.size.height;
-}
-
-static CGFloat CGRectGetWidth_inline(const CGRect& rect) {
- return rect.size.width;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static void sk_memset_rect32(uint32_t* ptr, uint32_t value,
- int width, int height, size_t rowBytes) {
- SkASSERT(width);
- SkASSERT(width * sizeof(uint32_t) <= rowBytes);
-
- if (width >= 32) {
- while (height) {
- sk_memset32(ptr, value, width);
- ptr = (uint32_t*)((char*)ptr + rowBytes);
- height -= 1;
- }
- return;
- }
-
- rowBytes -= width * sizeof(uint32_t);
-
- if (width >= 8) {
- while (height) {
- int w = width;
- do {
- *ptr++ = value; *ptr++ = value;
- *ptr++ = value; *ptr++ = value;
- *ptr++ = value; *ptr++ = value;
- *ptr++ = value; *ptr++ = value;
- w -= 8;
- } while (w >= 8);
- while (--w >= 0) {
- *ptr++ = value;
- }
- ptr = (uint32_t*)((char*)ptr + rowBytes);
- height -= 1;
- }
- } else {
- while (height) {
- int w = width;
- do {
- *ptr++ = value;
- } while (--w > 0);
- ptr = (uint32_t*)((char*)ptr + rowBytes);
- height -= 1;
- }
- }
-}
-
-typedef uint32_t CGRGBPixel;
-
-static unsigned CGRGBPixel_getAlpha(CGRGBPixel pixel) {
- return pixel & 0xFF;
-}
-
-static CGFloat ScalarToCG(SkScalar scalar) {
- if (sizeof(CGFloat) == sizeof(float)) {
- return SkScalarToFloat(scalar);
- } else {
- SkASSERT(sizeof(CGFloat) == sizeof(double));
- return (CGFloat) SkScalarToDouble(scalar);
- }
-}
-
-static SkScalar CGToScalar(CGFloat cgFloat) {
- if (sizeof(CGFloat) == sizeof(float)) {
- return SkFloatToScalar(cgFloat);
- } else {
- SkASSERT(sizeof(CGFloat) == sizeof(double));
- return SkDoubleToScalar(cgFloat);
- }
-}
-
-static float CGToFloat(CGFloat cgFloat) {
- if (sizeof(CGFloat) == sizeof(float)) {
- return cgFloat;
- } else {
- SkASSERT(sizeof(CGFloat) == sizeof(double));
- return static_cast<float>(cgFloat);
- }
-}
-
-static CGAffineTransform MatrixToCGAffineTransform(const SkMatrix& matrix) {
- return CGAffineTransformMake( ScalarToCG(matrix[SkMatrix::kMScaleX]),
- -ScalarToCG(matrix[SkMatrix::kMSkewY] ),
- -ScalarToCG(matrix[SkMatrix::kMSkewX] ),
- ScalarToCG(matrix[SkMatrix::kMScaleY]),
- ScalarToCG(matrix[SkMatrix::kMTransX]),
- ScalarToCG(matrix[SkMatrix::kMTransY]));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-#define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host)
-
-/** Drawn in FontForge, reduced with fonttools ttx, converted by xxd -i,
- * this TrueType font contains a glyph of the spider.
- *
- * To re-forge the original bytes of the TrueType font file,
- * remove all ',|( +0x)' from this definition,
- * copy the data to the clipboard,
- * run 'pbpaste | xxd -p -r - spider.ttf'.
- */
-static constexpr const uint8_t kSpiderSymbol_ttf[] = {
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x80, 0x00, 0x03, 0x00, 0x40,
- 0x47, 0x44, 0x45, 0x46, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x07, 0xa8,
- 0x00, 0x00, 0x00, 0x18, 0x4f, 0x53, 0x2f, 0x32, 0x8a, 0xf4, 0xfb, 0xdb,
- 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x00, 0x60, 0x63, 0x6d, 0x61, 0x70,
- 0xe0, 0x7f, 0x10, 0x7e, 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x54,
- 0x67, 0x61, 0x73, 0x70, 0xff, 0xff, 0x00, 0x03, 0x00, 0x00, 0x07, 0xa0,
- 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0x97, 0x0b, 0x6a, 0xf6,
- 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x03, 0x40, 0x68, 0x65, 0x61, 0x64,
- 0x0f, 0xa2, 0x24, 0x1a, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x36,
- 0x68, 0x68, 0x65, 0x61, 0x0e, 0xd3, 0x07, 0x3f, 0x00, 0x00, 0x01, 0x04,
- 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78, 0x10, 0x03, 0x00, 0x44,
- 0x00, 0x00, 0x01, 0xa8, 0x00, 0x00, 0x00, 0x0e, 0x6c, 0x6f, 0x63, 0x61,
- 0x01, 0xb4, 0x00, 0x28, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x0a,
- 0x6d, 0x61, 0x78, 0x70, 0x00, 0x4a, 0x01, 0x4d, 0x00, 0x00, 0x01, 0x28,
- 0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0xc3, 0xe5, 0x39, 0xd4,
- 0x00, 0x00, 0x05, 0x58, 0x00, 0x00, 0x02, 0x28, 0x70, 0x6f, 0x73, 0x74,
- 0xff, 0x03, 0x00, 0x67, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x20,
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x0f, 0x08, 0x1d,
- 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xd1, 0x97, 0xa8, 0x5a, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xe8, 0x32, 0x33,
- 0x00, 0x03, 0xff, 0x3b, 0x08, 0x00, 0x05, 0x55, 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
- 0x05, 0x55, 0xff, 0x3b, 0x01, 0x79, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00,
- 0x00, 0x04, 0x01, 0x1c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x2e,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x01, 0x90, 0x00, 0x05,
- 0x00, 0x00, 0x05, 0x33, 0x05, 0x99, 0x00, 0x00, 0x01, 0x1e, 0x05, 0x33,
- 0x05, 0x99, 0x00, 0x00, 0x03, 0xd7, 0x00, 0x66, 0x02, 0x12, 0x00, 0x00,
- 0x05, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x73, 0x6b, 0x69, 0x61, 0x00, 0xc0, 0x00, 0x00, 0xf0, 0x21,
- 0x06, 0x66, 0xfe, 0x66, 0x01, 0x79, 0x05, 0x55, 0x00, 0xc5, 0x80, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x20, 0x00, 0x01, 0x08, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x48,
- 0x00, 0x00, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00,
- 0x00, 0x09, 0x00, 0x0d, 0x00, 0x1d, 0x00, 0x21, 0xf0, 0x21, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00, 0x1d, 0x00, 0x21,
- 0xf0, 0x21, 0xff, 0xff, 0x00, 0x01, 0xff, 0xf9, 0xff, 0xf5, 0xff, 0xe4,
- 0xff, 0xe2, 0x0f, 0xe2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
- 0x00, 0x14, 0x00, 0x14, 0x01, 0xa0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x44,
- 0x00, 0x00, 0x02, 0x64, 0x05, 0x55, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00,
- 0x33, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x44, 0x02, 0x20, 0xfe,
- 0x24, 0x01, 0x98, 0xfe, 0x68, 0x05, 0x55, 0xfa, 0xab, 0x44, 0x04, 0xcd,
- 0x00, 0x04, 0x00, 0x03, 0xff, 0x3b, 0x08, 0x00, 0x05, 0x4c, 0x00, 0x15,
- 0x00, 0x1d, 0x00, 0x25, 0x01, 0x1b, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36,
- 0x27, 0x26, 0x07, 0x06, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07,
- 0x06, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x32, 0x35, 0x34, 0x23, 0x22,
- 0x15, 0x14, 0x27, 0x32, 0x35, 0x34, 0x23, 0x22, 0x15, 0x14, 0x03, 0x32,
- 0x17, 0x30, 0x17, 0x31, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33,
- 0x32, 0x33, 0x16, 0x33, 0x32, 0x17, 0x16, 0x07, 0x06, 0x23, 0x22, 0x27,
- 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
- 0x1f, 0x02, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x17, 0x16, 0x33,
- 0x16, 0x17, 0x16, 0x07, 0x06, 0x23, 0x22, 0x27, 0x27, 0x26, 0x23, 0x22,
- 0x07, 0x06, 0x07, 0x06, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x33, 0x32,
- 0x37, 0x36, 0x37, 0x36, 0x17, 0x16, 0x1f, 0x02, 0x16, 0x17, 0x16, 0x15,
- 0x14, 0x23, 0x22, 0x27, 0x27, 0x26, 0x27, 0x27, 0x26, 0x27, 0x26, 0x07,
- 0x06, 0x07, 0x06, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07,
- 0x06, 0x23, 0x22, 0x27, 0x26, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17,
- 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27,
- 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x34, 0x27, 0x26, 0x07,
- 0x06, 0x07, 0x06, 0x0f, 0x02, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34,
- 0x37, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x27, 0x26, 0x27,
- 0x26, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x07, 0x06, 0x23, 0x22,
- 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x37, 0x36, 0x37, 0x37, 0x36,
- 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26,
- 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x27, 0x26, 0x27, 0x26,
- 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32,
- 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36,
- 0x33, 0x04, 0xf5, 0x23, 0x13, 0x11, 0x14, 0x16, 0x1d, 0x1b, 0x4c, 0x1f,
- 0x0e, 0x2d, 0x23, 0x14, 0x2c, 0x13, 0x18, 0x25, 0x2c, 0x10, 0x3c, 0x71,
- 0x1d, 0x5c, 0x5c, 0x3f, 0xae, 0x5c, 0x5c, 0x3f, 0x6a, 0x27, 0x31, 0x5b,
- 0x09, 0x27, 0x36, 0x03, 0x0a, 0x26, 0x35, 0x2e, 0x09, 0x08, 0xc6, 0x13,
- 0x81, 0x17, 0x20, 0x18, 0x21, 0x1e, 0x04, 0x04, 0x15, 0x5c, 0x22, 0x26,
- 0x48, 0x56, 0x3b, 0x10, 0x21, 0x01, 0x0c, 0x06, 0x06, 0x0f, 0x31, 0x44,
- 0x3c, 0x52, 0x4a, 0x1d, 0x11, 0x3f, 0xb4, 0x71, 0x01, 0x26, 0x06, 0x0d,
- 0x15, 0x1a, 0x2a, 0x13, 0x53, 0xaa, 0x42, 0x1d, 0x0a, 0x33, 0x20, 0x21,
- 0x2b, 0x01, 0x02, 0x3e, 0x21, 0x09, 0x02, 0x02, 0x0f, 0x2d, 0x4b, 0x0a,
- 0x22, 0x15, 0x20, 0x1f, 0x72, 0x8b, 0x2d, 0x2f, 0x1d, 0x1f, 0x0e, 0x25,
- 0x3f, 0x4d, 0x1b, 0x63, 0x2a, 0x2c, 0x14, 0x22, 0x18, 0x1c, 0x0f, 0x08,
- 0x2a, 0x08, 0x08, 0x0d, 0x3b, 0x4c, 0x52, 0x74, 0x27, 0x71, 0x2e, 0x01,
- 0x0c, 0x10, 0x15, 0x0d, 0x06, 0x0d, 0x05, 0x01, 0x06, 0x2c, 0x28, 0x14,
- 0x1b, 0x05, 0x04, 0x10, 0x06, 0x12, 0x08, 0x0a, 0x16, 0x27, 0x03, 0x0d,
- 0x30, 0x4c, 0x4c, 0x4b, 0x1f, 0x0b, 0x22, 0x26, 0x0d, 0x15, 0x0d, 0x2d,
- 0x68, 0x34, 0x14, 0x3c, 0x25, 0x12, 0x04, 0x10, 0x18, 0x0b, 0x09, 0x30,
- 0x2b, 0x44, 0x66, 0x14, 0x47, 0x47, 0x59, 0x73, 0x25, 0x05, 0x03, 0x1f,
- 0x01, 0x08, 0x3f, 0x48, 0x4b, 0x4b, 0x76, 0x2f, 0x49, 0x2d, 0x22, 0x24,
- 0x0c, 0x15, 0x08, 0x0e, 0x33, 0x03, 0x44, 0x4c, 0x10, 0x46, 0x13, 0x1f,
- 0x27, 0x1b, 0x1d, 0x13, 0x02, 0x24, 0x08, 0x02, 0x42, 0x0e, 0x4d, 0x3c,
- 0x19, 0x1b, 0x40, 0x2b, 0x2b, 0x1e, 0x16, 0x11, 0x04, 0x1f, 0x11, 0x04,
- 0x18, 0x11, 0x35, 0x01, 0xa3, 0x13, 0x24, 0x1f, 0x0b, 0x0c, 0x19, 0x19,
- 0x18, 0x13, 0x0f, 0x0c, 0x1a, 0x18, 0x1f, 0x19, 0x1e, 0x07, 0x1a, 0xc3,
- 0x54, 0x51, 0x54, 0x51, 0x04, 0x53, 0x51, 0x54, 0x50, 0x02, 0x48, 0x1a,
- 0x31, 0x18, 0x55, 0x74, 0x04, 0x0e, 0x09, 0x0d, 0x06, 0x10, 0x16, 0x1b,
- 0x24, 0x01, 0x04, 0x0b, 0x04, 0x10, 0x3f, 0x0a, 0x41, 0x02, 0x41, 0x20,
- 0x06, 0x12, 0x16, 0x21, 0x17, 0x2a, 0x1e, 0x15, 0x40, 0x27, 0x11, 0x0e,
- 0x1e, 0x11, 0x15, 0x1f, 0x43, 0x13, 0x1a, 0x10, 0x15, 0x1b, 0x04, 0x09,
- 0x4d, 0x2a, 0x0f, 0x19, 0x0a, 0x0a, 0x03, 0x05, 0x15, 0x3c, 0x64, 0x21,
- 0x4b, 0x2e, 0x21, 0x28, 0x13, 0x47, 0x44, 0x19, 0x3f, 0x11, 0x18, 0x0b,
- 0x0a, 0x07, 0x18, 0x0d, 0x07, 0x24, 0x2c, 0x2b, 0x21, 0x32, 0x10, 0x48,
- 0x2a, 0x2d, 0x1e, 0x1a, 0x01, 0x0c, 0x43, 0x59, 0x28, 0x4e, 0x1c, 0x0d,
- 0x5d, 0x24, 0x14, 0x0a, 0x05, 0x1f, 0x24, 0x32, 0x46, 0x3e, 0x5f, 0x3e,
- 0x44, 0x1a, 0x30, 0x15, 0x0d, 0x07, 0x18, 0x2b, 0x03, 0x0d, 0x1a, 0x28,
- 0x28, 0x57, 0xb2, 0x29, 0x27, 0x40, 0x2c, 0x23, 0x16, 0x63, 0x58, 0x1a,
- 0x0a, 0x18, 0x11, 0x23, 0x08, 0x1b, 0x29, 0x05, 0x04, 0x0b, 0x15, 0x0d,
- 0x14, 0x0b, 0x2a, 0x29, 0x5a, 0x62, 0x01, 0x19, 0x1e, 0x05, 0x05, 0x26,
- 0x42, 0x42, 0x2a, 0x2a, 0x3f, 0x0d, 0x0f, 0x09, 0x05, 0x07, 0x01, 0x0b,
- 0x25, 0x3e, 0x0d, 0x17, 0x11, 0x01, 0x03, 0x0d, 0x13, 0x20, 0x19, 0x11,
- 0x03, 0x02, 0x01, 0x04, 0x11, 0x04, 0x05, 0x1b, 0x3d, 0x10, 0x29, 0x20,
- 0x04, 0x04, 0x0a, 0x07, 0x04, 0x1f, 0x15, 0x20, 0x3e, 0x0f, 0x2a, 0x1e,
- 0x00, 0x00, 0x00, 0x1b, 0x01, 0x4a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x00, 0x07, 0x00, 0x27, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x04, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x05, 0x00, 0x02, 0x00, 0x2e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x06, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0e, 0x00, 0x1a, 0x00, 0x30, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
- 0x00, 0x00, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
- 0x00, 0x01, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
- 0x00, 0x02, 0x00, 0x0e, 0x00, 0x98, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
- 0x00, 0x03, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
- 0x00, 0x04, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
- 0x00, 0x05, 0x00, 0x04, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
- 0x00, 0x06, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
- 0x00, 0x0d, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
- 0x00, 0x0e, 0x00, 0x34, 0x00, 0xaa, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
- 0x00, 0x00, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
- 0x00, 0x01, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
- 0x00, 0x02, 0x00, 0x0e, 0x00, 0x98, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
- 0x00, 0x03, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
- 0x00, 0x04, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
- 0x00, 0x05, 0x00, 0x04, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
- 0x00, 0x06, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
- 0x00, 0x0d, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
- 0x00, 0x0e, 0x00, 0x34, 0x00, 0xaa, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69,
- 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x31, 0x35,
- 0x2c, 0x20, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x53, 0x70, 0x69,
- 0x64, 0x65, 0x72, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x52, 0x65, 0x67,
- 0x75, 0x6c, 0x61, 0x72, 0x56, 0x31, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
- 0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x2e, 0x73, 0x69, 0x6c,
- 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x4f, 0x46, 0x4c, 0x00, 0x43, 0x00, 0x6f,
- 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68,
- 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x63, 0x00, 0x29, 0x00, 0x20,
- 0x00, 0x32, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x2c, 0x00, 0x20,
- 0x00, 0x47, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x6c, 0x00, 0x65,
- 0x00, 0x2e, 0x00, 0x53, 0x00, 0x70, 0x00, 0x69, 0x00, 0x64, 0x00, 0x65,
- 0x00, 0x72, 0x00, 0x53, 0x00, 0x79, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x6f,
- 0x00, 0x6c, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c,
- 0x00, 0x61, 0x00, 0x72, 0x00, 0x56, 0x00, 0x31, 0x00, 0x68, 0x00, 0x74,
- 0x00, 0x74, 0x00, 0x70, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x73,
- 0x00, 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x73,
- 0x00, 0x2e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x2e, 0x00, 0x6f,
- 0x00, 0x72, 0x00, 0x67, 0x00, 0x2f, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x4c,
- 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x66,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0xff, 0xff, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
- 0x00, 0x02, 0x00, 0x00
-};
-
-enum class SmoothBehavior {
- none, // SmoothFonts produces no effect.
- some, // SmoothFonts produces some effect, but not subpixel coverage.
- subpixel, // SmoothFonts produces some effect and provides subpixel coverage.
-};
-
-/**
- * There does not appear to be a publicly accessable API for determining if lcd
- * font smoothing will be applied if we request it. The main issue is that if
- * smoothing is applied a gamma of 2.0 will be used, if not a gamma of 1.0.
- */
-static SmoothBehavior smooth_behavior() {
- static SmoothBehavior gSmoothBehavior = []{
- uint32_t noSmoothBitmap[16][16] = {};
- uint32_t smoothBitmap[16][16] = {};
-
- SkUniqueCFRef<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB());
- SkUniqueCFRef<CGContextRef> noSmoothContext(
- CGBitmapContextCreate(&noSmoothBitmap, 16, 16, 8, 16*4,
- colorspace.get(), BITMAP_INFO_RGB));
- SkUniqueCFRef<CGContextRef> smoothContext(
- CGBitmapContextCreate(&smoothBitmap, 16, 16, 8, 16*4,
- colorspace.get(), BITMAP_INFO_RGB));
-
- SkUniqueCFRef<CFDataRef> data(CFDataCreateWithBytesNoCopy(
- kCFAllocatorDefault, kSpiderSymbol_ttf, SK_ARRAY_COUNT(kSpiderSymbol_ttf),
- kCFAllocatorNull));
- SkUniqueCFRef<CTFontDescriptorRef> desc(
- CTFontManagerCreateFontDescriptorFromData(data.get()));
- SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc.get(), 16, nullptr));
- SkASSERT(ctFont);
-
- CGContextSetShouldSmoothFonts(noSmoothContext.get(), false);
- CGContextSetShouldAntialias(noSmoothContext.get(), true);
- CGContextSetTextDrawingMode(noSmoothContext.get(), kCGTextFill);
- CGContextSetGrayFillColor(noSmoothContext.get(), 1, 1);
-
- CGContextSetShouldSmoothFonts(smoothContext.get(), true);
- CGContextSetShouldAntialias(smoothContext.get(), true);
- CGContextSetTextDrawingMode(smoothContext.get(), kCGTextFill);
- CGContextSetGrayFillColor(smoothContext.get(), 1, 1);
-
- CGPoint point = CGPointMake(0, 3);
- CGGlyph spiderGlyph = 3;
- CTFontDrawGlyphs(ctFont.get(), &spiderGlyph, &point, 1, noSmoothContext.get());
- CTFontDrawGlyphs(ctFont.get(), &spiderGlyph, &point, 1, smoothContext.get());
-
- // For debugging.
- //SkUniqueCFRef<CGImageRef> image(CGBitmapContextCreateImage(noSmoothContext()));
- //SkUniqueCFRef<CGImageRef> image(CGBitmapContextCreateImage(smoothContext()));
-
- SmoothBehavior smoothBehavior = SmoothBehavior::none;
- for (int x = 0; x < 16; ++x) {
- for (int y = 0; y < 16; ++y) {
- uint32_t smoothPixel = smoothBitmap[x][y];
- uint32_t r = (smoothPixel >> 16) & 0xFF;
- uint32_t g = (smoothPixel >> 8) & 0xFF;
- uint32_t b = (smoothPixel >> 0) & 0xFF;
- if (r != g || r != b) {
- return SmoothBehavior::subpixel;
- }
- if (noSmoothBitmap[x][y] != smoothPixel) {
- smoothBehavior = SmoothBehavior::some;
- }
- }
- }
- return smoothBehavior;
- }();
- return gSmoothBehavior;
-}
-
-class Offscreen {
-public:
- Offscreen()
- : fRGBSpace(nullptr)
- , fCG(nullptr)
- , fDoAA(false)
- , fDoLCD(false)
- {
- fSize.set(0, 0);
- }
-
- CGRGBPixel* getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph,
- CGGlyph glyphID, size_t* rowBytesPtr, bool generateA8FromLCD);
-
-private:
- enum {
- kSize = 32 * 32 * sizeof(CGRGBPixel)
- };
- SkAutoSMalloc<kSize> fImageStorage;
- SkUniqueCFRef<CGColorSpaceRef> fRGBSpace;
-
- // cached state
- SkUniqueCFRef<CGContextRef> fCG;
- SkISize fSize;
- bool fDoAA;
- bool fDoLCD;
-
- static int RoundSize(int dimension) {
- return SkNextPow2(dimension);
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-static bool find_dict_CGFloat(CFDictionaryRef dict, CFStringRef name, CGFloat* value) {
- CFNumberRef num;
- return CFDictionaryGetValueIfPresent(dict, name, (const void**)&num)
- && CFNumberIsFloatType(num)
- && CFNumberGetValue(num, kCFNumberCGFloatType, value);
-}
-
-template <typename S, typename D, typename C> struct LinearInterpolater {
- struct Mapping {
- S src_val;
- D dst_val;
- };
- constexpr LinearInterpolater(Mapping const mapping[], int mappingCount)
- : fMapping(mapping), fMappingCount(mappingCount) {}
-
- static D map(S value, S src_min, S src_max, D dst_min, D dst_max) {
- SkASSERT(src_min < src_max);
- SkASSERT(dst_min <= dst_max);
- return C()(dst_min + (((value - src_min) * (dst_max - dst_min)) / (src_max - src_min)));
- }
-
- D map(S val) const {
- // -Inf to [0]
- if (val < fMapping[0].src_val) {
- return fMapping[0].dst_val;
- }
-
- // Linear from [i] to [i+1]
- for (int i = 0; i < fMappingCount - 1; ++i) {
- if (val < fMapping[i+1].src_val) {
- return map(val, fMapping[i].src_val, fMapping[i+1].src_val,
- fMapping[i].dst_val, fMapping[i+1].dst_val);
- }
- }
-
- // From [n] to +Inf
- // if (fcweight < Inf)
- return fMapping[fMappingCount - 1].dst_val;
- }
-
- Mapping const * fMapping;
- int fMappingCount;
-};
-
-struct RoundCGFloatToInt {
- int operator()(CGFloat s) { return s + 0.5; }
-};
-struct CGFloatIdentity {
- CGFloat operator()(CGFloat s) { return s; }
-};
-
-/** Returns the [-1, 1] CTFontDescriptor weights for the
- * <0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000> CSS weights.
- *
- * It is assumed that the values will be interpolated linearly between these points.
- * NSFontWeightXXX were added in 10.11, appear in 10.10, but do not appear in 10.9.
- * The actual values appear to be stable, but they may change in the future without notice.
- */
-static CGFloat(&get_NSFontWeight_mapping())[11] {
-
- // Declarations in <AppKit/AppKit.h> on macOS, <UIKit/UIKit.h> on iOS
-#ifdef SK_BUILD_FOR_MAC
-# define SK_KIT_FONT_WEIGHT_PREFIX "NS"
-#endif
-#ifdef SK_BUILD_FOR_IOS
-# define SK_KIT_FONT_WEIGHT_PREFIX "UI"
-#endif
- static constexpr struct {
- CGFloat defaultValue;
- const char* name;
- } nsFontWeightLoaderInfos[] = {
- { -0.80f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightUltraLight" },
- { -0.60f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightThin" },
- { -0.40f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightLight" },
- { 0.00f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightRegular" },
- { 0.23f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightMedium" },
- { 0.30f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightSemibold" },
- { 0.40f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightBold" },
- { 0.56f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightHeavy" },
- { 0.62f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightBlack" },
- };
-
- static_assert(SK_ARRAY_COUNT(nsFontWeightLoaderInfos) == 9, "");
- static CGFloat nsFontWeights[11];
- static SkOnce once;
- once([&] {
- size_t i = 0;
- nsFontWeights[i++] = -1.00;
- for (const auto& nsFontWeightLoaderInfo : nsFontWeightLoaderInfos) {
- void* nsFontWeightValuePtr = dlsym(RTLD_DEFAULT, nsFontWeightLoaderInfo.name);
- if (nsFontWeightValuePtr) {
- nsFontWeights[i++] = *(static_cast<CGFloat*>(nsFontWeightValuePtr));
- } else {
- nsFontWeights[i++] = nsFontWeightLoaderInfo.defaultValue;
- }
- }
- nsFontWeights[i++] = 1.00;
- });
- return nsFontWeights;
-}
-
-/** Convert the [0, 1000] CSS weight to [-1, 1] CTFontDescriptor weight (for system fonts).
- *
- * The -1 to 1 weights reported by CTFontDescriptors have different mappings depending on if the
- * CTFont is native or created from a CGDataProvider.
- */
-static CGFloat fontstyle_to_ct_weight(int fontstyleWeight) {
- using Interpolator = LinearInterpolater<int, CGFloat, CGFloatIdentity>;
-
- // Note that Mac supports the old OS2 version A so 0 through 10 are as if multiplied by 100.
- // However, on this end we can't tell, so this is ignored.
-
- static Interpolator::Mapping nativeWeightMappings[11];
- static SkOnce once;
- once([&] {
- CGFloat(&nsFontWeights)[11] = get_NSFontWeight_mapping();
- for (int i = 0; i < 11; ++i) {
- nativeWeightMappings[i].src_val = i * 100;
- nativeWeightMappings[i].dst_val = nsFontWeights[i];
- }
- });
- static constexpr Interpolator nativeInterpolator(
- nativeWeightMappings, SK_ARRAY_COUNT(nativeWeightMappings));
-
- return nativeInterpolator.map(fontstyleWeight);
-}
-
-
-/** Convert the [-1, 1] CTFontDescriptor weight to [0, 1000] CSS weight.
- *
- * The -1 to 1 weights reported by CTFontDescriptors have different mappings depending on if the
- * CTFont is native or created from a CGDataProvider.
- */
-static int ct_weight_to_fontstyle(CGFloat cgWeight, bool fromDataProvider) {
- using Interpolator = LinearInterpolater<CGFloat, int, RoundCGFloatToInt>;
-
- // Note that Mac supports the old OS2 version A so 0 through 10 are as if multiplied by 100.
- // However, on this end we can't tell, so this is ignored.
-
- /** This mapping for CGDataProvider created fonts is determined by creating font data with every
- * weight, creating a CTFont, and asking the CTFont for its weight. See the TypefaceStyle test
- * in tests/TypefaceTest.cpp for the code used to determine these values.
- */
- static constexpr Interpolator::Mapping dataProviderWeightMappings[] = {
- { -1.00, 0 },
- { -0.70, 100 },
- { -0.50, 200 },
- { -0.23, 300 },
- { 0.00, 400 },
- { 0.20, 500 },
- { 0.30, 600 },
- { 0.40, 700 },
- { 0.60, 800 },
- { 0.80, 900 },
- { 1.00, 1000 },
- };
- static constexpr Interpolator dataProviderInterpolator(
- dataProviderWeightMappings, SK_ARRAY_COUNT(dataProviderWeightMappings));
-
- static Interpolator::Mapping nativeWeightMappings[11];
- static SkOnce once;
- once([&] {
- CGFloat(&nsFontWeights)[11] = get_NSFontWeight_mapping();
- for (int i = 0; i < 11; ++i) {
- nativeWeightMappings[i].src_val = nsFontWeights[i];
- nativeWeightMappings[i].dst_val = i * 100;
- }
- });
- static constexpr Interpolator nativeInterpolator(
- nativeWeightMappings, SK_ARRAY_COUNT(nativeWeightMappings));
-
- return fromDataProvider ? dataProviderInterpolator.map(cgWeight)
- : nativeInterpolator.map(cgWeight);
-}
-
-/** Convert the [0, 10] CSS weight to [-1, 1] CTFontDescriptor width. */
-static int fontstyle_to_ct_width(int fontstyleWidth) {
- using Interpolator = LinearInterpolater<int, CGFloat, CGFloatIdentity>;
-
- // Values determined by creating font data with every width, creating a CTFont,
- // and asking the CTFont for its width. See TypefaceStyle test for basics.
- static constexpr Interpolator::Mapping widthMappings[] = {
- { 0, -0.5 },
- { 10, 0.5 },
- };
- static constexpr Interpolator interpolator(widthMappings, SK_ARRAY_COUNT(widthMappings));
- return interpolator.map(fontstyleWidth);
-}
-
-/** Convert the [-1, 1] CTFontDescriptor width to [0, 10] CSS weight. */
-static int ct_width_to_fontstyle(CGFloat cgWidth) {
- using Interpolator = LinearInterpolater<CGFloat, int, RoundCGFloatToInt>;
-
- // Values determined by creating font data with every width, creating a CTFont,
- // and asking the CTFont for its width. See TypefaceStyle test for basics.
- static constexpr Interpolator::Mapping widthMappings[] = {
- { -0.5, 0 },
- { 0.5, 10 },
- };
- static constexpr Interpolator interpolator(widthMappings, SK_ARRAY_COUNT(widthMappings));
- return interpolator.map(cgWidth);
-}
-
-static SkFontStyle fontstyle_from_descriptor(CTFontDescriptorRef desc, bool fromDataProvider) {
- SkUniqueCFRef<CFTypeRef> traits(CTFontDescriptorCopyAttribute(desc, kCTFontTraitsAttribute));
- if (!traits || CFDictionaryGetTypeID() != CFGetTypeID(traits.get())) {
- return SkFontStyle();
- }
- SkUniqueCFRef<CFDictionaryRef> fontTraitsDict(static_cast<CFDictionaryRef>(traits.release()));
-
- CGFloat weight, width, slant;
- if (!find_dict_CGFloat(fontTraitsDict.get(), kCTFontWeightTrait, &weight)) {
- weight = 0;
- }
- if (!find_dict_CGFloat(fontTraitsDict.get(), kCTFontWidthTrait, &width)) {
- width = 0;
- }
- if (!find_dict_CGFloat(fontTraitsDict.get(), kCTFontSlantTrait, &slant)) {
- slant = 0;
- }
-
- return SkFontStyle(ct_weight_to_fontstyle(weight, fromDataProvider),
- ct_width_to_fontstyle(width),
- slant ? SkFontStyle::kItalic_Slant
- : SkFontStyle::kUpright_Slant);
-}
-
-struct OpszVariation {
- bool isSet = false;
- double value = 0;
-};
-
-class SkTypeface_Mac : public SkTypeface {
-public:
- SkTypeface_Mac(SkUniqueCFRef<CTFontRef> fontRef, const SkFontStyle& fs, bool isFixedPitch,
- OpszVariation opszVariation, std::unique_ptr<SkStreamAsset> providedData)
- : SkTypeface(fs, isFixedPitch)
- , fFontRef(std::move(fontRef))
- , fOpszVariation(opszVariation)
- , fHasColorGlyphs(
- SkToBool(CTFontGetSymbolicTraits(fFontRef.get()) & kCTFontColorGlyphsTrait))
- , fStream(std::move(providedData))
- , fIsFromStream(fStream)
- {
- SkASSERT(fFontRef);
- }
-
- SkUniqueCFRef<CTFontRef> fFontRef;
- const OpszVariation fOpszVariation;
- const bool fHasColorGlyphs;
-
-protected:
- int onGetUPEM() const override;
- std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override;
- std::unique_ptr<SkFontData> onMakeFontData() const override;
- int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
- int coordinateCount) const override;
- void onGetFamilyName(SkString* familyName) const override;
- SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
- int onGetTableTags(SkFontTableTag tags[]) const override;
- size_t onGetTableData(SkFontTableTag, size_t offset, size_t length, void* data) const override;
- sk_sp<SkData> onCopyTableData(SkFontTableTag) const override;
- SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
- const SkDescriptor*) const override;
- void onFilterRec(SkScalerContextRec*) const override;
- void onGetFontDescriptor(SkFontDescriptor*, bool*) const override;
- void getGlyphToUnicodeMap(SkUnichar*) const override;
- std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override;
- void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override;
- int onCountGlyphs() const override;
- void getPostScriptGlyphNames(SkString*) const override {}
- int onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
- int parameterCount) const override;
- sk_sp<SkTypeface> onMakeClone(const SkFontArguments&) const override;
-
- void* onGetCTFontRef() const override { return (void*)fFontRef.get(); }
-
-private:
- mutable std::unique_ptr<SkStreamAsset> fStream;
- bool fIsFromStream;
- mutable SkOnce fInitStream;
-
- typedef SkTypeface INHERITED;
-};
-
-static bool find_by_CTFontRef(SkTypeface* cached, void* context) {
- CTFontRef self = (CTFontRef)context;
- CTFontRef other = (CTFontRef)cached->internal_private_getCTFontRef();
-
- return CFEqual(self, other);
-}
-
-/** Creates a typeface, searching the cache if isLocalStream is false. */
-static sk_sp<SkTypeface> create_from_CTFontRef(SkUniqueCFRef<CTFontRef> font,
- OpszVariation opszVariation,
- std::unique_ptr<SkStreamAsset> providedData) {
- SkASSERT(font);
- const bool isFromStream(providedData);
-
- if (!isFromStream) {
- sk_sp<SkTypeface> face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef,
- (void*)font.get());
- if (face) {
- return face;
- }
- }
-
- SkUniqueCFRef<CTFontDescriptorRef> desc(CTFontCopyFontDescriptor(font.get()));
- SkFontStyle style = fontstyle_from_descriptor(desc.get(), isFromStream);
- CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font.get());
- bool isFixedPitch = SkToBool(traits & kCTFontMonoSpaceTrait);
-
- sk_sp<SkTypeface> face(new SkTypeface_Mac(std::move(font), style,
- isFixedPitch, opszVariation,
- std::move(providedData)));
- if (!isFromStream) {
- SkTypefaceCache::Add(face);
- }
- return face;
-}
-
-/** Creates a typeface from a descriptor, searching the cache. */
-static sk_sp<SkTypeface> create_from_desc(CTFontDescriptorRef desc) {
- SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr));
- if (!ctFont) {
- return nullptr;
- }
-
- return create_from_CTFontRef(std::move(ctFont), OpszVariation(), nullptr);
-}
-
-static SkUniqueCFRef<CTFontDescriptorRef> create_descriptor(const char familyName[],
- const SkFontStyle& style) {
- SkUniqueCFRef<CFMutableDictionaryRef> cfAttributes(
- CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
-
- SkUniqueCFRef<CFMutableDictionaryRef> cfTraits(
- CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
-
- if (!cfAttributes || !cfTraits) {
- return nullptr;
- }
-
- // TODO(crbug.com/1018581) Some CoreText versions have errant behavior when
- // certain traits set. Temporary workaround to omit specifying trait for
- // those versions.
- // Long term solution will involve serializing typefaces instead of relying
- // upon this to match between processes.
- //
- // Compare CoreText.h in an up to date SDK for where these values come from.
- static const uint32_t kSkiaLocalCTVersionNumber10_14 = 0x000B0000;
- static const uint32_t kSkiaLocalCTVersionNumber10_15 = 0x000C0000;
-
- // CTFontTraits (symbolic)
- // macOS 14 and iOS 12 seem to behave badly when kCTFontSymbolicTrait is set.
- // macOS 15 yields LastResort font instead of a good default font when
- // kCTFontSymbolicTrait is set.
- if (!(&CTGetCoreTextVersion && CTGetCoreTextVersion() >= kSkiaLocalCTVersionNumber10_14)) {
- CTFontSymbolicTraits ctFontTraits = 0;
- if (style.weight() >= SkFontStyle::kBold_Weight) {
- ctFontTraits |= kCTFontBoldTrait;
- }
- if (style.slant() != SkFontStyle::kUpright_Slant) {
- ctFontTraits |= kCTFontItalicTrait;
- }
- SkUniqueCFRef<CFNumberRef> cfFontTraits(
- CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits));
- if (cfFontTraits) {
- CFDictionaryAddValue(cfTraits.get(), kCTFontSymbolicTrait, cfFontTraits.get());
- }
- }
-
- // CTFontTraits (weight)
- CGFloat ctWeight = fontstyle_to_ct_weight(style.weight());
- SkUniqueCFRef<CFNumberRef> cfFontWeight(
- CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctWeight));
- if (cfFontWeight) {
- CFDictionaryAddValue(cfTraits.get(), kCTFontWeightTrait, cfFontWeight.get());
- }
- // CTFontTraits (width)
- CGFloat ctWidth = fontstyle_to_ct_width(style.width());
- SkUniqueCFRef<CFNumberRef> cfFontWidth(
- CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctWidth));
- if (cfFontWidth) {
- CFDictionaryAddValue(cfTraits.get(), kCTFontWidthTrait, cfFontWidth.get());
- }
- // CTFontTraits (slant)
- // macOS 15 behaves badly when kCTFontSlantTrait is set.
- if (!(&CTGetCoreTextVersion && CTGetCoreTextVersion() == kSkiaLocalCTVersionNumber10_15)) {
- CGFloat ctSlant = style.slant() == SkFontStyle::kUpright_Slant ? 0 : 1;
- SkUniqueCFRef<CFNumberRef> cfFontSlant(
- CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctSlant));
- if (cfFontSlant) {
- CFDictionaryAddValue(cfTraits.get(), kCTFontSlantTrait, cfFontSlant.get());
- }
- }
- // CTFontTraits
- CFDictionaryAddValue(cfAttributes.get(), kCTFontTraitsAttribute, cfTraits.get());
-
- // CTFontFamilyName
- if (familyName) {
- SkUniqueCFRef<CFStringRef> cfFontName = make_CFString(familyName);
- if (cfFontName) {
- CFDictionaryAddValue(cfAttributes.get(), kCTFontFamilyNameAttribute, cfFontName.get());
- }
- }
-
- return SkUniqueCFRef<CTFontDescriptorRef>(
- CTFontDescriptorCreateWithAttributes(cfAttributes.get()));
-}
-
-// Same as the above function except style is included so we can
-// compare whether the created font conforms to the style. If not, we need
-// to recreate the font with symbolic traits. This is needed due to MacOS 10.11
-// font creation problem https://bugs.chromium.org/p/skia/issues/detail?id=8447.
-static sk_sp<SkTypeface> create_from_desc_and_style(CTFontDescriptorRef desc,
- const SkFontStyle& style) {
- SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr));
- if (!ctFont) {
- return nullptr;
- }
-
- const CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctFont.get());
- CTFontSymbolicTraits expected_traits = traits;
- if (style.slant() != SkFontStyle::kUpright_Slant) {
- expected_traits |= kCTFontItalicTrait;
- }
- if (style.weight() >= SkFontStyle::kBold_Weight) {
- expected_traits |= kCTFontBoldTrait;
- }
-
- if (expected_traits != traits) {
- SkUniqueCFRef<CTFontRef> ctNewFont(CTFontCreateCopyWithSymbolicTraits(
- ctFont.get(), 0, nullptr, expected_traits, expected_traits));
- if (ctNewFont) {
- ctFont = std::move(ctNewFont);
- }
- }
-
- return create_from_CTFontRef(std::move(ctFont), OpszVariation(), nullptr);
-}
-
-/** Creates a typeface from a name, searching the cache. */
-static sk_sp<SkTypeface> create_from_name(const char familyName[], const SkFontStyle& style) {
- SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style);
- if (!desc) {
- return nullptr;
- }
- return create_from_desc_and_style(desc.get(), style);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-/* This function is visible on the outside. It first searches the cache, and if
- * not found, returns a new entry (after adding it to the cache).
- */
-sk_sp<SkTypeface> SkMakeTypefaceFromCTFont(CTFontRef font) {
- CFRetain(font);
- return create_from_CTFontRef(SkUniqueCFRef<CTFontRef>(font),
- OpszVariation(),
- nullptr);
-}
-
-static const char* map_css_names(const char* name) {
- static const struct {
- const char* fFrom; // name the caller specified
- const char* fTo; // "canonical" name we map to
- } gPairs[] = {
- { "sans-serif", "Helvetica" },
- { "serif", "Times" },
- { "monospace", "Courier" }
- };
-
- for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
- if (strcmp(name, gPairs[i].fFrom) == 0) {
- return gPairs[i].fTo;
- }
- }
- return name; // no change
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-class SkScalerContext_Mac : public SkScalerContext {
-public:
- SkScalerContext_Mac(sk_sp<SkTypeface_Mac>, const SkScalerContextEffects&, const SkDescriptor*);
-
-protected:
- unsigned generateGlyphCount(void) override;
- bool generateAdvance(SkGlyph* glyph) override;
- void generateMetrics(SkGlyph* glyph) override;
- void generateImage(const SkGlyph& glyph) override;
- bool generatePath(SkGlyphID glyph, SkPath* path) override;
- void generateFontMetrics(SkFontMetrics*) override;
-
-private:
- template<bool APPLY_PREBLEND>
- static void RGBToA8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes,
- const SkGlyph& glyph, const uint8_t* table8);
- template<bool APPLY_PREBLEND>
- static uint16_t RGBToLcd16(CGRGBPixel rgb, const uint8_t* tableR,
- const uint8_t* tableG,
- const uint8_t* tableB);
- template<bool APPLY_PREBLEND>
- static void RGBToLcd16(const CGRGBPixel* SK_RESTRICT cgPixels,
- size_t cgRowBytes,
- const SkGlyph& glyph,
- const uint8_t* tableR,
- const uint8_t* tableG,
- const uint8_t* tableB);
-
- Offscreen fOffscreen;
-
- /** Unrotated variant of fCTFont.
- *
- * In 10.10.1 CTFontGetAdvancesForGlyphs applies the font transform to the width of the
- * advances, but always sets the height to 0. This font is used to get the advances of the
- * unrotated glyph, and then the rotation is applied separately.
- *
- * CT vertical metrics are pre-rotated (in em space, before transform) 90deg clock-wise.
- * This makes kCTFontOrientationDefault dangerous, because the metrics from
- * kCTFontOrientationHorizontal are in a different space from kCTFontOrientationVertical.
- * With kCTFontOrientationVertical the advances must be unrotated.
- *
- * Sometimes, creating a copy of a CTFont with the same size but different trasform will select
- * different underlying font data. As a result, avoid ever creating more than one CTFont per
- * SkScalerContext to ensure that only one CTFont is used.
- *
- * As a result of the above (and other constraints) this font contains the size, but not the
- * transform. The transform must always be applied separately.
- */
- SkUniqueCFRef<CTFontRef> fCTFont;
-
- /** The transform without the font size. */
- CGAffineTransform fTransform;
- CGAffineTransform fInvTransform;
-
- SkUniqueCFRef<CGFontRef> fCGFont;
- uint16_t fGlyphCount;
- const bool fDoSubPosition;
-
- friend class Offscreen;
-
- typedef SkScalerContext INHERITED;
-};
-
-// In macOS 10.12 and later any variation on the CGFont which has default axis value will be
-// dropped when creating the CTFont. Unfortunately, in macOS 10.15 the priority of setting
-// the optical size (and opsz variation) is
-// 1. the value of kCTFontOpticalSizeAttribute in the CTFontDescriptor (undocumented)
-// 2. the opsz axis default value if kCTFontOpticalSizeAttribute is 'none' (undocumented)
-// 3. the opsz variation on the nascent CTFont from the CGFont (was dropped if default)
-// 4. the opsz variation in kCTFontVariationAttribute in CTFontDescriptor (crashes 10.10)
-// 5. the size requested (can fudge in SkTypeface but not SkScalerContext)
-// The first one which is found will be used to set the opsz variation (after clamping).
-static void add_opsz_attr(CFMutableDictionaryRef attr, double opsz) {
- SkUniqueCFRef<CFNumberRef> opszValueNumber(
- CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &opsz));
- // Avoid using kCTFontOpticalSizeAttribute directly
- CFStringRef SkCTFontOpticalSizeAttribute = CFSTR("NSCTFontOpticalSizeAttribute");
- CFDictionarySetValue(attr, SkCTFontOpticalSizeAttribute, opszValueNumber.get());
-}
-
-// This turns off application of the 'trak' table to advances, but also all other tracking.
-static void add_notrak_attr(CFMutableDictionaryRef attr) {
- int zero = 0;
- SkUniqueCFRef<CFNumberRef> unscaledTrackingNumber(
- CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &zero));
- CFStringRef SkCTFontUnscaledTrackingAttribute = CFSTR("NSCTFontUnscaledTrackingAttribute");
- CFDictionarySetValue(attr, SkCTFontUnscaledTrackingAttribute, unscaledTrackingNumber.get());
-}
-
-static SkUniqueCFRef<CTFontRef> ctfont_create_exact_copy(CTFontRef baseFont, CGFloat textSize,
- OpszVariation opsz)
-{
- SkUniqueCFRef<CFMutableDictionaryRef> attr(
- CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
-
- if (opsz.isSet) {
- add_opsz_attr(attr.get(), opsz.value);
-#if !defined(SK_IGNORE_MAC_OPSZ_FORCE)
- } else {
- // On (at least) 10.10 though 10.14 the default system font was SFNSText/SFNSDisplay.
- // The CTFont is backed by both; optical size < 20 means SFNSText else SFNSDisplay.
- // On at least 10.11 the glyph ids in these fonts became non-interchangable.
- // To keep glyph ids stable over size changes, preserve the optical size.
- // In 10.15 this was replaced with use of variable fonts with an opsz axis.
- // A CTFont backed by multiple fonts picked by opsz where the multiple backing fonts are
- // variable fonts with opsz axis and non-interchangeable glyph ids would break the
- // opsz.isSet branch above, but hopefully that never happens.
- // See https://crbug.com/524646 .
- CFStringRef SkCTFontOpticalSizeAttribute = CFSTR("NSCTFontOpticalSizeAttribute");
- SkUniqueCFRef<CFTypeRef> opsz(CTFontCopyAttribute(baseFont, SkCTFontOpticalSizeAttribute));
- double opsz_val;
- if (!opsz ||
- CFGetTypeID(opsz.get()) != CFNumberGetTypeID() ||
- !CFNumberGetValue(static_cast<CFNumberRef>(opsz.get()),kCFNumberDoubleType,&opsz_val) ||
- opsz_val <= 0)
- {
- opsz_val = CTFontGetSize(baseFont);
- }
- add_opsz_attr(attr.get(), opsz_val);
-#endif
- }
- add_notrak_attr(attr.get());
-
- SkUniqueCFRef<CTFontDescriptorRef> desc(CTFontDescriptorCreateWithAttributes(attr.get()));
-
-#if !defined(SK_IGNORE_MAC_OPSZ_FORCE)
- return SkUniqueCFRef<CTFontRef>(
- CTFontCreateCopyWithAttributes(baseFont, textSize, nullptr, desc.get()));
-#else
- SkUniqueCFRef<CGFontRef> baseCGFont(CTFontCopyGraphicsFont(baseFont, nullptr));
- return SkUniqueCFRef<CTFontRef>(
- CTFontCreateWithGraphicsFont(baseCGFont.get(), textSize, nullptr, desc.get()));
-
-#endif
-}
-
-SkScalerContext_Mac::SkScalerContext_Mac(sk_sp<SkTypeface_Mac> typeface,
- const SkScalerContextEffects& effects,
- const SkDescriptor* desc)
- : INHERITED(std::move(typeface), effects, desc)
- , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag))
-
-{
- CTFontRef ctFont = (CTFontRef)this->getTypeface()->internal_private_getCTFontRef();
- CFIndex numGlyphs = CTFontGetGlyphCount(ctFont);
- SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF);
- fGlyphCount = SkToU16(numGlyphs);
-
- // CT on (at least) 10.9 will size color glyphs down from the requested size, but not up.
- // As a result, it is necessary to know the actual device size and request that.
- SkVector scale;
- SkMatrix skTransform;
- bool invertible = fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale,
- &scale, &skTransform, nullptr, nullptr, nullptr);
- fTransform = MatrixToCGAffineTransform(skTransform);
- // CGAffineTransformInvert documents that if the transform is non-invertible it will return the
- // passed transform unchanged. It does so, but then also prints a message to stdout. Avoid this.
- if (invertible) {
- fInvTransform = CGAffineTransformInvert(fTransform);
- } else {
- fInvTransform = fTransform;
- }
-
- // The transform contains everything except the requested text size.
- // Some properties, like 'trak', are based on the optical text size.
- CGFloat textSize = ScalarToCG(scale.y());
- fCTFont = ctfont_create_exact_copy(ctFont, textSize,
- ((SkTypeface_Mac*)this->getTypeface())->fOpszVariation);
- fCGFont.reset(CTFontCopyGraphicsFont(fCTFont.get(), nullptr));
-}
-
-CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph,
- CGGlyph glyphID, size_t* rowBytesPtr,
- bool generateA8FromLCD) {
- if (!fRGBSpace) {
- //It doesn't appear to matter what color space is specified.
- //Regular blends and antialiased text are always (s*a + d*(1-a))
- //and subpixel antialiased text is always g=2.0.
- fRGBSpace.reset(CGColorSpaceCreateDeviceRGB());
- }
-
- // default to kBW_Format
- bool doAA = false;
- bool doLCD = false;
-
- if (SkMask::kBW_Format != glyph.maskFormat()) {
- doLCD = true;
- doAA = true;
- }
-
- // FIXME: lcd smoothed un-hinted rasterization unsupported.
- if (!generateA8FromLCD && SkMask::kA8_Format == glyph.maskFormat()) {
- doLCD = false;
- doAA = true;
- }
-
- // If this font might have color glyphs, disable LCD as there's no way to support it.
- // CoreText doesn't tell us which format it ended up using, so we can't detect it.
- // A8 will end up black on transparent, but TODO: we can detect gray and set to A8.
- if (SkMask::kARGB32_Format == glyph.maskFormat()) {
- doLCD = false;
- }
-
- size_t rowBytes = fSize.fWidth * sizeof(CGRGBPixel);
- if (!fCG || fSize.fWidth < glyph.width() || fSize.fHeight < glyph.height()) {
- if (fSize.fWidth < glyph.width()) {
- fSize.fWidth = RoundSize(glyph.width());
- }
- if (fSize.fHeight < glyph.height()) {
- fSize.fHeight = RoundSize(glyph.height());
- }
-
- rowBytes = fSize.fWidth * sizeof(CGRGBPixel);
- void* image = fImageStorage.reset(rowBytes * fSize.fHeight);
- const CGImageAlphaInfo alpha = (glyph.isColor())
- ? kCGImageAlphaPremultipliedFirst
- : kCGImageAlphaNoneSkipFirst;
- const CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | alpha;
- fCG.reset(CGBitmapContextCreate(image, fSize.fWidth, fSize.fHeight, 8,
- rowBytes, fRGBSpace.get(), bitmapInfo));
-
- // Skia handles quantization and subpixel positioning,
- // so disable quantization and enabe subpixel positioning in CG.
- CGContextSetAllowsFontSubpixelQuantization(fCG.get(), false);
- CGContextSetShouldSubpixelQuantizeFonts(fCG.get(), false);
-
- // Because CG always draws from the horizontal baseline,
- // if there is a non-integral translation from the horizontal origin to the vertical origin,
- // then CG cannot draw the glyph in the correct location without subpixel positioning.
- CGContextSetAllowsFontSubpixelPositioning(fCG.get(), true);
- CGContextSetShouldSubpixelPositionFonts(fCG.get(), true);
-
- CGContextSetTextDrawingMode(fCG.get(), kCGTextFill);
-
- // Draw black on white to create mask. (Special path exists to speed this up in CG.)
- CGContextSetGrayFillColor(fCG.get(), 0.0f, 1.0f);
-
- // force our checks below to happen
- fDoAA = !doAA;
- fDoLCD = !doLCD;
-
- CGContextSetTextMatrix(fCG.get(), context.fTransform);
- }
-
- if (fDoAA != doAA) {
- CGContextSetShouldAntialias(fCG.get(), doAA);
- fDoAA = doAA;
- }
- if (fDoLCD != doLCD) {
- CGContextSetShouldSmoothFonts(fCG.get(), doLCD);
- fDoLCD = doLCD;
- }
-
- CGRGBPixel* image = (CGRGBPixel*)fImageStorage.get();
- // skip rows based on the glyph's height
- image += (fSize.fHeight - glyph.height()) * fSize.fWidth;
-
- // Erase to white (or transparent black if it's a color glyph, to not composite against white).
- uint32_t bgColor = (!glyph.isColor()) ? 0xFFFFFFFF : 0x00000000;
- sk_memset_rect32(image, bgColor, glyph.width(), glyph.height(), rowBytes);
-
- float subX = 0;
- float subY = 0;
- if (context.fDoSubPosition) {
- subX = SkFixedToFloat(glyph.getSubXFixed());
- subY = SkFixedToFloat(glyph.getSubYFixed());
- }
-
- CGPoint point = CGPointMake(-glyph.left() + subX, glyph.top() + glyph.height() - subY);
- // Prior to 10.10, CTFontDrawGlyphs acted like CGContextShowGlyphsAtPositions and took
- // 'positions' which are in text space. The glyph location (in device space) must be
- // mapped into text space, so that CG can convert it back into device space.
- // In 10.10.1, this is handled directly in CTFontDrawGlyphs.
- //
- // However, in 10.10.2 color glyphs no longer rotate based on the font transform.
- // So always make the font transform identity and place the transform on the context.
- point = CGPointApplyAffineTransform(point, context.fInvTransform);
-
- CTFontDrawGlyphs(context.fCTFont.get(), &glyphID, &point, 1, fCG.get());
-
- SkASSERT(rowBytesPtr);
- *rowBytesPtr = rowBytes;
- return image;
-}
-
-unsigned SkScalerContext_Mac::generateGlyphCount(void) {
- return fGlyphCount;
-}
-
-bool SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) {
- return false;
-}
-
-void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) {
- glyph->fMaskFormat = fRec.fMaskFormat;
-
- const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID();
- glyph->zeroMetrics();
-
- // The following block produces cgAdvance in CG units (pixels, y up).
- CGSize cgAdvance;
- CTFontGetAdvancesForGlyphs(fCTFont.get(), kCTFontOrientationHorizontal,
- &cgGlyph, &cgAdvance, 1);
- cgAdvance = CGSizeApplyAffineTransform(cgAdvance, fTransform);
- glyph->fAdvanceX = CGToFloat(cgAdvance.width);
- glyph->fAdvanceY = -CGToFloat(cgAdvance.height);
-
- // The following produces skBounds in SkGlyph units (pixels, y down),
- // or returns early if skBounds would be empty.
- SkRect skBounds;
-
- // Glyphs are always drawn from the horizontal origin. The caller must manually use the result
- // of CTFontGetVerticalTranslationsForGlyphs to calculate where to draw the glyph for vertical
- // glyphs. As a result, always get the horizontal bounds of a glyph and translate it if the
- // glyph is vertical. This avoids any diagreement between the various means of retrieving
- // vertical metrics.
- {
- // CTFontGetBoundingRectsForGlyphs produces cgBounds in CG units (pixels, y up).
- CGRect cgBounds;
- CTFontGetBoundingRectsForGlyphs(fCTFont.get(), kCTFontOrientationHorizontal,
- &cgGlyph, &cgBounds, 1);
- cgBounds = CGRectApplyAffineTransform(cgBounds, fTransform);
-
- // BUG?
- // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when
- // it should be empty. So, if we see a zero-advance, we check if it has an
- // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-advance
- // is rare, so we won't incur a big performance cost for this extra check.
- if (0 == cgAdvance.width && 0 == cgAdvance.height) {
- SkUniqueCFRef<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont.get(), cgGlyph,nullptr));
- if (!path || CGPathIsEmpty(path.get())) {
- return;
- }
- }
-
- if (CGRectIsEmpty_inline(cgBounds)) {
- return;
- }
-
- // Convert cgBounds to SkGlyph units (pixels, y down).
- skBounds = SkRect::MakeXYWH(cgBounds.origin.x, -cgBounds.origin.y - cgBounds.size.height,
- cgBounds.size.width, cgBounds.size.height);
- }
-
- // Currently the bounds are based on being rendered at (0,0).
- // The top left must not move, since that is the base from which subpixel positioning is offset.
- if (fDoSubPosition) {
- skBounds.fRight += SkFixedToFloat(glyph->getSubXFixed());
- skBounds.fBottom += SkFixedToFloat(glyph->getSubYFixed());
- }
-
- // We're trying to pack left and top into int16_t,
- // and width and height into uint16_t, after outsetting by 1.
- if (!SkRect::MakeXYWH(-32767, -32767, 65535, 65535).contains(skBounds)) {
- return;
- }
-
- SkIRect skIBounds;
- skBounds.roundOut(&skIBounds);
- // Expand the bounds by 1 pixel, to give CG room for anti-aliasing.
- // Note that this outset is to allow room for LCD smoothed glyphs. However, the correct outset
- // is not currently known, as CG dilates the outlines by some percentage.
- // Note that if this context is A8 and not back-forming from LCD, there is no need to outset.
- skIBounds.outset(1, 1);
- glyph->fLeft = SkToS16(skIBounds.fLeft);
- glyph->fTop = SkToS16(skIBounds.fTop);
- glyph->fWidth = SkToU16(skIBounds.width());
- glyph->fHeight = SkToU16(skIBounds.height());
-}
-
-static constexpr uint8_t sk_pow2_table(size_t i) {
- return SkToU8(((i * i + 128) / 255));
-}
-
-/**
- * This will invert the gamma applied by CoreGraphics, so we can get linear
- * values.
- *
- * CoreGraphics obscurely defaults to 2.0 as the subpixel coverage gamma value.
- * The color space used does not appear to affect this choice.
- */
-static constexpr auto gLinearCoverageFromCGLCDValue = SkMakeArray<256>(sk_pow2_table);
-
-static void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) {
- while (count > 0) {
- uint8_t mask = 0;
- for (int i = 7; i >= 0; --i) {
- mask |= ((CGRGBPixel_getAlpha(*src++) >> 7) ^ 0x1) << i;
- if (0 == --count) {
- break;
- }
- }
- *dst++ = mask;
- }
-}
-
-template<bool APPLY_PREBLEND>
-static inline uint8_t rgb_to_a8(CGRGBPixel rgb, const uint8_t* table8) {
- U8CPU r = 0xFF - ((rgb >> 16) & 0xFF);
- U8CPU g = 0xFF - ((rgb >> 8) & 0xFF);
- U8CPU b = 0xFF - ((rgb >> 0) & 0xFF);
- U8CPU lum = sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8);
-#if SK_SHOW_TEXT_BLIT_COVERAGE
- lum = std::max(lum, (U8CPU)0x30);
-#endif
- return lum;
-}
-
-template<bool APPLY_PREBLEND>
-void SkScalerContext_Mac::RGBToA8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes,
- const SkGlyph& glyph, const uint8_t* table8) {
- const int width = glyph.fWidth;
- size_t dstRB = glyph.rowBytes();
- uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage;
-
- for (int y = 0; y < glyph.fHeight; y++) {
- for (int i = 0; i < width; ++i) {
- dst[i] = rgb_to_a8<APPLY_PREBLEND>(cgPixels[i], table8);
- }
- cgPixels = SkTAddOffset<const CGRGBPixel>(cgPixels, cgRowBytes);
- dst = SkTAddOffset<uint8_t>(dst, dstRB);
- }
-}
-
-template<bool APPLY_PREBLEND>
-uint16_t SkScalerContext_Mac::RGBToLcd16(CGRGBPixel rgb, const uint8_t* tableR,
- const uint8_t* tableG,
- const uint8_t* tableB) {
- U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >> 16) & 0xFF), tableR);
- U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >> 8) & 0xFF), tableG);
- U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >> 0) & 0xFF), tableB);
-#if SK_SHOW_TEXT_BLIT_COVERAGE
- r = std::max(r, (U8CPU)0x30);
- g = std::max(g, (U8CPU)0x30);
- b = std::max(b, (U8CPU)0x30);
-#endif
- return SkPack888ToRGB16(r, g, b);
-}
-
-template<bool APPLY_PREBLEND>
-void SkScalerContext_Mac::RGBToLcd16(const CGRGBPixel* SK_RESTRICT cgPixels,
- size_t cgRowBytes,
- const SkGlyph& glyph,
- const uint8_t* tableR,
- const uint8_t* tableG,
- const uint8_t* tableB) {
- const int width = glyph.fWidth;
- size_t dstRB = glyph.rowBytes();
- uint16_t* SK_RESTRICT dst = (uint16_t*)glyph.fImage;
-
- for (int y = 0; y < glyph.fHeight; y++) {
- for (int i = 0; i < width; i++) {
- dst[i] = RGBToLcd16<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, tableB);
- }
- cgPixels = SkTAddOffset<const CGRGBPixel>(cgPixels, cgRowBytes);
- dst = SkTAddOffset<uint16_t>(dst, dstRB);
- }
-}
-
-static SkPMColor cgpixels_to_pmcolor(CGRGBPixel rgb) {
- U8CPU a = (rgb >> 24) & 0xFF;
- U8CPU r = (rgb >> 16) & 0xFF;
- U8CPU g = (rgb >> 8) & 0xFF;
- U8CPU b = (rgb >> 0) & 0xFF;
-#if SK_SHOW_TEXT_BLIT_COVERAGE
- a = std::max(a, (U8CPU)0x30);
-#endif
- return SkPackARGB32(a, r, g, b);
-}
-
-void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
- CGGlyph cgGlyph = SkTo<CGGlyph>(glyph.getGlyphID());
-
- // FIXME: lcd smoothed un-hinted rasterization unsupported.
- bool requestSmooth = fRec.getHinting() != SkFontHinting::kNone;
-
- // Draw the glyph
- size_t cgRowBytes;
- CGRGBPixel* cgPixels = fOffscreen.getCG(*this, glyph, cgGlyph, &cgRowBytes, requestSmooth);
- if (cgPixels == nullptr) {
- return;
- }
-
- // Fix the glyph
- if ((glyph.fMaskFormat == SkMask::kLCD16_Format) ||
- (glyph.fMaskFormat == SkMask::kA8_Format
- && requestSmooth
- && smooth_behavior() != SmoothBehavior::none))
- {
- const uint8_t* linear = gLinearCoverageFromCGLCDValue.data();
-
- //Note that the following cannot really be integrated into the
- //pre-blend, since we may not be applying the pre-blend; when we aren't
- //applying the pre-blend it means that a filter wants linear anyway.
- //Other code may also be applying the pre-blend, so we'd need another
- //one with this and one without.
- CGRGBPixel* addr = cgPixels;
- for (int y = 0; y < glyph.fHeight; ++y) {
- for (int x = 0; x < glyph.fWidth; ++x) {
- int r = (addr[x] >> 16) & 0xFF;
- int g = (addr[x] >> 8) & 0xFF;
- int b = (addr[x] >> 0) & 0xFF;
- addr[x] = (linear[r] << 16) | (linear[g] << 8) | linear[b];
- }
- addr = SkTAddOffset<CGRGBPixel>(addr, cgRowBytes);
- }
- }
-
- // Convert glyph to mask
- switch (glyph.fMaskFormat) {
- case SkMask::kLCD16_Format: {
- if (fPreBlend.isApplicable()) {
- RGBToLcd16<true>(cgPixels, cgRowBytes, glyph,
- fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
- } else {
- RGBToLcd16<false>(cgPixels, cgRowBytes, glyph,
- fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
- }
- } break;
- case SkMask::kA8_Format: {
- if (fPreBlend.isApplicable()) {
- RGBToA8<true>(cgPixels, cgRowBytes, glyph, fPreBlend.fG);
- } else {
- RGBToA8<false>(cgPixels, cgRowBytes, glyph, fPreBlend.fG);
- }
- } break;
- case SkMask::kBW_Format: {
- const int width = glyph.fWidth;
- size_t dstRB = glyph.rowBytes();
- uint8_t* dst = (uint8_t*)glyph.fImage;
- for (int y = 0; y < glyph.fHeight; y++) {
- cgpixels_to_bits(dst, cgPixels, width);
- cgPixels = SkTAddOffset<CGRGBPixel>(cgPixels, cgRowBytes);
- dst = SkTAddOffset<uint8_t>(dst, dstRB);
- }
- } break;
- case SkMask::kARGB32_Format: {
- const int width = glyph.fWidth;
- size_t dstRB = glyph.rowBytes();
- SkPMColor* dst = (SkPMColor*)glyph.fImage;
- for (int y = 0; y < glyph.fHeight; y++) {
- for (int x = 0; x < width; ++x) {
- dst[x] = cgpixels_to_pmcolor(cgPixels[x]);
- }
- cgPixels = SkTAddOffset<CGRGBPixel>(cgPixels, cgRowBytes);
- dst = SkTAddOffset<SkPMColor>(dst, dstRB);
- }
- } break;
- default:
- SkDEBUGFAIL("unexpected mask format");
- break;
- }
-}
-
-namespace {
-class SkCTPathGeometrySink {
- SkPath* fPath;
- bool fStarted;
- CGPoint fCurrent;
-
- void goingTo(const CGPoint pt) {
- if (!fStarted) {
- fStarted = true;
- fPath->moveTo(fCurrent.x, -fCurrent.y);
- }
- fCurrent = pt;
- }
-
- bool currentIsNot(const CGPoint pt) {
- return fCurrent.x != pt.x || fCurrent.y != pt.y;
- }
-
-public:
- SkCTPathGeometrySink(SkPath* path) : fPath{path}, fStarted{false}, fCurrent{0,0} {}
- static void ApplyElement(void *ctx, const CGPathElement *element) {
- SkCTPathGeometrySink& self = *(SkCTPathGeometrySink*)ctx;
- CGPoint* points = element->points;
-
- switch (element->type) {
- case kCGPathElementMoveToPoint:
- self.fStarted = false;
- self.fCurrent = points[0];
- break;
-
- case kCGPathElementAddLineToPoint:
- if (self.currentIsNot(points[0])) {
- self.goingTo(points[0]);
- self.fPath->lineTo(points[0].x, -points[0].y);
- }
- break;
-
- case kCGPathElementAddQuadCurveToPoint:
- if (self.currentIsNot(points[0]) || self.currentIsNot(points[1])) {
- self.goingTo(points[1]);
- self.fPath->quadTo(points[0].x, -points[0].y,
- points[1].x, -points[1].y);
- }
- break;
-
- case kCGPathElementAddCurveToPoint:
- if (self.currentIsNot(points[0]) ||
- self.currentIsNot(points[1]) ||
- self.currentIsNot(points[2]))
- {
- self.goingTo(points[2]);
- self.fPath->cubicTo(points[0].x, -points[0].y,
- points[1].x, -points[1].y,
- points[2].x, -points[2].y);
- }
- break;
-
- case kCGPathElementCloseSubpath:
- if (self.fStarted) {
- self.fPath->close();
- }
- break;
-
- default:
- SkDEBUGFAIL("Unknown path element!");
- break;
- }
- }
-};
-} // namespace
-
-/*
- * Our subpixel resolution is only 2 bits in each direction, so a scale of 4
- * seems sufficient, and possibly even correct, to allow the hinted outline
- * to be subpixel positioned.
- */
-#define kScaleForSubPixelPositionHinting (4.0f)
-
-bool SkScalerContext_Mac::generatePath(SkGlyphID glyph, SkPath* path) {
- SkScalar scaleX = SK_Scalar1;
- SkScalar scaleY = SK_Scalar1;
-
- CGAffineTransform xform = fTransform;
- /*
- * For subpixel positioning, we want to return an unhinted outline, so it
- * can be positioned nicely at fractional offsets. However, we special-case
- * if the baseline of the (horizontal) text is axis-aligned. In those cases
- * we want to retain hinting in the direction orthogonal to the baseline.
- * e.g. for horizontal baseline, we want to retain hinting in Y.
- * The way we remove hinting is to scale the font by some value (4) in that
- * direction, ask for the path, and then scale the path back down.
- */
- if (fDoSubPosition) {
- // start out by assuming that we want no hining in X and Y
- scaleX = scaleY = kScaleForSubPixelPositionHinting;
- // now see if we need to restore hinting for axis-aligned baselines
- switch (this->computeAxisAlignmentForHText()) {
- case kX_SkAxisAlignment:
- scaleY = SK_Scalar1; // want hinting in the Y direction
- break;
- case kY_SkAxisAlignment:
- scaleX = SK_Scalar1; // want hinting in the X direction
- break;
- default:
- break;
- }
-
- CGAffineTransform scale(CGAffineTransformMakeScale(ScalarToCG(scaleX), ScalarToCG(scaleY)));
- xform = CGAffineTransformConcat(fTransform, scale);
- }
-
- CGGlyph cgGlyph = SkTo<CGGlyph>(glyph);
- SkUniqueCFRef<CGPathRef> cgPath(CTFontCreatePathForGlyph(fCTFont.get(), cgGlyph, &xform));
-
- path->reset();
- if (!cgPath) {
- return false;
- }
-
- SkCTPathGeometrySink sink(path);
- CGPathApply(cgPath.get(), &sink, SkCTPathGeometrySink::ApplyElement);
- if (fDoSubPosition) {
- SkMatrix m;
- m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY));
- path->transform(m);
- }
- return true;
-}
-
-void SkScalerContext_Mac::generateFontMetrics(SkFontMetrics* metrics) {
- if (nullptr == metrics) {
- return;
- }
-
- CGRect theBounds = CTFontGetBoundingBox(fCTFont.get());
-
- metrics->fTop = CGToScalar(-CGRectGetMaxY_inline(theBounds));
- metrics->fAscent = CGToScalar(-CTFontGetAscent(fCTFont.get()));
- metrics->fDescent = CGToScalar( CTFontGetDescent(fCTFont.get()));
- metrics->fBottom = CGToScalar(-CGRectGetMinY_inline(theBounds));
- metrics->fLeading = CGToScalar( CTFontGetLeading(fCTFont.get()));
- metrics->fAvgCharWidth = CGToScalar( CGRectGetWidth_inline(theBounds));
- metrics->fXMin = CGToScalar( CGRectGetMinX_inline(theBounds));
- metrics->fXMax = CGToScalar( CGRectGetMaxX_inline(theBounds));
- metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin;
- metrics->fXHeight = CGToScalar( CTFontGetXHeight(fCTFont.get()));
- metrics->fCapHeight = CGToScalar( CTFontGetCapHeight(fCTFont.get()));
- metrics->fUnderlineThickness = CGToScalar( CTFontGetUnderlineThickness(fCTFont.get()));
- metrics->fUnderlinePosition = -CGToScalar( CTFontGetUnderlinePosition(fCTFont.get()));
-
- metrics->fFlags = 0;
- metrics->fFlags |= SkFontMetrics::kUnderlineThicknessIsValid_Flag;
- metrics->fFlags |= SkFontMetrics::kUnderlinePositionIsValid_Flag;
-
- // See https://bugs.chromium.org/p/skia/issues/detail?id=6203
- // At least on 10.12.3 with memory based fonts the x-height is always 0.6666 of the ascent and
- // the cap-height is always 0.8888 of the ascent. It appears that the values from the 'OS/2'
- // table are read, but then overwritten if the font is not a system font. As a result, if there
- // is a valid 'OS/2' table available use the values from the table if they aren't too strange.
- struct OS2HeightMetrics {
- SK_OT_SHORT sxHeight;
- SK_OT_SHORT sCapHeight;
- } heights;
- size_t bytesRead = this->getTypeface()->getTableData(
- SkTEndian_SwapBE32(SkOTTableOS2::TAG), offsetof(SkOTTableOS2, version.v2.sxHeight),
- sizeof(heights), &heights);
- if (bytesRead == sizeof(heights)) {
- // 'fontSize' is correct because the entire resolved size is set by the constructor.
- CGFloat fontSize = CTFontGetSize(this->fCTFont.get());
- unsigned upem = CTFontGetUnitsPerEm(this->fCTFont.get());
- unsigned maxSaneHeight = upem * 2;
- uint16_t xHeight = SkEndian_SwapBE16(heights.sxHeight);
- if (xHeight && xHeight < maxSaneHeight) {
- metrics->fXHeight = CGToScalar(xHeight * fontSize / upem);
- }
- uint16_t capHeight = SkEndian_SwapBE16(heights.sCapHeight);
- if (capHeight && capHeight < maxSaneHeight) {
- metrics->fCapHeight = CGToScalar(capHeight * fontSize / upem);
- }
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-// Web fonts added to the CTFont registry do not return their character set.
-// Iterate through the font in this case. The existing caller caches the result,
-// so the performance impact isn't too bad.
-static void populate_glyph_to_unicode_slow(CTFontRef ctFont, CFIndex glyphCount,
- SkUnichar* out) {
- sk_bzero(out, glyphCount * sizeof(SkUnichar));
- UniChar unichar = 0;
- while (glyphCount > 0) {
- CGGlyph glyph;
- if (CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) {
- if (out[glyph] == 0) {
- out[glyph] = unichar;
- --glyphCount;
- }
- }
- if (++unichar == 0) {
- break;
- }
- }
-}
-
-static constexpr uint16_t kPlaneSize = 1 << 13;
-
-static void get_plane_glyph_map(const uint8_t* bits,
- CTFontRef ctFont,
- CFIndex glyphCount,
- SkUnichar* glyphToUnicode,
- uint8_t planeIndex) {
- SkUnichar planeOrigin = (SkUnichar)planeIndex << 16; // top half of codepoint.
- for (uint16_t i = 0; i < kPlaneSize; i++) {
- uint8_t mask = bits[i];
- if (!mask) {
- continue;
- }
- for (uint8_t j = 0; j < 8; j++) {
- if (0 == (mask & ((uint8_t)1 << j))) {
- continue;
- }
- uint16_t planeOffset = (i << 3) | j;
- SkUnichar codepoint = planeOrigin | (SkUnichar)planeOffset;
- uint16_t utf16[2] = {planeOffset, 0};
- size_t count = 1;
- if (planeOrigin != 0) {
- count = SkUTF::ToUTF16(codepoint, utf16);
- }
- CGGlyph glyphs[2] = {0, 0};
- if (CTFontGetGlyphsForCharacters(ctFont, utf16, glyphs, count)) {
- SkASSERT(glyphs[1] == 0);
- SkASSERT(glyphs[0] < glyphCount);
- // CTFontCopyCharacterSet and CTFontGetGlyphsForCharacters seem to add 'support'
- // for characters 0x9, 0xA, and 0xD mapping them to the glyph for character 0x20?
- // Prefer mappings to codepoints at or above 0x20.
- if (glyphToUnicode[glyphs[0]] < 0x20) {
- glyphToUnicode[glyphs[0]] = codepoint;
- }
- }
- }
- }
-}
-// Construct Glyph to Unicode table.
-static void populate_glyph_to_unicode(CTFontRef ctFont, CFIndex glyphCount,
- SkUnichar* glyphToUnicode) {
- sk_bzero(glyphToUnicode, sizeof(SkUnichar) * glyphCount);
- SkUniqueCFRef<CFCharacterSetRef> charSet(CTFontCopyCharacterSet(ctFont));
- if (!charSet) {
- populate_glyph_to_unicode_slow(ctFont, glyphCount, glyphToUnicode);
- return;
- }
-
- SkUniqueCFRef<CFDataRef> bitmap(
- CFCharacterSetCreateBitmapRepresentation(nullptr, charSet.get()));
- if (!bitmap) {
- return;
- }
- CFIndex dataLength = CFDataGetLength(bitmap.get());
- if (!dataLength) {
- return;
- }
- SkASSERT(dataLength >= kPlaneSize);
- const UInt8* bits = CFDataGetBytePtr(bitmap.get());
-
- get_plane_glyph_map(bits, ctFont, glyphCount, glyphToUnicode, 0);
- /*
- A CFData object that specifies the bitmap representation of the Unicode
- character points the for the new character set. The bitmap representation could
- contain all the Unicode character range starting from BMP to Plane 16. The
- first 8KiB (8192 bytes) of the data represent the BMP range. The BMP range 8KiB
- can be followed by zero to sixteen 8KiB bitmaps, each prepended with the plane
- index byte. For example, the bitmap representing the BMP and Plane 2 has the
- size of 16385 bytes (8KiB for BMP, 1 byte index, and a 8KiB bitmap for Plane
- 2). The plane index byte, in this case, contains the integer value two.
- */
-
- if (dataLength <= kPlaneSize) {
- return;
- }
- int extraPlaneCount = (dataLength - kPlaneSize) / (1 + kPlaneSize);
- SkASSERT(dataLength == kPlaneSize + extraPlaneCount * (1 + kPlaneSize));
- while (extraPlaneCount-- > 0) {
- bits += kPlaneSize;
- uint8_t planeIndex = *bits++;
- SkASSERT(planeIndex >= 1);
- SkASSERT(planeIndex <= 16);
- get_plane_glyph_map(bits, ctFont, glyphCount, glyphToUnicode, planeIndex);
- }
-}
-
-/** Assumes src and dst are not nullptr. */
-static void CFStringToSkString(CFStringRef src, SkString* dst) {
- // Reserve enough room for the worst-case string,
- // plus 1 byte for the trailing null.
- CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(src),
- kCFStringEncodingUTF8) + 1;
- dst->resize(length);
- CFStringGetCString(src, dst->writable_str(), length, kCFStringEncodingUTF8);
- // Resize to the actual UTF-8 length used, stripping the null character.
- dst->resize(strlen(dst->c_str()));
-}
-
-void SkTypeface_Mac::getGlyphToUnicodeMap(SkUnichar* dstArray) const {
- SkUniqueCFRef<CTFontRef> ctFont =
- ctfont_create_exact_copy(fFontRef.get(), CTFontGetUnitsPerEm(fFontRef.get()),
- fOpszVariation);
- CFIndex glyphCount = CTFontGetGlyphCount(ctFont.get());
- populate_glyph_to_unicode(ctFont.get(), glyphCount, dstArray);
-}
-
-std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface_Mac::onGetAdvancedMetrics() const {
-
- SkUniqueCFRef<CTFontRef> ctFont =
- ctfont_create_exact_copy(fFontRef.get(), CTFontGetUnitsPerEm(fFontRef.get()),
- fOpszVariation);
-
- std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics);
-
- {
- SkUniqueCFRef<CFStringRef> fontName(CTFontCopyPostScriptName(ctFont.get()));
- if (fontName.get()) {
- CFStringToSkString(fontName.get(), &info->fPostScriptName);
- info->fFontName = info->fPostScriptName;
- }
- }
-
- // In 10.10 and earlier, CTFontCopyVariationAxes and CTFontCopyVariation do not work when
- // applied to fonts which started life with CGFontCreateWithDataProvider (they simply always
- // return nullptr). As a result, we are limited to CGFontCopyVariationAxes and
- // CGFontCopyVariations here until support for 10.10 and earlier is removed.
- SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont.get(), nullptr));
- if (cgFont) {
- SkUniqueCFRef<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cgFont.get()));
- if (cgAxes && CFArrayGetCount(cgAxes.get()) > 0) {
- info->fFlags |= SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag;
- }
- }
-
- SkOTTableOS2_V4::Type fsType;
- if (sizeof(fsType) == this->getTableData(SkTEndian_SwapBE32(SkOTTableOS2::TAG),
- offsetof(SkOTTableOS2_V4, fsType),
- sizeof(fsType),
- &fsType)) {
- SkOTUtils::SetAdvancedTypefaceFlags(fsType, info.get());
- }
-
- // If it's not a truetype font, mark it as 'other'. Assume that TrueType
- // fonts always have both glyf and loca tables. At the least, this is what
- // sfntly needs to subset the font. CTFontCopyAttribute() does not always
- // succeed in determining this directly.
- if (!this->getTableSize('glyf') || !this->getTableSize('loca')) {
- return info;
- }
-
- info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
- CTFontSymbolicTraits symbolicTraits = CTFontGetSymbolicTraits(ctFont.get());
- if (symbolicTraits & kCTFontMonoSpaceTrait) {
- info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
- }
- if (symbolicTraits & kCTFontItalicTrait) {
- info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
- }
- CTFontStylisticClass stylisticClass = symbolicTraits & kCTFontClassMaskTrait;
- if (stylisticClass >= kCTFontOldStyleSerifsClass && stylisticClass <= kCTFontSlabSerifsClass) {
- info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
- } else if (stylisticClass & kCTFontScriptsClass) {
- info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
- }
- info->fItalicAngle = (int16_t) CTFontGetSlantAngle(ctFont.get());
- info->fAscent = (int16_t) CTFontGetAscent(ctFont.get());
- info->fDescent = (int16_t) CTFontGetDescent(ctFont.get());
- info->fCapHeight = (int16_t) CTFontGetCapHeight(ctFont.get());
- CGRect bbox = CTFontGetBoundingBox(ctFont.get());
-
- SkRect r;
- r.setLTRB(CGToScalar(CGRectGetMinX_inline(bbox)), // Left
- CGToScalar(CGRectGetMaxY_inline(bbox)), // Top
- CGToScalar(CGRectGetMaxX_inline(bbox)), // Right
- CGToScalar(CGRectGetMinY_inline(bbox))); // Bottom
-
- r.roundOut(&(info->fBBox));
-
- // Figure out a good guess for StemV - Min width of i, I, !, 1.
- // This probably isn't very good with an italic font.
- int16_t min_width = SHRT_MAX;
- info->fStemV = 0;
- static const UniChar stem_chars[] = {'i', 'I', '!', '1'};
- const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
- CGGlyph glyphs[count];
- CGRect boundingRects[count];
- if (CTFontGetGlyphsForCharacters(ctFont.get(), stem_chars, glyphs, count)) {
- CTFontGetBoundingRectsForGlyphs(ctFont.get(), kCTFontOrientationHorizontal,
- glyphs, boundingRects, count);
- for (size_t i = 0; i < count; i++) {
- int16_t width = (int16_t) boundingRects[i].size.width;
- if (width > 0 && width < min_width) {
- min_width = width;
- info->fStemV = min_width;
- }
- }
- }
- return info;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static SK_SFNT_ULONG get_font_type_tag(CTFontRef ctFont) {
- SkUniqueCFRef<CFNumberRef> fontFormatRef(
- static_cast<CFNumberRef>(CTFontCopyAttribute(ctFont, kCTFontFormatAttribute)));
- if (!fontFormatRef) {
- return 0;
- }
-
- SInt32 fontFormatValue;
- if (!CFNumberGetValue(fontFormatRef.get(), kCFNumberSInt32Type, &fontFormatValue)) {
- return 0;
- }
-
- switch (fontFormatValue) {
- case kCTFontFormatOpenTypePostScript:
- return SkSFNTHeader::fontType_OpenTypeCFF::TAG;
- case kCTFontFormatOpenTypeTrueType:
- return SkSFNTHeader::fontType_WindowsTrueType::TAG;
- case kCTFontFormatTrueType:
- return SkSFNTHeader::fontType_MacTrueType::TAG;
- case kCTFontFormatPostScript:
- return SkSFNTHeader::fontType_PostScript::TAG;
- case kCTFontFormatBitmap:
- return SkSFNTHeader::fontType_MacTrueType::TAG;
- case kCTFontFormatUnrecognized:
- default:
- return 0;
- }
-}
-
-std::unique_ptr<SkStreamAsset> SkTypeface_Mac::onOpenStream(int* ttcIndex) const {
- *ttcIndex = 0;
-
- fInitStream([this]{
- if (fStream) {
- return;
- }
-
- SK_SFNT_ULONG fontType = get_font_type_tag(fFontRef.get());
-
- // get table tags
- int numTables = this->countTables();
- SkTDArray<SkFontTableTag> tableTags;
- tableTags.setCount(numTables);
- this->getTableTags(tableTags.begin());
-
- // CT seems to be unreliable in being able to obtain the type,
- // even if all we want is the first four bytes of the font resource.
- // Just the presence of the FontForge 'FFTM' table seems to throw it off.
- if (fontType == 0) {
- fontType = SkSFNTHeader::fontType_WindowsTrueType::TAG;
-
- // see https://skbug.com/7630#c7
- bool couldBeCFF = false;
- constexpr SkFontTableTag CFFTag = SkSetFourByteTag('C', 'F', 'F', ' ');
- constexpr SkFontTableTag CFF2Tag = SkSetFourByteTag('C', 'F', 'F', '2');
- for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
- if (CFFTag == tableTags[tableIndex] || CFF2Tag == tableTags[tableIndex]) {
- couldBeCFF = true;
- }
- }
- if (couldBeCFF) {
- fontType = SkSFNTHeader::fontType_OpenTypeCFF::TAG;
- }
- }
-
- // Sometimes CoreGraphics incorrectly thinks a font is kCTFontFormatPostScript.
- // It is exceedingly unlikely that this is the case, so double check
- // (see https://crbug.com/809763 ).
- if (fontType == SkSFNTHeader::fontType_PostScript::TAG) {
- // see if there are any required 'typ1' tables (see Adobe Technical Note #5180)
- bool couldBeTyp1 = false;
- constexpr SkFontTableTag TYPE1Tag = SkSetFourByteTag('T', 'Y', 'P', '1');
- constexpr SkFontTableTag CIDTag = SkSetFourByteTag('C', 'I', 'D', ' ');
- for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
- if (TYPE1Tag == tableTags[tableIndex] || CIDTag == tableTags[tableIndex]) {
- couldBeTyp1 = true;
- }
- }
- if (!couldBeTyp1) {
- fontType = SkSFNTHeader::fontType_OpenTypeCFF::TAG;
- }
- }
-
- // get the table sizes and accumulate the total size of the font
- SkTDArray<size_t> tableSizes;
- size_t totalSize = sizeof(SkSFNTHeader) + sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables;
- for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
- size_t tableSize = this->getTableSize(tableTags[tableIndex]);
- totalSize += (tableSize + 3) & ~3;
- *tableSizes.append() = tableSize;
- }
-
- // reserve memory for stream, and zero it (tables must be zero padded)
- fStream.reset(new SkMemoryStream(totalSize));
- char* dataStart = (char*)fStream->getMemoryBase();
- sk_bzero(dataStart, totalSize);
- char* dataPtr = dataStart;
-
- // compute font header entries
- uint16_t entrySelector = 0;
- uint16_t searchRange = 1;
- while (searchRange < numTables >> 1) {
- entrySelector++;
- searchRange <<= 1;
- }
- searchRange <<= 4;
- uint16_t rangeShift = (numTables << 4) - searchRange;
-
- // write font header
- SkSFNTHeader* header = (SkSFNTHeader*)dataPtr;
- header->fontType = fontType;
- header->numTables = SkEndian_SwapBE16(numTables);
- header->searchRange = SkEndian_SwapBE16(searchRange);
- header->entrySelector = SkEndian_SwapBE16(entrySelector);
- header->rangeShift = SkEndian_SwapBE16(rangeShift);
- dataPtr += sizeof(SkSFNTHeader);
-
- // write tables
- SkSFNTHeader::TableDirectoryEntry* entry = (SkSFNTHeader::TableDirectoryEntry*)dataPtr;
- dataPtr += sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables;
- for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
- size_t tableSize = tableSizes[tableIndex];
- this->getTableData(tableTags[tableIndex], 0, tableSize, dataPtr);
- entry->tag = SkEndian_SwapBE32(tableTags[tableIndex]);
- entry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum((SK_OT_ULONG*)dataPtr,
- tableSize));
- entry->offset = SkEndian_SwapBE32(SkToU32(dataPtr - dataStart));
- entry->logicalLength = SkEndian_SwapBE32(SkToU32(tableSize));
-
- dataPtr += (tableSize + 3) & ~3;
- ++entry;
- }
- });
- return fStream->duplicate();
-}
-
-struct NonDefaultAxesContext {
- SkFixed* axisValue;
- CFArrayRef cgAxes;
-};
-static void set_non_default_axes(CFTypeRef key, CFTypeRef value, void* context) {
- NonDefaultAxesContext* self = static_cast<NonDefaultAxesContext*>(context);
-
- if (CFGetTypeID(key) != CFStringGetTypeID() || CFGetTypeID(value) != CFNumberGetTypeID()) {
- return;
- }
-
- // The key is a CFString which is a string from the 'name' table.
- // Search the cgAxes for an axis with this name, and use its index to store the value.
- CFIndex keyIndex = -1;
- CFStringRef keyString = static_cast<CFStringRef>(key);
- for (CFIndex i = 0; i < CFArrayGetCount(self->cgAxes); ++i) {
- CFTypeRef cgAxis = CFArrayGetValueAtIndex(self->cgAxes, i);
- if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
- continue;
- }
-
- CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
- CFTypeRef cgAxisName = CFDictionaryGetValue(cgAxisDict, kCGFontVariationAxisName);
- if (!cgAxisName || CFGetTypeID(cgAxisName) != CFStringGetTypeID()) {
- continue;
- }
- CFStringRef cgAxisNameString = static_cast<CFStringRef>(cgAxisName);
- if (CFStringCompare(keyString, cgAxisNameString, 0) == kCFCompareEqualTo) {
- keyIndex = i;
- break;
- }
- }
- if (keyIndex == -1) {
- return;
- }
-
- CFNumberRef valueNumber = static_cast<CFNumberRef>(value);
- double valueDouble;
- if (!CFNumberGetValue(valueNumber, kCFNumberDoubleType, &valueDouble) ||
- valueDouble < SkFixedToDouble(SK_FixedMin) || SkFixedToDouble(SK_FixedMax) < valueDouble)
- {
- return;
- }
- self->axisValue[keyIndex] = SkDoubleToFixed(valueDouble);
-}
-static bool get_variations(CTFontRef ctFont, CFIndex* cgAxisCount,
- SkAutoSTMalloc<4, SkFixed>* axisValues)
-{
- // In 10.10 and earlier, CTFontCopyVariationAxes and CTFontCopyVariation do not work when
- // applied to fonts which started life with CGFontCreateWithDataProvider (they simply always
- // return nullptr). As a result, we are limited to CGFontCopyVariationAxes and
- // CGFontCopyVariations here until support for 10.10 and earlier is removed.
- SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont, nullptr));
- if (!cgFont) {
- return false;
- }
-
- SkUniqueCFRef<CFDictionaryRef> cgVariations(CGFontCopyVariations(cgFont.get()));
- // If a font has no variations CGFontCopyVariations returns nullptr (instead of an empty dict).
- if (!cgVariations) {
- return false;
- }
-
- SkUniqueCFRef<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cgFont.get()));
- if (!cgAxes) {
- return false;
- }
- *cgAxisCount = CFArrayGetCount(cgAxes.get());
- axisValues->reset(*cgAxisCount);
-
- // Set all of the axes to their default values.
- // Fail if any default value cannot be determined.
- for (CFIndex i = 0; i < *cgAxisCount; ++i) {
- CFTypeRef cgAxis = CFArrayGetValueAtIndex(cgAxes.get(), i);
- if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
- return false;
- }
-
- CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
- CFTypeRef axisDefaultValue = CFDictionaryGetValue(cgAxisDict,
- kCGFontVariationAxisDefaultValue);
- if (!axisDefaultValue || CFGetTypeID(axisDefaultValue) != CFNumberGetTypeID()) {
- return false;
- }
- CFNumberRef axisDefaultValueNumber = static_cast<CFNumberRef>(axisDefaultValue);
- double axisDefaultValueDouble;
- if (!CFNumberGetValue(axisDefaultValueNumber, kCFNumberDoubleType, &axisDefaultValueDouble))
- {
- return false;
- }
- if (axisDefaultValueDouble < SkFixedToDouble(SK_FixedMin) ||
- SkFixedToDouble(SK_FixedMax) < axisDefaultValueDouble)
- {
- return false;
- }
- (*axisValues)[(int)i] = SkDoubleToFixed(axisDefaultValueDouble);
- }
-
- // Override the default values with the given font's stated axis values.
- NonDefaultAxesContext c = { axisValues->get(), cgAxes.get() };
- CFDictionaryApplyFunction(cgVariations.get(), set_non_default_axes, &c);
-
- return true;
-}
-std::unique_ptr<SkFontData> SkTypeface_Mac::onMakeFontData() const {
- int index;
- std::unique_ptr<SkStreamAsset> stream(this->onOpenStream(&index));
-
- CFIndex cgAxisCount;
- SkAutoSTMalloc<4, SkFixed> axisValues;
- if (get_variations(fFontRef.get(), &cgAxisCount, &axisValues)) {
- return std::make_unique<SkFontData>(std::move(stream), index,
- axisValues.get(), cgAxisCount);
- }
- return std::make_unique<SkFontData>(std::move(stream), index, nullptr, 0);
-}
-
-/** Creates a CT variation dictionary {tag, value} from a CG variation dictionary {name, value}. */
-static SkUniqueCFRef<CFDictionaryRef> ct_variation_from_cg_variation(CFDictionaryRef cgVariations,
- CFArrayRef ctAxes) {
-
- SkUniqueCFRef<CFMutableDictionaryRef> ctVariation(
- CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
-
- CFIndex axisCount = CFArrayGetCount(ctAxes);
- for (CFIndex i = 0; i < axisCount; ++i) {
- CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes, i);
- if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
- return nullptr;
- }
- CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
-
- // The assumption is that values produced by kCTFontVariationAxisNameKey and
- // kCGFontVariationAxisName will always be equal.
- CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisNameKey);
- if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
- return nullptr;
- }
-
- CFTypeRef axisValue = CFDictionaryGetValue(cgVariations, axisName);
- if (!axisValue || CFGetTypeID(axisValue) != CFNumberGetTypeID()) {
- return nullptr;
- }
-
- CFTypeRef axisTag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
- if (!axisTag || CFGetTypeID(axisTag) != CFNumberGetTypeID()) {
- return nullptr;
- }
-
- CFDictionaryAddValue(ctVariation.get(), axisTag, axisValue);
- }
- return std::move(ctVariation);
-}
-
-int SkTypeface_Mac::onGetVariationDesignPosition(
- SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
-{
- // The CGFont variation data does not contain the tag.
-
- // CTFontCopyVariationAxes returns nullptr for CGFontCreateWithDataProvider fonts with
- // macOS 10.10 and iOS 9 or earlier. When this happens, there is no API to provide the tag.
- SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(fFontRef.get()));
- if (!ctAxes) {
- return -1;
- }
- CFIndex axisCount = CFArrayGetCount(ctAxes.get());
- if (!coordinates || coordinateCount < axisCount) {
- return axisCount;
- }
-
- // This call always returns nullptr on 10.11 and under for CGFontCreateWithDataProvider fonts.
- // When this happens, try converting the CG variation to a CT variation.
- // On 10.12 and later, this only returns non-default variations.
- SkUniqueCFRef<CFDictionaryRef> ctVariation(CTFontCopyVariation(fFontRef.get()));
- if (!ctVariation) {
- // When 10.11 and earlier are no longer supported, the following code can be replaced with
- // return -1 and ct_variation_from_cg_variation can be removed.
- SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef.get(), nullptr));
- if (!cgFont) {
- return -1;
- }
- SkUniqueCFRef<CFDictionaryRef> cgVariations(CGFontCopyVariations(cgFont.get()));
- if (!cgVariations) {
- return -1;
- }
- ctVariation = ct_variation_from_cg_variation(cgVariations.get(), ctAxes.get());
- if (!ctVariation) {
- return -1;
- }
- }
-
- for (int i = 0; i < axisCount; ++i) {
- CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
- if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
- return -1;
- }
- CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
-
- CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
- if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
- return -1;
- }
- CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
- int64_t tagLong;
- if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
- return -1;
- }
- coordinates[i].axis = tagLong;
-
- CGFloat variationCGFloat;
- CFTypeRef variationValue = CFDictionaryGetValue(ctVariation.get(), tagNumber);
- if (variationValue) {
- if (CFGetTypeID(variationValue) != CFNumberGetTypeID()) {
- return -1;
- }
- CFNumberRef variationNumber = static_cast<CFNumberRef>(variationValue);
- if (!CFNumberGetValue(variationNumber, kCFNumberCGFloatType, &variationCGFloat)) {
- return -1;
- }
- } else {
- CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisDefaultValueKey);
- if (!def || CFGetTypeID(def) != CFNumberGetTypeID()) {
- return -1;
- }
- CFNumberRef defNumber = static_cast<CFNumberRef>(def);
- if (!CFNumberGetValue(defNumber, kCFNumberCGFloatType, &variationCGFloat)) {
- return -1;
- }
- }
- coordinates[i].value = CGToScalar(variationCGFloat);
-
- }
- return axisCount;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-int SkTypeface_Mac::onGetUPEM() const {
- SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef.get(), nullptr));
- return CGFontGetUnitsPerEm(cgFont.get());
-}
-
-SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const {
- sk_sp<SkTypeface::LocalizedStrings> nameIter =
- SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*this);
- if (!nameIter) {
- CFStringRef cfLanguageRaw;
- SkUniqueCFRef<CFStringRef> cfFamilyName(
- CTFontCopyLocalizedName(fFontRef.get(), kCTFontFamilyNameKey, &cfLanguageRaw));
- SkUniqueCFRef<CFStringRef> cfLanguage(cfLanguageRaw);
-
- SkString skLanguage;
- SkString skFamilyName;
- if (cfLanguage) {
- CFStringToSkString(cfLanguage.get(), &skLanguage);
- } else {
- skLanguage = "und"; //undetermined
- }
- if (cfFamilyName) {
- CFStringToSkString(cfFamilyName.get(), &skFamilyName);
- }
-
- nameIter = sk_make_sp<SkOTUtils::LocalizedStrings_SingleName>(skFamilyName, skLanguage);
- }
- return nameIter.release();
-}
-
-int SkTypeface_Mac::onGetTableTags(SkFontTableTag tags[]) const {
- SkUniqueCFRef<CFArrayRef> cfArray(
- CTFontCopyAvailableTables(fFontRef.get(), kCTFontTableOptionNoOptions));
- if (!cfArray) {
- return 0;
- }
- int count = SkToInt(CFArrayGetCount(cfArray.get()));
- if (tags) {
- for (int i = 0; i < count; ++i) {
- uintptr_t fontTag = reinterpret_cast<uintptr_t>(
- CFArrayGetValueAtIndex(cfArray.get(), i));
- tags[i] = static_cast<SkFontTableTag>(fontTag);
- }
- }
- return count;
-}
-
-// If, as is the case with web fonts, the CTFont data isn't available,
-// the CGFont data may work. While the CGFont may always provide the
-// right result, leave the CTFont code path to minimize disruption.
-static SkUniqueCFRef<CFDataRef> copy_table_from_font(CTFontRef ctFont, SkFontTableTag tag) {
- SkUniqueCFRef<CFDataRef> data(CTFontCopyTable(ctFont, (CTFontTableTag) tag,
- kCTFontTableOptionNoOptions));
- if (!data) {
- SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont, nullptr));
- data.reset(CGFontCopyTableForTag(cgFont.get(), tag));
- }
- return data;
-}
-
-size_t SkTypeface_Mac::onGetTableData(SkFontTableTag tag, size_t offset,
- size_t length, void* dstData) const {
- SkUniqueCFRef<CFDataRef> srcData = copy_table_from_font(fFontRef.get(), tag);
- if (!srcData) {
- return 0;
- }
-
- size_t srcSize = CFDataGetLength(srcData.get());
- if (offset >= srcSize) {
- return 0;
- }
- if (length > srcSize - offset) {
- length = srcSize - offset;
- }
- if (dstData) {
- memcpy(dstData, CFDataGetBytePtr(srcData.get()) + offset, length);
- }
- return length;
-}
-
-sk_sp<SkData> SkTypeface_Mac::onCopyTableData(SkFontTableTag tag) const {
- SkUniqueCFRef<CFDataRef> srcData = copy_table_from_font(fFontRef.get(), tag);
- if (!srcData) {
- return nullptr;
- }
- const UInt8* data = CFDataGetBytePtr(srcData.get());
- CFIndex length = CFDataGetLength(srcData.get());
- return SkData::MakeWithProc(data, length,
- [](const void*, void* ctx) {
- CFRelease((CFDataRef)ctx);
- }, (void*)srcData.release());
-}
-
-SkScalerContext* SkTypeface_Mac::onCreateScalerContext(const SkScalerContextEffects& effects,
- const SkDescriptor* desc) const {
- return new SkScalerContext_Mac(sk_ref_sp(const_cast<SkTypeface_Mac*>(this)), effects, desc);
-}
-
-void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const {
- if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
- rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
- {
- rec->fMaskFormat = SkMask::kA8_Format;
- // Render the glyphs as close as possible to what was requested.
- // The above turns off subpixel rendering, but the user requested it.
- // Normal hinting will cause the A8 masks to be generated from CoreGraphics subpixel masks.
- // See comments below for more details.
- rec->setHinting(SkFontHinting::kNormal);
- }
-
- unsigned flagsWeDontSupport = SkScalerContext::kForceAutohinting_Flag |
- SkScalerContext::kLCD_BGROrder_Flag |
- SkScalerContext::kLCD_Vertical_Flag;
-
- rec->fFlags &= ~flagsWeDontSupport;
-
- const SmoothBehavior smoothBehavior = smooth_behavior();
-
- // Only two levels of hinting are supported.
- // kNo_Hinting means avoid CoreGraphics outline dilation (smoothing).
- // kNormal_Hinting means CoreGraphics outline dilation (smoothing) is allowed.
- if (rec->getHinting() != SkFontHinting::kNone) {
- rec->setHinting(SkFontHinting::kNormal);
- }
- // If smoothing has no effect, don't request it.
- if (smoothBehavior == SmoothBehavior::none) {
- rec->setHinting(SkFontHinting::kNone);
- }
-
- // FIXME: lcd smoothed un-hinted rasterization unsupported.
- // Tracked by http://code.google.com/p/skia/issues/detail?id=915 .
- // There is no current means to honor a request for unhinted lcd,
- // so arbitrarilly ignore the hinting request and honor lcd.
-
- // Hinting and smoothing should be orthogonal, but currently they are not.
- // CoreGraphics has no API to influence hinting. However, its lcd smoothed
- // output is drawn from auto-dilated outlines (the amount of which is
- // determined by AppleFontSmoothing). Its regular anti-aliased output is
- // drawn from un-dilated outlines.
-
- // The behavior of Skia is as follows:
- // [AA][no-hint]: generate AA using CoreGraphic's AA output.
- // [AA][yes-hint]: use CoreGraphic's LCD output and reduce it to a single
- // channel. This matches [LCD][yes-hint] in weight.
- // [LCD][no-hint]: curently unable to honor, and must pick which to respect.
- // Currenly side with LCD, effectively ignoring the hinting setting.
- // [LCD][yes-hint]: generate LCD using CoreGraphic's LCD output.
- if (rec->fMaskFormat == SkMask::kLCD16_Format) {
- if (smoothBehavior == SmoothBehavior::subpixel) {
- //CoreGraphics creates 555 masks for smoothed text anyway.
- rec->fMaskFormat = SkMask::kLCD16_Format;
- rec->setHinting(SkFontHinting::kNormal);
- } else {
- rec->fMaskFormat = SkMask::kA8_Format;
- if (smoothBehavior != SmoothBehavior::none) {
- rec->setHinting(SkFontHinting::kNormal);
- }
- }
- }
-
- // CoreText provides no information as to whether a glyph will be color or not.
- // Fonts may mix outlines and bitmaps, so information is needed on a glyph by glyph basis.
- // If a font contains an 'sbix' table, consider it to be a color font, and disable lcd.
- if (fHasColorGlyphs) {
- rec->fMaskFormat = SkMask::kARGB32_Format;
- }
-
- // Unhinted A8 masks (those not derived from LCD masks) must respect SK_GAMMA_APPLY_TO_A8.
- // All other masks can use regular gamma.
- if (SkMask::kA8_Format == rec->fMaskFormat && SkFontHinting::kNone == rec->getHinting()) {
-#ifndef SK_GAMMA_APPLY_TO_A8
- // SRGBTODO: Is this correct? Do we want contrast boost?
- rec->ignorePreBlend();
-#endif
- } else {
- SkColor color = rec->getLuminanceColor();
- if (smoothBehavior == SmoothBehavior::some) {
- // CoreGraphics smoothed text without subpixel coverage blitting goes from a gamma of
- // 2.0 for black foreground to a gamma of 1.0 for white foreground. Emulate this
- // through the mask gamma by reducing the color values to 1/2.
- color = SkColorSetRGB(SkColorGetR(color) * 1/2,
- SkColorGetG(color) * 1/2,
- SkColorGetB(color) * 1/2);
- } else if (smoothBehavior == SmoothBehavior::subpixel) {
- // CoreGraphics smoothed text with subpixel coverage blitting goes from a gamma of
- // 2.0 for black foreground to a gamma of ~1.4? for white foreground. Emulate this
- // through the mask gamma by reducing the color values to 3/4.
- color = SkColorSetRGB(SkColorGetR(color) * 3/4,
- SkColorGetG(color) * 3/4,
- SkColorGetB(color) * 3/4);
- }
- rec->setLuminanceColor(color);
-
- // CoreGraphics dialates smoothed text to provide contrast.
- rec->setContrast(0);
- }
-}
-
-/** Takes ownership of the CFStringRef. */
-static const char* get_str(CFStringRef ref, SkString* str) {
- if (nullptr == ref) {
- return nullptr;
- }
- CFStringToSkString(ref, str);
- CFRelease(ref);
- return str->c_str();
-}
-
-void SkTypeface_Mac::onGetFamilyName(SkString* familyName) const {
- get_str(CTFontCopyFamilyName(fFontRef.get()), familyName);
-}
-
-void SkTypeface_Mac::onGetFontDescriptor(SkFontDescriptor* desc,
- bool* isLocalStream) const {
- SkString tmpStr;
-
- desc->setFamilyName(get_str(CTFontCopyFamilyName(fFontRef.get()), &tmpStr));
- desc->setFullName(get_str(CTFontCopyFullName(fFontRef.get()), &tmpStr));
- desc->setPostscriptName(get_str(CTFontCopyPostScriptName(fFontRef.get()), &tmpStr));
- desc->setStyle(this->fontStyle());
- *isLocalStream = fIsFromStream;
-}
-
-void SkTypeface_Mac::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
- // Undocumented behavior of CTFontGetGlyphsForCharacters with non-bmp code points:
- // When a surrogate pair is detected, the glyph index used is the index of the high surrogate.
- // It is documented that if a mapping is unavailable, the glyph will be set to 0.
-
- SkAutoSTMalloc<1024, UniChar> charStorage;
- const UniChar* src; // UniChar is a UTF-16 16-bit code unit.
- int srcCount;
- const SkUnichar* utf32 = reinterpret_cast<const SkUnichar*>(uni);
- UniChar* utf16 = charStorage.reset(2 * count);
- src = utf16;
- for (int i = 0; i < count; ++i) {
- utf16 += SkUTF::ToUTF16(utf32[i], utf16);
- }
- srcCount = SkToInt(utf16 - src);
-
- // If there are any non-bmp code points, the provided 'glyphs' storage will be inadequate.
- SkAutoSTMalloc<1024, uint16_t> glyphStorage;
- uint16_t* macGlyphs = glyphs;
- if (srcCount > count) {
- macGlyphs = glyphStorage.reset(srcCount);
- }
-
- CTFontGetGlyphsForCharacters(fFontRef.get(), src, macGlyphs, srcCount);
-
- // If there were any non-bmp, then copy and compact.
- // If all are bmp, 'glyphs' already contains the compact glyphs.
- // If some are non-bmp, copy and compact into 'glyphs'.
- if (srcCount > count) {
- SkASSERT(glyphs != macGlyphs);
- int extra = 0;
- for (int i = 0; i < count; ++i) {
- glyphs[i] = macGlyphs[i + extra];
- if (SkUTF16_IsLeadingSurrogate(src[i + extra])) {
- ++extra;
- }
- }
- } else {
- SkASSERT(glyphs == macGlyphs);
- }
-}
-
-int SkTypeface_Mac::onCountGlyphs() const {
- return SkToInt(CTFontGetGlyphCount(fFontRef.get()));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-namespace {
-
-struct CTFontVariation {
- SkUniqueCFRef<CFDictionaryRef> dict;
- OpszVariation opsz;
-};
-
-/** Creates a dictionary suitable for setting the axes on a CTFont. */
-static CTFontVariation ctvariation_from_skfontarguments(CTFontRef ct,
- const SkFontArguments& args)
-{
- OpszVariation opsz;
- constexpr const SkFourByteTag opszTag = SkSetFourByteTag('o','p','s','z');
-
- SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ct));
- if (!ctAxes) {
- return CTFontVariation();
- }
- CFIndex axisCount = CFArrayGetCount(ctAxes.get());
-
- const SkFontArguments::VariationPosition position = args.getVariationDesignPosition();
-
- SkUniqueCFRef<CFMutableDictionaryRef> dict(
- CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
-
- for (int i = 0; i < axisCount; ++i) {
- CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
- if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
- return CTFontVariation();
- }
- CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
-
- CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
- if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
- return CTFontVariation();
- }
- CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
- int64_t tagLong;
- if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
- return CTFontVariation();
- }
-
- // The variation axes can be set to any value, but cg will effectively pin them.
- // Pin them here to normalize.
- CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMinimumValueKey);
- CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMaximumValueKey);
- CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisDefaultValueKey);
- if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
- !max || CFGetTypeID(max) != CFNumberGetTypeID() ||
- !def || CFGetTypeID(def) != CFNumberGetTypeID())
- {
- return CTFontVariation();
- }
- CFNumberRef minNumber = static_cast<CFNumberRef>(min);
- CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
- CFNumberRef defNumber = static_cast<CFNumberRef>(def);
- double minDouble;
- double maxDouble;
- double defDouble;
- if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
- !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble) ||
- !CFNumberGetValue(defNumber, kCFNumberDoubleType, &defDouble))
- {
- return CTFontVariation();
- }
-
- double value = defDouble;
- // The position may be over specified. If there are multiple values for a given axis,
- // use the last one since that's what css-fonts-4 requires.
- for (int j = position.coordinateCount; j --> 0;) {
- if (position.coordinates[j].axis == tagLong) {
- value = SkTPin(SkScalarToDouble(position.coordinates[j].value),
- minDouble, maxDouble);
- if (tagLong == opszTag) {
- opsz.isSet = true;
- }
- break;
- }
- }
- if (tagLong == opszTag) {
- opsz.value = value;
- }
- SkUniqueCFRef<CFNumberRef> valueNumber(
- CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
- CFDictionaryAddValue(dict.get(), tagNumber, valueNumber.get());
- }
- return { SkUniqueCFRef<CFDictionaryRef>(std::move(dict)), opsz };
-}
-
-/** Creates a dictionary suitable for setting the axes on a CTFont. */
-static CTFontVariation ctvariation_from_skfontdata(CTFontRef ct, SkFontData* fontData) {
- // In macOS 10.15 CTFontCreate* overrides any 'opsz' variation with the 'size'.
- // Track the 'opsz' and return it, since it is an out of band axis.
- OpszVariation opsz;
- constexpr const SkFourByteTag opszTag = SkSetFourByteTag('o','p','s','z');
-
- SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ct));
- if (!ctAxes) {
- return CTFontVariation();
- }
-
- CFIndex axisCount = CFArrayGetCount(ctAxes.get());
- if (0 == axisCount || axisCount != fontData->getAxisCount()) {
- return CTFontVariation();
- }
-
- SkUniqueCFRef<CFMutableDictionaryRef> dict(
- CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
-
- for (int i = 0; i < fontData->getAxisCount(); ++i) {
- CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
- if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
- return CTFontVariation();
- }
- CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
-
- CFTypeRef tag = CFDictionaryGetValue(axisInfoDict,
- kCTFontVariationAxisIdentifierKey);
- if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
- return CTFontVariation();
- }
- CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
- int64_t tagLong;
- if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
- return CTFontVariation();
- }
-
- // The variation axes can be set to any value, but cg will effectively pin them.
- // Pin them here to normalize.
- CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMinimumValueKey);
- CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMaximumValueKey);
- if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
- !max || CFGetTypeID(max) != CFNumberGetTypeID())
- {
- return CTFontVariation();
- }
- CFNumberRef minNumber = static_cast<CFNumberRef>(min);
- CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
- double minDouble;
- double maxDouble;
- if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
- !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble))
- {
- return CTFontVariation();
- }
- double value = SkTPin(SkFixedToDouble(fontData->getAxis()[i]), minDouble, maxDouble);
-
- if (tagLong == opszTag) {
- opsz.isSet = true;
- opsz.value = value;
- }
-
- SkUniqueCFRef<CFNumberRef> valueNumber(
- CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
- CFDictionaryAddValue(dict.get(), tagNumber, valueNumber.get());
- }
- return { SkUniqueCFRef<CFDictionaryRef>(std::move(dict)), opsz };
-}
-
-static sk_sp<SkData> skdata_from_skstreamasset(std::unique_ptr<SkStreamAsset> stream) {
- size_t size = stream->getLength();
- if (const void* base = stream->getMemoryBase()) {
- return SkData::MakeWithProc(base, size,
- [](const void*, void* ctx) -> void {
- delete (SkStreamAsset*)ctx;
- }, stream.release());
- }
- return SkData::MakeFromStream(stream.get(), size);
-}
-
-static SkUniqueCFRef<CFDataRef> cfdata_from_skdata(sk_sp<SkData> data) {
- void const * const addr = data->data();
- size_t const size = data->size();
-
- CFAllocatorContext ctx = {
- 0, // CFIndex version
- data.release(), // void* info
- nullptr, // const void *(*retain)(const void *info);
- nullptr, // void (*release)(const void *info);
- nullptr, // CFStringRef (*copyDescription)(const void *info);
- nullptr, // void * (*allocate)(CFIndex size, CFOptionFlags hint, void *info);
- nullptr, // void*(*reallocate)(void* ptr,CFIndex newsize,CFOptionFlags hint,void* info);
- [](void*,void* info) -> void { // void (*deallocate)(void *ptr, void *info);
- SkASSERT(info);
- ((SkData*)info)->unref();
- },
- nullptr, // CFIndex (*preferredSize)(CFIndex size, CFOptionFlags hint, void *info);
- };
- SkUniqueCFRef<CFAllocatorRef> alloc(CFAllocatorCreate(kCFAllocatorDefault, &ctx));
- return SkUniqueCFRef<CFDataRef>(CFDataCreateWithBytesNoCopy(
- kCFAllocatorDefault, (const UInt8 *)addr, size, alloc.get()));
-}
-
-static SkUniqueCFRef<CTFontRef> ctfont_from_skdata(sk_sp<SkData> data, int ttcIndex) {
- // TODO: Use CTFontManagerCreateFontDescriptorsFromData when available.
- if (ttcIndex != 0) {
- return nullptr;
- }
-
- SkUniqueCFRef<CFDataRef> cfData(cfdata_from_skdata(std::move(data)));
-
- SkUniqueCFRef<CTFontDescriptorRef> desc(
- CTFontManagerCreateFontDescriptorFromData(cfData.get()));
- if (!desc) {
- return nullptr;
- }
- return SkUniqueCFRef<CTFontRef>(CTFontCreateWithFontDescriptor(desc.get(), 0, nullptr));
-}
-
-static bool find_desc_str(CTFontDescriptorRef desc, CFStringRef name, SkString* value) {
- SkUniqueCFRef<CFStringRef> ref((CFStringRef)CTFontDescriptorCopyAttribute(desc, name));
- if (!ref) {
- return false;
- }
- CFStringToSkString(ref.get(), value);
- return true;
-}
-
-static inline int sqr(int value) {
- SkASSERT(SkAbs32(value) < 0x7FFF); // check for overflow
- return value * value;
-}
-
-// We normalize each axis (weight, width, italic) to be base-900
-static int compute_metric(const SkFontStyle& a, const SkFontStyle& b) {
- return sqr(a.weight() - b.weight()) +
- sqr((a.width() - b.width()) * 100) +
- sqr((a.slant() != b.slant()) * 900);
-}
-
-class SkFontStyleSet_Mac : public SkFontStyleSet {
-public:
- SkFontStyleSet_Mac(CTFontDescriptorRef desc)
- : fArray(CTFontDescriptorCreateMatchingFontDescriptors(desc, nullptr))
- , fCount(0)
- {
- if (!fArray) {
- fArray.reset(CFArrayCreate(nullptr, nullptr, 0, nullptr));
- }
- fCount = SkToInt(CFArrayGetCount(fArray.get()));
- }
-
- int count() override {
- return fCount;
- }
-
- void getStyle(int index, SkFontStyle* style, SkString* name) override {
- SkASSERT((unsigned)index < (unsigned)fCount);
- CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index);
- if (style) {
- *style = fontstyle_from_descriptor(desc, false);
- }
- if (name) {
- if (!find_desc_str(desc, kCTFontStyleNameAttribute, name)) {
- name->reset();
- }
- }
- }
-
- SkTypeface* createTypeface(int index) override {
- SkASSERT((unsigned)index < (unsigned)CFArrayGetCount(fArray.get()));
- CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index);
-
- return create_from_desc(desc).release();
- }
-
- SkTypeface* matchStyle(const SkFontStyle& pattern) override {
- if (0 == fCount) {
- return nullptr;
- }
- return create_from_desc(findMatchingDesc(pattern)).release();
- }
-
-private:
- SkUniqueCFRef<CFArrayRef> fArray;
- int fCount;
-
- CTFontDescriptorRef findMatchingDesc(const SkFontStyle& pattern) const {
- int bestMetric = SK_MaxS32;
- CTFontDescriptorRef bestDesc = nullptr;
-
- for (int i = 0; i < fCount; ++i) {
- CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), i);
- int metric = compute_metric(pattern, fontstyle_from_descriptor(desc, false));
- if (0 == metric) {
- return desc;
- }
- if (metric < bestMetric) {
- bestMetric = metric;
- bestDesc = desc;
- }
- }
- SkASSERT(bestDesc);
- return bestDesc;
- }
-};
-
-} // namespace
-
-sk_sp<SkTypeface> SkTypeface_Mac::onMakeClone(const SkFontArguments& args) const {
- CTFontVariation ctVariation = ctvariation_from_skfontarguments(fFontRef.get(), args);
-
- SkUniqueCFRef<CTFontRef> ctVariant;
- if (ctVariation.dict) {
- SkUniqueCFRef<CFMutableDictionaryRef> attributes(
- CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
- CFDictionaryAddValue(attributes.get(),
- kCTFontVariationAttribute, ctVariation.dict.get());
- SkUniqueCFRef<CTFontDescriptorRef> varDesc(
- CTFontDescriptorCreateWithAttributes(attributes.get()));
- ctVariant.reset(CTFontCreateCopyWithAttributes(fFontRef.get(), 0, nullptr, varDesc.get()));
- } else {
- ctVariant.reset((CTFontRef)CFRetain(fFontRef.get()));
- }
- if (!ctVariant) {
- return nullptr;
- }
-
- return create_from_CTFontRef(std::move(ctVariant), ctVariation.opsz,
- fStream ? fStream->duplicate() : nullptr);
-}
-
-int SkTypeface_Mac::onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
- int parameterCount) const
-{
- SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(fFontRef.get()));
- if (!ctAxes) {
- return -1;
- }
- CFIndex axisCount = CFArrayGetCount(ctAxes.get());
-
- if (!parameters || parameterCount < axisCount) {
- return axisCount;
- }
-
- // Added in 10.13
- CFStringRef* kCTFontVariationAxisHiddenKeyPtr =
- static_cast<CFStringRef*>(dlsym(RTLD_DEFAULT, "kCTFontVariationAxisHiddenKey"));
-
- for (int i = 0; i < axisCount; ++i) {
- CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
- if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
- return -1;
- }
- CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
-
- CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
- if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
- return -1;
- }
- CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
- int64_t tagLong;
- if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
- return -1;
- }
-
- CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMinimumValueKey);
- CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMaximumValueKey);
- CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisDefaultValueKey);
- if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
- !max || CFGetTypeID(max) != CFNumberGetTypeID() ||
- !def || CFGetTypeID(def) != CFNumberGetTypeID())
- {
- return -1;
- }
- CFNumberRef minNumber = static_cast<CFNumberRef>(min);
- CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
- CFNumberRef defNumber = static_cast<CFNumberRef>(def);
- double minDouble;
- double maxDouble;
- double defDouble;
- if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
- !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble) ||
- !CFNumberGetValue(defNumber, kCFNumberDoubleType, &defDouble))
- {
- return -1;
- }
-
- SkFontParameters::Variation::Axis& skAxis = parameters[i];
- skAxis.tag = tagLong;
- skAxis.min = minDouble;
- skAxis.max = maxDouble;
- skAxis.def = defDouble;
- skAxis.setHidden(false);
- if (kCTFontVariationAxisHiddenKeyPtr) {
- CFTypeRef hidden = CFDictionaryGetValue(axisInfoDict,*kCTFontVariationAxisHiddenKeyPtr);
- if (hidden) {
- if (CFGetTypeID(hidden) != CFBooleanGetTypeID()) {
- return -1;
- }
- CFBooleanRef hiddenBoolean = static_cast<CFBooleanRef>(hidden);
- skAxis.setHidden(CFBooleanGetValue(hiddenBoolean));
- }
- }
- }
- return axisCount;
-}
-
-class SkFontMgr_Mac : public SkFontMgr {
- SkUniqueCFRef<CFArrayRef> fNames;
- int fCount;
-
- CFStringRef getFamilyNameAt(int index) const {
- SkASSERT((unsigned)index < (unsigned)fCount);
- return (CFStringRef)CFArrayGetValueAtIndex(fNames.get(), index);
- }
-
- static SkFontStyleSet* CreateSet(CFStringRef cfFamilyName) {
- SkUniqueCFRef<CFMutableDictionaryRef> cfAttr(
- CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
-
- CFDictionaryAddValue(cfAttr.get(), kCTFontFamilyNameAttribute, cfFamilyName);
-
- SkUniqueCFRef<CTFontDescriptorRef> desc(
- CTFontDescriptorCreateWithAttributes(cfAttr.get()));
- return new SkFontStyleSet_Mac(desc.get());
- }
-
- /** CTFontManagerCopyAvailableFontFamilyNames() is not always available, so we
- * provide a wrapper here that will return an empty array if need be.
- */
- static SkUniqueCFRef<CFArrayRef> CopyAvailableFontFamilyNames() {
-#ifdef SK_BUILD_FOR_IOS
- return SkUniqueCFRef<CFArrayRef>(CFArrayCreate(nullptr, nullptr, 0, nullptr));
-#else
- return SkUniqueCFRef<CFArrayRef>(CTFontManagerCopyAvailableFontFamilyNames());
-#endif
- }
-
-public:
- SkFontMgr_Mac()
- : fNames(CopyAvailableFontFamilyNames())
- , fCount(fNames ? SkToInt(CFArrayGetCount(fNames.get())) : 0) {}
-
-protected:
- int onCountFamilies() const override {
- return fCount;
- }
-
- void onGetFamilyName(int index, SkString* familyName) const override {
- if ((unsigned)index < (unsigned)fCount) {
- CFStringToSkString(this->getFamilyNameAt(index), familyName);
- } else {
- familyName->reset();
- }
- }
-
- SkFontStyleSet* onCreateStyleSet(int index) const override {
- if ((unsigned)index >= (unsigned)fCount) {
- return nullptr;
- }
- return CreateSet(this->getFamilyNameAt(index));
- }
-
- SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
- if (!familyName) {
- return nullptr;
- }
- SkUniqueCFRef<CFStringRef> cfName = make_CFString(familyName);
- return CreateSet(cfName.get());
- }
-
- SkTypeface* onMatchFamilyStyle(const char familyName[],
- const SkFontStyle& style) const override {
- SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style);
- return create_from_desc(desc.get()).release();
- }
-
- SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
- const SkFontStyle& style,
- const char* bcp47[], int bcp47Count,
- SkUnichar character) const override {
- SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style);
- SkUniqueCFRef<CTFontRef> familyFont(CTFontCreateWithFontDescriptor(desc.get(), 0, nullptr));
-
- // kCFStringEncodingUTF32 is BE unless there is a BOM.
- // Since there is no machine endian option, explicitly state machine endian.
-#ifdef SK_CPU_LENDIAN
- constexpr CFStringEncoding encoding = kCFStringEncodingUTF32LE;
-#else
- constexpr CFStringEncoding encoding = kCFStringEncodingUTF32BE;
-#endif
- SkUniqueCFRef<CFStringRef> string(CFStringCreateWithBytes(
- kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(&character), sizeof(character),
- encoding, false));
- // If 0xD800 <= codepoint <= 0xDFFF || 0x10FFFF < codepoint 'string' may be nullptr.
- // No font should be covering such codepoints (even the magic fallback font).
- if (!string) {
- return nullptr;
- }
- CFRange range = CFRangeMake(0, CFStringGetLength(string.get())); // in UniChar units.
- SkUniqueCFRef<CTFontRef> fallbackFont(
- CTFontCreateForString(familyFont.get(), string.get(), range));
- return create_from_CTFontRef(std::move(fallbackFont), OpszVariation(), nullptr).release();
- }
-
- SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
- const SkFontStyle&) const override {
- return nullptr;
- }
-
- sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData> data, int ttcIndex) const override {
- if (ttcIndex != 0) {
- return nullptr;
- }
-
- SkUniqueCFRef<CTFontRef> ct = ctfont_from_skdata(data, ttcIndex);
- if (!ct) {
- return nullptr;
- }
-
- return create_from_CTFontRef(std::move(ct), OpszVariation(),
- SkMemoryStream::Make(std::move(data)));
- }
-
- sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
- int ttcIndex) const override {
- if (ttcIndex != 0) {
- return nullptr;
- }
-
- sk_sp<SkData> data = skdata_from_skstreamasset(stream->duplicate());
- if (!data) {
- return nullptr;
- }
- SkUniqueCFRef<CTFontRef> ct = ctfont_from_skdata(std::move(data), ttcIndex);
- if (!ct) {
- return nullptr;
- }
-
- return create_from_CTFontRef(std::move(ct), OpszVariation(), std::move(stream));
- }
-
- sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
- const SkFontArguments& args) const override
- {
- // TODO: Use CTFontManagerCreateFontDescriptorsFromData when available.
- int ttcIndex = args.getCollectionIndex();
- if (ttcIndex != 0) {
- return nullptr;
- }
-
- sk_sp<SkData> data = skdata_from_skstreamasset(stream->duplicate());
- if (!data) {
- return nullptr;
- }
- SkUniqueCFRef<CTFontRef> ct = ctfont_from_skdata(std::move(data), ttcIndex);
- if (!ct) {
- return nullptr;
- }
-
- CTFontVariation ctVariation = ctvariation_from_skfontarguments(ct.get(), args);
-
- SkUniqueCFRef<CTFontRef> ctVariant;
- if (ctVariation.dict) {
- SkUniqueCFRef<CFMutableDictionaryRef> attributes(
- CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
- CFDictionaryAddValue(attributes.get(),
- kCTFontVariationAttribute, ctVariation.dict.get());
- SkUniqueCFRef<CTFontDescriptorRef> varDesc(
- CTFontDescriptorCreateWithAttributes(attributes.get()));
- ctVariant.reset(CTFontCreateCopyWithAttributes(ct.get(), 0, nullptr, varDesc.get()));
- } else {
- ctVariant.reset(ct.release());
- }
- if (!ctVariant) {
- return nullptr;
- }
-
- return create_from_CTFontRef(std::move(ctVariant), ctVariation.opsz,
- std::move(stream));
- }
-
- sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData> fontData) const override {
- // TODO: Use CTFontManagerCreateFontDescriptorsFromData when available.
- if (fontData->getIndex() != 0) {
- return nullptr;
- }
-
- sk_sp<SkData> data = skdata_from_skstreamasset(fontData->getStream()->duplicate());
- if (!data) {
- return nullptr;
- }
- SkUniqueCFRef<CTFontRef> ct = ctfont_from_skdata(std::move(data), fontData->getIndex());
- if (!ct) {
- return nullptr;
- }
-
- CTFontVariation ctVariation = ctvariation_from_skfontdata(ct.get(), fontData.get());
-
- SkUniqueCFRef<CTFontRef> ctVariant;
- if (ctVariation.dict) {
- SkUniqueCFRef<CFMutableDictionaryRef> attributes(
- CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
- CFDictionaryAddValue(attributes.get(),
- kCTFontVariationAttribute, ctVariation.dict.get());
- SkUniqueCFRef<CTFontDescriptorRef> varDesc(
- CTFontDescriptorCreateWithAttributes(attributes.get()));
- ctVariant.reset(CTFontCreateCopyWithAttributes(ct.get(), 0, nullptr, varDesc.get()));
- } else {
- ctVariant.reset(ct.release());
- }
- if (!ctVariant) {
- return nullptr;
- }
-
- return create_from_CTFontRef(std::move(ctVariant), ctVariation.opsz,
- fontData->detachStream());
- }
-
- sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override {
- if (ttcIndex != 0) {
- return nullptr;
- }
-
- sk_sp<SkData> data = SkData::MakeFromFileName(path);
- if (!data) {
- return nullptr;
- }
-
- return this->onMakeFromData(std::move(data), ttcIndex);
- }
-
- sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const override {
- if (familyName) {
- familyName = map_css_names(familyName);
- }
-
- sk_sp<SkTypeface> face = create_from_name(familyName, style);
- if (face) {
- return face;
- }
-
- static SkTypeface* gDefaultFace;
- static SkOnce lookupDefault;
- static const char FONT_DEFAULT_NAME[] = "Lucida Sans";
- lookupDefault([]{
- gDefaultFace = create_from_name(FONT_DEFAULT_NAME, SkFontStyle()).release();
- });
- return sk_ref_sp(gDefaultFace);
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-sk_sp<SkFontMgr> SkFontMgr::Factory() { return sk_make_sp<SkFontMgr_Mac>(); }
-
-#endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
diff --git a/chromium/third_party/skia/src/ports/SkFontMgr_custom_directory_factory.cpp b/chromium/third_party/skia/src/ports/SkFontMgr_custom_directory_factory.cpp
index 3bb52eb3393..f20b1b5bc47 100644
--- a/chromium/third_party/skia/src/ports/SkFontMgr_custom_directory_factory.cpp
+++ b/chromium/third_party/skia/src/ports/SkFontMgr_custom_directory_factory.cpp
@@ -9,7 +9,11 @@
#include "include/ports/SkFontMgr_directory.h"
#ifndef SK_FONT_FILE_PREFIX
+# if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+# define SK_FONT_FILE_PREFIX "/System/Library/Fonts/"
+# else
# define SK_FONT_FILE_PREFIX "/usr/share/fonts/"
+# endif
#endif
sk_sp<SkFontMgr> SkFontMgr::Factory() {
diff --git a/chromium/third_party/skia/src/ports/SkFontMgr_custom_embedded.cpp b/chromium/third_party/skia/src/ports/SkFontMgr_custom_embedded.cpp
index 924dc5a5628..a9b0f810d31 100644
--- a/chromium/third_party/skia/src/ports/SkFontMgr_custom_embedded.cpp
+++ b/chromium/third_party/skia/src/ports/SkFontMgr_custom_embedded.cpp
@@ -100,7 +100,7 @@ static void load_font_from_data(const SkTypeface_FreeType::Scanner& scanner,
addTo = new SkFontStyleSet_Custom(realname);
families->push_back().reset(addTo);
}
- auto data = std::make_unique<SkFontData>(std::move(stream), faceIndex, nullptr, 0);
+ auto data = std::make_unique<SkFontData>(stream->duplicate(), faceIndex, nullptr, 0);
addTo->appendTypeface(sk_make_sp<SkTypeface_Stream>(std::move(data),
style, isFixedPitch,
true, realname));
diff --git a/chromium/third_party/skia/src/ports/SkFontMgr_mac_ct.cpp b/chromium/third_party/skia/src/ports/SkFontMgr_mac_ct.cpp
new file mode 100644
index 00000000000..c362b160e50
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkFontMgr_mac_ct.cpp
@@ -0,0 +1,669 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkTypes.h"
+#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+
+#ifdef SK_BUILD_FOR_MAC
+#import <ApplicationServices/ApplicationServices.h>
+#endif
+
+#ifdef SK_BUILD_FOR_IOS
+#include <CoreText/CoreText.h>
+#include <CoreText/CTFontManager.h>
+#include <CoreGraphics/CoreGraphics.h>
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+#include "include/core/SkData.h"
+#include "include/core/SkFontArguments.h"
+#include "include/core/SkFontMgr.h"
+#include "include/core/SkFontStyle.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkString.h"
+#include "include/core/SkTypeface.h"
+#include "include/ports/SkFontMgr_mac_ct.h"
+#include "include/private/SkFixed.h"
+#include "include/private/SkOnce.h"
+#include "include/private/SkTemplates.h"
+#include "include/private/SkTo.h"
+#include "src/core/SkFontDescriptor.h"
+#include "src/ports/SkTypeface_mac_ct.h"
+#include "src/utils/SkUTF.h"
+
+#include <string.h>
+#include <memory>
+
+static SkUniqueCFRef<CFStringRef> make_CFString(const char s[]) {
+ return SkUniqueCFRef<CFStringRef>(CFStringCreateWithCString(nullptr, s, kCFStringEncodingUTF8));
+}
+
+/** Creates a typeface from a descriptor, searching the cache. */
+static sk_sp<SkTypeface> create_from_desc(CTFontDescriptorRef desc) {
+ SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr));
+ if (!ctFont) {
+ return nullptr;
+ }
+
+ return SkTypeface_Mac::Make(std::move(ctFont), OpszVariation(), nullptr);
+}
+
+static SkUniqueCFRef<CTFontDescriptorRef> create_descriptor(const char familyName[],
+ const SkFontStyle& style) {
+ SkUniqueCFRef<CFMutableDictionaryRef> cfAttributes(
+ CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ SkUniqueCFRef<CFMutableDictionaryRef> cfTraits(
+ CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ if (!cfAttributes || !cfTraits) {
+ return nullptr;
+ }
+
+ // TODO(crbug.com/1018581) Some CoreText versions have errant behavior when
+ // certain traits set. Temporary workaround to omit specifying trait for
+ // those versions.
+ // Long term solution will involve serializing typefaces instead of relying
+ // upon this to match between processes.
+ //
+ // Compare CoreText.h in an up to date SDK for where these values come from.
+ static const uint32_t kSkiaLocalCTVersionNumber10_14 = 0x000B0000;
+ static const uint32_t kSkiaLocalCTVersionNumber10_15 = 0x000C0000;
+
+ // CTFontTraits (symbolic)
+ // macOS 14 and iOS 12 seem to behave badly when kCTFontSymbolicTrait is set.
+ // macOS 15 yields LastResort font instead of a good default font when
+ // kCTFontSymbolicTrait is set.
+ if (!(&CTGetCoreTextVersion && CTGetCoreTextVersion() >= kSkiaLocalCTVersionNumber10_14)) {
+ CTFontSymbolicTraits ctFontTraits = 0;
+ if (style.weight() >= SkFontStyle::kBold_Weight) {
+ ctFontTraits |= kCTFontBoldTrait;
+ }
+ if (style.slant() != SkFontStyle::kUpright_Slant) {
+ ctFontTraits |= kCTFontItalicTrait;
+ }
+ SkUniqueCFRef<CFNumberRef> cfFontTraits(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits));
+ if (cfFontTraits) {
+ CFDictionaryAddValue(cfTraits.get(), kCTFontSymbolicTrait, cfFontTraits.get());
+ }
+ }
+
+ // CTFontTraits (weight)
+ CGFloat ctWeight = SkCTFontCTWeightForCSSWeight(style.weight());
+ SkUniqueCFRef<CFNumberRef> cfFontWeight(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctWeight));
+ if (cfFontWeight) {
+ CFDictionaryAddValue(cfTraits.get(), kCTFontWeightTrait, cfFontWeight.get());
+ }
+ // CTFontTraits (width)
+ CGFloat ctWidth = SkCTFontCTWidthForCSSWidth(style.width());
+ SkUniqueCFRef<CFNumberRef> cfFontWidth(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctWidth));
+ if (cfFontWidth) {
+ CFDictionaryAddValue(cfTraits.get(), kCTFontWidthTrait, cfFontWidth.get());
+ }
+ // CTFontTraits (slant)
+ // macOS 15 behaves badly when kCTFontSlantTrait is set.
+ if (!(&CTGetCoreTextVersion && CTGetCoreTextVersion() == kSkiaLocalCTVersionNumber10_15)) {
+ CGFloat ctSlant = style.slant() == SkFontStyle::kUpright_Slant ? 0 : 1;
+ SkUniqueCFRef<CFNumberRef> cfFontSlant(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &ctSlant));
+ if (cfFontSlant) {
+ CFDictionaryAddValue(cfTraits.get(), kCTFontSlantTrait, cfFontSlant.get());
+ }
+ }
+ // CTFontTraits
+ CFDictionaryAddValue(cfAttributes.get(), kCTFontTraitsAttribute, cfTraits.get());
+
+ // CTFontFamilyName
+ if (familyName) {
+ SkUniqueCFRef<CFStringRef> cfFontName = make_CFString(familyName);
+ if (cfFontName) {
+ CFDictionaryAddValue(cfAttributes.get(), kCTFontFamilyNameAttribute, cfFontName.get());
+ }
+ }
+
+ return SkUniqueCFRef<CTFontDescriptorRef>(
+ CTFontDescriptorCreateWithAttributes(cfAttributes.get()));
+}
+
+// Same as the above function except style is included so we can
+// compare whether the created font conforms to the style. If not, we need
+// to recreate the font with symbolic traits. This is needed due to MacOS 10.11
+// font creation problem https://bugs.chromium.org/p/skia/issues/detail?id=8447.
+static sk_sp<SkTypeface> create_from_desc_and_style(CTFontDescriptorRef desc,
+ const SkFontStyle& style) {
+ SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr));
+ if (!ctFont) {
+ return nullptr;
+ }
+
+ const CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctFont.get());
+ CTFontSymbolicTraits expected_traits = traits;
+ if (style.slant() != SkFontStyle::kUpright_Slant) {
+ expected_traits |= kCTFontItalicTrait;
+ }
+ if (style.weight() >= SkFontStyle::kBold_Weight) {
+ expected_traits |= kCTFontBoldTrait;
+ }
+
+ if (expected_traits != traits) {
+ SkUniqueCFRef<CTFontRef> ctNewFont(CTFontCreateCopyWithSymbolicTraits(
+ ctFont.get(), 0, nullptr, expected_traits, expected_traits));
+ if (ctNewFont) {
+ ctFont = std::move(ctNewFont);
+ }
+ }
+
+ return SkTypeface_Mac::Make(std::move(ctFont), OpszVariation(), nullptr);
+}
+
+/** Creates a typeface from a name, searching the cache. */
+static sk_sp<SkTypeface> create_from_name(const char familyName[], const SkFontStyle& style) {
+ SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style);
+ if (!desc) {
+ return nullptr;
+ }
+ return create_from_desc_and_style(desc.get(), style);
+}
+
+static const char* map_css_names(const char* name) {
+ static const struct {
+ const char* fFrom; // name the caller specified
+ const char* fTo; // "canonical" name we map to
+ } gPairs[] = {
+ { "sans-serif", "Helvetica" },
+ { "serif", "Times" },
+ { "monospace", "Courier" }
+ };
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
+ if (strcmp(name, gPairs[i].fFrom) == 0) {
+ return gPairs[i].fTo;
+ }
+ }
+ return name; // no change
+}
+
+namespace {
+
+/** Creates a dictionary suitable for setting the axes on a CTFont. */
+static CTFontVariation ctvariation_from_skfontdata(CTFontRef ct, SkFontData* fontData) {
+ // In macOS 10.15 CTFontCreate* overrides any 'opsz' variation with the 'size'.
+ // Track the 'opsz' and return it, since it is an out of band axis.
+ OpszVariation opsz;
+ constexpr const SkFourByteTag opszTag = SkSetFourByteTag('o','p','s','z');
+
+ SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ct));
+ if (!ctAxes) {
+ return CTFontVariation();
+ }
+
+ CFIndex axisCount = CFArrayGetCount(ctAxes.get());
+ if (0 == axisCount || axisCount != fontData->getAxisCount()) {
+ return CTFontVariation();
+ }
+
+ SkUniqueCFRef<CFMutableDictionaryRef> dict(
+ CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ for (int i = 0; i < fontData->getAxisCount(); ++i) {
+ CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
+ if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
+ return CTFontVariation();
+ }
+ CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
+
+ CFTypeRef tag = CFDictionaryGetValue(axisInfoDict,
+ kCTFontVariationAxisIdentifierKey);
+ if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
+ return CTFontVariation();
+ }
+ CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
+ int64_t tagLong;
+ if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
+ return CTFontVariation();
+ }
+
+ // The variation axes can be set to any value, but cg will effectively pin them.
+ // Pin them here to normalize.
+ CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMinimumValueKey);
+ CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMaximumValueKey);
+ if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
+ !max || CFGetTypeID(max) != CFNumberGetTypeID())
+ {
+ return CTFontVariation();
+ }
+ CFNumberRef minNumber = static_cast<CFNumberRef>(min);
+ CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
+ double minDouble;
+ double maxDouble;
+ if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
+ !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble))
+ {
+ return CTFontVariation();
+ }
+ double value = SkTPin(SkFixedToDouble(fontData->getAxis()[i]), minDouble, maxDouble);
+
+ if (tagLong == opszTag) {
+ opsz.isSet = true;
+ opsz.value = value;
+ }
+
+ SkUniqueCFRef<CFNumberRef> valueNumber(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
+ CFDictionaryAddValue(dict.get(), tagNumber, valueNumber.get());
+ }
+ return { SkUniqueCFRef<CFDictionaryRef>(std::move(dict)), opsz };
+}
+
+static sk_sp<SkData> skdata_from_skstreamasset(std::unique_ptr<SkStreamAsset> stream) {
+ size_t size = stream->getLength();
+ if (const void* base = stream->getMemoryBase()) {
+ return SkData::MakeWithProc(base, size,
+ [](const void*, void* ctx) -> void {
+ delete (SkStreamAsset*)ctx;
+ }, stream.release());
+ }
+ return SkData::MakeFromStream(stream.get(), size);
+}
+
+static SkUniqueCFRef<CFDataRef> cfdata_from_skdata(sk_sp<SkData> data) {
+ void const * const addr = data->data();
+ size_t const size = data->size();
+
+ CFAllocatorContext ctx = {
+ 0, // CFIndex version
+ data.release(), // void* info
+ nullptr, // const void *(*retain)(const void *info);
+ nullptr, // void (*release)(const void *info);
+ nullptr, // CFStringRef (*copyDescription)(const void *info);
+ nullptr, // void * (*allocate)(CFIndex size, CFOptionFlags hint, void *info);
+ nullptr, // void*(*reallocate)(void* ptr,CFIndex newsize,CFOptionFlags hint,void* info);
+ [](void*,void* info) -> void { // void (*deallocate)(void *ptr, void *info);
+ SkASSERT(info);
+ ((SkData*)info)->unref();
+ },
+ nullptr, // CFIndex (*preferredSize)(CFIndex size, CFOptionFlags hint, void *info);
+ };
+ SkUniqueCFRef<CFAllocatorRef> alloc(CFAllocatorCreate(kCFAllocatorDefault, &ctx));
+ return SkUniqueCFRef<CFDataRef>(CFDataCreateWithBytesNoCopy(
+ kCFAllocatorDefault, (const UInt8 *)addr, size, alloc.get()));
+}
+
+static SkUniqueCFRef<CTFontRef> ctfont_from_skdata(sk_sp<SkData> data, int ttcIndex) {
+ // TODO: Use CTFontManagerCreateFontDescriptorsFromData when available.
+ if (ttcIndex != 0) {
+ return nullptr;
+ }
+
+ SkUniqueCFRef<CFDataRef> cfData(cfdata_from_skdata(std::move(data)));
+
+ SkUniqueCFRef<CTFontDescriptorRef> desc(
+ CTFontManagerCreateFontDescriptorFromData(cfData.get()));
+ if (!desc) {
+ return nullptr;
+ }
+ return SkUniqueCFRef<CTFontRef>(CTFontCreateWithFontDescriptor(desc.get(), 0, nullptr));
+}
+
+static bool find_desc_str(CTFontDescriptorRef desc, CFStringRef name, SkString* value) {
+ SkUniqueCFRef<CFStringRef> ref((CFStringRef)CTFontDescriptorCopyAttribute(desc, name));
+ if (!ref) {
+ return false;
+ }
+ SkStringFromCFString(ref.get(), value);
+ return true;
+}
+
+static inline int sqr(int value) {
+ SkASSERT(SkAbs32(value) < 0x7FFF); // check for overflow
+ return value * value;
+}
+
+// We normalize each axis (weight, width, italic) to be base-900
+static int compute_metric(const SkFontStyle& a, const SkFontStyle& b) {
+ return sqr(a.weight() - b.weight()) +
+ sqr((a.width() - b.width()) * 100) +
+ sqr((a.slant() != b.slant()) * 900);
+}
+
+class SkFontStyleSet_Mac : public SkFontStyleSet {
+public:
+ SkFontStyleSet_Mac(CTFontDescriptorRef desc)
+ : fArray(CTFontDescriptorCreateMatchingFontDescriptors(desc, nullptr))
+ , fCount(0)
+ {
+ if (!fArray) {
+ fArray.reset(CFArrayCreate(nullptr, nullptr, 0, nullptr));
+ }
+ fCount = SkToInt(CFArrayGetCount(fArray.get()));
+ }
+
+ int count() override {
+ return fCount;
+ }
+
+ void getStyle(int index, SkFontStyle* style, SkString* name) override {
+ SkASSERT((unsigned)index < (unsigned)fCount);
+ CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index);
+ if (style) {
+ *style = SkCTFontDescriptorGetSkFontStyle(desc, false);
+ }
+ if (name) {
+ if (!find_desc_str(desc, kCTFontStyleNameAttribute, name)) {
+ name->reset();
+ }
+ }
+ }
+
+ SkTypeface* createTypeface(int index) override {
+ SkASSERT((unsigned)index < (unsigned)CFArrayGetCount(fArray.get()));
+ CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), index);
+
+ return create_from_desc(desc).release();
+ }
+
+ SkTypeface* matchStyle(const SkFontStyle& pattern) override {
+ if (0 == fCount) {
+ return nullptr;
+ }
+ return create_from_desc(findMatchingDesc(pattern)).release();
+ }
+
+private:
+ SkUniqueCFRef<CFArrayRef> fArray;
+ int fCount;
+
+ CTFontDescriptorRef findMatchingDesc(const SkFontStyle& pattern) const {
+ int bestMetric = SK_MaxS32;
+ CTFontDescriptorRef bestDesc = nullptr;
+
+ for (int i = 0; i < fCount; ++i) {
+ CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray.get(), i);
+ int metric = compute_metric(pattern, SkCTFontDescriptorGetSkFontStyle(desc, false));
+ if (0 == metric) {
+ return desc;
+ }
+ if (metric < bestMetric) {
+ bestMetric = metric;
+ bestDesc = desc;
+ }
+ }
+ SkASSERT(bestDesc);
+ return bestDesc;
+ }
+};
+
+} // namespace
+
+class SkFontMgr_Mac : public SkFontMgr {
+ SkUniqueCFRef<CFArrayRef> fNames;
+ int fCount;
+
+ CFStringRef getFamilyNameAt(int index) const {
+ SkASSERT((unsigned)index < (unsigned)fCount);
+ return (CFStringRef)CFArrayGetValueAtIndex(fNames.get(), index);
+ }
+
+ static SkFontStyleSet* CreateSet(CFStringRef cfFamilyName) {
+ SkUniqueCFRef<CFMutableDictionaryRef> cfAttr(
+ CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ CFDictionaryAddValue(cfAttr.get(), kCTFontFamilyNameAttribute, cfFamilyName);
+
+ SkUniqueCFRef<CTFontDescriptorRef> desc(
+ CTFontDescriptorCreateWithAttributes(cfAttr.get()));
+ return new SkFontStyleSet_Mac(desc.get());
+ }
+
+ /** CTFontManagerCopyAvailableFontFamilyNames() is not always available, so we
+ * provide a wrapper here that will return an empty array if need be.
+ */
+ static SkUniqueCFRef<CFArrayRef> CopyAvailableFontFamilyNames() {
+#ifdef SK_BUILD_FOR_IOS
+ return SkUniqueCFRef<CFArrayRef>(CFArrayCreate(nullptr, nullptr, 0, nullptr));
+#else
+ return SkUniqueCFRef<CFArrayRef>(CTFontManagerCopyAvailableFontFamilyNames());
+#endif
+ }
+
+public:
+ SkUniqueCFRef<CTFontCollectionRef> fFontCollection;
+ SkFontMgr_Mac(CTFontCollectionRef fontCollection)
+ : fNames(CopyAvailableFontFamilyNames())
+ , fCount(fNames ? SkToInt(CFArrayGetCount(fNames.get())) : 0)
+ , fFontCollection(fontCollection ? (CTFontCollectionRef)CFRetain(fontCollection)
+ : CTFontCollectionCreateFromAvailableFonts(nullptr))
+ {}
+
+protected:
+ int onCountFamilies() const override {
+ return fCount;
+ }
+
+ void onGetFamilyName(int index, SkString* familyName) const override {
+ if ((unsigned)index < (unsigned)fCount) {
+ SkStringFromCFString(this->getFamilyNameAt(index), familyName);
+ } else {
+ familyName->reset();
+ }
+ }
+
+ SkFontStyleSet* onCreateStyleSet(int index) const override {
+ if ((unsigned)index >= (unsigned)fCount) {
+ return nullptr;
+ }
+ return CreateSet(this->getFamilyNameAt(index));
+ }
+
+ SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
+ if (!familyName) {
+ return nullptr;
+ }
+ SkUniqueCFRef<CFStringRef> cfName = make_CFString(familyName);
+ return CreateSet(cfName.get());
+ }
+
+ SkTypeface* onMatchFamilyStyle(const char familyName[],
+ const SkFontStyle& style) const override {
+ SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style);
+ return create_from_desc(desc.get()).release();
+ }
+
+ SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
+ const SkFontStyle& style,
+ const char* bcp47[], int bcp47Count,
+ SkUnichar character) const override {
+ SkUniqueCFRef<CTFontDescriptorRef> desc = create_descriptor(familyName, style);
+ SkUniqueCFRef<CTFontRef> familyFont(CTFontCreateWithFontDescriptor(desc.get(), 0, nullptr));
+
+ // kCFStringEncodingUTF32 is BE unless there is a BOM.
+ // Since there is no machine endian option, explicitly state machine endian.
+#ifdef SK_CPU_LENDIAN
+ constexpr CFStringEncoding encoding = kCFStringEncodingUTF32LE;
+#else
+ constexpr CFStringEncoding encoding = kCFStringEncodingUTF32BE;
+#endif
+ SkUniqueCFRef<CFStringRef> string(CFStringCreateWithBytes(
+ kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(&character), sizeof(character),
+ encoding, false));
+ // If 0xD800 <= codepoint <= 0xDFFF || 0x10FFFF < codepoint 'string' may be nullptr.
+ // No font should be covering such codepoints (even the magic fallback font).
+ if (!string) {
+ return nullptr;
+ }
+ CFRange range = CFRangeMake(0, CFStringGetLength(string.get())); // in UniChar units.
+ SkUniqueCFRef<CTFontRef> fallbackFont(
+ CTFontCreateForString(familyFont.get(), string.get(), range));
+ return SkTypeface_Mac::Make(std::move(fallbackFont), OpszVariation(), nullptr).release();
+ }
+
+ SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
+ const SkFontStyle&) const override {
+ return nullptr;
+ }
+
+ sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData> data, int ttcIndex) const override {
+ if (ttcIndex != 0) {
+ return nullptr;
+ }
+
+ SkUniqueCFRef<CTFontRef> ct = ctfont_from_skdata(data, ttcIndex);
+ if (!ct) {
+ return nullptr;
+ }
+
+ return SkTypeface_Mac::Make(std::move(ct), OpszVariation(),
+ SkMemoryStream::Make(std::move(data)));
+ }
+
+ sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
+ int ttcIndex) const override {
+ if (ttcIndex != 0) {
+ return nullptr;
+ }
+
+ sk_sp<SkData> data = skdata_from_skstreamasset(stream->duplicate());
+ if (!data) {
+ return nullptr;
+ }
+ SkUniqueCFRef<CTFontRef> ct = ctfont_from_skdata(std::move(data), ttcIndex);
+ if (!ct) {
+ return nullptr;
+ }
+
+ return SkTypeface_Mac::Make(std::move(ct), OpszVariation(), std::move(stream));
+ }
+
+ sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
+ const SkFontArguments& args) const override
+ {
+ // TODO: Use CTFontManagerCreateFontDescriptorsFromData when available.
+ int ttcIndex = args.getCollectionIndex();
+ if (ttcIndex != 0) {
+ return nullptr;
+ }
+
+ sk_sp<SkData> data = skdata_from_skstreamasset(stream->duplicate());
+ if (!data) {
+ return nullptr;
+ }
+ SkUniqueCFRef<CTFontRef> ct = ctfont_from_skdata(std::move(data), ttcIndex);
+ if (!ct) {
+ return nullptr;
+ }
+
+ CTFontVariation ctVariation = SkCTVariationFromSkFontArguments(ct.get(), args);
+
+ SkUniqueCFRef<CTFontRef> ctVariant;
+ if (ctVariation.dict) {
+ SkUniqueCFRef<CFMutableDictionaryRef> attributes(
+ CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+ CFDictionaryAddValue(attributes.get(),
+ kCTFontVariationAttribute, ctVariation.dict.get());
+ SkUniqueCFRef<CTFontDescriptorRef> varDesc(
+ CTFontDescriptorCreateWithAttributes(attributes.get()));
+ ctVariant.reset(CTFontCreateCopyWithAttributes(ct.get(), 0, nullptr, varDesc.get()));
+ } else {
+ ctVariant.reset(ct.release());
+ }
+ if (!ctVariant) {
+ return nullptr;
+ }
+
+ return SkTypeface_Mac::Make(std::move(ctVariant), ctVariation.opsz, std::move(stream));
+ }
+
+ sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData> fontData) const override {
+ // TODO: Use CTFontManagerCreateFontDescriptorsFromData when available.
+ if (fontData->getIndex() != 0) {
+ return nullptr;
+ }
+
+ sk_sp<SkData> data = skdata_from_skstreamasset(fontData->getStream()->duplicate());
+ if (!data) {
+ return nullptr;
+ }
+ SkUniqueCFRef<CTFontRef> ct = ctfont_from_skdata(std::move(data), fontData->getIndex());
+ if (!ct) {
+ return nullptr;
+ }
+
+ CTFontVariation ctVariation = ctvariation_from_skfontdata(ct.get(), fontData.get());
+
+ SkUniqueCFRef<CTFontRef> ctVariant;
+ if (ctVariation.dict) {
+ SkUniqueCFRef<CFMutableDictionaryRef> attributes(
+ CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+ CFDictionaryAddValue(attributes.get(),
+ kCTFontVariationAttribute, ctVariation.dict.get());
+ SkUniqueCFRef<CTFontDescriptorRef> varDesc(
+ CTFontDescriptorCreateWithAttributes(attributes.get()));
+ ctVariant.reset(CTFontCreateCopyWithAttributes(ct.get(), 0, nullptr, varDesc.get()));
+ } else {
+ ctVariant.reset(ct.release());
+ }
+ if (!ctVariant) {
+ return nullptr;
+ }
+
+ return SkTypeface_Mac::Make(std::move(ctVariant), ctVariation.opsz,
+ fontData->detachStream());
+ }
+
+ sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override {
+ if (ttcIndex != 0) {
+ return nullptr;
+ }
+
+ sk_sp<SkData> data = SkData::MakeFromFileName(path);
+ if (!data) {
+ return nullptr;
+ }
+
+ return this->onMakeFromData(std::move(data), ttcIndex);
+ }
+
+ sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const override {
+ if (familyName) {
+ familyName = map_css_names(familyName);
+ }
+
+ sk_sp<SkTypeface> face = create_from_name(familyName, style);
+ if (face) {
+ return face;
+ }
+
+ static SkTypeface* gDefaultFace;
+ static SkOnce lookupDefault;
+ static const char FONT_DEFAULT_NAME[] = "Lucida Sans";
+ lookupDefault([]{
+ gDefaultFace = create_from_name(FONT_DEFAULT_NAME, SkFontStyle()).release();
+ });
+ return sk_ref_sp(gDefaultFace);
+ }
+};
+
+sk_sp<SkFontMgr> SkFontMgr_New_CoreText(CTFontCollectionRef fontCollection) {
+ return sk_make_sp<SkFontMgr_Mac>(fontCollection);
+}
+
+#endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
diff --git a/chromium/third_party/skia/src/ports/SkFontMgr_mac_ct_factory.cpp b/chromium/third_party/skia/src/ports/SkFontMgr_mac_ct_factory.cpp
new file mode 100644
index 00000000000..ef834e4af28
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkFontMgr_mac_ct_factory.cpp
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkTypes.h"
+#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+
+#include "include/core/SkFontMgr.h"
+#include "include/ports/SkFontMgr_mac_ct.h"
+
+sk_sp<SkFontMgr> SkFontMgr::Factory() {
+ return SkFontMgr_New_CoreText(nullptr);
+}
+
+#endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
diff --git a/chromium/third_party/skia/src/ports/SkGlobalInitialization_default.cpp b/chromium/third_party/skia/src/ports/SkGlobalInitialization_default.cpp
index e277b2c8457..167d94cca1e 100644
--- a/chromium/third_party/skia/src/ports/SkGlobalInitialization_default.cpp
+++ b/chromium/third_party/skia/src/ports/SkGlobalInitialization_default.cpp
@@ -73,8 +73,8 @@
// Color filters.
SkColorFilter_Matrix::RegisterFlattenables();
- SK_REGISTER_FLATTENABLE(SkLumaColorFilter);
- SkColorFilter::RegisterFlattenables();
+ SkLumaColorFilter::RegisterFlattenable();
+ SkColorFilterBase::RegisterFlattenables();
SkHighContrastFilter::RegisterFlattenables();
SkTableColorFilter::RegisterFlattenables();
@@ -96,6 +96,7 @@
SK_REGISTER_FLATTENABLE(SkPath1DPathEffect);
SK_REGISTER_FLATTENABLE(SkPath2DPathEffect);
SK_REGISTER_FLATTENABLE(SkStrokePE);
+ SK_REGISTER_FLATTENABLE(SkStrokeAndFillPE);
SK_REGISTER_FLATTENABLE(SkTrimPE);
SkPathEffect::RegisterFlattenables();
diff --git a/chromium/third_party/skia/src/ports/SkScalerContext_mac_ct.cpp b/chromium/third_party/skia/src/ports/SkScalerContext_mac_ct.cpp
new file mode 100644
index 00000000000..f2f2298fb4d
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkScalerContext_mac_ct.cpp
@@ -0,0 +1,721 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkTypes.h"
+#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+
+#ifdef SK_BUILD_FOR_MAC
+#import <ApplicationServices/ApplicationServices.h>
+#endif
+
+#ifdef SK_BUILD_FOR_IOS
+#include <CoreText/CoreText.h>
+#include <CoreText/CTFontManager.h>
+#include <CoreGraphics/CoreGraphics.h>
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+#include "include/core/SkColor.h"
+#include "include/core/SkColorPriv.h"
+#include "include/core/SkFontMetrics.h"
+#include "include/core/SkFontTypes.h"
+#include "include/core/SkMatrix.h"
+#include "include/core/SkPath.h"
+#include "include/core/SkPoint.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkTypeface.h"
+#include "include/private/SkColorData.h"
+#include "include/private/SkFixed.h"
+#include "include/private/SkTemplates.h"
+#include "include/private/SkTo.h"
+#include "src/core/SkAutoMalloc.h"
+#include "src/core/SkEndian.h"
+#include "src/core/SkGlyph.h"
+#include "src/core/SkMask.h"
+#include "src/core/SkMaskGamma.h"
+#include "src/core/SkMathPriv.h"
+#include "src/core/SkUtils.h"
+#include "src/ports/SkScalerContext_mac_ct.h"
+#include "src/ports/SkTypeface_mac_ct.h"
+#include "src/sfnt/SkOTTableTypes.h"
+#include "src/sfnt/SkOTTable_OS_2.h"
+#include "src/utils/mac/SkCGBase.h"
+#include "src/utils/mac/SkCGGeometry.h"
+#include "src/utils/mac/SkCTFontSmoothBehavior.h"
+#include "src/utils/mac/SkUniqueCFRef.h"
+
+#include <algorithm>
+
+class SkDescriptor;
+
+
+// Set to make glyph bounding boxes visible.
+#define SK_SHOW_TEXT_BLIT_COVERAGE 0
+
+static void sk_memset_rect32(uint32_t* ptr, uint32_t value,
+ int width, int height, size_t rowBytes) {
+ SkASSERT(width);
+ SkASSERT(width * sizeof(uint32_t) <= rowBytes);
+
+ if (width >= 32) {
+ while (height) {
+ sk_memset32(ptr, value, width);
+ ptr = (uint32_t*)((char*)ptr + rowBytes);
+ height -= 1;
+ }
+ return;
+ }
+
+ rowBytes -= width * sizeof(uint32_t);
+
+ if (width >= 8) {
+ while (height) {
+ int w = width;
+ do {
+ *ptr++ = value; *ptr++ = value;
+ *ptr++ = value; *ptr++ = value;
+ *ptr++ = value; *ptr++ = value;
+ *ptr++ = value; *ptr++ = value;
+ w -= 8;
+ } while (w >= 8);
+ while (--w >= 0) {
+ *ptr++ = value;
+ }
+ ptr = (uint32_t*)((char*)ptr + rowBytes);
+ height -= 1;
+ }
+ } else {
+ while (height) {
+ int w = width;
+ do {
+ *ptr++ = value;
+ } while (--w > 0);
+ ptr = (uint32_t*)((char*)ptr + rowBytes);
+ height -= 1;
+ }
+ }
+}
+
+static unsigned CGRGBPixel_getAlpha(CGRGBPixel pixel) {
+ return pixel & 0xFF;
+}
+
+static CGAffineTransform MatrixToCGAffineTransform(const SkMatrix& matrix) {
+ return CGAffineTransformMake( SkScalarToCGFloat(matrix[SkMatrix::kMScaleX]),
+ -SkScalarToCGFloat(matrix[SkMatrix::kMSkewY] ),
+ -SkScalarToCGFloat(matrix[SkMatrix::kMSkewX] ),
+ SkScalarToCGFloat(matrix[SkMatrix::kMScaleY]),
+ SkScalarToCGFloat(matrix[SkMatrix::kMTransX]),
+ SkScalarToCGFloat(matrix[SkMatrix::kMTransY]));
+}
+
+SkScalerContext_Mac::SkScalerContext_Mac(sk_sp<SkTypeface_Mac> typeface,
+ const SkScalerContextEffects& effects,
+ const SkDescriptor* desc)
+ : INHERITED(std::move(typeface), effects, desc)
+ , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag))
+
+{
+ CTFontRef ctFont = (CTFontRef)this->getTypeface()->internal_private_getCTFontRef();
+ CFIndex numGlyphs = CTFontGetGlyphCount(ctFont);
+ SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF);
+ fGlyphCount = SkToU16(numGlyphs);
+
+ // CT on (at least) 10.9 will size color glyphs down from the requested size, but not up.
+ // As a result, it is necessary to know the actual device size and request that.
+ SkVector scale;
+ SkMatrix skTransform;
+ bool invertible = fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale,
+ &scale, &skTransform, nullptr, nullptr, nullptr);
+ fTransform = MatrixToCGAffineTransform(skTransform);
+ // CGAffineTransformInvert documents that if the transform is non-invertible it will return the
+ // passed transform unchanged. It does so, but then also prints a message to stdout. Avoid this.
+ if (invertible) {
+ fInvTransform = CGAffineTransformInvert(fTransform);
+ } else {
+ fInvTransform = fTransform;
+ }
+
+ // The transform contains everything except the requested text size.
+ // Some properties, like 'trak', are based on the optical text size.
+ CGFloat textSize = SkScalarToCGFloat(scale.y());
+ fCTFont = SkCTFontCreateExactCopy(ctFont, textSize,
+ ((SkTypeface_Mac*)this->getTypeface())->fOpszVariation);
+ fCGFont.reset(CTFontCopyGraphicsFont(fCTFont.get(), nullptr));
+}
+
+static int RoundSize(int dimension) {
+ return SkNextPow2(dimension);
+}
+
+CGRGBPixel* SkScalerContext_Mac::Offscreen::getCG(const SkScalerContext_Mac& context,
+ const SkGlyph& glyph, CGGlyph glyphID,
+ size_t* rowBytesPtr,
+ bool generateA8FromLCD) {
+ if (!fRGBSpace) {
+ //It doesn't appear to matter what color space is specified.
+ //Regular blends and antialiased text are always (s*a + d*(1-a))
+ //and subpixel antialiased text is always g=2.0.
+ fRGBSpace.reset(CGColorSpaceCreateDeviceRGB());
+ }
+
+ // default to kBW_Format
+ bool doAA = false;
+ bool doLCD = false;
+
+ if (SkMask::kBW_Format != glyph.maskFormat()) {
+ doLCD = true;
+ doAA = true;
+ }
+
+ // FIXME: lcd smoothed un-hinted rasterization unsupported.
+ if (!generateA8FromLCD && SkMask::kA8_Format == glyph.maskFormat()) {
+ doLCD = false;
+ doAA = true;
+ }
+
+ // If this font might have color glyphs, disable LCD as there's no way to support it.
+ // CoreText doesn't tell us which format it ended up using, so we can't detect it.
+ // A8 will end up black on transparent, but TODO: we can detect gray and set to A8.
+ if (SkMask::kARGB32_Format == glyph.maskFormat()) {
+ doLCD = false;
+ }
+
+ size_t rowBytes = fSize.fWidth * sizeof(CGRGBPixel);
+ if (!fCG || fSize.fWidth < glyph.width() || fSize.fHeight < glyph.height()) {
+ if (fSize.fWidth < glyph.width()) {
+ fSize.fWidth = RoundSize(glyph.width());
+ }
+ if (fSize.fHeight < glyph.height()) {
+ fSize.fHeight = RoundSize(glyph.height());
+ }
+
+ rowBytes = fSize.fWidth * sizeof(CGRGBPixel);
+ void* image = fImageStorage.reset(rowBytes * fSize.fHeight);
+ const CGImageAlphaInfo alpha = (glyph.isColor())
+ ? kCGImageAlphaPremultipliedFirst
+ : kCGImageAlphaNoneSkipFirst;
+ const CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | (CGBitmapInfo)alpha;
+ fCG.reset(CGBitmapContextCreate(image, fSize.fWidth, fSize.fHeight, 8,
+ rowBytes, fRGBSpace.get(), bitmapInfo));
+
+ // Skia handles quantization and subpixel positioning,
+ // so disable quantization and enable subpixel positioning in CG.
+ CGContextSetAllowsFontSubpixelQuantization(fCG.get(), false);
+ CGContextSetShouldSubpixelQuantizeFonts(fCG.get(), false);
+
+ // Because CG always draws from the horizontal baseline,
+ // if there is a non-integral translation from the horizontal origin to the vertical origin,
+ // then CG cannot draw the glyph in the correct location without subpixel positioning.
+ CGContextSetAllowsFontSubpixelPositioning(fCG.get(), true);
+ CGContextSetShouldSubpixelPositionFonts(fCG.get(), true);
+
+ CGContextSetTextDrawingMode(fCG.get(), kCGTextFill);
+
+ // Draw black on white to create mask. (Special path exists to speed this up in CG.)
+ CGContextSetGrayFillColor(fCG.get(), 0.0f, 1.0f);
+
+ // force our checks below to happen
+ fDoAA = !doAA;
+ fDoLCD = !doLCD;
+
+ CGContextSetTextMatrix(fCG.get(), context.fTransform);
+ }
+
+ if (fDoAA != doAA) {
+ CGContextSetShouldAntialias(fCG.get(), doAA);
+ fDoAA = doAA;
+ }
+ if (fDoLCD != doLCD) {
+ CGContextSetShouldSmoothFonts(fCG.get(), doLCD);
+ fDoLCD = doLCD;
+ }
+
+ CGRGBPixel* image = (CGRGBPixel*)fImageStorage.get();
+ // skip rows based on the glyph's height
+ image += (fSize.fHeight - glyph.height()) * fSize.fWidth;
+
+ // Erase to white (or transparent black if it's a color glyph, to not composite against white).
+ uint32_t bgColor = (!glyph.isColor()) ? 0xFFFFFFFF : 0x00000000;
+ sk_memset_rect32(image, bgColor, glyph.width(), glyph.height(), rowBytes);
+
+ float subX = 0;
+ float subY = 0;
+ if (context.fDoSubPosition) {
+ subX = SkFixedToFloat(glyph.getSubXFixed());
+ subY = SkFixedToFloat(glyph.getSubYFixed());
+ }
+
+ CGPoint point = CGPointMake(-glyph.left() + subX, glyph.top() + glyph.height() - subY);
+ // Prior to 10.10, CTFontDrawGlyphs acted like CGContextShowGlyphsAtPositions and took
+ // 'positions' which are in text space. The glyph location (in device space) must be
+ // mapped into text space, so that CG can convert it back into device space.
+ // In 10.10.1, this is handled directly in CTFontDrawGlyphs.
+ //
+ // However, in 10.10.2 color glyphs no longer rotate based on the font transform.
+ // So always make the font transform identity and place the transform on the context.
+ point = CGPointApplyAffineTransform(point, context.fInvTransform);
+
+ CTFontDrawGlyphs(context.fCTFont.get(), &glyphID, &point, 1, fCG.get());
+
+ SkASSERT(rowBytesPtr);
+ *rowBytesPtr = rowBytes;
+ return image;
+}
+
+unsigned SkScalerContext_Mac::generateGlyphCount(void) {
+ return fGlyphCount;
+}
+
+bool SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) {
+ return false;
+}
+
+void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) {
+ glyph->fMaskFormat = fRec.fMaskFormat;
+
+ const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID();
+ glyph->zeroMetrics();
+
+ // The following block produces cgAdvance in CG units (pixels, y up).
+ CGSize cgAdvance;
+ CTFontGetAdvancesForGlyphs(fCTFont.get(), kCTFontOrientationHorizontal,
+ &cgGlyph, &cgAdvance, 1);
+ cgAdvance = CGSizeApplyAffineTransform(cgAdvance, fTransform);
+ glyph->fAdvanceX = SkFloatFromCGFloat(cgAdvance.width);
+ glyph->fAdvanceY = -SkFloatFromCGFloat(cgAdvance.height);
+
+ // The following produces skBounds in SkGlyph units (pixels, y down),
+ // or returns early if skBounds would be empty.
+ SkRect skBounds;
+
+ // Glyphs are always drawn from the horizontal origin. The caller must manually use the result
+ // of CTFontGetVerticalTranslationsForGlyphs to calculate where to draw the glyph for vertical
+ // glyphs. As a result, always get the horizontal bounds of a glyph and translate it if the
+ // glyph is vertical. This avoids any diagreement between the various means of retrieving
+ // vertical metrics.
+ {
+ // CTFontGetBoundingRectsForGlyphs produces cgBounds in CG units (pixels, y up).
+ CGRect cgBounds;
+ CTFontGetBoundingRectsForGlyphs(fCTFont.get(), kCTFontOrientationHorizontal,
+ &cgGlyph, &cgBounds, 1);
+ cgBounds = CGRectApplyAffineTransform(cgBounds, fTransform);
+
+ // BUG?
+ // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when
+ // it should be empty. So, if we see a zero-advance, we check if it has an
+ // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-advance
+ // is rare, so we won't incur a big performance cost for this extra check.
+ if (0 == cgAdvance.width && 0 == cgAdvance.height) {
+ SkUniqueCFRef<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont.get(), cgGlyph,nullptr));
+ if (!path || CGPathIsEmpty(path.get())) {
+ return;
+ }
+ }
+
+ if (SkCGRectIsEmpty(cgBounds)) {
+ return;
+ }
+
+ // Convert cgBounds to SkGlyph units (pixels, y down).
+ skBounds = SkRect::MakeXYWH(cgBounds.origin.x, -cgBounds.origin.y - cgBounds.size.height,
+ cgBounds.size.width, cgBounds.size.height);
+ }
+
+ // Currently the bounds are based on being rendered at (0,0).
+ // The top left must not move, since that is the base from which subpixel positioning is offset.
+ if (fDoSubPosition) {
+ skBounds.fRight += SkFixedToFloat(glyph->getSubXFixed());
+ skBounds.fBottom += SkFixedToFloat(glyph->getSubYFixed());
+ }
+
+ // We're trying to pack left and top into int16_t,
+ // and width and height into uint16_t, after outsetting by 1.
+ if (!SkRect::MakeXYWH(-32767, -32767, 65535, 65535).contains(skBounds)) {
+ return;
+ }
+
+ SkIRect skIBounds;
+ skBounds.roundOut(&skIBounds);
+ // Expand the bounds by 1 pixel, to give CG room for anti-aliasing.
+ // Note that this outset is to allow room for LCD smoothed glyphs. However, the correct outset
+ // is not currently known, as CG dilates the outlines by some percentage.
+ // Note that if this context is A8 and not back-forming from LCD, there is no need to outset.
+ skIBounds.outset(1, 1);
+ glyph->fLeft = SkToS16(skIBounds.fLeft);
+ glyph->fTop = SkToS16(skIBounds.fTop);
+ glyph->fWidth = SkToU16(skIBounds.width());
+ glyph->fHeight = SkToU16(skIBounds.height());
+}
+
+static constexpr uint8_t sk_pow2_table(size_t i) {
+ return SkToU8(((i * i + 128) / 255));
+}
+
+/**
+ * This will invert the gamma applied by CoreGraphics, so we can get linear
+ * values.
+ *
+ * CoreGraphics obscurely defaults to 2.0 as the subpixel coverage gamma value.
+ * The color space used does not appear to affect this choice.
+ */
+static constexpr auto gLinearCoverageFromCGLCDValue = SkMakeArray<256>(sk_pow2_table);
+
+static void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) {
+ while (count > 0) {
+ uint8_t mask = 0;
+ for (int i = 7; i >= 0; --i) {
+ mask |= ((CGRGBPixel_getAlpha(*src++) >> 7) ^ 0x1) << i;
+ if (0 == --count) {
+ break;
+ }
+ }
+ *dst++ = mask;
+ }
+}
+
+template<bool APPLY_PREBLEND>
+static inline uint8_t rgb_to_a8(CGRGBPixel rgb, const uint8_t* table8) {
+ U8CPU r = 0xFF - ((rgb >> 16) & 0xFF);
+ U8CPU g = 0xFF - ((rgb >> 8) & 0xFF);
+ U8CPU b = 0xFF - ((rgb >> 0) & 0xFF);
+ U8CPU lum = sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8);
+#if SK_SHOW_TEXT_BLIT_COVERAGE
+ lum = std::max(lum, (U8CPU)0x30);
+#endif
+ return lum;
+}
+
+template<bool APPLY_PREBLEND>
+static void RGBToA8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes,
+ const SkGlyph& glyph, void* glyphImage, const uint8_t* table8) {
+ const int width = glyph.width();
+ const int height = glyph.height();
+ size_t dstRB = glyph.rowBytes();
+ uint8_t* SK_RESTRICT dst = (uint8_t*)glyphImage;
+
+ for (int y = 0; y < height; y++) {
+ for (int i = 0; i < width; ++i) {
+ dst[i] = rgb_to_a8<APPLY_PREBLEND>(cgPixels[i], table8);
+ }
+ cgPixels = SkTAddOffset<const CGRGBPixel>(cgPixels, cgRowBytes);
+ dst = SkTAddOffset<uint8_t>(dst, dstRB);
+ }
+}
+
+template<bool APPLY_PREBLEND>
+static uint16_t RGBToLcd16(CGRGBPixel rgb,
+ const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
+ U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >> 16) & 0xFF), tableR);
+ U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >> 8) & 0xFF), tableG);
+ U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >> 0) & 0xFF), tableB);
+#if SK_SHOW_TEXT_BLIT_COVERAGE
+ r = std::max(r, (U8CPU)0x30);
+ g = std::max(g, (U8CPU)0x30);
+ b = std::max(b, (U8CPU)0x30);
+#endif
+ return SkPack888ToRGB16(r, g, b);
+}
+
+template<bool APPLY_PREBLEND>
+static void RGBToLcd16(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes,
+ const SkGlyph& glyph, void* glyphImage,
+ const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
+ const int width = glyph.width();
+ const int height = glyph.height();
+ size_t dstRB = glyph.rowBytes();
+ uint16_t* SK_RESTRICT dst = (uint16_t*)glyphImage;
+
+ for (int y = 0; y < height; y++) {
+ for (int i = 0; i < width; i++) {
+ dst[i] = RGBToLcd16<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, tableB);
+ }
+ cgPixels = SkTAddOffset<const CGRGBPixel>(cgPixels, cgRowBytes);
+ dst = SkTAddOffset<uint16_t>(dst, dstRB);
+ }
+}
+
+static SkPMColor cgpixels_to_pmcolor(CGRGBPixel rgb) {
+ U8CPU a = (rgb >> 24) & 0xFF;
+ U8CPU r = (rgb >> 16) & 0xFF;
+ U8CPU g = (rgb >> 8) & 0xFF;
+ U8CPU b = (rgb >> 0) & 0xFF;
+#if SK_SHOW_TEXT_BLIT_COVERAGE
+ a = std::max(a, (U8CPU)0x30);
+#endif
+ return SkPackARGB32(a, r, g, b);
+}
+
+void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
+ CGGlyph cgGlyph = SkTo<CGGlyph>(glyph.getGlyphID());
+
+ // FIXME: lcd smoothed un-hinted rasterization unsupported.
+ bool requestSmooth = fRec.getHinting() != SkFontHinting::kNone;
+
+ // Draw the glyph
+ size_t cgRowBytes;
+ CGRGBPixel* cgPixels = fOffscreen.getCG(*this, glyph, cgGlyph, &cgRowBytes, requestSmooth);
+ if (cgPixels == nullptr) {
+ return;
+ }
+
+ // Fix the glyph
+ if ((glyph.fMaskFormat == SkMask::kLCD16_Format) ||
+ (glyph.fMaskFormat == SkMask::kA8_Format
+ && requestSmooth
+ && SkCTFontGetSmoothBehavior() != SkCTFontSmoothBehavior::none))
+ {
+ const uint8_t* linear = gLinearCoverageFromCGLCDValue.data();
+
+ //Note that the following cannot really be integrated into the
+ //pre-blend, since we may not be applying the pre-blend; when we aren't
+ //applying the pre-blend it means that a filter wants linear anyway.
+ //Other code may also be applying the pre-blend, so we'd need another
+ //one with this and one without.
+ CGRGBPixel* addr = cgPixels;
+ for (int y = 0; y < glyph.fHeight; ++y) {
+ for (int x = 0; x < glyph.fWidth; ++x) {
+ int r = (addr[x] >> 16) & 0xFF;
+ int g = (addr[x] >> 8) & 0xFF;
+ int b = (addr[x] >> 0) & 0xFF;
+ addr[x] = (linear[r] << 16) | (linear[g] << 8) | linear[b];
+ }
+ addr = SkTAddOffset<CGRGBPixel>(addr, cgRowBytes);
+ }
+ }
+
+ // Convert glyph to mask
+ switch (glyph.fMaskFormat) {
+ case SkMask::kLCD16_Format: {
+ if (fPreBlend.isApplicable()) {
+ RGBToLcd16<true>(cgPixels, cgRowBytes, glyph, glyph.fImage,
+ fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+ } else {
+ RGBToLcd16<false>(cgPixels, cgRowBytes, glyph, glyph.fImage,
+ fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+ }
+ } break;
+ case SkMask::kA8_Format: {
+ if (fPreBlend.isApplicable()) {
+ RGBToA8<true>(cgPixels, cgRowBytes, glyph, glyph.fImage, fPreBlend.fG);
+ } else {
+ RGBToA8<false>(cgPixels, cgRowBytes, glyph, glyph.fImage, fPreBlend.fG);
+ }
+ } break;
+ case SkMask::kBW_Format: {
+ const int width = glyph.fWidth;
+ size_t dstRB = glyph.rowBytes();
+ uint8_t* dst = (uint8_t*)glyph.fImage;
+ for (int y = 0; y < glyph.fHeight; y++) {
+ cgpixels_to_bits(dst, cgPixels, width);
+ cgPixels = SkTAddOffset<CGRGBPixel>(cgPixels, cgRowBytes);
+ dst = SkTAddOffset<uint8_t>(dst, dstRB);
+ }
+ } break;
+ case SkMask::kARGB32_Format: {
+ const int width = glyph.fWidth;
+ size_t dstRB = glyph.rowBytes();
+ SkPMColor* dst = (SkPMColor*)glyph.fImage;
+ for (int y = 0; y < glyph.fHeight; y++) {
+ for (int x = 0; x < width; ++x) {
+ dst[x] = cgpixels_to_pmcolor(cgPixels[x]);
+ }
+ cgPixels = SkTAddOffset<CGRGBPixel>(cgPixels, cgRowBytes);
+ dst = SkTAddOffset<SkPMColor>(dst, dstRB);
+ }
+ } break;
+ default:
+ SkDEBUGFAIL("unexpected mask format");
+ break;
+ }
+}
+
+namespace {
+class SkCTPathGeometrySink {
+ SkPath* fPath;
+ bool fStarted;
+ CGPoint fCurrent;
+
+ void goingTo(const CGPoint pt) {
+ if (!fStarted) {
+ fStarted = true;
+ fPath->moveTo(fCurrent.x, -fCurrent.y);
+ }
+ fCurrent = pt;
+ }
+
+ bool currentIsNot(const CGPoint pt) {
+ return fCurrent.x != pt.x || fCurrent.y != pt.y;
+ }
+
+public:
+ SkCTPathGeometrySink(SkPath* path) : fPath{path}, fStarted{false}, fCurrent{0,0} {}
+ static void ApplyElement(void *ctx, const CGPathElement *element) {
+ SkCTPathGeometrySink& self = *(SkCTPathGeometrySink*)ctx;
+ CGPoint* points = element->points;
+
+ switch (element->type) {
+ case kCGPathElementMoveToPoint:
+ self.fStarted = false;
+ self.fCurrent = points[0];
+ break;
+
+ case kCGPathElementAddLineToPoint:
+ if (self.currentIsNot(points[0])) {
+ self.goingTo(points[0]);
+ self.fPath->lineTo(points[0].x, -points[0].y);
+ }
+ break;
+
+ case kCGPathElementAddQuadCurveToPoint:
+ if (self.currentIsNot(points[0]) || self.currentIsNot(points[1])) {
+ self.goingTo(points[1]);
+ self.fPath->quadTo(points[0].x, -points[0].y,
+ points[1].x, -points[1].y);
+ }
+ break;
+
+ case kCGPathElementAddCurveToPoint:
+ if (self.currentIsNot(points[0]) ||
+ self.currentIsNot(points[1]) ||
+ self.currentIsNot(points[2]))
+ {
+ self.goingTo(points[2]);
+ self.fPath->cubicTo(points[0].x, -points[0].y,
+ points[1].x, -points[1].y,
+ points[2].x, -points[2].y);
+ }
+ break;
+
+ case kCGPathElementCloseSubpath:
+ if (self.fStarted) {
+ self.fPath->close();
+ }
+ break;
+
+ default:
+ SkDEBUGFAIL("Unknown path element!");
+ break;
+ }
+ }
+};
+} // namespace
+
+/*
+ * Our subpixel resolution is only 2 bits in each direction, so a scale of 4
+ * seems sufficient, and possibly even correct, to allow the hinted outline
+ * to be subpixel positioned.
+ */
+#define kScaleForSubPixelPositionHinting (4.0f)
+
+bool SkScalerContext_Mac::generatePath(SkGlyphID glyph, SkPath* path) {
+ SkScalar scaleX = SK_Scalar1;
+ SkScalar scaleY = SK_Scalar1;
+
+ CGAffineTransform xform = fTransform;
+ /*
+ * For subpixel positioning, we want to return an unhinted outline, so it
+ * can be positioned nicely at fractional offsets. However, we special-case
+ * if the baseline of the (horizontal) text is axis-aligned. In those cases
+ * we want to retain hinting in the direction orthogonal to the baseline.
+ * e.g. for horizontal baseline, we want to retain hinting in Y.
+ * The way we remove hinting is to scale the font by some value (4) in that
+ * direction, ask for the path, and then scale the path back down.
+ */
+ if (fDoSubPosition) {
+ // start out by assuming that we want no hining in X and Y
+ scaleX = scaleY = kScaleForSubPixelPositionHinting;
+ // now see if we need to restore hinting for axis-aligned baselines
+ switch (this->computeAxisAlignmentForHText()) {
+ case kX_SkAxisAlignment:
+ scaleY = SK_Scalar1; // want hinting in the Y direction
+ break;
+ case kY_SkAxisAlignment:
+ scaleX = SK_Scalar1; // want hinting in the X direction
+ break;
+ default:
+ break;
+ }
+
+ CGAffineTransform scale(CGAffineTransformMakeScale(SkScalarToCGFloat(scaleX),
+ SkScalarToCGFloat(scaleY)));
+ xform = CGAffineTransformConcat(fTransform, scale);
+ }
+
+ CGGlyph cgGlyph = SkTo<CGGlyph>(glyph);
+ SkUniqueCFRef<CGPathRef> cgPath(CTFontCreatePathForGlyph(fCTFont.get(), cgGlyph, &xform));
+
+ path->reset();
+ if (!cgPath) {
+ return false;
+ }
+
+ SkCTPathGeometrySink sink(path);
+ CGPathApply(cgPath.get(), &sink, SkCTPathGeometrySink::ApplyElement);
+ if (fDoSubPosition) {
+ SkMatrix m;
+ m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY));
+ path->transform(m);
+ }
+ return true;
+}
+
+void SkScalerContext_Mac::generateFontMetrics(SkFontMetrics* metrics) {
+ if (nullptr == metrics) {
+ return;
+ }
+
+ CGRect theBounds = CTFontGetBoundingBox(fCTFont.get());
+
+ metrics->fTop = SkScalarFromCGFloat(-SkCGRectGetMaxY(theBounds));
+ metrics->fAscent = SkScalarFromCGFloat(-CTFontGetAscent(fCTFont.get()));
+ metrics->fDescent = SkScalarFromCGFloat( CTFontGetDescent(fCTFont.get()));
+ metrics->fBottom = SkScalarFromCGFloat(-SkCGRectGetMinY(theBounds));
+ metrics->fLeading = SkScalarFromCGFloat( CTFontGetLeading(fCTFont.get()));
+ metrics->fAvgCharWidth = SkScalarFromCGFloat( SkCGRectGetWidth(theBounds));
+ metrics->fXMin = SkScalarFromCGFloat( SkCGRectGetMinX(theBounds));
+ metrics->fXMax = SkScalarFromCGFloat( SkCGRectGetMaxX(theBounds));
+ metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin;
+ metrics->fXHeight = SkScalarFromCGFloat( CTFontGetXHeight(fCTFont.get()));
+ metrics->fCapHeight = SkScalarFromCGFloat( CTFontGetCapHeight(fCTFont.get()));
+ metrics->fUnderlineThickness = SkScalarFromCGFloat( CTFontGetUnderlineThickness(fCTFont.get()));
+ metrics->fUnderlinePosition = -SkScalarFromCGFloat( CTFontGetUnderlinePosition(fCTFont.get()));
+
+ metrics->fFlags = 0;
+ metrics->fFlags |= SkFontMetrics::kUnderlineThicknessIsValid_Flag;
+ metrics->fFlags |= SkFontMetrics::kUnderlinePositionIsValid_Flag;
+
+ // See https://bugs.chromium.org/p/skia/issues/detail?id=6203
+ // At least on 10.12.3 with memory based fonts the x-height is always 0.6666 of the ascent and
+ // the cap-height is always 0.8888 of the ascent. It appears that the values from the 'OS/2'
+ // table are read, but then overwritten if the font is not a system font. As a result, if there
+ // is a valid 'OS/2' table available use the values from the table if they aren't too strange.
+ struct OS2HeightMetrics {
+ SK_OT_SHORT sxHeight;
+ SK_OT_SHORT sCapHeight;
+ } heights;
+ size_t bytesRead = this->getTypeface()->getTableData(
+ SkTEndian_SwapBE32(SkOTTableOS2::TAG), offsetof(SkOTTableOS2, version.v2.sxHeight),
+ sizeof(heights), &heights);
+ if (bytesRead == sizeof(heights)) {
+ // 'fontSize' is correct because the entire resolved size is set by the constructor.
+ CGFloat fontSize = CTFontGetSize(this->fCTFont.get());
+ unsigned upem = CTFontGetUnitsPerEm(this->fCTFont.get());
+ unsigned maxSaneHeight = upem * 2;
+ uint16_t xHeight = SkEndian_SwapBE16(heights.sxHeight);
+ if (xHeight && xHeight < maxSaneHeight) {
+ metrics->fXHeight = SkScalarFromCGFloat(xHeight * fontSize / upem);
+ }
+ uint16_t capHeight = SkEndian_SwapBE16(heights.sCapHeight);
+ if (capHeight && capHeight < maxSaneHeight) {
+ metrics->fCapHeight = SkScalarFromCGFloat(capHeight * fontSize / upem);
+ }
+ }
+}
+
+#endif
diff --git a/chromium/third_party/skia/src/ports/SkScalerContext_mac_ct.h b/chromium/third_party/skia/src/ports/SkScalerContext_mac_ct.h
new file mode 100644
index 00000000000..4b7f548a1ca
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkScalerContext_mac_ct.h
@@ -0,0 +1,118 @@
+/*
+ * 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 SkScalerContext_mac_ct_DEFINED
+#define SkScalerContext_mac_ct_DEFINED
+
+#include "include/core/SkTypes.h"
+#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSize.h"
+#include "src/core/SkAutoMalloc.h"
+#include "src/core/SkScalerContext.h"
+#include "src/utils/mac/SkUniqueCFRef.h"
+
+#ifdef SK_BUILD_FOR_MAC
+#import <ApplicationServices/ApplicationServices.h>
+#endif
+
+#ifdef SK_BUILD_FOR_IOS
+#include <CoreText/CoreText.h>
+#include <CoreText/CTFontManager.h>
+#include <CoreGraphics/CoreGraphics.h>
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+#include <memory>
+
+class SkDescriptor;
+class SkGlyph;
+class SkPath;
+class SkTypeface_Mac;
+struct SkFontMetrics;
+
+
+typedef uint32_t CGRGBPixel;
+
+class SkScalerContext_Mac : public SkScalerContext {
+public:
+ SkScalerContext_Mac(sk_sp<SkTypeface_Mac>, const SkScalerContextEffects&, const SkDescriptor*);
+
+protected:
+ unsigned generateGlyphCount(void) override;
+ bool generateAdvance(SkGlyph* glyph) override;
+ void generateMetrics(SkGlyph* glyph) override;
+ void generateImage(const SkGlyph& glyph) override;
+ bool generatePath(SkGlyphID glyph, SkPath* path) override;
+ void generateFontMetrics(SkFontMetrics*) override;
+
+private:
+ class Offscreen {
+ public:
+ Offscreen()
+ : fRGBSpace(nullptr)
+ , fCG(nullptr)
+ , fDoAA(false)
+ , fDoLCD(false)
+ {
+ fSize.set(0, 0);
+ }
+
+ CGRGBPixel* getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph,
+ CGGlyph glyphID, size_t* rowBytesPtr, bool generateA8FromLCD);
+
+ private:
+ enum {
+ kSize = 32 * 32 * sizeof(CGRGBPixel)
+ };
+ SkAutoSMalloc<kSize> fImageStorage;
+ SkUniqueCFRef<CGColorSpaceRef> fRGBSpace;
+
+ // cached state
+ SkUniqueCFRef<CGContextRef> fCG;
+ SkISize fSize;
+ bool fDoAA;
+ bool fDoLCD;
+ };
+ Offscreen fOffscreen;
+
+ /** Unrotated variant of fCTFont.
+ *
+ * In 10.10.1 CTFontGetAdvancesForGlyphs applies the font transform to the width of the
+ * advances, but always sets the height to 0. This font is used to get the advances of the
+ * unrotated glyph, and then the rotation is applied separately.
+ *
+ * CT vertical metrics are pre-rotated (in em space, before transform) 90deg clock-wise.
+ * This makes kCTFontOrientationDefault dangerous, because the metrics from
+ * kCTFontOrientationHorizontal are in a different space from kCTFontOrientationVertical.
+ * With kCTFontOrientationVertical the advances must be unrotated.
+ *
+ * Sometimes, creating a copy of a CTFont with the same size but different trasform will select
+ * different underlying font data. As a result, avoid ever creating more than one CTFont per
+ * SkScalerContext to ensure that only one CTFont is used.
+ *
+ * As a result of the above (and other constraints) this font contains the size, but not the
+ * transform. The transform must always be applied separately.
+ */
+ SkUniqueCFRef<CTFontRef> fCTFont;
+
+ /** The transform without the font size. */
+ CGAffineTransform fTransform;
+ CGAffineTransform fInvTransform;
+
+ SkUniqueCFRef<CGFontRef> fCGFont;
+ uint16_t fGlyphCount;
+ const bool fDoSubPosition;
+
+ friend class Offscreen;
+
+ typedef SkScalerContext INHERITED;
+};
+
+#endif
+#endif //SkScalerContext_mac_ct_DEFINED
diff --git a/chromium/third_party/skia/src/ports/SkScalerContext_win_dw.cpp b/chromium/third_party/skia/src/ports/SkScalerContext_win_dw.cpp
index b8208907088..f95f6c60ffa 100644
--- a/chromium/third_party/skia/src/ports/SkScalerContext_win_dw.cpp
+++ b/chromium/third_party/skia/src/ports/SkScalerContext_win_dw.cpp
@@ -368,6 +368,15 @@ SkScalerContext_DW::SkScalerContext_DW(sk_sp<DWriteFontTypeface> typefaceRef,
fTextSizeMeasure = realTextSize;
fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
}
+
+ // The GDI measuring modes don't seem to work well with CBDT fonts (DWrite.dll 10.0.18362.836).
+ if (fMeasuringMode != DWRITE_MEASURING_MODE_NATURAL) {
+ constexpr UINT32 CBDTTag = DWRITE_MAKE_OPENTYPE_TAG('C','B','D','T');
+ AutoDWriteTable CBDT(typeface->fDWriteFontFace.get(), CBDTTag);
+ if (CBDT.fExists) {
+ fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
+ }
+ }
}
SkScalerContext_DW::~SkScalerContext_DW() {
diff --git a/chromium/third_party/skia/src/ports/SkTypeface_mac_ct.cpp b/chromium/third_party/skia/src/ports/SkTypeface_mac_ct.cpp
new file mode 100644
index 00000000000..8055f6bcb28
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkTypeface_mac_ct.cpp
@@ -0,0 +1,1470 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkTypes.h"
+#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+
+#ifdef SK_BUILD_FOR_MAC
+#import <ApplicationServices/ApplicationServices.h>
+#endif
+
+#ifdef SK_BUILD_FOR_IOS
+#include <CoreText/CoreText.h>
+#include <CoreText/CTFontManager.h>
+#include <CoreGraphics/CoreGraphics.h>
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+#include "include/core/SkColor.h"
+#include "include/core/SkData.h"
+#include "include/core/SkFontArguments.h"
+#include "include/core/SkFontParameters.h"
+#include "include/core/SkFontStyle.h"
+#include "include/core/SkFontTypes.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkString.h"
+#include "include/core/SkTypeface.h"
+#include "include/ports/SkTypeface_mac.h"
+#include "include/private/SkFixed.h"
+#include "include/private/SkMalloc.h"
+#include "include/private/SkMutex.h"
+#include "include/private/SkOnce.h"
+#include "include/private/SkTDArray.h"
+#include "include/private/SkTemplates.h"
+#include "include/private/SkTo.h"
+#include "src/core/SkAdvancedTypefaceMetrics.h"
+#include "src/core/SkEndian.h"
+#include "src/core/SkFontDescriptor.h"
+#include "src/core/SkMask.h"
+#include "src/core/SkScalerContext.h"
+#include "src/core/SkTypefaceCache.h"
+#include "src/core/SkUtils.h"
+#include "src/ports/SkScalerContext_mac_ct.h"
+#include "src/ports/SkTypeface_mac_ct.h"
+#include "src/sfnt/SkOTTableTypes.h"
+#include "src/sfnt/SkOTTable_OS_2.h"
+#include "src/sfnt/SkOTTable_OS_2_V4.h"
+#include "src/sfnt/SkOTUtils.h"
+#include "src/sfnt/SkSFNTHeader.h"
+#include "src/utils/SkUTF.h"
+#include "src/utils/mac/SkCGBase.h"
+#include "src/utils/mac/SkCGGeometry.h"
+#include "src/utils/mac/SkCTFontSmoothBehavior.h"
+#include "src/utils/mac/SkUniqueCFRef.h"
+
+#include <dlfcn.h>
+#include <limits.h>
+#include <string.h>
+#include <memory>
+
+// In macOS 10.12 and later any variation on the CGFont which has default axis value will be
+// dropped when creating the CTFont. Unfortunately, in macOS 10.15 the priority of setting
+// the optical size (and opsz variation) is
+// 1. the value of kCTFontOpticalSizeAttribute in the CTFontDescriptor (undocumented)
+// 2. the opsz axis default value if kCTFontOpticalSizeAttribute is 'none' (undocumented)
+// 3. the opsz variation on the nascent CTFont from the CGFont (was dropped if default)
+// 4. the opsz variation in kCTFontVariationAttribute in CTFontDescriptor (crashes 10.10)
+// 5. the size requested (can fudge in SkTypeface but not SkScalerContext)
+// The first one which is found will be used to set the opsz variation (after clamping).
+static void add_opsz_attr(CFMutableDictionaryRef attr, double opsz) {
+ SkUniqueCFRef<CFNumberRef> opszValueNumber(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &opsz));
+ // Avoid using kCTFontOpticalSizeAttribute directly
+ CFStringRef SkCTFontOpticalSizeAttribute = CFSTR("NSCTFontOpticalSizeAttribute");
+ CFDictionarySetValue(attr, SkCTFontOpticalSizeAttribute, opszValueNumber.get());
+}
+
+// This turns off application of the 'trak' table to advances, but also all other tracking.
+static void add_notrak_attr(CFMutableDictionaryRef attr) {
+ int zero = 0;
+ SkUniqueCFRef<CFNumberRef> unscaledTrackingNumber(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &zero));
+ CFStringRef SkCTFontUnscaledTrackingAttribute = CFSTR("NSCTFontUnscaledTrackingAttribute");
+ CFDictionarySetValue(attr, SkCTFontUnscaledTrackingAttribute, unscaledTrackingNumber.get());
+}
+
+SkUniqueCFRef<CTFontRef> SkCTFontCreateExactCopy(CTFontRef baseFont, CGFloat textSize,
+ OpszVariation opsz)
+{
+ SkUniqueCFRef<CFMutableDictionaryRef> attr(
+ CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ if (opsz.isSet) {
+ add_opsz_attr(attr.get(), opsz.value);
+#if !defined(SK_IGNORE_MAC_OPSZ_FORCE)
+ } else {
+ // On (at least) 10.10 though 10.14 the default system font was SFNSText/SFNSDisplay.
+ // The CTFont is backed by both; optical size < 20 means SFNSText else SFNSDisplay.
+ // On at least 10.11 the glyph ids in these fonts became non-interchangable.
+ // To keep glyph ids stable over size changes, preserve the optical size.
+ // In 10.15 this was replaced with use of variable fonts with an opsz axis.
+ // A CTFont backed by multiple fonts picked by opsz where the multiple backing fonts are
+ // variable fonts with opsz axis and non-interchangeable glyph ids would break the
+ // opsz.isSet branch above, but hopefully that never happens.
+ // See https://crbug.com/524646 .
+ CFStringRef SkCTFontOpticalSizeAttribute = CFSTR("NSCTFontOpticalSizeAttribute");
+ SkUniqueCFRef<CFTypeRef> opsz(CTFontCopyAttribute(baseFont, SkCTFontOpticalSizeAttribute));
+ double opsz_val;
+ if (!opsz ||
+ CFGetTypeID(opsz.get()) != CFNumberGetTypeID() ||
+ !CFNumberGetValue(static_cast<CFNumberRef>(opsz.get()),kCFNumberDoubleType,&opsz_val) ||
+ opsz_val <= 0)
+ {
+ opsz_val = CTFontGetSize(baseFont);
+ }
+ add_opsz_attr(attr.get(), opsz_val);
+#endif
+ }
+ add_notrak_attr(attr.get());
+
+ SkUniqueCFRef<CTFontDescriptorRef> desc(CTFontDescriptorCreateWithAttributes(attr.get()));
+
+#if !defined(SK_IGNORE_MAC_OPSZ_FORCE)
+ return SkUniqueCFRef<CTFontRef>(
+ CTFontCreateCopyWithAttributes(baseFont, textSize, nullptr, desc.get()));
+#else
+ SkUniqueCFRef<CGFontRef> baseCGFont(CTFontCopyGraphicsFont(baseFont, nullptr));
+ return SkUniqueCFRef<CTFontRef>(
+ CTFontCreateWithGraphicsFont(baseCGFont.get(), textSize, nullptr, desc.get()));
+
+#endif
+}
+
+CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face) {
+ return face ? (CTFontRef)face->internal_private_getCTFontRef() : nullptr;
+}
+
+static bool find_by_CTFontRef(SkTypeface* cached, void* context) {
+ CTFontRef self = (CTFontRef)context;
+ CTFontRef other = (CTFontRef)cached->internal_private_getCTFontRef();
+
+ return CFEqual(self, other);
+}
+
+/** Creates a typeface, searching the cache if isLocalStream is false. */
+sk_sp<SkTypeface> SkTypeface_Mac::Make(SkUniqueCFRef<CTFontRef> font,
+ OpszVariation opszVariation,
+ std::unique_ptr<SkStreamAsset> providedData) {
+ static SkMutex gTFCacheMutex;
+ static SkTypefaceCache gTFCache;
+
+ SkASSERT(font);
+ const bool isFromStream(providedData);
+
+ if (!isFromStream) {
+ SkAutoMutexExclusive ama(gTFCacheMutex);
+ sk_sp<SkTypeface> face = gTFCache.findByProcAndRef(find_by_CTFontRef, (void*)font.get());
+ if (face) {
+ return face;
+ }
+ }
+
+ SkUniqueCFRef<CTFontDescriptorRef> desc(CTFontCopyFontDescriptor(font.get()));
+ SkFontStyle style = SkCTFontDescriptorGetSkFontStyle(desc.get(), isFromStream);
+ CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font.get());
+ bool isFixedPitch = SkToBool(traits & kCTFontMonoSpaceTrait);
+
+ sk_sp<SkTypeface> face(new SkTypeface_Mac(std::move(font), style,
+ isFixedPitch, opszVariation,
+ std::move(providedData)));
+ if (!isFromStream) {
+ SkAutoMutexExclusive ama(gTFCacheMutex);
+ gTFCache.add(face);
+ }
+ return face;
+}
+
+/* This function is visible on the outside. It first searches the cache, and if
+ * not found, returns a new entry (after adding it to the cache).
+ */
+sk_sp<SkTypeface> SkMakeTypefaceFromCTFont(CTFontRef font) {
+ CFRetain(font);
+ return SkTypeface_Mac::Make(SkUniqueCFRef<CTFontRef>(font),
+ OpszVariation(),
+ nullptr);
+}
+
+static bool find_dict_CGFloat(CFDictionaryRef dict, CFStringRef name, CGFloat* value) {
+ CFNumberRef num;
+ return CFDictionaryGetValueIfPresent(dict, name, (const void**)&num)
+ && CFNumberIsFloatType(num)
+ && CFNumberGetValue(num, kCFNumberCGFloatType, value);
+}
+
+template <typename S, typename D, typename C> struct LinearInterpolater {
+ struct Mapping {
+ S src_val;
+ D dst_val;
+ };
+ constexpr LinearInterpolater(Mapping const mapping[], int mappingCount)
+ : fMapping(mapping), fMappingCount(mappingCount) {}
+
+ static D map(S value, S src_min, S src_max, D dst_min, D dst_max) {
+ SkASSERT(src_min < src_max);
+ SkASSERT(dst_min <= dst_max);
+ return C()(dst_min + (((value - src_min) * (dst_max - dst_min)) / (src_max - src_min)));
+ }
+
+ D map(S val) const {
+ // -Inf to [0]
+ if (val < fMapping[0].src_val) {
+ return fMapping[0].dst_val;
+ }
+
+ // Linear from [i] to [i+1]
+ for (int i = 0; i < fMappingCount - 1; ++i) {
+ if (val < fMapping[i+1].src_val) {
+ return map(val, fMapping[i].src_val, fMapping[i+1].src_val,
+ fMapping[i].dst_val, fMapping[i+1].dst_val);
+ }
+ }
+
+ // From [n] to +Inf
+ // if (fcweight < Inf)
+ return fMapping[fMappingCount - 1].dst_val;
+ }
+
+ Mapping const * fMapping;
+ int fMappingCount;
+};
+
+struct RoundCGFloatToInt {
+ int operator()(CGFloat s) { return s + 0.5; }
+};
+struct CGFloatIdentity {
+ CGFloat operator()(CGFloat s) { return s; }
+};
+
+/** Returns the [-1, 1] CTFontDescriptor weights for the
+ * <0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000> CSS weights.
+ *
+ * It is assumed that the values will be interpolated linearly between these points.
+ * NSFontWeightXXX were added in 10.11, appear in 10.10, but do not appear in 10.9.
+ * The actual values appear to be stable, but they may change in the future without notice.
+ */
+static CGFloat(&get_NSFontWeight_mapping())[11] {
+
+ // Declarations in <AppKit/AppKit.h> on macOS, <UIKit/UIKit.h> on iOS
+#ifdef SK_BUILD_FOR_MAC
+# define SK_KIT_FONT_WEIGHT_PREFIX "NS"
+#endif
+#ifdef SK_BUILD_FOR_IOS
+# define SK_KIT_FONT_WEIGHT_PREFIX "UI"
+#endif
+ static constexpr struct {
+ CGFloat defaultValue;
+ const char* name;
+ } nsFontWeightLoaderInfos[] = {
+ { -0.80f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightUltraLight" },
+ { -0.60f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightThin" },
+ { -0.40f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightLight" },
+ { 0.00f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightRegular" },
+ { 0.23f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightMedium" },
+ { 0.30f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightSemibold" },
+ { 0.40f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightBold" },
+ { 0.56f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightHeavy" },
+ { 0.62f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightBlack" },
+ };
+
+ static_assert(SK_ARRAY_COUNT(nsFontWeightLoaderInfos) == 9, "");
+ static CGFloat nsFontWeights[11];
+ static SkOnce once;
+ once([&] {
+ size_t i = 0;
+ nsFontWeights[i++] = -1.00;
+ for (const auto& nsFontWeightLoaderInfo : nsFontWeightLoaderInfos) {
+ void* nsFontWeightValuePtr = dlsym(RTLD_DEFAULT, nsFontWeightLoaderInfo.name);
+ if (nsFontWeightValuePtr) {
+ nsFontWeights[i++] = *(static_cast<CGFloat*>(nsFontWeightValuePtr));
+ } else {
+ nsFontWeights[i++] = nsFontWeightLoaderInfo.defaultValue;
+ }
+ }
+ nsFontWeights[i++] = 1.00;
+ });
+ return nsFontWeights;
+}
+
+/** Convert the [0, 1000] CSS weight to [-1, 1] CTFontDescriptor weight (for system fonts).
+ *
+ * The -1 to 1 weights reported by CTFontDescriptors have different mappings depending on if the
+ * CTFont is native or created from a CGDataProvider.
+ */
+CGFloat SkCTFontCTWeightForCSSWeight(int fontstyleWeight) {
+ using Interpolator = LinearInterpolater<int, CGFloat, CGFloatIdentity>;
+
+ // Note that Mac supports the old OS2 version A so 0 through 10 are as if multiplied by 100.
+ // However, on this end we can't tell, so this is ignored.
+
+ static Interpolator::Mapping nativeWeightMappings[11];
+ static SkOnce once;
+ once([&] {
+ CGFloat(&nsFontWeights)[11] = get_NSFontWeight_mapping();
+ for (int i = 0; i < 11; ++i) {
+ nativeWeightMappings[i].src_val = i * 100;
+ nativeWeightMappings[i].dst_val = nsFontWeights[i];
+ }
+ });
+ static constexpr Interpolator nativeInterpolator(
+ nativeWeightMappings, SK_ARRAY_COUNT(nativeWeightMappings));
+
+ return nativeInterpolator.map(fontstyleWeight);
+}
+
+
+/** Convert the [-1, 1] CTFontDescriptor weight to [0, 1000] CSS weight.
+ *
+ * The -1 to 1 weights reported by CTFontDescriptors have different mappings depending on if the
+ * CTFont is native or created from a CGDataProvider.
+ */
+static int ct_weight_to_fontstyle(CGFloat cgWeight, bool fromDataProvider) {
+ using Interpolator = LinearInterpolater<CGFloat, int, RoundCGFloatToInt>;
+
+ // Note that Mac supports the old OS2 version A so 0 through 10 are as if multiplied by 100.
+ // However, on this end we can't tell, so this is ignored.
+
+ /** This mapping for CGDataProvider created fonts is determined by creating font data with every
+ * weight, creating a CTFont, and asking the CTFont for its weight. See the TypefaceStyle test
+ * in tests/TypefaceTest.cpp for the code used to determine these values.
+ */
+ static constexpr Interpolator::Mapping dataProviderWeightMappings[] = {
+ { -1.00, 0 },
+ { -0.70, 100 },
+ { -0.50, 200 },
+ { -0.23, 300 },
+ { 0.00, 400 },
+ { 0.20, 500 },
+ { 0.30, 600 },
+ { 0.40, 700 },
+ { 0.60, 800 },
+ { 0.80, 900 },
+ { 1.00, 1000 },
+ };
+ static constexpr Interpolator dataProviderInterpolator(
+ dataProviderWeightMappings, SK_ARRAY_COUNT(dataProviderWeightMappings));
+
+ static Interpolator::Mapping nativeWeightMappings[11];
+ static SkOnce once;
+ once([&] {
+ CGFloat(&nsFontWeights)[11] = get_NSFontWeight_mapping();
+ for (int i = 0; i < 11; ++i) {
+ nativeWeightMappings[i].src_val = nsFontWeights[i];
+ nativeWeightMappings[i].dst_val = i * 100;
+ }
+ });
+ static constexpr Interpolator nativeInterpolator(
+ nativeWeightMappings, SK_ARRAY_COUNT(nativeWeightMappings));
+
+ return fromDataProvider ? dataProviderInterpolator.map(cgWeight)
+ : nativeInterpolator.map(cgWeight);
+}
+
+/** Convert the [0, 10] CSS weight to [-1, 1] CTFontDescriptor width. */
+CGFloat SkCTFontCTWidthForCSSWidth(int fontstyleWidth) {
+ using Interpolator = LinearInterpolater<int, CGFloat, CGFloatIdentity>;
+
+ // Values determined by creating font data with every width, creating a CTFont,
+ // and asking the CTFont for its width. See TypefaceStyle test for basics.
+ static constexpr Interpolator::Mapping widthMappings[] = {
+ { 0, -0.5 },
+ { 10, 0.5 },
+ };
+ static constexpr Interpolator interpolator(widthMappings, SK_ARRAY_COUNT(widthMappings));
+ return interpolator.map(fontstyleWidth);
+}
+
+/** Convert the [-1, 1] CTFontDescriptor width to [0, 10] CSS weight. */
+static int ct_width_to_fontstyle(CGFloat cgWidth) {
+ using Interpolator = LinearInterpolater<CGFloat, int, RoundCGFloatToInt>;
+
+ // Values determined by creating font data with every width, creating a CTFont,
+ // and asking the CTFont for its width. See TypefaceStyle test for basics.
+ static constexpr Interpolator::Mapping widthMappings[] = {
+ { -0.5, 0 },
+ { 0.5, 10 },
+ };
+ static constexpr Interpolator interpolator(widthMappings, SK_ARRAY_COUNT(widthMappings));
+ return interpolator.map(cgWidth);
+}
+
+SkFontStyle SkCTFontDescriptorGetSkFontStyle(CTFontDescriptorRef desc, bool fromDataProvider) {
+ SkUniqueCFRef<CFTypeRef> traits(CTFontDescriptorCopyAttribute(desc, kCTFontTraitsAttribute));
+ if (!traits || CFDictionaryGetTypeID() != CFGetTypeID(traits.get())) {
+ return SkFontStyle();
+ }
+ SkUniqueCFRef<CFDictionaryRef> fontTraitsDict(static_cast<CFDictionaryRef>(traits.release()));
+
+ CGFloat weight, width, slant;
+ if (!find_dict_CGFloat(fontTraitsDict.get(), kCTFontWeightTrait, &weight)) {
+ weight = 0;
+ }
+ if (!find_dict_CGFloat(fontTraitsDict.get(), kCTFontWidthTrait, &width)) {
+ width = 0;
+ }
+ if (!find_dict_CGFloat(fontTraitsDict.get(), kCTFontSlantTrait, &slant)) {
+ slant = 0;
+ }
+
+ return SkFontStyle(ct_weight_to_fontstyle(weight, fromDataProvider),
+ ct_width_to_fontstyle(width),
+ slant ? SkFontStyle::kItalic_Slant
+ : SkFontStyle::kUpright_Slant);
+}
+
+
+// Web fonts added to the CTFont registry do not return their character set.
+// Iterate through the font in this case. The existing caller caches the result,
+// so the performance impact isn't too bad.
+static void populate_glyph_to_unicode_slow(CTFontRef ctFont, CFIndex glyphCount,
+ SkUnichar* out) {
+ sk_bzero(out, glyphCount * sizeof(SkUnichar));
+ UniChar unichar = 0;
+ while (glyphCount > 0) {
+ CGGlyph glyph;
+ if (CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) {
+ if (out[glyph] == 0) {
+ out[glyph] = unichar;
+ --glyphCount;
+ }
+ }
+ if (++unichar == 0) {
+ break;
+ }
+ }
+}
+
+static constexpr uint16_t kPlaneSize = 1 << 13;
+
+static void get_plane_glyph_map(const uint8_t* bits,
+ CTFontRef ctFont,
+ CFIndex glyphCount,
+ SkUnichar* glyphToUnicode,
+ uint8_t planeIndex) {
+ SkUnichar planeOrigin = (SkUnichar)planeIndex << 16; // top half of codepoint.
+ for (uint16_t i = 0; i < kPlaneSize; i++) {
+ uint8_t mask = bits[i];
+ if (!mask) {
+ continue;
+ }
+ for (uint8_t j = 0; j < 8; j++) {
+ if (0 == (mask & ((uint8_t)1 << j))) {
+ continue;
+ }
+ uint16_t planeOffset = (i << 3) | j;
+ SkUnichar codepoint = planeOrigin | (SkUnichar)planeOffset;
+ uint16_t utf16[2] = {planeOffset, 0};
+ size_t count = 1;
+ if (planeOrigin != 0) {
+ count = SkUTF::ToUTF16(codepoint, utf16);
+ }
+ CGGlyph glyphs[2] = {0, 0};
+ if (CTFontGetGlyphsForCharacters(ctFont, utf16, glyphs, count)) {
+ SkASSERT(glyphs[1] == 0);
+ SkASSERT(glyphs[0] < glyphCount);
+ // CTFontCopyCharacterSet and CTFontGetGlyphsForCharacters seem to add 'support'
+ // for characters 0x9, 0xA, and 0xD mapping them to the glyph for character 0x20?
+ // Prefer mappings to codepoints at or above 0x20.
+ if (glyphToUnicode[glyphs[0]] < 0x20) {
+ glyphToUnicode[glyphs[0]] = codepoint;
+ }
+ }
+ }
+ }
+}
+// Construct Glyph to Unicode table.
+static void populate_glyph_to_unicode(CTFontRef ctFont, CFIndex glyphCount,
+ SkUnichar* glyphToUnicode) {
+ sk_bzero(glyphToUnicode, sizeof(SkUnichar) * glyphCount);
+ SkUniqueCFRef<CFCharacterSetRef> charSet(CTFontCopyCharacterSet(ctFont));
+ if (!charSet) {
+ populate_glyph_to_unicode_slow(ctFont, glyphCount, glyphToUnicode);
+ return;
+ }
+
+ SkUniqueCFRef<CFDataRef> bitmap(
+ CFCharacterSetCreateBitmapRepresentation(nullptr, charSet.get()));
+ if (!bitmap) {
+ return;
+ }
+ CFIndex dataLength = CFDataGetLength(bitmap.get());
+ if (!dataLength) {
+ return;
+ }
+ SkASSERT(dataLength >= kPlaneSize);
+ const UInt8* bits = CFDataGetBytePtr(bitmap.get());
+
+ get_plane_glyph_map(bits, ctFont, glyphCount, glyphToUnicode, 0);
+ /*
+ A CFData object that specifies the bitmap representation of the Unicode
+ character points the for the new character set. The bitmap representation could
+ contain all the Unicode character range starting from BMP to Plane 16. The
+ first 8KiB (8192 bytes) of the data represent the BMP range. The BMP range 8KiB
+ can be followed by zero to sixteen 8KiB bitmaps, each prepended with the plane
+ index byte. For example, the bitmap representing the BMP and Plane 2 has the
+ size of 16385 bytes (8KiB for BMP, 1 byte index, and a 8KiB bitmap for Plane
+ 2). The plane index byte, in this case, contains the integer value two.
+ */
+
+ if (dataLength <= kPlaneSize) {
+ return;
+ }
+ int extraPlaneCount = (dataLength - kPlaneSize) / (1 + kPlaneSize);
+ SkASSERT(dataLength == kPlaneSize + extraPlaneCount * (1 + kPlaneSize));
+ while (extraPlaneCount-- > 0) {
+ bits += kPlaneSize;
+ uint8_t planeIndex = *bits++;
+ SkASSERT(planeIndex >= 1);
+ SkASSERT(planeIndex <= 16);
+ get_plane_glyph_map(bits, ctFont, glyphCount, glyphToUnicode, planeIndex);
+ }
+}
+
+/** Assumes src and dst are not nullptr. */
+void SkStringFromCFString(CFStringRef src, SkString* dst) {
+ // Reserve enough room for the worst-case string,
+ // plus 1 byte for the trailing null.
+ CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(src),
+ kCFStringEncodingUTF8) + 1;
+ dst->resize(length);
+ CFStringGetCString(src, dst->writable_str(), length, kCFStringEncodingUTF8);
+ // Resize to the actual UTF-8 length used, stripping the null character.
+ dst->resize(strlen(dst->c_str()));
+}
+
+void SkTypeface_Mac::getGlyphToUnicodeMap(SkUnichar* dstArray) const {
+ SkUniqueCFRef<CTFontRef> ctFont =
+ SkCTFontCreateExactCopy(fFontRef.get(), CTFontGetUnitsPerEm(fFontRef.get()),
+ fOpszVariation);
+ CFIndex glyphCount = CTFontGetGlyphCount(ctFont.get());
+ populate_glyph_to_unicode(ctFont.get(), glyphCount, dstArray);
+}
+
+std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface_Mac::onGetAdvancedMetrics() const {
+
+ SkUniqueCFRef<CTFontRef> ctFont =
+ SkCTFontCreateExactCopy(fFontRef.get(), CTFontGetUnitsPerEm(fFontRef.get()),
+ fOpszVariation);
+
+ std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics);
+
+ {
+ SkUniqueCFRef<CFStringRef> fontName(CTFontCopyPostScriptName(ctFont.get()));
+ if (fontName.get()) {
+ SkStringFromCFString(fontName.get(), &info->fPostScriptName);
+ info->fFontName = info->fPostScriptName;
+ }
+ }
+
+ // In 10.10 and earlier, CTFontCopyVariationAxes and CTFontCopyVariation do not work when
+ // applied to fonts which started life with CGFontCreateWithDataProvider (they simply always
+ // return nullptr). As a result, we are limited to CGFontCopyVariationAxes and
+ // CGFontCopyVariations here until support for 10.10 and earlier is removed.
+ SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont.get(), nullptr));
+ if (cgFont) {
+ SkUniqueCFRef<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cgFont.get()));
+ if (cgAxes && CFArrayGetCount(cgAxes.get()) > 0) {
+ info->fFlags |= SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag;
+ }
+ }
+
+ SkOTTableOS2_V4::Type fsType;
+ if (sizeof(fsType) == this->getTableData(SkTEndian_SwapBE32(SkOTTableOS2::TAG),
+ offsetof(SkOTTableOS2_V4, fsType),
+ sizeof(fsType),
+ &fsType)) {
+ SkOTUtils::SetAdvancedTypefaceFlags(fsType, info.get());
+ }
+
+ // If it's not a truetype font, mark it as 'other'. Assume that TrueType
+ // fonts always have both glyf and loca tables. At the least, this is what
+ // sfntly needs to subset the font. CTFontCopyAttribute() does not always
+ // succeed in determining this directly.
+ if (!this->getTableSize('glyf') || !this->getTableSize('loca')) {
+ return info;
+ }
+
+ info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
+ CTFontSymbolicTraits symbolicTraits = CTFontGetSymbolicTraits(ctFont.get());
+ if (symbolicTraits & kCTFontMonoSpaceTrait) {
+ info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
+ }
+ if (symbolicTraits & kCTFontItalicTrait) {
+ info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
+ }
+ CTFontStylisticClass stylisticClass = symbolicTraits & kCTFontClassMaskTrait;
+ if (stylisticClass >= kCTFontOldStyleSerifsClass && stylisticClass <= kCTFontSlabSerifsClass) {
+ info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
+ } else if (stylisticClass & kCTFontScriptsClass) {
+ info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
+ }
+ info->fItalicAngle = (int16_t) CTFontGetSlantAngle(ctFont.get());
+ info->fAscent = (int16_t) CTFontGetAscent(ctFont.get());
+ info->fDescent = (int16_t) CTFontGetDescent(ctFont.get());
+ info->fCapHeight = (int16_t) CTFontGetCapHeight(ctFont.get());
+ CGRect bbox = CTFontGetBoundingBox(ctFont.get());
+
+ SkRect r;
+ r.setLTRB(SkScalarFromCGFloat(SkCGRectGetMinX(bbox)), // Left
+ SkScalarFromCGFloat(SkCGRectGetMaxY(bbox)), // Top
+ SkScalarFromCGFloat(SkCGRectGetMaxX(bbox)), // Right
+ SkScalarFromCGFloat(SkCGRectGetMinY(bbox))); // Bottom
+
+ r.roundOut(&(info->fBBox));
+
+ // Figure out a good guess for StemV - Min width of i, I, !, 1.
+ // This probably isn't very good with an italic font.
+ int16_t min_width = SHRT_MAX;
+ info->fStemV = 0;
+ static const UniChar stem_chars[] = {'i', 'I', '!', '1'};
+ const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]);
+ CGGlyph glyphs[count];
+ CGRect boundingRects[count];
+ if (CTFontGetGlyphsForCharacters(ctFont.get(), stem_chars, glyphs, count)) {
+ CTFontGetBoundingRectsForGlyphs(ctFont.get(), kCTFontOrientationHorizontal,
+ glyphs, boundingRects, count);
+ for (size_t i = 0; i < count; i++) {
+ int16_t width = (int16_t) boundingRects[i].size.width;
+ if (width > 0 && width < min_width) {
+ min_width = width;
+ info->fStemV = min_width;
+ }
+ }
+ }
+ return info;
+}
+
+static SK_SFNT_ULONG get_font_type_tag(CTFontRef ctFont) {
+ SkUniqueCFRef<CFNumberRef> fontFormatRef(
+ static_cast<CFNumberRef>(CTFontCopyAttribute(ctFont, kCTFontFormatAttribute)));
+ if (!fontFormatRef) {
+ return 0;
+ }
+
+ SInt32 fontFormatValue;
+ if (!CFNumberGetValue(fontFormatRef.get(), kCFNumberSInt32Type, &fontFormatValue)) {
+ return 0;
+ }
+
+ switch (fontFormatValue) {
+ case kCTFontFormatOpenTypePostScript:
+ return SkSFNTHeader::fontType_OpenTypeCFF::TAG;
+ case kCTFontFormatOpenTypeTrueType:
+ return SkSFNTHeader::fontType_WindowsTrueType::TAG;
+ case kCTFontFormatTrueType:
+ return SkSFNTHeader::fontType_MacTrueType::TAG;
+ case kCTFontFormatPostScript:
+ return SkSFNTHeader::fontType_PostScript::TAG;
+ case kCTFontFormatBitmap:
+ return SkSFNTHeader::fontType_MacTrueType::TAG;
+ case kCTFontFormatUnrecognized:
+ default:
+ return 0;
+ }
+}
+
+std::unique_ptr<SkStreamAsset> SkTypeface_Mac::onOpenStream(int* ttcIndex) const {
+ *ttcIndex = 0;
+
+ fInitStream([this]{
+ if (fStream) {
+ return;
+ }
+
+ SK_SFNT_ULONG fontType = get_font_type_tag(fFontRef.get());
+
+ // get table tags
+ int numTables = this->countTables();
+ SkTDArray<SkFontTableTag> tableTags;
+ tableTags.setCount(numTables);
+ this->getTableTags(tableTags.begin());
+
+ // CT seems to be unreliable in being able to obtain the type,
+ // even if all we want is the first four bytes of the font resource.
+ // Just the presence of the FontForge 'FFTM' table seems to throw it off.
+ if (fontType == 0) {
+ fontType = SkSFNTHeader::fontType_WindowsTrueType::TAG;
+
+ // see https://skbug.com/7630#c7
+ bool couldBeCFF = false;
+ constexpr SkFontTableTag CFFTag = SkSetFourByteTag('C', 'F', 'F', ' ');
+ constexpr SkFontTableTag CFF2Tag = SkSetFourByteTag('C', 'F', 'F', '2');
+ for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
+ if (CFFTag == tableTags[tableIndex] || CFF2Tag == tableTags[tableIndex]) {
+ couldBeCFF = true;
+ }
+ }
+ if (couldBeCFF) {
+ fontType = SkSFNTHeader::fontType_OpenTypeCFF::TAG;
+ }
+ }
+
+ // Sometimes CoreGraphics incorrectly thinks a font is kCTFontFormatPostScript.
+ // It is exceedingly unlikely that this is the case, so double check
+ // (see https://crbug.com/809763 ).
+ if (fontType == SkSFNTHeader::fontType_PostScript::TAG) {
+ // see if there are any required 'typ1' tables (see Adobe Technical Note #5180)
+ bool couldBeTyp1 = false;
+ constexpr SkFontTableTag TYPE1Tag = SkSetFourByteTag('T', 'Y', 'P', '1');
+ constexpr SkFontTableTag CIDTag = SkSetFourByteTag('C', 'I', 'D', ' ');
+ for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
+ if (TYPE1Tag == tableTags[tableIndex] || CIDTag == tableTags[tableIndex]) {
+ couldBeTyp1 = true;
+ }
+ }
+ if (!couldBeTyp1) {
+ fontType = SkSFNTHeader::fontType_OpenTypeCFF::TAG;
+ }
+ }
+
+ // get the table sizes and accumulate the total size of the font
+ SkTDArray<size_t> tableSizes;
+ size_t totalSize = sizeof(SkSFNTHeader) + sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables;
+ for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
+ size_t tableSize = this->getTableSize(tableTags[tableIndex]);
+ totalSize += (tableSize + 3) & ~3;
+ *tableSizes.append() = tableSize;
+ }
+
+ // reserve memory for stream, and zero it (tables must be zero padded)
+ fStream.reset(new SkMemoryStream(totalSize));
+ char* dataStart = (char*)fStream->getMemoryBase();
+ sk_bzero(dataStart, totalSize);
+ char* dataPtr = dataStart;
+
+ // compute font header entries
+ uint16_t entrySelector = 0;
+ uint16_t searchRange = 1;
+ while (searchRange < numTables >> 1) {
+ entrySelector++;
+ searchRange <<= 1;
+ }
+ searchRange <<= 4;
+ uint16_t rangeShift = (numTables << 4) - searchRange;
+
+ // write font header
+ SkSFNTHeader* header = (SkSFNTHeader*)dataPtr;
+ header->fontType = fontType;
+ header->numTables = SkEndian_SwapBE16(numTables);
+ header->searchRange = SkEndian_SwapBE16(searchRange);
+ header->entrySelector = SkEndian_SwapBE16(entrySelector);
+ header->rangeShift = SkEndian_SwapBE16(rangeShift);
+ dataPtr += sizeof(SkSFNTHeader);
+
+ // write tables
+ SkSFNTHeader::TableDirectoryEntry* entry = (SkSFNTHeader::TableDirectoryEntry*)dataPtr;
+ dataPtr += sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables;
+ for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) {
+ size_t tableSize = tableSizes[tableIndex];
+ this->getTableData(tableTags[tableIndex], 0, tableSize, dataPtr);
+ entry->tag = SkEndian_SwapBE32(tableTags[tableIndex]);
+ entry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum((SK_OT_ULONG*)dataPtr,
+ tableSize));
+ entry->offset = SkEndian_SwapBE32(SkToU32(dataPtr - dataStart));
+ entry->logicalLength = SkEndian_SwapBE32(SkToU32(tableSize));
+
+ dataPtr += (tableSize + 3) & ~3;
+ ++entry;
+ }
+ });
+ return fStream->duplicate();
+}
+
+struct NonDefaultAxesContext {
+ SkFixed* axisValue;
+ CFArrayRef cgAxes;
+};
+static void set_non_default_axes(CFTypeRef key, CFTypeRef value, void* context) {
+ NonDefaultAxesContext* self = static_cast<NonDefaultAxesContext*>(context);
+
+ if (CFGetTypeID(key) != CFStringGetTypeID() || CFGetTypeID(value) != CFNumberGetTypeID()) {
+ return;
+ }
+
+ // The key is a CFString which is a string from the 'name' table.
+ // Search the cgAxes for an axis with this name, and use its index to store the value.
+ CFIndex keyIndex = -1;
+ CFStringRef keyString = static_cast<CFStringRef>(key);
+ for (CFIndex i = 0; i < CFArrayGetCount(self->cgAxes); ++i) {
+ CFTypeRef cgAxis = CFArrayGetValueAtIndex(self->cgAxes, i);
+ if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
+ continue;
+ }
+
+ CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
+ CFTypeRef cgAxisName = CFDictionaryGetValue(cgAxisDict, kCGFontVariationAxisName);
+ if (!cgAxisName || CFGetTypeID(cgAxisName) != CFStringGetTypeID()) {
+ continue;
+ }
+ CFStringRef cgAxisNameString = static_cast<CFStringRef>(cgAxisName);
+ if (CFStringCompare(keyString, cgAxisNameString, 0) == kCFCompareEqualTo) {
+ keyIndex = i;
+ break;
+ }
+ }
+ if (keyIndex == -1) {
+ return;
+ }
+
+ CFNumberRef valueNumber = static_cast<CFNumberRef>(value);
+ double valueDouble;
+ if (!CFNumberGetValue(valueNumber, kCFNumberDoubleType, &valueDouble) ||
+ valueDouble < SkFixedToDouble(SK_FixedMin) || SkFixedToDouble(SK_FixedMax) < valueDouble)
+ {
+ return;
+ }
+ self->axisValue[keyIndex] = SkDoubleToFixed(valueDouble);
+}
+static bool get_variations(CTFontRef ctFont, CFIndex* cgAxisCount,
+ SkAutoSTMalloc<4, SkFixed>* axisValues)
+{
+ // In 10.10 and earlier, CTFontCopyVariationAxes and CTFontCopyVariation do not work when
+ // applied to fonts which started life with CGFontCreateWithDataProvider (they simply always
+ // return nullptr). As a result, we are limited to CGFontCopyVariationAxes and
+ // CGFontCopyVariations here until support for 10.10 and earlier is removed.
+ SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont, nullptr));
+ if (!cgFont) {
+ return false;
+ }
+
+ SkUniqueCFRef<CFDictionaryRef> cgVariations(CGFontCopyVariations(cgFont.get()));
+ // If a font has no variations CGFontCopyVariations returns nullptr (instead of an empty dict).
+ if (!cgVariations) {
+ return false;
+ }
+
+ SkUniqueCFRef<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cgFont.get()));
+ if (!cgAxes) {
+ return false;
+ }
+ *cgAxisCount = CFArrayGetCount(cgAxes.get());
+ axisValues->reset(*cgAxisCount);
+
+ // Set all of the axes to their default values.
+ // Fail if any default value cannot be determined.
+ for (CFIndex i = 0; i < *cgAxisCount; ++i) {
+ CFTypeRef cgAxis = CFArrayGetValueAtIndex(cgAxes.get(), i);
+ if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
+ return false;
+ }
+
+ CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis);
+ CFTypeRef axisDefaultValue = CFDictionaryGetValue(cgAxisDict,
+ kCGFontVariationAxisDefaultValue);
+ if (!axisDefaultValue || CFGetTypeID(axisDefaultValue) != CFNumberGetTypeID()) {
+ return false;
+ }
+ CFNumberRef axisDefaultValueNumber = static_cast<CFNumberRef>(axisDefaultValue);
+ double axisDefaultValueDouble;
+ if (!CFNumberGetValue(axisDefaultValueNumber, kCFNumberDoubleType, &axisDefaultValueDouble))
+ {
+ return false;
+ }
+ if (axisDefaultValueDouble < SkFixedToDouble(SK_FixedMin) ||
+ SkFixedToDouble(SK_FixedMax) < axisDefaultValueDouble)
+ {
+ return false;
+ }
+ (*axisValues)[(int)i] = SkDoubleToFixed(axisDefaultValueDouble);
+ }
+
+ // Override the default values with the given font's stated axis values.
+ NonDefaultAxesContext c = { axisValues->get(), cgAxes.get() };
+ CFDictionaryApplyFunction(cgVariations.get(), set_non_default_axes, &c);
+
+ return true;
+}
+std::unique_ptr<SkFontData> SkTypeface_Mac::onMakeFontData() const {
+ int index;
+ std::unique_ptr<SkStreamAsset> stream(this->onOpenStream(&index));
+
+ CFIndex cgAxisCount;
+ SkAutoSTMalloc<4, SkFixed> axisValues;
+ if (get_variations(fFontRef.get(), &cgAxisCount, &axisValues)) {
+ return std::make_unique<SkFontData>(std::move(stream), index,
+ axisValues.get(), cgAxisCount);
+ }
+ return std::make_unique<SkFontData>(std::move(stream), index, nullptr, 0);
+}
+
+/** Creates a CT variation dictionary {tag, value} from a CG variation dictionary {name, value}. */
+static SkUniqueCFRef<CFDictionaryRef> ct_variation_from_cg_variation(CFDictionaryRef cgVariations,
+ CFArrayRef ctAxes) {
+
+ SkUniqueCFRef<CFMutableDictionaryRef> ctVariation(
+ CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ CFIndex axisCount = CFArrayGetCount(ctAxes);
+ for (CFIndex i = 0; i < axisCount; ++i) {
+ CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes, i);
+ if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
+ return nullptr;
+ }
+ CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
+
+ // The assumption is that values produced by kCTFontVariationAxisNameKey and
+ // kCGFontVariationAxisName will always be equal.
+ CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisNameKey);
+ if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
+ return nullptr;
+ }
+
+ CFTypeRef axisValue = CFDictionaryGetValue(cgVariations, axisName);
+ if (!axisValue || CFGetTypeID(axisValue) != CFNumberGetTypeID()) {
+ return nullptr;
+ }
+
+ CFTypeRef axisTag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
+ if (!axisTag || CFGetTypeID(axisTag) != CFNumberGetTypeID()) {
+ return nullptr;
+ }
+
+ CFDictionaryAddValue(ctVariation.get(), axisTag, axisValue);
+ }
+ return std::move(ctVariation);
+}
+
+int SkTypeface_Mac::onGetVariationDesignPosition(
+ SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
+{
+ // The CGFont variation data does not contain the tag.
+
+ // CTFontCopyVariationAxes returns nullptr for CGFontCreateWithDataProvider fonts with
+ // macOS 10.10 and iOS 9 or earlier. When this happens, there is no API to provide the tag.
+ SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(fFontRef.get()));
+ if (!ctAxes) {
+ return -1;
+ }
+ CFIndex axisCount = CFArrayGetCount(ctAxes.get());
+ if (!coordinates || coordinateCount < axisCount) {
+ return axisCount;
+ }
+
+ // This call always returns nullptr on 10.11 and under for CGFontCreateWithDataProvider fonts.
+ // When this happens, try converting the CG variation to a CT variation.
+ // On 10.12 and later, this only returns non-default variations.
+ SkUniqueCFRef<CFDictionaryRef> ctVariation(CTFontCopyVariation(fFontRef.get()));
+ if (!ctVariation) {
+ // When 10.11 and earlier are no longer supported, the following code can be replaced with
+ // return -1 and ct_variation_from_cg_variation can be removed.
+ SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef.get(), nullptr));
+ if (!cgFont) {
+ return -1;
+ }
+ SkUniqueCFRef<CFDictionaryRef> cgVariations(CGFontCopyVariations(cgFont.get()));
+ if (!cgVariations) {
+ return -1;
+ }
+ ctVariation = ct_variation_from_cg_variation(cgVariations.get(), ctAxes.get());
+ if (!ctVariation) {
+ return -1;
+ }
+ }
+
+ for (int i = 0; i < axisCount; ++i) {
+ CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
+ if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
+ return -1;
+ }
+ CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
+
+ CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
+ if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
+ return -1;
+ }
+ CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
+ int64_t tagLong;
+ if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
+ return -1;
+ }
+ coordinates[i].axis = tagLong;
+
+ CGFloat variationCGFloat;
+ CFTypeRef variationValue = CFDictionaryGetValue(ctVariation.get(), tagNumber);
+ if (variationValue) {
+ if (CFGetTypeID(variationValue) != CFNumberGetTypeID()) {
+ return -1;
+ }
+ CFNumberRef variationNumber = static_cast<CFNumberRef>(variationValue);
+ if (!CFNumberGetValue(variationNumber, kCFNumberCGFloatType, &variationCGFloat)) {
+ return -1;
+ }
+ } else {
+ CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisDefaultValueKey);
+ if (!def || CFGetTypeID(def) != CFNumberGetTypeID()) {
+ return -1;
+ }
+ CFNumberRef defNumber = static_cast<CFNumberRef>(def);
+ if (!CFNumberGetValue(defNumber, kCFNumberCGFloatType, &variationCGFloat)) {
+ return -1;
+ }
+ }
+ coordinates[i].value = SkScalarFromCGFloat(variationCGFloat);
+
+ }
+ return axisCount;
+}
+
+int SkTypeface_Mac::onGetUPEM() const {
+ SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef.get(), nullptr));
+ return CGFontGetUnitsPerEm(cgFont.get());
+}
+
+SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const {
+ sk_sp<SkTypeface::LocalizedStrings> nameIter =
+ SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*this);
+ if (!nameIter) {
+ CFStringRef cfLanguageRaw;
+ SkUniqueCFRef<CFStringRef> cfFamilyName(
+ CTFontCopyLocalizedName(fFontRef.get(), kCTFontFamilyNameKey, &cfLanguageRaw));
+ SkUniqueCFRef<CFStringRef> cfLanguage(cfLanguageRaw);
+
+ SkString skLanguage;
+ SkString skFamilyName;
+ if (cfLanguage) {
+ SkStringFromCFString(cfLanguage.get(), &skLanguage);
+ } else {
+ skLanguage = "und"; //undetermined
+ }
+ if (cfFamilyName) {
+ SkStringFromCFString(cfFamilyName.get(), &skFamilyName);
+ }
+
+ nameIter = sk_make_sp<SkOTUtils::LocalizedStrings_SingleName>(skFamilyName, skLanguage);
+ }
+ return nameIter.release();
+}
+
+int SkTypeface_Mac::onGetTableTags(SkFontTableTag tags[]) const {
+ SkUniqueCFRef<CFArrayRef> cfArray(
+ CTFontCopyAvailableTables(fFontRef.get(), kCTFontTableOptionNoOptions));
+ if (!cfArray) {
+ return 0;
+ }
+ int count = SkToInt(CFArrayGetCount(cfArray.get()));
+ if (tags) {
+ for (int i = 0; i < count; ++i) {
+ uintptr_t fontTag = reinterpret_cast<uintptr_t>(
+ CFArrayGetValueAtIndex(cfArray.get(), i));
+ tags[i] = static_cast<SkFontTableTag>(fontTag);
+ }
+ }
+ return count;
+}
+
+// If, as is the case with web fonts, the CTFont data isn't available,
+// the CGFont data may work. While the CGFont may always provide the
+// right result, leave the CTFont code path to minimize disruption.
+static SkUniqueCFRef<CFDataRef> copy_table_from_font(CTFontRef ctFont, SkFontTableTag tag) {
+ SkUniqueCFRef<CFDataRef> data(CTFontCopyTable(ctFont, (CTFontTableTag) tag,
+ kCTFontTableOptionNoOptions));
+ if (!data) {
+ SkUniqueCFRef<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont, nullptr));
+ data.reset(CGFontCopyTableForTag(cgFont.get(), tag));
+ }
+ return data;
+}
+
+size_t SkTypeface_Mac::onGetTableData(SkFontTableTag tag, size_t offset,
+ size_t length, void* dstData) const {
+ SkUniqueCFRef<CFDataRef> srcData = copy_table_from_font(fFontRef.get(), tag);
+ if (!srcData) {
+ return 0;
+ }
+
+ size_t srcSize = CFDataGetLength(srcData.get());
+ if (offset >= srcSize) {
+ return 0;
+ }
+ if (length > srcSize - offset) {
+ length = srcSize - offset;
+ }
+ if (dstData) {
+ memcpy(dstData, CFDataGetBytePtr(srcData.get()) + offset, length);
+ }
+ return length;
+}
+
+sk_sp<SkData> SkTypeface_Mac::onCopyTableData(SkFontTableTag tag) const {
+ SkUniqueCFRef<CFDataRef> srcData = copy_table_from_font(fFontRef.get(), tag);
+ if (!srcData) {
+ return nullptr;
+ }
+ const UInt8* data = CFDataGetBytePtr(srcData.get());
+ CFIndex length = CFDataGetLength(srcData.get());
+ return SkData::MakeWithProc(data, length,
+ [](const void*, void* ctx) {
+ CFRelease((CFDataRef)ctx);
+ }, (void*)srcData.release());
+}
+
+SkScalerContext* SkTypeface_Mac::onCreateScalerContext(const SkScalerContextEffects& effects,
+ const SkDescriptor* desc) const {
+ return new SkScalerContext_Mac(sk_ref_sp(const_cast<SkTypeface_Mac*>(this)), effects, desc);
+}
+
+void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const {
+ if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
+ rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
+ {
+ rec->fMaskFormat = SkMask::kA8_Format;
+ // Render the glyphs as close as possible to what was requested.
+ // The above turns off subpixel rendering, but the user requested it.
+ // Normal hinting will cause the A8 masks to be generated from CoreGraphics subpixel masks.
+ // See comments below for more details.
+ rec->setHinting(SkFontHinting::kNormal);
+ }
+
+ unsigned flagsWeDontSupport = SkScalerContext::kForceAutohinting_Flag |
+ SkScalerContext::kLCD_BGROrder_Flag |
+ SkScalerContext::kLCD_Vertical_Flag;
+
+ rec->fFlags &= ~flagsWeDontSupport;
+
+ const SkCTFontSmoothBehavior smoothBehavior = SkCTFontGetSmoothBehavior();
+
+ // Only two levels of hinting are supported.
+ // kNo_Hinting means avoid CoreGraphics outline dilation (smoothing).
+ // kNormal_Hinting means CoreGraphics outline dilation (smoothing) is allowed.
+ if (rec->getHinting() != SkFontHinting::kNone) {
+ rec->setHinting(SkFontHinting::kNormal);
+ }
+ // If smoothing has no effect, don't request it.
+ if (smoothBehavior == SkCTFontSmoothBehavior::none) {
+ rec->setHinting(SkFontHinting::kNone);
+ }
+
+ // FIXME: lcd smoothed un-hinted rasterization unsupported.
+ // Tracked by http://code.google.com/p/skia/issues/detail?id=915 .
+ // There is no current means to honor a request for unhinted lcd,
+ // so arbitrarilly ignore the hinting request and honor lcd.
+
+ // Hinting and smoothing should be orthogonal, but currently they are not.
+ // CoreGraphics has no API to influence hinting. However, its lcd smoothed
+ // output is drawn from auto-dilated outlines (the amount of which is
+ // determined by AppleFontSmoothing). Its regular anti-aliased output is
+ // drawn from un-dilated outlines.
+
+ // The behavior of Skia is as follows:
+ // [AA][no-hint]: generate AA using CoreGraphic's AA output.
+ // [AA][yes-hint]: use CoreGraphic's LCD output and reduce it to a single
+ // channel. This matches [LCD][yes-hint] in weight.
+ // [LCD][no-hint]: currently unable to honor, and must pick which to respect.
+ // Currently side with LCD, effectively ignoring the hinting setting.
+ // [LCD][yes-hint]: generate LCD using CoreGraphic's LCD output.
+ if (rec->fMaskFormat == SkMask::kLCD16_Format) {
+ if (smoothBehavior == SkCTFontSmoothBehavior::subpixel) {
+ //CoreGraphics creates 555 masks for smoothed text anyway.
+ rec->fMaskFormat = SkMask::kLCD16_Format;
+ rec->setHinting(SkFontHinting::kNormal);
+ } else {
+ rec->fMaskFormat = SkMask::kA8_Format;
+ if (smoothBehavior != SkCTFontSmoothBehavior::none) {
+ rec->setHinting(SkFontHinting::kNormal);
+ }
+ }
+ }
+
+ // CoreText provides no information as to whether a glyph will be color or not.
+ // Fonts may mix outlines and bitmaps, so information is needed on a glyph by glyph basis.
+ // If a font contains an 'sbix' table, consider it to be a color font, and disable lcd.
+ if (fHasColorGlyphs) {
+ rec->fMaskFormat = SkMask::kARGB32_Format;
+ }
+
+ // Unhinted A8 masks (those not derived from LCD masks) must respect SK_GAMMA_APPLY_TO_A8.
+ // All other masks can use regular gamma.
+ if (SkMask::kA8_Format == rec->fMaskFormat && SkFontHinting::kNone == rec->getHinting()) {
+#ifndef SK_GAMMA_APPLY_TO_A8
+ // SRGBTODO: Is this correct? Do we want contrast boost?
+ rec->ignorePreBlend();
+#endif
+ } else {
+ SkColor color = rec->getLuminanceColor();
+ if (smoothBehavior == SkCTFontSmoothBehavior::some) {
+ // CoreGraphics smoothed text without subpixel coverage blitting goes from a gamma of
+ // 2.0 for black foreground to a gamma of 1.0 for white foreground. Emulate this
+ // through the mask gamma by reducing the color values to 1/2.
+ color = SkColorSetRGB(SkColorGetR(color) * 1/2,
+ SkColorGetG(color) * 1/2,
+ SkColorGetB(color) * 1/2);
+ } else if (smoothBehavior == SkCTFontSmoothBehavior::subpixel) {
+ // CoreGraphics smoothed text with subpixel coverage blitting goes from a gamma of
+ // 2.0 for black foreground to a gamma of ~1.4? for white foreground. Emulate this
+ // through the mask gamma by reducing the color values to 3/4.
+ color = SkColorSetRGB(SkColorGetR(color) * 3/4,
+ SkColorGetG(color) * 3/4,
+ SkColorGetB(color) * 3/4);
+ }
+ rec->setLuminanceColor(color);
+
+ // CoreGraphics dialates smoothed text to provide contrast.
+ rec->setContrast(0);
+ }
+}
+
+/** Takes ownership of the CFStringRef. */
+static const char* get_str(CFStringRef ref, SkString* str) {
+ if (nullptr == ref) {
+ return nullptr;
+ }
+ SkStringFromCFString(ref, str);
+ CFRelease(ref);
+ return str->c_str();
+}
+
+void SkTypeface_Mac::onGetFamilyName(SkString* familyName) const {
+ get_str(CTFontCopyFamilyName(fFontRef.get()), familyName);
+}
+
+void SkTypeface_Mac::onGetFontDescriptor(SkFontDescriptor* desc,
+ bool* isLocalStream) const {
+ SkString tmpStr;
+
+ desc->setFamilyName(get_str(CTFontCopyFamilyName(fFontRef.get()), &tmpStr));
+ desc->setFullName(get_str(CTFontCopyFullName(fFontRef.get()), &tmpStr));
+ desc->setPostscriptName(get_str(CTFontCopyPostScriptName(fFontRef.get()), &tmpStr));
+ desc->setStyle(this->fontStyle());
+ *isLocalStream = fIsFromStream;
+}
+
+void SkTypeface_Mac::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
+ // Undocumented behavior of CTFontGetGlyphsForCharacters with non-bmp code points:
+ // When a surrogate pair is detected, the glyph index used is the index of the high surrogate.
+ // It is documented that if a mapping is unavailable, the glyph will be set to 0.
+
+ SkAutoSTMalloc<1024, UniChar> charStorage;
+ const UniChar* src; // UniChar is a UTF-16 16-bit code unit.
+ int srcCount;
+ const SkUnichar* utf32 = reinterpret_cast<const SkUnichar*>(uni);
+ UniChar* utf16 = charStorage.reset(2 * count);
+ src = utf16;
+ for (int i = 0; i < count; ++i) {
+ utf16 += SkUTF::ToUTF16(utf32[i], utf16);
+ }
+ srcCount = SkToInt(utf16 - src);
+
+ // If there are any non-bmp code points, the provided 'glyphs' storage will be inadequate.
+ SkAutoSTMalloc<1024, uint16_t> glyphStorage;
+ uint16_t* macGlyphs = glyphs;
+ if (srcCount > count) {
+ macGlyphs = glyphStorage.reset(srcCount);
+ }
+
+ CTFontGetGlyphsForCharacters(fFontRef.get(), src, macGlyphs, srcCount);
+
+ // If there were any non-bmp, then copy and compact.
+ // If all are bmp, 'glyphs' already contains the compact glyphs.
+ // If some are non-bmp, copy and compact into 'glyphs'.
+ if (srcCount > count) {
+ SkASSERT(glyphs != macGlyphs);
+ int extra = 0;
+ for (int i = 0; i < count; ++i) {
+ glyphs[i] = macGlyphs[i + extra];
+ if (SkUTF16_IsLeadingSurrogate(src[i + extra])) {
+ ++extra;
+ }
+ }
+ } else {
+ SkASSERT(glyphs == macGlyphs);
+ }
+}
+
+int SkTypeface_Mac::onCountGlyphs() const {
+ return SkToInt(CTFontGetGlyphCount(fFontRef.get()));
+}
+
+/** Creates a dictionary suitable for setting the axes on a CTFont. */
+CTFontVariation SkCTVariationFromSkFontArguments(CTFontRef ct, const SkFontArguments& args) {
+ OpszVariation opsz;
+ constexpr const SkFourByteTag opszTag = SkSetFourByteTag('o','p','s','z');
+
+ SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ct));
+ if (!ctAxes) {
+ return CTFontVariation();
+ }
+ CFIndex axisCount = CFArrayGetCount(ctAxes.get());
+
+ const SkFontArguments::VariationPosition position = args.getVariationDesignPosition();
+
+ SkUniqueCFRef<CFMutableDictionaryRef> dict(
+ CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ for (int i = 0; i < axisCount; ++i) {
+ CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
+ if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
+ return CTFontVariation();
+ }
+ CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
+
+ CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
+ if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
+ return CTFontVariation();
+ }
+ CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
+ int64_t tagLong;
+ if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
+ return CTFontVariation();
+ }
+
+ // The variation axes can be set to any value, but cg will effectively pin them.
+ // Pin them here to normalize.
+ CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMinimumValueKey);
+ CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMaximumValueKey);
+ CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisDefaultValueKey);
+ if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
+ !max || CFGetTypeID(max) != CFNumberGetTypeID() ||
+ !def || CFGetTypeID(def) != CFNumberGetTypeID())
+ {
+ return CTFontVariation();
+ }
+ CFNumberRef minNumber = static_cast<CFNumberRef>(min);
+ CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
+ CFNumberRef defNumber = static_cast<CFNumberRef>(def);
+ double minDouble;
+ double maxDouble;
+ double defDouble;
+ if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
+ !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble) ||
+ !CFNumberGetValue(defNumber, kCFNumberDoubleType, &defDouble))
+ {
+ return CTFontVariation();
+ }
+
+ double value = defDouble;
+ // The position may be over specified. If there are multiple values for a given axis,
+ // use the last one since that's what css-fonts-4 requires.
+ for (int j = position.coordinateCount; j --> 0;) {
+ if (position.coordinates[j].axis == tagLong) {
+ value = SkTPin(SkScalarToDouble(position.coordinates[j].value),
+ minDouble, maxDouble);
+ if (tagLong == opszTag) {
+ opsz.isSet = true;
+ }
+ break;
+ }
+ }
+ if (tagLong == opszTag) {
+ opsz.value = value;
+ }
+ SkUniqueCFRef<CFNumberRef> valueNumber(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
+ CFDictionaryAddValue(dict.get(), tagNumber, valueNumber.get());
+ }
+ return { SkUniqueCFRef<CFDictionaryRef>(std::move(dict)), opsz };
+}
+
+sk_sp<SkTypeface> SkTypeface_Mac::onMakeClone(const SkFontArguments& args) const {
+ CTFontVariation ctVariation = SkCTVariationFromSkFontArguments(fFontRef.get(), args);
+
+ SkUniqueCFRef<CTFontRef> ctVariant;
+ if (ctVariation.dict) {
+ SkUniqueCFRef<CFMutableDictionaryRef> attributes(
+ CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+ CFDictionaryAddValue(attributes.get(),
+ kCTFontVariationAttribute, ctVariation.dict.get());
+ SkUniqueCFRef<CTFontDescriptorRef> varDesc(
+ CTFontDescriptorCreateWithAttributes(attributes.get()));
+ ctVariant.reset(CTFontCreateCopyWithAttributes(fFontRef.get(), 0, nullptr, varDesc.get()));
+ } else {
+ ctVariant.reset((CTFontRef)CFRetain(fFontRef.get()));
+ }
+ if (!ctVariant) {
+ return nullptr;
+ }
+
+ return SkTypeface_Mac::Make(std::move(ctVariant), ctVariation.opsz,
+ fStream ? fStream->duplicate() : nullptr);
+}
+
+int SkTypeface_Mac::onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
+ int parameterCount) const
+{
+ SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(fFontRef.get()));
+ if (!ctAxes) {
+ return -1;
+ }
+ CFIndex axisCount = CFArrayGetCount(ctAxes.get());
+
+ if (!parameters || parameterCount < axisCount) {
+ return axisCount;
+ }
+
+ // Added in 10.13
+ CFStringRef* kCTFontVariationAxisHiddenKeyPtr =
+ static_cast<CFStringRef*>(dlsym(RTLD_DEFAULT, "kCTFontVariationAxisHiddenKey"));
+
+ for (int i = 0; i < axisCount; ++i) {
+ CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
+ if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
+ return -1;
+ }
+ CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
+
+ CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
+ if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
+ return -1;
+ }
+ CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
+ int64_t tagLong;
+ if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
+ return -1;
+ }
+
+ CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMinimumValueKey);
+ CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMaximumValueKey);
+ CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisDefaultValueKey);
+ if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
+ !max || CFGetTypeID(max) != CFNumberGetTypeID() ||
+ !def || CFGetTypeID(def) != CFNumberGetTypeID())
+ {
+ return -1;
+ }
+ CFNumberRef minNumber = static_cast<CFNumberRef>(min);
+ CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
+ CFNumberRef defNumber = static_cast<CFNumberRef>(def);
+ double minDouble;
+ double maxDouble;
+ double defDouble;
+ if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
+ !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble) ||
+ !CFNumberGetValue(defNumber, kCFNumberDoubleType, &defDouble))
+ {
+ return -1;
+ }
+
+ SkFontParameters::Variation::Axis& skAxis = parameters[i];
+ skAxis.tag = tagLong;
+ skAxis.min = minDouble;
+ skAxis.max = maxDouble;
+ skAxis.def = defDouble;
+ skAxis.setHidden(false);
+ if (kCTFontVariationAxisHiddenKeyPtr) {
+ CFTypeRef hidden = CFDictionaryGetValue(axisInfoDict,*kCTFontVariationAxisHiddenKeyPtr);
+ if (hidden) {
+ if (CFGetTypeID(hidden) != CFBooleanGetTypeID()) {
+ return -1;
+ }
+ CFBooleanRef hiddenBoolean = static_cast<CFBooleanRef>(hidden);
+ skAxis.setHidden(CFBooleanGetValue(hiddenBoolean));
+ }
+ }
+ }
+ return axisCount;
+}
+
+#endif
diff --git a/chromium/third_party/skia/src/ports/SkTypeface_mac_ct.h b/chromium/third_party/skia/src/ports/SkTypeface_mac_ct.h
new file mode 100644
index 00000000000..49f55b384f3
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkTypeface_mac_ct.h
@@ -0,0 +1,128 @@
+/*
+ * 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 SkTypeface_mac_ct_DEFINED
+#define SkTypeface_mac_ct_DEFINED
+
+#include "include/core/SkTypes.h"
+#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+
+#include "include/core/SkFontArguments.h"
+#include "include/core/SkFontParameters.h"
+#include "include/core/SkFontStyle.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkTypeface.h"
+#include "include/private/SkOnce.h"
+#include "src/utils/mac/SkUniqueCFRef.h"
+
+#ifdef SK_BUILD_FOR_MAC
+#import <ApplicationServices/ApplicationServices.h>
+#endif
+
+#ifdef SK_BUILD_FOR_IOS
+#include <CoreText/CoreText.h>
+#include <CoreText/CTFontManager.h>
+#include <CoreGraphics/CoreGraphics.h>
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+#include <memory>
+
+class SkData;
+class SkDescriptor;
+class SkFontData;
+class SkFontDescriptor;
+class SkScalerContext;
+class SkString;
+struct SkAdvancedTypefaceMetrics;
+struct SkScalerContextEffects;
+struct SkScalerContextRec;
+
+struct OpszVariation {
+ bool isSet = false;
+ double value = 0;
+};
+
+struct CTFontVariation {
+ SkUniqueCFRef<CFDictionaryRef> dict;
+ OpszVariation opsz;
+};
+
+CTFontVariation SkCTVariationFromSkFontArguments(CTFontRef ct, const SkFontArguments& args);
+
+SkUniqueCFRef<CTFontRef> SkCTFontCreateExactCopy(CTFontRef baseFont, CGFloat textSize,
+ OpszVariation opsz);
+
+SkFontStyle SkCTFontDescriptorGetSkFontStyle(CTFontDescriptorRef desc, bool fromDataProvider);
+
+CGFloat SkCTFontCTWeightForCSSWeight(int fontstyleWeight);
+CGFloat SkCTFontCTWidthForCSSWidth(int fontstyleWidth);
+
+void SkStringFromCFString(CFStringRef src, SkString* dst);
+
+class SkTypeface_Mac : public SkTypeface {
+private:
+ SkTypeface_Mac(SkUniqueCFRef<CTFontRef> fontRef, const SkFontStyle& fs, bool isFixedPitch,
+ OpszVariation opszVariation, std::unique_ptr<SkStreamAsset> providedData)
+ : SkTypeface(fs, isFixedPitch)
+ , fFontRef(std::move(fontRef))
+ , fOpszVariation(opszVariation)
+ , fHasColorGlyphs(
+ SkToBool(CTFontGetSymbolicTraits(fFontRef.get()) & kCTFontColorGlyphsTrait))
+ , fStream(std::move(providedData))
+ , fIsFromStream(fStream)
+ {
+ SkASSERT(fFontRef);
+ }
+
+public:
+ static sk_sp<SkTypeface> Make(SkUniqueCFRef<CTFontRef> font,
+ OpszVariation opszVariation,
+ std::unique_ptr<SkStreamAsset> providedData);
+
+ SkUniqueCFRef<CTFontRef> fFontRef;
+ const OpszVariation fOpszVariation;
+ const bool fHasColorGlyphs;
+
+protected:
+ int onGetUPEM() const override;
+ std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override;
+ std::unique_ptr<SkFontData> onMakeFontData() const override;
+ int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
+ int coordinateCount) const override;
+ void onGetFamilyName(SkString* familyName) const override;
+ SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
+ int onGetTableTags(SkFontTableTag tags[]) const override;
+ size_t onGetTableData(SkFontTableTag, size_t offset, size_t length, void* data) const override;
+ sk_sp<SkData> onCopyTableData(SkFontTableTag) const override;
+ SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
+ const SkDescriptor*) const override;
+ void onFilterRec(SkScalerContextRec*) const override;
+ void onGetFontDescriptor(SkFontDescriptor*, bool*) const override;
+ void getGlyphToUnicodeMap(SkUnichar*) const override;
+ std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override;
+ void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override;
+ int onCountGlyphs() const override;
+ void getPostScriptGlyphNames(SkString*) const override {}
+ int onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
+ int parameterCount) const override;
+ sk_sp<SkTypeface> onMakeClone(const SkFontArguments&) const override;
+
+ void* onGetCTFontRef() const override { return (void*)fFontRef.get(); }
+
+private:
+ mutable std::unique_ptr<SkStreamAsset> fStream;
+ bool fIsFromStream;
+ mutable SkOnce fInitStream;
+
+ typedef SkTypeface INHERITED;
+};
+
+#endif
+#endif //SkTypeface_mac_ct_DEFINED
diff --git a/chromium/third_party/skia/src/sfnt/SkOTTable_name.cpp b/chromium/third_party/skia/src/sfnt/SkOTTable_name.cpp
index c9d47b8f82e..ecb3ce4bdd8 100644
--- a/chromium/third_party/skia/src/sfnt/SkOTTable_name.cpp
+++ b/chromium/third_party/skia/src/sfnt/SkOTTable_name.cpp
@@ -506,6 +506,7 @@ bool SkOTTableName::Iterator::next(SkOTTableName::Iterator::Record& record) {
record.name.reset();
break; // continue?
}
+ [[fallthrough]];
case SkOTTableName::Record::PlatformID::Unicode:
case SkOTTableName::Record::PlatformID::ISO:
SkString_from_UTF16BE(nameString, nameLength, record.name);
diff --git a/chromium/third_party/skia/src/shaders/SkColorFilterShader.cpp b/chromium/third_party/skia/src/shaders/SkColorFilterShader.cpp
index 6b39bc67b7a..c3cf2444a66 100644
--- a/chromium/third_party/skia/src/shaders/SkColorFilterShader.cpp
+++ b/chromium/third_party/skia/src/shaders/SkColorFilterShader.cpp
@@ -8,6 +8,7 @@
#include "include/core/SkShader.h"
#include "include/core/SkString.h"
#include "src/core/SkArenaAlloc.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/core/SkRasterPipeline.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkVM.h"
@@ -22,7 +23,7 @@ SkColorFilterShader::SkColorFilterShader(sk_sp<SkShader> shader,
float alpha,
sk_sp<SkColorFilter> filter)
: fShader(std::move(shader))
- , fFilter(std::move(filter))
+ , fFilter(as_CFB_sp(std::move(filter)))
, fAlpha (alpha)
{
SkASSERT(fShader);
@@ -39,9 +40,7 @@ sk_sp<SkFlattenable> SkColorFilterShader::CreateProc(SkReadBuffer& buffer) {
}
bool SkColorFilterShader::isOpaque() const {
- return fShader->isOpaque()
- && fAlpha == 1.0f
- && (fFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag) != 0;
+ return fShader->isOpaque() && fAlpha == 1.0f && as_CFB(fFilter)->isAlphaUnchanged();
}
void SkColorFilterShader::flatten(SkWriteBuffer& buffer) const {
@@ -62,12 +61,15 @@ bool SkColorFilterShader::onAppendStages(const SkStageRec& rec) const {
}
skvm::Color SkColorFilterShader::onProgram(skvm::Builder* p,
- skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider& matrices, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
// Run the shader.
- skvm::Color c = as_SB(fShader)->program(p, x,y, paint, ctm,localM, quality,dst, uniforms,alloc);
+ skvm::Color c = as_SB(fShader)->program(p, device,local, paint,
+ matrices,localM,
+ quality,dst,
+ uniforms,alloc);
if (!c) {
return {};
}
diff --git a/chromium/third_party/skia/src/shaders/SkColorFilterShader.h b/chromium/third_party/skia/src/shaders/SkColorFilterShader.h
index e1d470086d4..c3bd0b081fc 100644
--- a/chromium/third_party/skia/src/shaders/SkColorFilterShader.h
+++ b/chromium/third_party/skia/src/shaders/SkColorFilterShader.h
@@ -8,7 +8,7 @@
#ifndef SkColorFilterShader_DEFINED
#define SkColorFilterShader_DEFINED
-#include "include/core/SkColorFilter.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/shaders/SkShaderBase.h"
class SkArenaAlloc;
@@ -26,16 +26,16 @@ private:
void flatten(SkWriteBuffer&) const override;
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc*) const override;
SK_FLATTENABLE_HOOKS(SkColorFilterShader)
- sk_sp<SkShader> fShader;
- sk_sp<SkColorFilter> fFilter;
- float fAlpha;
+ sk_sp<SkShader> fShader;
+ sk_sp<SkColorFilterBase> fFilter;
+ float fAlpha;
typedef SkShaderBase INHERITED;
};
diff --git a/chromium/third_party/skia/src/shaders/SkColorShader.cpp b/chromium/third_party/skia/src/shaders/SkColorShader.cpp
index 83149989275..8afdda1128e 100644
--- a/chromium/third_party/skia/src/shaders/SkColorShader.cpp
+++ b/chromium/third_party/skia/src/shaders/SkColorShader.cpp
@@ -92,16 +92,18 @@ bool SkColor4Shader::onAppendStages(const SkStageRec& rec) const {
}
skvm::Color SkColorShader::onProgram(skvm::Builder* p,
- skvm::F32 /*x*/, skvm::F32 /*y*/, skvm::Color /*paint*/,
- const SkMatrix& /*ctm*/, const SkMatrix* /*localM*/,
+ skvm::Coord /*device*/, skvm::Coord /*local*/,
+ skvm::Color /*paint*/,
+ const SkMatrixProvider&, const SkMatrix* /*localM*/,
SkFilterQuality /*quality*/, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc*) const {
return p->uniformPremul(SkColor4f::FromColor(fColor), sk_srgb_singleton(),
uniforms, dst.colorSpace());
}
skvm::Color SkColor4Shader::onProgram(skvm::Builder* p,
- skvm::F32 /*x*/, skvm::F32 /*y*/, skvm::Color /*paint*/,
- const SkMatrix& /*ctm*/, const SkMatrix* /*localM*/,
+ skvm::Coord /*device*/, skvm::Coord /*local*/,
+ skvm::Color /*paint*/,
+ const SkMatrixProvider&, const SkMatrix* /*localM*/,
SkFilterQuality /*quality*/, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc*) const {
return p->uniformPremul(fColor, fColorSpace.get(),
@@ -118,7 +120,8 @@ skvm::Color SkColor4Shader::onProgram(skvm::Builder* p,
std::unique_ptr<GrFragmentProcessor> SkColorShader::asFragmentProcessor(
const GrFPArgs& args) const {
SkPMColor4f color = SkColorToPMColor4f(fColor, *args.fDstColorInfo);
- return GrConstColorProcessor::Make(color, GrConstColorProcessor::InputMode::kModulateA);
+ return GrConstColorProcessor::Make(/*inputFP=*/nullptr, color,
+ GrConstColorProcessor::InputMode::kModulateA);
}
std::unique_ptr<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(
@@ -127,7 +130,7 @@ std::unique_ptr<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(
args.fDstColorInfo->colorSpace(), kUnpremul_SkAlphaType };
SkColor4f color = fColor;
steps.apply(color.vec());
- return GrConstColorProcessor::Make(color.premul(),
+ return GrConstColorProcessor::Make(/*inputFP=*/nullptr, color.premul(),
GrConstColorProcessor::InputMode::kModulateA);
}
diff --git a/chromium/third_party/skia/src/shaders/SkColorShader.h b/chromium/third_party/skia/src/shaders/SkColorShader.h
index 0e9225cb6db..5b876655970 100644
--- a/chromium/third_party/skia/src/shaders/SkColorShader.h
+++ b/chromium/third_party/skia/src/shaders/SkColorShader.h
@@ -44,8 +44,8 @@ private:
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc*) const override;
@@ -69,8 +69,8 @@ private:
void flatten(SkWriteBuffer&) const override;
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc*) const override;
diff --git a/chromium/third_party/skia/src/shaders/SkComposeShader.cpp b/chromium/third_party/skia/src/shaders/SkComposeShader.cpp
index 96ebf79726f..77fbfeb42ae 100644
--- a/chromium/third_party/skia/src/shaders/SkComposeShader.cpp
+++ b/chromium/third_party/skia/src/shaders/SkComposeShader.cpp
@@ -127,13 +127,14 @@ bool SkShader_Blend::onAppendStages(const SkStageRec& orig_rec) const {
return true;
}
-skvm::Color SkShader_Blend::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+skvm::Color SkShader_Blend::onProgram(skvm::Builder* p,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider& mats, const SkMatrix* localM,
SkFilterQuality q, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
skvm::Color d,s;
- if ((d = as_SB(fDst)->program(p, x,y, paint, ctm,localM, q, dst, uniforms, alloc)) &&
- (s = as_SB(fSrc)->program(p, x,y, paint, ctm,localM, q, dst, uniforms, alloc)))
+ if ((d = as_SB(fDst)->program(p, device,local, paint, mats,localM, q,dst, uniforms,alloc)) &&
+ (s = as_SB(fSrc)->program(p, device,local, paint, mats,localM, q,dst, uniforms,alloc)))
{
return p->blend(fMode, s,d);
}
@@ -167,13 +168,14 @@ bool SkShader_Lerp::onAppendStages(const SkStageRec& orig_rec) const {
return true;
}
-skvm::Color SkShader_Lerp::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+skvm::Color SkShader_Lerp::onProgram(skvm::Builder* p,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider& mats, const SkMatrix* localM,
SkFilterQuality q, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
skvm::Color d,s;
- if ((d = as_SB(fDst)->program(p, x,y, paint, ctm,localM, q, dst, uniforms, alloc)) &&
- (s = as_SB(fSrc)->program(p, x,y, paint, ctm,localM, q, dst, uniforms, alloc)))
+ if ((d = as_SB(fDst)->program(p, device,local, paint, mats,localM, q,dst, uniforms,alloc)) &&
+ (s = as_SB(fSrc)->program(p, device,local, paint, mats,localM, q,dst, uniforms,alloc)))
{
auto t = p->uniformF(uniforms->pushF(fWeight));
return {
diff --git a/chromium/third_party/skia/src/shaders/SkComposeShader.h b/chromium/third_party/skia/src/shaders/SkComposeShader.h
index dd36d38816a..96ae0a04b51 100644
--- a/chromium/third_party/skia/src/shaders/SkComposeShader.h
+++ b/chromium/third_party/skia/src/shaders/SkComposeShader.h
@@ -27,8 +27,8 @@ protected:
SkShader_Blend(SkReadBuffer&);
void flatten(SkWriteBuffer&) const override;
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality, const SkColorInfo& dst,
skvm::Uniforms*, SkArenaAlloc*) const override;
@@ -60,8 +60,8 @@ protected:
SkShader_Lerp(SkReadBuffer&);
void flatten(SkWriteBuffer&) const override;
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality, const SkColorInfo& dst,
skvm::Uniforms*, SkArenaAlloc*) const override;
diff --git a/chromium/third_party/skia/src/shaders/SkEmptyShader.h b/chromium/third_party/skia/src/shaders/SkEmptyShader.h
index edd1e27dc2d..414be6c199d 100644
--- a/chromium/third_party/skia/src/shaders/SkEmptyShader.h
+++ b/chromium/third_party/skia/src/shaders/SkEmptyShader.h
@@ -37,9 +37,10 @@ protected:
return false;
}
- skvm::Color onProgram(skvm::Builder*, skvm::F32, skvm::F32, skvm::Color, const SkMatrix&,
- const SkMatrix*, SkFilterQuality, const SkColorInfo&, skvm::Uniforms*,
- SkArenaAlloc*) const override;
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord, skvm::Coord, skvm::Color,
+ const SkMatrixProvider&, const SkMatrix*,
+ SkFilterQuality, const SkColorInfo&,
+ skvm::Uniforms*, SkArenaAlloc*) const override;
private:
SK_FLATTENABLE_HOOKS(SkEmptyShader)
diff --git a/chromium/third_party/skia/src/shaders/SkImageShader.cpp b/chromium/third_party/skia/src/shaders/SkImageShader.cpp
index 93bada25380..7f69d8413d1 100755
--- a/chromium/third_party/skia/src/shaders/SkImageShader.cpp
+++ b/chromium/third_party/skia/src/shaders/SkImageShader.cpp
@@ -37,11 +37,13 @@ static SkTileMode optimize(SkTileMode tm, int dimension) {
SkImageShader::SkImageShader(sk_sp<SkImage> img,
SkTileMode tmx, SkTileMode tmy,
const SkMatrix* localMatrix,
+ FilterEnum filtering,
bool clampAsIfUnpremul)
: INHERITED(localMatrix)
, fImage(std::move(img))
, fTileModeX(optimize(tmx, fImage->width()))
, fTileModeY(optimize(tmy, fImage->height()))
+ , fFiltering(filtering)
, fClampAsIfUnpremul(clampAsIfUnpremul)
{}
@@ -51,18 +53,26 @@ SkImageShader::SkImageShader(sk_sp<SkImage> img,
sk_sp<SkFlattenable> SkImageShader::CreateProc(SkReadBuffer& buffer) {
auto tmx = buffer.read32LE<SkTileMode>(SkTileMode::kLastTileMode);
auto tmy = buffer.read32LE<SkTileMode>(SkTileMode::kLastTileMode);
+
+ FilterEnum filtering = kInheritFromPaint;
+ if (!buffer.isVersionLT(SkPicturePriv::kFilteringInImageShader_Version)) {
+ filtering = buffer.read32LE<FilterEnum>(kInheritFromPaint);
+ }
+
SkMatrix localMatrix;
buffer.readMatrix(&localMatrix);
sk_sp<SkImage> img = buffer.readImage();
if (!img) {
return nullptr;
}
- return SkImageShader::Make(std::move(img), tmx, tmy, &localMatrix);
+
+ return SkImageShader::Make(std::move(img), tmx, tmy, &localMatrix, filtering);
}
void SkImageShader::flatten(SkWriteBuffer& buffer) const {
buffer.writeUInt((unsigned)fTileModeX);
buffer.writeUInt((unsigned)fTileModeY);
+ buffer.writeUInt((unsigned)fFiltering);
buffer.writeMatrix(this->getLocalMatrix());
buffer.writeImage(fImage.get());
SkASSERT(fClampAsIfUnpremul == false);
@@ -75,9 +85,7 @@ bool SkImageShader::isOpaque() const {
#ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
static bool legacy_shader_can_handle(const SkMatrix& inv) {
- if (inv.hasPerspective()) {
- return false;
- }
+ SkASSERT(!inv.hasPerspective());
// Scale+translate methods are always present, but affine might not be.
if (!SkOpts::S32_alpha_D32_filter_DXDY && !inv.isScaleTranslate()) {
@@ -102,6 +110,11 @@ static bool legacy_shader_can_handle(const SkMatrix& inv) {
SkShaderBase::Context* SkImageShader::onMakeContext(const ContextRec& rec,
SkArenaAlloc* alloc) const {
+ SkFilterQuality quality = this->resolveFiltering(rec.fPaint->getFilterQuality());
+
+ if (quality == kHigh_SkFilterQuality) {
+ return nullptr;
+ }
if (fImage->alphaType() == kUnpremul_SkAlphaType) {
return nullptr;
}
@@ -140,8 +153,16 @@ SkShaderBase::Context* SkImageShader::onMakeContext(const ContextRec& rec,
return nullptr;
}
+ // Send in a modified paint with different filter-quality if we don't agree with the paint
+ SkPaint modifiedPaint;
+ ContextRec modifiedRec = rec;
+ if (quality != rec.fPaint->getFilterQuality()) {
+ modifiedPaint = *rec.fPaint;
+ modifiedPaint.setFilterQuality(quality);
+ modifiedRec.fPaint = &modifiedPaint;
+ }
return SkBitmapProcLegacyShader::MakeContext(*this, fTileModeX, fTileModeY,
- as_IB(fImage.get()), rec, alloc);
+ as_IB(fImage.get()), modifiedRec, alloc);
}
#endif
@@ -159,11 +180,14 @@ SkImage* SkImageShader::onIsAImage(SkMatrix* texM, SkTileMode xy[]) const {
sk_sp<SkShader> SkImageShader::Make(sk_sp<SkImage> image,
SkTileMode tmx, SkTileMode tmy,
const SkMatrix* localMatrix,
+ FilterEnum filtering,
bool clampAsIfUnpremul) {
if (!image) {
return sk_make_sp<SkEmptyShader>();
}
- return sk_sp<SkShader>{ new SkImageShader(image, tmx, tmy, localMatrix, clampAsIfUnpremul) };
+ return sk_sp<SkShader>{
+ new SkImageShader(image, tmx, tmy, localMatrix, filtering, clampAsIfUnpremul)
+ };
}
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -195,7 +219,7 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
// are provided by the caller.
bool doBicubic;
GrSamplerState::Filter textureFilterMode = GrSkFilterQualityToGrFilterMode(
- fImage->width(), fImage->height(), args.fFilterQuality,
+ fImage->width(), fImage->height(), this->resolveFiltering(args.fFilterQuality),
args.fMatrixProvider.localToDevice(), *lm,
args.fContext->priv().options().fSharpenMipmappedTextures, &doBicubic);
GrMipMapped mipMapped = GrMipMapped::kNo;
@@ -240,7 +264,7 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
sk_sp<SkShader> SkMakeBitmapShader(const SkBitmap& src, SkTileMode tmx, SkTileMode tmy,
const SkMatrix* localMatrix, SkCopyPixelsMode cpm) {
return SkImageShader::Make(SkMakeImageFromRasterBitmap(src, cpm),
- tmx, tmy, localMatrix);
+ tmx, tmy, localMatrix, SkImageShader::kInheritFromPaint);
}
sk_sp<SkShader> SkMakeBitmapShaderForPaint(const SkPaint& paint, const SkBitmap& src,
@@ -336,14 +360,15 @@ static void tweak_quality_and_inv_matrix(SkFilterQuality* quality, SkMatrix* mat
}
bool SkImageShader::doStages(const SkStageRec& rec, SkImageStageUpdater* updater) const {
- if (updater && rec.fPaint.getFilterQuality() == kMedium_SkFilterQuality) {
+ auto quality = this->resolveFiltering(rec.fPaint.getFilterQuality());
+
+ if (updater && quality == kMedium_SkFilterQuality) {
// TODO: medium: recall RequestBitmap and update width/height accordingly
return false;
}
SkRasterPipeline* p = rec.fPipeline;
SkArenaAlloc* alloc = rec.fAlloc;
- auto quality = rec.fPaint.getFilterQuality();
SkMatrix matrix;
if (!this->computeTotalInverse(rec.fMatrixProvider.localToDevice(), rec.fLocalM, &matrix)) {
@@ -464,14 +489,6 @@ bool SkImageShader::doStages(const SkStageRec& rec, SkImageStageUpdater* updater
};
auto append_misc = [&] {
- // This is an inessential optimization... it's logically safe to set this to false.
- // But if...
- // - we know the image is definitely normalized, and
- // - we're doing some color space conversion, and
- // - sRGB curves are involved,
- // then we can use slightly faster math that doesn't work well outside [0,1].
- bool src_is_normalized = SkColorTypeIsNormalized(info.colorType());
-
SkColorSpace* cs = info.colorSpace();
SkAlphaType at = info.alphaType();
@@ -480,7 +497,6 @@ bool SkImageShader::doStages(const SkStageRec& rec, SkImageStageUpdater* updater
SkColor4f rgb = rec.fPaint.getColor4f();
p->append_set_rgb(alloc, rgb);
- src_is_normalized = rgb.fitsInBytes();
cs = sk_srgb_singleton();
at = kUnpremul_SkAlphaType;
}
@@ -491,13 +507,12 @@ bool SkImageShader::doStages(const SkStageRec& rec, SkImageStageUpdater* updater
p->append(at == kUnpremul_SkAlphaType || fClampAsIfUnpremul
? SkRasterPipeline::clamp_1
: SkRasterPipeline::clamp_a);
- src_is_normalized = true;
}
// Transform color space and alpha type to match shader convention (dst CS, premul alpha).
alloc->make<SkColorSpaceXformSteps>(cs, at,
rec.fDstCS, kPremul_SkAlphaType)
- ->apply(p, src_is_normalized);
+ ->apply(p);
return true;
};
@@ -624,12 +639,15 @@ SkStageUpdater* SkImageShader::onAppendUpdatableStages(const SkStageRec& rec) co
return this->doStages(rec, updater) ? updater : nullptr;
}
-skvm::Color SkImageShader::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+skvm::Color SkImageShader::onProgram(skvm::Builder* p,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider& matrices, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
+ quality = this->resolveFiltering(quality);
+
SkMatrix inv;
- if (!this->computeTotalInverse(ctm, localM, &inv)) {
+ if (!this->computeTotalInverse(matrices.localToDevice(), localM, &inv)) {
return {};
}
@@ -646,7 +664,7 @@ skvm::Color SkImageShader::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y,
inv.normalizePerspective();
// Apply matrix to convert dst coords to sample center coords.
- SkShaderBase::ApplyMatrix(p, inv, &x,&y,uniforms);
+ local = SkShaderBase::ApplyMatrix(p, inv, local, uniforms);
// Bail out if sample() can't yet handle our image's color type.
switch (pm.colorType()) {
@@ -771,14 +789,14 @@ skvm::Color SkImageShader::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y,
skvm::Color c;
if (quality == kNone_SkFilterQuality) {
- c = sample(x,y);
+ c = sample(local.x,local.y);
} else if (quality == kLow_SkFilterQuality) {
// Our four sample points are the corners of a logical 1x1 pixel
// box surrounding (x,y) at (0.5,0.5) off-center.
- skvm::F32 left = x - 0.5f,
- top = y - 0.5f,
- right = x + 0.5f,
- bottom = y + 0.5f;
+ skvm::F32 left = local.x - 0.5f,
+ top = local.y - 0.5f,
+ right = local.x + 0.5f,
+ bottom = local.y + 0.5f;
// The fractional parts of right and bottom are our lerp factors in x and y respectively.
skvm::F32 fx = fract(right ),
@@ -791,8 +809,8 @@ skvm::Color SkImageShader::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y,
// All bicubic samples have the same fractional offset (fx,fy) from the center.
// They're either the 16 corners of a 3x3 grid/ surrounding (x,y) at (0.5,0.5) off-center.
- skvm::F32 fx = fract(x + 0.5f),
- fy = fract(y + 0.5f);
+ skvm::F32 fx = fract(local.x + 0.5f),
+ fy = fract(local.y + 0.5f);
// See GrCubicEffect for details of these weights.
// TODO: these maybe don't seem right looking at gm/bicubic and GrBicubicEffect.
@@ -819,9 +837,9 @@ skvm::Color SkImageShader::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y,
c.r = c.g = c.b = c.a = p->splat(0.0f);
- skvm::F32 sy = y - 1.5f;
+ skvm::F32 sy = local.y - 1.5f;
for (int j = 0; j < 4; j++, sy += 1.0f) {
- skvm::F32 sx = x - 1.5f;
+ skvm::F32 sx = local.x - 1.5f;
for (int i = 0; i < 4; i++, sx += 1.0f) {
skvm::Color s = sample(sx,sy);
skvm::F32 w = wx[i] * wy[j];
diff --git a/chromium/third_party/skia/src/shaders/SkImageShader.h b/chromium/third_party/skia/src/shaders/SkImageShader.h
index 24f6b81b76c..a653a9f332a 100644
--- a/chromium/third_party/skia/src/shaders/SkImageShader.h
+++ b/chromium/third_party/skia/src/shaders/SkImageShader.h
@@ -17,10 +17,20 @@ class SkImageStageUpdater;
class SkImageShader : public SkShaderBase {
public:
+ enum FilterEnum { // first 4 entries match SkFilterQuality
+ kNone,
+ kLow,
+ kMedium,
+ kHigh,
+ // this is the special value for backward compatibility
+ kInheritFromPaint,
+ };
+
static sk_sp<SkShader> Make(sk_sp<SkImage>,
SkTileMode tmx,
SkTileMode tmy,
const SkMatrix* localMatrix,
+ FilterEnum,
bool clampAsIfUnpremul = false);
bool isOpaque() const override;
@@ -36,6 +46,7 @@ private:
SkTileMode tmx,
SkTileMode tmy,
const SkMatrix* localMatrix,
+ FilterEnum,
bool clampAsIfUnpremul);
void flatten(SkWriteBuffer&) const override;
@@ -47,16 +58,21 @@ private:
bool onAppendStages(const SkStageRec&) const override;
SkStageUpdater* onAppendUpdatableStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc*) const override;
bool doStages(const SkStageRec&, SkImageStageUpdater* = nullptr) const;
+ SkFilterQuality resolveFiltering(SkFilterQuality paintQuality) const {
+ return fFiltering == kInheritFromPaint ? paintQuality : (SkFilterQuality)fFiltering;
+ }
+
sk_sp<SkImage> fImage;
const SkTileMode fTileModeX;
const SkTileMode fTileModeY;
+ const FilterEnum fFiltering;
const bool fClampAsIfUnpremul;
friend class SkShaderBase;
diff --git a/chromium/third_party/skia/src/shaders/SkLocalMatrixShader.cpp b/chromium/third_party/skia/src/shaders/SkLocalMatrixShader.cpp
index 66ee52be696..c0ef126ffa4 100644
--- a/chromium/third_party/skia/src/shaders/SkLocalMatrixShader.cpp
+++ b/chromium/third_party/skia/src/shaders/SkLocalMatrixShader.cpp
@@ -12,6 +12,7 @@
#if SK_SUPPORT_GPU
#include "src/gpu/GrFragmentProcessor.h"
+#include "src/gpu/effects/generated/GrDeviceSpaceEffect.h"
#endif
#if SK_SUPPORT_GPU
@@ -77,15 +78,18 @@ bool SkLocalMatrixShader::onAppendStages(const SkStageRec& rec) const {
skvm::Color SkLocalMatrixShader::onProgram(skvm::Builder* p,
- skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider& matrices, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
SkTCopyOnFirstWrite<SkMatrix> lm(this->getLocalMatrix());
if (localM) {
lm.writable()->preConcat(*localM);
}
- return as_SB(fProxyShader)->program(p, x,y, paint, ctm,lm.get(), quality,dst, uniforms,alloc);
+ return as_SB(fProxyShader)->program(p, device,local, paint,
+ matrices,lm.get(),
+ quality,dst,
+ uniforms,alloc);
}
sk_sp<SkShader> SkShader::makeWithLocalMatrix(const SkMatrix& localMatrix) const {
@@ -152,11 +156,16 @@ protected:
return as_SB(fProxyShader)->appendStages(newRec);
}
- skvm::Color onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Color onProgram(skvm::Builder* p,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider& matrices, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override {
- return as_SB(fProxyShader)->program(p, x,y,paint, fCTM,localM, quality,dst, uniforms,alloc);
+ SkOverrideDeviceMatrixProvider matrixProvider(matrices, fCTM);
+ return as_SB(fProxyShader)->program(p, device,local, paint,
+ matrixProvider,localM,
+ quality,dst,
+ uniforms,alloc);
}
private:
@@ -172,8 +181,23 @@ private:
#if SK_SUPPORT_GPU
std::unique_ptr<GrFragmentProcessor> SkCTMShader::asFragmentProcessor(
const GrFPArgs& args) const {
- return as_SB(fProxyShader)->asFragmentProcessor(
- GrFPArgs::WithPreLocalMatrix(args, this->getLocalMatrix()));
+ SkMatrix ctmInv;
+ if (!fCTM.invert(&ctmInv)) {
+ return nullptr;
+ }
+
+ auto ctmProvider = SkOverrideDeviceMatrixProvider(args.fMatrixProvider, fCTM);
+ auto base = as_SB(fProxyShader)->asFragmentProcessor(
+ GrFPArgs::WithPreLocalMatrix(args.withNewMatrixProvider(ctmProvider),
+ this->getLocalMatrix()));
+ if (!base) {
+ return nullptr;
+ }
+
+ // In order for the shader to be evaluated with the original CTM, we explicitly evaluate it
+ // at sk_FragCoord, and pass that through the inverse of the original CTM. This avoids requiring
+ // local coords for the shader and mapping from the draw's local to device and then back.
+ return GrDeviceSpaceEffect::Make(std::move(base), ctmInv);
}
#endif
@@ -183,6 +207,5 @@ sk_sp<SkFlattenable> SkCTMShader::CreateProc(SkReadBuffer& buffer) {
}
sk_sp<SkShader> SkShaderBase::makeWithCTM(const SkMatrix& postM) const {
- return postM.isIdentity() ? sk_ref_sp(this)
- : sk_sp<SkShader>(new SkCTMShader(sk_ref_sp(this), postM));
+ return sk_sp<SkShader>(new SkCTMShader(sk_ref_sp(this), postM));
}
diff --git a/chromium/third_party/skia/src/shaders/SkLocalMatrixShader.h b/chromium/third_party/skia/src/shaders/SkLocalMatrixShader.h
index 603e30e2603..b1fd8826901 100644
--- a/chromium/third_party/skia/src/shaders/SkLocalMatrixShader.h
+++ b/chromium/third_party/skia/src/shaders/SkLocalMatrixShader.h
@@ -48,8 +48,8 @@ protected:
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc*) const override;
diff --git a/chromium/third_party/skia/src/shaders/SkPerlinNoiseShader.cpp b/chromium/third_party/skia/src/shaders/SkPerlinNoiseShader.cpp
index 2d00c03aa4a..a17d7507f54 100644
--- a/chromium/third_party/skia/src/shaders/SkPerlinNoiseShader.cpp
+++ b/chromium/third_party/skia/src/shaders/SkPerlinNoiseShader.cpp
@@ -21,6 +21,7 @@
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/SkGr.h"
+#include "src/gpu/effects/GrTextureEffect.h"
#include "src/gpu/effects/generated/GrConstColorProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
@@ -119,7 +120,7 @@ public:
fPermutationsBitmap.installPixels(info, fLatticeSelector, info.minRowBytes());
fPermutationsBitmap.setImmutable();
- info = SkImageInfo::MakeN32Premul(kBlockSize, 4);
+ info = SkImageInfo::Make(kBlockSize, 4, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
fNoiseBitmap.installPixels(info, fNoise[0][0], info.minRowBytes());
fNoiseBitmap.setImmutable();
@@ -144,7 +145,7 @@ public:
1, 0, 2, 0,
0, 2, 1, 0,
1, 0, 0, 0 };
- info = SkImageInfo::MakeN32Premul(16, 1);
+ info = SkImageInfo::Make(16, 1, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
fGradientBitmap.installPixels(info, gradients, info.minRowBytes());
fGradientBitmap.setImmutable();
#endif
@@ -717,13 +718,26 @@ private:
class GrPerlinNoise2Effect : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(
- SkPerlinNoiseShaderImpl::Type type, int numOctaves, bool stitchTiles,
+ SkPerlinNoiseShaderImpl::Type type,
+ int numOctaves,
+ bool stitchTiles,
std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,
- GrSurfaceProxyView permutationsView, GrSurfaceProxyView noiseView,
- const SkMatrix& matrix) {
- return std::unique_ptr<GrFragmentProcessor>(new GrPerlinNoise2Effect(
- type, numOctaves, stitchTiles, std::move(paintingData),
- std::move(permutationsView), std::move(noiseView), matrix));
+ GrSurfaceProxyView permutationsView,
+ GrSurfaceProxyView noiseView,
+ const SkMatrix& matrix,
+ const GrCaps& caps) {
+ static constexpr GrSamplerState kRepeatXSampler = {GrSamplerState::WrapMode::kRepeat,
+ GrSamplerState::WrapMode::kClamp,
+ GrSamplerState::Filter::kNearest};
+ auto permutationsFP =
+ GrTextureEffect::Make(std::move(permutationsView), kPremul_SkAlphaType,
+ SkMatrix::I(), kRepeatXSampler, caps);
+ auto noiseFP = GrTextureEffect::Make(std::move(noiseView), kPremul_SkAlphaType,
+ SkMatrix::I(), kRepeatXSampler, caps);
+
+ return std::unique_ptr<GrFragmentProcessor>(
+ new GrPerlinNoise2Effect(type, numOctaves, stitchTiles, std::move(paintingData),
+ std::move(permutationsFP), std::move(noiseFP), matrix));
}
const char* name() const override { return "PerlinNoise"; }
@@ -759,19 +773,20 @@ private:
fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit;
}
- GrPerlinNoise2Effect(SkPerlinNoiseShaderImpl::Type type, int numOctaves, bool stitchTiles,
+ GrPerlinNoise2Effect(SkPerlinNoiseShaderImpl::Type type,
+ int numOctaves,
+ bool stitchTiles,
std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,
- GrSurfaceProxyView permutationsView,
- GrSurfaceProxyView noiseView,
+ std::unique_ptr<GrFragmentProcessor> permutationsFP,
+ std::unique_ptr<GrFragmentProcessor> noiseFP,
const SkMatrix& matrix)
: INHERITED(kGrPerlinNoise2Effect_ClassID, kNone_OptimizationFlags)
, fType(type)
, fNumOctaves(numOctaves)
, fStitchTiles(stitchTiles)
- , fPermutationsSampler(std::move(permutationsView))
- , fNoiseSampler(std::move(noiseView))
, fPaintingData(std::move(paintingData)) {
- this->setTextureSamplerCnt(2);
+ this->registerExplicitlySampledChild(std::move(permutationsFP));
+ this->registerExplicitlySampledChild(std::move(noiseFP));
fCoordTransform = GrCoordTransform(matrix);
this->addCoordTransform(&fCoordTransform);
}
@@ -782,16 +797,11 @@ private:
, fCoordTransform(that.fCoordTransform)
, fNumOctaves(that.fNumOctaves)
, fStitchTiles(that.fStitchTiles)
- , fPermutationsSampler(that.fPermutationsSampler)
- , fNoiseSampler(that.fNoiseSampler)
, fPaintingData(new SkPerlinNoiseShaderImpl::PaintingData(*that.fPaintingData)) {
- this->setTextureSamplerCnt(2);
+ this->cloneAndRegisterAllChildProcessors(that);
this->addCoordTransform(&fCoordTransform);
}
- const TextureSampler& onTextureSampler(int i) const override {
- return IthTextureSampler(i, fPermutationsSampler, fNoiseSampler);
- }
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
@@ -799,8 +809,7 @@ private:
GrCoordTransform fCoordTransform;
int fNumOctaves;
bool fStitchTiles;
- TextureSampler fPermutationsSampler;
- TextureSampler fNoiseSampler;
+
std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> fPaintingData;
typedef GrFragmentProcessor INHERITED;
@@ -851,86 +860,36 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
}
- // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
- const char* chanCoordR = "0.125";
- const char* chanCoordG = "0.375";
- const char* chanCoordB = "0.625";
- const char* chanCoordA = "0.875";
- const char* chanCoord = "chanCoord";
- const char* stitchData = "stitchData";
- const char* ratio = "ratio";
- const char* noiseVec = "noiseVec";
- const char* noiseSmooth = "noiseSmooth";
- const char* floorVal = "floorVal";
- const char* fractVal = "fractVal";
- const char* uv = "uv";
- const char* ab = "ab";
- const char* latticeIdx = "latticeIdx";
- const char* bcoords = "bcoords";
- const char* lattice = "lattice";
- const char* inc8bit = "0.00390625"; // 1.0 / 256.0
- // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
- // [-1,1] vector and perform a dot product between that vector and the provided vector.
- const char* dotLattice = "dot(((%s.ga + %s.rb * half2(%s)) * half2(2.0) - half2(1.0)), %s);";
-
// Add noise function
- const GrShaderVar gPerlinNoiseArgs[] = {
- GrShaderVar(chanCoord, kHalf_GrSLType),
- GrShaderVar(noiseVec, kHalf2_GrSLType)
- };
+ const GrShaderVar gPerlinNoiseArgs[] = {{"chanCoord", kHalf_GrSLType },
+ {"noiseVec ", kHalf2_GrSLType}};
- const GrShaderVar gPerlinNoiseStitchArgs[] = {
- GrShaderVar(chanCoord, kHalf_GrSLType),
- GrShaderVar(noiseVec, kHalf2_GrSLType),
- GrShaderVar(stitchData, kHalf2_GrSLType)
- };
+ const GrShaderVar gPerlinNoiseStitchArgs[] = {{"chanCoord" , kHalf_GrSLType },
+ {"noiseVec" , kHalf2_GrSLType},
+ {"stitchData", kHalf2_GrSLType}};
SkString noiseCode;
- noiseCode.appendf("\thalf4 %s;\n", floorVal);
- noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
- noiseCode.appendf("\t%s.zw = %s.xy + half2(1.0);\n", floorVal, floorVal);
- noiseCode.appendf("\thalf2 %s = fract(%s);\n", fractVal, noiseVec);
-
- // smooth curve : t * t * (3 - 2 * t)
- noiseCode.appendf("\n\thalf2 %s = %s * %s * (half2(3.0) - half2(2.0) * %s);",
- noiseSmooth, fractVal, fractVal, fractVal);
+ noiseCode.append(
+ R"(half4 floorVal;
+ floorVal.xy = floor(noiseVec);
+ floorVal.zw = floorVal.xy + half2(1);
+ half2 fractVal = fract(noiseVec);
+ // smooth curve : t^2*(3 - 2*t)
+ half2 noiseSmooth = fractVal*fractVal*(half2(3) - 2*fractVal);)");
// Adjust frequencies if we're stitching tiles
if (pne.stitchTiles()) {
- noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
- floorVal, stitchData, floorVal, stitchData);
- noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
- floorVal, stitchData, floorVal, stitchData);
- noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
- floorVal, stitchData, floorVal, stitchData);
- noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
- floorVal, stitchData, floorVal, stitchData);
+ noiseCode.append(
+ R"(if (floorVal.x >= stitchData.x) { floorVal.x -= stitchData.x; };
+ if (floorVal.y >= stitchData.y) { floorVal.y -= stitchData.y; };
+ if (floorVal.z >= stitchData.x) { floorVal.z -= stitchData.x; };
+ if (floorVal.w >= stitchData.y) { floorVal.w -= stitchData.y; };)");
}
- // Get texture coordinates and normalize
- noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / half4(256.0));\n",
- floorVal, floorVal);
-
- // Get permutation for x
- {
- SkString xCoords("");
- xCoords.appendf("half2(%s.x, 0.5)", floorVal);
-
- noiseCode.appendf("\n\thalf2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
- fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str());
- noiseCode.append(".r;");
- }
-
- // Get permutation for x + 1
- {
- SkString xCoords("");
- xCoords.appendf("half2(%s.z, 0.5)", floorVal);
-
- noiseCode.appendf("\n\t%s.y = ", latticeIdx);
- fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str());
- noiseCode.append(".r;");
- }
+ SkString sampleX = this->invokeChild(0, args, "half2(floorVal.x, 0.5)");
+ SkString sampleY = this->invokeChild(0, args, "half2(floorVal.z, 0.5)");
+ noiseCode.appendf("half2 latticeIdx = half2(%s.r, %s.r);", sampleX.c_str(), sampleY.c_str());
#if defined(SK_BUILD_FOR_ANDROID)
// Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
@@ -939,65 +898,54 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
// (or 0.484368 here). The following rounding operation prevents these precision issues from
// affecting the result of the noise by making sure that we only have multiples of 1/255.
// (Note that 1/255 is about 0.003921569, which is the value used here).
- noiseCode.appendf("\n\t%s = floor(%s * half2(255.0) + half2(0.5)) * half2(0.003921569);",
- latticeIdx, latticeIdx);
+ noiseCode.append(
+ "latticeIdx = floor(latticeIdx * half2(255.0) + half2(0.5)) * half2(0.003921569);");
#endif
// Get (x,y) coordinates with the permutated x
- noiseCode.appendf("\n\thalf4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
+ noiseCode.append("half4 bcoords = 256*latticeIdx.xyxy + floorVal.yyww;");
+
+ noiseCode.append("half2 uv;");
+
+ // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
+ // [-1,1] vector and perform a dot product between that vector and the provided vector.
+ // Save it as a string because we will repeat it 4x.
+ static constexpr const char* inc8bit = "0.00390625"; // 1.0 / 256.0
+ SkString dotLattice =
+ SkStringPrintf("dot((lattice.ga + lattice.rb*%s)*2 - half2(1), fractVal)", inc8bit);
+
+ SkString sampleA = this->invokeChild(1, args, "half2(bcoords.x, chanCoord)");
+ SkString sampleB = this->invokeChild(1, args, "half2(bcoords.y, chanCoord)");
+ SkString sampleC = this->invokeChild(1, args, "half2(bcoords.w, chanCoord)");
+ SkString sampleD = this->invokeChild(1, args, "half2(bcoords.z, chanCoord)");
- noiseCode.appendf("\n\n\thalf2 %s;", uv);
// Compute u, at offset (0,0)
- {
- SkString latticeCoords("");
- latticeCoords.appendf("half2(%s.x, %s)", bcoords, chanCoord);
- noiseCode.appendf("\n\thalf4 %s = ", lattice);
- fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str());
- noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
- noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
- }
+ noiseCode.appendf("half4 lattice = %s;", sampleA.c_str());
+ noiseCode.appendf("uv.x = %s;", dotLattice.c_str());
- noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
// Compute v, at offset (-1,0)
- {
- SkString latticeCoords("");
- latticeCoords.appendf("half2(%s.y, %s)", bcoords, chanCoord);
- noiseCode.append("\n\tlattice = ");
- fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str());
- noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
- noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
- }
+ noiseCode.append("fractVal.x -= 1.0;");
+ noiseCode.appendf("lattice = %s;", sampleB.c_str());
+ noiseCode.appendf("uv.y = %s;", dotLattice.c_str());
// Compute 'a' as a linear interpolation of 'u' and 'v'
- noiseCode.appendf("\n\thalf2 %s;", ab);
- noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
+ noiseCode.append("half2 ab;");
+ noiseCode.append("ab.x = mix(uv.x, uv.y, noiseSmooth.x);");
- noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
// Compute v, at offset (-1,-1)
- {
- SkString latticeCoords("");
- latticeCoords.appendf("half2(%s.w, %s)", bcoords, chanCoord);
- noiseCode.append("\n\tlattice = ");
- fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str());
- noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
- noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
- }
+ noiseCode.append("fractVal.y -= 1.0;");
+ noiseCode.appendf("lattice = %s;", sampleC.c_str());
+ noiseCode.appendf("uv.y = %s;", dotLattice.c_str());
- noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
// Compute u, at offset (0,-1)
- {
- SkString latticeCoords("");
- latticeCoords.appendf("half2(%s.z, %s)", bcoords, chanCoord);
- noiseCode.append("\n\tlattice = ");
- fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str());
- noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
- noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
- }
+ noiseCode.append("fractVal.x += 1.0;");
+ noiseCode.appendf("lattice = %s;", sampleD.c_str());
+ noiseCode.appendf("uv.x = %s;", dotLattice.c_str());
// Compute 'b' as a linear interpolation of 'u' and 'v'
- noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
+ noiseCode.append("ab.y = mix(uv.x, uv.y, noiseSmooth.x);");
// Compute the noise as a linear interpolation of 'a' and 'b'
- noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
+ noiseCode.append("return mix(ab.x, ab.y, noiseSmooth.y);");
SkString noiseFuncName;
if (pne.stitchTiles()) {
@@ -1011,68 +959,73 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
}
// There are rounding errors if the floor operation is not performed here
- fragBuilder->codeAppendf("\n\t\thalf2 %s = half2(floor(%s.xy) * %s);",
- noiseVec, vCoords.c_str(), baseFrequencyUni);
+ fragBuilder->codeAppendf("half2 noiseVec = half2(floor(%s.xy) * %s);",
+ vCoords.c_str(), baseFrequencyUni);
// Clear the color accumulator
- fragBuilder->codeAppendf("\n\t\t%s = half4(0.0);", args.fOutputColor);
+ fragBuilder->codeAppendf("%s = half4(0.0);", args.fOutputColor);
if (pne.stitchTiles()) {
// Set up TurbulenceInitial stitch values.
- fragBuilder->codeAppendf("\n\t\thalf2 %s = %s;", stitchData, stitchDataUni);
+ fragBuilder->codeAppendf("half2 stitchData = %s;", stitchDataUni);
}
- fragBuilder->codeAppendf("\n\t\thalf %s = 1.0;", ratio);
+ fragBuilder->codeAppendf("half ratio = 1.0;");
// Loop over all octaves
fragBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
-
- fragBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor);
+ fragBuilder->codeAppendf(" %s += ", args.fOutputColor);
if (pne.type() != SkPerlinNoiseShaderImpl::kFractalNoise_Type) {
fragBuilder->codeAppend("abs(");
}
+
+ // There are 4 lines, put y coords at center of each.
+ static constexpr const char* chanCoordR = "0.5";
+ static constexpr const char* chanCoordG = "1.5";
+ static constexpr const char* chanCoordB = "2.5";
+ static constexpr const char* chanCoordA = "3.5";
if (pne.stitchTiles()) {
- fragBuilder->codeAppendf(
- "half4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
- "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
- noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
- noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
- noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
- noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
+ fragBuilder->codeAppendf(R"(
+ half4(%s(%s, noiseVec, stitchData), %s(%s, noiseVec, stitchData),"
+ %s(%s, noiseVec, stitchData), %s(%s, noiseVec, stitchData)))",
+ noiseFuncName.c_str(), chanCoordR,
+ noiseFuncName.c_str(), chanCoordG,
+ noiseFuncName.c_str(), chanCoordB,
+ noiseFuncName.c_str(), chanCoordA);
} else {
- fragBuilder->codeAppendf(
- "half4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
- "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
- noiseFuncName.c_str(), chanCoordR, noiseVec,
- noiseFuncName.c_str(), chanCoordG, noiseVec,
- noiseFuncName.c_str(), chanCoordB, noiseVec,
- noiseFuncName.c_str(), chanCoordA, noiseVec);
+ fragBuilder->codeAppendf(R"(
+ half4(%s(%s, noiseVec), %s(%s, noiseVec),
+ %s(%s, noiseVec), %s(%s, noiseVec)))",
+ noiseFuncName.c_str(), chanCoordR,
+ noiseFuncName.c_str(), chanCoordG,
+ noiseFuncName.c_str(), chanCoordB,
+ noiseFuncName.c_str(), chanCoordA);
}
if (pne.type() != SkPerlinNoiseShaderImpl::kFractalNoise_Type) {
- fragBuilder->codeAppendf(")"); // end of "abs("
+ fragBuilder->codeAppend(")"); // end of "abs("
}
- fragBuilder->codeAppendf(" * %s;", ratio);
+ fragBuilder->codeAppend(" * ratio;");
- fragBuilder->codeAppendf("\n\t\t\t%s *= half2(2.0);", noiseVec);
- fragBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
+ fragBuilder->codeAppend(R"(noiseVec *= half2(2.0);
+ ratio *= 0.5;)");
if (pne.stitchTiles()) {
- fragBuilder->codeAppendf("\n\t\t\t%s *= half2(2.0);", stitchData);
+ fragBuilder->codeAppend("stitchData *= half2(2.0);");
}
- fragBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
+ fragBuilder->codeAppend("}"); // end of the for loop on octaves
if (pne.type() == SkPerlinNoiseShaderImpl::kFractalNoise_Type) {
// The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
// by fractalNoise and (turbulenceFunctionResult) by turbulence.
- fragBuilder->codeAppendf("\n\t\t%s = %s * half4(0.5) + half4(0.5);",
- args.fOutputColor,args.fOutputColor);
+ fragBuilder->codeAppendf("%s = %s * half4(0.5) + half4(0.5);",
+ args.fOutputColor, args.fOutputColor);
}
// Clamp values
- fragBuilder->codeAppendf("\n\t\t%s = saturate(%s);", args.fOutputColor, args.fOutputColor);
+ fragBuilder->codeAppendf("%s = saturate(%s);", args.fOutputColor, args.fOutputColor);
// Pre-multiply the result
- fragBuilder->codeAppendf("\n\t\t%s = half4(%s.rgb * %s.aaa, %s.a);\n",
+ fragBuilder->codeAppendf("%s = half4(%s.rgb * %s.aaa, %s.a);\n",
args.fOutputColor, args.fOutputColor,
args.fOutputColor, args.fOutputColor);
}
@@ -1116,7 +1069,7 @@ void GrGLPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
if (turbulence.stitchTiles()) {
const SkPerlinNoiseShaderImpl::StitchData& stitchData = turbulence.stitchData();
pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
- SkIntToScalar(stitchData.fHeight));
+ SkIntToScalar(stitchData.fHeight));
}
}
@@ -1143,13 +1096,24 @@ private:
class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(
- int octaves, SkScalar z,
+ int octaves,
+ SkScalar z,
std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,
- GrSurfaceProxyView permutationsView, GrSurfaceProxyView gradientView,
- const SkMatrix& matrix) {
+ GrSurfaceProxyView permutationsView,
+ GrSurfaceProxyView gradientView,
+ const SkMatrix& matrix,
+ const GrCaps& caps) {
+ static constexpr GrSamplerState kRepeatXSampler = {GrSamplerState::WrapMode::kRepeat,
+ GrSamplerState::WrapMode::kClamp,
+ GrSamplerState::Filter::kNearest};
+ auto permutationsFP =
+ GrTextureEffect::Make(std::move(permutationsView), kPremul_SkAlphaType,
+ SkMatrix::I(), kRepeatXSampler, caps);
+ auto gradientFP = GrTextureEffect::Make(std::move(gradientView), kPremul_SkAlphaType,
+ SkMatrix::I(), kRepeatXSampler, caps);
return std::unique_ptr<GrFragmentProcessor>(new GrImprovedPerlinNoiseEffect(
- octaves, z, std::move(paintingData), std::move(permutationsView),
- std::move(gradientView), matrix));
+ octaves, z, std::move(paintingData), std::move(permutationsFP),
+ std::move(gradientFP), matrix));
}
const char* name() const override { return "ImprovedPerlinNoise"; }
@@ -1178,18 +1142,18 @@ private:
fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency;
}
- GrImprovedPerlinNoiseEffect(int octaves, SkScalar z,
+ GrImprovedPerlinNoiseEffect(int octaves,
+ SkScalar z,
std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData,
- GrSurfaceProxyView permutationsView,
- GrSurfaceProxyView gradientView,
+ std::unique_ptr<GrFragmentProcessor> permutationsFP,
+ std::unique_ptr<GrFragmentProcessor> gradientFP,
const SkMatrix& matrix)
: INHERITED(kGrImprovedPerlinNoiseEffect_ClassID, kNone_OptimizationFlags)
, fOctaves(octaves)
, fZ(z)
- , fPermutationsSampler(std::move(permutationsView))
- , fGradientSampler(std::move(gradientView))
, fPaintingData(std::move(paintingData)) {
- this->setTextureSamplerCnt(2);
+ this->registerExplicitlySampledChild(std::move(permutationsFP));
+ this->registerExplicitlySampledChild(std::move(gradientFP));
fCoordTransform = GrCoordTransform(matrix);
this->addCoordTransform(&fCoordTransform);
}
@@ -1199,24 +1163,17 @@ private:
, fCoordTransform(that.fCoordTransform)
, fOctaves(that.fOctaves)
, fZ(that.fZ)
- , fPermutationsSampler(that.fPermutationsSampler)
- , fGradientSampler(that.fGradientSampler)
, fPaintingData(new SkPerlinNoiseShaderImpl::PaintingData(*that.fPaintingData)) {
- this->setTextureSamplerCnt(2);
+ this->cloneAndRegisterAllChildProcessors(that);
this->addCoordTransform(&fCoordTransform);
}
- const TextureSampler& onTextureSampler(int i) const override {
- return IthTextureSampler(i, fPermutationsSampler, fGradientSampler);
- }
-
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
GrCoordTransform fCoordTransform;
int fOctaves;
SkScalar fZ;
- TextureSampler fPermutationsSampler;
- TextureSampler fGradientSampler;
+
std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> fPaintingData;
typedef GrFragmentProcessor INHERITED;
@@ -1271,44 +1228,39 @@ void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
// perm function
const GrShaderVar permArgs[] = {
- GrShaderVar("x", kHalf_GrSLType)
+ {"x", kHalf_GrSLType}
};
+ SkString samplePerm = this->invokeChild(0, args, "float2(x, 0.5)");
SkString permFuncName;
- SkString permCode("return ");
- // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
- // sure why. Using fract() (here and the next texture lookup) as a workaround.
- fragBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0],
- "float2(fract(x / 256.0), 0.0)");
- permCode.append(".r * 255.0;");
+ SkString permCode = SkStringPrintf("return %s.r * 255;", samplePerm.c_str());
fragBuilder->emitFunction(kHalf_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
permCode.c_str(), &permFuncName);
// grad function
const GrShaderVar gradArgs[] = {
- GrShaderVar("x", kHalf_GrSLType),
- GrShaderVar("p", kHalf3_GrSLType)
+ {"x", kHalf_GrSLType},
+ {"p", kHalf3_GrSLType}
};
+ SkString sampleGrad = this->invokeChild(1, args, "float2(x, 0.5)");
SkString gradFuncName;
- SkString gradCode("return half(dot(");
- fragBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1],
- "float2(fract(x / 16.0), 0.0)");
- gradCode.append(".rgb * 255.0 - float3(1.0), p));");
+ SkString gradCode = SkStringPrintf("return half(dot(%s.rgb * 255.0 - float3(1.0), p));",
+ sampleGrad.c_str());
fragBuilder->emitFunction(kHalf_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
gradCode.c_str(), &gradFuncName);
// lerp function
const GrShaderVar lerpArgs[] = {
- GrShaderVar("a", kHalf_GrSLType),
- GrShaderVar("b", kHalf_GrSLType),
- GrShaderVar("w", kHalf_GrSLType)
+ {"a", kHalf_GrSLType},
+ {"b", kHalf_GrSLType},
+ {"w", kHalf_GrSLType}
};
SkString lerpFuncName;
fragBuilder->emitFunction(kHalf_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
"return a + w * (b - a);", &lerpFuncName);
// noise function
- const GrShaderVar noiseArgs[] = {
- GrShaderVar("p", kHalf3_GrSLType),
+ const GrShaderVar noiseArgs[] = {
+ {"p", kHalf3_GrSLType},
};
SkString noiseFuncName;
SkString noiseCode;
@@ -1345,7 +1297,7 @@ void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
// noiseOctaves function
const GrShaderVar noiseOctavesArgs[] = {
- GrShaderVar("p", kHalf3_GrSLType)
+ {"p", kHalf3_GrSLType}
};
SkString noiseOctavesFuncName;
SkString noiseOctavesCode;
@@ -1432,9 +1384,13 @@ std::unique_ptr<GrFragmentProcessor> SkPerlinNoiseShaderImpl::asFragmentProcesso
const SkBitmap& gradientBitmap = paintingData->getGradientBitmap();
SkASSERT(SkIsPow2(gradientBitmap.width()) && SkIsPow2(gradientBitmap.height()));
auto gradientView = GrMakeCachedBitmapProxyView(context, gradientBitmap);
- return GrImprovedPerlinNoiseEffect::Make(fNumOctaves, fSeed, std::move(paintingData),
+ return GrImprovedPerlinNoiseEffect::Make(fNumOctaves,
+ fSeed,
+ std::move(paintingData),
std::move(permutationsView),
- std::move(gradientView), m);
+ std::move(gradientView),
+ m,
+ *context->priv().caps());
}
if (0 == fNumOctaves) {
@@ -1443,13 +1399,13 @@ std::unique_ptr<GrFragmentProcessor> SkPerlinNoiseShaderImpl::asFragmentProcesso
// TODO: Either treat the output of this shader as sRGB or allow client to specify a
// color space of the noise. Either way, this case (and the GLSL) need to convert to
// the destination.
- auto inner =
- GrConstColorProcessor::Make(SkPMColor4f::FromBytes_RGBA(0x80404040),
- GrConstColorProcessor::InputMode::kModulateRGBA);
+ auto inner = GrConstColorProcessor::Make(
+ /*inputFP=*/nullptr, SkPMColor4f::FromBytes_RGBA(0x80404040),
+ GrConstColorProcessor::InputMode::kModulateRGBA);
return GrFragmentProcessor::MulChildByInputAlpha(std::move(inner));
}
// Emit zero.
- return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
+ return GrConstColorProcessor::Make(/*inputFP=*/nullptr, SK_PMColor4fTRANSPARENT,
GrConstColorProcessor::InputMode::kIgnore);
}
@@ -1471,7 +1427,8 @@ std::unique_ptr<GrFragmentProcessor> SkPerlinNoiseShaderImpl::asFragmentProcesso
std::move(paintingData),
std::move(permutationsView),
std::move(noiseView),
- m);
+ m,
+ *context->priv().caps());
return GrFragmentProcessor::MulChildByInputAlpha(std::move(inner));
}
return nullptr;
diff --git a/chromium/third_party/skia/src/shaders/SkPictureShader.cpp b/chromium/third_party/skia/src/shaders/SkPictureShader.cpp
index 009ae54d36e..6a77004b49c 100644
--- a/chromium/third_party/skia/src/shaders/SkPictureShader.cpp
+++ b/chromium/third_party/skia/src/shaders/SkPictureShader.cpp
@@ -275,20 +275,24 @@ bool SkPictureShader::onAppendStages(const SkStageRec& rec) const {
}
skvm::Color SkPictureShader::onProgram(skvm::Builder* p,
- skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider& matrices, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
auto lm = this->totalLocalMatrix(localM);
// Keep bitmapShader alive by using alloc instead of stack memory
auto& bitmapShader = *alloc->make<sk_sp<SkShader>>();
- bitmapShader = this->refBitmapShader(ctm, &lm, dst.colorType(), dst.colorSpace());
+ bitmapShader = this->refBitmapShader(matrices.localToDevice(), &lm,
+ dst.colorType(), dst.colorSpace());
if (!bitmapShader) {
return {};
}
- return as_SB(bitmapShader)->program(p, x,y, paint, ctm, lm, quality, dst, uniforms, alloc);
+ return as_SB(bitmapShader)->program(p, device,local, paint,
+ matrices,lm,
+ quality,dst,
+ uniforms,alloc);
}
/////////////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/src/shaders/SkPictureShader.h b/chromium/third_party/skia/src/shaders/SkPictureShader.h
index 0bdc9cd9e09..01ef4b4d122 100644
--- a/chromium/third_party/skia/src/shaders/SkPictureShader.h
+++ b/chromium/third_party/skia/src/shaders/SkPictureShader.h
@@ -37,8 +37,8 @@ protected:
SkPictureShader(SkReadBuffer&);
void flatten(SkWriteBuffer&) const override;
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override;
diff --git a/chromium/third_party/skia/src/shaders/SkShader.cpp b/chromium/third_party/skia/src/shaders/SkShader.cpp
index c1c09e7d9a2..e8bcdb9927c 100644
--- a/chromium/third_party/skia/src/shaders/SkShader.cpp
+++ b/chromium/third_party/skia/src/shaders/SkShader.cpp
@@ -189,14 +189,15 @@ bool SkShaderBase::onAppendStages(const SkStageRec& rec) const {
rec.fPipeline->append(SkRasterPipeline::callback, cb);
rec.fAlloc->make<SkColorSpaceXformSteps>(sk_srgb_singleton(), kPremul_SkAlphaType,
rec.fDstCS, kPremul_SkAlphaType)
- ->apply(rec.fPipeline, true);
+ ->apply(rec.fPipeline);
return true;
}
return false;
}
-skvm::Color SkShaderBase::program(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+skvm::Color SkShaderBase::program(skvm::Builder* p,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider& matrices, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
// Force opaque alpha for all opaque shaders.
@@ -211,7 +212,8 @@ skvm::Color SkShaderBase::program(skvm::Builder* p, skvm::F32 x, skvm::F32 y, sk
// shader program hash and blitter Key. This makes it safe for us to use
// that bit to make decisions when constructing an SkVMBlitter, like doing
// SrcOver -> Src strength reduction.
- if (auto color = this->onProgram(p, x,y, paint, ctm,localM, quality,dst, uniforms,alloc)) {
+ if (auto color = this->onProgram(p, device,local, paint, matrices,localM, quality,dst,
+ uniforms,alloc)) {
if (this->isOpaque()) {
color.a = p->splat(1.0f);
}
@@ -220,11 +222,12 @@ skvm::Color SkShaderBase::program(skvm::Builder* p, skvm::F32 x, skvm::F32 y, sk
return {};
}
-skvm::Color SkShaderBase::onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+skvm::Color SkShaderBase::onProgram(skvm::Builder*,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
- //SkDebugf("cannot onProgram %s\n", this->getTypeName());
+ // SkDebugf("cannot onProgram %s\n", this->getTypeName());
return {};
}
@@ -234,36 +237,40 @@ sk_sp<SkShader> SkShaderBase::makeInvertAlpha() const {
}
-void SkShaderBase::ApplyMatrix(skvm::Builder* p, const SkMatrix& m,
- skvm::F32* x, skvm::F32* y, skvm::Uniforms* uniforms) {
+skvm::Coord SkShaderBase::ApplyMatrix(skvm::Builder* p, const SkMatrix& m,
+ skvm::Coord coord, skvm::Uniforms* uniforms) {
+ skvm::F32 x = coord.x,
+ y = coord.y;
if (m.isIdentity()) {
// That was easy.
} else if (m.isTranslate()) {
- *x = p->add(*x, p->uniformF(uniforms->pushF(m[2])));
- *y = p->add(*y, p->uniformF(uniforms->pushF(m[5])));
+ x = p->add(x, p->uniformF(uniforms->pushF(m[2])));
+ y = p->add(y, p->uniformF(uniforms->pushF(m[5])));
} else if (m.isScaleTranslate()) {
- *x = p->mad(*x, p->uniformF(uniforms->pushF(m[0])), p->uniformF(uniforms->pushF(m[2])));
- *y = p->mad(*y, p->uniformF(uniforms->pushF(m[4])), p->uniformF(uniforms->pushF(m[5])));
+ x = p->mad(x, p->uniformF(uniforms->pushF(m[0])), p->uniformF(uniforms->pushF(m[2])));
+ y = p->mad(y, p->uniformF(uniforms->pushF(m[4])), p->uniformF(uniforms->pushF(m[5])));
} else { // Affine or perspective.
- auto dot = [&,X=*x,Y=*y](int row) {
- return p->mad(X, p->uniformF(uniforms->pushF(m[3*row+0])),
- p->mad(Y, p->uniformF(uniforms->pushF(m[3*row+1])),
+ auto dot = [&,x,y](int row) {
+ return p->mad(x, p->uniformF(uniforms->pushF(m[3*row+0])),
+ p->mad(y, p->uniformF(uniforms->pushF(m[3*row+1])),
p->uniformF(uniforms->pushF(m[3*row+2]))));
};
- *x = dot(0);
- *y = dot(1);
+ x = dot(0);
+ y = dot(1);
if (m.hasPerspective()) {
- *x = p->div(*x, dot(2));
- *y = p->div(*y, dot(2));
+ x = p->div(x, dot(2));
+ y = p->div(y, dot(2));
}
}
+ return {x,y};
}
///////////////////////////////////////////////////////////////////////////////////////////////////
-skvm::Color SkEmptyShader::onProgram(skvm::Builder*, skvm::F32, skvm::F32, skvm::Color,
- const SkMatrix&, const SkMatrix*, SkFilterQuality,
- const SkColorInfo&, skvm::Uniforms*, SkArenaAlloc*) const {
+skvm::Color SkEmptyShader::onProgram(skvm::Builder*, skvm::Coord, skvm::Coord, skvm::Color,
+ const SkMatrixProvider&, const SkMatrix*,
+ SkFilterQuality, const SkColorInfo&,
+ skvm::Uniforms*, SkArenaAlloc*) const {
return {}; // signal failure
}
diff --git a/chromium/third_party/skia/src/shaders/SkShaderBase.h b/chromium/third_party/skia/src/shaders/SkShaderBase.h
index dda4d1aac5f..9119056bd93 100644
--- a/chromium/third_party/skia/src/shaders/SkShaderBase.h
+++ b/chromium/third_party/skia/src/shaders/SkShaderBase.h
@@ -211,8 +211,8 @@ public:
return this->onAppendUpdatableStages(rec);
}
- skvm::Color program(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Color program(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const;
@@ -241,14 +241,15 @@ protected:
virtual SkStageUpdater* onAppendUpdatableStages(const SkStageRec&) const { return nullptr; }
protected:
- static void ApplyMatrix(skvm::Builder*, const SkMatrix&, skvm::F32* x, skvm::F32* y, skvm::Uniforms*);
+ static skvm::Coord ApplyMatrix(skvm::Builder*, const SkMatrix&, skvm::Coord, skvm::Uniforms*);
private:
// This is essentially const, but not officially so it can be modified in constructors.
SkMatrix fLocalMatrix;
- virtual skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ virtual skvm::Color onProgram(skvm::Builder*,
+ skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dst,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const;
diff --git a/chromium/third_party/skia/src/shaders/gradients/Sk4fLinearGradient.cpp b/chromium/third_party/skia/src/shaders/gradients/Sk4fLinearGradient.cpp
index d75bec96556..944ac9fdb47 100644
--- a/chromium/third_party/skia/src/shaders/gradients/Sk4fLinearGradient.cpp
+++ b/chromium/third_party/skia/src/shaders/gradients/Sk4fLinearGradient.cpp
@@ -190,17 +190,17 @@ LinearGradient4fContext::shadePremulSpan(int x, int y, SkPMColor dst[], int coun
const SkLinearGradient& shader = static_cast<const SkLinearGradient&>(fShader);
switch (shader.fTileMode) {
case SkTileMode::kDecal:
- SkASSERT(false); // decal only supported via stages
- // fall-through
+ SkASSERT(false); // decal only supported via stages
+ [[fallthrough]];
case SkTileMode::kClamp:
this->shadeSpanInternal<premul, SkTileMode::kClamp >(x, y, dst, count, bias0, bias1);
- break;
+ break;
case SkTileMode::kRepeat:
this->shadeSpanInternal<premul, SkTileMode::kRepeat>(x, y, dst, count, bias0, bias1);
- break;
+ break;
case SkTileMode::kMirror:
this->shadeSpanInternal<premul, SkTileMode::kMirror>(x, y, dst, count, bias0, bias1);
- break;
+ break;
}
}
diff --git a/chromium/third_party/skia/src/shaders/gradients/SkGradientShader.cpp b/chromium/third_party/skia/src/shaders/gradients/SkGradientShader.cpp
index 205a18f05b3..23e5d9a8495 100644
--- a/chromium/third_party/skia/src/shaders/gradients/SkGradientShader.cpp
+++ b/chromium/third_party/skia/src/shaders/gradients/SkGradientShader.cpp
@@ -299,7 +299,8 @@ bool SkGradientShaderBase::onAppendStages(const SkStageRec& rec) const {
decal_ctx->limit_x = SkBits2Float(SkFloat2Bits(1.0f) + 1);
// reuse mask + limit_x stage, or create a custom decal_1 that just stores the mask
p->append(SkRasterPipeline::decal_x, decal_ctx);
- // fall-through to clamp
+ [[fallthrough]];
+
case SkTileMode::kClamp:
if (!fOrigPos) {
// We clamp only when the stops are evenly spaced.
@@ -419,21 +420,22 @@ bool SkGradientShaderBase::onAppendStages(const SkStageRec& rec) const {
}
skvm::Color SkGradientShaderBase::onProgram(skvm::Builder* p,
- skvm::F32 x, skvm::F32 y, skvm::Color /*paint*/,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Coord device, skvm::Coord local,
+ skvm::Color /*paint*/,
+ const SkMatrixProvider& mats, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dstInfo,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
SkMatrix inv;
- if (!this->computeTotalInverse(ctm, localM, &inv)) {
+ if (!this->computeTotalInverse(mats.localToDevice(), localM, &inv)) {
return {};
}
inv.postConcat(fPtsToUnit);
inv.normalizePerspective();
- SkShaderBase::ApplyMatrix(p, inv, &x,&y,uniforms);
+ local = SkShaderBase::ApplyMatrix(p, inv, local, uniforms);
skvm::I32 mask = p->splat(~0);
- skvm::F32 t = this->transformT(p,uniforms, x,y, &mask);
+ skvm::F32 t = this->transformT(p,uniforms, local, &mask);
// Perhaps unexpectedly, clamping is handled naturally by our search, so we
// don't explicitly clamp t to [0,1]. That clamp would break hard stops
diff --git a/chromium/third_party/skia/src/shaders/gradients/SkGradientShaderPriv.h b/chromium/third_party/skia/src/shaders/gradients/SkGradientShaderPriv.h
index 2a3bfca1808..f33c444f9b5 100644
--- a/chromium/third_party/skia/src/shaders/gradients/SkGradientShaderPriv.h
+++ b/chromium/third_party/skia/src/shaders/gradients/SkGradientShaderPriv.h
@@ -79,8 +79,8 @@ protected:
bool onAppendStages(const SkStageRec&) const override;
- skvm::Color onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
- const SkMatrix& ctm, const SkMatrix* localM,
+ skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
+ const SkMatrixProvider&, const SkMatrix* localM,
SkFilterQuality quality, const SkColorInfo& dstCS,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override;
@@ -89,7 +89,7 @@ protected:
// Produce t from (x,y), modifying mask if it should be anything other than ~0.
virtual skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const = 0;
+ skvm::Coord coord, skvm::I32* mask) const = 0;
template <typename T, typename... Args>
static Context* CheckedMakeContext(SkArenaAlloc* alloc, Args&&... args) {
diff --git a/chromium/third_party/skia/src/shaders/gradients/SkLinearGradient.cpp b/chromium/third_party/skia/src/shaders/gradients/SkLinearGradient.cpp
index ad5129ccc3b..347fd177f00 100644
--- a/chromium/third_party/skia/src/shaders/gradients/SkLinearGradient.cpp
+++ b/chromium/third_party/skia/src/shaders/gradients/SkLinearGradient.cpp
@@ -76,9 +76,9 @@ void SkLinearGradient::appendGradientStages(SkArenaAlloc*, SkRasterPipeline*,
}
skvm::F32 SkLinearGradient::transformT(skvm::Builder* p, skvm::Uniforms*,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const {
+ skvm::Coord coord, skvm::I32* mask) const {
// We've baked getting t in x into the matrix, so this is pretty trivial.
- return x;
+ return coord.x;
}
SkShader::GradientType SkLinearGradient::asAGradient(GradientInfo* info) const {
diff --git a/chromium/third_party/skia/src/shaders/gradients/SkLinearGradient.h b/chromium/third_party/skia/src/shaders/gradients/SkLinearGradient.h
index c8f9bc678f5..063b9c5a647 100644
--- a/chromium/third_party/skia/src/shaders/gradients/SkLinearGradient.h
+++ b/chromium/third_party/skia/src/shaders/gradients/SkLinearGradient.h
@@ -30,7 +30,7 @@ protected:
SkRasterPipeline* postPipeline) const final;
skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const final;
+ skvm::Coord coord, skvm::I32* mask) const final;
private:
SK_FLATTENABLE_HOOKS(SkLinearGradient)
diff --git a/chromium/third_party/skia/src/shaders/gradients/SkRadialGradient.cpp b/chromium/third_party/skia/src/shaders/gradients/SkRadialGradient.cpp
index aeefe15e741..fea9ca6b316 100644
--- a/chromium/third_party/skia/src/shaders/gradients/SkRadialGradient.cpp
+++ b/chromium/third_party/skia/src/shaders/gradients/SkRadialGradient.cpp
@@ -64,8 +64,8 @@ void SkRadialGradient::appendGradientStages(SkArenaAlloc*, SkRasterPipeline* p,
}
skvm::F32 SkRadialGradient::transformT(skvm::Builder* p, skvm::Uniforms*,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const {
- return sqrt(x*x + y*y);
+ skvm::Coord coord, skvm::I32* mask) const {
+ return sqrt(coord.x*coord.x + coord.y*coord.y);
}
/////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/src/shaders/gradients/SkRadialGradient.h b/chromium/third_party/skia/src/shaders/gradients/SkRadialGradient.h
index 75680978637..7396bb21d2b 100644
--- a/chromium/third_party/skia/src/shaders/gradients/SkRadialGradient.h
+++ b/chromium/third_party/skia/src/shaders/gradients/SkRadialGradient.h
@@ -27,7 +27,7 @@ protected:
SkRasterPipeline* postPipeline) const override;
skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const final;
+ skvm::Coord coord, skvm::I32* mask) const final;
private:
SK_FLATTENABLE_HOOKS(SkRadialGradient)
diff --git a/chromium/third_party/skia/src/shaders/gradients/SkSweepGradient.cpp b/chromium/third_party/skia/src/shaders/gradients/SkSweepGradient.cpp
index b8a8c51977d..6256cc6bf35 100644
--- a/chromium/third_party/skia/src/shaders/gradients/SkSweepGradient.cpp
+++ b/chromium/third_party/skia/src/shaders/gradients/SkSweepGradient.cpp
@@ -13,7 +13,7 @@
SkSweepGradient::SkSweepGradient(const SkPoint& center, SkScalar t0, SkScalar t1,
const Descriptor& desc)
- : SkGradientShaderBase(desc, SkMatrix::MakeTrans(-center.x(), -center.y()))
+ : SkGradientShaderBase(desc, SkMatrix::Translate(-center.x(), -center.y()))
, fCenter(center)
, fTBias(-t0)
, fTScale(1 / (t1 - t0))
@@ -64,14 +64,13 @@ void SkSweepGradient::flatten(SkWriteBuffer& buffer) const {
void SkSweepGradient::appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* p,
SkRasterPipeline*) const {
p->append(SkRasterPipeline::xy_to_unit_angle);
- p->append_matrix(alloc, SkMatrix::Concat(SkMatrix::MakeScale(fTScale, 1),
- SkMatrix::MakeTrans(fTBias , 0)));
+ p->append_matrix(alloc, SkMatrix::Scale(fTScale, 1) * SkMatrix::Translate(fTBias, 0));
}
skvm::F32 SkSweepGradient::transformT(skvm::Builder* p, skvm::Uniforms* uniforms,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const {
- skvm::F32 xabs = abs(x),
- yabs = abs(y),
+ skvm::Coord coord, skvm::I32* mask) const {
+ skvm::F32 xabs = abs(coord.x),
+ yabs = abs(coord.y),
slope = min(xabs, yabs) / max(xabs, yabs);
skvm::F32 s = slope * slope;
@@ -83,9 +82,9 @@ skvm::F32 SkSweepGradient::transformT(skvm::Builder* p, skvm::Uniforms* uniforms
+2.476101927459239959716796875e-2f,
-5.185396969318389892578125e-2f,
+0.15912117063999176025390625f);
- phi = select(xabs < yabs, (1/4.0f) - phi, phi);
- phi = select( x < 0.0f, (1/2.0f) - phi, phi);
- phi = select( y < 0.0f, (1/1.0f) - phi, phi);
+ phi = select( xabs < yabs, (1/4.0f) - phi, phi);
+ phi = select(coord.x < 0.0f, (1/2.0f) - phi, phi);
+ phi = select(coord.y < 0.0f, (1/1.0f) - phi, phi);
skvm::F32 t = select(is_NaN(phi), p->splat(0.0f)
, phi);
diff --git a/chromium/third_party/skia/src/shaders/gradients/SkSweepGradient.h b/chromium/third_party/skia/src/shaders/gradients/SkSweepGradient.h
index e7beae2dae5..86ca372ba0c 100644
--- a/chromium/third_party/skia/src/shaders/gradients/SkSweepGradient.h
+++ b/chromium/third_party/skia/src/shaders/gradients/SkSweepGradient.h
@@ -31,7 +31,7 @@ protected:
SkRasterPipeline* postPipeline) const override;
skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const final;
+ skvm::Coord coord, skvm::I32* mask) const final;
private:
SK_FLATTENABLE_HOOKS(SkSweepGradient)
diff --git a/chromium/third_party/skia/src/shaders/gradients/SkTwoPointConicalGradient.cpp b/chromium/third_party/skia/src/shaders/gradients/SkTwoPointConicalGradient.cpp
index 811d719b9d5..d3ec7552176 100644
--- a/chromium/third_party/skia/src/shaders/gradients/SkTwoPointConicalGradient.cpp
+++ b/chromium/third_party/skia/src/shaders/gradients/SkTwoPointConicalGradient.cpp
@@ -62,7 +62,7 @@ sk_sp<SkShader> SkTwoPointConicalGradient::Create(const SkPoint& c0, SkScalar r0
}
// Concentric case: we can pretend we're radial (with a tiny twist).
const SkScalar scale = sk_ieee_float_divide(1, std::max(r0, r1));
- gradientMatrix = SkMatrix::MakeTrans(-c1.x(), -c1.y());
+ gradientMatrix = SkMatrix::Translate(-c1.x(), -c1.y());
gradientMatrix.postScale(scale, scale);
gradientType = Type::kRadial;
@@ -188,8 +188,7 @@ void SkTwoPointConicalGradient::appendGradientStages(SkArenaAlloc* alloc, SkRast
auto scale = std::max(fRadius1, fRadius2) / dRadius;
auto bias = -fRadius1 / dRadius;
- p->append_matrix(alloc, SkMatrix::Concat(SkMatrix::MakeTrans(bias, 0),
- SkMatrix::MakeScale(scale, 1)));
+ p->append_matrix(alloc, SkMatrix::Translate(bias, 0) * SkMatrix::Scale(scale, 1));
return;
}
@@ -235,11 +234,13 @@ void SkTwoPointConicalGradient::appendGradientStages(SkArenaAlloc* alloc, SkRast
}
skvm::F32 SkTwoPointConicalGradient::transformT(skvm::Builder* p, skvm::Uniforms* uniforms,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const {
+ skvm::Coord coord, skvm::I32* mask) const {
// See https://skia.org/dev/design/conical, and onAppendStages() above.
// There's a lot going on here, and I'm not really sure what's independent
// or disjoint, what can be reordered, simplified, etc. Tweak carefully.
+ const skvm::F32 x = coord.x,
+ y = coord.y;
if (fType == Type::kRadial) {
float denom = 1.0f / (fRadius2 - fRadius1),
scale = std::max(fRadius1, fRadius2) * denom,
diff --git a/chromium/third_party/skia/src/shaders/gradients/SkTwoPointConicalGradient.h b/chromium/third_party/skia/src/shaders/gradients/SkTwoPointConicalGradient.h
index a8893ce5e1f..d362ba0a303 100644
--- a/chromium/third_party/skia/src/shaders/gradients/SkTwoPointConicalGradient.h
+++ b/chromium/third_party/skia/src/shaders/gradients/SkTwoPointConicalGradient.h
@@ -70,7 +70,7 @@ protected:
SkRasterPipeline* postPipeline) const override;
skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
- skvm::F32 x, skvm::F32 y, skvm::I32* mask) const final;
+ skvm::Coord coord, skvm::I32* mask) const final;
private:
SK_FLATTENABLE_HOOKS(SkTwoPointConicalGradient)
diff --git a/chromium/third_party/skia/src/sksl/README b/chromium/third_party/skia/src/sksl/README
index 906fd814984..525726b7c08 100644
--- a/chromium/third_party/skia/src/sksl/README
+++ b/chromium/third_party/skia/src/sksl/README
@@ -150,10 +150,12 @@ Within an '.fp' fragment processor file:
The first variant emits the child with a solid white input color. The second
variant emits the child with the result of the 2nd argument's expression,
which must evaluate to a half4. The process function returns a half4.
-* By default, fragment processors must be non-null. The type for a nullable
- fragment processor is 'fragmentProcessor?', as in
- 'in fragmentProcessor? <name>'. You can check for the presence of such a
- fragment processor by comparing it to 'null'.
+* The 'fragmentProcessor' type cannot hold a null. Nullable fragment processors
+ should use the 'fragmentProcessor?' type: 'in fragmentProcessor? <name>'. You
+ can check for null fragment processors by comparing them against 'null', as
+ in: 'if (inputFP != null) { ... }'. Invoking 'sample()' on a null fragment
+ processor will return the inputColor unchanged (this defaults to solid white
+ if not explicitly specified).
Creating a new .fp file
diff --git a/chromium/third_party/skia/src/sksl/SkSLASTNode.cpp b/chromium/third_party/skia/src/sksl/SkSLASTNode.cpp
index 7c5a2033a0c..a74d5ab338b 100644
--- a/chromium/third_party/skia/src/sksl/SkSLASTNode.cpp
+++ b/chromium/third_party/skia/src/sksl/SkSLASTNode.cpp
@@ -34,7 +34,7 @@ String ASTNode::description() const {
return "break";
case Kind::kCall: {
auto iter = this->begin();
- String result = iter->description();
+ String result = (iter++)->description();
result += "(";
const char* separator = "";
while (iter != this->end()) {
@@ -230,6 +230,11 @@ String ASTNode::description() const {
}
return result;
}
+ case Kind::kWhile: {
+ return "while (" + this->begin()->description() + ") " +
+ (this->begin() + 1)->description();
+
+ }
default:
SkASSERT(false);
return "<error>";
diff --git a/chromium/third_party/skia/src/sksl/SkSLByteCode.cpp b/chromium/third_party/skia/src/sksl/SkSLByteCode.cpp
index 65e4301c4b9..132dc6d298e 100644
--- a/chromium/third_party/skia/src/sksl/SkSLByteCode.cpp
+++ b/chromium/third_party/skia/src/sksl/SkSLByteCode.cpp
@@ -61,6 +61,7 @@ static const uint8_t* DisassembleInstruction(const uint8_t* ip) {
printf("callexternal %d, %d, %d", argumentCount, returnCount, externalValue);
break;
}
+ VECTOR_DISASSEMBLE(kCeil, "ceil")
case ByteCodeInstruction::kClampIndex: printf("clampindex %d", READ8()); break;
VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
@@ -86,6 +87,7 @@ static const uint8_t* DisassembleInstruction(const uint8_t* ip) {
VECTOR_DISASSEMBLE(kDivideS, "divideS")
VECTOR_DISASSEMBLE(kDivideU, "divideu")
VECTOR_MATRIX_DISASSEMBLE(kDup, "dup")
+ VECTOR_DISASSEMBLE(kFloor, "floor")
VECTOR_DISASSEMBLE(kFract, "fract")
case ByteCodeInstruction::kInverse2x2: printf("inverse2x2"); break;
case ByteCodeInstruction::kInverse3x3: printf("inverse3x3"); break;
@@ -103,38 +105,12 @@ static const uint8_t* DisassembleInstruction(const uint8_t* ip) {
case ByteCodeInstruction::kLoadUniform2: printf("loaduniform2 %d", READ8()); break;
case ByteCodeInstruction::kLoadUniform3: printf("loaduniform3 %d", READ8()); break;
case ByteCodeInstruction::kLoadUniform4: printf("loaduniform4 %d", READ8()); break;
- case ByteCodeInstruction::kLoadSwizzle: {
- int target = READ8();
- int count = READ8();
- printf("loadswizzle %d %d", target, count);
- for (int i = 0; i < count; ++i) {
- printf(", %d", READ8());
- }
- break;
- }
- case ByteCodeInstruction::kLoadSwizzleGlobal: {
- int target = READ8();
- int count = READ8();
- printf("loadswizzleglobal %d %d", target, count);
- for (int i = 0; i < count; ++i) {
- printf(", %d", READ8());
- }
- break;
- }
- case ByteCodeInstruction::kLoadSwizzleUniform: {
- int target = READ8();
- int count = READ8();
- printf("loadswizzleuniform %d %d", target, count);
- for (int i = 0; i < count; ++i) {
- printf(", %d", READ8());
- }
- break;
- }
case ByteCodeInstruction::kLoadExtended: printf("loadextended %d", READ8()); break;
case ByteCodeInstruction::kLoadExtendedGlobal: printf("loadextendedglobal %d", READ8());
break;
case ByteCodeInstruction::kLoadExtendedUniform: printf("loadextendeduniform %d", READ8());
break;
+ case ByteCodeInstruction::kLoadFragCoord: printf("loadfragcoord"); break;
case ByteCodeInstruction::kMatrixToMatrix: {
int srcCols = READ8();
int srcRows = READ8();
@@ -178,6 +154,8 @@ static const uint8_t* DisassembleInstruction(const uint8_t* ip) {
VECTOR_DISASSEMBLE(kRemainderU, "remainderu")
case ByteCodeInstruction::kReserve: printf("reserve %d", READ8()); break;
case ByteCodeInstruction::kReturn: printf("return %d", READ8()); break;
+ case ByteCodeInstruction::kSampleExplicit: printf("sample %d", READ8()); break;
+ case ByteCodeInstruction::kSampleMatrix: printf("sampleMtx %d", READ8()); break;
case ByteCodeInstruction::kScalarToMatrix: {
int cols = READ8();
int rows = READ8();
@@ -197,40 +175,6 @@ static const uint8_t* DisassembleInstruction(const uint8_t* ip) {
case ByteCodeInstruction::kStoreGlobal2: printf("storeglobal2 %d", READ8()); break;
case ByteCodeInstruction::kStoreGlobal3: printf("storeglobal3 %d", READ8()); break;
case ByteCodeInstruction::kStoreGlobal4: printf("storeglobal4 %d", READ8()); break;
- case ByteCodeInstruction::kStoreSwizzle: {
- int target = READ8();
- int count = READ8();
- printf("storeswizzle %d %d", target, count);
- for (int i = 0; i < count; ++i) {
- printf(", %d", READ8());
- }
- break;
- }
- case ByteCodeInstruction::kStoreSwizzleGlobal: {
- int target = READ8();
- int count = READ8();
- printf("storeswizzleglobal %d %d", target, count);
- for (int i = 0; i < count; ++i) {
- printf(", %d", READ8());
- }
- break;
- }
- case ByteCodeInstruction::kStoreSwizzleIndirect: {
- int count = READ8();
- printf("storeswizzleindirect %d", count);
- for (int i = 0; i < count; ++i) {
- printf(", %d", READ8());
- }
- break;
- }
- case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
- int count = READ8();
- printf("storeswizzleindirectglobal %d", count);
- for (int i = 0; i < count; ++i) {
- printf(", %d", READ8());
- }
- break;
- }
case ByteCodeInstruction::kStoreExtended: printf("storeextended %d", READ8()); break;
case ByteCodeInstruction::kStoreExtendedGlobal: printf("storeextendedglobal %d", READ8());
break;
@@ -273,20 +217,23 @@ static const uint8_t* DisassembleInstruction(const uint8_t* ip) {
}
#define VECTOR_BINARY_OP(base, field, op) \
- case ByteCodeInstruction::base ## 4: \
+ case ByteCodeInstruction::base ## 4: { \
sp[-4] = sp[-4].field op sp[0].field; \
POP(); \
- /* fall through */ \
+ [[fallthrough]]; \
+ } \
case ByteCodeInstruction::base ## 3: { \
int count = (int)inst - (int)(ByteCodeInstruction::base) - 1; \
sp[count] = sp[count].field op sp[0].field; \
POP(); \
- } /* fall through */ \
+ [[fallthrough]]; \
+ } \
case ByteCodeInstruction::base ## 2: { \
int count = (int)inst - (int)(ByteCodeInstruction::base) - 1; \
sp[count] = sp[count].field op sp[0].field; \
POP(); \
- } /* fall through */ \
+ [[fallthrough]]; \
+ } \
case ByteCodeInstruction::base: { \
int count = (int)inst - (int)(ByteCodeInstruction::base) - 1; \
sp[count] = sp[count].field op sp[0].field; \
@@ -297,14 +244,15 @@ static const uint8_t* DisassembleInstruction(const uint8_t* ip) {
// A naive implementation of / or % using skvx operations will likely crash with a divide by zero
// in inactive vector lanes, so we need to be sure to avoid masked-off lanes.
#define VECTOR_BINARY_MASKED_OP(base, field, op) \
- case ByteCodeInstruction::base ## 4: \
+ case ByteCodeInstruction::base ## 4: { \
for (int i = 0; i < VecWidth; ++i) { \
if (mask()[i]) { \
sp[-4].field[i] op ## = sp[0].field[i]; \
} \
} \
POP(); \
- /* fall through */ \
+ [[fallthrough]]; \
+ } \
case ByteCodeInstruction::base ## 3: { \
int count = (int)inst - (int)(ByteCodeInstruction::base) - 1; \
for (int i = 0; i < VecWidth; ++i) { \
@@ -313,7 +261,8 @@ static const uint8_t* DisassembleInstruction(const uint8_t* ip) {
} \
} \
POP(); \
- } /* fall through */ \
+ [[fallthrough]]; \
+ } \
case ByteCodeInstruction::base ## 2: { \
int count = (int)inst - (int)(ByteCodeInstruction::base) - 1; \
for (int i = 0; i < VecWidth; ++i) { \
@@ -322,7 +271,8 @@ static const uint8_t* DisassembleInstruction(const uint8_t* ip) {
} \
} \
POP(); \
- } /* fall through */ \
+ [[fallthrough]]; \
+ } \
case ByteCodeInstruction::base: { \
int count = (int)inst - (int)(ByteCodeInstruction::base) - 1; \
for (int i = 0; i < VecWidth; ++i) { \
@@ -347,20 +297,23 @@ static const uint8_t* DisassembleInstruction(const uint8_t* ip) {
}
#define VECTOR_BINARY_FN(base, field, fn) \
- case ByteCodeInstruction::base ## 4: \
+ case ByteCodeInstruction::base ## 4: { \
sp[-4] = fn(sp[-4].field, sp[0].field); \
POP(); \
- /* fall through */ \
+ [[fallthrough]]; \
+ } \
case ByteCodeInstruction::base ## 3: { \
int count = (int)inst - (int)(ByteCodeInstruction::base) - 1; \
sp[count] = fn(sp[count].field, sp[0].field); \
POP(); \
- } /* fall through */ \
+ [[fallthrough]]; \
+ } \
case ByteCodeInstruction::base ## 2: { \
int count = (int)inst - (int)(ByteCodeInstruction::base) - 1; \
sp[count] = fn(sp[count].field, sp[0].field); \
POP(); \
- } /* fall through */ \
+ [[fallthrough]]; \
+ } \
case ByteCodeInstruction::base: { \
int count = (int)inst - (int)(ByteCodeInstruction::base) - 1; \
sp[count] = fn(sp[count].field, sp[0].field); \
@@ -368,11 +321,11 @@ static const uint8_t* DisassembleInstruction(const uint8_t* ip) {
continue; \
}
-#define VECTOR_UNARY_FN(base, fn, field) \
- case ByteCodeInstruction::base ## 4: sp[-3] = fn(sp[-3].field); \
- case ByteCodeInstruction::base ## 3: sp[-2] = fn(sp[-2].field); \
- case ByteCodeInstruction::base ## 2: sp[-1] = fn(sp[-1].field); \
- case ByteCodeInstruction::base: sp[ 0] = fn(sp[ 0].field); \
+#define VECTOR_UNARY_FN(base, fn, field) \
+ case ByteCodeInstruction::base ## 4: sp[-3] = fn(sp[-3].field); [[fallthrough]]; \
+ case ByteCodeInstruction::base ## 3: sp[-2] = fn(sp[-2].field); [[fallthrough]]; \
+ case ByteCodeInstruction::base ## 2: sp[-1] = fn(sp[-1].field); [[fallthrough]]; \
+ case ByteCodeInstruction::base: sp[ 0] = fn(sp[ 0].field); \
continue;
union VValue {
@@ -561,9 +514,9 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
sp[-1] = sp[-1].fSigned & sp[0].fSigned;
POP();
continue;
- case ByteCodeInstruction::kNotB4: sp[-3] = ~sp[-3].fSigned;
- case ByteCodeInstruction::kNotB3: sp[-2] = ~sp[-2].fSigned;
- case ByteCodeInstruction::kNotB2: sp[-1] = ~sp[-1].fSigned;
+ case ByteCodeInstruction::kNotB4: sp[-3] = ~sp[-3].fSigned; [[fallthrough]];
+ case ByteCodeInstruction::kNotB3: sp[-2] = ~sp[-2].fSigned; [[fallthrough]];
+ case ByteCodeInstruction::kNotB2: sp[-1] = ~sp[-1].fSigned; [[fallthrough]];
case ByteCodeInstruction::kNotB: sp[ 0] = ~sp[ 0].fSigned;
continue;
case ByteCodeInstruction::kOrB:
@@ -603,6 +556,8 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
continue;
}
+ VECTOR_UNARY_FN(kCeil, skvx::ceil, fFloat)
+
case ByteCodeInstruction::kClampIndex: {
int length = READ8();
if (skvx::any(mask() & ((sp[0].fSigned < 0) | (sp[0].fSigned >= length)))) {
@@ -628,23 +583,44 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
VECTOR_BINARY_OP(kCompareULTEQ, fUnsigned, <=)
VECTOR_BINARY_OP(kCompareFLTEQ, fFloat, <=)
- case ByteCodeInstruction::kConvertFtoI4: sp[-3] = skvx::cast<int>(sp[-3].fFloat);
- case ByteCodeInstruction::kConvertFtoI3: sp[-2] = skvx::cast<int>(sp[-2].fFloat);
- case ByteCodeInstruction::kConvertFtoI2: sp[-1] = skvx::cast<int>(sp[-1].fFloat);
- case ByteCodeInstruction::kConvertFtoI: sp[ 0] = skvx::cast<int>(sp[ 0].fFloat);
- continue;
+ case ByteCodeInstruction::kConvertFtoI4:
+ sp[-3] = skvx::cast<int>(sp[-3].fFloat);
+ [[fallthrough]];
+ case ByteCodeInstruction::kConvertFtoI3:
+ sp[-2] = skvx::cast<int>(sp[-2].fFloat);
+ [[fallthrough]];
+ case ByteCodeInstruction::kConvertFtoI2:
+ sp[-1] = skvx::cast<int>(sp[-1].fFloat);
+ [[fallthrough]];
+ case ByteCodeInstruction::kConvertFtoI:
+ sp[ 0] = skvx::cast<int>(sp[ 0].fFloat);
+ continue;
- case ByteCodeInstruction::kConvertStoF4: sp[-3] = skvx::cast<float>(sp[-3].fSigned);
- case ByteCodeInstruction::kConvertStoF3: sp[-2] = skvx::cast<float>(sp[-2].fSigned);
- case ByteCodeInstruction::kConvertStoF2: sp[-1] = skvx::cast<float>(sp[-1].fSigned);
- case ByteCodeInstruction::kConvertStoF: sp[ 0] = skvx::cast<float>(sp[ 0].fSigned);
- continue;
+ case ByteCodeInstruction::kConvertStoF4:
+ sp[-3] = skvx::cast<float>(sp[-3].fSigned);
+ [[fallthrough]];
+ case ByteCodeInstruction::kConvertStoF3:
+ sp[-2] = skvx::cast<float>(sp[-2].fSigned);
+ [[fallthrough]];
+ case ByteCodeInstruction::kConvertStoF2:
+ sp[-1] = skvx::cast<float>(sp[-1].fSigned);
+ [[fallthrough]];
+ case ByteCodeInstruction::kConvertStoF:
+ sp[ 0] = skvx::cast<float>(sp[ 0].fSigned);
+ continue;
- case ByteCodeInstruction::kConvertUtoF4: sp[-3] = skvx::cast<float>(sp[-3].fUnsigned);
- case ByteCodeInstruction::kConvertUtoF3: sp[-2] = skvx::cast<float>(sp[-2].fUnsigned);
- case ByteCodeInstruction::kConvertUtoF2: sp[-1] = skvx::cast<float>(sp[-1].fUnsigned);
- case ByteCodeInstruction::kConvertUtoF: sp[ 0] = skvx::cast<float>(sp[ 0].fUnsigned);
- continue;
+ case ByteCodeInstruction::kConvertUtoF4:
+ sp[-3] = skvx::cast<float>(sp[-3].fUnsigned);
+ [[fallthrough]];
+ case ByteCodeInstruction::kConvertUtoF3:
+ sp[-2] = skvx::cast<float>(sp[-2].fUnsigned);
+ [[fallthrough]];
+ case ByteCodeInstruction::kConvertUtoF2:
+ sp[-1] = skvx::cast<float>(sp[-1].fUnsigned);
+ [[fallthrough]];
+ case ByteCodeInstruction::kConvertUtoF:
+ sp[ 0] = skvx::cast<float>(sp[ 0].fUnsigned);
+ continue;
VECTOR_UNARY_FN(kCos, skvx::cos, fFloat)
@@ -652,11 +628,18 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
VECTOR_BINARY_MASKED_OP(kDivideU, fUnsigned, /)
VECTOR_MATRIX_BINARY_OP(kDivideF, fFloat, /)
- case ByteCodeInstruction::kDup4: PUSH(sp[(int)inst - (int)ByteCodeInstruction::kDup]);
- case ByteCodeInstruction::kDup3: PUSH(sp[(int)inst - (int)ByteCodeInstruction::kDup]);
- case ByteCodeInstruction::kDup2: PUSH(sp[(int)inst - (int)ByteCodeInstruction::kDup]);
- case ByteCodeInstruction::kDup : PUSH(sp[(int)inst - (int)ByteCodeInstruction::kDup]);
- continue;
+ case ByteCodeInstruction::kDup4:
+ PUSH(sp[(int)inst - (int)ByteCodeInstruction::kDup]);
+ [[fallthrough]];
+ case ByteCodeInstruction::kDup3:
+ PUSH(sp[(int)inst - (int)ByteCodeInstruction::kDup]);
+ [[fallthrough]];
+ case ByteCodeInstruction::kDup2:
+ PUSH(sp[(int)inst - (int)ByteCodeInstruction::kDup]);
+ [[fallthrough]];
+ case ByteCodeInstruction::kDup :
+ PUSH(sp[(int)inst - (int)ByteCodeInstruction::kDup]);
+ continue;
case ByteCodeInstruction::kDupN: {
int count = READ8();
@@ -665,6 +648,7 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
continue;
}
+ VECTOR_UNARY_FN(kFloor, skvx::floor, fFloat)
VECTOR_UNARY_FN(kFract, skvx::fract, fFloat)
case ByteCodeInstruction::kInverse2x2:
@@ -692,29 +676,36 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
continue;
}
- case ByteCodeInstruction::kLoad4: sp[4] = stack[*ip + 3];
- case ByteCodeInstruction::kLoad3: sp[3] = stack[*ip + 2];
- case ByteCodeInstruction::kLoad2: sp[2] = stack[*ip + 1];
+ case ByteCodeInstruction::kLoad4: sp[4] = stack[*ip + 3]; [[fallthrough]];
+ case ByteCodeInstruction::kLoad3: sp[3] = stack[*ip + 2]; [[fallthrough]];
+ case ByteCodeInstruction::kLoad2: sp[2] = stack[*ip + 1]; [[fallthrough]];
case ByteCodeInstruction::kLoad: sp[1] = stack[*ip + 0];
++ip;
sp += (int)ByteCodeInstruction::kLoad - (int)inst + 1;
continue;
- case ByteCodeInstruction::kLoadGlobal4: sp[4] = globals[*ip + 3];
- case ByteCodeInstruction::kLoadGlobal3: sp[3] = globals[*ip + 2];
- case ByteCodeInstruction::kLoadGlobal2: sp[2] = globals[*ip + 1];
+ case ByteCodeInstruction::kLoadGlobal4: sp[4] = globals[*ip + 3]; [[fallthrough]];
+ case ByteCodeInstruction::kLoadGlobal3: sp[3] = globals[*ip + 2]; [[fallthrough]];
+ case ByteCodeInstruction::kLoadGlobal2: sp[2] = globals[*ip + 1]; [[fallthrough]];
case ByteCodeInstruction::kLoadGlobal: sp[1] = globals[*ip + 0];
++ip;
sp += (int)ByteCodeInstruction::kLoadGlobal - (int)inst + 1;
continue;
- case ByteCodeInstruction::kLoadUniform4: sp[4].fFloat = uniforms[*ip + 3];
- case ByteCodeInstruction::kLoadUniform3: sp[3].fFloat = uniforms[*ip + 2];
- case ByteCodeInstruction::kLoadUniform2: sp[2].fFloat = uniforms[*ip + 1];
- case ByteCodeInstruction::kLoadUniform: sp[1].fFloat = uniforms[*ip + 0];
- ++ip;
- sp += (int)ByteCodeInstruction::kLoadUniform - (int)inst + 1;
- continue;
+ case ByteCodeInstruction::kLoadUniform4:
+ sp[4].fFloat = uniforms[*ip + 3];
+ [[fallthrough]];
+ case ByteCodeInstruction::kLoadUniform3:
+ sp[3].fFloat = uniforms[*ip + 2];
+ [[fallthrough]];
+ case ByteCodeInstruction::kLoadUniform2:
+ sp[2].fFloat = uniforms[*ip + 1];
+ [[fallthrough]];
+ case ByteCodeInstruction::kLoadUniform:
+ sp[1].fFloat = uniforms[*ip + 0];
+ ++ip;
+ sp += (int)ByteCodeInstruction::kLoadUniform - (int)inst + 1;
+ continue;
case ByteCodeInstruction::kLoadExtended: {
int count = READ8();
@@ -761,36 +752,6 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
continue;
}
- case ByteCodeInstruction::kLoadSwizzle: {
- int src = READ8();
- int count = READ8();
- for (int i = 0; i < count; ++i) {
- PUSH(stack[src + *(ip + i)]);
- }
- ip += count;
- continue;
- }
-
- case ByteCodeInstruction::kLoadSwizzleGlobal: {
- int src = READ8();
- int count = READ8();
- for (int i = 0; i < count; ++i) {
- PUSH(globals[src + *(ip + i)]);
- }
- ip += count;
- continue;
- }
-
- case ByteCodeInstruction::kLoadSwizzleUniform: {
- int src = READ8();
- int count = READ8();
- for (int i = 0; i < count; ++i) {
- PUSH(F32(uniforms[src + *(ip + i)]));
- }
- ip += count;
- continue;
- }
-
case ByteCodeInstruction::kMatrixToMatrix: {
int srcCols = READ8();
int srcRows = READ8();
@@ -860,9 +821,9 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
VECTOR_BINARY_OP(kMultiplyI, fSigned, *)
VECTOR_MATRIX_BINARY_OP(kMultiplyF, fFloat, *)
- case ByteCodeInstruction::kNegateF4: sp[-3] = -sp[-3].fFloat;
- case ByteCodeInstruction::kNegateF3: sp[-2] = -sp[-2].fFloat;
- case ByteCodeInstruction::kNegateF2: sp[-1] = -sp[-1].fFloat;
+ case ByteCodeInstruction::kNegateF4: sp[-3] = -sp[-3].fFloat; [[fallthrough]];
+ case ByteCodeInstruction::kNegateF3: sp[-2] = -sp[-2].fFloat; [[fallthrough]];
+ case ByteCodeInstruction::kNegateF2: sp[-1] = -sp[-1].fFloat; [[fallthrough]];
case ByteCodeInstruction::kNegateF: sp[ 0] = -sp[ 0].fFloat;
continue;
@@ -874,15 +835,15 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
continue;
}
- case ByteCodeInstruction::kNegateI4: sp[-3] = -sp[-3].fSigned;
- case ByteCodeInstruction::kNegateI3: sp[-2] = -sp[-2].fSigned;
- case ByteCodeInstruction::kNegateI2: sp[-1] = -sp[-1].fSigned;
+ case ByteCodeInstruction::kNegateI4: sp[-3] = -sp[-3].fSigned; [[fallthrough]];
+ case ByteCodeInstruction::kNegateI3: sp[-2] = -sp[-2].fSigned; [[fallthrough]];
+ case ByteCodeInstruction::kNegateI2: sp[-1] = -sp[-1].fSigned; [[fallthrough]];
case ByteCodeInstruction::kNegateI: sp[ 0] = -sp[ 0].fSigned;
continue;
- case ByteCodeInstruction::kPop4: POP();
- case ByteCodeInstruction::kPop3: POP();
- case ByteCodeInstruction::kPop2: POP();
+ case ByteCodeInstruction::kPop4: POP(); [[fallthrough]];
+ case ByteCodeInstruction::kPop3: POP(); [[fallthrough]];
+ case ByteCodeInstruction::kPop2: POP(); [[fallthrough]];
case ByteCodeInstruction::kPop: POP();
continue;
@@ -993,10 +954,13 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
case ByteCodeInstruction::kStore4:
stack[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+3].fFloat);
+ [[fallthrough]];
case ByteCodeInstruction::kStore3:
stack[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+2].fFloat);
+ [[fallthrough]];
case ByteCodeInstruction::kStore2:
stack[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+1].fFloat);
+ [[fallthrough]];
case ByteCodeInstruction::kStore:
stack[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, stack[*ip+0].fFloat);
++ip;
@@ -1004,10 +968,13 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
case ByteCodeInstruction::kStoreGlobal4:
globals[*ip+3] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+3].fFloat);
+ [[fallthrough]];
case ByteCodeInstruction::kStoreGlobal3:
globals[*ip+2] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+2].fFloat);
+ [[fallthrough]];
case ByteCodeInstruction::kStoreGlobal2:
globals[*ip+1] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+1].fFloat);
+ [[fallthrough]];
case ByteCodeInstruction::kStoreGlobal:
globals[*ip+0] = skvx::if_then_else(mask(), POP().fFloat, globals[*ip+0].fFloat);
++ip;
@@ -1044,60 +1011,6 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
continue;
}
- case ByteCodeInstruction::kStoreSwizzle: {
- int target = READ8();
- int count = READ8();
- for (int i = count - 1; i >= 0; --i) {
- stack[target + *(ip + i)] = skvx::if_then_else(
- mask(), POP().fFloat, stack[target + *(ip + i)].fFloat);
- }
- ip += count;
- continue;
- }
-
- case ByteCodeInstruction::kStoreSwizzleGlobal: {
- int target = READ8();
- int count = READ8();
- for (int i = count - 1; i >= 0; --i) {
- globals[target + *(ip + i)] = skvx::if_then_else(
- mask(), POP().fFloat, globals[target + *(ip + i)].fFloat);
- }
- ip += count;
- continue;
- }
-
- case ByteCodeInstruction::kStoreSwizzleIndirect: {
- int count = READ8();
- I32 target = POP().fSigned;
- I32 m = mask();
- for (int i = count - 1; i >= 0; --i) {
- I32 v = POP().fSigned;
- for (int j = 0; j < VecWidth; ++j) {
- if (m[j]) {
- stack[target[j] + *(ip + i)].fSigned[j] = v[j];
- }
- }
- }
- ip += count;
- continue;
- }
-
- case ByteCodeInstruction::kStoreSwizzleIndirectGlobal: {
- int count = READ8();
- I32 target = POP().fSigned;
- I32 m = mask();
- for (int i = count - 1; i >= 0; --i) {
- I32 v = POP().fSigned;
- for (int j = 0; j < VecWidth; ++j) {
- if (m[j]) {
- globals[target[j] + *(ip + i)].fSigned[j] = v[j];
- }
- }
- }
- ip += count;
- continue;
- }
-
VECTOR_BINARY_OP(kSubtractI, fSigned, -)
VECTOR_MATRIX_BINARY_OP(kSubtractF, fFloat, -)
@@ -1188,6 +1101,14 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
*loopPtr &= ~m;
continue;
}
+
+ case ByteCodeInstruction::kLoadFragCoord:
+ case ByteCodeInstruction::kSampleExplicit:
+ case ByteCodeInstruction::kSampleMatrix:
+ default:
+ // TODO: Support these?
+ SkASSERT(false);
+ return false;
}
}
}
diff --git a/chromium/third_party/skia/src/sksl/SkSLByteCode.h b/chromium/third_party/skia/src/sksl/SkSLByteCode.h
index 0e98736910c..79f2befb886 100644
--- a/chromium/third_party/skia/src/sksl/SkSLByteCode.h
+++ b/chromium/third_party/skia/src/sksl/SkSLByteCode.h
@@ -34,6 +34,7 @@ enum class ByteCodeInstruction : uint16_t {
// Followed by three bytes indicating: the number of argument slots, the number of return slots,
// and the index of the external value to call
kCallExternal,
+ VECTOR(kCeil),
// For dynamic array access: Followed by byte indicating length of array
kClampIndex,
VECTOR(kCompareIEQ),
@@ -61,6 +62,7 @@ enum class ByteCodeInstruction : uint16_t {
VECTOR(kDivideU),
// Duplicates the top stack value
VECTOR_MATRIX(kDup),
+ VECTOR(kFloor),
VECTOR(kFract),
kInverse2x2,
kInverse3x3,
@@ -71,15 +73,13 @@ enum class ByteCodeInstruction : uint16_t {
VECTOR(kLoad),
VECTOR(kLoadGlobal),
VECTOR(kLoadUniform),
- // As kLoad/kLoadGlobal, then a count byte (1-4), and then one byte per swizzle component (0-3).
- kLoadSwizzle,
- kLoadSwizzleGlobal,
- kLoadSwizzleUniform,
// kLoadExtended* are fallback load ops when we lack a specialization. They are followed by a
// count byte, and get the slot to load from the top of the stack.
kLoadExtended,
kLoadExtendedGlobal,
kLoadExtendedUniform,
+ // Loads "sk_FragCoord" [X, Y, Z, 1/W]
+ kLoadFragCoord,
// Followed by four bytes: srcCols, srcRows, dstCols, dstRows. Consumes the src matrix from the
// stack, and replaces it with the dst matrix. Per GLSL rules, there are no restrictions on
// dimensions. Any overlapping values are copied, and any other values are filled in with the
@@ -113,6 +113,11 @@ enum class ByteCodeInstruction : uint16_t {
kReserve,
// Followed by a byte indicating the number of slots being returned
kReturn,
+ // kSampleExplicit/kSampleMatrix are followed by a byte indicating the FP slot to sample
+ // Expects stack to contain (X, Y), produces (R, G, B, A)
+ kSampleExplicit,
+ // Expects stack to contain a 3x3 matrix, produces (R, G, B, A)
+ kSampleMatrix,
// Followed by two bytes indicating columns and rows of matrix (2, 3, or 4 each).
// Takes a single value from the top of the stack, and converts to a CxR matrix with that value
// replicated along the diagonal (and zero elsewhere), per the GLSL matrix construction rules.
@@ -129,14 +134,6 @@ enum class ByteCodeInstruction : uint16_t {
// Fallback stores. Followed by count byte, and get the slot to store from the top of the stack
kStoreExtended,
kStoreExtendedGlobal,
- // As kStore/kStoreGlobal, then a count byte (1-4), then one byte per swizzle component (0-3).
- // Expects the stack to look like: ... v1 v2 v3 v4, where the number of 'v's is equal to the
- // number of swizzle components. After the store, all v's are popped from the stack.
- kStoreSwizzle,
- kStoreSwizzleGlobal,
- // As above, but gets the store slot from the top of the stack (before values to be stored)
- kStoreSwizzleIndirect,
- kStoreSwizzleIndirectGlobal,
// Followed by two count bytes (1-4), and then one byte per swizzle component (0-3). The first
// count byte provides the current vector size (the vector is the top n stack elements), and the
// second count byte provides the swizzle component count.
@@ -276,6 +273,12 @@ public:
}
const Uniform& getUniform(int i) const { return fUniforms[i]; }
+ /**
+ * Some byte code programs can't be executed by the interpreter, due to unsupported features.
+ * They may still be used to convert to other formats, or for reflection of uniforms.
+ */
+ bool canRun() const { return fChildFPCount == 0 && !fUsesFragCoord; }
+
private:
ByteCode(const ByteCode&) = delete;
ByteCode& operator=(const ByteCode&) = delete;
@@ -285,6 +288,8 @@ private:
int fGlobalSlotCount = 0;
int fUniformSlotCount = 0;
+ int fChildFPCount = 0;
+ bool fUsesFragCoord = false;
std::vector<Uniform> fUniforms;
std::vector<std::unique_ptr<ByteCodeFunction>> fFunctions;
diff --git a/chromium/third_party/skia/src/sksl/SkSLByteCodeGenerator.cpp b/chromium/third_party/skia/src/sksl/SkSLByteCodeGenerator.cpp
index c625051ff0d..819a1a3c44e 100644
--- a/chromium/third_party/skia/src/sksl/SkSLByteCodeGenerator.cpp
+++ b/chromium/third_party/skia/src/sksl/SkSLByteCodeGenerator.cpp
@@ -46,21 +46,25 @@ ByteCodeGenerator::ByteCodeGenerator(const Context* context, const Program* prog
// they're available to "generic" interpreter programs (eg particles).
// You can probably copy the declarations from sksl_gpu.inc.
, fIntrinsics {
- { "atan", ByteCodeInstruction::kATan },
- { "clamp", SpecialIntrinsic::kClamp },
- { "cos", ByteCodeInstruction::kCos },
- { "dot", SpecialIntrinsic::kDot },
- { "fract", ByteCodeInstruction::kFract },
- { "inverse", ByteCodeInstruction::kInverse2x2 },
- { "length", SpecialIntrinsic::kLength },
- { "max", SpecialIntrinsic::kMax },
- { "min", SpecialIntrinsic::kMin },
- { "mix", SpecialIntrinsic::kMix },
- { "pow", ByteCodeInstruction::kPow },
- { "saturate", SpecialIntrinsic::kSaturate },
- { "sin", ByteCodeInstruction::kSin },
- { "sqrt", ByteCodeInstruction::kSqrt },
- { "tan", ByteCodeInstruction::kTan },
+ { "atan", ByteCodeInstruction::kATan },
+ { "ceil", ByteCodeInstruction::kCeil },
+ { "clamp", SpecialIntrinsic::kClamp },
+ { "cos", ByteCodeInstruction::kCos },
+ { "dot", SpecialIntrinsic::kDot },
+ { "floor", ByteCodeInstruction::kFloor },
+ { "fract", ByteCodeInstruction::kFract },
+ { "inverse", ByteCodeInstruction::kInverse2x2 },
+ { "length", SpecialIntrinsic::kLength },
+ { "max", SpecialIntrinsic::kMax },
+ { "min", SpecialIntrinsic::kMin },
+ { "mix", SpecialIntrinsic::kMix },
+ { "normalize", SpecialIntrinsic::kNormalize },
+ { "pow", ByteCodeInstruction::kPow },
+ { "sample", SpecialIntrinsic::kSample },
+ { "saturate", SpecialIntrinsic::kSaturate },
+ { "sin", ByteCodeInstruction::kSin },
+ { "sqrt", ByteCodeInstruction::kSqrt },
+ { "tan", ByteCodeInstruction::kTan },
{ "lessThan", { ByteCodeInstruction::kCompareFLT,
ByteCodeInstruction::kCompareSLT,
@@ -150,6 +154,9 @@ bool ByteCodeGenerator::generateCode() {
VarDeclarations& decl = (VarDeclarations&) e;
for (const auto& v : decl.fVars) {
const Variable* declVar = ((VarDeclaration&) *v).fVar;
+ if (declVar->fType == *fContext.fFragmentProcessor_Type) {
+ fOutput->fChildFPCount++;
+ }
if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
continue;
}
@@ -200,10 +207,27 @@ std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const Functio
return result;
}
+// If the expression is a reference to a builtin global variable, return the builtin ID.
+// Otherwise, return -1.
+static int expression_as_builtin(const Expression& e) {
+ if (e.fKind == Expression::kVariableReference_Kind) {
+ const Variable& var(((VariableReference&)e).fVariable);
+ if (var.fStorage == Variable::kGlobal_Storage) {
+ return var.fModifiers.fLayout.fBuiltin;
+ }
+ }
+ return -1;
+}
+
// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
// that references consecutive values, such that it can be implemented using normal load/store ops
// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
static bool swizzle_is_simple(const Swizzle& s) {
+ // Builtin variables use dedicated instructions that don't allow subset loads
+ if (expression_as_builtin(*s.fBase) >= 0) {
+ return false;
+ }
+
switch (s.fBase->fKind) {
case Expression::kFieldAccess_Kind:
case Expression::kIndex_Kind:
@@ -253,7 +277,9 @@ int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
VECTOR_UNARY_OP(kConvertUtoF)
VECTOR_UNARY_OP(kATan)
+ VECTOR_UNARY_OP(kCeil)
VECTOR_UNARY_OP(kCos)
+ VECTOR_UNARY_OP(kFloor)
VECTOR_UNARY_OP(kFract)
VECTOR_UNARY_OP(kSin)
VECTOR_UNARY_OP(kSqrt)
@@ -357,12 +383,10 @@ int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
case ByteCodeInstruction::kLoadGlobal4:
case ByteCodeInstruction::kLoadUniform4:
case ByteCodeInstruction::kReadExternal4:
+ case ByteCodeInstruction::kLoadFragCoord:
return 4;
case ByteCodeInstruction::kDupN:
- case ByteCodeInstruction::kLoadSwizzle:
- case ByteCodeInstruction::kLoadSwizzleGlobal:
- case ByteCodeInstruction::kLoadSwizzleUniform:
return count;
// Pushes 'count' values, minus one for the 'address' that's consumed first
@@ -397,15 +421,11 @@ int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
return -4;
case ByteCodeInstruction::kPopN:
- case ByteCodeInstruction::kStoreSwizzle:
- case ByteCodeInstruction::kStoreSwizzleGlobal:
return -count;
// Consumes 'count' values, plus one for the 'address'
case ByteCodeInstruction::kStoreExtended:
case ByteCodeInstruction::kStoreExtendedGlobal:
- case ByteCodeInstruction::kStoreSwizzleIndirect:
- case ByteCodeInstruction::kStoreSwizzleIndirectGlobal:
return -count - 1;
// Strange ops where the caller computes the delta for us:
@@ -420,6 +440,11 @@ int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
// Miscellaneous
+ // (X, Y) -> (R, G, B, A)
+ case ByteCodeInstruction::kSampleExplicit: return 4 - 2;
+ // (float3x3) -> (R, G, B, A)
+ case ByteCodeInstruction::kSampleMatrix: return 4 - 9;
+
// kMix does a 3 -> 1 reduction (A, B, M -> A -or- B) for each component
case ByteCodeInstruction::kMix: return -2;
case ByteCodeInstruction::kMix2: return -4;
@@ -485,6 +510,27 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var)
return Location::MakeInvalid();
}
case Variable::kGlobal_Storage: {
+ if (var.fType == *fContext.fFragmentProcessor_Type) {
+ int offset = 0;
+ for (const auto& e : fProgram) {
+ if (e.fKind == ProgramElement::kVar_Kind) {
+ VarDeclarations& decl = (VarDeclarations&) e;
+ for (const auto& v : decl.fVars) {
+ const Variable* declVar = ((VarDeclaration&) *v).fVar;
+ if (declVar->fType != *fContext.fFragmentProcessor_Type) {
+ continue;
+ }
+ if (declVar == &var) {
+ SkASSERT(offset <= 255);
+ return { offset, Storage::kChildFP };
+ }
+ offset++;
+ }
+ }
+ }
+ SkASSERT(false);
+ return Location::MakeInvalid();
+ }
if (is_in(var)) {
// If you see this error, it means the program is using raw 'in' variables. You
// should either specialize the program (Compiler::specialize) to bake in the final
@@ -987,27 +1033,41 @@ void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
}
void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
+ if (int builtin = expression_as_builtin(expr); builtin >= 0) {
+ switch (builtin) {
+ case SK_FRAGCOORD_BUILTIN:
+ this->write(ByteCodeInstruction::kLoadFragCoord);
+ fOutput->fUsesFragCoord = true;
+ break;
+ default:
+ fErrors.error(expr.fOffset, "Unsupported builtin");
+ break;
+ }
+ return;
+ }
+
Location location = this->getLocation(expr);
int count = SlotCount(expr.fType);
if (count == 0) {
return;
}
- if (location.isOnStack() || count > 4) {
- if (!location.isOnStack()) {
- this->write(ByteCodeInstruction::kPushImmediate);
- this->write32(location.fSlot);
- }
+ if (location.isOnStack()) {
this->write(location.selectLoad(ByteCodeInstruction::kLoadExtended,
ByteCodeInstruction::kLoadExtendedGlobal,
ByteCodeInstruction::kLoadExtendedUniform),
count);
this->write8(count);
} else {
- this->write(vector_instruction(location.selectLoad(ByteCodeInstruction::kLoad,
- ByteCodeInstruction::kLoadGlobal,
- ByteCodeInstruction::kLoadUniform),
- count));
- this->write8(location.fSlot);
+ while (count) {
+ int loadCount = std::min(count, 4);
+ this->write(vector_instruction(location.selectLoad(ByteCodeInstruction::kLoad,
+ ByteCodeInstruction::kLoadGlobal,
+ ByteCodeInstruction::kLoadUniform),
+ loadCount));
+ this->write8(location.fSlot);
+ count -= loadCount;
+ location.fSlot += loadCount;
+ }
}
}
@@ -1046,6 +1106,29 @@ void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
}
};
+ if (intrin.is_special && intrin.special == SpecialIntrinsic::kSample) {
+ // Sample is very special, the first argument is an FP, which can't be pushed to the stack
+ if (c.fArguments.size() != 2 ||
+ c.fArguments[0]->fType != *fContext.fFragmentProcessor_Type ||
+ (c.fArguments[1]->fType != *fContext.fFloat2_Type &&
+ c.fArguments[1]->fType != *fContext.fFloat3x3_Type)) {
+ fErrors.error(c.fOffset, "Unsupported form of sample");
+ return;
+ }
+
+ // Write our coords or matrix
+ this->writeExpression(*c.fArguments[1]);
+
+ this->write(c.fArguments[1]->fType == *fContext.fFloat3x3_Type
+ ? ByteCodeInstruction::kSampleMatrix
+ : ByteCodeInstruction::kSampleExplicit);
+
+ Location childLoc = this->getLocation(*c.fArguments[0]);
+ SkASSERT(childLoc.fStorage == Storage::kChildFP);
+ this->write8(childLoc.fSlot);
+ return;
+ }
+
if (intrin.is_special && (intrin.special == SpecialIntrinsic::kClamp ||
intrin.special == SpecialIntrinsic::kSaturate)) {
// These intrinsics are extra-special, we need instructions interleaved with arguments
@@ -1162,6 +1245,19 @@ void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
}
} break;
+ case SpecialIntrinsic::kNormalize: {
+ SkASSERT(c.fArguments.size() == 1);
+ this->write(vector_instruction(ByteCodeInstruction::kDup , count));
+ this->write(vector_instruction(ByteCodeInstruction::kDup , count));
+ this->write(vector_instruction(ByteCodeInstruction::kMultiplyF, count));
+ for (int i = count-1; i --> 0;) {
+ this->write(ByteCodeInstruction::kAddF);
+ }
+ this->write(ByteCodeInstruction::kSqrt);
+ dupSmallerType(1);
+ this->write(vector_instruction(ByteCodeInstruction::kDivideF, count));
+ } break;
+
default:
SkASSERT(false);
}
@@ -1375,29 +1471,12 @@ void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
return;
}
- switch (s.fBase->fKind) {
- case Expression::kVariableReference_Kind: {
- Location location = this->getLocation(*s.fBase);
- this->write(location.selectLoad(ByteCodeInstruction::kLoadSwizzle,
- ByteCodeInstruction::kLoadSwizzleGlobal,
- ByteCodeInstruction::kLoadSwizzleUniform),
- s.fComponents.size());
- this->write8(location.fSlot);
- this->write8(s.fComponents.size());
- for (int c : s.fComponents) {
- this->write8(c);
- }
- break;
- }
- default:
- this->writeExpression(*s.fBase);
- this->write(ByteCodeInstruction::kSwizzle,
- s.fComponents.size() - s.fBase->fType.columns());
- this->write8(s.fBase->fType.columns());
- this->write8(s.fComponents.size());
- for (int c : s.fComponents) {
- this->write8(c);
- }
+ this->writeExpression(*s.fBase);
+ this->write(ByteCodeInstruction::kSwizzle, s.fComponents.size() - s.fBase->fType.columns());
+ this->write8(s.fBase->fType.columns());
+ this->write8(s.fComponents.size());
+ for (int c : s.fComponents) {
+ this->write8(c);
}
}
@@ -1522,20 +1601,31 @@ public:
if (!discard) {
fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
}
- ByteCodeGenerator::Location location = fGenerator.getLocation(*fSwizzle.fBase);
- if (location.isOnStack()) {
- fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzleIndirect,
- ByteCodeInstruction::kStoreSwizzleIndirectGlobal),
- count);
- } else {
- fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreSwizzle,
- ByteCodeInstruction::kStoreSwizzleGlobal),
- count);
- fGenerator.write8(location.fSlot);
- }
- fGenerator.write8(count);
- for (int c : fSwizzle.fComponents) {
- fGenerator.write8(c);
+ // We already have the correct number of values on the stack, thanks to type checking.
+ // The algorithm: Walk down the values on the stack, doing 'count' single-element stores.
+ // For each value, use the corresponding swizzle component to offset the store location.
+ //
+ // Static locations: We (wastefully) call getLocation every time, but get good byte code.
+ // Note that we could (but don't) store adjacent/sequential values with fewer instructions.
+ //
+ // Dynamic locations: ... are bad. We have to recompute the base address on each iteration,
+ // because the stack doesn't let us retain that address between stores. Dynamic locations
+ // are rare though, and swizzled writes to those are even rarer, so we just live with this.
+ for (int i = count; i-- > 0;) {
+ ByteCodeGenerator::Location location = fGenerator.getLocation(*fSwizzle.fBase);
+ if (!location.isOnStack()) {
+ fGenerator.write(location.selectStore(ByteCodeInstruction::kStore,
+ ByteCodeInstruction::kStoreGlobal));
+ fGenerator.write8(location.fSlot + fSwizzle.fComponents[i]);
+ } else {
+ fGenerator.write(ByteCodeInstruction::kPushImmediate);
+ fGenerator.write32(fSwizzle.fComponents[i]);
+ fGenerator.write(ByteCodeInstruction::kAddI);
+ fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
+ ByteCodeInstruction::kStoreExtendedGlobal),
+ 1);
+ fGenerator.write8(1);
+ }
}
}
diff --git a/chromium/third_party/skia/src/sksl/SkSLByteCodeGenerator.h b/chromium/third_party/skia/src/sksl/SkSLByteCodeGenerator.h
index 02e186b9d00..9178c4fd16e 100644
--- a/chromium/third_party/skia/src/sksl/SkSLByteCodeGenerator.h
+++ b/chromium/third_party/skia/src/sksl/SkSLByteCodeGenerator.h
@@ -146,6 +146,8 @@ private:
kMax,
kMin,
kMix,
+ kNormalize,
+ kSample,
kSaturate,
};
@@ -170,6 +172,7 @@ private:
kLocal, // include parameters
kGlobal, // non-uniform globals
kUniform, // uniform globals
+ kChildFP, // child fragment processors
};
struct Location {
@@ -179,10 +182,14 @@ private:
// Not really invalid, but a "safe" placeholder to be more explicit at call-sites
static Location MakeInvalid() { return { 0, Storage::kLocal }; }
- Location makeOnStack() { return { -1, fStorage }; }
+ Location makeOnStack() {
+ SkASSERT(fStorage != Storage::kChildFP);
+ return { -1, fStorage };
+ }
bool isOnStack() const { return fSlot < 0; }
Location operator+(int offset) {
+ SkASSERT(fStorage != Storage::kChildFP);
SkASSERT(fSlot >= 0);
return { fSlot + offset, fStorage };
}
@@ -194,8 +201,9 @@ private:
case Storage::kLocal: return local;
case Storage::kGlobal: return global;
case Storage::kUniform: return uniform;
+ case Storage::kChildFP: ABORT("Trying to load an FP"); break;
}
- SkUNREACHABLE;
+ return local;
}
ByteCodeInstruction selectStore(ByteCodeInstruction local,
@@ -204,6 +212,7 @@ private:
case Storage::kLocal: return local;
case Storage::kGlobal: return global;
case Storage::kUniform: ABORT("Trying to store to a uniform"); break;
+ case Storage::kChildFP: ABORT("Trying to store an FP"); break;
}
return local;
}
diff --git a/chromium/third_party/skia/src/sksl/SkSLCPPCodeGenerator.cpp b/chromium/third_party/skia/src/sksl/SkSLCPPCodeGenerator.cpp
index 3042662cd21..66b020c4112 100644
--- a/chromium/third_party/skia/src/sksl/SkSLCPPCodeGenerator.cpp
+++ b/chromium/third_party/skia/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -23,11 +23,11 @@ static bool needs_uniform_var(const Variable& var) {
CPPCodeGenerator::CPPCodeGenerator(const Context* context, const Program* program,
ErrorReporter* errors, String name, OutputStream* out)
-: INHERITED(context, program, errors, out)
-, fName(std::move(name))
-, fFullName(String::printf("Gr%s", fName.c_str()))
-, fSectionAndParameterHelper(program, *errors) {
- fLineEnding = "\\n";
+ : INHERITED(context, program, errors, out)
+ , fName(std::move(name))
+ , fFullName(String::printf("Gr%s", fName.c_str()))
+ , fSectionAndParameterHelper(program, *errors) {
+ fLineEnding = "\n";
fTextureFunctionOverride = "sample";
}
@@ -36,7 +36,7 @@ void CPPCodeGenerator::writef(const char* s, va_list va) {
va_list copy;
va_copy(copy, va);
char buffer[BUFFER_SIZE];
- int length = vsnprintf(buffer, BUFFER_SIZE, s, va);
+ int length = std::vsnprintf(buffer, BUFFER_SIZE, s, va);
if (length < BUFFER_SIZE) {
fOut->write(buffer, length);
} else {
@@ -122,13 +122,17 @@ void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) {
return;
}
int64_t index = ((IntLiteral&) *i.fIndex).fValue;
+ if (index != 0) {
+ fErrors.error(i.fIndex->fOffset, "Only sk_TransformedCoords2D[0] is allowed");
+ return;
+ }
String name = "sk_TransformedCoords2D_" + to_string(index);
fFormatArgs.push_back(name + ".c_str()");
- if (fWrittenTransformedCoords.find(index) == fWrittenTransformedCoords.end()) {
+ if (!fAccessLocalCoordsDirectly) {
+ fAccessLocalCoordsDirectly = true;
addExtraEmitCodeLine("SkString " + name +
" = fragBuilder->ensureCoords2D(args.fTransformedCoords[" +
to_string(index) + "].fVaryingPoint, _outer.sampleMatrix());");
- fWrittenTransformedCoords.insert(index);
}
return;
} else if (SK_TEXTURESAMPLERS_BUILTIN == builtin) {
@@ -431,18 +435,19 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
// must be properly formatted with a prefixed comma when the parameter should be inserted
// into the invokeChild() parameter list.
String inputArg;
+ String inputColorName;
if (c.fArguments.size() > 1 && c.fArguments[1]->fType.name() == "half4") {
// Use the invokeChild() variant that accepts an input color, so convert the 2nd
// argument's expression into C++ code that produces sksl stored in an SkString.
- String inputName = "_input" + to_string(c.fOffset);
- addExtraEmitCodeLine(convertSKSLExpressionToCPP(*c.fArguments[1], inputName));
+ inputColorName = "_input" + to_string(c.fOffset);
+ addExtraEmitCodeLine(convertSKSLExpressionToCPP(*c.fArguments[1], inputColorName));
// invokeChild() needs a char*
- inputArg = ", " + inputName + ".c_str()";
+ inputArg = ", " + inputColorName + ".c_str()";
}
bool hasCoords = c.fArguments.back()->fType.name() == "float2";
- SampleMatrix matrix = fSectionAndParameterHelper.getMatrix(child);
+ SampleMatrix matrix = SampleMatrix::Make(fProgram, child);
// Write the output handling after the possible input handling
String childName = "_sample" + to_string(c.fOffset);
addExtraEmitCodeLine("SkString " + childName + ";");
@@ -481,14 +486,21 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
if (c.fArguments[0]->fType.kind() == Type::kNullable_Kind) {
// Null FPs are not emitted, but their output can still be referenced in dependent
// expressions - thus we always fill the variable with something.
- // Note: this is essentially dead code required to satisfy the compiler, because
- // 'process' function calls should always be guarded at a higher level, in the .fp
- // source.
- addExtraEmitCodeLine(
- "} else {"
- " " + childName + " = \"half4(1)\";"
- "}");
+ // Sampling from a null fragment processor will provide in the input color as-is. This
+ // defaults to half4(1) if no color is specified.
+ if (!inputColorName.empty()) {
+ addExtraEmitCodeLine(
+ "} else {"
+ " " + childName + ".swap(" + inputColorName + ");"
+ "}");
+ } else {
+ addExtraEmitCodeLine(
+ "} else {"
+ " " + childName + " = \"half4(1)\";"
+ "}");
+ }
}
+
this->write("%s");
fFormatArgs.push_back(childName + ".c_str()");
return;
@@ -557,6 +569,9 @@ static const char* glsltype_string(const Context& context, const Type& type) {
void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) {
const FunctionDeclaration& decl = f.fDeclaration;
+ if (decl.fBuiltin) {
+ return;
+ }
fFunctionHeader = "";
OutputStream* oldOut = fOut;
StringStream buffer;
@@ -594,7 +609,7 @@ void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) {
emit += ", \"" + decl.fName + "\"";
emit += ", " + to_string((int64_t) decl.fParameters.size());
emit += ", " + decl.fName + "_args";
- emit += ", \"" + buffer.str() + "\"";
+ emit += ",\nR\"SkSL(" + buffer.str() + ")SkSL\"";
emit += ", &" + decl.fName + "_name);";
this->addExtraEmitCodeLine(emit.c_str());
}
@@ -815,46 +830,33 @@ void CPPCodeGenerator::flushEmittedCode() {
}
void CPPCodeGenerator::writeCodeAppend(const String& code) {
- // codeAppendf can only handle appending 1024 bytes at a time, so we need to break the string
- // into chunks. Unfortunately we can't tell exactly how long the string is going to end up,
- // because printf escape sequences get replaced by strings of unknown length, but keeping the
- // format string below 512 bytes is probably safe.
- static constexpr size_t maxChunkSize = 512;
- size_t start = 0;
- size_t index = 0;
- size_t argStart = 0;
- size_t argCount;
- while (index < code.size()) {
- argCount = 0;
- this->write(" fragBuilder->codeAppendf(\"");
- while (index < code.size() && index < start + maxChunkSize) {
+ if (!code.empty()) {
+ // Count % format specifiers.
+ size_t argCount = 0;
+ for (size_t index = 0; index < code.size(); ++index) {
if ('%' == code[index]) {
- if (index == start + maxChunkSize - 1 || index == code.size() - 1) {
+ if (index == code.size() - 1) {
break;
}
if (code[index + 1] != '%') {
++argCount;
}
- } else if ('\\' == code[index] && index == start + maxChunkSize - 1) {
- // avoid splitting an escape sequence that happens to fall across a chunk boundary
- break;
}
- ++index;
}
- fOut->write(code.c_str() + start, index - start);
- this->write("\"");
- for (size_t i = argStart; i < argStart + argCount; ++i) {
+
+ // Emit the code string.
+ this->writef(" fragBuilder->codeAppendf(\n"
+ "R\"SkSL(%s)SkSL\"\n", code.c_str());
+ for (size_t i = 0; i < argCount; ++i) {
this->writef(", %s", fFormatArgs[i].c_str());
}
this->write(");\n");
- argStart += argCount;
- start = index;
- }
- // argStart is equal to the number of fFormatArgs that were consumed
- // so they should be removed from the list
- if (argStart > 0) {
- fFormatArgs.erase(fFormatArgs.begin(), fFormatArgs.begin() + argStart);
+ // argCount is equal to the number of fFormatArgs that were consumed, so they should be
+ // removed from the list.
+ if (argCount > 0) {
+ fFormatArgs.erase(fFormatArgs.begin(), fFormatArgs.begin() + argCount);
+ }
}
}
@@ -901,10 +903,14 @@ String CPPCodeGenerator::convertSKSLExpressionToCPP(const Expression& e,
// Now build the final C++ code snippet from the format string and args
String cppExpr;
- if (newArgs.size() == 0) {
+ if (newArgs.empty()) {
// This was a static expression, so we can simplify the input
// color declaration in the emitted code to just a static string
cppExpr = "SkString " + cppVar + "(\"" + exprFormat + "\");";
+ } else if (newArgs.size() == 1 && exprFormat == "%s") {
+ // If the format expression is simply "%s", we can avoid an expensive call to printf.
+ // This happens fairly often in codegen so it is worth simplifying.
+ cppExpr = "SkString " + cppVar + "(" + newArgs[0] + ");";
} else {
// String formatting must occur dynamically, so have the C++ declaration
// use SkStringPrintf with the format args that were accumulated
@@ -970,7 +976,7 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
"const GrFragmentProcessor& _proc) override {\n",
pdman);
bool wroteProcessor = false;
- for (const auto u : uniforms) {
+ for (const Variable* u : uniforms) {
if (is_uniform_in(*u)) {
if (!wroteProcessor) {
this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName, fullName);
@@ -1043,11 +1049,12 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
for (const auto& p : fProgram) {
if (ProgramElement::kVar_Kind == p.fKind) {
const VarDeclarations& decls = (const VarDeclarations&) p;
- for (const auto& raw : decls.fVars) {
- VarDeclaration& decl = (VarDeclaration&) *raw;
- String nameString(decl.fVar->fName);
+ for (const std::unique_ptr<Statement>& raw : decls.fVars) {
+ const VarDeclaration& decl = static_cast<VarDeclaration&>(*raw);
+ const Variable& variable = *decl.fVar;
+ String nameString(variable.fName);
const char* name = nameString.c_str();
- if (decl.fVar->fType.kind() == Type::kSampler_Kind) {
+ if (variable.fType.kind() == Type::kSampler_Kind) {
this->writef(" const GrSurfaceProxyView& %sView = "
"_outer.textureSampler(%d).view();\n",
name, samplerIndex);
@@ -1055,20 +1062,23 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
name, name);
this->writef(" (void) %s;\n", name);
++samplerIndex;
- } else if (needs_uniform_var(*decl.fVar)) {
+ } else if (needs_uniform_var(variable)) {
this->writef(" UniformHandle& %s = %sVar;\n"
" (void) %s;\n",
name, HCodeGenerator::FieldName(name).c_str(), name);
- } else if (SectionAndParameterHelper::IsParameter(*decl.fVar) &&
- decl.fVar->fType != *fContext.fFragmentProcessor_Type) {
+ } else if (SectionAndParameterHelper::IsParameter(variable) &&
+ variable.fType != *fContext.fFragmentProcessor_Type) {
if (!wroteProcessor) {
this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName,
fullName);
wroteProcessor = true;
}
- this->writef(" auto %s = _outer.%s;\n"
- " (void) %s;\n",
- name, name, name);
+
+ if (variable.fType.nonnullable() != *fContext.fFragmentProcessor_Type) {
+ this->writef(" auto %s = _outer.%s;\n"
+ " (void) %s;\n",
+ name, name, name);
+ }
}
}
}
@@ -1116,13 +1126,9 @@ void CPPCodeGenerator::writeClone() {
String fieldName = HCodeGenerator::CoordTransformName(s.fArgument, i);
this->writef("\n, %s(src.%s)", fieldName.c_str(), fieldName.c_str());
}
- for (const auto& param : fSectionAndParameterHelper.getParameters()) {
+ for (const Variable* param : fSectionAndParameterHelper.getParameters()) {
String fieldName = HCodeGenerator::FieldName(String(param->fName).c_str());
- if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
- this->writef("\n, %s_index(src.%s_index)",
- fieldName.c_str(),
- fieldName.c_str());
- } else {
+ if (param->fType.nonnullable() != *fContext.fFragmentProcessor_Type) {
this->writef("\n, %s(src.%s)",
fieldName.c_str(),
fieldName.c_str());
@@ -1136,18 +1142,14 @@ void CPPCodeGenerator::writeClone() {
} else if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
String fieldName = HCodeGenerator::FieldName(String(param->fName).c_str());
if (param->fType.kind() == Type::kNullable_Kind) {
- this->writef(" if (%s_index >= 0) {\n", fieldName.c_str());
+ this->writef(" if (src.%s_index >= 0) {\n", fieldName.c_str());
} else {
this->write(" {\n");
}
- this->writef(
- " auto clone = src.childProcessor(%s_index).clone();\n"
- " if (src.childProcessor(%s_index).isSampledWithExplicitCoords()) {\n"
- " clone->setSampledWithExplicitCoords();\n"
- " }"
- " this->registerChildProcessor(std::move(clone));\n"
- " }\n",
- fieldName.c_str(), fieldName.c_str());
+ this->writef(" %s_index = this->cloneAndRegisterChildProcessor("
+ "src.childProcessor(src.%s_index));\n"
+ " }\n",
+ fieldName.c_str(), fieldName.c_str());
}
}
if (samplerCount) {
diff --git a/chromium/third_party/skia/src/sksl/SkSLCPPCodeGenerator.h b/chromium/third_party/skia/src/sksl/SkSLCPPCodeGenerator.h
index 803270cc575..357e7c1ef48 100644
--- a/chromium/third_party/skia/src/sksl/SkSLCPPCodeGenerator.h
+++ b/chromium/third_party/skia/src/sksl/SkSLCPPCodeGenerator.h
@@ -123,7 +123,9 @@ private:
std::vector<String> fExtraEmitCodeBlocks;
std::vector<String> fFormatArgs;
- std::set<int> fWrittenTransformedCoords;
+ // true if the sksl referenced sk_TransformedCoords[0]
+ bool fAccessLocalCoordsDirectly = false;
+
// if true, we are writing a C++ expression instead of a GLSL expression
bool fCPPMode = false;
bool fInMain = false;
diff --git a/chromium/third_party/skia/src/sksl/SkSLCPPUniformCTypes.cpp b/chromium/third_party/skia/src/sksl/SkSLCPPUniformCTypes.cpp
index 061ad55c711..f18c410f2a1 100644
--- a/chromium/third_party/skia/src/sksl/SkSLCPPUniformCTypes.cpp
+++ b/chromium/third_party/skia/src/sksl/SkSLCPPUniformCTypes.cpp
@@ -176,7 +176,7 @@ static const std::vector<UniformCTypeMapper>& get_mappers() {
REGISTER(Layout::CType::kSkMatrix, { "half3x3", "float3x3", "double3x3" },
"${pdman}.setSkMatrix(${uniform}, ${var})", // to gpu
- "SkMatrix::MakeScale(SK_FloatNaN)", // default value
+ "SkMatrix::Scale(SK_FloatNaN, SK_FloatNaN)", // default value
"!${oldVar}.cheapEqualTo(${newVar})"), // dirty check
REGISTER(Layout::CType::kSkM44, { "half4x4", "float4x4", "double4x4" },
diff --git a/chromium/third_party/skia/src/sksl/SkSLCompiler.cpp b/chromium/third_party/skia/src/sksl/SkSLCompiler.cpp
index 9ac276a9e13..d5c1293f7fa 100644
--- a/chromium/third_party/skia/src/sksl/SkSLCompiler.cpp
+++ b/chromium/third_party/skia/src/sksl/SkSLCompiler.cpp
@@ -78,14 +78,17 @@ static const char* SKSL_PIPELINE_INCLUDE =
namespace SkSL {
static void grab_intrinsics(std::vector<std::unique_ptr<ProgramElement>>* src,
- std::map<StringFragment, std::pair<std::unique_ptr<ProgramElement>, bool>>* target) {
- for (auto& element : *src) {
+ std::map<String, std::pair<std::unique_ptr<ProgramElement>, bool>>* target) {
+ for (auto iter = src->begin(); iter != src->end(); ) {
+ std::unique_ptr<ProgramElement>& element = *iter;
switch (element->fKind) {
case ProgramElement::kFunction_Kind: {
FunctionDefinition& f = (FunctionDefinition&) *element;
- StringFragment name = f.fDeclaration.fName;
- SkASSERT(target->find(name) == target->end());
- (*target)[name] = std::make_pair(std::move(element), false);
+ SkASSERT(f.fDeclaration.fBuiltin);
+ String key = f.fDeclaration.declaration();
+ SkASSERT(target->find(key) == target->end());
+ (*target)[key] = std::make_pair(std::move(element), false);
+ iter = src->erase(iter);
break;
}
case ProgramElement::kEnum_Kind: {
@@ -93,6 +96,7 @@ static void grab_intrinsics(std::vector<std::unique_ptr<ProgramElement>>* src,
StringFragment name = e.fTypeName;
SkASSERT(target->find(name) == target->end());
(*target)[name] = std::make_pair(std::move(element), false);
+ iter = src->erase(iter);
break;
}
default:
@@ -122,10 +126,6 @@ Compiler::Compiler(Flags flags)
ADD_TYPE(Half2);
ADD_TYPE(Half3);
ADD_TYPE(Half4);
- ADD_TYPE(Double);
- ADD_TYPE(Double2);
- ADD_TYPE(Double3);
- ADD_TYPE(Double4);
ADD_TYPE(Int);
ADD_TYPE(Int2);
ADD_TYPE(Int3);
@@ -172,18 +172,8 @@ Compiler::Compiler(Flags flags)
ADD_TYPE(Half4x2);
ADD_TYPE(Half4x3);
ADD_TYPE(Half4x4);
- ADD_TYPE(Double2x2);
- ADD_TYPE(Double2x3);
- ADD_TYPE(Double2x4);
- ADD_TYPE(Double3x2);
- ADD_TYPE(Double3x3);
- ADD_TYPE(Double3x4);
- ADD_TYPE(Double4x2);
- ADD_TYPE(Double4x3);
- ADD_TYPE(Double4x4);
ADD_TYPE(GenType);
ADD_TYPE(GenHType);
- ADD_TYPE(GenDType);
ADD_TYPE(GenIType);
ADD_TYPE(GenUType);
ADD_TYPE(GenBType);
@@ -194,7 +184,6 @@ Compiler::Compiler(Flags flags)
ADD_TYPE(GVec3);
ADD_TYPE(GVec4);
ADD_TYPE(HVec);
- ADD_TYPE(DVec);
ADD_TYPE(IVec);
ADD_TYPE(UVec);
ADD_TYPE(SVec);
@@ -249,6 +238,9 @@ Compiler::Compiler(Flags flags)
ADD_TYPE(Sampler);
ADD_TYPE(Texture2D);
+ StringFragment fpAliasName("shader");
+ fTypes->addWithoutOwnership(fpAliasName, fContext->fFragmentProcessor_Type.get());
+
StringFragment skCapsName("sk_Caps");
Variable* skCaps = new Variable(-1, Modifiers(), skCapsName,
*fContext->fSkCaps_Type, Variable::kGlobal_Storage);
@@ -434,6 +426,7 @@ void Compiler::addDefinitions(const BasicBlock::Node& node,
(std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
definitions);
}
+ break;
}
default:
break;
@@ -1029,88 +1022,167 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
return;
}
SkASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind);
- break;
}
+ break;
}
default:
break;
}
}
-// returns true if this statement could potentially execute a break at the current level (we ignore
-// nested loops and switches, since any breaks inside of them will merely break the loop / switch)
-static bool contains_conditional_break(Statement& s, bool inConditional) {
+// Implementation-detail recursive helper function for `contains_conditional_break`.
+static bool contains_conditional_break_impl(Statement& s, bool inConditional) {
switch (s.fKind) {
case Statement::kBlock_Kind:
- for (const auto& sub : ((Block&) s).fStatements) {
- if (contains_conditional_break(*sub, inConditional)) {
+ for (const std::unique_ptr<Statement>& sub : static_cast<Block&>(s).fStatements) {
+ if (contains_conditional_break_impl(*sub, inConditional)) {
return true;
}
}
return false;
+
case Statement::kBreak_Kind:
return inConditional;
+
case Statement::kIf_Kind: {
- const IfStatement& i = (IfStatement&) s;
- return contains_conditional_break(*i.fIfTrue, true) ||
- (i.fIfFalse && contains_conditional_break(*i.fIfFalse, true));
+ const IfStatement& i = static_cast<IfStatement&>(s);
+ return contains_conditional_break_impl(*i.fIfTrue, /*inConditional=*/true) ||
+ (i.fIfFalse &&
+ contains_conditional_break_impl(*i.fIfFalse, /*inConditional=*/true));
}
+
default:
return false;
}
}
+// Returns true if this statement could potentially execute a break at the current level. We ignore
+// nested loops and switches, since any breaks inside of them will merely break the loop / switch.
+static bool contains_conditional_break(Statement& s) {
+ return contains_conditional_break_impl(s, /*inConditional=*/false);
+}
+
// returns true if this statement definitely executes a break at the current level (we ignore
// nested loops and switches, since any breaks inside of them will merely break the loop / switch)
static bool contains_unconditional_break(Statement& s) {
switch (s.fKind) {
case Statement::kBlock_Kind:
- for (const auto& sub : ((Block&) s).fStatements) {
+ for (const std::unique_ptr<Statement>& sub : static_cast<Block&>(s).fStatements) {
if (contains_unconditional_break(*sub)) {
return true;
}
}
return false;
+
case Statement::kBreak_Kind:
return true;
+
default:
return false;
}
}
+static void move_all_but_break(std::unique_ptr<Statement>& stmt,
+ std::vector<std::unique_ptr<Statement>>* target) {
+ switch (stmt->fKind) {
+ case Statement::kBlock_Kind: {
+ // Recurse into the block.
+ Block& block = static_cast<Block&>(*stmt);
+
+ std::vector<std::unique_ptr<Statement>> blockStmts;
+ blockStmts.reserve(block.fStatements.size());
+ for (std::unique_ptr<Statement>& statementInBlock : block.fStatements) {
+ move_all_but_break(statementInBlock, &blockStmts);
+ }
+
+ target->push_back(std::make_unique<Block>(block.fOffset, std::move(blockStmts),
+ block.fSymbols, block.fIsScope));
+ break;
+ }
+
+ case Statement::kBreak_Kind:
+ // Do not append a break to the target.
+ break;
+
+ default:
+ // Append normal statements to the target.
+ target->push_back(std::move(stmt));
+ break;
+ }
+}
+
// Returns a block containing all of the statements that will be run if the given case matches
// (which, owing to the statements being owned by unique_ptrs, means the switch itself will be
// broken by this call and must then be discarded).
// Returns null (and leaves the switch unmodified) if no such simple reduction is possible, such as
// when break statements appear inside conditionals.
-static std::unique_ptr<Statement> block_for_case(SwitchStatement* s, SwitchCase* c) {
- bool capturing = false;
- std::vector<std::unique_ptr<Statement>*> statementPtrs;
- for (const auto& current : s->fCases) {
- if (current.get() == c) {
- capturing = true;
+static std::unique_ptr<Statement> block_for_case(SwitchStatement* switchStatement,
+ SwitchCase* caseToCapture) {
+ // We have to be careful to not move any of the pointers until after we're sure we're going to
+ // succeed, so before we make any changes at all, we check the switch-cases to decide on a plan
+ // of action. First, find the switch-case we are interested in.
+ auto iter = switchStatement->fCases.begin();
+ for (; iter != switchStatement->fCases.end(); ++iter) {
+ if (iter->get() == caseToCapture) {
+ break;
}
- if (capturing) {
- for (auto& stmt : current->fStatements) {
- if (contains_conditional_break(*stmt, s->fKind == Statement::kIf_Kind)) {
- return nullptr;
- }
- if (contains_unconditional_break(*stmt)) {
- capturing = false;
- break;
- }
- statementPtrs.push_back(&stmt);
+ }
+
+ // Next, walk forward through the rest of the switch. If we find a conditional break, we're
+ // stuck and can't simplify at all. If we find an unconditional break, we have a range of
+ // statements that we can use for simplification.
+ auto startIter = iter;
+ Statement* unconditionalBreakStmt = nullptr;
+ for (; iter != switchStatement->fCases.end(); ++iter) {
+ for (std::unique_ptr<Statement>& stmt : (*iter)->fStatements) {
+ if (contains_conditional_break(*stmt)) {
+ // We can't reduce switch-cases to a block when they have conditional breaks.
+ return nullptr;
}
- if (!capturing) {
+
+ if (contains_unconditional_break(*stmt)) {
+ // We found an unconditional break. We can use this block, but we need to strip
+ // out the break statement.
+ unconditionalBreakStmt = stmt.get();
break;
}
}
+
+ if (unconditionalBreakStmt != nullptr) {
+ break;
+ }
}
- std::vector<std::unique_ptr<Statement>> statements;
- for (const auto& s : statementPtrs) {
- statements.push_back(std::move(*s));
+
+ // We fell off the bottom of the switch or encountered a break. We know the range of statements
+ // that we need to move over, and we know it's safe to do so.
+ std::vector<std::unique_ptr<Statement>> caseStmts;
+
+ // We can move over most of the statements as-is.
+ while (startIter != iter) {
+ for (std::unique_ptr<Statement>& stmt : (*startIter)->fStatements) {
+ caseStmts.push_back(std::move(stmt));
+ }
+ ++startIter;
+ }
+
+ // If we found an unconditional break at the end, we need to move what we can while avoiding
+ // that break.
+ if (unconditionalBreakStmt != nullptr) {
+ for (std::unique_ptr<Statement>& stmt : (*startIter)->fStatements) {
+ if (stmt.get() == unconditionalBreakStmt) {
+ move_all_but_break(stmt, &caseStmts);
+ unconditionalBreakStmt = nullptr;
+ break;
+ }
+
+ caseStmts.push_back(std::move(stmt));
+ }
}
- return std::unique_ptr<Statement>(new Block(-1, std::move(statements), s->fSymbols));
+
+ SkASSERT(unconditionalBreakStmt == nullptr); // Verify that we fixed the unconditional break.
+
+ // Return our newly-synthesized block.
+ return std::make_unique<Block>(/*offset=*/-1, std::move(caseStmts), switchStatement->fSymbols);
}
void Compiler::simplifyStatement(DefinitionMap& definitions,
@@ -1262,6 +1334,14 @@ void Compiler::scanCFG(FunctionDefinition& f) {
break;
case BasicBlock::Node::kExpression_Kind:
offset = (*cfg.fBlocks[i].fNodes[0].expression())->fOffset;
+ if ((*cfg.fBlocks[i].fNodes[0].expression())->fKind ==
+ Expression::kBoolLiteral_Kind) {
+ // Function inlining can generate do { ... } while(false) loops which always
+ // break, so the boolean condition is considered unreachable. Since not
+ // being able to reach a literal is a non-issue in the first place, we
+ // don't report an error in this case.
+ continue;
+ }
break;
}
this->error(offset, String("unreachable"));
@@ -1283,7 +1363,22 @@ void Compiler::scanCFG(FunctionDefinition& f) {
}
updated = false;
+ bool first = true;
for (BasicBlock& b : cfg.fBlocks) {
+ if (!first && b.fEntrances.empty()) {
+ // Block was reachable before optimization, but has since become unreachable. In
+ // addition to being dead code, it's broken - since control flow can't reach it, no
+ // prior variable definitions can reach it, and therefore variables might look to
+ // have not been properly assigned. Kill it.
+ for (BasicBlock::Node& node : b.fNodes) {
+ if (node.fKind == BasicBlock::Node::kStatement_Kind &&
+ (*node.statement())->fKind != Statement::kNop_Kind) {
+ node.setStatement(std::unique_ptr<Statement>(new Nop()));
+ }
+ }
+ continue;
+ }
+ first = false;
DefinitionMap definitions = b.fBefore;
for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan; ++iter) {
@@ -1448,6 +1543,20 @@ bool Compiler::optimize(Program& program) {
this->scanCFG((FunctionDefinition&) element);
}
}
+ // we wait until after analysis to remove dead functions so that we still report errors
+ // even in unused code
+ if (program.fSettings.fRemoveDeadFunctions) {
+ for (auto iter = program.fElements.begin(); iter != program.fElements.end(); ) {
+ if ((*iter)->fKind == ProgramElement::kFunction_Kind) {
+ const FunctionDefinition& f = (const FunctionDefinition&) **iter;
+ if (!f.fDeclaration.fCallCount && f.fDeclaration.fName != "main") {
+ iter = program.fElements.erase(iter);
+ continue;
+ }
+ }
+ ++iter;
+ }
+ }
if (program.fKind != Program::kFragmentProcessor_Kind) {
for (auto iter = program.fElements.begin(); iter != program.fElements.end();) {
if ((*iter)->fKind == ProgramElement::kVar_Kind) {
diff --git a/chromium/third_party/skia/src/sksl/SkSLCompiler.h b/chromium/third_party/skia/src/sksl/SkSLCompiler.h
index 65f7a70a371..31931977a1d 100644
--- a/chromium/third_party/skia/src/sksl/SkSLCompiler.h
+++ b/chromium/third_party/skia/src/sksl/SkSLCompiler.h
@@ -215,8 +215,8 @@ private:
Position position(int offset);
- std::map<StringFragment, std::pair<std::unique_ptr<ProgramElement>, bool>> fGPUIntrinsics;
- std::map<StringFragment, std::pair<std::unique_ptr<ProgramElement>, bool>> fInterpreterIntrinsics;
+ std::map<String, std::pair<std::unique_ptr<ProgramElement>, bool>> fGPUIntrinsics;
+ std::map<String, std::pair<std::unique_ptr<ProgramElement>, bool>> fInterpreterIntrinsics;
std::unique_ptr<ASTFile> fGpuIncludeSource;
std::shared_ptr<SymbolTable> fGpuSymbolTable;
std::vector<std::unique_ptr<ProgramElement>> fVertexInclude;
diff --git a/chromium/third_party/skia/src/sksl/SkSLContext.h b/chromium/third_party/skia/src/sksl/SkSLContext.h
index eb7659a072f..832413035a2 100644
--- a/chromium/third_party/skia/src/sksl/SkSLContext.h
+++ b/chromium/third_party/skia/src/sksl/SkSLContext.h
@@ -24,10 +24,6 @@ public:
, fNull_Type(new Type("null"))
, fFloatLiteral_Type(new Type("$floatLiteral", Type::kFloat_NumberKind, 3))
, fIntLiteral_Type(new Type("$intLiteral", Type::kSigned_NumberKind, 1))
- , fDouble_Type(new Type("double", Type::kFloat_NumberKind, 6, true))
- , fDouble2_Type(new Type("double2", *fDouble_Type, 2))
- , fDouble3_Type(new Type("double3", *fDouble_Type, 3))
- , fDouble4_Type(new Type("double4", *fDouble_Type, 4))
, fFloat_Type(new Type("float", Type::kFloat_NumberKind, 5, true))
, fFloat2_Type(new Type("float2", *fFloat_Type, 2))
, fFloat3_Type(new Type("float3", *fFloat_Type, 3))
@@ -82,15 +78,6 @@ public:
, fHalf4x2_Type(new Type("half4x2", *fHalf_Type, 4, 2))
, fHalf4x3_Type(new Type("half4x3", *fHalf_Type, 4, 3))
, fHalf4x4_Type(new Type("half4x4", *fHalf_Type, 4, 4))
- , fDouble2x2_Type(new Type("double2x2", *fDouble_Type, 2, 2))
- , fDouble2x3_Type(new Type("double2x3", *fDouble_Type, 2, 3))
- , fDouble2x4_Type(new Type("double2x4", *fDouble_Type, 2, 4))
- , fDouble3x2_Type(new Type("double3x2", *fDouble_Type, 3, 2))
- , fDouble3x3_Type(new Type("double3x3", *fDouble_Type, 3, 3))
- , fDouble3x4_Type(new Type("double3x4", *fDouble_Type, 3, 4))
- , fDouble4x2_Type(new Type("double4x2", *fDouble_Type, 4, 2))
- , fDouble4x3_Type(new Type("double4x3", *fDouble_Type, 4, 3))
- , fDouble4x4_Type(new Type("double4x4", *fDouble_Type, 4, 4))
, fTexture1D_Type(new Type("texture1D", SpvDim1D, false, false, false, true))
, fTexture2D_Type(new Type("texture2D", SpvDim2D, false, false, false, true))
, fTexture3D_Type(new Type("texture3D", SpvDim3D, false, false, false, true))
@@ -158,8 +145,6 @@ public:
fFloat3_Type.get(), fFloat4_Type.get() }))
, fGenHType_Type(new Type("$genHType", { fHalf_Type.get(), fHalf2_Type.get(),
fHalf3_Type.get(), fHalf4_Type.get() }))
- , fGenDType_Type(new Type("$genDType", { fDouble_Type.get(), fDouble2_Type.get(),
- fDouble3_Type.get(), fDouble4_Type.get() }))
, fGenIType_Type(new Type("$genIType", { fInt_Type.get(), fInt2_Type.get(),
fInt3_Type.get(), fInt4_Type.get() }))
, fGenUType_Type(new Type("$genUType", { fUInt_Type.get(), fUInt2_Type.get(),
@@ -188,8 +173,6 @@ public:
, fGVec4_Type(new Type("$gfloat4", static_type(*fFloat4_Type)))
, fHVec_Type(new Type("$hvec", { fInvalid_Type.get(), fHalf2_Type.get(),
fHalf3_Type.get(), fHalf4_Type.get() }))
- , fDVec_Type(new Type("$dvec", { fInvalid_Type.get(), fDouble2_Type.get(),
- fDouble3_Type.get(), fDouble4_Type.get() }))
, fIVec_Type(new Type("$ivec", { fInvalid_Type.get(), fInt2_Type.get(),
fInt3_Type.get(), fInt4_Type.get() }))
, fUVec_Type(new Type("$uvec", { fInvalid_Type.get(), fUInt2_Type.get(),
@@ -219,11 +202,6 @@ public:
const std::unique_ptr<Type> fFloatLiteral_Type;
const std::unique_ptr<Type> fIntLiteral_Type;
- const std::unique_ptr<Type> fDouble_Type;
- const std::unique_ptr<Type> fDouble2_Type;
- const std::unique_ptr<Type> fDouble3_Type;
- const std::unique_ptr<Type> fDouble4_Type;
-
const std::unique_ptr<Type> fFloat_Type;
const std::unique_ptr<Type> fFloat2_Type;
const std::unique_ptr<Type> fFloat3_Type;
@@ -353,7 +331,6 @@ public:
const std::unique_ptr<Type> fGenType_Type;
const std::unique_ptr<Type> fGenHType_Type;
- const std::unique_ptr<Type> fGenDType_Type;
const std::unique_ptr<Type> fGenIType_Type;
const std::unique_ptr<Type> fGenUType_Type;
const std::unique_ptr<Type> fGenBType_Type;
@@ -400,6 +377,11 @@ private:
return "<defined>";
}
+ int nodeCount() const override {
+ SkASSERT(false);
+ return 1;
+ }
+
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new Defined(fType));
}
diff --git a/chromium/third_party/skia/src/sksl/SkSLDefines.h b/chromium/third_party/skia/src/sksl/SkSLDefines.h
index d0ba9d7572e..1138c500633 100644
--- a/chromium/third_party/skia/src/sksl/SkSLDefines.h
+++ b/chromium/third_party/skia/src/sksl/SkSLDefines.h
@@ -22,6 +22,9 @@
#ifdef SKSL_STANDALONE
#define SkASSERT(x) do { if (!(x)) abort(); } while (false)
+#define SkASSERTF(x, __VA_ARGS__) do { if (!(x)) { printf(__VA_ARGS__); abort(); } } while (false)
+#define SkDEBUGFAIL(x) do { printf("%s", x); abort(); } while (false)
+#define SkDEBUGFAILF(fmt, ...) do { printf(__VA_ARGS__); abort(); } while (false)
#define SkAssertResult(x) do { if (!(x)) abort(); } while (false)
#define SkDEBUGCODE(...) __VA_ARGS__
#define SK_API
diff --git a/chromium/third_party/skia/src/sksl/SkSLGLSLCodeGenerator.cpp b/chromium/third_party/skia/src/sksl/SkSLGLSLCodeGenerator.cpp
index e21c32c2c22..127145a1921 100644
--- a/chromium/third_party/skia/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/chromium/third_party/skia/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -87,9 +87,6 @@ String GLSLCodeGenerator::getTypeName(const Type& type) {
if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) {
result = "vec";
}
- else if (component == *fContext.fDouble_Type) {
- result = "dvec";
- }
else if (component.isSigned()) {
result = "ivec";
}
@@ -111,9 +108,6 @@ String GLSLCodeGenerator::getTypeName(const Type& type) {
if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) {
result = "mat";
}
- else if (component == *fContext.fDouble_Type) {
- result = "dmat";
- }
else {
ABORT("unsupported matrix type");
}
@@ -528,7 +522,7 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
this->write("-dFdy");
nameWritten = true;
}
- // fallthru
+ [[fallthrough]];
case FunctionClass::kDFdx:
case FunctionClass::kFwidth:
if (!fFoundDerivatives &&
@@ -1521,11 +1515,15 @@ void GLSLCodeGenerator::writeStatements(const std::vector<std::unique_ptr<Statem
}
void GLSLCodeGenerator::writeBlock(const Block& b) {
- this->writeLine("{");
- fIndentation++;
+ if (b.fIsScope) {
+ this->writeLine("{");
+ fIndentation++;
+ }
this->writeStatements(b.fStatements);
- fIndentation--;
- this->write("}");
+ if (b.fIsScope) {
+ fIndentation--;
+ this->write("}");
+ }
}
void GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) {
diff --git a/chromium/third_party/skia/src/sksl/SkSLHCodeGenerator.cpp b/chromium/third_party/skia/src/sksl/SkSLHCodeGenerator.cpp
index 8a6f3502d56..5d4195bcf81 100644
--- a/chromium/third_party/skia/src/sksl/SkSLHCodeGenerator.cpp
+++ b/chromium/third_party/skia/src/sksl/SkSLHCodeGenerator.cpp
@@ -8,6 +8,7 @@
#include "src/sksl/SkSLHCodeGenerator.h"
#include "src/sksl/SkSLParser.h"
+#include "src/sksl/SkSLSampleMatrix.h"
#include "src/sksl/SkSLUtil.h"
#include "src/sksl/ir/SkSLEnum.h"
#include "src/sksl/ir/SkSLFunctionDeclaration.h"
@@ -272,7 +273,7 @@ void HCodeGenerator::writeConstructor() {
this->writef(" {\n");
this->writeSection(CONSTRUCTOR_CODE_SECTION);
int samplerCount = 0;
- for (const auto& param : fSectionAndParameterHelper.getParameters()) {
+ for (const Variable* param : fSectionAndParameterHelper.getParameters()) {
if (param->fType.kind() == Type::kSampler_Kind) {
++samplerCount;
} else if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
@@ -281,36 +282,45 @@ void HCodeGenerator::writeConstructor() {
} else {
this->writef(" SkASSERT(%s);", String(param->fName).c_str());
}
- this->writef(" %s_index = this->numChildProcessors();",
- FieldName(String(param->fName).c_str()).c_str());
- if (fSectionAndParameterHelper.hasCoordOverrides(*param)) {
- this->writef(" %s->setSampledWithExplicitCoords();",
- String(param->fName).c_str());
- }
- SampleMatrix matrix = fSectionAndParameterHelper.getMatrix(*param);
- switch (matrix.fKind) {
- case SampleMatrix::Kind::kVariable:
- this->writef(" %s->setSampleMatrix(this, "
- "SkSL::SampleMatrix::Kind::kVariable);",
- String(param->fName).c_str());
- break;
- case SampleMatrix::Kind::kConstantOrUniform:
- this->writef(" %s->setSampleMatrix(SkSL::SampleMatrix("
- "SkSL::SampleMatrix::Kind::kConstantOrUniform, this, \"%s\"));",
- String(param->fName).c_str(),
- matrix.fExpression.c_str());
- break;
- case SampleMatrix::Kind::kMixed:
- this->writef(" %s->setSampleMatrix(SkSL::SampleMatrix("
- "SkSL::SampleMatrix::Kind::kMixed, this, \"%s\"));",
- String(param->fName).c_str(),
- matrix.fExpression.c_str());
- break;
- case SampleMatrix::Kind::kNone:
- break;
+
+ bool explicitCoords = fSectionAndParameterHelper.hasCoordOverrides(*param);
+ SampleMatrix matrix = SampleMatrix::Make(fProgram, *param);
+
+ String registerFunc;
+ String matrixArg;
+ String explicitArg;
+
+ if (explicitCoords && matrix.fKind == SampleMatrix::Kind::kNone) {
+ registerFunc = "registerExplicitlySampledChild";
+ } else {
+ registerFunc = "registerChild";
+ if (explicitCoords) {
+ explicitArg = ", true";
+ }
+ switch(matrix.fKind) {
+ case SampleMatrix::Kind::kVariable:
+ matrixArg.appendf(", SkSL::SampleMatrix::MakeVariable()");
+ break;
+ case SampleMatrix::Kind::kConstantOrUniform:
+ matrixArg.appendf(", SkSL::SampleMatrix::MakeConstUniform(\"%s\")",
+ matrix.fExpression.c_str());
+ break;
+ case SampleMatrix::Kind::kMixed:
+ // Mixed is only produced when combining FPs, not from analysis of sksl
+ SkASSERT(false);
+ break;
+ case SampleMatrix::Kind::kNone:
+ break;
+ }
}
- this->writef(" this->registerChildProcessor(std::move(%s));",
- String(param->fName).c_str());
+
+ this->writef(" %s_index = this->%s(std::move(%s)%s%s);",
+ FieldName(String(param->fName).c_str()).c_str(),
+ registerFunc.c_str(),
+ String(param->fName).c_str(),
+ matrixArg.c_str(),
+ explicitArg.c_str());
+
if (param->fType.kind() == Type::kNullable_Kind) {
this->writef(" }");
}
@@ -367,15 +377,18 @@ bool HCodeGenerator::generateCode() {
this->writef("%s\n", GetHeader(fProgram, fErrors).c_str());
this->writef(kFragmentProcessorHeader, fFullName.c_str());
this->writef("#ifndef %s_DEFINED\n"
- "#define %s_DEFINED\n",
+ "#define %s_DEFINED\n"
+ "\n",
fFullName.c_str(),
fFullName.c_str());
- this->writef("#include \"include/core/SkTypes.h\"\n");
- this->writef("#include \"include/core/SkM44.h\"\n");
+ this->writef("#include \"include/core/SkM44.h\"\n"
+ "#include \"include/core/SkTypes.h\"\n"
+ "\n");
this->writeSection(HEADER_SECTION);
this->writef("\n"
"#include \"src/gpu/GrCoordTransform.h\"\n"
- "#include \"src/gpu/GrFragmentProcessor.h\"\n");
+ "#include \"src/gpu/GrFragmentProcessor.h\"\n"
+ "\n");
this->writef("class %s : public GrFragmentProcessor {\n"
"public:\n",
fFullName.c_str());
diff --git a/chromium/third_party/skia/src/sksl/SkSLIRGenerator.cpp b/chromium/third_party/skia/src/sksl/SkSLIRGenerator.cpp
index 5ab04abbaaa..40b9128406a 100644
--- a/chromium/third_party/skia/src/sksl/SkSLIRGenerator.cpp
+++ b/chromium/third_party/skia/src/sksl/SkSLIRGenerator.cpp
@@ -156,6 +156,7 @@ void IRGenerator::start(const Program::Settings* settings,
fSkPerVertex = nullptr;
fRTAdjust = nullptr;
fRTAdjustInterfaceBlock = nullptr;
+ fInlineVarCounter = 0;
if (inherited) {
for (const auto& e : *inherited) {
if (e->fKind == ProgramElement::kInterfaceBlock_Kind) {
@@ -182,7 +183,7 @@ void IRGenerator::finish() {
fSettings = nullptr;
}
-std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTNode& statement) {
+std::unique_ptr<Statement> IRGenerator::convertSingleStatement(const ASTNode& statement) {
switch (statement.fKind) {
case ASTNode::Kind::kBlock:
return this->convertBlock(statement);
@@ -228,6 +229,24 @@ std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTNode& statemen
}
}
+std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTNode& statement) {
+ std::vector<std::unique_ptr<Statement>> oldExtraStatements = std::move(fExtraStatements);
+ std::unique_ptr<Statement> result = this->convertSingleStatement(statement);
+ if (!result) {
+ fExtraStatements = std::move(oldExtraStatements);
+ return nullptr;
+ }
+ if (fExtraStatements.size()) {
+ fExtraStatements.push_back(std::move(result));
+ std::unique_ptr<Statement> block(new Block(-1, std::move(fExtraStatements), nullptr,
+ false));
+ fExtraStatements = std::move(oldExtraStatements);
+ return block;
+ }
+ fExtraStatements = std::move(oldExtraStatements);
+ return result;
+}
+
std::unique_ptr<Block> IRGenerator::convertBlock(const ASTNode& block) {
SkASSERT(block.fKind == ASTNode::Kind::kBlock);
AutoSymbolTable table(this);
@@ -496,15 +515,22 @@ std::unique_ptr<Statement> IRGenerator::convertFor(const ASTNode& f) {
++iter;
std::unique_ptr<Expression> test;
if (*iter) {
+ bool oldCanInline = fCanInline;
+ fCanInline = false;
test = this->coerce(this->convertExpression(*iter), *fContext.fBool_Type);
+ fCanInline = oldCanInline;
if (!test) {
return nullptr;
}
+
}
++iter;
std::unique_ptr<Expression> next;
if (*iter) {
+ bool oldCanInline = fCanInline;
+ fCanInline = false;
next = this->convertExpression(*iter);
+ fCanInline = oldCanInline;
if (!next) {
return nullptr;
}
@@ -524,8 +550,11 @@ std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTNode& w) {
SkASSERT(w.fKind == ASTNode::Kind::kWhile);
AutoLoopLevel level(this);
auto iter = w.begin();
+ bool oldCanInline = fCanInline;
+ fCanInline = false;
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
*fContext.fBool_Type);
+ fCanInline = oldCanInline;
if (!test) {
return nullptr;
}
@@ -545,8 +574,11 @@ std::unique_ptr<Statement> IRGenerator::convertDo(const ASTNode& d) {
if (!statement) {
return nullptr;
}
+ bool oldCanInline = fCanInline;
+ fCanInline = false;
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
*fContext.fBool_Type);
+ fCanInline = oldCanInline;
if (!test) {
return nullptr;
}
@@ -884,7 +916,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
return;
}
}
- if (other->fDefined && !other->fBuiltin) {
+ if (other->fDefinition && !other->fBuiltin) {
fErrors.error(f.fOffset, "duplicate definition of " +
other->declaration());
}
@@ -907,7 +939,6 @@ void IRGenerator::convertFunction(const ASTNode& f) {
// compile body
SkASSERT(!fCurrentFunction);
fCurrentFunction = decl;
- decl->fDefined = true;
std::shared_ptr<SymbolTable> old = fSymbolTable;
AutoSymbolTable table(this);
if (fd.fName == "main" && fKind == Program::kPipelineStage_Kind) {
@@ -940,6 +971,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
}
std::unique_ptr<FunctionDefinition> result(new FunctionDefinition(f.fOffset, *decl,
std::move(body)));
+ decl->fDefinition = result.get();
result->fSource = &f;
fProgramElements->push_back(std::move(result));
}
@@ -1398,7 +1430,7 @@ static bool determine_binary_type(const Context& context,
*outResultType = &left;
return right.canCoerceTo(left);
}
- // fall through
+ [[fallthrough]];
case Token::Kind::TK_STAR:
if (is_matrix_multiply(left, right)) {
// determine final component type
@@ -1451,7 +1483,7 @@ static bool determine_binary_type(const Context& context,
*outResultType = &left;
return right.canCoerceTo(left);
}
- // fall through
+ [[fallthrough]];
case Token::Kind::TK_PLUS: // fall through
case Token::Kind::TK_MINUS: // fall through
case Token::Kind::TK_SLASH: // fall through
@@ -1715,7 +1747,15 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(const ASTNode&
if (!left) {
return nullptr;
}
+ Token::Kind op = expression.getToken().fKind;
+ bool oldCanInline = fCanInline;
+ if (op == Token::Kind::TK_LOGICALAND || op == Token::Kind::TK_LOGICALOR) {
+ // can't inline the right side of a short-circuiting boolean, because our inlining
+ // approach runs things out of order
+ fCanInline = false;
+ }
std::unique_ptr<Expression> right = this->convertExpression(*(iter++));
+ fCanInline = oldCanInline;
if (!right) {
return nullptr;
}
@@ -1734,7 +1774,6 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(const ASTNode&
} else {
rawRightType = &right->fType;
}
- Token::Kind op = expression.getToken().fKind;
if (!determine_binary_type(fContext, op, *rawLeftType, *rawRightType, &leftType, &rightType,
&resultType, !Compiler::IsAssignment(op))) {
fErrors.error(expression.fOffset, String("type mismatch: '") +
@@ -1811,11 +1850,432 @@ std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(const ASTNode&
std::move(ifFalse)));
}
+std::unique_ptr<Expression> IRGenerator::inlineExpression(int offset,
+ std::map<const Variable*,
+ const Variable*>* varMap,
+ const Expression& expression) {
+ auto expr = [&](const std::unique_ptr<Expression>& e) {
+ if (e) {
+ return this->inlineExpression(offset, varMap, *e);
+ }
+ return std::unique_ptr<Expression>(nullptr);
+ };
+ switch (expression.fKind) {
+ case Expression::kBinary_Kind: {
+ const BinaryExpression& b = (const BinaryExpression&) expression;
+ return std::unique_ptr<Expression>(new BinaryExpression(offset,
+ expr(b.fLeft),
+ b.fOperator,
+ expr(b.fRight),
+ b.fType));
+ }
+ case Expression::kBoolLiteral_Kind:
+ case Expression::kIntLiteral_Kind:
+ case Expression::kFloatLiteral_Kind:
+ case Expression::kNullLiteral_Kind:
+ return expression.clone();
+ case Expression::kConstructor_Kind: {
+ const Constructor& c = (const Constructor&) expression;
+ std::vector<std::unique_ptr<Expression>> args;
+ for (const auto& arg : c.fArguments) {
+ args.push_back(expr(arg));
+ }
+ return std::unique_ptr<Expression>(new Constructor(offset, c.fType, std::move(args)));
+ }
+ case Expression::kExternalFunctionCall_Kind: {
+ const ExternalFunctionCall& e = (const ExternalFunctionCall&) expression;
+ std::vector<std::unique_ptr<Expression>> args;
+ for (const auto& arg : e.fArguments) {
+ args.push_back(expr(arg));
+ }
+ return std::unique_ptr<Expression>(new ExternalFunctionCall(offset, e.fType,
+ e.fFunction,
+ std::move(args)));
+ }
+ case Expression::kExternalValue_Kind:
+ return expression.clone();
+ case Expression::kFieldAccess_Kind: {
+ const FieldAccess& f = (const FieldAccess&) expression;
+ return std::unique_ptr<Expression>(new FieldAccess(expr(f.fBase), f.fFieldIndex,
+ f.fOwnerKind));
+ }
+ case Expression::kFunctionCall_Kind: {
+ const FunctionCall& c = (const FunctionCall&) expression;
+ std::vector<std::unique_ptr<Expression>> args;
+ for (const auto& arg : c.fArguments) {
+ args.push_back(expr(arg));
+ }
+ return std::unique_ptr<Expression>(new FunctionCall(offset, c.fType, c.fFunction,
+ std::move(args)));
+ }
+ case Expression::kIndex_Kind: {
+ const IndexExpression& idx = (const IndexExpression&) expression;
+ return std::unique_ptr<Expression>(new IndexExpression(fContext, expr(idx.fBase),
+ expr(idx.fIndex)));
+ }
+ case Expression::kPrefix_Kind: {
+ const PrefixExpression& p = (const PrefixExpression&) expression;
+ return std::unique_ptr<Expression>(new PrefixExpression(p.fOperator, expr(p.fOperand)));
+ }
+ case Expression::kPostfix_Kind: {
+ const PostfixExpression& p = (const PostfixExpression&) expression;
+ return std::unique_ptr<Expression>(new PostfixExpression(expr(p.fOperand),
+ p.fOperator));
+ }
+ case Expression::kSetting_Kind:
+ return expression.clone();
+ case Expression::kSwizzle_Kind: {
+ const Swizzle& s = (const Swizzle&) expression;
+ return std::unique_ptr<Expression>(new Swizzle(fContext, expr(s.fBase), s.fComponents));
+ }
+ case Expression::kTernary_Kind: {
+ const TernaryExpression& t = (const TernaryExpression&) expression;
+ return std::unique_ptr<Expression>(new TernaryExpression(offset, expr(t.fTest),
+ expr(t.fIfTrue),
+ expr(t.fIfFalse)));
+ }
+ case Expression::kVariableReference_Kind: {
+ const VariableReference& v = (const VariableReference&) expression;
+ auto found = varMap->find(&v.fVariable);
+ if (found != varMap->end()) {
+ return std::unique_ptr<Expression>(new VariableReference(offset,
+ *found->second,
+ v.fRefKind));
+ }
+ return v.clone();
+ }
+ default:
+ SkASSERT(false);
+ return nullptr;
+ }
+}
+
+std::unique_ptr<Statement> IRGenerator::inlineStatement(int offset,
+ std::map<const Variable*,
+ const Variable*>* varMap,
+ const Variable* returnVar,
+ bool haveEarlyReturns,
+ const Statement& statement) {
+ auto stmt = [&](const std::unique_ptr<Statement>& s) {
+ if (s) {
+ return this->inlineStatement(offset, varMap, returnVar, haveEarlyReturns, *s);
+ }
+ return std::unique_ptr<Statement>(nullptr);
+ };
+ auto stmts = [&](const std::vector<std::unique_ptr<Statement>>& ss) {
+ std::vector<std::unique_ptr<Statement>> result;
+ for (const auto& s : ss) {
+ result.push_back(stmt(s));
+ }
+ return result;
+ };
+ auto expr = [&](const std::unique_ptr<Expression>& e) {
+ if (e) {
+ return this->inlineExpression(offset, varMap, *e);
+ }
+ return std::unique_ptr<Expression>(nullptr);
+ };
+ switch (statement.fKind) {
+ case Statement::kBlock_Kind: {
+ const Block& b = (const Block&) statement;
+ return std::unique_ptr<Statement>(new Block(offset, stmts(b.fStatements), b.fSymbols,
+ b.fIsScope));
+ }
+
+ case Statement::kBreak_Kind:
+ case Statement::kContinue_Kind:
+ case Statement::kDiscard_Kind:
+ return statement.clone();
+
+ case Statement::kDo_Kind: {
+ const DoStatement& d = (const DoStatement&) statement;
+ return std::unique_ptr<Statement>(new DoStatement(offset,
+ stmt(d.fStatement),
+ expr(d.fTest)));
+ }
+ case Statement::kExpression_Kind: {
+ const ExpressionStatement& e = (const ExpressionStatement&) statement;
+ return std::unique_ptr<Statement>(new ExpressionStatement(expr(e.fExpression)));
+ }
+ case Statement::kFor_Kind: {
+ const ForStatement& f = (const ForStatement&) statement;
+ // need to ensure initializer is evaluated first so that we've already remapped its
+ // declarations by the time we evaluate test & next
+ std::unique_ptr<Statement> initializer = stmt(f.fInitializer);
+ return std::unique_ptr<Statement>(new ForStatement(offset, std::move(initializer),
+ expr(f.fTest), expr(f.fNext),
+ stmt(f.fStatement), f.fSymbols));
+ }
+ case Statement::kIf_Kind: {
+ const IfStatement& i = (const IfStatement&) statement;
+ return std::unique_ptr<Statement>(new IfStatement(offset, i.fIsStatic, expr(i.fTest),
+ stmt(i.fIfTrue), stmt(i.fIfFalse)));
+ }
+ case Statement::kNop_Kind:
+ return statement.clone();
+ case Statement::kReturn_Kind: {
+ const ReturnStatement& r = (const ReturnStatement&) statement;
+ if (r.fExpression) {
+ std::unique_ptr<Statement> assignment(new ExpressionStatement(
+ std::unique_ptr<Expression>(new BinaryExpression(offset,
+ std::unique_ptr<Expression>(new VariableReference(
+ offset,
+ *returnVar,
+ VariableReference::kWrite_RefKind)),
+ Token::Kind::TK_EQ,
+ expr(r.fExpression),
+ returnVar->fType))));
+ if (haveEarlyReturns) {
+ std::vector<std::unique_ptr<Statement>> block;
+ block.push_back(std::move(assignment));
+ block.emplace_back(new BreakStatement(offset));
+ return std::unique_ptr<Statement>(new Block(offset, std::move(block), nullptr,
+ false));
+ } else {
+ return assignment;
+ }
+ } else {
+ if (haveEarlyReturns) {
+ return std::unique_ptr<Statement>(new BreakStatement(offset));
+ } else {
+ return std::unique_ptr<Statement>(new Nop());
+ }
+ }
+ }
+ case Statement::kSwitch_Kind: {
+ const SwitchStatement& ss = (const SwitchStatement&) statement;
+ std::vector<std::unique_ptr<SwitchCase>> cases;
+ for (const auto& sc : ss.fCases) {
+ cases.emplace_back(new SwitchCase(offset, expr(sc->fValue),
+ stmts(sc->fStatements)));
+ }
+ return std::unique_ptr<Statement>(new SwitchStatement(offset, ss.fIsStatic,
+ expr(ss.fValue),
+ std::move(cases),
+ ss.fSymbols));
+ }
+ case Statement::kVarDeclaration_Kind: {
+ const VarDeclaration& decl = (const VarDeclaration&) statement;
+ std::vector<std::unique_ptr<Expression>> sizes;
+ for (const auto& size : decl.fSizes) {
+ sizes.push_back(expr(size));
+ }
+ std::unique_ptr<Expression> initialValue = expr(decl.fValue);
+ const Variable* old = decl.fVar;
+ // need to copy the var name in case the originating function is discarded and we lose
+ // its symbols
+ std::unique_ptr<String> name(new String(old->fName));
+ String* namePtr = (String*) fSymbolTable->takeOwnership(std::move(name));
+ std::unique_ptr<Symbol> type(new Type(old->fType));
+ Type* typePtr = (Type*) fSymbolTable->takeOwnership(std::move(type));
+ Variable* clone = (Variable*) fSymbolTable->takeOwnership(std::unique_ptr<Symbol>(
+ new Variable(offset, old->fModifiers,
+ namePtr->c_str(), *typePtr,
+ old->fStorage,
+ initialValue.get())));
+ (*varMap)[old] = clone;
+ return std::unique_ptr<Statement>(new VarDeclaration(clone, std::move(sizes),
+ std::move(initialValue)));
+ }
+ case Statement::kVarDeclarations_Kind: {
+ const VarDeclarations& decls = *((VarDeclarationsStatement&) statement).fDeclaration;
+ std::vector<std::unique_ptr<VarDeclaration>> vars;
+ for (const auto& var : decls.fVars) {
+ vars.emplace_back((VarDeclaration*) stmt(var).release());
+ }
+ std::unique_ptr<Symbol> type(new Type(decls.fBaseType));
+ Type* typePtr = (Type*) fSymbolTable->takeOwnership(std::move(type));
+ return std::unique_ptr<Statement>(new VarDeclarationsStatement(
+ std::unique_ptr<VarDeclarations>(new VarDeclarations(offset, typePtr,
+ std::move(vars)))));
+ }
+ case Statement::kWhile_Kind: {
+ const WhileStatement& w = (const WhileStatement&) statement;
+ return std::unique_ptr<Statement>(new WhileStatement(offset,
+ expr(w.fTest),
+ stmt(w.fStatement)));
+ }
+ default:
+ SkASSERT(false);
+ return nullptr;
+ }
+}
+
+int return_count(const Statement& statement) {
+ switch (statement.fKind) {
+ case Statement::kBlock_Kind: {
+ const Block& b = (const Block&) statement;
+ int result = 0;
+ for (const auto& s : b.fStatements) {
+ result += return_count(*s);
+ }
+ return result;
+ }
+ case Statement::kDo_Kind: {
+ const DoStatement& d = (const DoStatement&) statement;
+ return return_count(*d.fStatement);
+ }
+ case Statement::kFor_Kind: {
+ const ForStatement& f = (const ForStatement&) statement;
+ return return_count(*f.fStatement);
+ }
+ case Statement::kIf_Kind: {
+ const IfStatement& i = (const IfStatement&) statement;
+ int result = return_count(*i.fIfTrue);
+ if (i.fIfFalse) {
+ result += return_count(*i.fIfFalse);
+ }
+ return result;
+ }
+ case Statement::kReturn_Kind:
+ return 1;
+ case Statement::kSwitch_Kind: {
+ const SwitchStatement& ss = (const SwitchStatement&) statement;
+ int result = 0;
+ for (const auto& sc : ss.fCases) {
+ for (const auto& s : ((SwitchCase&) *sc).fStatements) {
+ result += return_count(*s);
+ }
+ }
+ return result;
+ }
+ case Statement::kWhile_Kind: {
+ const WhileStatement& w = (const WhileStatement&) statement;
+ return return_count(*w.fStatement);
+ }
+ case Statement::kBreak_Kind:
+ case Statement::kContinue_Kind:
+ case Statement::kDiscard_Kind:
+ case Statement::kExpression_Kind:
+ case Statement::kNop_Kind:
+ case Statement::kVarDeclaration_Kind:
+ case Statement::kVarDeclarations_Kind:
+ return 0;
+ default:
+ SkASSERT(false);
+ return 0;
+ }
+}
+
+bool has_early_return(const FunctionDefinition& f) {
+ int returnCount = return_count(*f.fBody);
+ if (returnCount == 0) {
+ return false;
+ }
+ if (returnCount > 1) {
+ return true;
+ }
+ SkASSERT(f.fBody->fKind == Statement::kBlock_Kind);
+ return ((Block&) *f.fBody).fStatements.back()->fKind != Statement::kReturn_Kind;
+}
+
+std::unique_ptr<Expression> IRGenerator::inlineCall(
+ int offset,
+ const FunctionDefinition& function,
+ std::vector<std::unique_ptr<Expression>> arguments) {
+ // Inlining is more complicated here than in a typical compiler, because we have to have a
+ // high-level IR and can't just drop statements into the middle of an expression or even use
+ // gotos.
+ //
+ // Since we can't insert statements into an expression, we run the inline function as extra
+ // statements before the statement we're currently processing, relying on a lack of execution
+ // order guarantees. Since we can't use gotos (which are normally used to replace return
+ // statements), we wrap the whole function in a loop and use break statements to jump to the
+ // end.
+ Variable* resultVar;
+ if (function.fDeclaration.fReturnType != *fContext.fVoid_Type) {
+ std::unique_ptr<String> name(new String());
+ int varIndex = fInlineVarCounter++;
+ name->appendf("inlineResult%d", varIndex);
+ String* namePtr = (String*) fSymbolTable->takeOwnership(std::move(name));
+ resultVar = (Variable*) fSymbolTable->takeOwnership(std::unique_ptr<Symbol>(
+ new Variable(-1, Modifiers(), namePtr->c_str(),
+ function.fDeclaration.fReturnType,
+ Variable::kLocal_Storage,
+ nullptr)));
+ std::vector<std::unique_ptr<VarDeclaration>> variables;
+ variables.emplace_back(new VarDeclaration(resultVar, {}, nullptr));
+ fExtraStatements.emplace_back(new VarDeclarationsStatement(
+ std::unique_ptr<VarDeclarations>(new VarDeclarations(offset,
+ &resultVar->fType,
+ std::move(variables)))));
+
+ } else {
+ resultVar = nullptr;
+ }
+ std::map<const Variable*, const Variable*> varMap;
+ // create variables to hold the arguments and assign the arguments to them
+ int argIndex = fInlineVarCounter++;
+ for (int i = 0; i < (int) arguments.size(); ++i) {
+ std::unique_ptr<String> argName(new String());
+ argName->appendf("inlineArg%d_%d", argIndex, i);
+ String* argNamePtr = (String*) fSymbolTable->takeOwnership(std::move(argName));
+ Variable* argVar = (Variable*) fSymbolTable->takeOwnership(std::unique_ptr<Symbol>(
+ new Variable(-1, Modifiers(),
+ argNamePtr->c_str(),
+ arguments[i]->fType,
+ Variable::kLocal_Storage,
+ arguments[i].get())));
+ varMap[function.fDeclaration.fParameters[i]] = argVar;
+ std::vector<std::unique_ptr<VarDeclaration>> vars;
+ if (function.fDeclaration.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag) {
+ vars.emplace_back(new VarDeclaration(argVar, {}, arguments[i]->clone()));
+ } else {
+ vars.emplace_back(new VarDeclaration(argVar, {}, std::move(arguments[i])));
+ }
+ fExtraStatements.emplace_back(new VarDeclarationsStatement(
+ std::unique_ptr<VarDeclarations>(new VarDeclarations(offset,
+ &argVar->fType,
+ std::move(vars)))));
+ }
+ SkASSERT(function.fBody->fKind == Statement::kBlock_Kind);
+ const Block& body = (Block&) *function.fBody;
+ bool hasEarlyReturn = has_early_return(function);
+ std::vector<std::unique_ptr<Statement>> inlined;
+ for (const auto& s : body.fStatements) {
+ inlined.push_back(this->inlineStatement(offset, &varMap, resultVar, hasEarlyReturn, *s));
+ }
+ if (hasEarlyReturn) {
+ // Since we output to backends that don't have a goto statement (which would normally be
+ // used to perform an early return), we fake it by wrapping the function in a
+ // do { } while (false); and then use break statements to jump to the end in order to
+ // emulate a goto.
+ fExtraStatements.emplace_back(new DoStatement(-1,
+ std::unique_ptr<Statement>(new Block(-1, std::move(inlined))),
+ std::unique_ptr<Expression>(new BoolLiteral(fContext, -1, false))));
+ } else {
+ // No early returns, so we can just dump the code in. We need to use a block so we don't get
+ // name conflicts with locals.
+ fExtraStatements.emplace_back(std::unique_ptr<Statement>(new Block(-1,
+ std::move(inlined))));
+ }
+ // copy the values of out parameters into their destinations
+ for (size_t i = 0; i < arguments.size(); ++i) {
+ const Variable* p = function.fDeclaration.fParameters[i];
+ if (p->fModifiers.fFlags & Modifiers::kOut_Flag) {
+ std::unique_ptr<Expression> varRef(new VariableReference(offset, *varMap[p]));
+ fExtraStatements.emplace_back(new ExpressionStatement(
+ std::unique_ptr<Expression>(new BinaryExpression(offset,
+ arguments[i]->clone(),
+ Token::Kind::TK_EQ,
+ std::move(varRef),
+ arguments[i]->fType))));
+ }
+ }
+ if (function.fDeclaration.fReturnType != *fContext.fVoid_Type) {
+ return std::unique_ptr<Expression>(new VariableReference(-1, *resultVar));
+ } else {
+ // it's a void function, so it doesn't actually result in anything, but we have to return
+ // something non-null as a standin
+ return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1, false));
+ }
+}
+
std::unique_ptr<Expression> IRGenerator::call(int offset,
const FunctionDeclaration& function,
std::vector<std::unique_ptr<Expression>> arguments) {
if (function.fBuiltin) {
- auto found = fIntrinsics->find(function.fName);
+ auto found = fIntrinsics->find(function.declaration());
if (found != fIntrinsics->end() && !found->second.second) {
found->second.second = true;
const FunctionDeclaration* old = fCurrentFunction;
@@ -1835,7 +2295,7 @@ std::unique_ptr<Expression> IRGenerator::call(int offset,
fErrors.error(offset, msg);
return nullptr;
}
- if (fKind == Program::kPipelineStage_Kind && !function.fDefined && !function.fBuiltin) {
+ if (fKind == Program::kPipelineStage_Kind && !function.fDefinition && !function.fBuiltin) {
String msg = "call to undefined function '" + function.fName + "'";
fErrors.error(offset, msg);
return nullptr;
@@ -1866,6 +2326,11 @@ std::unique_ptr<Expression> IRGenerator::call(int offset,
VariableReference::kPointer_RefKind);
}
}
+ if (fCanInline && function.fDefinition && function.fDefinition->canBeInlined() &&
+ ((fSettings->fCaps && fSettings->fCaps->canUseDoLoops()) ||
+ !has_early_return(*function.fDefinition))) {
+ return this->inlineCall(offset, *function.fDefinition, std::move(arguments));
+ }
return std::unique_ptr<FunctionCall>(new FunctionCall(offset, *returnType, function,
std::move(arguments)));
}
@@ -2264,7 +2729,7 @@ std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expressi
swizzleComponents.push_back(1);
break;
}
- // fall through
+ [[fallthrough]];
case 'z':
case 'b':
case 'p':
@@ -2273,7 +2738,7 @@ std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expressi
swizzleComponents.push_back(2);
break;
}
- // fall through
+ [[fallthrough]];
case 'w':
case 'a':
case 'q':
@@ -2282,7 +2747,7 @@ std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expressi
swizzleComponents.push_back(3);
break;
}
- // fall through
+ [[fallthrough]];
default:
fErrors.error(base->fOffset, String::printf("invalid swizzle component '%c'",
fields[i]));
diff --git a/chromium/third_party/skia/src/sksl/SkSLIRGenerator.h b/chromium/third_party/skia/src/sksl/SkSLIRGenerator.h
index 51381e0c3a9..e13e320fe7e 100644
--- a/chromium/third_party/skia/src/sksl/SkSLIRGenerator.h
+++ b/chromium/third_party/skia/src/sksl/SkSLIRGenerator.h
@@ -83,11 +83,22 @@ private:
std::unique_ptr<VarDeclarations> convertVarDeclarations(const ASTNode& decl,
Variable::Storage storage);
void convertFunction(const ASTNode& f);
+ std::unique_ptr<Statement> convertSingleStatement(const ASTNode& statement);
std::unique_ptr<Statement> convertStatement(const ASTNode& statement);
std::unique_ptr<Expression> convertExpression(const ASTNode& expression);
std::unique_ptr<ModifiersDeclaration> convertModifiersDeclaration(const ASTNode& m);
const Type* convertType(const ASTNode& type);
+ std::unique_ptr<Expression> inlineExpression(int offset,
+ std::map<const Variable*, const Variable*>* varMap,
+ const Expression& expression);
+ std::unique_ptr<Statement> inlineStatement(int offset,
+ std::map<const Variable*, const Variable*>* varMap,
+ const Variable* returnVar,
+ bool haveEarlyReturns,
+ const Statement& statement);
+ std::unique_ptr<Expression> inlineCall(int offset, const FunctionDefinition& function,
+ std::vector<std::unique_ptr<Expression>> arguments);
std::unique_ptr<Expression> call(int offset,
const FunctionDeclaration& function,
std::vector<std::unique_ptr<Expression>> arguments);
@@ -156,9 +167,12 @@ private:
std::unordered_map<String, Program::Settings::Value> fCapsMap;
std::shared_ptr<SymbolTable> fRootSymbolTable;
std::shared_ptr<SymbolTable> fSymbolTable;
+ // additional statements that need to be inserted before the one that convertStatement is
+ // currently working on
+ std::vector<std::unique_ptr<Statement>> fExtraStatements;
// Symbols which have definitions in the include files. The bool tells us whether this
// intrinsic has been included already.
- std::map<StringFragment, std::pair<std::unique_ptr<ProgramElement>, bool>>* fIntrinsics = nullptr;
+ std::map<String, std::pair<std::unique_ptr<ProgramElement>, bool>>* fIntrinsics = nullptr;
int fLoopLevel;
int fSwitchLevel;
ErrorReporter& fErrors;
@@ -168,6 +182,8 @@ private:
Variable* fRTAdjust;
Variable* fRTAdjustInterfaceBlock;
int fRTAdjustFieldIndex;
+ int fInlineVarCounter;
+ bool fCanInline = true;
friend class AutoSymbolTable;
friend class AutoLoopLevel;
diff --git a/chromium/third_party/skia/src/sksl/SkSLMetalCodeGenerator.cpp b/chromium/third_party/skia/src/sksl/SkSLMetalCodeGenerator.cpp
index b8d700abb59..21fb47f6ea9 100644
--- a/chromium/third_party/skia/src/sksl/SkSLMetalCodeGenerator.cpp
+++ b/chromium/third_party/skia/src/sksl/SkSLMetalCodeGenerator.cpp
@@ -379,82 +379,94 @@ void MetalCodeGenerator::writeSpecialIntrinsic(const FunctionCall & c, SpecialIn
}
}
-// If it hasn't already been written, writes a constructor for 'matrix' which takes a single value
-// of type 'arg'.
-String MetalCodeGenerator::getMatrixConstructHelper(const Type& matrix, const Type& arg) {
- String key = matrix.name() + arg.name();
- auto found = fHelpers.find(key);
- if (found != fHelpers.end()) {
- return found->second;
- }
- String name;
+// Generates a constructor for 'matrix' which reorganizes the input arguments into the proper shape.
+// Keeps track of previously generated constructors so that we won't generate more than one
+// constructor for any given permutation of input argument types. Returns the name of the
+// generated constructor method.
+String MetalCodeGenerator::getMatrixConstructHelper(const Constructor& c) {
+ const Type& matrix = c.fType;
int columns = matrix.columns();
int rows = matrix.rows();
- if (arg.isNumber()) {
- // creating a matrix from a single scalar value
- name = "float" + to_string(columns) + "x" + to_string(rows) + "_from_float";
- fExtraFunctions.printf("float%dx%d %s(float x) {\n",
- columns, rows, name.c_str());
- fExtraFunctions.printf(" return float%dx%d(", columns, rows);
- for (int i = 0; i < columns; ++i) {
- if (i > 0) {
- fExtraFunctions.writeText(", ");
- }
- fExtraFunctions.printf("float%d(", rows);
- for (int j = 0; j < rows; ++j) {
- if (j > 0) {
- fExtraFunctions.writeText(", ");
+ const std::vector<std::unique_ptr<Expression>>& args = c.fArguments;
+
+ // Create the helper-method name and use it as our lookup key.
+ String name;
+ name.appendf("float%dx%d_from", columns, rows);
+ for (const std::unique_ptr<Expression>& expr : args) {
+ name.appendf("_%s", expr->fType.displayName().c_str());
+ }
+
+ // If a helper-method has already been synthesized, we don't need to synthesize it again.
+ auto [iter, newlyCreated] = fHelpers.insert(name);
+ if (!newlyCreated) {
+ return name;
+ }
+
+ // Unlike GLSL, Metal requires that matrices are initialized with exactly R vectors of C
+ // components apiece. (In Metal 2.0, you can also supply R*C scalars, but you still cannot
+ // supply a mixture of scalars and vectors.)
+ fExtraFunctions.printf("float%dx%d %s(", columns, rows, name.c_str());
+
+ size_t argIndex = 0;
+ const char* argSeparator = "";
+ for (const std::unique_ptr<Expression>& expr : c.fArguments) {
+ fExtraFunctions.printf("%s%s x%zu", argSeparator,
+ expr->fType.displayName().c_str(), argIndex++);
+ argSeparator = ", ";
+ }
+
+ fExtraFunctions.printf(") {\n return float%dx%d(", columns, rows);
+
+ argIndex = 0;
+ int argPosition = 0;
+
+ const char* columnSeparator = "";
+ for (int c = 0; c < columns; ++c) {
+ fExtraFunctions.printf("%sfloat%d(", columnSeparator, rows);
+ columnSeparator = "), ";
+
+ const char* rowSeparator = "";
+ for (int r = 0; r < rows; ++r) {
+ fExtraFunctions.printf("%s", rowSeparator);
+ rowSeparator = ", ";
+
+ const Type& argType = args[argIndex]->fType;
+ switch (argType.kind()) {
+ case Type::kScalar_Kind: {
+ fExtraFunctions.printf("x%zu", argIndex);
+ break;
}
- if (i == j) {
- fExtraFunctions.writeText("x");
- } else {
- fExtraFunctions.writeText("0");
+ case Type::kVector_Kind: {
+ fExtraFunctions.printf("x%zu[%d]", argIndex, argPosition);
+ break;
}
- }
- fExtraFunctions.writeText(")");
- }
- fExtraFunctions.writeText(");\n}\n");
- } else if (arg.kind() == Type::kMatrix_Kind) {
- // creating a matrix from another matrix
- int argColumns = arg.columns();
- int argRows = arg.rows();
- name = "float" + to_string(columns) + "x" + to_string(rows) + "_from_float" +
- to_string(argColumns) + "x" + to_string(argRows);
- fExtraFunctions.printf("float%dx%d %s(float%dx%d m) {\n",
- columns, rows, name.c_str(), argColumns, argRows);
- fExtraFunctions.printf(" return float%dx%d(", columns, rows);
- for (int i = 0; i < columns; ++i) {
- if (i > 0) {
- fExtraFunctions.writeText(", ");
- }
- fExtraFunctions.printf("float%d(", rows);
- for (int j = 0; j < rows; ++j) {
- if (j > 0) {
- fExtraFunctions.writeText(", ");
+ case Type::kMatrix_Kind: {
+ fExtraFunctions.printf("x%zu[%d][%d]", argIndex,
+ argPosition / argType.rows(),
+ argPosition % argType.rows());
+ break;
}
- if (i < argColumns && j < argRows) {
- fExtraFunctions.printf("m[%d][%d]", i, j);
- } else {
- fExtraFunctions.writeText("0");
+ default: {
+ SkDEBUGFAIL("incorrect type of argument for matrix constructor");
+ fExtraFunctions.printf("<error>");
+ break;
}
}
- fExtraFunctions.writeText(")");
- }
- fExtraFunctions.writeText(");\n}\n");
- } else if (matrix.rows() == 2 && matrix.columns() == 2 && arg == *fContext.fFloat4_Type) {
- // float2x2(float4) doesn't work, need to split it into float2x2(float2, float2)
- name = "float2x2_from_float4";
- fExtraFunctions.printf(
- "float2x2 %s(float4 v) {\n"
- " return float2x2(float2(v[0], v[1]), float2(v[2], v[3]));\n"
- "}\n",
- name.c_str()
- );
- } else {
- SkASSERT(false);
+
+ ++argPosition;
+ if (argPosition >= argType.columns() * argType.rows()) {
+ ++argIndex;
+ argPosition = 0;
+ }
+ }
+ }
+
+ if (argPosition != 0 || argIndex != args.size()) {
+ SkDEBUGFAIL("incorrect number of arguments for matrix constructor");
name = "<error>";
}
- fHelpers[key] = name;
+
+ fExtraFunctions.printf("));\n}\n");
return name;
}
@@ -468,43 +480,116 @@ bool MetalCodeGenerator::canCoerce(const Type& t1, const Type& t2) {
return t1.isFloat() && t2.isFloat();
}
+bool MetalCodeGenerator::matrixConstructHelperIsNeeded(const Constructor& c) {
+ // A matrix construct helper is only necessary if we are, in fact, constructing a matrix.
+ if (c.fType.kind() != Type::kMatrix_Kind) {
+ return false;
+ }
+
+ // GLSL is fairly free-form about inputs to its matrix constructors, but Metal is not; it
+ // expects exactly R vectors of C components apiece. (Metal 2.0 also allows a list of R*C
+ // scalars.) Some cases are simple to translate and so we handle those inline--e.g. a list of
+ // scalars can be constructed trivially. In more complex cases, we generate a helper function
+ // that converts our inputs into a properly-shaped matrix.
+ // A matrix construct helper method is always used if any input argument is a matrix.
+ // Helper methods are also necessary when any argument would span multiple rows. For instance:
+ //
+ // float2 x = (1, 2);
+ // float3x2(x, 3, 4, 5, 6) = | 1 3 5 | = no helper needed; conversion can be done inline
+ // | 2 4 6 |
+ //
+ // float2 x = (2, 3);
+ // float3x2(1, x, 4, 5, 6) = | 1 3 5 | = x spans multiple rows; a helper method will be used
+ // | 2 4 6 |
+ //
+ // float4 x = (1, 2, 3, 4);
+ // float2x2(x) = | 1 3 | = x spans multiple rows; a helper method will be used
+ // | 2 4 |
+ //
+
+ int position = 0;
+ for (const std::unique_ptr<Expression>& expr : c.fArguments) {
+ // If an input argument is a matrix, we need a helper function.
+ if (expr->fType.kind() == Type::kMatrix_Kind) {
+ return true;
+ }
+ position += expr->fType.columns();
+ if (position > c.fType.rows()) {
+ // An input argument would span multiple rows; a helper function is required.
+ return true;
+ }
+ if (position == c.fType.rows()) {
+ // We've advanced to the end of a row. Wrap to the start of the next row.
+ position = 0;
+ }
+ }
+
+ return false;
+}
+
void MetalCodeGenerator::writeConstructor(const Constructor& c, Precedence parentPrecedence) {
- if (c.fArguments.size() == 1 && this->canCoerce(c.fType, c.fArguments[0]->fType)) {
- this->writeExpression(*c.fArguments[0], parentPrecedence);
- return;
+ // Handle special cases for single-argument constructors.
+ if (c.fArguments.size() == 1) {
+ // If the type is coercible, emit it directly.
+ const Expression& arg = *c.fArguments.front();
+ if (this->canCoerce(c.fType, arg.fType)) {
+ this->writeExpression(arg, parentPrecedence);
+ return;
+ }
+
+ // Metal supports creating matrices with a scalar on the diagonal via the single-argument
+ // matrix constructor.
+ if (c.fType.kind() == Type::kMatrix_Kind && arg.fType.isNumber()) {
+ const Type& matrix = c.fType;
+ this->write("float");
+ this->write(to_string(matrix.columns()));
+ this->write("x");
+ this->write(to_string(matrix.rows()));
+ this->write("(");
+ this->writeExpression(arg, parentPrecedence);
+ this->write(")");
+ return;
+ }
}
- if (c.fType.kind() == Type::kMatrix_Kind && c.fArguments.size() == 1) {
- const Expression& arg = *c.fArguments[0];
- String name = this->getMatrixConstructHelper(c.fType, arg.fType);
- this->write(name);
- this->write("(");
- this->writeExpression(arg, kSequence_Precedence);
- this->write(")");
- } else {
- this->writeType(c.fType);
+
+ // Emit and invoke a matrix-constructor helper method if one is necessary.
+ if (this->matrixConstructHelperIsNeeded(c)) {
+ this->write(this->getMatrixConstructHelper(c));
this->write("(");
const char* separator = "";
- int scalarCount = 0;
- for (const auto& arg : c.fArguments) {
+ for (const std::unique_ptr<Expression>& expr : c.fArguments) {
this->write(separator);
separator = ", ";
- if (Type::kMatrix_Kind == c.fType.kind() && arg->fType.columns() != c.fType.rows()) {
- // merge scalars and smaller vectors together
- if (!scalarCount) {
- this->writeType(c.fType.componentType());
- this->write(to_string(c.fType.rows()));
- this->write("(");
- }
- scalarCount += arg->fType.columns();
- }
- this->writeExpression(*arg, kSequence_Precedence);
- if (scalarCount && scalarCount == c.fType.rows()) {
- this->write(")");
- scalarCount = 0;
- }
+ this->writeExpression(*expr, kSequence_Precedence);
}
this->write(")");
+ return;
+ }
+
+ // Explicitly invoke the constructor, passing in the necessary arguments.
+ this->writeType(c.fType);
+ this->write("(");
+ const char* separator = "";
+ int scalarCount = 0;
+ for (const std::unique_ptr<Expression>& arg : c.fArguments) {
+ this->write(separator);
+ separator = ", ";
+ if (Type::kMatrix_Kind == c.fType.kind() && arg->fType.columns() < c.fType.rows()) {
+ // Merge scalars and smaller vectors together.
+ if (!scalarCount) {
+ this->writeType(c.fType.componentType());
+ this->write(to_string(c.fType.rows()));
+ this->write("(");
+ }
+ scalarCount += arg->fType.columns();
+ }
+ this->writeExpression(*arg, kSequence_Precedence);
+ if (scalarCount && scalarCount == c.fType.rows()) {
+ this->write(")");
+ scalarCount = 0;
+ }
}
+ this->write(")");
}
void MetalCodeGenerator::writeFragCoord() {
@@ -791,7 +876,7 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
this->write("vertex Outputs vertexMain");
break;
default:
- SkASSERT(false);
+ SkDEBUGFAIL("unsupported kind of program");
}
this->write("(Inputs _in [[stage_in]]");
if (-1 != fUniformBuffer) {
@@ -906,35 +991,42 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
if ("main" == f.fDeclaration.fName) {
if (fNeedsGlobalStructInit) {
- this->writeLine(" Globals globalStruct{");
- const char* separator = "";
- for (const auto& intf: fInterfaceBlockNameMap) {
- const auto& intfName = intf.second;
- this->write(separator);
- separator = ", ";
- this->write("&");
- this->writeName(intfName);
+ this->writeLine(" Globals globalStruct;");
+ for (const auto& [interfaceBlock, interfaceName] : fInterfaceBlockNameMap) {
+ this->write(" globalStruct.");
+ this->writeName(interfaceName);
+ this->write(" = &");
+ this->writeName(interfaceName);
+ this->writeLine(";");
}
- for (const auto& var: fInitNonConstGlobalVars) {
- this->write(separator);
- separator = ", ";
+ for (const VarDeclaration* var : fInitNonConstGlobalVars) {
+ this->write(" globalStruct.");
+ this->writeName(var->fVar->fName);
+ this->write(" = ");
this->writeVarInitializer(*var->fVar, *var->fValue);
+ this->writeLine(";");
}
- for (const auto& texture: fTextures) {
- this->write(separator);
- separator = ", ";
+ for (const Variable* texture : fTextures) {
+ this->write(" globalStruct.");
this->writeName(texture->fName);
- this->write(separator);
+ this->write(" = ");
this->writeName(texture->fName);
- this->write(SAMPLER_SUFFIX);
+ this->writeLine(";");
+
+ String samplerName = String(texture->fName) + SAMPLER_SUFFIX;
+ this->write(" globalStruct.");
+ this->writeName(samplerName);
+ this->write(" = ");
+ this->writeName(samplerName);
+ this->writeLine(";");
}
- this->writeLine("};");
this->writeLine(" thread Globals* _globals = &globalStruct;");
this->writeLine(" (void)_globals;");
}
this->writeLine(" Outputs _outputStruct;");
this->writeLine(" thread Outputs* _out = &_outputStruct;");
}
+
fFunctionHeader = "";
OutputStream* oldOut = fOut;
StringStream buffer;
@@ -951,7 +1043,7 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
this->writeLine("return *_out;"); // FIXME - detect if function already has return
break;
default:
- SkASSERT(false);
+ SkDEBUGFAIL("unsupported kind of program");
}
}
fIndentation--;
@@ -1164,11 +1256,15 @@ void MetalCodeGenerator::writeStatements(const std::vector<std::unique_ptr<State
}
void MetalCodeGenerator::writeBlock(const Block& b) {
- this->writeLine("{");
- fIndentation++;
+ if (b.fIsScope) {
+ this->writeLine("{");
+ fIndentation++;
+ }
this->writeStatements(b.fStatements);
- fIndentation--;
- this->write("}");
+ if (b.fIsScope) {
+ fIndentation--;
+ this->write("}");
+ }
}
void MetalCodeGenerator::writeIfStatement(const IfStatement& stmt) {
@@ -1388,11 +1484,15 @@ void MetalCodeGenerator::writeInterfaceBlocks() {
void MetalCodeGenerator::writeGlobalStruct() {
bool wroteStructDecl = false;
- for (const auto& intf : fInterfaceBlockNameMap) {
+ auto WriteStructDecl = [&] {
if (!wroteStructDecl) {
this->write("struct Globals {\n");
wroteStructDecl = true;
}
+ };
+
+ for (const auto& intf : fInterfaceBlockNameMap) {
+ WriteStructDecl();
fNeedsGlobalStructInit = true;
const auto& intfType = intf.first;
const auto& intfName = intf.second;
@@ -1411,10 +1511,7 @@ void MetalCodeGenerator::writeGlobalStruct() {
const Variable& first = *((VarDeclaration&) *decls.fVars[0]).fVar;
if ((!first.fModifiers.fFlags && -1 == first.fModifiers.fLayout.fBuiltin) ||
first.fType.kind() == Type::kSampler_Kind) {
- if (!wroteStructDecl) {
- this->write("struct Globals {\n");
- wroteStructDecl = true;
- }
+ WriteStructDecl();
fNeedsGlobalStructInit = true;
this->write(" ");
this->writeType(first.fType);
@@ -1478,52 +1575,55 @@ void MetalCodeGenerator::writeProgramElement(const ProgramElement& e) {
}
}
-MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Expression& e) {
- switch (e.fKind) {
+MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Expression* e) {
+ if (!e) {
+ return kNo_Requirements;
+ }
+ switch (e->fKind) {
case Expression::kFunctionCall_Kind: {
- const FunctionCall& f = (const FunctionCall&) e;
+ const FunctionCall& f = (const FunctionCall&) *e;
Requirements result = this->requirements(f.fFunction);
- for (const auto& e : f.fArguments) {
- result |= this->requirements(*e);
+ for (const auto& arg : f.fArguments) {
+ result |= this->requirements(arg.get());
}
return result;
}
case Expression::kConstructor_Kind: {
- const Constructor& c = (const Constructor&) e;
+ const Constructor& c = (const Constructor&) *e;
Requirements result = kNo_Requirements;
- for (const auto& e : c.fArguments) {
- result |= this->requirements(*e);
+ for (const auto& arg : c.fArguments) {
+ result |= this->requirements(arg.get());
}
return result;
}
case Expression::kFieldAccess_Kind: {
- const FieldAccess& f = (const FieldAccess&) e;
+ const FieldAccess& f = (const FieldAccess&) *e;
if (FieldAccess::kAnonymousInterfaceBlock_OwnerKind == f.fOwnerKind) {
return kGlobals_Requirement;
}
- return this->requirements(*((const FieldAccess&) e).fBase);
+ return this->requirements(f.fBase.get());
}
case Expression::kSwizzle_Kind:
- return this->requirements(*((const Swizzle&) e).fBase);
+ return this->requirements(((const Swizzle&) *e).fBase.get());
case Expression::kBinary_Kind: {
- const BinaryExpression& b = (const BinaryExpression&) e;
- return this->requirements(*b.fLeft) | this->requirements(*b.fRight);
+ const BinaryExpression& b = (const BinaryExpression&) *e;
+ return this->requirements(b.fLeft.get()) | this->requirements(b.fRight.get());
}
case Expression::kIndex_Kind: {
- const IndexExpression& idx = (const IndexExpression&) e;
- return this->requirements(*idx.fBase) | this->requirements(*idx.fIndex);
+ const IndexExpression& idx = (const IndexExpression&) *e;
+ return this->requirements(idx.fBase.get()) | this->requirements(idx.fIndex.get());
}
case Expression::kPrefix_Kind:
- return this->requirements(*((const PrefixExpression&) e).fOperand);
+ return this->requirements(((const PrefixExpression&) *e).fOperand.get());
case Expression::kPostfix_Kind:
- return this->requirements(*((const PostfixExpression&) e).fOperand);
+ return this->requirements(((const PostfixExpression&) *e).fOperand.get());
case Expression::kTernary_Kind: {
- const TernaryExpression& t = (const TernaryExpression&) e;
- return this->requirements(*t.fTest) | this->requirements(*t.fIfTrue) |
- this->requirements(*t.fIfFalse);
+ const TernaryExpression& t = (const TernaryExpression&) *e;
+ return this->requirements(t.fTest.get()) | this->requirements(t.fIfTrue.get()) |
+ this->requirements(t.fIfFalse.get());
}
case Expression::kVariableReference_Kind: {
- const VariableReference& v = (const VariableReference&) e;
+ const VariableReference& v = (const VariableReference&) *e;
Requirements result = kNo_Requirements;
if (v.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) {
result = kGlobals_Requirement | kFragCoord_Requirement;
@@ -1546,69 +1646,65 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Expressi
}
}
-MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Statement& s) {
- switch (s.fKind) {
+MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Statement* s) {
+ if (!s) {
+ return kNo_Requirements;
+ }
+ switch (s->fKind) {
case Statement::kBlock_Kind: {
Requirements result = kNo_Requirements;
- for (const auto& child : ((const Block&) s).fStatements) {
- result |= this->requirements(*child);
+ for (const auto& child : ((const Block*) s)->fStatements) {
+ result |= this->requirements(child.get());
}
return result;
}
case Statement::kVarDeclaration_Kind: {
- Requirements result = kNo_Requirements;
- const VarDeclaration& var = (const VarDeclaration&) s;
- if (var.fValue) {
- result = this->requirements(*var.fValue);
- }
- return result;
+ const VarDeclaration& var = (const VarDeclaration&) *s;
+ return this->requirements(var.fValue.get());
}
case Statement::kVarDeclarations_Kind: {
Requirements result = kNo_Requirements;
- const VarDeclarations& decls = *((const VarDeclarationsStatement&) s).fDeclaration;
+ const VarDeclarations& decls = *((const VarDeclarationsStatement&) *s).fDeclaration;
for (const auto& stmt : decls.fVars) {
- result |= this->requirements(*stmt);
+ result |= this->requirements(stmt.get());
}
return result;
}
case Statement::kExpression_Kind:
- return this->requirements(*((const ExpressionStatement&) s).fExpression);
+ return this->requirements(((const ExpressionStatement&) *s).fExpression.get());
case Statement::kReturn_Kind: {
- const ReturnStatement& r = (const ReturnStatement&) s;
- if (r.fExpression) {
- return this->requirements(*r.fExpression);
- }
- return kNo_Requirements;
+ const ReturnStatement& r = (const ReturnStatement&) *s;
+ return this->requirements(r.fExpression.get());
}
case Statement::kIf_Kind: {
- const IfStatement& i = (const IfStatement&) s;
- return this->requirements(*i.fTest) |
- this->requirements(*i.fIfTrue) |
- (i.fIfFalse ? this->requirements(*i.fIfFalse) : 0);
+ const IfStatement& i = (const IfStatement&) *s;
+ return this->requirements(i.fTest.get()) |
+ this->requirements(i.fIfTrue.get()) |
+ this->requirements(i.fIfFalse.get());
}
case Statement::kFor_Kind: {
- const ForStatement& f = (const ForStatement&) s;
- return this->requirements(*f.fInitializer) |
- this->requirements(*f.fTest) |
- this->requirements(*f.fNext) |
- this->requirements(*f.fStatement);
+ const ForStatement& f = (const ForStatement&) *s;
+ return this->requirements(f.fInitializer.get()) |
+ this->requirements(f.fTest.get()) |
+ this->requirements(f.fNext.get()) |
+ this->requirements(f.fStatement.get());
}
case Statement::kWhile_Kind: {
- const WhileStatement& w = (const WhileStatement&) s;
- return this->requirements(*w.fTest) |
- this->requirements(*w.fStatement);
+ const WhileStatement& w = (const WhileStatement&) *s;
+ return this->requirements(w.fTest.get()) |
+ this->requirements(w.fStatement.get());
}
case Statement::kDo_Kind: {
- const DoStatement& d = (const DoStatement&) s;
- return this->requirements(*d.fTest) |
- this->requirements(*d.fStatement);
+ const DoStatement& d = (const DoStatement&) *s;
+ return this->requirements(d.fTest.get()) |
+ this->requirements(d.fStatement.get());
}
case Statement::kSwitch_Kind: {
- const SwitchStatement& sw = (const SwitchStatement&) s;
- Requirements result = this->requirements(*sw.fValue);
+ const SwitchStatement& sw = (const SwitchStatement&) *s;
+ Requirements result = this->requirements(sw.fValue.get());
for (const auto& c : sw.fCases) {
for (const auto& st : c->fStatements) {
- result |= this->requirements(*st);
+ result |= this->requirements(st.get());
}
}
return result;
@@ -1629,7 +1725,7 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Function
if (ProgramElement::kFunction_Kind == e.fKind) {
const FunctionDefinition& def = (const FunctionDefinition&) e;
if (&def.fDeclaration == &f) {
- Requirements reqs = this->requirements(*def.fBody);
+ Requirements reqs = this->requirements(def.fBody.get());
fRequirements[&f] = reqs;
return reqs;
}
diff --git a/chromium/third_party/skia/src/sksl/SkSLMetalCodeGenerator.h b/chromium/third_party/skia/src/sksl/SkSLMetalCodeGenerator.h
index 1b750629c4d..65216dc3aa2 100644
--- a/chromium/third_party/skia/src/sksl/SkSLMetalCodeGenerator.h
+++ b/chromium/third_party/skia/src/sksl/SkSLMetalCodeGenerator.h
@@ -11,6 +11,7 @@
#include <stack>
#include <tuple>
#include <unordered_map>
+#include <unordered_set>
#include "src/sksl/SkSLCodeGenerator.h"
#include "src/sksl/SkSLMemoryLayout.h"
@@ -189,7 +190,8 @@ protected:
void writeInverseHack(const Expression& mat);
- String getMatrixConstructHelper(const Type& matrix, const Type& arg);
+ bool matrixConstructHelperIsNeeded(const Constructor& c);
+ String getMatrixConstructHelper(const Constructor& c);
void writeMatrixTimesEqualHelper(const Type& left, const Type& right, const Type& result);
@@ -245,9 +247,9 @@ protected:
Requirements requirements(const FunctionDeclaration& f);
- Requirements requirements(const Expression& e);
+ Requirements requirements(const Expression* e);
- Requirements requirements(const Statement& e);
+ Requirements requirements(const Statement* s);
typedef std::pair<IntrinsicKind, int32_t> Intrinsic;
std::unordered_map<String, Intrinsic> fIntrinsicMap;
@@ -278,7 +280,7 @@ protected:
std::unordered_map<const FunctionDeclaration*, Requirements> fRequirements;
bool fSetupFragPositionGlobal = false;
bool fSetupFragPositionLocal = false;
- std::unordered_map<String, String> fHelpers;
+ std::unordered_set<String> fHelpers;
int fUniformBuffer = -1;
String fRTHeightName;
diff --git a/chromium/third_party/skia/src/sksl/SkSLParser.cpp b/chromium/third_party/skia/src/sksl/SkSLParser.cpp
index 3f7df7997fd..afa9e3dab1b 100644
--- a/chromium/third_party/skia/src/sksl/SkSLParser.cpp
+++ b/chromium/third_party/skia/src/sksl/SkSLParser.cpp
@@ -1069,7 +1069,7 @@ ASTNode::ID Parser::statement() {
if (this->isType(this->text(start))) {
return this->varDeclarations();
}
- // fall through
+ [[fallthrough]];
default:
return this->expressionStatement();
}
@@ -1370,7 +1370,8 @@ ASTNode::ID Parser::forStatement() {
getNode(result).addChild(initializer);
break;
}
- } // fall through
+ [[fallthrough]];
+ }
default:
initializer = this->expressionStatement();
if (!initializer) {
@@ -1960,7 +1961,7 @@ ASTNode::ID Parser::postfixExpression() {
if (this->text(t)[0] != '.') {
return result;
}
- // fall through
+ [[fallthrough]];
case Token::Kind::TK_LBRACKET:
case Token::Kind::TK_DOT:
case Token::Kind::TK_LPAREN:
@@ -2016,6 +2017,7 @@ ASTNode::ID Parser::suffix(ASTNode::ID base) {
getNode(result).addChild(base);
return result;
}
+ [[fallthrough]]; // FIXME(ethannicholas)
}
case Token::Kind::TK_FLOAT_LITERAL: {
// Swizzles that start with a constant number, e.g. '.000r', will be tokenized as
@@ -2082,6 +2084,7 @@ ASTNode::ID Parser::term() {
if (this->identifier(&text)) {
RETURN_NODE(t.fOffset, ASTNode::Kind::kIdentifier, std::move(text));
}
+ break;
}
case Token::Kind::TK_INT_LITERAL: {
SKSL_INT i;
diff --git a/chromium/third_party/skia/src/sksl/SkSLSPIRVCodeGenerator.cpp b/chromium/third_party/skia/src/sksl/SkSLSPIRVCodeGenerator.cpp
index b01bd95c38c..4103592581e 100644
--- a/chromium/third_party/skia/src/sksl/SkSLSPIRVCodeGenerator.cpp
+++ b/chromium/third_party/skia/src/sksl/SkSLSPIRVCodeGenerator.cpp
@@ -152,8 +152,7 @@ static bool is_float(const Context& context, const Type& type) {
if (type.columns() > 1) {
return is_float(context, type.componentType());
}
- return type == *context.fFloat_Type || type == *context.fHalf_Type ||
- type == *context.fDouble_Type;
+ return type == *context.fFloat_Type || type == *context.fHalf_Type;
}
static bool is_signed(const Context& context, const Type& type) {
@@ -254,10 +253,10 @@ void SPIRVCodeGenerator::writeString(const char* string, size_t length, OutputSt
switch (length % 4) {
case 1:
out.write8(0);
- // fall through
+ [[fallthrough]];
case 2:
out.write8(0);
- // fall through
+ [[fallthrough]];
case 3:
out.write8(0);
break;
@@ -491,8 +490,6 @@ SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layou
} else if (type == *fContext.fFloat_Type || type == *fContext.fHalf_Type ||
type == *fContext.fFloatLiteral_Type) {
this->writeInstruction(SpvOpTypeFloat, result, 32, fConstantBuffer);
- } else if (type == *fContext.fDouble_Type) {
- this->writeInstruction(SpvOpTypeFloat, result, 64, fConstantBuffer);
} else {
SkASSERT(false);
}
@@ -1813,77 +1810,111 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
this->writeInstruction(SpvOpLoad, this->getType(ref.fVariable.fType), result, var, out);
this->writePrecisionModifier(ref.fVariable.fType, result);
if (ref.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN &&
- fProgram.fSettings.fFlipY) {
- // need to remap to a top-left coordinate system
- if (fRTHeightStructId == (SpvId) -1) {
- // height variable hasn't been written yet
- std::shared_ptr<SymbolTable> st(new SymbolTable(&fErrors));
- SkASSERT(fRTHeightFieldIndex == (SpvId) -1);
- std::vector<Type::Field> fields;
- SkASSERT(fProgram.fSettings.fRTHeightOffset >= 0);
- fields.emplace_back(Modifiers(Layout(0, -1, fProgram.fSettings.fRTHeightOffset, -1,
- -1, -1, -1, -1, Layout::Format::kUnspecified,
- Layout::kUnspecified_Primitive, -1, -1, "", "",
- Layout::kNo_Key, Layout::CType::kDefault), 0),
- SKSL_RTHEIGHT_NAME, fContext.fFloat_Type.get());
- StringFragment name("sksl_synthetic_uniforms");
- Type intfStruct(-1, name, fields);
-
- int binding = fProgram.fSettings.fRTHeightBinding;
- int set = fProgram.fSettings.fRTHeightSet;
- SkASSERT(binding != -1 && set != -1);
-
- Layout layout(0, -1, -1, binding, -1, set, -1, -1, Layout::Format::kUnspecified,
- Layout::kUnspecified_Primitive, -1, -1, "", "", Layout::kNo_Key,
- Layout::CType::kDefault);
- Variable* intfVar = (Variable*) fSynthetics.takeOwnership(std::unique_ptr<Symbol>(
- new Variable(-1,
- Modifiers(layout, Modifiers::kUniform_Flag),
- name,
- intfStruct,
- Variable::kGlobal_Storage)));
- InterfaceBlock intf(-1, intfVar, name, String(""),
- std::vector<std::unique_ptr<Expression>>(), st);
- fRTHeightStructId = this->writeInterfaceBlock(intf);
- fRTHeightFieldIndex = 0;
- }
- SkASSERT(fRTHeightFieldIndex != (SpvId) -1);
- // write float4(gl_FragCoord.x, u_skRTHeight - gl_FragCoord.y, 0.0, gl_FragCoord.w)
+ (fProgram.fSettings.fFlipY || fProgram.fSettings.fInverseW)) {
+ // The x component never changes, so just grab it
SpvId xId = this->nextId();
this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fFloat_Type), xId,
result, 0, out);
- IntLiteral fieldIndex(fContext, -1, fRTHeightFieldIndex);
- SpvId fieldIndexId = this->writeIntLiteral(fieldIndex);
- SpvId heightPtr = this->nextId();
- this->writeOpCode(SpvOpAccessChain, 5, out);
- this->writeWord(this->getPointerType(*fContext.fFloat_Type, SpvStorageClassUniform), out);
- this->writeWord(heightPtr, out);
- this->writeWord(fRTHeightStructId, out);
- this->writeWord(fieldIndexId, out);
- SpvId heightRead = this->nextId();
- this->writeInstruction(SpvOpLoad, this->getType(*fContext.fFloat_Type), heightRead,
- heightPtr, out);
+
+ // Calculate the y component which may need to be flipped
SpvId rawYId = this->nextId();
this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fFloat_Type), rawYId,
result, 1, out);
- SpvId flippedYId = this->nextId();
- this->writeInstruction(SpvOpFSub, this->getType(*fContext.fFloat_Type), flippedYId,
- heightRead, rawYId, out);
+ SpvId flippedYId = 0;
+ if (fProgram.fSettings.fFlipY) {
+ // need to remap to a top-left coordinate system
+ if (fRTHeightStructId == (SpvId)-1) {
+ // height variable hasn't been written yet
+ std::shared_ptr<SymbolTable> st(new SymbolTable(&fErrors));
+ SkASSERT(fRTHeightFieldIndex == (SpvId)-1);
+ std::vector<Type::Field> fields;
+ SkASSERT(fProgram.fSettings.fRTHeightOffset >= 0);
+ fields.emplace_back(
+ Modifiers(Layout(0, -1, fProgram.fSettings.fRTHeightOffset, -1, -1, -1, -1,
+ -1, Layout::Format::kUnspecified,
+ Layout::kUnspecified_Primitive, 1, -1, "", "",
+ Layout::kNo_Key, Layout::CType::kDefault),
+ 0),
+ SKSL_RTHEIGHT_NAME, fContext.fFloat_Type.get());
+ StringFragment name("sksl_synthetic_uniforms");
+ Type intfStruct(-1, name, fields);
+
+ int binding = fProgram.fSettings.fRTHeightBinding;
+ int set = fProgram.fSettings.fRTHeightSet;
+ SkASSERT(binding != -1 && set != -1);
+
+ Layout layout(0, -1, -1, binding, -1, set, -1, -1, Layout::Format::kUnspecified,
+ Layout::kUnspecified_Primitive, -1, -1, "", "", Layout::kNo_Key,
+ Layout::CType::kDefault);
+ Variable* intfVar = (Variable*)fSynthetics.takeOwnership(std::unique_ptr<Symbol>(
+ new Variable(-1,
+ Modifiers(layout, Modifiers::kUniform_Flag),
+ name,
+ intfStruct,
+ Variable::kGlobal_Storage)));
+ InterfaceBlock intf(-1, intfVar, name, String(""),
+ std::vector<std::unique_ptr<Expression>>(), st);
+
+ fRTHeightStructId = this->writeInterfaceBlock(intf, false);
+ fRTHeightFieldIndex = 0;
+ }
+ SkASSERT(fRTHeightFieldIndex != (SpvId)-1);
+
+ IntLiteral fieldIndex(fContext, -1, fRTHeightFieldIndex);
+ SpvId fieldIndexId = this->writeIntLiteral(fieldIndex);
+ SpvId heightPtr = this->nextId();
+ this->writeOpCode(SpvOpAccessChain, 5, out);
+ this->writeWord(this->getPointerType(*fContext.fFloat_Type, SpvStorageClassUniform),
+ out);
+ this->writeWord(heightPtr, out);
+ this->writeWord(fRTHeightStructId, out);
+ this->writeWord(fieldIndexId, out);
+ SpvId heightRead = this->nextId();
+ this->writeInstruction(SpvOpLoad, this->getType(*fContext.fFloat_Type), heightRead,
+ heightPtr, out);
+
+ flippedYId = this->nextId();
+ this->writeInstruction(SpvOpFSub, this->getType(*fContext.fFloat_Type), flippedYId,
+ heightRead, rawYId, out);
+ }
+
+ // The z component will always be zero so we just get an id to the 0 literal
FloatLiteral zero(fContext, -1, 0.0);
SpvId zeroId = writeFloatLiteral(zero);
- FloatLiteral one(fContext, -1, 1.0);
- SpvId wId = this->nextId();
- this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fFloat_Type), wId,
+
+ // Calculate the w component which may need to be inverted
+ SpvId rawWId = this->nextId();
+ this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fFloat_Type), rawWId,
result, 3, out);
- SpvId flipped = this->nextId();
+ SpvId invWId = 0;
+ if (fProgram.fSettings.fInverseW) {
+ // We need to invert w
+ FloatLiteral one(fContext, -1, 1.0);
+ SpvId oneId = writeFloatLiteral(one);
+ invWId = this->nextId();
+ this->writeInstruction(SpvOpFDiv, this->getType(*fContext.fFloat_Type), invWId, oneId,
+ rawWId, out);
+ }
+
+ // Fill in the new fragcoord with the components from above
+ SpvId adjusted = this->nextId();
this->writeOpCode(SpvOpCompositeConstruct, 7, out);
this->writeWord(this->getType(*fContext.fFloat4_Type), out);
- this->writeWord(flipped, out);
+ this->writeWord(adjusted, out);
this->writeWord(xId, out);
- this->writeWord(flippedYId, out);
+ if (fProgram.fSettings.fFlipY) {
+ this->writeWord(flippedYId, out);
+ } else {
+ this->writeWord(rawYId, out);
+ }
this->writeWord(zeroId, out);
- this->writeWord(wId, out);
- return flipped;
+ if (fProgram.fSettings.fInverseW) {
+ this->writeWord(invWId, out);
+ } else {
+ this->writeWord(rawWId, out);
+ }
+
+ return adjusted;
}
if (ref.fVariable.fModifiers.fLayout.fBuiltin == SK_CLOCKWISE_BUILTIN &&
!fProgram.fSettings.fFlipY) {
@@ -2510,42 +2541,26 @@ SpvId SPIRVCodeGenerator::writeIntLiteral(const IntLiteral& i) {
}
SpvId SPIRVCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
- if (f.fType != *fContext.fDouble_Type) {
- ConstantType type;
- if (f.fType == *fContext.fHalf_Type) {
- type = ConstantType::kHalf;
- } else {
- type = ConstantType::kFloat;
- }
- float value = (float) f.fValue;
- std::pair<ConstantValue, ConstantType> key(f.fValue, type);
- auto entry = fNumberConstants.find(key);
- if (entry == fNumberConstants.end()) {
- SpvId result = this->nextId();
- uint32_t bits;
- SkASSERT(sizeof(bits) == sizeof(value));
- memcpy(&bits, &value, sizeof(bits));
- this->writeInstruction(SpvOpConstant, this->getType(f.fType), result, bits,
- fConstantBuffer);
- fNumberConstants[key] = result;
- return result;
- }
- return entry->second;
+ ConstantType type;
+ if (f.fType == *fContext.fHalf_Type) {
+ type = ConstantType::kHalf;
} else {
- std::pair<ConstantValue, ConstantType> key(f.fValue, ConstantType::kDouble);
- auto entry = fNumberConstants.find(key);
- if (entry == fNumberConstants.end()) {
- SpvId result = this->nextId();
- uint64_t bits;
- SkASSERT(sizeof(bits) == sizeof(f.fValue));
- memcpy(&bits, &f.fValue, sizeof(bits));
- this->writeInstruction(SpvOpConstant, this->getType(f.fType), result,
- bits & 0xffffffff, bits >> 32, fConstantBuffer);
- fNumberConstants[key] = result;
- return result;
- }
- return entry->second;
+ type = ConstantType::kFloat;
}
+ float value = (float) f.fValue;
+ std::pair<ConstantValue, ConstantType> key(f.fValue, type);
+ auto entry = fNumberConstants.find(key);
+ if (entry == fNumberConstants.end()) {
+ SpvId result = this->nextId();
+ uint32_t bits;
+ SkASSERT(sizeof(bits) == sizeof(value));
+ memcpy(&bits, &value, sizeof(bits));
+ this->writeInstruction(SpvOpConstant, this->getType(f.fType), result, bits,
+ fConstantBuffer);
+ fNumberConstants[key] = result;
+ return result;
+ }
+ return entry->second;
}
SpvId SPIRVCodeGenerator::writeFunctionStart(const FunctionDeclaration& f, OutputStream& out) {
@@ -2663,7 +2678,7 @@ static void update_sk_in_count(const Modifiers& m, int* outSkInCount) {
}
}
-SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
+SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool appendRTHeight) {
bool isBuffer = (0 != (intf.fVariable.fModifiers.fFlags & Modifiers::kBuffer_Flag));
bool pushConstant = (0 != (intf.fVariable.fModifiers.fLayout.fFlags &
Layout::kPushConstant_Flag));
@@ -2672,7 +2687,7 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
fDefaultLayout;
SpvId result = this->nextId();
const Type* type = &intf.fVariable.fType;
- if (fProgram.fInputs.fRTHeight) {
+ if (fProgram.fInputs.fRTHeight && appendRTHeight) {
SkASSERT(fRTHeightStructId == (SpvId) -1);
SkASSERT(fRTHeightFieldIndex == (SpvId) -1);
std::vector<Type::Field> fields = type->fields();
@@ -2709,7 +2724,7 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
}
this->writeLayout(layout, result);
fVariableMap[&intf.fVariable] = result;
- if (fProgram.fInputs.fRTHeight) {
+ if (fProgram.fInputs.fRTHeight && appendRTHeight) {
delete type;
}
return result;
@@ -2987,14 +3002,6 @@ void SPIRVCodeGenerator::writeWhileStatement(const WhileStatement& w, OutputStre
}
void SPIRVCodeGenerator::writeDoStatement(const DoStatement& d, OutputStream& out) {
- // We believe the do loop code below will work, but Skia doesn't actually use them and
- // adequately testing this code in the absence of Skia exercising it isn't straightforward. For
- // the time being, we just fail with an error due to the lack of testing. If you encounter this
- // message, simply remove the error call below to see whether our do loop support actually
- // works.
- fErrors.error(d.fOffset, "internal error: do loop support has been disabled in SPIR-V, see "
- "SkSLSPIRVCodeGenerator.cpp for details");
-
SpvId header = this->nextId();
SpvId start = this->nextId();
SpvId next = this->nextId();
diff --git a/chromium/third_party/skia/src/sksl/SkSLSPIRVCodeGenerator.h b/chromium/third_party/skia/src/sksl/SkSLSPIRVCodeGenerator.h
index 8f14b46fb57..efb89a5dca9 100644
--- a/chromium/third_party/skia/src/sksl/SkSLSPIRVCodeGenerator.h
+++ b/chromium/third_party/skia/src/sksl/SkSLSPIRVCodeGenerator.h
@@ -177,7 +177,7 @@ private:
void writeProgramElement(const ProgramElement& pe, OutputStream& out);
- SpvId writeInterfaceBlock(const InterfaceBlock& intf);
+ SpvId writeInterfaceBlock(const InterfaceBlock& intf, bool appendRTHeight = true);
SpvId writeFunctionStart(const FunctionDeclaration& f, OutputStream& out);
diff --git a/chromium/third_party/skia/src/sksl/SkSLSampleMatrix.cpp b/chromium/third_party/skia/src/sksl/SkSLSampleMatrix.cpp
index 4593702c0e8..9b07f5948e8 100644
--- a/chromium/third_party/skia/src/sksl/SkSLSampleMatrix.cpp
+++ b/chromium/third_party/skia/src/sksl/SkSLSampleMatrix.cpp
@@ -7,13 +7,32 @@
#include "src/sksl/SkSLSampleMatrix.h"
+#include "src/sksl/ir/SkSLBinaryExpression.h"
+#include "src/sksl/ir/SkSLConstructor.h"
+#include "src/sksl/ir/SkSLDoStatement.h"
#include "src/sksl/ir/SkSLExpression.h"
+#include "src/sksl/ir/SkSLExpressionStatement.h"
+#include "src/sksl/ir/SkSLFieldAccess.h"
+#include "src/sksl/ir/SkSLForStatement.h"
+#include "src/sksl/ir/SkSLFunctionCall.h"
+#include "src/sksl/ir/SkSLIfStatement.h"
+#include "src/sksl/ir/SkSLIndexExpression.h"
+#include "src/sksl/ir/SkSLPostfixExpression.h"
+#include "src/sksl/ir/SkSLPrefixExpression.h"
+#include "src/sksl/ir/SkSLProgram.h"
+#include "src/sksl/ir/SkSLReturnStatement.h"
+#include "src/sksl/ir/SkSLSwitchStatement.h"
+#include "src/sksl/ir/SkSLSwizzle.h"
+#include "src/sksl/ir/SkSLTernaryExpression.h"
+#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
+#include "src/sksl/ir/SkSLVariable.h"
+#include "src/sksl/ir/SkSLWhileStatement.h"
namespace SkSL {
SampleMatrix SampleMatrix::merge(const SampleMatrix& other) {
if (fKind == Kind::kVariable || other.fKind == Kind::kVariable) {
- *this = SampleMatrix(Kind::kVariable);
+ *this = SampleMatrix::MakeVariable();
return *this;
}
if (other.fKind == Kind::kConstantOrUniform) {
@@ -21,7 +40,7 @@ SampleMatrix SampleMatrix::merge(const SampleMatrix& other) {
if (fExpression == other.fExpression) {
return *this;
}
- *this = SampleMatrix(Kind::kVariable);
+ *this = SampleMatrix::MakeVariable();
return *this;
}
SkASSERT(fKind == Kind::kNone);
@@ -31,4 +50,175 @@ SampleMatrix SampleMatrix::merge(const SampleMatrix& other) {
return *this;
}
+struct SampleMatrixExtractor {
+ SampleMatrixExtractor(const Program& program, const Variable& fp)
+ : fProgram(program), fFP(fp) {}
+
+ SampleMatrix getMatrix(const Expression&) const;
+ SampleMatrix getMatrix(const Statement&) const;
+
+ SampleMatrix getMatrix(const Expression* e) const {
+ return e ? this->getMatrix(*e) : SampleMatrix();
+ }
+ SampleMatrix getMatrix(const Statement* s) const {
+ return s ? this->getMatrix(*s) : SampleMatrix();
+ }
+
+ SampleMatrix getMatrix(const ProgramElement& pe) const {
+ if (pe.fKind == ProgramElement::kFunction_Kind) {
+ return this->getMatrix(*((const FunctionDefinition&) pe).fBody);
+ }
+ return SampleMatrix();
+ }
+
+ const Program& fProgram;
+ const Variable& fFP;
+};
+
+SampleMatrix SampleMatrix::Make(const Program& program, const Variable& fp) {
+ SampleMatrix result;
+ SampleMatrixExtractor extractor(program, fp);
+ for (const auto& pe : program) {
+ result.merge(extractor.getMatrix(pe));
+ }
+ return result;
+}
+
+SampleMatrix SampleMatrixExtractor::getMatrix(const Expression& e) const {
+ switch (e.fKind) {
+ case Expression::kFunctionCall_Kind: {
+ const FunctionCall& fc = (const FunctionCall&) e;
+ const FunctionDeclaration& f = fc.fFunction;
+ if (f.fBuiltin && f.fName == "sample" && fc.fArguments.size() >= 2 &&
+ fc.fArguments.back()->fType == *fProgram.fContext->fFloat3x3_Type &&
+ fc.fArguments[0]->fKind == Expression::kVariableReference_Kind &&
+ &((VariableReference&) *fc.fArguments[0]).fVariable == &fFP) {
+ if (fc.fArguments.back()->isConstantOrUniform()) {
+ return SampleMatrix::MakeConstUniform(fc.fArguments.back()->description());
+ } else {
+ return SampleMatrix::MakeVariable();
+ }
+ }
+ SampleMatrix result;
+ for (const auto& e : fc.fArguments) {
+ result.merge(this->getMatrix(*e));
+ }
+ return result;
+ }
+ case Expression::kConstructor_Kind: {
+ SampleMatrix result;
+ const Constructor& c = (const Constructor&) e;
+ for (const auto& e : c.fArguments) {
+ result.merge(this->getMatrix(*e));
+ }
+ return result;
+ }
+ case Expression::kFieldAccess_Kind:
+ return this->getMatrix(*((const FieldAccess&) e).fBase);
+ case Expression::kSwizzle_Kind:
+ return this->getMatrix(*((const Swizzle&) e).fBase);
+ case Expression::kBinary_Kind: {
+ const BinaryExpression& b = (const BinaryExpression&) e;
+ return this->getMatrix(*b.fLeft).merge(
+ this->getMatrix(*b.fRight));
+ }
+ case Expression::kIndex_Kind: {
+ const IndexExpression& idx = (const IndexExpression&) e;
+ return this->getMatrix(*idx.fBase).merge(
+ this->getMatrix(*idx.fIndex));
+ }
+ case Expression::kPrefix_Kind:
+ return this->getMatrix(*((const PrefixExpression&) e).fOperand);
+ case Expression::kPostfix_Kind:
+ return this->getMatrix(*((const PostfixExpression&) e).fOperand);
+ case Expression::kTernary_Kind: {
+ const TernaryExpression& t = (const TernaryExpression&) e;
+ return this->getMatrix(*t.fTest).merge(
+ this->getMatrix(*t.fIfTrue)).merge(
+ this->getMatrix(*t.fIfFalse));
+ }
+ case Expression::kVariableReference_Kind:
+ return SampleMatrix();
+ case Expression::kBoolLiteral_Kind:
+ case Expression::kDefined_Kind:
+ case Expression::kExternalFunctionCall_Kind:
+ case Expression::kExternalValue_Kind:
+ case Expression::kFloatLiteral_Kind:
+ case Expression::kFunctionReference_Kind:
+ case Expression::kIntLiteral_Kind:
+ case Expression::kNullLiteral_Kind:
+ case Expression::kSetting_Kind:
+ case Expression::kTypeReference_Kind:
+ return SampleMatrix();
+ }
+ SkASSERT(false);
+ return SampleMatrix();
+}
+
+SampleMatrix SampleMatrixExtractor::getMatrix(const Statement& s) const {
+ switch (s.fKind) {
+ case Statement::kBlock_Kind: {
+ SampleMatrix result;
+ for (const auto& child : ((const Block&) s).fStatements) {
+ result.merge(this->getMatrix(*child));
+ }
+ return result;
+ }
+ case Statement::kVarDeclaration_Kind:
+ return this->getMatrix(((const VarDeclaration&) s).fValue.get());
+ case Statement::kVarDeclarations_Kind: {
+ const VarDeclarations& decls = *((const VarDeclarationsStatement&) s).fDeclaration;
+ SampleMatrix result;
+ for (const auto& stmt : decls.fVars) {
+ result.merge(this->getMatrix(*stmt));
+ }
+ return result;
+ }
+ case Statement::kExpression_Kind:
+ return this->getMatrix(*((const ExpressionStatement&) s).fExpression);
+ case Statement::kReturn_Kind:
+ return this->getMatrix(((const ReturnStatement&) s).fExpression.get());
+ case Statement::kIf_Kind: {
+ const IfStatement& i = (const IfStatement&) s;
+ return this->getMatrix(*i.fTest).merge(
+ this->getMatrix(*i.fIfTrue)).merge(
+ this->getMatrix(i.fIfFalse.get()));
+ }
+ case Statement::kFor_Kind: {
+ const ForStatement& f = (const ForStatement&) s;
+ return this->getMatrix(f.fInitializer.get()).merge(
+ this->getMatrix(f.fTest.get()).merge(
+ this->getMatrix(f.fNext.get()).merge(
+ this->getMatrix(*f.fStatement))));
+ }
+ case Statement::kWhile_Kind: {
+ const WhileStatement& w = (const WhileStatement&) s;
+ return this->getMatrix(*w.fTest).merge(
+ this->getMatrix(*w.fStatement));
+ }
+ case Statement::kDo_Kind: {
+ const DoStatement& d = (const DoStatement&) s;
+ return this->getMatrix(*d.fTest).merge(
+ this->getMatrix(*d.fStatement));
+ }
+ case Statement::kSwitch_Kind: {
+ SampleMatrix result;
+ const SwitchStatement& sw = (const SwitchStatement&) s;
+ for (const auto& c : sw.fCases) {
+ for (const auto& st : c->fStatements) {
+ result.merge(this->getMatrix(*st));
+ }
+ }
+ return result.merge(this->getMatrix(*sw.fValue));
+ }
+ case Statement::kBreak_Kind:
+ case Statement::kContinue_Kind:
+ case Statement::kDiscard_Kind:
+ case Statement::kNop_Kind:
+ return SampleMatrix();
+ }
+ SkASSERT(false);
+ return SampleMatrix();
+}
+
} // namespace
diff --git a/chromium/third_party/skia/src/sksl/SkSLSampleMatrix.h b/chromium/third_party/skia/src/sksl/SkSLSampleMatrix.h
index 7f121b07c03..41c0cb68ee5 100644
--- a/chromium/third_party/skia/src/sksl/SkSLSampleMatrix.h
+++ b/chromium/third_party/skia/src/sksl/SkSLSampleMatrix.h
@@ -16,6 +16,8 @@ class GrFragmentProcessor;
namespace SkSL {
struct Expression;
+struct Program;
+struct Variable;
/**
* Represents the matrix applied to a fragment processor by its parent's sample(child, matrix) call.
@@ -25,7 +27,8 @@ struct SampleMatrix {
// No sample(child, matrix) call affects the FP.
kNone,
// The FP is sampled with a matrix whose value is fixed and based only on constants or
- // uniforms, and thus the transform can be hoisted to the vertex shader.
+ // uniforms, and thus the transform can be hoisted to the vertex shader (assuming that
+ // its parent can also be hoisted, i.e. not sampled explicitly).
kConstantOrUniform,
// The FP is sampled with a non-constant/uniform value, or sampled multiple times, and
// thus the transform cannot be hoisted to the vertex shader.
@@ -36,25 +39,25 @@ struct SampleMatrix {
kMixed,
};
+ // Make a SampleMatrix with kNone for its kind. Will not have an expression or have perspective.
SampleMatrix()
- : fOwner(nullptr)
- , fKind(Kind::kNone) {}
+ : fOwner(nullptr)
+ , fKind(Kind::kNone) {}
- SampleMatrix(Kind kind)
- : fOwner(nullptr)
- , fKind(kind) {
- SkASSERT(kind == Kind::kNone || kind == Kind::kVariable);
+ static SampleMatrix MakeConstUniform(String expression) {
+ return SampleMatrix(Kind::kConstantOrUniform, expression);
}
- SampleMatrix(Kind kind, GrFragmentProcessor* owner, String expression)
- : fOwner(owner)
- , fKind(kind)
- , fExpression(expression) {}
+ static SampleMatrix MakeVariable() {
+ return SampleMatrix(Kind::kVariable, "");
+ }
+
+ static SampleMatrix Make(const Program& program, const Variable& fp);
SampleMatrix merge(const SampleMatrix& other);
bool operator==(const SampleMatrix& other) const {
- return fKind == other.fKind && fExpression == other.fExpression;
+ return fKind == other.fKind && fExpression == other.fExpression && fOwner == other.fOwner;
}
#ifdef SK_DEBUG
@@ -72,11 +75,20 @@ struct SampleMatrix {
}
#endif
+ // TODO(michaelludwig): fOwner and fBase are going away; owner is filled in automatically when
+ // a matrix-sampled FP is registered as a child.
GrFragmentProcessor* fOwner;
Kind fKind;
// The constant or uniform expression representing the matrix (will be the empty string when
// kind == kNone or kVariable)
String fExpression;
+ const GrFragmentProcessor* fBase = nullptr;
+
+private:
+ SampleMatrix(Kind kind, String expression)
+ : fOwner(nullptr)
+ , fKind(kind)
+ , fExpression(expression) {}
};
} // namespace
diff --git a/chromium/third_party/skia/src/sksl/SkSLSectionAndParameterHelper.cpp b/chromium/third_party/skia/src/sksl/SkSLSectionAndParameterHelper.cpp
index a8973868110..e05c5087883 100644
--- a/chromium/third_party/skia/src/sksl/SkSLSectionAndParameterHelper.cpp
+++ b/chromium/third_party/skia/src/sksl/SkSLSectionAndParameterHelper.cpp
@@ -199,9 +199,9 @@ bool SectionAndParameterHelper::hasCoordOverrides(const Statement& s, const Vari
}
case Statement::kFor_Kind: {
const ForStatement& f = (const ForStatement&) s;
- return this->hasCoordOverrides(*f.fInitializer, fp) ||
- this->hasCoordOverrides(*f.fTest, fp) ||
- this->hasCoordOverrides(*f.fNext, fp) ||
+ return (f.fInitializer ? this->hasCoordOverrides(*f.fInitializer, fp) : 0) ||
+ (f.fTest ? this->hasCoordOverrides(*f.fTest, fp) : 0) ||
+ (f.fNext ? this->hasCoordOverrides(*f.fNext, fp) : 0) ||
this->hasCoordOverrides(*f.fStatement, fp);
}
case Statement::kWhile_Kind: {
@@ -228,7 +228,6 @@ bool SectionAndParameterHelper::hasCoordOverrides(const Statement& s, const Vari
case Statement::kBreak_Kind:
case Statement::kContinue_Kind:
case Statement::kDiscard_Kind:
- case Statement::kGroup_Kind:
case Statement::kNop_Kind:
return false;
}
@@ -236,163 +235,4 @@ bool SectionAndParameterHelper::hasCoordOverrides(const Statement& s, const Vari
return false;
}
-SampleMatrix SectionAndParameterHelper::getMatrix(const Variable& fp) {
- SampleMatrix result;
- for (const auto& pe : fProgram) {
- result.merge(this->getMatrix(pe, fp));
- }
- return result;
-}
-
-SampleMatrix SectionAndParameterHelper::getMatrix(const ProgramElement& pe, const Variable& fp) {
- if (pe.fKind == ProgramElement::kFunction_Kind) {
- return this->getMatrix(*((const FunctionDefinition&) pe).fBody, fp);
- }
- return SampleMatrix();
-}
-
-SampleMatrix SectionAndParameterHelper::getMatrix(const Expression& e, const Variable& fp) {
- switch (e.fKind) {
- case Expression::kFunctionCall_Kind: {
- const FunctionCall& fc = (const FunctionCall&) e;
- const FunctionDeclaration& f = fc.fFunction;
- if (f.fBuiltin && f.fName == "sample" && fc.fArguments.size() >= 2 &&
- fc.fArguments.back()->fType == *fProgram.fContext->fFloat3x3_Type &&
- fc.fArguments[0]->fKind == Expression::kVariableReference_Kind &&
- &((VariableReference&) *fc.fArguments[0]).fVariable == &fp) {
- if (fc.fArguments.back()->isConstantOrUniform()) {
- return SampleMatrix(SampleMatrix::Kind::kConstantOrUniform, nullptr,
- fc.fArguments.back()->description());
- } else {
- return SampleMatrix(SampleMatrix::Kind::kVariable);
- }
- }
- SampleMatrix result;
- for (const auto& e : fc.fArguments) {
- result.merge(this->getMatrix(*e, fp));
- }
- return result;
- }
- case Expression::kConstructor_Kind: {
- SampleMatrix result;
- const Constructor& c = (const Constructor&) e;
- for (const auto& e : c.fArguments) {
- result.merge(this->getMatrix(*e, fp));
- }
- return result;
- }
- case Expression::kFieldAccess_Kind: {
- return this->getMatrix(*((const FieldAccess&) e).fBase, fp);
- }
- case Expression::kSwizzle_Kind:
- return this->getMatrix(*((const Swizzle&) e).fBase, fp);
- case Expression::kBinary_Kind: {
- const BinaryExpression& b = (const BinaryExpression&) e;
- return this->getMatrix(*b.fLeft, fp).merge(this->getMatrix(*b.fRight, fp));
- }
- case Expression::kIndex_Kind: {
- const IndexExpression& idx = (const IndexExpression&) e;
- return this->getMatrix(*idx.fBase, fp).merge(this->getMatrix(*idx.fIndex, fp));
- }
- case Expression::kPrefix_Kind:
- return this->getMatrix(*((const PrefixExpression&) e).fOperand, fp);
- case Expression::kPostfix_Kind:
- return this->getMatrix(*((const PostfixExpression&) e).fOperand, fp);
- case Expression::kTernary_Kind: {
- const TernaryExpression& t = (const TernaryExpression&) e;
- return this->getMatrix(*t.fTest, fp).merge(this->getMatrix(*t.fIfTrue, fp)).merge(
- this->getMatrix(*t.fIfFalse, fp));
- }
- case Expression::kVariableReference_Kind:
- return SampleMatrix();
- case Expression::kBoolLiteral_Kind:
- case Expression::kDefined_Kind:
- case Expression::kExternalFunctionCall_Kind:
- case Expression::kExternalValue_Kind:
- case Expression::kFloatLiteral_Kind:
- case Expression::kFunctionReference_Kind:
- case Expression::kIntLiteral_Kind:
- case Expression::kNullLiteral_Kind:
- case Expression::kSetting_Kind:
- case Expression::kTypeReference_Kind:
- return SampleMatrix();
- }
- SkASSERT(false);
- return SampleMatrix();
-}
-
-SampleMatrix SectionAndParameterHelper::getMatrix(const Statement& s, const Variable& fp) {
- switch (s.fKind) {
- case Statement::kBlock_Kind: {
- SampleMatrix result;
- for (const auto& child : ((const Block&) s).fStatements) {
- result.merge(this->getMatrix(*child, fp));
- }
- return result;
- }
- case Statement::kVarDeclaration_Kind: {
- const VarDeclaration& var = (const VarDeclaration&) s;
- if (var.fValue) {
- return this->getMatrix(*var.fValue, fp);
- }
- return SampleMatrix();
- }
- case Statement::kVarDeclarations_Kind: {
- const VarDeclarations& decls = *((const VarDeclarationsStatement&) s).fDeclaration;
- SampleMatrix result;
- for (const auto& stmt : decls.fVars) {
- result.merge(this->getMatrix(*stmt, fp));
- }
- return result;
- }
- case Statement::kExpression_Kind:
- return this->getMatrix(*((const ExpressionStatement&) s).fExpression, fp);
- case Statement::kReturn_Kind: {
- const ReturnStatement& r = (const ReturnStatement&) s;
- if (r.fExpression) {
- return this->getMatrix(*r.fExpression, fp);
- }
- return SampleMatrix();
- }
- case Statement::kIf_Kind: {
- const IfStatement& i = (const IfStatement&) s;
- return this->getMatrix(*i.fTest, fp).merge(this->getMatrix(*i.fIfTrue, fp)).merge(
- (i.fIfFalse ? this->getMatrix(*i.fIfFalse, fp) : SampleMatrix()));
- }
- case Statement::kFor_Kind: {
- const ForStatement& f = (const ForStatement&) s;
- return this->getMatrix(*f.fInitializer, fp).merge(
- this->getMatrix(*f.fTest, fp).merge(
- this->getMatrix(*f.fNext, fp).merge(
- this->getMatrix(*f.fStatement, fp))));
- }
- case Statement::kWhile_Kind: {
- const WhileStatement& w = (const WhileStatement&) s;
- return this->getMatrix(*w.fTest, fp).merge(this->getMatrix(*w.fStatement, fp));
- }
- case Statement::kDo_Kind: {
- const DoStatement& d = (const DoStatement&) s;
- return this->getMatrix(*d.fTest, fp).merge(this->getMatrix(*d.fStatement, fp));
- }
- case Statement::kSwitch_Kind: {
- SampleMatrix result;
- const SwitchStatement& sw = (const SwitchStatement&) s;
- for (const auto& c : sw.fCases) {
- for (const auto& st : c->fStatements) {
- result.merge(this->getMatrix(*st, fp));
- }
- }
- return result.merge(this->getMatrix(*sw.fValue, fp));
- }
- case Statement::kBreak_Kind:
- case Statement::kContinue_Kind:
- case Statement::kDiscard_Kind:
- case Statement::kGroup_Kind:
- case Statement::kNop_Kind:
- return SampleMatrix();
- }
- SkASSERT(false);
- return SampleMatrix();
-}
-
}
diff --git a/chromium/third_party/skia/src/sksl/SkSLSectionAndParameterHelper.h b/chromium/third_party/skia/src/sksl/SkSLSectionAndParameterHelper.h
index d52302aabde..3251024f2ea 100644
--- a/chromium/third_party/skia/src/sksl/SkSLSectionAndParameterHelper.h
+++ b/chromium/third_party/skia/src/sksl/SkSLSectionAndParameterHelper.h
@@ -9,7 +9,6 @@
#define SKSL_SECTIONANDPARAMETERHELPER
#include "src/sksl/SkSLErrorReporter.h"
-#include "src/sksl/SkSLSampleMatrix.h"
#include "src/sksl/ir/SkSLProgram.h"
#include "src/sksl/ir/SkSLSection.h"
#include "src/sksl/ir/SkSLVarDeclarations.h"
@@ -65,8 +64,6 @@ public:
bool hasCoordOverrides(const Variable& fp);
- SampleMatrix getMatrix(const Variable& fp);
-
static bool IsParameter(const Variable& var) {
return (var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
-1 == var.fModifiers.fLayout.fBuiltin;
@@ -118,12 +115,6 @@ private:
bool hasCoordOverrides(const ProgramElement& p, const Variable& fp);
- SampleMatrix getMatrix(const Statement& s, const Variable& fp);
-
- SampleMatrix getMatrix(const Expression& e, const Variable& fp);
-
- SampleMatrix getMatrix(const ProgramElement& p, const Variable& fp);
-
const Program& fProgram;
std::vector<const Variable*> fParameters;
std::unordered_map<String, std::vector<const Section*>> fSections;
diff --git a/chromium/third_party/skia/src/sksl/SkSLUtil.h b/chromium/third_party/skia/src/sksl/SkSLUtil.h
index 08f2842b624..552a99b444f 100644
--- a/chromium/third_party/skia/src/sksl/SkSLUtil.h
+++ b/chromium/third_party/skia/src/sksl/SkSLUtil.h
@@ -144,6 +144,13 @@ public:
return true;
}
+ bool canUseDoLoops() const {
+ // we define this to false in standalone so we don't use do loops while inlining in FP files
+ // (which would then, being baked in, end up being used even in contexts where do loops are
+ // not allowed)
+ return false;
+ }
+
const char* shaderDerivativeExtensionString() const {
return nullptr;
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLBinaryExpression.h b/chromium/third_party/skia/src/sksl/ir/SkSLBinaryExpression.h
index 9fc8683e954..f4a48e94df6 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLBinaryExpression.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLBinaryExpression.h
@@ -45,6 +45,10 @@ struct BinaryExpression : public Expression {
return fLeft->hasProperty(property) || fRight->hasProperty(property);
}
+ int nodeCount() const override {
+ return 1 + fLeft->nodeCount() + fRight->nodeCount();
+ }
+
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new BinaryExpression(fOffset, fLeft->clone(), fOperator,
fRight->clone(), fType));
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLBlock.h b/chromium/third_party/skia/src/sksl/ir/SkSLBlock.h
index 8a4449a01c6..b9fdf290724 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLBlock.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLBlock.h
@@ -18,10 +18,11 @@ namespace SkSL {
*/
struct Block : public Statement {
Block(int offset, std::vector<std::unique_ptr<Statement>> statements,
- const std::shared_ptr<SymbolTable> symbols = nullptr)
+ const std::shared_ptr<SymbolTable> symbols = nullptr, bool isScope = true)
: INHERITED(offset, kBlock_Kind)
, fSymbols(std::move(symbols))
- , fStatements(std::move(statements)) {}
+ , fStatements(std::move(statements))
+ , fIsScope(isScope) {}
bool isEmpty() const override {
for (const auto& s : fStatements) {
@@ -32,12 +33,21 @@ struct Block : public Statement {
return true;
}
+ int nodeCount() const override {
+ int result = 1;
+ for (const auto& s : fStatements) {
+ result += s->nodeCount();
+ }
+ return result;
+ }
+
std::unique_ptr<Statement> clone() const override {
std::vector<std::unique_ptr<Statement>> cloned;
for (const auto& s : fStatements) {
cloned.push_back(s->clone());
}
- return std::unique_ptr<Statement>(new Block(fOffset, std::move(cloned), fSymbols));
+ return std::unique_ptr<Statement>(new Block(fOffset, std::move(cloned), fSymbols,
+ fIsScope));
}
String description() const override {
@@ -54,6 +64,10 @@ struct Block : public Statement {
// because destroying statements can modify reference counts in symbols
const std::shared_ptr<SymbolTable> fSymbols;
std::vector<std::unique_ptr<Statement>> fStatements;
+ // if isScope is false, this is just a group of statements rather than an actual language-level
+ // block. This allows us to pass around multiple statements as if they were a single unit, with
+ // no semantic impact.
+ bool fIsScope;
typedef Statement INHERITED;
};
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLBoolLiteral.h b/chromium/third_party/skia/src/sksl/ir/SkSLBoolLiteral.h
index 74f48ad9b30..85dd8c5d0b7 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLBoolLiteral.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLBoolLiteral.h
@@ -38,6 +38,10 @@ struct BoolLiteral : public Expression {
return fValue == b.fValue;
}
+ int nodeCount() const override {
+ return 1;
+ }
+
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new BoolLiteral(fOffset, fValue, &fType));
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLBreakStatement.h b/chromium/third_party/skia/src/sksl/ir/SkSLBreakStatement.h
index ae0c1987e94..daedece915e 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLBreakStatement.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLBreakStatement.h
@@ -20,6 +20,10 @@ struct BreakStatement : public Statement {
BreakStatement(int offset)
: INHERITED(offset, kBreak_Kind) {}
+ int nodeCount() const override {
+ return 1;
+ }
+
std::unique_ptr<Statement> clone() const override {
return std::unique_ptr<Statement>(new BreakStatement(fOffset));
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLConstructor.h b/chromium/third_party/skia/src/sksl/ir/SkSLConstructor.h
index 524a6ad643c..cdd6f84a94b 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLConstructor.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLConstructor.h
@@ -59,6 +59,14 @@ struct Constructor : public Expression {
return false;
}
+ int nodeCount() const override {
+ int result = 1;
+ for (const auto& a : fArguments) {
+ result += a->nodeCount();
+ }
+ return result;
+ }
+
std::unique_ptr<Expression> clone() const override {
std::vector<std::unique_ptr<Expression>> cloned;
for (const auto& arg : fArguments) {
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLContinueStatement.h b/chromium/third_party/skia/src/sksl/ir/SkSLContinueStatement.h
index ecd9c3f4976..1e01ac8e0e7 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLContinueStatement.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLContinueStatement.h
@@ -20,6 +20,10 @@ struct ContinueStatement : public Statement {
ContinueStatement(int offset)
: INHERITED(offset, kContinue_Kind) {}
+ int nodeCount() const override {
+ return 1;
+ }
+
std::unique_ptr<Statement> clone() const override {
return std::unique_ptr<Statement>(new ContinueStatement(fOffset));
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLDiscardStatement.h b/chromium/third_party/skia/src/sksl/ir/SkSLDiscardStatement.h
index 40f625c178d..8cc7e3feec2 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLDiscardStatement.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLDiscardStatement.h
@@ -20,6 +20,10 @@ struct DiscardStatement : public Statement {
DiscardStatement(int offset)
: INHERITED(offset, kDiscard_Kind) {}
+ int nodeCount() const override {
+ return 1;
+ }
+
std::unique_ptr<Statement> clone() const override {
return std::unique_ptr<Statement>(new DiscardStatement(fOffset));
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLDoStatement.h b/chromium/third_party/skia/src/sksl/ir/SkSLDoStatement.h
index 5cab5c8bcd6..474aac7839f 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLDoStatement.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLDoStatement.h
@@ -23,6 +23,10 @@ struct DoStatement : public Statement {
, fStatement(std::move(statement))
, fTest(std::move(test)) {}
+ int nodeCount() const override {
+ return 1 + fStatement->nodeCount() + fTest->nodeCount();
+ }
+
std::unique_ptr<Statement> clone() const override {
return std::unique_ptr<Statement>(new DoStatement(fOffset, fStatement->clone(),
fTest->clone()));
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLExpressionStatement.h b/chromium/third_party/skia/src/sksl/ir/SkSLExpressionStatement.h
index 80a8d316c7e..1732bbbcdba 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLExpressionStatement.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLExpressionStatement.h
@@ -21,6 +21,10 @@ struct ExpressionStatement : public Statement {
: INHERITED(expression->fOffset, kExpression_Kind)
, fExpression(std::move(expression)) {}
+ int nodeCount() const override {
+ return 1 + fExpression->nodeCount();
+ }
+
std::unique_ptr<Statement> clone() const override {
return std::unique_ptr<Statement>(new ExpressionStatement(fExpression->clone()));
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLExternalFunctionCall.h b/chromium/third_party/skia/src/sksl/ir/SkSLExternalFunctionCall.h
index deb1f4d5cd6..bf70561a5dc 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLExternalFunctionCall.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLExternalFunctionCall.h
@@ -36,6 +36,14 @@ struct ExternalFunctionCall : public Expression {
return false;
}
+ int nodeCount() const override {
+ int result = 1;
+ for (const auto& a : fArguments) {
+ result += a->nodeCount();
+ }
+ return result;
+ }
+
std::unique_ptr<Expression> clone() const override {
std::vector<std::unique_ptr<Expression>> cloned;
for (const auto& arg : fArguments) {
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLExternalValueReference.h b/chromium/third_party/skia/src/sksl/ir/SkSLExternalValueReference.h
index aa0ec181ed5..868c6c9baef 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLExternalValueReference.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLExternalValueReference.h
@@ -25,6 +25,10 @@ struct ExternalValueReference : public Expression {
return property == Property::kSideEffects;
}
+ int nodeCount() const override {
+ return 1;
+ }
+
String description() const override {
return String(fValue->fName);
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLFieldAccess.h b/chromium/third_party/skia/src/sksl/ir/SkSLFieldAccess.h
index 59f4c166a17..6cba5663404 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLFieldAccess.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLFieldAccess.h
@@ -35,6 +35,10 @@ struct FieldAccess : public Expression {
return fBase->hasProperty(property);
}
+ int nodeCount() const override {
+ return 1 + fBase->nodeCount();
+ }
+
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new FieldAccess(fBase->clone(), fFieldIndex,
fOwnerKind));
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLFloatLiteral.h b/chromium/third_party/skia/src/sksl/ir/SkSLFloatLiteral.h
index 79f5dcf7010..9d817719946 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLFloatLiteral.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLFloatLiteral.h
@@ -53,6 +53,10 @@ struct FloatLiteral : public Expression {
return fValue;
}
+ int nodeCount() const override {
+ return 1;
+ }
+
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new FloatLiteral(fOffset, fValue, &fType));
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLForStatement.h b/chromium/third_party/skia/src/sksl/ir/SkSLForStatement.h
index 4906e192a69..29c61bffa7b 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLForStatement.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLForStatement.h
@@ -28,16 +28,36 @@ struct ForStatement : public Statement {
, fNext(std::move(next))
, fStatement(std::move(statement)) {}
+ int nodeCount() const override {
+ int result = 1;
+ if (fInitializer) {
+ result += fInitializer->nodeCount();
+ }
+ if (fTest) {
+ result += fTest->nodeCount();
+ }
+ if (fNext) {
+ result += fNext->nodeCount();
+ }
+ result += fStatement->nodeCount();
+ return result;
+ }
+
std::unique_ptr<Statement> clone() const override {
- return std::unique_ptr<Statement>(new ForStatement(fOffset, fInitializer->clone(),
- fTest->clone(), fNext->clone(),
- fStatement->clone(), fSymbols));
+ return std::unique_ptr<Statement>(new ForStatement(fOffset,
+ fInitializer ? fInitializer->clone() : nullptr,
+ fTest ? fTest->clone() : nullptr,
+ fNext ? fNext->clone() : nullptr,
+ fStatement->clone(),
+ fSymbols));
}
String description() const override {
String result("for (");
if (fInitializer) {
result += fInitializer->description();
+ } else {
+ result += ";";
}
result += " ";
if (fTest) {
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLFunctionCall.h b/chromium/third_party/skia/src/sksl/ir/SkSLFunctionCall.h
index 296aa0b3efe..7f7e7c5f373 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLFunctionCall.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLFunctionCall.h
@@ -21,7 +21,13 @@ struct FunctionCall : public Expression {
std::vector<std::unique_ptr<Expression>> arguments)
: INHERITED(offset, kFunctionCall_Kind, type)
, fFunction(std::move(function))
- , fArguments(std::move(arguments)) {}
+ , fArguments(std::move(arguments)) {
+ ++fFunction.fCallCount;
+ }
+
+ ~FunctionCall() override {
+ --fFunction.fCallCount;
+ }
bool hasProperty(Property property) const override {
if (property == Property::kSideEffects && (fFunction.fModifiers.fFlags &
@@ -36,6 +42,14 @@ struct FunctionCall : public Expression {
return false;
}
+ int nodeCount() const override {
+ int result = 1;
+ for (const auto& a : fArguments) {
+ result += a->nodeCount();
+ }
+ return result;
+ }
+
std::unique_ptr<Expression> clone() const override {
std::vector<std::unique_ptr<Expression>> cloned;
for (const auto& arg : fArguments) {
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLFunctionDeclaration.h b/chromium/third_party/skia/src/sksl/ir/SkSLFunctionDeclaration.h
index dffb9a3c981..8436460c24b 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLFunctionDeclaration.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLFunctionDeclaration.h
@@ -15,8 +15,12 @@
#include "src/sksl/ir/SkSLType.h"
#include "src/sksl/ir/SkSLVariable.h"
+#include <atomic>
+
namespace SkSL {
+struct FunctionDefinition;
+
/**
* A function declaration (not a definition -- does not contain a body).
*/
@@ -24,7 +28,7 @@ struct FunctionDeclaration : public Symbol {
FunctionDeclaration(int offset, Modifiers modifiers, StringFragment name,
std::vector<const Variable*> parameters, const Type& returnType)
: INHERITED(offset, kFunctionDeclaration_Kind, std::move(name))
- , fDefined(false)
+ , fDefinition(nullptr)
, fBuiltin(false)
, fModifiers(modifiers)
, fParameters(std::move(parameters))
@@ -36,7 +40,7 @@ struct FunctionDeclaration : public Symbol {
for (auto p : fParameters) {
result += separator;
separator = ", ";
- result += p->fName;
+ result += p->fType.displayName();
}
result += ")";
return result;
@@ -107,11 +111,12 @@ struct FunctionDeclaration : public Symbol {
return true;
}
- mutable bool fDefined;
+ mutable FunctionDefinition* fDefinition;
bool fBuiltin;
Modifiers fModifiers;
const std::vector<const Variable*> fParameters;
const Type& fReturnType;
+ mutable std::atomic<int> fCallCount = 0;
typedef Symbol INHERITED;
};
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLFunctionDefinition.h b/chromium/third_party/skia/src/sksl/ir/SkSLFunctionDefinition.h
index 511a0f8c200..4bcadcf57d1 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLFunctionDefinition.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLFunctionDefinition.h
@@ -26,6 +26,11 @@ struct FunctionDefinition : public ProgramElement {
, fDeclaration(declaration)
, fBody(std::move(body)) {}
+ bool canBeInlined() const {
+ static const int INLINE_THRESHOLD = 50; // chosen arbitrarily, feel free to adjust
+ return fBody->nodeCount() < INLINE_THRESHOLD;
+ }
+
std::unique_ptr<ProgramElement> clone() const override {
return std::unique_ptr<ProgramElement>(new FunctionDefinition(fOffset, fDeclaration,
fBody->clone()));
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLIRNode.h b/chromium/third_party/skia/src/sksl/ir/SkSLIRNode.h
index ca9ea999989..cace825fe74 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLIRNode.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLIRNode.h
@@ -23,6 +23,12 @@ struct IRNode {
virtual ~IRNode() {}
+ virtual int nodeCount() const {
+ SkASSERT(false);
+ return 1;
+ }
+
+
virtual String description() const = 0;
// character offset of this element within the program being compiled, for error reporting
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLIfStatement.h b/chromium/third_party/skia/src/sksl/ir/SkSLIfStatement.h
index 5d0a22b647a..6af6740b0f2 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLIfStatement.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLIfStatement.h
@@ -25,6 +25,11 @@ struct IfStatement : public Statement {
, fIfTrue(std::move(ifTrue))
, fIfFalse(std::move(ifFalse)) {}
+ int nodeCount() const override {
+ return 1 + fTest->nodeCount() + fIfTrue->nodeCount() +
+ (fIfFalse ? fIfFalse->nodeCount() : 0);
+ }
+
std::unique_ptr<Statement> clone() const override {
return std::unique_ptr<Statement>(new IfStatement(fOffset, fIsStatic, fTest->clone(),
fIfTrue->clone(), fIfFalse ? fIfFalse->clone() : nullptr));
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLIndexExpression.h b/chromium/third_party/skia/src/sksl/ir/SkSLIndexExpression.h
index 2b3a3a93d5b..5e7a011937f 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLIndexExpression.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLIndexExpression.h
@@ -33,14 +33,6 @@ static const Type& index_type(const Context& context, const Type& type) {
case 4: return *context.fHalf4_Type;
default: SkASSERT(false);
}
- } else {
- SkASSERT(type.componentType() == *context.fDouble_Type);
- switch (type.rows()) {
- case 2: return *context.fDouble2_Type;
- case 3: return *context.fDouble3_Type;
- case 4: return *context.fDouble4_Type;
- default: SkASSERT(false);
- }
}
}
return type.componentType();
@@ -62,6 +54,10 @@ struct IndexExpression : public Expression {
return fBase->hasProperty(property) || fIndex->hasProperty(property);
}
+ int nodeCount() const override {
+ return 1 + fBase->nodeCount() + fIndex->nodeCount();
+ }
+
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new IndexExpression(fBase->clone(), fIndex->clone(),
&fType));
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLIntLiteral.h b/chromium/third_party/skia/src/sksl/ir/SkSLIntLiteral.h
index 6c686e135ba..4977fbf0b8a 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLIntLiteral.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLIntLiteral.h
@@ -56,6 +56,10 @@ struct IntLiteral : public Expression {
return fValue;
}
+ int nodeCount() const override {
+ return 1;
+ }
+
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new IntLiteral(fOffset, fValue, &fType));
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLNop.h b/chromium/third_party/skia/src/sksl/ir/SkSLNop.h
index 2ead371f876..787060d8b45 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLNop.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLNop.h
@@ -28,6 +28,10 @@ struct Nop : public Statement {
return String(";");
}
+ int nodeCount() const override {
+ return 0;
+ }
+
std::unique_ptr<Statement> clone() const override {
return std::unique_ptr<Statement>(new Nop());
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLNullLiteral.h b/chromium/third_party/skia/src/sksl/ir/SkSLNullLiteral.h
index d04fc5cb209..0d04b77e227 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLNullLiteral.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLNullLiteral.h
@@ -39,6 +39,10 @@ struct NullLiteral : public Expression {
return true;
}
+ int nodeCount() const override {
+ return 1;
+ }
+
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new NullLiteral(fOffset, fType));
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLPostfixExpression.h b/chromium/third_party/skia/src/sksl/ir/SkSLPostfixExpression.h
index d95f687e378..c6f89eb2d61 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLPostfixExpression.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLPostfixExpression.h
@@ -30,6 +30,10 @@ struct PostfixExpression : public Expression {
return fOperand->hasProperty(property);
}
+ int nodeCount() const override {
+ return 1 + fOperand->nodeCount();
+ }
+
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new PostfixExpression(fOperand->clone(), fOperator));
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLPrefixExpression.h b/chromium/third_party/skia/src/sksl/ir/SkSLPrefixExpression.h
index 76f144b7fb8..ab0363ec661 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLPrefixExpression.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLPrefixExpression.h
@@ -64,6 +64,10 @@ struct PrefixExpression : public Expression {
return -fOperand->getMatComponent(col, row);
}
+ int nodeCount() const override {
+ return 1 + fOperand->nodeCount();
+ }
+
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new PrefixExpression(fOperator, fOperand->clone()));
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLProgram.h b/chromium/third_party/skia/src/sksl/ir/SkSLProgram.h
index c7694b5f917..cf16d1fd460 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLProgram.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLProgram.h
@@ -53,7 +53,7 @@ struct Program {
Value(float f)
: fKind(kFloat_Kind)
- , fValue(f) {}
+ , fValueF(f) {}
std::unique_ptr<Expression> literal(const Context& context, int offset) const {
switch (fKind) {
@@ -67,8 +67,8 @@ struct Program {
fValue));
case Program::Settings::Value::kFloat_Kind:
return std::unique_ptr<Expression>(new FloatLiteral(context,
- offset,
- fValue));
+ offset,
+ fValueF));
default:
SkASSERT(false);
return nullptr;
@@ -81,7 +81,10 @@ struct Program {
kFloat_Kind,
} fKind;
- int fValue;
+ union {
+ int fValue; // for kBool_Kind and kInt_Kind
+ float fValueF; // for kFloat_Kind
+ };
};
#if defined(SKSL_STANDALONE) || !SK_SUPPORT_GPU
@@ -92,6 +95,9 @@ struct Program {
// if false, sk_FragCoord is exactly the same as gl_FragCoord. If true, the y coordinate
// must be flipped.
bool fFlipY = false;
+ // if false, sk_FragCoord is exactly the same as gl_FragCoord. If true, the w coordinate
+ // must be inversed.
+ bool fInverseW = false;
// If true the destination fragment color is read sk_FragColor. It must be declared inout.
bool fFragColorIsInOut = false;
// if true, Setting objects (e.g. sk_Caps.fbFetchSupport) should be replaced with their
@@ -108,6 +114,9 @@ struct Program {
// binding and set number of the uniform buffer.
int fRTHeightBinding = -1;
int fRTHeightSet = -1;
+ // If true, remove any uncalled functions other than main(). Note that a function which
+ // starts out being used may end up being uncalled after optimization.
+ bool fRemoveDeadFunctions = true;
std::unordered_map<String, Value> fArgs;
};
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLReturnStatement.h b/chromium/third_party/skia/src/sksl/ir/SkSLReturnStatement.h
index e61fa36c742..82b46781061 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLReturnStatement.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLReturnStatement.h
@@ -24,6 +24,10 @@ struct ReturnStatement : public Statement {
: INHERITED(expression->fOffset, kReturn_Kind)
, fExpression(std::move(expression)) {}
+ int nodeCount() const override {
+ return 1 + fExpression->nodeCount();
+ }
+
std::unique_ptr<Statement> clone() const override {
if (fExpression) {
return std::unique_ptr<Statement>(new ReturnStatement(fExpression->clone()));
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLSetting.h b/chromium/third_party/skia/src/sksl/ir/SkSLSetting.h
index a47b42be914..9a69802b575 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLSetting.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLSetting.h
@@ -28,6 +28,10 @@ struct Setting : public Expression {
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
const DefinitionMap& definitions) override;
+ int nodeCount() const override {
+ return 1;
+ }
+
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new Setting(fOffset, fName, fValue->clone()));
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLStatement.h b/chromium/third_party/skia/src/sksl/ir/SkSLStatement.h
index ed8d33b1422..2260cdd5a4d 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLStatement.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLStatement.h
@@ -25,7 +25,6 @@ struct Statement : public IRNode {
kDo_Kind,
kExpression_Kind,
kFor_Kind,
- kGroup_Kind,
kIf_Kind,
kNop_Kind,
kReturn_Kind,
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLSwitchCase.h b/chromium/third_party/skia/src/sksl/ir/SkSLSwitchCase.h
index b1ddb012ec4..dcfe9564268 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLSwitchCase.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLSwitchCase.h
@@ -23,6 +23,17 @@ struct SwitchCase : public Statement {
, fValue(std::move(value))
, fStatements(std::move(statements)) {}
+ int nodeCount() const override {
+ int result = 1;
+ if (fValue) {
+ result += fValue->nodeCount();
+ }
+ for (const auto& s : fStatements) {
+ result += s->nodeCount();
+ }
+ return result;
+ }
+
std::unique_ptr<Statement> clone() const override {
std::vector<std::unique_ptr<Statement>> cloned;
for (const auto& s : fStatements) {
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLSwitchStatement.h b/chromium/third_party/skia/src/sksl/ir/SkSLSwitchStatement.h
index 0777c5c5c61..a85420a6959 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLSwitchStatement.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLSwitchStatement.h
@@ -28,6 +28,14 @@ struct SwitchStatement : public Statement {
, fSymbols(std::move(symbols))
, fCases(std::move(cases)) {}
+ int nodeCount() const override {
+ int result = 1 + fValue->nodeCount();
+ for (const auto& c : fCases) {
+ result += c->nodeCount();
+ }
+ return result;
+ }
+
std::unique_ptr<Statement> clone() const override {
std::vector<std::unique_ptr<SwitchCase>> cloned;
for (const auto& s : fCases) {
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLSwizzle.h b/chromium/third_party/skia/src/sksl/ir/SkSLSwizzle.h
index 3428f287fa2..040af8491aa 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLSwizzle.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLSwizzle.h
@@ -44,12 +44,6 @@ static const Type& get_type(const Context& context, Expression& value, size_t co
case 3: return *context.fHalf3_Type;
case 4: return *context.fHalf4_Type;
}
- } else if (base == *context.fDouble_Type) {
- switch (count) {
- case 2: return *context.fDouble2_Type;
- case 3: return *context.fDouble3_Type;
- case 4: return *context.fDouble4_Type;
- }
} else if (base == *context.fInt_Type) {
switch (count) {
case 2: return *context.fInt2_Type;
@@ -136,6 +130,10 @@ struct Swizzle : public Expression {
return fBase->hasProperty(property);
}
+ int nodeCount() const override {
+ return 1 + fBase->nodeCount();
+ }
+
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new Swizzle(fType, fBase->clone(), fComponents));
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLSymbol.h b/chromium/third_party/skia/src/sksl/ir/SkSLSymbol.h
index 4ee4d3d90dd..df606b88c47 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLSymbol.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLSymbol.h
@@ -30,7 +30,7 @@ struct Symbol : public IRNode {
, fKind(kind)
, fName(name) {}
- virtual ~Symbol() {}
+ virtual ~Symbol() override {}
Kind fKind;
StringFragment fName;
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLSymbolTable.cpp b/chromium/third_party/skia/src/sksl/ir/SkSLSymbolTable.cpp
index ed2cb4d565b..b0a2a56e08d 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLSymbolTable.cpp
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLSymbolTable.cpp
@@ -72,6 +72,12 @@ IRNode* SymbolTable::takeOwnership(std::unique_ptr<IRNode> n) {
return result;
}
+String* SymbolTable::takeOwnership(std::unique_ptr<String> n) {
+ String* result = n.get();
+ fOwnedStrings.push_back(std::move(n));
+ return result;
+}
+
void SymbolTable::add(StringFragment name, std::unique_ptr<Symbol> symbol) {
this->addWithoutOwnership(name, symbol.get());
this->takeOwnership(std::move(symbol));
@@ -114,9 +120,7 @@ void SymbolTable::markAllFunctionsBuiltin() {
break;
case Symbol::kUnresolvedFunction_Kind:
for (auto& f : ((UnresolvedFunction&) *pair.second).fFunctions) {
- if (!((FunctionDeclaration*)f)->fDefined) {
- ((FunctionDeclaration*)f)->fBuiltin = true;
- }
+ ((FunctionDeclaration*)f)->fBuiltin = true;
}
break;
default:
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLSymbolTable.h b/chromium/third_party/skia/src/sksl/ir/SkSLSymbolTable.h
index 6969ba5e08c..a3f89e2288f 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLSymbolTable.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLSymbolTable.h
@@ -41,6 +41,8 @@ public:
IRNode* takeOwnership(std::unique_ptr<IRNode> n);
+ String* takeOwnership(std::unique_ptr<String> n);
+
void markAllFunctionsBuiltin();
std::unordered_map<StringFragment, const Symbol*>::iterator begin();
@@ -56,6 +58,8 @@ private:
std::vector<std::unique_ptr<IRNode>> fOwnedNodes;
+ std::vector<std::unique_ptr<String>> fOwnedStrings;
+
std::unordered_map<StringFragment, const Symbol*> fSymbols;
ErrorReporter& fErrorReporter;
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLTernaryExpression.h b/chromium/third_party/skia/src/sksl/ir/SkSLTernaryExpression.h
index 80dcb8fada6..cb4c0047209 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLTernaryExpression.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLTernaryExpression.h
@@ -36,6 +36,10 @@ struct TernaryExpression : public Expression {
fIfFalse->isConstantOrUniform();
}
+ int nodeCount() const override {
+ return 1 + fTest->nodeCount() + fIfTrue->nodeCount() + fIfFalse->nodeCount();
+ }
+
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new TernaryExpression(fOffset, fTest->clone(),
fIfTrue->clone(),
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLType.cpp b/chromium/third_party/skia/src/sksl/ir/SkSLType.cpp
index cd18e8ed910..edff101dc9d 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLType.cpp
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLType.cpp
@@ -116,38 +116,6 @@ const Type& Type::toCompound(const Context& context, int columns, int rows) cons
}
default: ABORT("unsupported row count (%d)", rows);
}
- } else if (*this == *context.fDouble_Type) {
- switch (rows) {
- case 1:
- switch (columns) {
- case 2: return *context.fDouble2_Type;
- case 3: return *context.fDouble3_Type;
- case 4: return *context.fDouble4_Type;
- default: ABORT("unsupported vector column count (%d)", columns);
- }
- case 2:
- switch (columns) {
- case 2: return *context.fDouble2x2_Type;
- case 3: return *context.fDouble3x2_Type;
- case 4: return *context.fDouble4x2_Type;
- default: ABORT("unsupported matrix column count (%d)", columns);
- }
- case 3:
- switch (columns) {
- case 2: return *context.fDouble2x3_Type;
- case 3: return *context.fDouble3x3_Type;
- case 4: return *context.fDouble4x3_Type;
- default: ABORT("unsupported matrix column count (%d)", columns);
- }
- case 4:
- switch (columns) {
- case 2: return *context.fDouble2x4_Type;
- case 3: return *context.fDouble3x4_Type;
- case 4: return *context.fDouble4x4_Type;
- default: ABORT("unsupported matrix column count (%d)", columns);
- }
- default: ABORT("unsupported row count (%d)", rows);
- }
} else if (*this == *context.fInt_Type || *this == *context.fIntLiteral_Type) {
switch (rows) {
case 1:
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLType.h b/chromium/third_party/skia/src/sksl/ir/SkSLType.h
index 37303cbee9c..e8c6a653cf4 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLType.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLType.h
@@ -269,7 +269,7 @@ public:
}
/**
- * Returns true if this is a floating-point scalar type (float, half, or double).
+ * Returns true if this is a floating-point scalar type (float or half).
*/
bool isFloat() const {
return fNumberKind == kFloat_NumberKind;
@@ -297,7 +297,7 @@ public:
}
/**
- * Returns the "priority" of a number type, in order of double > float > half > int > short.
+ * Returns the "priority" of a number type, in order of float > half > int > short.
* When operating on two number types, the result is the higher-priority type.
*/
int priority() const {
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLVarDeclarations.h b/chromium/third_party/skia/src/sksl/ir/SkSLVarDeclarations.h
index 82dbd8616d8..86aafdb3db3 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLVarDeclarations.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLVarDeclarations.h
@@ -29,6 +29,19 @@ struct VarDeclaration : public Statement {
, fSizes(std::move(sizes))
, fValue(std::move(value)) {}
+ int nodeCount() const override {
+ int result = 1;
+ for (const auto& s : fSizes) {
+ if (s) {
+ result += s->nodeCount();
+ }
+ }
+ if (fValue) {
+ result += fValue->nodeCount();
+ }
+ return result;
+ }
+
std::unique_ptr<Statement> clone() const override {
std::vector<std::unique_ptr<Expression>> sizesClone;
for (const auto& s : fSizes) {
@@ -77,6 +90,14 @@ struct VarDeclarations : public ProgramElement {
}
}
+ int nodeCount() const override {
+ int result = 1;
+ for (const auto& v : fVars) {
+ result += v->nodeCount();
+ }
+ return result;
+ }
+
std::unique_ptr<ProgramElement> clone() const override {
std::vector<std::unique_ptr<VarDeclaration>> cloned;
for (const auto& v : fVars) {
@@ -91,8 +112,15 @@ struct VarDeclarations : public ProgramElement {
if (!fVars.size()) {
return String();
}
- String result = ((VarDeclaration&) *fVars[0]).fVar->fModifiers.description() +
- fBaseType.description() + " ";
+ String result;
+ for (const auto& var : fVars) {
+ if (var->fKind != Statement::kNop_Kind) {
+ SkASSERT(var->fKind == Statement::kVarDeclaration_Kind);
+ result = ((const VarDeclaration&) *var).fVar->fModifiers.description();
+ break;
+ }
+ }
+ result += fBaseType.description() + " ";
String separator;
for (const auto& var : fVars) {
result += separator;
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLVarDeclarationsStatement.h b/chromium/third_party/skia/src/sksl/ir/SkSLVarDeclarationsStatement.h
index 465b6919361..eb7880f310c 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLVarDeclarationsStatement.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLVarDeclarationsStatement.h
@@ -30,6 +30,10 @@ struct VarDeclarationsStatement : public Statement {
return true;
}
+ int nodeCount() const override {
+ return 1 + fDeclaration->nodeCount();
+ }
+
std::unique_ptr<Statement> clone() const override {
std::unique_ptr<VarDeclarations> cloned((VarDeclarations*) fDeclaration->clone().release());
return std::unique_ptr<Statement>(new VarDeclarationsStatement(std::move(cloned)));
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLVariableReference.h b/chromium/third_party/skia/src/sksl/ir/SkSLVariableReference.h
index 5d962b9ff25..c6751441ddb 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLVariableReference.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLVariableReference.h
@@ -62,6 +62,10 @@ struct VariableReference : public Expression {
return (fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) != 0;
}
+ int nodeCount() const override {
+ return 1;
+ }
+
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new VariableReference(fOffset, fVariable, fRefKind));
}
diff --git a/chromium/third_party/skia/src/sksl/ir/SkSLWhileStatement.h b/chromium/third_party/skia/src/sksl/ir/SkSLWhileStatement.h
index 8e311a090a4..0782a018994 100644
--- a/chromium/third_party/skia/src/sksl/ir/SkSLWhileStatement.h
+++ b/chromium/third_party/skia/src/sksl/ir/SkSLWhileStatement.h
@@ -23,6 +23,10 @@ struct WhileStatement : public Statement {
, fTest(std::move(test))
, fStatement(std::move(statement)) {}
+ int nodeCount() const override {
+ return 1 + fTest->nodeCount() + fStatement->nodeCount();
+ }
+
std::unique_ptr<Statement> clone() const override {
return std::unique_ptr<Statement>(new WhileStatement(fOffset, fTest->clone(),
fStatement->clone()));
diff --git a/chromium/third_party/skia/src/sksl/lex/RegexParser.cpp b/chromium/third_party/skia/src/sksl/lex/RegexParser.cpp
index 9b5445e1a3d..be7d09a1063 100644
--- a/chromium/third_party/skia/src/sksl/lex/RegexParser.cpp
+++ b/chromium/third_party/skia/src/sksl/lex/RegexParser.cpp
@@ -63,8 +63,8 @@ void RegexParser::sequence() {
this->quantifiedTerm();
for (;;) {
switch (this->peek()) {
- case END: // fall through
- case '|': // fall through
+ case END: [[fallthrough]];
+ case '|': [[fallthrough]];
case ')': return;
default:
this->sequence();
diff --git a/chromium/third_party/skia/src/sksl/sksl_blend.inc b/chromium/third_party/skia/src/sksl/sksl_blend.inc
index 9094aedfb0d..ab6dcb8922d 100644
--- a/chromium/third_party/skia/src/sksl/sksl_blend.inc
+++ b/chromium/third_party/skia/src/sksl/sksl_blend.inc
@@ -69,8 +69,9 @@ half4 blend_lighten(half4 src, half4 dst) {
half _guarded_divide(half n, half d) {
@if (sk_Caps.mustGuardDivisionEvenAfterExplicitZeroCheck) {
return n/(d + 0.00000001);
+ } else {
+ return n/d;
}
- return n/d;
}
half _color_dodge_component(half sc, half sa, half dc, half da) {
@@ -298,4 +299,8 @@ half4 blend(SkBlendMode mode, half4 src, half4 dst) {
}
return half4(0); // Avoids "'blend' can exit without returning a value."
}
+
+// The max() guards against division by zero when the incoming color is transparent black
+half4 unpremul(half4 color) { return half4(color.rgb / max(color.a, 0.0001), color.a); }
+float4 unpremul_float(float4 color) { return float4(color.rgb / max(color.a, 0.0001), color.a); }
)SKSL"
diff --git a/chromium/third_party/skia/src/sksl/sksl_enums.inc b/chromium/third_party/skia/src/sksl/sksl_enums.inc
index eb60b3b0c5b..b29daf93da5 100644
--- a/chromium/third_party/skia/src/sksl/sksl_enums.inc
+++ b/chromium/third_party/skia/src/sksl/sksl_enums.inc
@@ -13,17 +13,15 @@ R"(/*
/**
* We have coverage effects that clip rendering to the edge of some geometric primitive.
* This enum specifies how that clipping is performed. Not all factories that take a
- * GrProcessorEdgeType will succeed with all values and it is up to the caller to check for
- * a NULL return.
+ * GrProcessorEdgeType will succeed with all values and it is up to the caller to verify success.
*/
enum class GrClipEdgeType {
kFillBW,
kFillAA,
kInverseFillBW,
kInverseFillAA,
- kHairlineAA,
- kLast = kHairlineAA
+ kLast = kInverseFillAA
};
enum class PMConversion {
diff --git a/chromium/third_party/skia/src/sksl/sksl_gpu.inc b/chromium/third_party/skia/src/sksl/sksl_gpu.inc
index 1bacef0d091..6122e48dd22 100644
--- a/chromium/third_party/skia/src/sksl/sksl_gpu.inc
+++ b/chromium/third_party/skia/src/sksl/sksl_gpu.inc
@@ -104,15 +104,12 @@ $genType smoothstep(float edge0, float edge1, $genType x);
$genHType smoothstep($genHType edge0, $genHType edge1, $genHType x);
$genHType smoothstep(half edge0, half edge1, $genHType x);
$genBType isnan($genType x);
-$genBType isnan($genDType x);
$genBType isinf($genType x);
-$genBType isinf($genDType x);
$genIType floatBitsToInt($genType value);
$genType intBitsTofloat($genIType value);
$genType uintBitsTofloat($genUType value);
$genType fma($genType a, $genType b, $genType c);
$genHType fma($genHType a, $genHType b, $genHType c);
-$genDType fma($genDType a, $genDType b, $genDType c);
sk_has_side_effects $genType frexp($genType x, out $genIType exp);
$genType ldexp($genType x, in $genIType exp);
uint packUnorm2x16(float2 v);
@@ -123,34 +120,25 @@ float2 unpackUnorm2x16(uint p);
float2 unpackSnorm2x16(uint p);
float4 unpackUnorm4x8(uint p);
float4 unpackSnorm4x8(uint p);
-uint2 unpackDouble2x32(double v);
uint packHalf2x16(float2 v);
float2 unpackHalf2x16(uint v);
float length($genType x);
half length($genHType x);
-double length($genDType x);
float distance($genType p0, $genType p1);
half distance($genHType p0, $genHType p1);
-double distance($genDType p0, $genDType p1);
float dot($genType x, $genType y);
half dot($genHType x, $genHType y);
-double dot($genDType x, $genDType y);
float3 cross(float3 x, float3 y);
half3 cross(half3 x, half3 y);
-double3 cross(double3 x, double3 y);
$genType normalize($genType x);
$genHType normalize($genHType x);
-$genDType normalize($genDType x);
float4 ftransform();
$genType faceforward($genType N, $genType I, $genType Nref);
$genHType faceforward($genHType N, $genHType I, $genHType Nref);
-$genDType faceforward($genDType N, $genDType I, $genDType Nref);
$genType reflect($genType I, $genType N);
$genHType reflect($genHType I, $genHType N);
-$genDType reflect($genDType I, $genDType N);
$genType refract($genType I, $genType N, float eta);
$genHType refract($genHType I, $genHType N, float eta);
-$genDType refract($genDType I, $genDType N, float eta);
$mat matrixCompMult($mat x, $mat y);
float2x2 outerProduct(float2 c, float2 r);
float3x3 outerProduct(float3 c, float3 r);
@@ -202,35 +190,30 @@ half3x3 inverse(half3x3 m);
half4x4 inverse(half4x4 m);
$bvec lessThan($vec x, $vec y);
$bvec lessThan($hvec x, $hvec y);
-$bvec lessThan($dvec x, $dvec y);
$bvec lessThan($ivec x, $ivec y);
$bvec lessThan($svec x, $svec y);
$bvec lessThan($usvec x, $usvec y);
$bvec lessThan($uvec x, $uvec y);
$bvec lessThanEqual($vec x, $vec y);
$bvec lessThanEqual($hvec x, $hvec y);
-$bvec lessThanEqual($dvec x, $dvec y);
$bvec lessThanEqual($ivec x, $ivec y);
$bvec lessThanEqual($uvec x, $uvec y);
$bvec lessThanEqual($svec x, $svec y);
$bvec lessThanEqual($usvec x, $usvec y);
$bvec greaterThan($vec x, $vec y);
$bvec greaterThan($hvec x, $hvec y);
-$bvec greaterThan($dvec x, $dvec y);
$bvec greaterThan($ivec x, $ivec y);
$bvec greaterThan($uvec x, $uvec y);
$bvec greaterThan($svec x, $svec y);
$bvec greaterThan($usvec x, $usvec y);
$bvec greaterThanEqual($vec x, $vec y);
$bvec greaterThanEqual($hvec x, $hvec y);
-$bvec greaterThanEqual($dvec x, $dvec y);
$bvec greaterThanEqual($ivec x, $ivec y);
$bvec greaterThanEqual($uvec x, $uvec y);
$bvec greaterThanEqual($svec x, $svec y);
$bvec greaterThanEqual($usvec x, $usvec y);
$bvec equal($vec x, $vec y);
$bvec equal($hvec x, $hvec y);
-$bvec equal($dvec x, $dvec y);
$bvec equal($ivec x, $ivec y);
$bvec equal($uvec x, $uvec y);
$bvec equal($svec x, $svec y);
@@ -238,7 +221,6 @@ $bvec equal($usvec x, $usvec y);
$bvec equal($bvec x, $bvec y);
$bvec notEqual($vec x, $vec y);
$bvec notEqual($hvec x, $hvec y);
-$bvec notEqual($dvec x, $dvec y);
$bvec notEqual($ivec x, $ivec y);
$bvec notEqual($uvec x, $uvec y);
$bvec notEqual($svec x, $svec y);
diff --git a/chromium/third_party/skia/src/sksl/sksl_interp.inc b/chromium/third_party/skia/src/sksl/sksl_interp.inc
index 894df0883df..c6644ca39d9 100644
--- a/chromium/third_party/skia/src/sksl/sksl_interp.inc
+++ b/chromium/third_party/skia/src/sksl/sksl_interp.inc
@@ -16,6 +16,8 @@ half3x3 inverse(half3x3 m);
half4x4 inverse(half4x4 m);
float length($genType x);
half length($genHType x);
+$genType normalize($genType x);
+$genHType normalize($genHType x);
$genType pow($genType x, $genType y);
$genHType pow($genHType x, $genHType y);
$genType sin($genType x);
@@ -101,10 +103,6 @@ float distance(float2 a, float2 b) { return length(a - b); }
float distance(float3 a, float3 b) { return length(a - b); }
float distance(float4 a, float4 b) { return length(a - b); }
-float2 normalize(float2 v) { return v / length(v); }
-float3 normalize(float3 v) { return v / length(v); }
-float4 normalize(float4 v) { return v / length(v); }
-
float3 cross(float3 a, float3 b) {
return float3(a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
diff --git a/chromium/third_party/skia/src/sksl/sksl_pipeline.inc b/chromium/third_party/skia/src/sksl/sksl_pipeline.inc
index 99e4e303f5a..2f319513c0b 100644
--- a/chromium/third_party/skia/src/sksl/sksl_pipeline.inc
+++ b/chromium/third_party/skia/src/sksl/sksl_pipeline.inc
@@ -1,4 +1,5 @@
STRINGIFY(
+ layout(builtin=15) float4 sk_FragCoord;
half4 sample(fragmentProcessor fp, float2 coords);
half4 sample(fragmentProcessor fp, float3x3 transform);
)
diff --git a/chromium/third_party/skia/src/svg/SkSVGDevice.cpp b/chromium/third_party/skia/src/svg/SkSVGDevice.cpp
index a6cb77d1911..3fbe4122ea5 100644
--- a/chromium/third_party/skia/src/svg/SkSVGDevice.cpp
+++ b/chromium/third_party/skia/src/svg/SkSVGDevice.cpp
@@ -760,6 +760,9 @@ void SkSVGDevice::syncClipStack(const SkClipStack& cs) {
path.addAttribute("clip-rule", "evenodd");
}
} break;
+ case SkClipStack::Element::DeviceSpaceType::kShader:
+ // TODO: handle shader clipping, perhaps rasterize and apply as a mask image?
+ break;
}
return cid;
diff --git a/chromium/third_party/skia/src/utils/SkCamera.cpp b/chromium/third_party/skia/src/utils/SkCamera.cpp
index 63d1c804fa4..45e216edb27 100644
--- a/chromium/third_party/skia/src/utils/SkCamera.cpp
+++ b/chromium/third_party/skia/src/utils/SkCamera.cpp
@@ -19,48 +19,6 @@ static SkScalar SkScalarDotDiv(int count, const SkScalar a[], int step_a,
return prod / denom;
}
-static SkScalar SkScalarDot(int count, const SkScalar a[], int step_a,
- const SkScalar b[], int step_b) {
- SkScalar prod = 0;
- for (int i = 0; i < count; i++) {
- prod += a[0] * b[0];
- a += step_a;
- b += step_b;
- }
- return prod;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkScalar SkPoint3D::normalize(SkUnit3D* unit) const {
- SkScalar mag = SkScalarSqrt(fX*fX + fY*fY + fZ*fZ);
- if (mag) {
- SkScalar scale = SkScalarInvert(mag);
- unit->fX = fX * scale;
- unit->fY = fY * scale;
- unit->fZ = fZ * scale;
- } else {
- unit->fX = unit->fY = unit->fZ = 0;
- }
- return mag;
-}
-
-SkScalar SkUnit3D::Dot(const SkUnit3D& a, const SkUnit3D& b) {
- return a.fX * b.fX + a.fY * b.fY + a.fZ * b.fZ;
-}
-
-void SkUnit3D::Cross(const SkUnit3D& a, const SkUnit3D& b, SkUnit3D* cross) {
- SkASSERT(cross);
-
- // use x,y,z, in case &a == cross or &b == cross
-
- SkScalar x = a.fY * b.fZ - a.fZ * b.fY;
- SkScalar y = a.fZ * b.fX - a.fX * b.fY;
- SkScalar z = a.fX * b.fY - a.fY * b.fX;
-
- cross->set(x, y, z);
-}
-
///////////////////////////////////////////////////////////////////////////////
SkPatch3D::SkPatch3D() {
@@ -68,141 +26,41 @@ SkPatch3D::SkPatch3D() {
}
void SkPatch3D::reset() {
- fOrigin.set(0, 0, 0);
- fU.set(SK_Scalar1, 0, 0);
- fV.set(0, -SK_Scalar1, 0);
+ fOrigin = {0, 0, 0};
+ fU = {SK_Scalar1, 0, 0};
+ fV = {0, -SK_Scalar1, 0};
}
-void SkPatch3D::transform(const SkMatrix3D& m, SkPatch3D* dst) const {
+void SkPatch3D::transform(const SkM44& m, SkPatch3D* dst) const {
if (dst == nullptr) {
dst = (SkPatch3D*)this;
}
- m.mapVector(fU, &dst->fU);
- m.mapVector(fV, &dst->fV);
- m.mapPoint(fOrigin, &dst->fOrigin);
+ dst->fU = m * fU;
+ dst->fV = m * fV;
+ auto [x,y,z,_] = m.map(fOrigin.x, fOrigin.y, fOrigin.z, 1);
+ dst->fOrigin = {x, y, z};
}
SkScalar SkPatch3D::dotWith(SkScalar dx, SkScalar dy, SkScalar dz) const {
- SkScalar cx = fU.fY * fV.fZ - fU.fZ * fV.fY;
- SkScalar cy = fU.fZ * fV.fX - fU.fX * fV.fY;
- SkScalar cz = fU.fX * fV.fY - fU.fY * fV.fX;
+ SkScalar cx = fU.y * fV.z - fU.z * fV.y;
+ SkScalar cy = fU.z * fV.x - fU.x * fV.y;
+ SkScalar cz = fU.x * fV.y - fU.y * fV.x;
return cx * dx + cy * dy + cz * dz;
}
///////////////////////////////////////////////////////////////////////////////
-void SkMatrix3D::reset() {
- memset(fMat, 0, sizeof(fMat));
- fMat[0][0] = fMat[1][1] = fMat[2][2] = SK_Scalar1;
-}
-
-void SkMatrix3D::setTranslate(SkScalar x, SkScalar y, SkScalar z) {
- memset(fMat, 0, sizeof(fMat));
- fMat[0][0] = x;
- fMat[1][1] = y;
- fMat[2][2] = z;
-}
-
-void SkMatrix3D::setRotateX(SkScalar degX) {
- SkScalar r = SkDegreesToRadians(degX),
- s = SkScalarSin(r),
- c = SkScalarCos(r);
- this->setRow(0, SK_Scalar1, 0, 0);
- this->setRow(1, 0, c, -s);
- this->setRow(2, 0, s, c);
-}
-
-void SkMatrix3D::setRotateY(SkScalar degY) {
- SkScalar r = SkDegreesToRadians(degY),
- s = SkScalarSin(r),
- c = SkScalarCos(r);
- this->setRow(0, c, 0, -s);
- this->setRow(1, 0, SK_Scalar1, 0);
- this->setRow(2, s, 0, c);
-}
-
-void SkMatrix3D::setRotateZ(SkScalar degZ) {
- SkScalar r = SkDegreesToRadians(degZ),
- s = SkScalarSin(r),
- c = SkScalarCos(r);
- this->setRow(0, c, -s, 0);
- this->setRow(1, s, c, 0);
- this->setRow(2, 0, 0, SK_Scalar1);
-}
-
-void SkMatrix3D::preTranslate(SkScalar x, SkScalar y, SkScalar z) {
- SkScalar col[3] = { x, y, z};
-
- for (int i = 0; i < 3; i++) {
- fMat[i][3] += SkScalarDot(3, &fMat[i][0], 1, col, 1);
- }
-}
-
-void SkMatrix3D::preRotateX(SkScalar degX) {
- SkMatrix3D m;
- m.setRotateX(degX);
- this->setConcat(*this, m);
-}
-
-void SkMatrix3D::preRotateY(SkScalar degY) {
- SkMatrix3D m;
- m.setRotateY(degY);
- this->setConcat(*this, m);
-}
-
-void SkMatrix3D::preRotateZ(SkScalar degZ) {
- SkMatrix3D m;
- m.setRotateZ(degZ);
- this->setConcat(*this, m);
-}
-
-void SkMatrix3D::setConcat(const SkMatrix3D& a, const SkMatrix3D& b) {
- SkMatrix3D tmp;
- SkMatrix3D* c = this;
-
- if (this == &a || this == &b) {
- c = &tmp;
- }
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- c->fMat[i][j] = SkScalarDot(3, &a.fMat[i][0], 1, &b.fMat[0][j], 4);
- }
- c->fMat[i][3] = SkScalarDot(3, &a.fMat[i][0], 1,
- &b.fMat[0][3], 4) + a.fMat[i][3];
- }
-
- if (c == &tmp) {
- *this = tmp;
- }
-}
-
-void SkMatrix3D::mapPoint(const SkPoint3D& src, SkPoint3D* dst) const {
- SkScalar x = SkScalarDot(3, &fMat[0][0], 1, &src.fX, 1) + fMat[0][3];
- SkScalar y = SkScalarDot(3, &fMat[1][0], 1, &src.fX, 1) + fMat[1][3];
- SkScalar z = SkScalarDot(3, &fMat[2][0], 1, &src.fX, 1) + fMat[2][3];
- dst->set(x, y, z);
-}
-
-void SkMatrix3D::mapVector(const SkVector3D& src, SkVector3D* dst) const {
- SkScalar x = SkScalarDot(3, &fMat[0][0], 1, &src.fX, 1);
- SkScalar y = SkScalarDot(3, &fMat[1][0], 1, &src.fX, 1);
- SkScalar z = SkScalarDot(3, &fMat[2][0], 1, &src.fX, 1);
- dst->set(x, y, z);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
SkCamera3D::SkCamera3D() {
this->reset();
}
void SkCamera3D::reset() {
- fLocation.set(0, 0, -SkIntToScalar(576)); // 8 inches backward
- fAxis.set(0, 0, SK_Scalar1); // forward
- fZenith.set(0, -SK_Scalar1, 0); // up
+ fLocation = {0, 0, -SkIntToScalar(576)}; // 8 inches backward
+ fAxis = {0, 0, SK_Scalar1}; // forward
+ fZenith = {0, -SK_Scalar1, 0}; // up
- fObserver.set(0, 0, fLocation.fZ);
+ fObserver = {0, 0, fLocation.z};
fNeedToUpdate = true;
}
@@ -212,28 +70,19 @@ void SkCamera3D::update() {
}
void SkCamera3D::doUpdate() const {
- SkUnit3D axis, zenith, cross;
+ SkV3 axis, zenith, cross;
// construct a orthonormal basis of cross (x), zenith (y), and axis (z)
- fAxis.normalize(&axis);
+ axis = fAxis.normalize();
- {
- SkScalar dot = SkUnit3D::Dot(SkUnit3D{fZenith.fX, fZenith.fY, fZenith.fZ}, axis);
+ zenith = fZenith - (axis * fZenith) * axis;
+ zenith = zenith.normalize();
- zenith.fX = fZenith.fX - dot * axis.fX;
- zenith.fY = fZenith.fY - dot * axis.fY;
- zenith.fZ = fZenith.fZ - dot * axis.fZ;
-
- SkPoint3D{zenith.fX, zenith.fY, zenith.fZ}.normalize(&zenith);
- }
-
- SkUnit3D::Cross(axis, zenith, &cross);
+ cross = axis.cross(zenith);
{
SkMatrix* orien = &fOrientation;
- SkScalar x = fObserver.fX;
- SkScalar y = fObserver.fY;
- SkScalar z = fObserver.fZ;
+ auto [x, y, z] = fObserver;
// Looking along the view axis we have:
//
@@ -249,15 +98,15 @@ void SkCamera3D::doUpdate() const {
// and scales in x and y relative to the negative of the observer's z value
// (the observer is in the negative z direction).
- orien->set(SkMatrix::kMScaleX, x * axis.fX - z * cross.fX);
- orien->set(SkMatrix::kMSkewX, x * axis.fY - z * cross.fY);
- orien->set(SkMatrix::kMTransX, x * axis.fZ - z * cross.fZ);
- orien->set(SkMatrix::kMSkewY, y * axis.fX - z * zenith.fX);
- orien->set(SkMatrix::kMScaleY, y * axis.fY - z * zenith.fY);
- orien->set(SkMatrix::kMTransY, y * axis.fZ - z * zenith.fZ);
- orien->set(SkMatrix::kMPersp0, axis.fX);
- orien->set(SkMatrix::kMPersp1, axis.fY);
- orien->set(SkMatrix::kMPersp2, axis.fZ);
+ orien->set(SkMatrix::kMScaleX, x * axis.x - z * cross.x);
+ orien->set(SkMatrix::kMSkewX, x * axis.y - z * cross.y);
+ orien->set(SkMatrix::kMTransX, x * axis.z - z * cross.z);
+ orien->set(SkMatrix::kMSkewY, y * axis.x - z * zenith.x);
+ orien->set(SkMatrix::kMScaleY, y * axis.y - z * zenith.y);
+ orien->set(SkMatrix::kMTransY, y * axis.z - z * zenith.z);
+ orien->set(SkMatrix::kMPersp0, axis.x);
+ orien->set(SkMatrix::kMPersp1, axis.y);
+ orien->set(SkMatrix::kMPersp2, axis.z);
}
}
@@ -269,15 +118,9 @@ void SkCamera3D::patchToMatrix(const SkPatch3D& quilt, SkMatrix* matrix) const {
const SkScalar* mapPtr = (const SkScalar*)(const void*)&fOrientation;
const SkScalar* patchPtr;
- SkPoint3D diff;
- SkScalar dot;
-
- diff.fX = quilt.fOrigin.fX - fLocation.fX;
- diff.fY = quilt.fOrigin.fY - fLocation.fY;
- diff.fZ = quilt.fOrigin.fZ - fLocation.fZ;
- dot = SkUnit3D::Dot(SkUnit3D{diff.fX, diff.fY, diff.fZ},
- SkUnit3D{mapPtr[6], mapPtr[7], mapPtr[8]});
+ SkV3 diff = quilt.fOrigin - fLocation;
+ SkScalar dot = diff.dot({mapPtr[6], mapPtr[7], mapPtr[8]});
// This multiplies fOrientation by the matrix [quilt.fU quilt.fV diff] -- U, V, and diff are
// column vectors in the matrix -- then divides by the length of the projection of diff onto
@@ -307,7 +150,6 @@ void SkCamera3D::patchToMatrix(const SkPatch3D& quilt, SkMatrix* matrix) const {
///////////////////////////////////////////////////////////////////////////////
Sk3DView::Sk3DView() {
- fInitialRec.fMatrix.reset();
fRec = &fInitialRec;
}
@@ -338,22 +180,22 @@ void Sk3DView::restore() {
void Sk3DView::setCameraLocation(SkScalar x, SkScalar y, SkScalar z) {
// the camera location is passed in inches, set in pt
SkScalar lz = z * 72.0f;
- fCamera.fLocation.set(x * 72.0f, y * 72.0f, lz);
- fCamera.fObserver.set(0, 0, lz);
+ fCamera.fLocation = {x * 72.0f, y * 72.0f, lz};
+ fCamera.fObserver = {0, 0, lz};
fCamera.update();
}
SkScalar Sk3DView::getCameraLocationX() const {
- return fCamera.fLocation.fX / 72.0f;
+ return fCamera.fLocation.x / 72.0f;
}
SkScalar Sk3DView::getCameraLocationY() const {
- return fCamera.fLocation.fY / 72.0f;
+ return fCamera.fLocation.y / 72.0f;
}
SkScalar Sk3DView::getCameraLocationZ() const {
- return fCamera.fLocation.fZ / 72.0f;
+ return fCamera.fLocation.z / 72.0f;
}
#endif
@@ -362,15 +204,15 @@ void Sk3DView::translate(SkScalar x, SkScalar y, SkScalar z) {
}
void Sk3DView::rotateX(SkScalar deg) {
- fRec->fMatrix.preRotateX(deg);
+ fRec->fMatrix.preConcat(SkM44::Rotate({1, 0, 0}, deg * SK_ScalarPI / 180));
}
void Sk3DView::rotateY(SkScalar deg) {
- fRec->fMatrix.preRotateY(deg);
+ fRec->fMatrix.preConcat(SkM44::Rotate({0,-1, 0}, deg * SK_ScalarPI / 180));
}
void Sk3DView::rotateZ(SkScalar deg) {
- fRec->fMatrix.preRotateZ(deg);
+ fRec->fMatrix.preConcat(SkM44::Rotate({0, 0, 1}, deg * SK_ScalarPI / 180));
}
SkScalar Sk3DView::dotWithNormal(SkScalar x, SkScalar y, SkScalar z) const {
diff --git a/chromium/third_party/skia/src/utils/SkClipStackUtils.cpp b/chromium/third_party/skia/src/utils/SkClipStackUtils.cpp
index 00b933630e4..fade198d6d9 100644
--- a/chromium/third_party/skia/src/utils/SkClipStackUtils.cpp
+++ b/chromium/third_party/skia/src/utils/SkClipStackUtils.cpp
@@ -14,6 +14,11 @@ void SkClipStack_AsPath(const SkClipStack& cs, SkPath* path) {
SkClipStack::Iter iter(cs, SkClipStack::Iter::kBottom_IterStart);
while (const SkClipStack::Element* element = iter.next()) {
+ if (element->getDeviceSpaceType() == SkClipStack::Element::DeviceSpaceType::kShader) {
+ // TODO: Handle DeviceSpaceType::kShader somehow; it can't be turned into an SkPath
+ // but perhaps the pdf backend can apply shaders in another way.
+ continue;
+ }
SkPath operand;
if (element->getDeviceSpaceType() != SkClipStack::Element::DeviceSpaceType::kEmpty) {
element->asDeviceSpacePath(&operand);
diff --git a/chromium/third_party/skia/src/utils/SkCustomTypeface.cpp b/chromium/third_party/skia/src/utils/SkCustomTypeface.cpp
index 61664aff9c1..2fbdd7542b9 100644
--- a/chromium/third_party/skia/src/utils/SkCustomTypeface.cpp
+++ b/chromium/third_party/skia/src/utils/SkCustomTypeface.cpp
@@ -11,21 +11,46 @@
#include "include/utils/SkCustomTypeface.h"
#include "src/core/SkAdvancedTypefaceMetrics.h"
-class SkUserTypeface : public SkTypeface {
+static SkFontMetrics scale_fontmetrics(const SkFontMetrics& src, float sx, float sy) {
+ SkFontMetrics dst = src;
+
+ #define SCALE_X(field) dst.field *= sx
+ #define SCALE_Y(field) dst.field *= sy
+
+ SCALE_X(fAvgCharWidth);
+ SCALE_X(fMaxCharWidth);
+ SCALE_X(fXMin);
+ SCALE_X(fXMax);
+
+ SCALE_Y(fTop);
+ SCALE_Y(fAscent);
+ SCALE_Y(fDescent);
+ SCALE_Y(fBottom);
+ SCALE_Y(fLeading);
+ SCALE_Y(fXHeight);
+ SCALE_Y(fCapHeight);
+ SCALE_Y(fUnderlineThickness);
+ SCALE_Y(fUnderlinePosition);
+ SCALE_Y(fStrikeoutThickness);
+ SCALE_Y(fStrikeoutPosition);
+
+ #undef SCALE_X
+ #undef SCALE_Y
+
+ return dst;
+}
+
+class SkUserTypeface final : public SkTypeface {
+private:
friend class SkCustomTypefaceBuilder;
friend class SkUserScalerContext;
- SkUserTypeface(int count)
- : SkTypeface(SkFontStyle())
- , fGlyphCount(count)
- {}
+ SkUserTypeface() : SkTypeface(SkFontStyle()) {}
- const int fGlyphCount;
std::vector<SkPath> fPaths;
std::vector<float> fAdvances;
- SkRect fBounds;
+ SkFontMetrics fMetrics;
-protected:
SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
const SkDescriptor* desc) const override;
void onFilterRec(SkScalerContextRec* rec) const override;
@@ -46,9 +71,12 @@ protected:
sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
return sk_ref_sp(this);
}
- int onCountGlyphs() const override { return fGlyphCount; }
+ int onCountGlyphs() const override { return this->glyphCount(); }
int onGetUPEM() const override { return 2048; /* ?? */ }
- bool onComputeBounds(SkRect* bounds) const override { *bounds = fBounds; return true; }
+ bool onComputeBounds(SkRect* bounds) const override {
+ bounds->setLTRB(fMetrics.fXMin, fMetrics.fTop, fMetrics.fXMax, fMetrics.fBottom);
+ return true;
+ }
// noops
@@ -59,27 +87,39 @@ protected:
int) const override { return 0; }
int onGetTableTags(SkFontTableTag tags[]) const override { return 0; }
size_t onGetTableData(SkFontTableTag, size_t, size_t, void*) const override { return 0; }
+
+ int glyphCount() const {
+ SkASSERT(fPaths.size() == fAdvances.size());
+ return SkToInt(fPaths.size());
+ }
};
-SkCustomTypefaceBuilder::SkCustomTypefaceBuilder(int numGlyphs) : fGlyphCount(numGlyphs) {
- fAdvances.resize(numGlyphs);
- fPaths.resize(numGlyphs);
+SkCustomTypefaceBuilder::SkCustomTypefaceBuilder() {
+ sk_bzero(&fMetrics, sizeof(fMetrics));
+}
+
+void SkCustomTypefaceBuilder::setMetrics(const SkFontMetrics& fm, float scale) {
+ fMetrics = scale_fontmetrics(fm, scale, scale);
}
void SkCustomTypefaceBuilder::setGlyph(SkGlyphID index, float advance, const SkPath& path) {
- if (index >= (unsigned)fGlyphCount) {
- return;
+ SkASSERT(fPaths.size() == fAdvances.size());
+ if (index >= fPaths.size()) {
+ fPaths.resize(SkToSizeT(index) + 1);
+ fAdvances.resize(SkToSizeT(index) + 1);
}
fAdvances[index] = advance;
fPaths[index] = path;
}
sk_sp<SkTypeface> SkCustomTypefaceBuilder::detach() {
- if (fGlyphCount <= 0) return nullptr;
+ SkASSERT(fPaths.size() == fAdvances.size());
+ if (fPaths.empty()) return nullptr;
- SkUserTypeface* tf = new SkUserTypeface(fGlyphCount);
+ sk_sp<SkUserTypeface> tf(new SkUserTypeface());
tf->fAdvances = std::move(fAdvances);
tf->fPaths = std::move(fPaths);
+ tf->fMetrics = fMetrics;
// initially inverted, so that any "union" will overwrite the first time
SkRect bounds = {SK_ScalarMax, SK_ScalarMax, -SK_ScalarMax, -SK_ScalarMax};
@@ -89,9 +129,12 @@ sk_sp<SkTypeface> SkCustomTypefaceBuilder::detach() {
bounds.join(path.getBounds());
}
}
- tf->fBounds = bounds;
+ tf->fMetrics.fTop = bounds.top();
+ tf->fMetrics.fBottom = bounds.bottom();
+ tf->fMetrics.fXMin = bounds.left();
+ tf->fMetrics.fXMax = bounds.right();
- return sk_sp<SkTypeface>(tf);
+ return std::move(tf);
}
/////////////
@@ -103,8 +146,8 @@ void SkUserTypeface::onFilterRec(SkScalerContextRec* rec) const {
}
void SkUserTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
- for (int gid = 0; gid < fGlyphCount; ++gid) {
- glyphToUnicode[gid] = 0;
+ for (int gid = 0; gid < this->glyphCount(); ++gid) {
+ glyphToUnicode[gid] = SkTo<SkUnichar>(gid);
}
}
@@ -118,7 +161,7 @@ void SkUserTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal)
void SkUserTypeface::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
for (int i = 0; i < count; ++i) {
- glyphs[i] = 0;
+ glyphs[i] = uni[i] < this->glyphCount() ? SkTo<SkGlyphID>(uni[i]) : 0;
}
}
@@ -150,7 +193,7 @@ public:
protected:
unsigned generateGlyphCount() override {
- return this->userTF()->fGlyphCount;
+ return this->userTF()->glyphCount();
}
bool generateAdvance(SkGlyph* glyph) override {
@@ -176,15 +219,8 @@ protected:
}
void generateFontMetrics(SkFontMetrics* metrics) override {
- auto [_, sy] = fMatrix.mapXY(0, 1);
-
- sk_bzero(metrics, sizeof(*metrics));
- metrics->fTop = this->userTF()->fBounds.fTop * sy;
- metrics->fBottom = this->userTF()->fBounds.fBottom * sy;
-
- // todo: get these from the creator of the typeface?
- metrics->fAscent = metrics->fTop;
- metrics->fDescent = metrics->fBottom;
+ auto [sx, sy] = fMatrix.mapXY(1, 1);
+ *metrics = scale_fontmetrics(this->userTF()->fMetrics, sx, sy);
}
private:
@@ -268,7 +304,7 @@ static void compress_write(SkWStream* stream, const SkPath& path, int upem) {
static constexpr int kMaxGlyphCount = 65536;
static constexpr size_t kHeaderSize = 16;
-static const char gHeaderString[] = "SkUserTypeface00";
+static const char gHeaderString[] = "SkUserTypeface01";
static_assert(sizeof(gHeaderString) == 1 + kHeaderSize, "need header to be 16 bytes");
std::unique_ptr<SkStreamAsset> SkUserTypeface::onOpenStream(int* ttcIndex) const {
@@ -276,20 +312,19 @@ std::unique_ptr<SkStreamAsset> SkUserTypeface::onOpenStream(int* ttcIndex) const
wstream.write(gHeaderString, kHeaderSize);
- SkASSERT(fAdvances.size() == (unsigned)fGlyphCount);
- SkASSERT(fPaths.size() == (unsigned)fGlyphCount);
+ wstream.write(&fMetrics, sizeof(fMetrics));
// just hacking around -- this makes the serialized font 1/2 size
const bool use_compression = false;
- wstream.write32(fGlyphCount);
+ wstream.write32(this->glyphCount());
if (use_compression) {
for (float a : fAdvances) {
write_scaled_float_to_16(&wstream, a, 2048);
}
} else {
- wstream.write(fAdvances.data(), fGlyphCount * sizeof(float));
+ wstream.write(fAdvances.data(), this->glyphCount() * sizeof(float));
}
for (const auto& p : fPaths) {
@@ -334,12 +369,19 @@ sk_sp<SkTypeface> SkCustomTypefaceBuilder::Deserialize(SkStream* stream) {
return nullptr;
}
+ SkFontMetrics metrics;
+ if (stream->read(&metrics, sizeof(metrics)) != sizeof(metrics)) {
+ return nullptr;
+ }
+
int glyphCount;
if (!stream->readS32(&glyphCount) || glyphCount < 0 || glyphCount > kMaxGlyphCount) {
return nullptr;
}
- SkCustomTypefaceBuilder builder(glyphCount);
+ SkCustomTypefaceBuilder builder;
+
+ builder.setMetrics(metrics);
std::vector<float> advances(glyphCount);
if (stream->read(advances.data(), glyphCount * sizeof(float)) != glyphCount * sizeof(float)) {
diff --git a/chromium/third_party/skia/src/utils/SkJSON.cpp b/chromium/third_party/skia/src/utils/SkJSON.cpp
index 181ca752e5a..c53fc1bfc0a 100644
--- a/chromium/third_party/skia/src/utils/SkJSON.cpp
+++ b/chromium/third_party/skia/src/utils/SkJSON.cpp
@@ -28,23 +28,22 @@ static constexpr size_t kRecAlign = alignof(Value);
void Value::init_tagged(Tag t) {
memset(fData8, 0, sizeof(fData8));
- fData8[Value::kTagOffset] = SkTo<uint8_t>(t);
+ fData8[0] = SkTo<uint8_t>(t);
SkASSERT(this->getTag() == t);
}
-// Pointer values store a type (in the upper kTagBits bits) and a pointer.
+// Pointer values store a type (in the lower kTagBits bits) and a pointer.
void Value::init_tagged_pointer(Tag t, void* p) {
- *this->cast<uintptr_t>() = reinterpret_cast<uintptr_t>(p);
-
if (sizeof(Value) == sizeof(uintptr_t)) {
- // For 64-bit, we rely on the pointer upper bits being unused/zero.
- SkASSERT(!(fData8[kTagOffset] & kTagMask));
- fData8[kTagOffset] |= SkTo<uint8_t>(t);
+ *this->cast<uintptr_t>() = reinterpret_cast<uintptr_t>(p);
+ // For 64-bit, we rely on the pointer lower bits being zero.
+ SkASSERT(!(fData8[0] & kTagMask));
+ fData8[0] |= SkTo<uint8_t>(t);
} else {
- // For 32-bit, we need to zero-initialize the upper 32 bits
+ // For 32-bit, we store the pointer in the upper word
SkASSERT(sizeof(Value) == sizeof(uintptr_t) * 2);
- this->cast<uintptr_t>()[kTagOffset >> 2] = 0;
- fData8[kTagOffset] = SkTo<uint8_t>(t);
+ this->init_tagged(t);
+ *this->cast<uintptr_t>() = reinterpret_cast<uintptr_t>(p);
}
SkASSERT(this->getTag() == t);
@@ -126,11 +125,8 @@ public:
return;
}
- static_assert(static_cast<uint8_t>(Tag::kShortString) == 0, "please don't break this");
- static_assert(sizeof(Value) == 8, "");
-
- // TODO: LIKELY
- if (src && src + 7 <= eos) {
+ // initFastShortString is faster (doh), but requires access to 6 chars past src.
+ if (src && src + 6 <= eos) {
this->initFastShortString(src, size);
} else {
this->initShortString(src, size);
@@ -140,7 +136,8 @@ public:
}
private:
- static constexpr size_t kMaxInlineStringSize = sizeof(Value) - 1;
+ // first byte reserved for tagging, \0 terminator => 6 usable chars
+ static constexpr size_t kMaxInlineStringSize = sizeof(Value) - 2;
void initLongString(const char* src, size_t size, SkArenaAlloc& alloc) {
SkASSERT(size > kMaxInlineStringSize);
@@ -162,12 +159,23 @@ private:
void initFastShortString(const char* src, size_t size) {
SkASSERT(size <= kMaxInlineStringSize);
- // Load 8 chars and mask out the tag and \0 terminator.
uint64_t* s64 = this->cast<uint64_t>();
- memcpy(s64, src, 8);
+
+ // Load 8 chars and mask out the tag and \0 terminator.
+ // Note: we picked kShortString == 0 to avoid setting explicitly below.
+ static_assert(SkToU8(Tag::kShortString) == 0, "please don't break this");
+
+ // Since the first byte is occupied by the tag, we want the string chars [0..5] to land
+ // on bytes [1..6] => the fastest way is to read8 @(src - 1) (always safe, because the
+ // string requires a " prefix at the very least).
+ memcpy(s64, src - 1, 8);
#if defined(SK_CPU_LENDIAN)
- *s64 &= 0x00ffffffffffffffULL >> ((kMaxInlineStringSize - size) * 8);
+ // The mask for a max-length string (6), with a leading tag and trailing \0 is
+ // 0x00ffffffffffff00. Accounting for the final left-shift, this becomes
+ // 0x0000ffffffffffff.
+ *s64 &= (0x0000ffffffffffffULL >> ((kMaxInlineStringSize - size) * 8)) // trailing \0s
+ << 8; // tag byte
#else
static_assert(false, "Big-endian builds are not supported at this time.");
#endif
diff --git a/chromium/third_party/skia/src/utils/SkJSON.h b/chromium/third_party/skia/src/utils/SkJSON.h
index 931b30f0a4e..d3f0b1d48f0 100644
--- a/chromium/third_party/skia/src/utils/SkJSON.h
+++ b/chromium/third_party/skia/src/utils/SkJSON.h
@@ -117,58 +117,69 @@ protected:
char[8] (short string storage)
external payload (tagged) pointer
- -- highest 3 bits reserved for type storage
+ -- lowest 3 bits reserved for tag storage
*/
enum class Tag : uint8_t {
- // We picked kShortString == 0 so that tag 0x00 and stored max_size-size (7-7=0)
- // conveniently overlap the '\0' terminator, allowing us to store a 7 character
- // C string inline.
+ // n.b.: we picked kShortString == 0 on purpose,
+ // to enable certain short-string optimizations.
kShortString = 0b00000000, // inline payload
- kNull = 0b00100000, // no payload
- kBool = 0b01000000, // inline payload
- kInt = 0b01100000, // inline payload
- kFloat = 0b10000000, // inline payload
- kString = 0b10100000, // ptr to external storage
- kArray = 0b11000000, // ptr to external storage
- kObject = 0b11100000, // ptr to external storage
+ kNull = 0b00000001, // no payload
+ kBool = 0b00000010, // inline payload
+ kInt = 0b00000011, // inline payload
+ kFloat = 0b00000100, // inline payload
+ kString = 0b00000101, // ptr to external storage
+ kArray = 0b00000110, // ptr to external storage
+ kObject = 0b00000111, // ptr to external storage
};
- static constexpr uint8_t kTagMask = 0b11100000;
+ static constexpr uint8_t kTagMask = 0b00000111;
void init_tagged(Tag);
void init_tagged_pointer(Tag, void*);
Tag getTag() const {
- return static_cast<Tag>(fData8[kTagOffset] & kTagMask);
+ return static_cast<Tag>(fData8[0] & kTagMask);
}
- // Access the record data as T.
+ // Access the record payload as T.
//
- // This is also used to access the payload for inline records. Since the record type lives in
- // the high bits, sizeof(T) must be less than sizeof(Value) when accessing inline payloads.
+ // Since the tag is stored in the lower bits, we skip the first word whenever feasible.
//
- // E.g.
+ // E.g. (U == unused)
//
// uint8_t
// -----------------------------------------------------------------------
- // | val8 | val8 | val8 | val8 | val8 | val8 | val8 | TYPE|
+ // |TAG| U | val8 | U | U | U | U | U | U |
+ // -----------------------------------------------------------------------
+ //
+ // uint16_t
+ // -----------------------------------------------------------------------
+ // |TAG| U | val16 | U | U |
// -----------------------------------------------------------------------
//
// uint32_t
// -----------------------------------------------------------------------
- // | val32 | unused | TYPE|
+ // |TAG| U | val32 |
+ // -----------------------------------------------------------------------
+ //
+ // T* (32b)
+ // -----------------------------------------------------------------------
+ // |TAG| U | T* (32bits) |
// -----------------------------------------------------------------------
//
// T* (64b)
// -----------------------------------------------------------------------
- // | T* (kTypeShift bits) |TYPE|
+ // |TAG| T* (61bits) |
// -----------------------------------------------------------------------
//
template <typename T>
const T* cast() const {
static_assert(sizeof (T) <= sizeof(Value), "");
static_assert(alignof(T) <= alignof(Value), "");
- return reinterpret_cast<const T*>(this);
+
+ return (sizeof(T) > sizeof(*this) / 2)
+ ? reinterpret_cast<const T*>(this) + 0 // need all the bits
+ : reinterpret_cast<const T*>(this) + 1; // skip the first word (where the tag lives)
}
template <typename T>
@@ -183,8 +194,8 @@ protected:
return (sizeof(uintptr_t) < sizeof(Value))
// For 32-bit, pointers are stored unmodified.
? *this->cast<const T*>()
- // For 64-bit, we use the high bits of the pointer as tag storage.
- : reinterpret_cast<T*>(*this->cast<uintptr_t>() & kTagPointerMask);
+ // For 64-bit, we use the lower bits of the pointer as tag storage.
+ : reinterpret_cast<T*>(*this->cast<uintptr_t>() & ~static_cast<uintptr_t>(kTagMask));
}
private:
@@ -192,12 +203,7 @@ private:
uint8_t fData8[kValueSize];
-#if defined(SK_CPU_LENDIAN)
- static constexpr size_t kTagOffset = kValueSize - 1;
-
- static constexpr uintptr_t kTagPointerMask =
- ~(static_cast<uintptr_t>(kTagMask) << ((sizeof(uintptr_t) - 1) * 8));
-#else
+#if !defined(SK_CPU_LENDIAN)
// The current value layout assumes LE and will take some tweaking for BE.
static_assert(false, "Big-endian builds are not supported at this time.");
#endif
@@ -319,11 +325,11 @@ class ObjectValue final : public VectorValue<Member, Value::Type::kObject> {
public:
ObjectValue(const Member* src, size_t size, SkArenaAlloc& alloc);
- const Value& operator[](const char*) const;
+ const Value& operator[](const char*) const;
-private:
- // Not particularly interesting - hiding for disambiguation.
- const Member& operator[](size_t i) const = delete;
+ const Member& operator[](size_t i) const {
+ return this->VectorValue::operator[](i);
+ }
};
class DOM final : public SkNoncopyable {
diff --git a/chromium/third_party/skia/src/utils/SkLuaCanvas.cpp b/chromium/third_party/skia/src/utils/SkLuaCanvas.cpp
index 7bdeb482da4..3a094c3f5f6 100644
--- a/chromium/third_party/skia/src/utils/SkLuaCanvas.cpp
+++ b/chromium/third_party/skia/src/utils/SkLuaCanvas.cpp
@@ -114,10 +114,10 @@ void SkLuaCanvas::didConcat44(const SkM44&) {
// TODO
}
void SkLuaCanvas::didScale(SkScalar x, SkScalar y) {
- this->didConcat(SkMatrix::MakeScale(x, y));
+ this->didConcat(SkMatrix::Scale(x, y));
}
void SkLuaCanvas::didTranslate(SkScalar x, SkScalar y) {
- this->didConcat(SkMatrix::MakeTrans(x, y));
+ this->didConcat(SkMatrix::Translate(x, y));
}
void SkLuaCanvas::didConcat(const SkMatrix& matrix) {
switch (matrix.getType()) {
diff --git a/chromium/third_party/skia/src/utils/SkParseColor.cpp b/chromium/third_party/skia/src/utils/SkParseColor.cpp
index ba7c51048f1..9846a8ff5ee 100644
--- a/chromium/third_party/skia/src/utils/SkParseColor.cpp
+++ b/chromium/third_party/skia/src/utils/SkParseColor.cpp
@@ -8,211 +8,172 @@
#include "include/utils/SkParse.h"
-static const unsigned int gColorNames[] = {
-0x85891945, 0x32a50000, 0x00f0f8ff, // aliceblue
-0x85d44c6b, 0x16e84d0a, 0x00faebd7, // antiquewhite
-0x86350800, 0x0000ffff, // aqua
-0x86350b43, 0x492e2800, 0x007fffd4, // aquamarine
-0x87559140, 0x00f0ffff, // azure
-0x88a93940, 0x00f5f5dc, // beige
-0x89338d4a, 0x00ffe4c4, // bisque
-0x89811ac0, 0x00000000, // black
-0x898170d1, 0x1481635f, 0x38800000, 0x00ffebcd, // blanchedalmond
-0x89952800, 0x000000ff, // blue
-0x89952d93, 0x3d85a000, 0x008a2be2, // blueviolet
-0x8a4fbb80, 0x00a52a2a, // brown
-0x8ab2666f, 0x3de40000, 0x00deb887, // burlywood
-0x8c242d05, 0x32a50000, 0x005f9ea0, // cadetblue
-0x8d019525, 0x16b32800, 0x007fff00, // chartreuse
-0x8d0f1bd9, 0x06850000, 0x00d2691e, // chocolate
-0x8df20b00, 0x00ff7f50, // coral
-0x8df27199, 0x3ee59099, 0x54a00000, 0x006495ed, // cornflowerblue
-0x8df274d3, 0x31600000, 0x00fff8dc, // cornsilk
-0x8e496cdf, 0x38000000, 0x00dc143c, // crimson
-0x8f217000, 0x0000ffff, // cyan
-0x90325899, 0x54a00000, 0x0000008b, // darkblue
-0x903258f3, 0x05c00000, 0x00008b8b, // darkcyan
-0x903259df, 0x3085749f, 0x10000000, 0x00b8860b, // darkgoldenrod
-0x903259e5, 0x07200000, 0x00a9a9a9, // darkgray
-0x903259e5, 0x14ae0000, 0x00006400, // darkgreen
-0x90325ad1, 0x05690000, 0x00bdb76b, // darkkhaki
-0x90325b43, 0x1caea040, 0x008b008b, // darkmagenta
-0x90325bd9, 0x26c53c8b, 0x15c00000, 0x00556b2f, // darkolivegreen
-0x90325be5, 0x05c72800, 0x00ff8c00, // darkorange
-0x90325be5, 0x0d092000, 0x009932cc, // darkorchid
-0x90325c8b, 0x10000000, 0x008b0000, // darkred
-0x90325cc3, 0x31af7000, 0x00e9967a, // darksalmon
-0x90325ccb, 0x04f2295c, 0x008fbc8f, // darkseagreen
-0x90325cd9, 0x0685132b, 0x14000000, 0x00483d8b, // darkslateblue
-0x90325cd9, 0x06853c83, 0x64000000, 0x002f4f4f, // darkslategray
-0x90325d2b, 0x4a357a67, 0x14000000, 0x0000ced1, // darkturquoise
-0x90325d93, 0x3d85a000, 0x009400d3, // darkviolet
-0x90a58413, 0x39600000, 0x00ff1493, // deeppink
-0x90a584d7, 0x644ca940, 0x0000bfff, // deepskyblue
-0x912d3c83, 0x64000000, 0x00696969, // dimgray
-0x91e43965, 0x09952800, 0x001e90ff, // dodgerblue
-0x993228a5, 0x246b0000, 0x00b22222, // firebrick
-0x998f9059, 0x5d09a140, 0x00fffaf0, // floralwhite
-0x99f22ce9, 0x1e452b80, 0x00228b22, // forestgreen
-0x9aa344d3, 0x04000000, 0x00ff00ff, // fuchsia
-0x9c2974c5, 0x3e4f0000, 0x00dcdcdc, // gainsboro
-0x9d0f9d2f, 0x21342800, 0x00f8f8ff, // ghostwhite
-0x9dec2000, 0x00ffd700, // gold
-0x9dec215d, 0x49e40000, 0x00daa520, // goldenrod
-0x9e41c800, 0x00808080, // gray
-0x9e452b80, 0x00008000, // green
-0x9e452bb3, 0x158c7dc0, 0x00adff2f, // greenyellow
-0xa1ee2e49, 0x16e00000, 0x00f0fff0, // honeydew
-0xa1f4825d, 0x2c000000, 0x00ff69b4, // hotpink
-0xa5c4485d, 0x48a40000, 0x00cd5c5c, // indianred
-0xa5c449de, 0x004b0082, // indigo
-0xa6cf9640, 0x00fffff0, // ivory
-0xad015a40, 0x00f0e68c, // khaki
-0xb0362b89, 0x16400000, 0x00e6e6fa, // lavender
-0xb0362b89, 0x16426567, 0x20000000, 0x00fff0f5, // lavenderblush
-0xb03771e5, 0x14ae0000, 0x007cfc00, // lawngreen
-0xb0ad7b87, 0x212633dc, 0x00fffacd, // lemonchiffon
-0xb1274505, 0x32a50000, 0x00add8e6, // lightblue
-0xb1274507, 0x3e416000, 0x00f08080, // lightcoral
-0xb1274507, 0x642e0000, 0x00e0ffff, // lightcyan
-0xb127450f, 0x3d842ba5, 0x3c992b19, 0x3ee00000, 0x00fafad2, // lightgoldenrodyellow
-0xb127450f, 0x48a57000, 0x0090ee90, // lightgreen
-0xb127450f, 0x48b90000, 0x00d3d3d3, // lightgrey
-0xb1274521, 0x25cb0000, 0x00ffb6c1, // lightpink
-0xb1274527, 0x058d7b80, 0x00ffa07a, // lightsalmon
-0xb1274527, 0x1427914b, 0x38000000, 0x0020b2aa, // lightseagreen
-0xb1274527, 0x2f22654a, 0x0087cefa, // lightskyblue
-0xb1274527, 0x303429e5, 0x07200000, 0x00778899, // lightslategray
-0xb1274527, 0x50a56099, 0x54a00000, 0x00b0c4de, // lightsteelblue
-0xb1274533, 0x158c7dc0, 0x00ffffe0, // lightyellow
-0xb12d2800, 0x0000ff00, // lime
-0xb12d29e5, 0x14ae0000, 0x0032cd32, // limegreen
-0xb12e2b80, 0x00faf0e6, // linen
-0xb4272ba9, 0x04000000, 0x00ff00ff, // magenta
-0xb4327bdc, 0x00800000, // maroon
-0xb4a44d5b, 0x06350b43, 0x492e2800, 0x0066cdaa, // mediumaquamarine
-0xb4a44d5b, 0x09952800, 0x000000cd, // mediumblue
-0xb4a44d5b, 0x3e434248, 0x00ba55d3, // mediumorchid
-0xb4a44d5b, 0x42b2830a, 0x009370db, // mediumpurple
-0xb4a44d5b, 0x4ca13c8b, 0x15c00000, 0x003cb371, // mediumseagreen
-0xb4a44d5b, 0x4d81a145, 0x32a50000, 0x007b68ee, // mediumslateblue
-0xb4a44d5b, 0x4e124b8f, 0x1e452b80, 0x0000fa9a, // mediumspringgreen
-0xb4a44d5b, 0x52b28d5f, 0x26650000, 0x0048d1cc, // mediumturquoise
-0xb4a44d5b, 0x592f6169, 0x48a40000, 0x00c71585, // mediumvioletred
-0xb524724f, 0x2282654a, 0x00191970, // midnightblue
-0xb52ea0e5, 0x142d0000, 0x00f5fffa, // mintcream
-0xb533a665, 0x3e650000, 0x00ffe4e1, // mistyrose
-0xb5e31867, 0x25c00000, 0x00ffe4b5, // moccasin
-0xb8360a9f, 0x5d09a140, 0x00ffdead, // navajowhite
-0xb836c800, 0x00000080, // navy
-0xbd846047, 0x14000000, 0x00fdf5e6, // oldlace
-0xbd89b140, 0x00808000, // olive
-0xbd89b149, 0x48220000, 0x006b8e23, // olivedrab
-0xbe4171ca, 0x00ffa500, // orange
-0xbe4171cb, 0x48a40000, 0x00ff4500, // orangered
-0xbe434248, 0x00da70d6, // orchid
-0xc02c29df, 0x3085749f, 0x10000000, 0x00eee8aa, // palegoldenrod
-0xc02c29e5, 0x14ae0000, 0x0098fb98, // palegreen
-0xc02c2d2b, 0x4a357a67, 0x14000000, 0x00afeeee, // paleturquoise
-0xc02c2d93, 0x3d85a48b, 0x10000000, 0x00db7093, // palevioletred
-0xc0300e43, 0x5d098000, 0x00ffefd5, // papayawhip
-0xc0a11a21, 0x54c60000, 0x00ffdab9, // peachpuff
-0xc0b2a800, 0x00cd853f, // peru
-0xc12e5800, 0x00ffc0cb, // pink
-0xc1956800, 0x00dda0dd, // plum
-0xc1f72165, 0x09952800, 0x00b0e0e6, // powderblue
-0xc2b2830a, 0x00800080, // purple
-0xc8a40000, 0x00ff0000, // red
-0xc9f3c8a5, 0x3eee0000, 0x00bc8f8f, // rosybrown
-0xc9f90b05, 0x32a50000, 0x004169e1, // royalblue
-0xcc24230b, 0x0a4fbb80, 0x008b4513, // saddlebrown
-0xcc2c6bdc, 0x00fa8072, // salmon
-0xcc2e2645, 0x49f77000, 0x00f4a460, // sandybrown
-0xcca13c8b, 0x15c00000, 0x002e8b57, // seagreen
-0xcca19a0b, 0x31800000, 0x00fff5ee, // seashell
-0xcd257382, 0x00a0522d, // sienna
-0xcd2cb164, 0x00c0c0c0, // silver
-0xcd79132b, 0x14000000, 0x0087ceeb, // skyblue
-0xcd81a145, 0x32a50000, 0x006a5acd, // slateblue
-0xcd81a14f, 0x48390000, 0x00708090, // slategray
-0xcdcfb800, 0x00fffafa, // snow
-0xce124b8f, 0x1e452b80, 0x0000ff7f, // springgreen
-0xce852b05, 0x32a50000, 0x004682b4, // steelblue
-0xd02e0000, 0x00d2b48c, // tan
-0xd0a16000, 0x00008080, // teal
-0xd1099d19, 0x14000000, 0x00d8bfd8, // thistle
-0xd1ed0d1e, 0x00ff6347, // tomato
-0xd2b28d5f, 0x26650000, 0x0040e0d0, // turquoise
-0xd92f6168, 0x00ee82ee, // violet
-0xdd050d00, 0x00f5deb3, // wheat
-0xdd09a140, 0x00ffffff, // white
-0xdd09a167, 0x35eb2800, 0x00f5f5f5, // whitesmoke
-0xe4ac63ee, 0x00ffff00, // yellow
-0xe4ac63ef, 0x1e452b80, 0x009acd32 // yellowgreen
-}; // original = 2505 : replacement = 1616
+#pragma pack(push,1)
+static constexpr struct ColorRec {
+ const char* name;
+ uint8_t r, g, b;
+} gNamedColors[] = {
+ { "aliceblue", 0xf0,0xf8,0xff },
+ { "antiquewhite", 0xfa,0xeb,0xd7 },
+ { "aqua", 0x00,0xff,0xff },
+ { "aquamarine", 0x7f,0xff,0xd4 },
+ { "azure", 0xf0,0xff,0xff },
+ { "beige", 0xf5,0xf5,0xdc },
+ { "bisque", 0xff,0xe4,0xc4 },
+ { "black", 0x00,0x00,0x00 },
+ { "blanchedalmond", 0xff,0xeb,0xcd },
+ { "blue", 0x00,0x00,0xff },
+ { "blueviolet", 0x8a,0x2b,0xe2 },
+ { "brown", 0xa5,0x2a,0x2a },
+ { "burlywood", 0xde,0xb8,0x87 },
+ { "cadetblue", 0x5f,0x9e,0xa0 },
+ { "chartreuse", 0x7f,0xff,0x00 },
+ { "chocolate", 0xd2,0x69,0x1e },
+ { "coral", 0xff,0x7f,0x50 },
+ { "cornflowerblue", 0x64,0x95,0xed },
+ { "cornsilk", 0xff,0xf8,0xdc },
+ { "crimson", 0xdc,0x14,0x3c },
+ { "cyan", 0x00,0xff,0xff },
+ { "darkblue", 0x00,0x00,0x8b },
+ { "darkcyan", 0x00,0x8b,0x8b },
+ { "darkgoldenrod", 0xb8,0x86,0x0b },
+ { "darkgray", 0xa9,0xa9,0xa9 },
+ { "darkgreen", 0x00,0x64,0x00 },
+ { "darkkhaki", 0xbd,0xb7,0x6b },
+ { "darkmagenta", 0x8b,0x00,0x8b },
+ { "darkolivegreen", 0x55,0x6b,0x2f },
+ { "darkorange", 0xff,0x8c,0x00 },
+ { "darkorchid", 0x99,0x32,0xcc },
+ { "darkred", 0x8b,0x00,0x00 },
+ { "darksalmon", 0xe9,0x96,0x7a },
+ { "darkseagreen", 0x8f,0xbc,0x8f },
+ { "darkslateblue", 0x48,0x3d,0x8b },
+ { "darkslategray", 0x2f,0x4f,0x4f },
+ { "darkturquoise", 0x00,0xce,0xd1 },
+ { "darkviolet", 0x94,0x00,0xd3 },
+ { "deeppink", 0xff,0x14,0x93 },
+ { "deepskyblue", 0x00,0xbf,0xff },
+ { "dimgray", 0x69,0x69,0x69 },
+ { "dodgerblue", 0x1e,0x90,0xff },
+ { "firebrick", 0xb2,0x22,0x22 },
+ { "floralwhite", 0xff,0xfa,0xf0 },
+ { "forestgreen", 0x22,0x8b,0x22 },
+ { "fuchsia", 0xff,0x00,0xff },
+ { "gainsboro", 0xdc,0xdc,0xdc },
+ { "ghostwhite", 0xf8,0xf8,0xff },
+ { "gold", 0xff,0xd7,0x00 },
+ { "goldenrod", 0xda,0xa5,0x20 },
+ { "gray", 0x80,0x80,0x80 },
+ { "green", 0x00,0x80,0x00 },
+ { "greenyellow", 0xad,0xff,0x2f },
+ { "honeydew", 0xf0,0xff,0xf0 },
+ { "hotpink", 0xff,0x69,0xb4 },
+ { "indianred", 0xcd,0x5c,0x5c },
+ { "indigo", 0x4b,0x00,0x82 },
+ { "ivory", 0xff,0xff,0xf0 },
+ { "khaki", 0xf0,0xe6,0x8c },
+ { "lavender", 0xe6,0xe6,0xfa },
+ { "lavenderblush", 0xff,0xf0,0xf5 },
+ { "lawngreen", 0x7c,0xfc,0x00 },
+ { "lemonchiffon", 0xff,0xfa,0xcd },
+ { "lightblue", 0xad,0xd8,0xe6 },
+ { "lightcoral", 0xf0,0x80,0x80 },
+ { "lightcyan", 0xe0,0xff,0xff },
+ { "lightgoldenrodyellow", 0xfa,0xfa,0xd2 },
+ { "lightgreen", 0x90,0xee,0x90 },
+ { "lightgrey", 0xd3,0xd3,0xd3 },
+ { "lightpink", 0xff,0xb6,0xc1 },
+ { "lightsalmon", 0xff,0xa0,0x7a },
+ { "lightseagreen", 0x20,0xb2,0xaa },
+ { "lightskyblue", 0x87,0xce,0xfa },
+ { "lightslategray", 0x77,0x88,0x99 },
+ { "lightsteelblue", 0xb0,0xc4,0xde },
+ { "lightyellow", 0xff,0xff,0xe0 },
+ { "lime", 0x00,0xff,0x00 },
+ { "limegreen", 0x32,0xcd,0x32 },
+ { "linen", 0xfa,0xf0,0xe6 },
+ { "magenta", 0xff,0x00,0xff },
+ { "maroon", 0x80,0x00,0x00 },
+ { "mediumaquamarine", 0x66,0xcd,0xaa },
+ { "mediumblue", 0x00,0x00,0xcd },
+ { "mediumorchid", 0xba,0x55,0xd3 },
+ { "mediumpurple", 0x93,0x70,0xdb },
+ { "mediumseagreen", 0x3c,0xb3,0x71 },
+ { "mediumslateblue", 0x7b,0x68,0xee },
+ { "mediumspringgreen", 0x00,0xfa,0x9a },
+ { "mediumturquoise", 0x48,0xd1,0xcc },
+ { "mediumvioletred", 0xc7,0x15,0x85 },
+ { "midnightblue", 0x19,0x19,0x70 },
+ { "mintcream", 0xf5,0xff,0xfa },
+ { "mistyrose", 0xff,0xe4,0xe1 },
+ { "moccasin", 0xff,0xe4,0xb5 },
+ { "navajowhite", 0xff,0xde,0xad },
+ { "navy", 0x00,0x00,0x80 },
+ { "oldlace", 0xfd,0xf5,0xe6 },
+ { "olive", 0x80,0x80,0x00 },
+ { "olivedrab", 0x6b,0x8e,0x23 },
+ { "orange", 0xff,0xa5,0x00 },
+ { "orangered", 0xff,0x45,0x00 },
+ { "orchid", 0xda,0x70,0xd6 },
+ { "palegoldenrod", 0xee,0xe8,0xaa },
+ { "palegreen", 0x98,0xfb,0x98 },
+ { "paleturquoise", 0xaf,0xee,0xee },
+ { "palevioletred", 0xdb,0x70,0x93 },
+ { "papayawhip", 0xff,0xef,0xd5 },
+ { "peachpuff", 0xff,0xda,0xb9 },
+ { "peru", 0xcd,0x85,0x3f },
+ { "pink", 0xff,0xc0,0xcb },
+ { "plum", 0xdd,0xa0,0xdd },
+ { "powderblue", 0xb0,0xe0,0xe6 },
+ { "purple", 0x80,0x00,0x80 },
+ { "red", 0xff,0x00,0x00 },
+ { "rosybrown", 0xbc,0x8f,0x8f },
+ { "royalblue", 0x41,0x69,0xe1 },
+ { "saddlebrown", 0x8b,0x45,0x13 },
+ { "salmon", 0xfa,0x80,0x72 },
+ { "sandybrown", 0xf4,0xa4,0x60 },
+ { "seagreen", 0x2e,0x8b,0x57 },
+ { "seashell", 0xff,0xf5,0xee },
+ { "sienna", 0xa0,0x52,0x2d },
+ { "silver", 0xc0,0xc0,0xc0 },
+ { "skyblue", 0x87,0xce,0xeb },
+ { "slateblue", 0x6a,0x5a,0xcd },
+ { "slategray", 0x70,0x80,0x90 },
+ { "snow", 0xff,0xfa,0xfa },
+ { "springgreen", 0x00,0xff,0x7f },
+ { "steelblue", 0x46,0x82,0xb4 },
+ { "tan", 0xd2,0xb4,0x8c },
+ { "teal", 0x00,0x80,0x80 },
+ { "thistle", 0xd8,0xbf,0xd8 },
+ { "tomato", 0xff,0x63,0x47 },
+ { "turquoise", 0x40,0xe0,0xd0 },
+ { "violet", 0xee,0x82,0xee },
+ { "wheat", 0xf5,0xde,0xb3 },
+ { "white", 0xff,0xff,0xff },
+ { "whitesmoke", 0xf5,0xf5,0xf5 },
+ { "yellow", 0xff,0xff,0x00 },
+ { "yellowgreen", 0x9a,0xcd,0x32 },
+};
+#pragma pack(pop)
const char* SkParse::FindNamedColor(const char* name, size_t len, SkColor* color) {
- const char* namePtr = name;
- unsigned int sixMatches[4];
- unsigned int* sixMatchPtr = sixMatches;
- bool first = true;
- bool last = false;
- char ch;
- do {
- unsigned int sixMatch = 0;
- for (int chIndex = 0; chIndex < 6; chIndex++) {
- sixMatch <<= 5;
- ch = *namePtr | 0x20;
- if (ch < 'a' || ch > 'z')
- ch = 0;
- else {
- ch = ch - 'a' + 1;
- namePtr++;
- }
- sixMatch |= ch ; // turn 'A' (0x41) into 'a' (0x61);
- }
- sixMatch <<= 1;
- sixMatch |= 1;
- if (first) {
- sixMatch |= 0x80000000;
- first = false;
- }
- ch = *namePtr | 0x20;
- last = ch < 'a' || ch > 'z';
- if (last)
- sixMatch &= ~1;
- len -= 6;
- *sixMatchPtr++ = sixMatch;
- } while (last == false && len > 0);
- const int colorNameSize = sizeof(gColorNames) / sizeof(unsigned int);
- int lo = 0;
- int hi = colorNameSize - 3; // back off to beginning of yellowgreen
- while (lo <= hi) {
- int mid = (hi + lo) >> 1;
- while ((int) gColorNames[mid] >= 0)
- --mid;
- sixMatchPtr = sixMatches;
- while (gColorNames[mid] == *sixMatchPtr) {
- ++mid;
- if ((*sixMatchPtr & 1) == 0) { // last
- *color = gColorNames[mid] | 0xFF000000;
- return namePtr;
- }
- ++sixMatchPtr;
- }
- int sixMask = *sixMatchPtr & ~0x80000000;
- int midMask = gColorNames[mid] & ~0x80000000;
- if (sixMask > midMask) {
- lo = mid + 2; // skip color
- while ((int) gColorNames[lo] >= 0)
- ++lo;
- } else if (hi == mid)
- return nullptr;
- else
- hi = mid;
+ const auto* rec = std::lower_bound(std::begin(gNamedColors),
+ std::end (gNamedColors),
+ ColorRec{name, 0,0,0}, // key
+ [](const ColorRec& rec, const ColorRec& key) {
+ return strcmp(rec.name, key.name) < 0;
+ });
+
+ if (rec == std::end(gNamedColors) || strcmp(name, rec->name)) {
+ return nullptr;
+ }
+
+ if (color) {
+ *color = SkColorSetRGB(rec->r, rec->g, rec->b);
}
- return nullptr;
+
+ return name + strlen(rec->name);
}
// !!! move to char utilities
diff --git a/chromium/third_party/skia/src/utils/SkParsePath.cpp b/chromium/third_party/skia/src/utils/SkParsePath.cpp
index 688daae33b1..31a912ca476 100644
--- a/chromium/third_party/skia/src/utils/SkParsePath.cpp
+++ b/chromium/third_party/skia/src/utils/SkParsePath.cpp
@@ -92,7 +92,7 @@ bool SkParsePath::FromSVGString(const char data[], SkPath* result) {
}
char ch = data[0];
if (is_digit(ch) || ch == '-' || ch == '+' || ch == '.') {
- if (op == '\0') {
+ if (op == '\0' || op == 'Z') {
return false;
}
} else if (is_sep(ch)) {
diff --git a/chromium/third_party/skia/src/utils/SkShadowUtils.cpp b/chromium/third_party/skia/src/utils/SkShadowUtils.cpp
index 869997f7b34..4691b3fef26 100644
--- a/chromium/third_party/skia/src/utils/SkShadowUtils.cpp
+++ b/chromium/third_party/skia/src/utils/SkShadowUtils.cpp
@@ -17,6 +17,7 @@
#include "include/private/SkIDChangeListener.h"
#include "include/utils/SkRandom.h"
#include "src/core/SkBlurMask.h"
+#include "src/core/SkColorFilterBase.h"
#include "src/core/SkColorFilterPriv.h"
#include "src/core/SkDevice.h"
#include "src/core/SkDrawShadowInfo.h"
@@ -40,7 +41,7 @@
* Final result is black with alpha of Gaussian(B)*G.
* The assumption is that the original color's alpha is 1.
*/
-class SkGaussianColorFilter : public SkColorFilter {
+class SkGaussianColorFilter : public SkColorFilterBase {
public:
SkGaussianColorFilter() : INHERITED() {}
@@ -73,7 +74,7 @@ protected:
private:
SK_FLATTENABLE_HOOKS(SkGaussianColorFilter)
- typedef SkColorFilter INHERITED;
+ typedef SkColorFilterBase INHERITED;
};
sk_sp<SkFlattenable> SkGaussianColorFilter::CreateProc(SkReadBuffer&) {
@@ -84,7 +85,8 @@ sk_sp<SkFlattenable> SkGaussianColorFilter::CreateProc(SkReadBuffer&) {
std::unique_ptr<GrFragmentProcessor> SkGaussianColorFilter::asFragmentProcessor(
GrRecordingContext*, const GrColorInfo&) const {
- return GrBlurredEdgeFragmentProcessor::Make(GrBlurredEdgeFragmentProcessor::Mode::kGaussian);
+ return GrBlurredEdgeFragmentProcessor::Make(
+ /*inputFP=*/nullptr, GrBlurredEdgeFragmentProcessor::Mode::kGaussian);
}
#endif
@@ -594,8 +596,7 @@ void SkBaseDevice::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) {
SkAutoDeviceTransformRestore adr(
this,
hasPerspective ? SkMatrix::I()
- : SkMatrix::Concat(this->localToDevice(),
- SkMatrix::MakeTrans(tx, ty)));
+ : this->localToDevice() * SkMatrix::Translate(tx, ty));
this->drawVertices(vertices, mode, paint);
}
};
diff --git a/chromium/third_party/skia/src/utils/mac/SkCGBase.h b/chromium/third_party/skia/src/utils/mac/SkCGBase.h
new file mode 100644
index 00000000000..a7b0ed06d05
--- /dev/null
+++ b/chromium/third_party/skia/src/utils/mac/SkCGBase.h
@@ -0,0 +1,37 @@
+/*
+ * 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 SkCGBase_DEFINED
+#define SkCGBase_DEFINED
+
+#include "include/core/SkTypes.h"
+#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+
+#ifdef SK_BUILD_FOR_MAC
+#import <ApplicationServices/ApplicationServices.h>
+#endif
+
+#ifdef SK_BUILD_FOR_IOS
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+// Skia extensions for types in CGBase.h
+
+static inline CGFloat SkScalarToCGFloat(SkScalar scalar) {
+ return CGFLOAT_IS_DOUBLE ? SkScalarToDouble(scalar) : SkScalarToFloat(scalar);
+}
+
+static inline SkScalar SkScalarFromCGFloat(CGFloat cgFloat) {
+ return CGFLOAT_IS_DOUBLE ? SkDoubleToScalar(cgFloat) : SkFloatToScalar(cgFloat);
+}
+
+static inline float SkFloatFromCGFloat(CGFloat cgFloat) {
+ return CGFLOAT_IS_DOUBLE ? static_cast<float>(cgFloat) : cgFloat;
+}
+
+#endif
+#endif //SkCGBase_DEFINED
diff --git a/chromium/third_party/skia/src/utils/mac/SkCGGeometry.h b/chromium/third_party/skia/src/utils/mac/SkCGGeometry.h
new file mode 100644
index 00000000000..04b1263bcd5
--- /dev/null
+++ b/chromium/third_party/skia/src/utils/mac/SkCGGeometry.h
@@ -0,0 +1,52 @@
+/*
+ * 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 SkCGGeometry_DEFINED
+#define SkCGGeometry_DEFINED
+
+#include "include/core/SkTypes.h"
+#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+
+#ifdef SK_BUILD_FOR_MAC
+#import <ApplicationServices/ApplicationServices.h>
+#endif
+
+#ifdef SK_BUILD_FOR_IOS
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+// Skia extensions for types in CGGeometry.h
+
+// Inline versions of these CGRect helpers.
+// The CG versions require making a call and a copy of the CGRect on the stack.
+
+static inline bool SkCGRectIsEmpty(const CGRect& rect) {
+ return rect.size.width <= 0 || rect.size.height <= 0;
+}
+
+static inline CGFloat SkCGRectGetMinX(const CGRect& rect) {
+ return rect.origin.x;
+}
+
+static inline CGFloat SkCGRectGetMaxX(const CGRect& rect) {
+ return rect.origin.x + rect.size.width;
+}
+
+static inline CGFloat SkCGRectGetMinY(const CGRect& rect) {
+ return rect.origin.y;
+}
+
+static inline CGFloat SkCGRectGetMaxY(const CGRect& rect) {
+ return rect.origin.y + rect.size.height;
+}
+
+static inline CGFloat SkCGRectGetWidth(const CGRect& rect) {
+ return rect.size.width;
+}
+
+#endif
+#endif //SkCGGeometry_DEFINED
diff --git a/chromium/third_party/skia/src/utils/mac/SkCTFontSmoothBehavior.cpp b/chromium/third_party/skia/src/utils/mac/SkCTFontSmoothBehavior.cpp
new file mode 100644
index 00000000000..da516874596
--- /dev/null
+++ b/chromium/third_party/skia/src/utils/mac/SkCTFontSmoothBehavior.cpp
@@ -0,0 +1,271 @@
+/*
+ * 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 "include/core/SkTypes.h"
+
+#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+
+#include "src/utils/mac/SkCTFontSmoothBehavior.h"
+#include "src/utils/mac/SkUniqueCFRef.h"
+
+#ifdef SK_BUILD_FOR_MAC
+#import <ApplicationServices/ApplicationServices.h>
+#endif
+
+#ifdef SK_BUILD_FOR_IOS
+#include <CoreText/CoreText.h>
+#include <CoreText/CTFontManager.h>
+#include <CoreGraphics/CoreGraphics.h>
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+static constexpr CGBitmapInfo kBitmapInfoRGB = ((CGBitmapInfo)kCGImageAlphaNoneSkipFirst |
+ kCGBitmapByteOrder32Host);
+
+/** Drawn in FontForge, reduced with fonttools ttx, converted by xxd -i,
+ * this TrueType font contains a glyph of the spider.
+ *
+ * To re-forge the original bytes of the TrueType font file,
+ * remove all ',|( +0x)' from this definition,
+ * copy the data to the clipboard,
+ * run 'pbpaste | xxd -p -r - spider.ttf'.
+ */
+static constexpr const uint8_t kSpiderSymbol_ttf[] = {
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x80, 0x00, 0x03, 0x00, 0x40,
+ 0x47, 0x44, 0x45, 0x46, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x07, 0xa8,
+ 0x00, 0x00, 0x00, 0x18, 0x4f, 0x53, 0x2f, 0x32, 0x8a, 0xf4, 0xfb, 0xdb,
+ 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x00, 0x60, 0x63, 0x6d, 0x61, 0x70,
+ 0xe0, 0x7f, 0x10, 0x7e, 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x54,
+ 0x67, 0x61, 0x73, 0x70, 0xff, 0xff, 0x00, 0x03, 0x00, 0x00, 0x07, 0xa0,
+ 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0x97, 0x0b, 0x6a, 0xf6,
+ 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x03, 0x40, 0x68, 0x65, 0x61, 0x64,
+ 0x0f, 0xa2, 0x24, 0x1a, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x36,
+ 0x68, 0x68, 0x65, 0x61, 0x0e, 0xd3, 0x07, 0x3f, 0x00, 0x00, 0x01, 0x04,
+ 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78, 0x10, 0x03, 0x00, 0x44,
+ 0x00, 0x00, 0x01, 0xa8, 0x00, 0x00, 0x00, 0x0e, 0x6c, 0x6f, 0x63, 0x61,
+ 0x01, 0xb4, 0x00, 0x28, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x0a,
+ 0x6d, 0x61, 0x78, 0x70, 0x00, 0x4a, 0x01, 0x4d, 0x00, 0x00, 0x01, 0x28,
+ 0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0xc3, 0xe5, 0x39, 0xd4,
+ 0x00, 0x00, 0x05, 0x58, 0x00, 0x00, 0x02, 0x28, 0x70, 0x6f, 0x73, 0x74,
+ 0xff, 0x03, 0x00, 0x67, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x0f, 0x08, 0x1d,
+ 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xd1, 0x97, 0xa8, 0x5a, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xe8, 0x32, 0x33,
+ 0x00, 0x03, 0xff, 0x3b, 0x08, 0x00, 0x05, 0x55, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x05, 0x55, 0xff, 0x3b, 0x01, 0x79, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x04, 0x01, 0x1c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x2e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x01, 0x90, 0x00, 0x05,
+ 0x00, 0x00, 0x05, 0x33, 0x05, 0x99, 0x00, 0x00, 0x01, 0x1e, 0x05, 0x33,
+ 0x05, 0x99, 0x00, 0x00, 0x03, 0xd7, 0x00, 0x66, 0x02, 0x12, 0x00, 0x00,
+ 0x05, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x73, 0x6b, 0x69, 0x61, 0x00, 0xc0, 0x00, 0x00, 0xf0, 0x21,
+ 0x06, 0x66, 0xfe, 0x66, 0x01, 0x79, 0x05, 0x55, 0x00, 0xc5, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x01, 0x08, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x48,
+ 0x00, 0x00, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x09, 0x00, 0x0d, 0x00, 0x1d, 0x00, 0x21, 0xf0, 0x21, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00, 0x1d, 0x00, 0x21,
+ 0xf0, 0x21, 0xff, 0xff, 0x00, 0x01, 0xff, 0xf9, 0xff, 0xf5, 0xff, 0xe4,
+ 0xff, 0xe2, 0x0f, 0xe2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14,
+ 0x00, 0x14, 0x00, 0x14, 0x01, 0xa0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x44,
+ 0x00, 0x00, 0x02, 0x64, 0x05, 0x55, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00,
+ 0x33, 0x11, 0x21, 0x11, 0x25, 0x21, 0x11, 0x21, 0x44, 0x02, 0x20, 0xfe,
+ 0x24, 0x01, 0x98, 0xfe, 0x68, 0x05, 0x55, 0xfa, 0xab, 0x44, 0x04, 0xcd,
+ 0x00, 0x04, 0x00, 0x03, 0xff, 0x3b, 0x08, 0x00, 0x05, 0x4c, 0x00, 0x15,
+ 0x00, 0x1d, 0x00, 0x25, 0x01, 0x1b, 0x00, 0x00, 0x01, 0x36, 0x37, 0x36,
+ 0x27, 0x26, 0x07, 0x06, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27, 0x26, 0x07,
+ 0x06, 0x17, 0x16, 0x17, 0x16, 0x32, 0x37, 0x32, 0x35, 0x34, 0x23, 0x22,
+ 0x15, 0x14, 0x27, 0x32, 0x35, 0x34, 0x23, 0x22, 0x15, 0x14, 0x03, 0x32,
+ 0x17, 0x30, 0x17, 0x31, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33,
+ 0x32, 0x33, 0x16, 0x33, 0x32, 0x17, 0x16, 0x07, 0x06, 0x23, 0x22, 0x27,
+ 0x26, 0x27, 0x26, 0x23, 0x22, 0x07, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06,
+ 0x1f, 0x02, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32, 0x17, 0x17, 0x16, 0x33,
+ 0x16, 0x17, 0x16, 0x07, 0x06, 0x23, 0x22, 0x27, 0x27, 0x26, 0x23, 0x22,
+ 0x07, 0x06, 0x07, 0x06, 0x17, 0x16, 0x17, 0x16, 0x33, 0x32, 0x33, 0x32,
+ 0x37, 0x36, 0x37, 0x36, 0x17, 0x16, 0x1f, 0x02, 0x16, 0x17, 0x16, 0x15,
+ 0x14, 0x23, 0x22, 0x27, 0x27, 0x26, 0x27, 0x27, 0x26, 0x27, 0x26, 0x07,
+ 0x06, 0x07, 0x06, 0x17, 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x07,
+ 0x06, 0x23, 0x22, 0x27, 0x26, 0x07, 0x06, 0x07, 0x06, 0x15, 0x14, 0x17,
+ 0x16, 0x17, 0x16, 0x15, 0x14, 0x07, 0x06, 0x23, 0x22, 0x27, 0x26, 0x27,
+ 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x34, 0x27, 0x26, 0x07,
+ 0x06, 0x07, 0x06, 0x0f, 0x02, 0x06, 0x23, 0x22, 0x27, 0x26, 0x35, 0x34,
+ 0x37, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x27, 0x26, 0x27,
+ 0x26, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x07, 0x06, 0x23, 0x22,
+ 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x37, 0x36, 0x37, 0x37, 0x36,
+ 0x37, 0x36, 0x37, 0x36, 0x35, 0x34, 0x27, 0x26, 0x27, 0x26, 0x27, 0x26,
+ 0x23, 0x22, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x27, 0x26, 0x27, 0x26,
+ 0x27, 0x26, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36, 0x37, 0x36, 0x33, 0x32,
+ 0x17, 0x16, 0x33, 0x32, 0x37, 0x36, 0x35, 0x34, 0x37, 0x36, 0x37, 0x36,
+ 0x33, 0x04, 0xf5, 0x23, 0x13, 0x11, 0x14, 0x16, 0x1d, 0x1b, 0x4c, 0x1f,
+ 0x0e, 0x2d, 0x23, 0x14, 0x2c, 0x13, 0x18, 0x25, 0x2c, 0x10, 0x3c, 0x71,
+ 0x1d, 0x5c, 0x5c, 0x3f, 0xae, 0x5c, 0x5c, 0x3f, 0x6a, 0x27, 0x31, 0x5b,
+ 0x09, 0x27, 0x36, 0x03, 0x0a, 0x26, 0x35, 0x2e, 0x09, 0x08, 0xc6, 0x13,
+ 0x81, 0x17, 0x20, 0x18, 0x21, 0x1e, 0x04, 0x04, 0x15, 0x5c, 0x22, 0x26,
+ 0x48, 0x56, 0x3b, 0x10, 0x21, 0x01, 0x0c, 0x06, 0x06, 0x0f, 0x31, 0x44,
+ 0x3c, 0x52, 0x4a, 0x1d, 0x11, 0x3f, 0xb4, 0x71, 0x01, 0x26, 0x06, 0x0d,
+ 0x15, 0x1a, 0x2a, 0x13, 0x53, 0xaa, 0x42, 0x1d, 0x0a, 0x33, 0x20, 0x21,
+ 0x2b, 0x01, 0x02, 0x3e, 0x21, 0x09, 0x02, 0x02, 0x0f, 0x2d, 0x4b, 0x0a,
+ 0x22, 0x15, 0x20, 0x1f, 0x72, 0x8b, 0x2d, 0x2f, 0x1d, 0x1f, 0x0e, 0x25,
+ 0x3f, 0x4d, 0x1b, 0x63, 0x2a, 0x2c, 0x14, 0x22, 0x18, 0x1c, 0x0f, 0x08,
+ 0x2a, 0x08, 0x08, 0x0d, 0x3b, 0x4c, 0x52, 0x74, 0x27, 0x71, 0x2e, 0x01,
+ 0x0c, 0x10, 0x15, 0x0d, 0x06, 0x0d, 0x05, 0x01, 0x06, 0x2c, 0x28, 0x14,
+ 0x1b, 0x05, 0x04, 0x10, 0x06, 0x12, 0x08, 0x0a, 0x16, 0x27, 0x03, 0x0d,
+ 0x30, 0x4c, 0x4c, 0x4b, 0x1f, 0x0b, 0x22, 0x26, 0x0d, 0x15, 0x0d, 0x2d,
+ 0x68, 0x34, 0x14, 0x3c, 0x25, 0x12, 0x04, 0x10, 0x18, 0x0b, 0x09, 0x30,
+ 0x2b, 0x44, 0x66, 0x14, 0x47, 0x47, 0x59, 0x73, 0x25, 0x05, 0x03, 0x1f,
+ 0x01, 0x08, 0x3f, 0x48, 0x4b, 0x4b, 0x76, 0x2f, 0x49, 0x2d, 0x22, 0x24,
+ 0x0c, 0x15, 0x08, 0x0e, 0x33, 0x03, 0x44, 0x4c, 0x10, 0x46, 0x13, 0x1f,
+ 0x27, 0x1b, 0x1d, 0x13, 0x02, 0x24, 0x08, 0x02, 0x42, 0x0e, 0x4d, 0x3c,
+ 0x19, 0x1b, 0x40, 0x2b, 0x2b, 0x1e, 0x16, 0x11, 0x04, 0x1f, 0x11, 0x04,
+ 0x18, 0x11, 0x35, 0x01, 0xa3, 0x13, 0x24, 0x1f, 0x0b, 0x0c, 0x19, 0x19,
+ 0x18, 0x13, 0x0f, 0x0c, 0x1a, 0x18, 0x1f, 0x19, 0x1e, 0x07, 0x1a, 0xc3,
+ 0x54, 0x51, 0x54, 0x51, 0x04, 0x53, 0x51, 0x54, 0x50, 0x02, 0x48, 0x1a,
+ 0x31, 0x18, 0x55, 0x74, 0x04, 0x0e, 0x09, 0x0d, 0x06, 0x10, 0x16, 0x1b,
+ 0x24, 0x01, 0x04, 0x0b, 0x04, 0x10, 0x3f, 0x0a, 0x41, 0x02, 0x41, 0x20,
+ 0x06, 0x12, 0x16, 0x21, 0x17, 0x2a, 0x1e, 0x15, 0x40, 0x27, 0x11, 0x0e,
+ 0x1e, 0x11, 0x15, 0x1f, 0x43, 0x13, 0x1a, 0x10, 0x15, 0x1b, 0x04, 0x09,
+ 0x4d, 0x2a, 0x0f, 0x19, 0x0a, 0x0a, 0x03, 0x05, 0x15, 0x3c, 0x64, 0x21,
+ 0x4b, 0x2e, 0x21, 0x28, 0x13, 0x47, 0x44, 0x19, 0x3f, 0x11, 0x18, 0x0b,
+ 0x0a, 0x07, 0x18, 0x0d, 0x07, 0x24, 0x2c, 0x2b, 0x21, 0x32, 0x10, 0x48,
+ 0x2a, 0x2d, 0x1e, 0x1a, 0x01, 0x0c, 0x43, 0x59, 0x28, 0x4e, 0x1c, 0x0d,
+ 0x5d, 0x24, 0x14, 0x0a, 0x05, 0x1f, 0x24, 0x32, 0x46, 0x3e, 0x5f, 0x3e,
+ 0x44, 0x1a, 0x30, 0x15, 0x0d, 0x07, 0x18, 0x2b, 0x03, 0x0d, 0x1a, 0x28,
+ 0x28, 0x57, 0xb2, 0x29, 0x27, 0x40, 0x2c, 0x23, 0x16, 0x63, 0x58, 0x1a,
+ 0x0a, 0x18, 0x11, 0x23, 0x08, 0x1b, 0x29, 0x05, 0x04, 0x0b, 0x15, 0x0d,
+ 0x14, 0x0b, 0x2a, 0x29, 0x5a, 0x62, 0x01, 0x19, 0x1e, 0x05, 0x05, 0x26,
+ 0x42, 0x42, 0x2a, 0x2a, 0x3f, 0x0d, 0x0f, 0x09, 0x05, 0x07, 0x01, 0x0b,
+ 0x25, 0x3e, 0x0d, 0x17, 0x11, 0x01, 0x03, 0x0d, 0x13, 0x20, 0x19, 0x11,
+ 0x03, 0x02, 0x01, 0x04, 0x11, 0x04, 0x05, 0x1b, 0x3d, 0x10, 0x29, 0x20,
+ 0x04, 0x04, 0x0a, 0x07, 0x04, 0x1f, 0x15, 0x20, 0x3e, 0x0f, 0x2a, 0x1e,
+ 0x00, 0x00, 0x00, 0x1b, 0x01, 0x4a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x07, 0x00, 0x27, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x02, 0x00, 0x2e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x00, 0x0c, 0x00, 0x1b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0d, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0e, 0x00, 0x1a, 0x00, 0x30, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
+ 0x00, 0x00, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
+ 0x00, 0x01, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
+ 0x00, 0x02, 0x00, 0x0e, 0x00, 0x98, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
+ 0x00, 0x03, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
+ 0x00, 0x04, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
+ 0x00, 0x05, 0x00, 0x04, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
+ 0x00, 0x06, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
+ 0x00, 0x0d, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x00, 0x04, 0x09,
+ 0x00, 0x0e, 0x00, 0x34, 0x00, 0xaa, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
+ 0x00, 0x00, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
+ 0x00, 0x01, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
+ 0x00, 0x02, 0x00, 0x0e, 0x00, 0x98, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
+ 0x00, 0x03, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
+ 0x00, 0x04, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
+ 0x00, 0x05, 0x00, 0x04, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
+ 0x00, 0x06, 0x00, 0x18, 0x00, 0x80, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
+ 0x00, 0x0d, 0x00, 0x36, 0x00, 0x4a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
+ 0x00, 0x0e, 0x00, 0x34, 0x00, 0xaa, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x31, 0x35,
+ 0x2c, 0x20, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x53, 0x70, 0x69,
+ 0x64, 0x65, 0x72, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x52, 0x65, 0x67,
+ 0x75, 0x6c, 0x61, 0x72, 0x56, 0x31, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x2e, 0x73, 0x69, 0x6c,
+ 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x4f, 0x46, 0x4c, 0x00, 0x43, 0x00, 0x6f,
+ 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68,
+ 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x63, 0x00, 0x29, 0x00, 0x20,
+ 0x00, 0x32, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x2c, 0x00, 0x20,
+ 0x00, 0x47, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x6c, 0x00, 0x65,
+ 0x00, 0x2e, 0x00, 0x53, 0x00, 0x70, 0x00, 0x69, 0x00, 0x64, 0x00, 0x65,
+ 0x00, 0x72, 0x00, 0x53, 0x00, 0x79, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x6f,
+ 0x00, 0x6c, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c,
+ 0x00, 0x61, 0x00, 0x72, 0x00, 0x56, 0x00, 0x31, 0x00, 0x68, 0x00, 0x74,
+ 0x00, 0x74, 0x00, 0x70, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x73,
+ 0x00, 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x73,
+ 0x00, 0x2e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x2e, 0x00, 0x6f,
+ 0x00, 0x72, 0x00, 0x67, 0x00, 0x2f, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x4c,
+ 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x66,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0xff, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00
+};
+
+/**
+ * There does not appear to be a publicly accessible API for determining if lcd
+ * font smoothing will be applied if we request it. The main issue is that if
+ * smoothing is applied a gamma of 2.0 will be used, if not a gamma of 1.0.
+ */
+SkCTFontSmoothBehavior SkCTFontGetSmoothBehavior() {
+ static SkCTFontSmoothBehavior gSmoothBehavior = []{
+ uint32_t noSmoothBitmap[16][16] = {};
+ uint32_t smoothBitmap[16][16] = {};
+
+ SkUniqueCFRef<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB());
+ SkUniqueCFRef<CGContextRef> noSmoothContext(
+ CGBitmapContextCreate(&noSmoothBitmap, 16, 16, 8, 16*4,
+ colorspace.get(), kBitmapInfoRGB));
+ SkUniqueCFRef<CGContextRef> smoothContext(
+ CGBitmapContextCreate(&smoothBitmap, 16, 16, 8, 16*4,
+ colorspace.get(), kBitmapInfoRGB));
+
+ SkUniqueCFRef<CFDataRef> data(CFDataCreateWithBytesNoCopy(
+ kCFAllocatorDefault, kSpiderSymbol_ttf, SK_ARRAY_COUNT(kSpiderSymbol_ttf),
+ kCFAllocatorNull));
+ SkUniqueCFRef<CTFontDescriptorRef> desc(
+ CTFontManagerCreateFontDescriptorFromData(data.get()));
+ SkUniqueCFRef<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc.get(), 16, nullptr));
+ SkASSERT(ctFont);
+
+ CGContextSetShouldSmoothFonts(noSmoothContext.get(), false);
+ CGContextSetShouldAntialias(noSmoothContext.get(), true);
+ CGContextSetTextDrawingMode(noSmoothContext.get(), kCGTextFill);
+ CGContextSetGrayFillColor(noSmoothContext.get(), 1, 1);
+
+ CGContextSetShouldSmoothFonts(smoothContext.get(), true);
+ CGContextSetShouldAntialias(smoothContext.get(), true);
+ CGContextSetTextDrawingMode(smoothContext.get(), kCGTextFill);
+ CGContextSetGrayFillColor(smoothContext.get(), 1, 1);
+
+ CGPoint point = CGPointMake(0, 3);
+ CGGlyph spiderGlyph = 3;
+ CTFontDrawGlyphs(ctFont.get(), &spiderGlyph, &point, 1, noSmoothContext.get());
+ CTFontDrawGlyphs(ctFont.get(), &spiderGlyph, &point, 1, smoothContext.get());
+
+ // For debugging.
+ //SkUniqueCFRef<CGImageRef> image(CGBitmapContextCreateImage(noSmoothContext()));
+ //SkUniqueCFRef<CGImageRef> image(CGBitmapContextCreateImage(smoothContext()));
+
+ SkCTFontSmoothBehavior smoothBehavior = SkCTFontSmoothBehavior::none;
+ for (int x = 0; x < 16; ++x) {
+ for (int y = 0; y < 16; ++y) {
+ uint32_t smoothPixel = smoothBitmap[x][y];
+ uint32_t r = (smoothPixel >> 16) & 0xFF;
+ uint32_t g = (smoothPixel >> 8) & 0xFF;
+ uint32_t b = (smoothPixel >> 0) & 0xFF;
+ if (r != g || r != b) {
+ return SkCTFontSmoothBehavior::subpixel;
+ }
+ if (noSmoothBitmap[x][y] != smoothPixel) {
+ smoothBehavior = SkCTFontSmoothBehavior::some;
+ }
+ }
+ }
+ return smoothBehavior;
+ }();
+ return gSmoothBehavior;
+}
+
+#endif
diff --git a/chromium/third_party/skia/src/utils/mac/SkCTFontSmoothBehavior.h b/chromium/third_party/skia/src/utils/mac/SkCTFontSmoothBehavior.h
new file mode 100644
index 00000000000..126cdb3ab2d
--- /dev/null
+++ b/chromium/third_party/skia/src/utils/mac/SkCTFontSmoothBehavior.h
@@ -0,0 +1,23 @@
+/*
+ * 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 SkCTFontSmoothBehavior_DEFINED
+#define SkCTFontSmoothBehavior_DEFINED
+
+#include "include/core/SkTypes.h"
+#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+
+enum class SkCTFontSmoothBehavior {
+ none, // SmoothFonts produces no effect.
+ some, // SmoothFonts produces some effect, but not subpixel coverage.
+ subpixel, // SmoothFonts produces some effect and provides subpixel coverage.
+};
+
+SkCTFontSmoothBehavior SkCTFontGetSmoothBehavior();
+
+#endif
+#endif // SkCTFontSmoothBehavior_DEFINED
diff --git a/chromium/third_party/skia/src/utils/mac/SkStream_mac.cpp b/chromium/third_party/skia/src/utils/mac/SkStream_mac.cpp
deleted file mode 100644
index b299fced492..00000000000
--- a/chromium/third_party/skia/src/utils/mac/SkStream_mac.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-// Remove file after it is removed from downstream builds.
diff --git a/chromium/third_party/skia/src/xps/SkXPSDevice.cpp b/chromium/third_party/skia/src/xps/SkXPSDevice.cpp
index e9f045cc855..ec4ba68fc03 100644
--- a/chromium/third_party/skia/src/xps/SkXPSDevice.cpp
+++ b/chromium/third_party/skia/src/xps/SkXPSDevice.cpp
@@ -116,7 +116,7 @@ HRESULT SkXPSDevice::createId(wchar_t* buffer, size_t bufferSize, wchar_t sep) {
SkXPSDevice::SkXPSDevice(SkISize s)
: INHERITED(SkImageInfo::MakeUnknown(s.width(), s.height()),
SkSurfaceProps(0, kUnknown_SkPixelGeometry))
- , fCurrentPage(0) {}
+ , fCurrentPage(0), fTopTypefaces(&fTypefaces) {}
SkXPSDevice::~SkXPSDevice() {}
@@ -414,7 +414,7 @@ static HRESULT subset_typeface(const SkXPSDevice::TypefaceUse& current) {
bool SkXPSDevice::endPortfolio() {
//Subset fonts
- for (const TypefaceUse& current : this->fTypefaces) {
+ for (const TypefaceUse& current : *this->fTopTypefaces) {
//Ignore return for now, if it didn't subset, let it be.
subset_typeface(current);
}
@@ -1632,7 +1632,7 @@ void SkXPSDevice::drawPath(const SkPath& platonicPath,
return;
}
}
- // The xpsCompatiblePath is now inverse even odd, so fall through.
+ [[fallthrough]]; // The xpsCompatiblePath is now inverse even odd, so fall through.
case SkPathFillType::kInverseEvenOdd: {
const SkRect universe = SkRect::MakeLTRB(
0, 0,
@@ -1726,7 +1726,7 @@ HRESULT SkXPSDevice::CreateTypefaceUse(const SkFont& font,
//Check cache.
const SkFontID typefaceID = typeface->uniqueID();
- for (TypefaceUse& current : this->fTypefaces) {
+ for (TypefaceUse& current : *this->fTopTypefaces) {
if (current.typefaceId == typefaceID) {
*typefaceUse = &current;
return S_OK;
@@ -1774,7 +1774,7 @@ HRESULT SkXPSDevice::CreateTypefaceUse(const SkFont& font,
int glyphCount = typeface->countGlyphs();
- TypefaceUse& newTypefaceUse = this->fTypefaces.emplace_back(
+ TypefaceUse& newTypefaceUse = this->fTopTypefaces->emplace_back(
typefaceID,
isTTC ? ttcIndex : -1,
std::move(fontData),
@@ -1954,10 +1954,11 @@ void SkXPSDevice::drawGlyphRunList(const SkGlyphRunList& glyphRunList) {
}
}
-void SkXPSDevice::drawDevice( SkBaseDevice* dev,
+void SkXPSDevice::drawDevice(SkBaseDevice* dev,
int x, int y,
const SkPaint&) {
SkXPSDevice* that = static_cast<SkXPSDevice*>(dev);
+ SkASSERT(that->fTopTypefaces == this->fTopTypefaces);
SkTScopedComPtr<IXpsOMMatrixTransform> xpsTransform;
// TODO(halcanary): assert that current transform is identity rather than calling setter.
@@ -1988,8 +1989,11 @@ SkBaseDevice* SkXPSDevice::onCreateDevice(const CreateInfo& info, const SkPaint*
}
#endif
SkXPSDevice* dev = new SkXPSDevice(info.fInfo.dimensions());
- // TODO(halcanary) implement copy constructor on SkTScopedCOmPtr
dev->fXpsFactory.reset(SkRefComPtr(fXpsFactory.get()));
+ dev->fCurrentCanvasSize = this->fCurrentCanvasSize;
+ dev->fCurrentUnitsPerMeter = this->fCurrentUnitsPerMeter;
+ dev->fCurrentPixelsPerMeter = this->fCurrentPixelsPerMeter;
+ dev->fTopTypefaces = this->fTopTypefaces;
SkAssertResult(dev->createCanvasForLayer());
return dev;
}
diff --git a/chromium/third_party/skia/src/xps/SkXPSDevice.h b/chromium/third_party/skia/src/xps/SkXPSDevice.h
index c0e6679c48c..0dcbb9b079a 100644
--- a/chromium/third_party/skia/src/xps/SkXPSDevice.h
+++ b/chromium/third_party/skia/src/xps/SkXPSDevice.h
@@ -125,6 +125,7 @@ private:
SkVector fCurrentPixelsPerMeter;
SkTArray<TypefaceUse, true> fTypefaces;
+ SkTArray<TypefaceUse, true>* fTopTypefaces;
/** Creates a GUID based id and places it into buffer.
buffer should have space for at least GUID_ID_LEN wide characters.