summaryrefslogtreecommitdiff
path: root/chromium/third_party/skia
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
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')
-rw-r--r--chromium/third_party/skia/BUILD.gn297
-rw-r--r--chromium/third_party/skia/DEPS18
-rw-r--r--chromium/third_party/skia/RELEASE_NOTES.txt70
-rw-r--r--chromium/third_party/skia/bench/BitmapRegionDecoderBench.cpp5
-rw-r--r--chromium/third_party/skia/bench/BitmapRegionDecoderBench.h21
-rw-r--r--chromium/third_party/skia/bench/BulkRectBench.cpp12
-rw-r--r--chromium/third_party/skia/bench/ClipMaskBench.cpp53
-rw-r--r--chromium/third_party/skia/bench/ColorFilterBench.cpp3
-rw-r--r--chromium/third_party/skia/bench/CoverageBench.cpp1
-rw-r--r--chromium/third_party/skia/bench/CreateBackendTextureBench.cpp1
-rw-r--r--chromium/third_party/skia/bench/DashBench.cpp2
-rw-r--r--chromium/third_party/skia/bench/DrawBitmapAABench.cpp12
-rw-r--r--chromium/third_party/skia/bench/HairlinePathBench.cpp2
-rw-r--r--chromium/third_party/skia/bench/ImageCacheBudgetBench.cpp4
-rw-r--r--chromium/third_party/skia/bench/ImageCycleBench.cpp2
-rw-r--r--chromium/third_party/skia/bench/MatrixBench.cpp2
-rw-r--r--chromium/third_party/skia/bench/PathBench.cpp2
-rw-r--r--chromium/third_party/skia/bench/PathOpsBench.cpp130
-rw-r--r--chromium/third_party/skia/bench/QuickRejectBench.cpp2
-rw-r--r--chromium/third_party/skia/bench/RectanizerBench.cpp27
-rw-r--r--chromium/third_party/skia/bench/SKPAnimationBench.cpp2
-rw-r--r--chromium/third_party/skia/bench/SKPBench.cpp6
-rw-r--r--chromium/third_party/skia/bench/TessellatePathBench.cpp206
-rw-r--r--chromium/third_party/skia/bench/VertexColorSpaceBench.cpp2
-rw-r--r--chromium/third_party/skia/bench/nanobench.cpp27
-rwxr-xr-xchromium/third_party/skia/bin/fetch-gn2
-rwxr-xr-xchromium/third_party/skia/build/fuchsia/fidl_gen_cpp3
-rw-r--r--chromium/third_party/skia/build/fuchsia/sdk.gni17
-rw-r--r--chromium/third_party/skia/client_utils/android/BRDAllocator.h (renamed from chromium/third_party/skia/include/android/SkBRDAllocator.h)14
-rw-r--r--chromium/third_party/skia/client_utils/android/BitmapRegionDecoder.cpp (renamed from chromium/third_party/skia/src/android/SkBitmapRegionCodec.cpp)45
-rw-r--r--chromium/third_party/skia/client_utils/android/BitmapRegionDecoder.h50
-rw-r--r--chromium/third_party/skia/client_utils/android/BitmapRegionDecoderPriv.h (renamed from chromium/third_party/skia/src/android/SkBitmapRegionDecoderPriv.h)6
-rw-r--r--chromium/third_party/skia/demos.skia.org/Makefile4
-rw-r--r--chromium/third_party/skia/demos.skia.org/demos/hello_world/index.html42
-rw-r--r--chromium/third_party/skia/dm/DM.cpp159
-rw-r--r--chromium/third_party/skia/dm/DMGpuTestProcs.cpp5
-rw-r--r--chromium/third_party/skia/dm/DMSrcSink.cpp248
-rw-r--r--chromium/third_party/skia/dm/DMSrcSink.h52
-rw-r--r--chromium/third_party/skia/experimental/minimal_ios_mtl_skia_app/main.mm2
-rwxr-xr-xchromium/third_party/skia/experimental/skottiekit/compile.sh10
-rw-r--r--chromium/third_party/skia/experimental/skottiekit/examples/ck.html2
-rw-r--r--chromium/third_party/skia/experimental/skottiekit/examples/index.html2
-rw-r--r--chromium/third_party/skia/experimental/skottiekit/ready.js16
-rw-r--r--chromium/third_party/skia/experimental/skrive/BUILD.gn52
-rw-r--r--chromium/third_party/skia/experimental/skrive/include/SkRive.h266
-rw-r--r--chromium/third_party/skia/experimental/skrive/skrive.gni26
-rw-r--r--chromium/third_party/skia/experimental/skrive/src/Artboard.cpp133
-rw-r--r--chromium/third_party/skia/experimental/skrive/src/Color.cpp38
-rw-r--r--chromium/third_party/skia/experimental/skrive/src/Component.cpp59
-rw-r--r--chromium/third_party/skia/experimental/skrive/src/Drawable.cpp32
-rw-r--r--chromium/third_party/skia/experimental/skrive/src/Ellipse.cpp32
-rw-r--r--chromium/third_party/skia/experimental/skrive/src/Node.cpp65
-rw-r--r--chromium/third_party/skia/experimental/skrive/src/Paint.cpp72
-rw-r--r--chromium/third_party/skia/experimental/skrive/src/Shape.cpp31
-rw-r--r--chromium/third_party/skia/experimental/skrive/src/SkRive.cpp75
-rw-r--r--chromium/third_party/skia/experimental/skrive/src/reader/BinaryReader.cpp149
-rw-r--r--chromium/third_party/skia/experimental/skrive/src/reader/JsonReader.cpp251
-rw-r--r--chromium/third_party/skia/experimental/skrive/src/reader/StreamReader.cpp72
-rw-r--r--chromium/third_party/skia/experimental/skrive/src/reader/StreamReader.h103
-rw-r--r--chromium/third_party/skia/experimental/svg/model/SkSVGSVG.cpp2
-rwxr-xr-xchromium/third_party/skia/experimental/tools/web_to_mskp7
-rwxr-xr-xchromium/third_party/skia/experimental/tools/web_to_skp7
-rwxr-xr-xchromium/third_party/skia/experimental/wasm-skp-debugger/compile.sh8
-rw-r--r--chromium/third_party/skia/experimental/wasm-skp-debugger/debugger/index.html2
-rw-r--r--chromium/third_party/skia/experimental/wasm-skp-debugger/debugger_bindings.cpp2
-rw-r--r--chromium/third_party/skia/experimental/wasm-skp-debugger/ready.js16
-rw-r--r--chromium/third_party/skia/gm/aarectmodes.cpp2
-rw-r--r--chromium/third_party/skia/gm/addarc.cpp14
-rw-r--r--chromium/third_party/skia/gm/asyncrescaleandread.cpp7
-rw-r--r--chromium/third_party/skia/gm/atlastext.cpp199
-rw-r--r--chromium/third_party/skia/gm/backdrop_imagefilter_croprect.cpp4
-rw-r--r--chromium/third_party/skia/gm/beziereffects.cpp149
-rw-r--r--chromium/third_party/skia/gm/bigrrectaaeffect.cpp8
-rw-r--r--chromium/third_party/skia/gm/bleed.cpp416
-rw-r--r--chromium/third_party/skia/gm/blurroundrect.cpp2
-rw-r--r--chromium/third_party/skia/gm/bug6783.cpp3
-rw-r--r--chromium/third_party/skia/gm/circles.cpp4
-rw-r--r--chromium/third_party/skia/gm/circulararcs.cpp35
-rw-r--r--chromium/third_party/skia/gm/clockwise.cpp15
-rw-r--r--chromium/third_party/skia/gm/complexclip.cpp183
-rw-r--r--chromium/third_party/skia/gm/composeshader.cpp2
-rw-r--r--chromium/third_party/skia/gm/conicpaths.cpp10
-rw-r--r--chromium/third_party/skia/gm/constcolorprocessor.cpp4
-rw-r--r--chromium/third_party/skia/gm/convexpolyeffect.cpp10
-rw-r--r--chromium/third_party/skia/gm/dashcircle.cpp12
-rw-r--r--chromium/third_party/skia/gm/dashcubics.cpp4
-rw-r--r--chromium/third_party/skia/gm/dashing.cpp60
-rw-r--r--chromium/third_party/skia/gm/dftext_blob_persp.cpp4
-rw-r--r--chromium/third_party/skia/gm/draw_bitmap_rect_skbug4374.cpp2
-rw-r--r--chromium/third_party/skia/gm/drawable.cpp2
-rw-r--r--chromium/third_party/skia/gm/drawimageset.cpp65
-rw-r--r--chromium/third_party/skia/gm/drawquadset.cpp3
-rw-r--r--chromium/third_party/skia/gm/dstreadshuffle.cpp1
-rw-r--r--chromium/third_party/skia/gm/encode_color_types.cpp170
-rw-r--r--chromium/third_party/skia/gm/flippity.cpp38
-rw-r--r--chromium/third_party/skia/gm/fontregen.cpp4
-rw-r--r--chromium/third_party/skia/gm/fpcoordinateoverride.cpp3
-rw-r--r--chromium/third_party/skia/gm/fwidth_squircle.cpp2
-rw-r--r--chromium/third_party/skia/gm/gm.cpp7
-rw-r--r--chromium/third_party/skia/gm/gm.h6
-rw-r--r--chromium/third_party/skia/gm/gpu_blur_utils.cpp231
-rw-r--r--chromium/third_party/skia/gm/hittestpath.cpp52
-rw-r--r--chromium/third_party/skia/gm/image_pict.cpp4
-rw-r--r--chromium/third_party/skia/gm/image_shader.cpp2
-rw-r--r--chromium/third_party/skia/gm/imagefilters.cpp2
-rw-r--r--chromium/third_party/skia/gm/imagefilterstransformed.cpp55
-rw-r--r--chromium/third_party/skia/gm/imagefromyuvtextures.cpp184
-rw-r--r--chromium/third_party/skia/gm/localmatriximagefilter.cpp6
-rw-r--r--chromium/third_party/skia/gm/localmatriximageshader.cpp4
-rw-r--r--chromium/third_party/skia/gm/localmatrixshader.cpp101
-rw-r--r--chromium/third_party/skia/gm/mac_aa_explorer.cpp2
-rw-r--r--chromium/third_party/skia/gm/offsetimagefilter.cpp2
-rw-r--r--chromium/third_party/skia/gm/patheffects.cpp55
-rw-r--r--chromium/third_party/skia/gm/perspshaders.cpp2
-rw-r--r--chromium/third_party/skia/gm/pictureimagegenerator.cpp2
-rw-r--r--chromium/third_party/skia/gm/preservefillrule.cpp8
-rw-r--r--chromium/third_party/skia/gm/recordopts.cpp8
-rw-r--r--chromium/third_party/skia/gm/rectangletexture.cpp78
-rw-r--r--chromium/third_party/skia/gm/rrects.cpp5
-rw-r--r--chromium/third_party/skia/gm/runtimeshader.cpp108
-rw-r--r--chromium/third_party/skia/gm/sample_matrix_constant.cpp69
-rw-r--r--chromium/third_party/skia/gm/sample_matrix_variable.cpp52
-rw-r--r--chromium/third_party/skia/gm/samplelocations.cpp9
-rw-r--r--chromium/third_party/skia/gm/savelayer.cpp175
-rw-r--r--chromium/third_party/skia/gm/sharedcorners.cpp2
-rw-r--r--chromium/third_party/skia/gm/strokefill.cpp169
-rw-r--r--chromium/third_party/skia/gm/swizzle.cpp43
-rw-r--r--chromium/third_party/skia/gm/tessellation.cpp28
-rw-r--r--chromium/third_party/skia/gm/texelsubset.cpp4
-rw-r--r--chromium/third_party/skia/gm/tilemodes_alpha.cpp2
-rw-r--r--chromium/third_party/skia/gm/userfont.cpp89
-rw-r--r--chromium/third_party/skia/gm/vertices.cpp39
-rw-r--r--chromium/third_party/skia/gm/wacky_yuv_formats.cpp271
-rw-r--r--chromium/third_party/skia/gm/widebuttcaps.cpp84
-rw-r--r--chromium/third_party/skia/gm/windowrectangles.cpp36
-rw-r--r--chromium/third_party/skia/gm/xfermodes.cpp8
-rw-r--r--chromium/third_party/skia/gm/ycbcrimage.cpp118
-rw-r--r--chromium/third_party/skia/gm/yuvtorgbeffect.cpp5
-rw-r--r--chromium/third_party/skia/gn/BUILD.gn28
-rw-r--r--chromium/third_party/skia/gn/BUILDCONFIG.gn2
-rwxr-xr-xchromium/third_party/skia/gn/compile_processors.py11
-rw-r--r--chromium/third_party/skia/gn/core.gni6
-rw-r--r--chromium/third_party/skia/gn/flutter_defines.gni4
-rw-r--r--chromium/third_party/skia/gn/gm.gni9
-rwxr-xr-xchromium/third_party/skia/gn/gn_to_bp.py44
-rwxr-xr-xchromium/third_party/skia/gn/gn_to_bp_utils.py7
-rw-r--r--chromium/third_party/skia/gn/gpu.gni46
-rw-r--r--chromium/third_party/skia/gn/opts.gni1
-rwxr-xr-xchromium/third_party/skia/gn/rm.py18
-rwxr-xr-xchromium/third_party/skia/gn/run_sksllex.py10
-rw-r--r--chromium/third_party/skia/gn/samples.gni1
-rw-r--r--chromium/third_party/skia/gn/shared_sources.gni1
-rw-r--r--chromium/third_party/skia/gn/skia.gni38
-rw-r--r--chromium/third_party/skia/gn/sksl.gni38
-rw-r--r--chromium/third_party/skia/gn/tests.gni7
-rw-r--r--chromium/third_party/skia/gn/toolchain/BUILD.gn12
-rw-r--r--chromium/third_party/skia/gn/utils.gni4
-rw-r--r--chromium/third_party/skia/go.mod29
-rw-r--r--chromium/third_party/skia/go.sum349
-rw-r--r--chromium/third_party/skia/include/android/SkBitmapRegionDecoder.h92
-rw-r--r--chromium/third_party/skia/include/atlastext/SkAtlasTextContext.h42
-rw-r--r--chromium/third_party/skia/include/atlastext/SkAtlasTextFont.h38
-rw-r--r--chromium/third_party/skia/include/atlastext/SkAtlasTextRenderer.h72
-rw-r--r--chromium/third_party/skia/include/atlastext/SkAtlasTextTarget.h100
-rw-r--r--chromium/third_party/skia/include/core/SkCanvas.h145
-rw-r--r--chromium/third_party/skia/include/core/SkColorFilter.h99
-rw-r--r--chromium/third_party/skia/include/core/SkColorSpace.h2
-rw-r--r--chromium/third_party/skia/include/core/SkDeferredDisplayList.h4
-rw-r--r--chromium/third_party/skia/include/core/SkDeferredDisplayListRecorder.h1
-rw-r--r--chromium/third_party/skia/include/core/SkDrawLooper.h7
-rw-r--r--chromium/third_party/skia/include/core/SkFlattenable.h27
-rw-r--r--chromium/third_party/skia/include/core/SkFontStyle.h2
-rw-r--r--chromium/third_party/skia/include/core/SkImage.h44
-rw-r--r--chromium/third_party/skia/include/core/SkImageInfo.h49
-rw-r--r--chromium/third_party/skia/include/core/SkMatrix.h72
-rw-r--r--chromium/third_party/skia/include/core/SkMilestone.h2
-rw-r--r--chromium/third_party/skia/include/core/SkPaint.h13
-rw-r--r--chromium/third_party/skia/include/core/SkPath.h14
-rw-r--r--chromium/third_party/skia/include/core/SkPathBuilder.h101
-rw-r--r--chromium/third_party/skia/include/core/SkPixmap.h8
-rw-r--r--chromium/third_party/skia/include/core/SkString.h21
-rw-r--r--chromium/third_party/skia/include/core/SkSurface.h153
-rw-r--r--chromium/third_party/skia/include/core/SkTypes.h49
-rw-r--r--chromium/third_party/skia/include/core/SkVertices.h3
-rw-r--r--chromium/third_party/skia/include/docs/SkPDFDocument.h15
-rw-r--r--chromium/third_party/skia/include/effects/SkBlurDrawLooper.h4
-rw-r--r--chromium/third_party/skia/include/effects/SkLayerDrawLooper.h3
-rw-r--r--chromium/third_party/skia/include/effects/SkLumaColorFilter.h22
-rw-r--r--chromium/third_party/skia/include/effects/SkRuntimeEffect.h3
-rw-r--r--chromium/third_party/skia/include/effects/SkStrokeAndFillPathEffect.h28
-rw-r--r--chromium/third_party/skia/include/gpu/GrBackendSurface.h42
-rw-r--r--chromium/third_party/skia/include/gpu/GrBackendSurfaceMutableState.h66
-rw-r--r--chromium/third_party/skia/include/gpu/GrContext.h194
-rw-r--r--chromium/third_party/skia/include/gpu/GrContextOptions.h27
-rw-r--r--chromium/third_party/skia/include/gpu/GrContextThreadSafeProxy.h37
-rw-r--r--chromium/third_party/skia/include/gpu/GrTypes.h68
-rw-r--r--chromium/third_party/skia/include/gpu/gl/GrGLInterface.h20
-rw-r--r--chromium/third_party/skia/include/gpu/mock/GrMockTypes.h2
-rw-r--r--chromium/third_party/skia/include/gpu/vk/GrVkMemoryAllocator.h66
-rw-r--r--chromium/third_party/skia/include/gpu/vk/GrVkTypes.h30
-rw-r--r--chromium/third_party/skia/include/ports/SkFontMgr_mac_ct.h27
-rw-r--r--chromium/third_party/skia/include/private/GrContext_Base.h21
-rw-r--r--chromium/third_party/skia/include/private/GrImageContext.h7
-rw-r--r--chromium/third_party/skia/include/private/GrRecordingContext.h4
-rw-r--r--chromium/third_party/skia/include/private/GrResourceKey.h10
-rw-r--r--chromium/third_party/skia/include/private/GrSharedEnums.h6
-rw-r--r--chromium/third_party/skia/include/private/GrSingleOwner.h22
-rw-r--r--chromium/third_party/skia/include/private/GrTypesPriv.h17
-rw-r--r--chromium/third_party/skia/include/private/GrVkTypesPriv.h49
-rw-r--r--chromium/third_party/skia/include/private/SkChecksum.h7
-rw-r--r--chromium/third_party/skia/include/private/SkColorData.h1
-rw-r--r--chromium/third_party/skia/include/private/SkFixed.h8
-rw-r--r--chromium/third_party/skia/include/private/SkImageInfoPriv.h4
-rw-r--r--chromium/third_party/skia/include/private/SkOpts_spi.h21
-rw-r--r--chromium/third_party/skia/include/private/SkPathRef.h18
-rw-r--r--chromium/third_party/skia/include/private/SkSemaphore.h8
-rw-r--r--chromium/third_party/skia/include/private/SkTArray.h43
-rw-r--r--chromium/third_party/skia/include/private/SkTDArray.h9
-rw-r--r--chromium/third_party/skia/include/private/SkTemplates.h9
-rw-r--r--chromium/third_party/skia/include/third_party/skcms/skcms.h3
-rw-r--r--chromium/third_party/skia/include/utils/SkCamera.h82
-rw-r--r--chromium/third_party/skia/include/utils/SkCustomTypeface.h7
-rw-r--r--chromium/third_party/skia/include/utils/SkRandom.h2
-rw-r--r--chromium/third_party/skia/modules/canvaskit/BUILD.gn6
-rw-r--r--chromium/third_party/skia/modules/canvaskit/CHANGELOG.md104
-rw-r--r--chromium/third_party/skia/modules/canvaskit/Makefile5
-rw-r--r--chromium/third_party/skia/modules/canvaskit/README.md77
-rw-r--r--chromium/third_party/skia/modules/canvaskit/canvaskit/README.md14
-rw-r--r--chromium/third_party/skia/modules/canvaskit/canvaskit/example.html118
-rw-r--r--chromium/third_party/skia/modules/canvaskit/canvaskit/extra.html552
-rw-r--r--chromium/third_party/skia/modules/canvaskit/canvaskit/node.example.js4
-rw-r--r--chromium/third_party/skia/modules/canvaskit/canvaskit/package.json2
-rw-r--r--chromium/third_party/skia/modules/canvaskit/canvaskit/viewer.html213
-rw-r--r--chromium/third_party/skia/modules/canvaskit/canvaskit_bindings.cpp303
-rwxr-xr-xchromium/third_party/skia/modules/canvaskit/compile.sh25
-rw-r--r--chromium/third_party/skia/modules/canvaskit/cpu.js23
-rw-r--r--chromium/third_party/skia/modules/canvaskit/externs.js37
-rw-r--r--chromium/third_party/skia/modules/canvaskit/font.js8
-rw-r--r--chromium/third_party/skia/modules/canvaskit/future_apis/ImageDecoder.md62
-rw-r--r--chromium/third_party/skia/modules/canvaskit/future_apis/WebGPU.md17
-rw-r--r--chromium/third_party/skia/modules/canvaskit/gpu.js93
-rw-r--r--chromium/third_party/skia/modules/canvaskit/helper.js315
-rw-r--r--chromium/third_party/skia/modules/canvaskit/htmlcanvas/_namedcolors.js4
-rw-r--r--chromium/third_party/skia/modules/canvaskit/htmlcanvas/canvas2dcontext.js3
-rw-r--r--chromium/third_party/skia/modules/canvaskit/interface.js405
-rw-r--r--chromium/third_party/skia/modules/canvaskit/karma.conf.js13
-rw-r--r--chromium/third_party/skia/modules/canvaskit/package-lock.json3494
-rw-r--r--chromium/third_party/skia/modules/canvaskit/package.json1
-rw-r--r--chromium/third_party/skia/modules/canvaskit/paragraph.js109
-rw-r--r--chromium/third_party/skia/modules/canvaskit/paragraph_bindings.cpp22
-rw-r--r--chromium/third_party/skia/modules/canvaskit/particles.js8
-rw-r--r--chromium/third_party/skia/modules/canvaskit/perf/assets/test_1500x959.jpgbin0 -> 1004868 bytes
-rw-r--r--chromium/third_party/skia/modules/canvaskit/perf/assets/test_512x512.pngbin0 -> 625834 bytes
-rw-r--r--chromium/third_party/skia/modules/canvaskit/perf/assets/test_64x64.pngbin0 -> 896 bytes
-rw-r--r--chromium/third_party/skia/modules/canvaskit/perf/canvas.bench.js169
-rw-r--r--chromium/third_party/skia/modules/canvaskit/ready.js16
-rw-r--r--chromium/third_party/skia/modules/canvaskit/rt_shader.js18
-rw-r--r--chromium/third_party/skia/modules/canvaskit/skottie.js11
-rw-r--r--chromium/third_party/skia/modules/canvaskit/viewer_bindings.cpp58
-rw-r--r--chromium/third_party/skia/modules/particles/src/SkParticleEffect.cpp1
-rw-r--r--chromium/third_party/skia/modules/pathkit/CHANGELOG.md6
-rwxr-xr-xchromium/third_party/skia/modules/pathkit/compile.sh5
-rw-r--r--chromium/third_party/skia/modules/pathkit/npm-asmjs/README.md6
-rw-r--r--chromium/third_party/skia/modules/pathkit/npm-asmjs/example.html2
-rw-r--r--chromium/third_party/skia/modules/pathkit/npm-wasm/README.md6
-rw-r--r--chromium/third_party/skia/modules/pathkit/npm-wasm/example.html2
-rw-r--r--chromium/third_party/skia/modules/pathkit/pathkit_wasm_bindings.cpp21
-rw-r--r--chromium/third_party/skia/modules/pathkit/perf/perfReporter.js49
-rw-r--r--chromium/third_party/skia/modules/pathkit/ready.js16
-rw-r--r--chromium/third_party/skia/modules/skottie/gm/ExternalProperties.cpp9
-rw-r--r--chromium/third_party/skia/modules/skottie/gm/SkottieGM.cpp9
-rw-r--r--chromium/third_party/skia/modules/skottie/include/Skottie.h11
-rw-r--r--chromium/third_party/skia/modules/skottie/src/Layer.cpp9
-rw-r--r--chromium/third_party/skia/modules/skottie/src/Layer.h1
-rw-r--r--chromium/third_party/skia/modules/skottie/src/SkottiePriv.h21
-rw-r--r--chromium/third_party/skia/modules/skottie/src/SkottieTool.cpp13
-rw-r--r--chromium/third_party/skia/modules/skottie/src/Transform.cpp27
-rw-r--r--chromium/third_party/skia/modules/skottie/src/Transform.h6
-rw-r--r--chromium/third_party/skia/modules/skottie/src/animator/Animator.cpp7
-rw-r--r--chromium/third_party/skia/modules/skottie/src/animator/Animator.h13
-rw-r--r--chromium/third_party/skia/modules/skottie/src/animator/KeyframeAnimator.h6
-rw-r--r--chromium/third_party/skia/modules/skottie/src/animator/ScalarKeyframeAnimator.cpp19
-rw-r--r--chromium/third_party/skia/modules/skottie/src/animator/ShapeKeyframeAnimator.cpp4
-rw-r--r--chromium/third_party/skia/modules/skottie/src/animator/TextKeyframeAnimator.cpp17
-rw-r--r--chromium/third_party/skia/modules/skottie/src/animator/Vec2KeyframeAnimator.cpp70
-rw-r--r--chromium/third_party/skia/modules/skottie/src/animator/VectorKeyframeAnimator.cpp37
-rw-r--r--chromium/third_party/skia/modules/skottie/src/animator/VectorKeyframeAnimator.h11
-rw-r--r--chromium/third_party/skia/modules/skottie/src/effects/MotionTileEffect.cpp2
-rw-r--r--chromium/third_party/skia/modules/skottie/src/layers/TextLayer.cpp327
-rw-r--r--chromium/third_party/skia/modules/skottie/src/layers/shapelayer/Repeater.cpp2
-rw-r--r--chromium/third_party/skia/modules/skottie/src/text/TextValue.cpp33
-rw-r--r--chromium/third_party/skia/modules/skparagraph/BUILD.gn26
-rw-r--r--chromium/third_party/skia/modules/skparagraph/bench/ParagraphBench.cpp (renamed from chromium/third_party/skia/bench/ParagraphBench.cpp)0
-rw-r--r--chromium/third_party/skia/modules/skparagraph/gm/simple_gm.cpp120
-rw-r--r--chromium/third_party/skia/modules/skparagraph/include/DartTypes.h4
-rw-r--r--chromium/third_party/skia/modules/skparagraph/include/Paragraph.h3
-rw-r--r--chromium/third_party/skia/modules/skparagraph/include/ParagraphCache.h12
-rw-r--r--chromium/third_party/skia/modules/skparagraph/include/ParagraphStyle.h10
-rw-r--r--chromium/third_party/skia/modules/skparagraph/include/TypefaceFontProvider.h4
-rw-r--r--chromium/third_party/skia/modules/skparagraph/samples/SampleParagraph.cpp (renamed from chromium/third_party/skia/samplecode/SampleParagraph.cpp)153
-rw-r--r--chromium/third_party/skia/modules/skparagraph/skparagraph.gni2
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/Decorations.cpp52
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/Decorations.h4
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/FontCollection.cpp4
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/Iterators.h12
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/OneLineShaper.cpp97
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/OneLineShaper.h8
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/ParagraphBuilderImpl.cpp23
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/ParagraphCache.cpp18
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/ParagraphImpl.cpp706
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/ParagraphImpl.h136
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/ParagraphStyle.cpp11
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/ParagraphUtil.cpp34
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/ParagraphUtil.h14
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/Run.cpp176
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/Run.h132
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/TextLine.cpp224
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/TextLine.h28
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/TextStyle.cpp3
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/TextWrapper.cpp4
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/TextWrapper.h1
-rw-r--r--chromium/third_party/skia/modules/skparagraph/src/TypefaceFontProvider.cpp8
-rw-r--r--chromium/third_party/skia/modules/skplaintexteditor/BUILD.gn3
-rw-r--r--chromium/third_party/skia/modules/skplaintexteditor/src/word_boundaries.cpp55
-rw-r--r--chromium/third_party/skia/modules/skresources/include/SkResources.h16
-rw-r--r--chromium/third_party/skia/modules/skresources/src/SkResources.cpp5
-rw-r--r--chromium/third_party/skia/modules/sksg/include/SkSGGroup.h1
-rw-r--r--chromium/third_party/skia/modules/sksg/include/SkSGTransform.h2
-rw-r--r--chromium/third_party/skia/modules/sksg/src/SkSGGroup.cpp2
-rw-r--r--chromium/third_party/skia/modules/skshaper/BUILD.gn13
-rw-r--r--chromium/third_party/skia/modules/skshaper/include/SkShaper.h3
-rw-r--r--chromium/third_party/skia/modules/skshaper/skshaper.gni2
-rw-r--r--chromium/third_party/skia/modules/skshaper/src/SkShaper_coretext.cpp74
-rw-r--r--chromium/third_party/skia/modules/skshaper/src/SkShaper_harfbuzz.cpp106
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/CMakeLists.txt76
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/build.gradle92
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/AndroidManifest.xml35
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/assets/models/trigrid.pngbin146080 -> 0 bytes
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/SkArCamera.cpp38
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/SkArCamera.h68
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/anchor_wrapper.cc41
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/anchor_wrapper.h45
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/background_renderer.cc113
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/background_renderer.h61
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/glm.h25
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/hello_ar_application.cc986
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/hello_ar_application.h158
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/jni_interface.cc130
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/jni_interface.h34
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/pending_anchor.cc68
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/pending_anchor.h50
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/plane_renderer.cc220
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/plane_renderer.h70
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/point_cloud_renderer.cc77
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/point_cloud_renderer.h57
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/util.cc329
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/util.h139
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/java/org/skia/arcore/CameraPermissionHelper.java65
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/java/org/skia/arcore/HelloArActivity.java364
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/java/org/skia/arcore/JniInterface.java82
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/drawable-xxhdpi/ic_launcher.pngbin21226 -> 0 bytes
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/layout-xlarge-land/activity_main.xml41
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/layout/activity_main.xml50
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/layout/state_item.xml35
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/draw_menu.xml15
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/edit_menu.xml8
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/rotation_mode.xml11
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/title.xml12
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/values/integers.xml4
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/values/strings.xml19
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/values/styles.xml35
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/gradle/wrapper/gradle-wrapper.properties4
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/settings.gradle4
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/skottie/build.gradle23
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/build.gradle36
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/AndroidManifest.xml2
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/cpp/native-lib.cpp (renamed from chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/cpp/native-lib.cpp)36
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/java/org/skia/skottie/SkottieAnimation.java (renamed from chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/java/org/skia/skottie/SkottieAnimation.java)2
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/java/org/skia/skottie/SkottieApplication.java (renamed from chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/java/org/skia/skottie/SkottieApplication.java)0
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/java/org/skia/skottie/SkottieRunner.java (renamed from chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/java/org/skia/skottie/SkottieRunner.java)46
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/java/org/skia/skottie/SkottieView.java (renamed from chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/java/org/skia/skottie/SkottieView.java)0
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/cpp/JavaInputStreamAdaptor.cpp256
-rw-r--r--chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/cpp/JavaInputStreamAdaptor.h24
-rw-r--r--chromium/third_party/skia/public.bzl128
-rw-r--r--chromium/third_party/skia/resources/images/lut_identity.pngbin0 -> 286 bytes
-rw-r--r--chromium/third_party/skia/resources/images/lut_sepia.pngbin0 -> 2610 bytes
-rw-r--r--chromium/third_party/skia/resources/images/mandrill_sepia.pngbin0 -> 83205 bytes
-rw-r--r--chromium/third_party/skia/resources/skottie/skottie-auto-orient.json1
-rw-r--r--chromium/third_party/skia/samplecode/Sample.cpp2
-rw-r--r--chromium/third_party/skia/samplecode/Sample3D.cpp10
-rw-r--r--chromium/third_party/skia/samplecode/SampleAAGeometry.cpp3
-rw-r--r--chromium/third_party/skia/samplecode/SampleAnimatedImage.cpp5
-rw-r--r--chromium/third_party/skia/samplecode/SampleBackdropBounds.cpp2
-rw-r--r--chromium/third_party/skia/samplecode/SampleCCPRGeometry.cpp6
-rw-r--r--chromium/third_party/skia/samplecode/SampleClip.cpp2
-rw-r--r--chromium/third_party/skia/samplecode/SampleCowboy.cpp8
-rw-r--r--chromium/third_party/skia/samplecode/SampleFatBits.cpp2
-rw-r--r--chromium/third_party/skia/samplecode/SampleFitCubicToCircle.cpp257
-rw-r--r--chromium/third_party/skia/samplecode/SampleLayers.cpp2
-rw-r--r--chromium/third_party/skia/samplecode/SamplePathText.cpp179
-rw-r--r--chromium/third_party/skia/samplecode/SampleRectanizer.cpp57
-rw-r--r--chromium/third_party/skia/samplecode/SampleTessellatedWedge.cpp35
-rw-r--r--chromium/third_party/skia/samplecode/SampleTextBox.cpp4
-rw-r--r--chromium/third_party/skia/site/dev/chrome/blink.md4
-rw-r--r--chromium/third_party/skia/site/dev/contrib/style.md17
-rw-r--r--chromium/third_party/skia/site/dev/testing/fuzz.md3
-rw-r--r--chromium/third_party/skia/site/user/api/catalog.htm8
-rw-r--r--chromium/third_party/skia/site/user/modules/canvaskit.md384
-rw-r--r--chromium/third_party/skia/site/user/modules/particles.md2
-rw-r--r--chromium/third_party/skia/site/user/modules/pathkit.md1
-rw-r--r--chromium/third_party/skia/site/user/release/release_notes.md63
-rw-r--r--chromium/third_party/skia/specs/web-img-decode/proposed/impl/impl.js3
-rw-r--r--chromium/third_party/skia/src/android/SkAnimatedImage.cpp4
-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/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
-rw-r--r--chromium/third_party/skia/third_party/angle2/BUILD.gn26
-rw-r--r--chromium/third_party/skia/third_party/glslang/BUILD.gn30
-rw-r--r--chromium/third_party/skia/third_party/icu/BUILD.gn1
-rw-r--r--chromium/third_party/skia/third_party/icu/config/BUILD.gn12
-rw-r--r--chromium/third_party/skia/third_party/skcms/skcms.cc15
-rw-r--r--chromium/third_party/skia/third_party/skcms/src/Transform_inl.h8
-rwxr-xr-xchromium/third_party/skia/third_party/skcms/version.sha12
-rw-r--r--chromium/third_party/skia/third_party/third_party.gni6
-rw-r--r--chromium/third_party/skia/third_party/zlib/BUILD.gn182
-rw-r--r--chromium/third_party/skia/tools/DDLPromiseImageHelper.cpp2
-rw-r--r--chromium/third_party/skia/tools/DDLTileHelper.cpp9
-rw-r--r--chromium/third_party/skia/tools/DDLTileHelper.h6
-rw-r--r--chromium/third_party/skia/tools/convert-to-nia.cpp227
-rw-r--r--chromium/third_party/skia/tools/debugger/DebugCanvas.cpp4
-rw-r--r--chromium/third_party/skia/tools/fiddle/all_examples.cpp5
-rw-r--r--chromium/third_party/skia/tools/fiddle/disabled_examples.txt1
-rw-r--r--chromium/third_party/skia/tools/fiddle/documumentation_examples_map.txt22
-rw-r--r--chromium/third_party/skia/tools/flags/CommonFlagsConfig.cpp8
-rw-r--r--chromium/third_party/skia/tools/flags/CommonFlagsConfig.h3
-rw-r--r--chromium/third_party/skia/tools/flags/CommonFlagsGpu.cpp2
-rw-r--r--chromium/third_party/skia/tools/fm/fm.cpp8
-rw-r--r--chromium/third_party/skia/tools/fonts/TestSVGTypeface.cpp4
-rw-r--r--chromium/third_party/skia/tools/fonts/TestTypeface.cpp2
-rw-r--r--chromium/third_party/skia/tools/gpu/GrContextFactory.cpp3
-rw-r--r--chromium/third_party/skia/tools/gpu/GrTest.cpp8
-rw-r--r--chromium/third_party/skia/tools/gpu/MemoryCache.cpp3
-rw-r--r--chromium/third_party/skia/tools/gpu/MemoryCache.h9
-rw-r--r--chromium/third_party/skia/tools/gpu/TestContext.cpp1
-rw-r--r--chromium/third_party/skia/tools/gpu/TestOps.cpp39
-rw-r--r--chromium/third_party/skia/tools/gpu/YUVUtils.cpp25
-rw-r--r--chromium/third_party/skia/tools/gpu/YUVUtils.h40
-rw-r--r--chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.cpp483
-rw-r--r--chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.h25
-rw-r--r--chromium/third_party/skia/tools/gpu/atlastext/TestAtlasTextRenderer.h37
-rw-r--r--chromium/third_party/skia/tools/gpu/d3d/D3DTestContext.cpp1
-rw-r--r--chromium/third_party/skia/tools/gpu/dawn/DawnTestContext.cpp12
-rw-r--r--chromium/third_party/skia/tools/gpu/dawn/DawnTestContext.h5
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/GLTestContext.cpp35
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/GLTestContext.h4
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.cpp23
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp6
-rw-r--r--chromium/third_party/skia/tools/gpu/gl/interface/templates.go48
-rw-r--r--chromium/third_party/skia/tools/gpu/vk/VkTestHelper.cpp109
-rw-r--r--chromium/third_party/skia/tools/gpu/vk/VkTestHelper.h71
-rw-r--r--chromium/third_party/skia/tools/gpu/vk/VkTestUtils.cpp5
-rw-r--r--chromium/third_party/skia/tools/gpu/vk/VkYcbcrSamplerHelper.cpp196
-rw-r--r--chromium/third_party/skia/tools/gpu/vk/VkYcbcrSamplerHelper.h48
-rw-r--r--chromium/third_party/skia/tools/lottie-web-perf/lottie-web-canvas-perf.html22
-rw-r--r--chromium/third_party/skia/tools/lottie-web-perf/lottie-web-perf.html22
-rw-r--r--chromium/third_party/skia/tools/lottiecap/driver.html38
-rw-r--r--chromium/third_party/skia/tools/perf-canvaskit-puppeteer/Makefile20
-rw-r--r--chromium/third_party/skia/tools/perf-canvaskit-puppeteer/package-lock.json49
-rw-r--r--chromium/third_party/skia/tools/perf-canvaskit-puppeteer/package.json2
-rw-r--r--chromium/third_party/skia/tools/perf-canvaskit-puppeteer/path-transform.html189
-rw-r--r--chromium/third_party/skia/tools/perf-canvaskit-puppeteer/path_translate_assets/car.svg5155
-rw-r--r--chromium/third_party/skia/tools/perf-canvaskit-puppeteer/perf-canvaskit-with-puppeteer.js33
-rw-r--r--chromium/third_party/skia/tools/perf-canvaskit-puppeteer/render-skp.html157
-rw-r--r--chromium/third_party/skia/tools/perf-canvaskit-puppeteer/skottie-frames.html6
-rw-r--r--chromium/third_party/skia/tools/sk_app/VulkanWindowContext.cpp11
-rw-r--r--chromium/third_party/skia/tools/sk_app/VulkanWindowContext.h2
-rw-r--r--chromium/third_party/skia/tools/sk_app/Window.cpp2
-rw-r--r--chromium/third_party/skia/tools/sk_app/Window.h3
-rw-r--r--chromium/third_party/skia/tools/sk_app/win/D3D12WindowContext_win.cpp243
-rw-r--r--chromium/third_party/skia/tools/sk_app/win/WindowContextFactory_win.h4
-rw-r--r--chromium/third_party/skia/tools/sk_app/win/Window_win.cpp6
-rw-r--r--chromium/third_party/skia/tools/skiaserve/Response.cpp2
-rw-r--r--chromium/third_party/skia/tools/skottie-wasm-perf/skottie-wasm-perf.html24
-rw-r--r--chromium/third_party/skia/tools/skottie2movie.cpp1
-rw-r--r--chromium/third_party/skia/tools/skottie_ios_app/SkiaGLContext.mm2
-rw-r--r--chromium/third_party/skia/tools/skottie_ios_app/SkiaMetalContext.mm2
-rw-r--r--chromium/third_party/skia/tools/skp/page_sets/skia_css3gradients_desktop.py3
-rw-r--r--chromium/third_party/skia/tools/skpbench/README.md67
-rw-r--r--chromium/third_party/skia/tools/skpbench/skpbench.cpp67
-rwxr-xr-xchromium/third_party/skia/tools/skpbench/skpbench.py10
-rw-r--r--chromium/third_party/skia/tools/skqp/bad_gms.txt1
-rw-r--r--chromium/third_party/skia/tools/valgrind.supp16
-rw-r--r--chromium/third_party/skia/tools/viewer/GMSlide.cpp7
-rw-r--r--chromium/third_party/skia/tools/viewer/ImGuiLayer.cpp2
-rw-r--r--chromium/third_party/skia/tools/viewer/SKPSlide.cpp34
-rw-r--r--chromium/third_party/skia/tools/viewer/SKPSlide.h5
-rw-r--r--chromium/third_party/skia/tools/viewer/SkRiveSlide.cpp69
-rw-r--r--chromium/third_party/skia/tools/viewer/SkRiveSlide.h41
-rw-r--r--chromium/third_party/skia/tools/viewer/SkSLSlide.cpp19
-rw-r--r--chromium/third_party/skia/tools/viewer/SkSLSlide.h3
-rw-r--r--chromium/third_party/skia/tools/viewer/SkottieSlide.cpp15
-rw-r--r--chromium/third_party/skia/tools/viewer/SkottieSlide.h3
-rw-r--r--chromium/third_party/skia/tools/viewer/SvgSlide.cpp22
-rw-r--r--chromium/third_party/skia/tools/viewer/SvgSlide.h6
-rw-r--r--chromium/third_party/skia/tools/viewer/Viewer.cpp212
-rw-r--r--chromium/third_party/skia/tools/viewer/Viewer.h7
1187 files changed, 46312 insertions, 27413 deletions
diff --git a/chromium/third_party/skia/BUILD.gn b/chromium/third_party/skia/BUILD.gn
index 38f7e6e0fe0..1a0e55b8273 100644
--- a/chromium/third_party/skia/BUILD.gn
+++ b/chromium/third_party/skia/BUILD.gn
@@ -41,9 +41,6 @@ config("skia_public") {
if (!skia_enable_gpu) {
defines += [ "SK_SUPPORT_GPU=0" ]
}
- if (skia_enable_atlas_text) {
- defines += [ "SK_SUPPORT_ATLAS_TEXT=1" ]
- }
if (is_fuchsia) {
defines += fuchsia_defines
}
@@ -203,7 +200,7 @@ opts("avx") {
} else {
cflags = [ "-mavx" ]
if (is_mac && is_debug) {
- cflags += [ "-O1" ] # Work around skia:9709
+ cflags += [ "-fno-stack-check" ] # Work around skia:9709
}
}
}
@@ -216,7 +213,20 @@ opts("hsw") {
} else {
cflags = [ "-march=haswell" ]
if (is_mac && is_debug) {
- cflags += [ "-O1" ] # Work around skia:9709
+ cflags += [ "-fno-stack-check" ] # Work around skia:9709
+ }
+ }
+}
+
+opts("skx") {
+ enabled = is_x86
+ sources = skia_opts.skx_sources
+ if (is_win) {
+ cflags = [ "/arch:AVX512" ]
+ } else {
+ cflags = [ "-march=skylake-avx512" ]
+ if (is_mac && is_debug) {
+ cflags += [ "-fno-stack-check" ] # Work around skia:9709
}
}
}
@@ -256,6 +266,7 @@ template("optional") {
forward_variables_from(invoker,
"*",
[
+ "public",
"public_defines",
"public_deps",
"deps",
@@ -275,9 +286,21 @@ template("optional") {
optional("android_utils") {
enabled = skia_enable_android_utils
- public = [ "client_utils/android/FrontBufferedStream.h" ]
+ public = [
+ "client_utils/android/BRDAllocator.h",
+ "client_utils/android/BitmapRegionDecoder.h",
+ "client_utils/android/FrontBufferedStream.h",
+ ]
public_defines = [ "SK_ENABLE_ANDROID_UTILS" ]
- sources = [ "client_utils/android/FrontBufferedStream.cpp" ]
+ sources = [
+ "client_utils/android/BitmapRegionDecoder.cpp",
+ "client_utils/android/FrontBufferedStream.cpp",
+ ]
+}
+
+source_set("fontmgr_factory") {
+ configs += skia_library_configs
+ sources = [ skia_fontmgr_factory ]
}
optional("fontmgr_android") {
@@ -287,57 +310,84 @@ optional("fontmgr_android") {
":typeface_freetype",
"//third_party/expat",
]
+ public = [ "include/ports/SkFontMgr_android.h" ]
sources = [
"src/ports/SkFontMgr_android.cpp",
- "src/ports/SkFontMgr_android_factory.cpp",
"src/ports/SkFontMgr_android_parser.cpp",
+ "src/ports/SkFontMgr_android_parser.h",
]
}
optional("fontmgr_custom") {
- enabled = skia_enable_fontmgr_custom
+ enabled =
+ skia_enable_fontmgr_custom_directory ||
+ skia_enable_fontmgr_custom_embedded || skia_enable_fontmgr_custom_empty
deps = [ ":typeface_freetype" ]
- sources = [
- "src/ports/SkFontMgr_custom.cpp",
- "src/ports/SkFontMgr_custom.h",
- "src/ports/SkFontMgr_custom_directory.cpp",
- "src/ports/SkFontMgr_custom_directory_factory.cpp",
- "src/ports/SkFontMgr_custom_embedded.cpp",
- "src/ports/SkFontMgr_custom_empty.cpp",
+ public = [ "src/ports/SkFontMgr_custom.h" ]
+ sources = [ "src/ports/SkFontMgr_custom.cpp" ]
+}
+
+optional("fontmgr_custom_directory") {
+ enabled = skia_enable_fontmgr_custom_directory
+
+ deps = [
+ ":fontmgr_custom",
+ ":typeface_freetype",
]
+ public = [ "include/ports/SkFontMgr_directory.h" ]
+ sources = [ "src/ports/SkFontMgr_custom_directory.cpp" ]
+}
+
+optional("fontmgr_custom_embedded") {
+ enabled = skia_enable_fontmgr_custom_embedded
+
+ deps = [
+ ":fontmgr_custom",
+ ":typeface_freetype",
+ ]
+ sources = [ "src/ports/SkFontMgr_custom_embedded.cpp" ]
}
optional("fontmgr_custom_empty") {
enabled = skia_enable_fontmgr_custom_empty
- deps = [ ":typeface_freetype" ]
- sources = [
- "src/ports/SkFontMgr_custom.cpp",
- "src/ports/SkFontMgr_custom_empty.cpp",
- "src/ports/SkFontMgr_custom_empty_factory.cpp",
+ deps = [
+ ":fontmgr_custom",
+ ":typeface_freetype",
]
+ public = [ "include/ports/SkFontMgr_empty.h" ]
+ sources = [ "src/ports/SkFontMgr_custom_empty.cpp" ]
}
-optional("fontmgr_empty") {
- enabled = skia_enable_fontmgr_empty
- sources = [ "src/ports/SkFontMgr_empty_factory.cpp" ]
+optional("fontmgr_fontconfig") {
+ enabled = skia_enable_fontmgr_fontconfig
+
+ deps = [
+ ":typeface_freetype",
+ "//third_party:fontconfig",
+ ]
+ public = [ "include/ports/SkFontMgr_fontconfig.h" ]
+ sources = [ "src/ports/SkFontMgr_fontconfig.cpp" ]
}
-optional("fontmgr_fontconfig") {
- enabled = skia_use_freetype && skia_use_fontconfig
+optional("fontmgr_FontConfigInterface") {
+ enabled = skia_enable_fontmgr_FontConfigInterface
deps = [
":typeface_freetype",
"//third_party:fontconfig",
]
+ public = [
+ "include/ports/SkFontConfigInterface.h",
+ "include/ports/SkFontMgr_FontConfigInterface.h",
+ ]
sources = [
"src/ports/SkFontConfigInterface.cpp",
"src/ports/SkFontConfigInterface_direct.cpp",
"src/ports/SkFontConfigInterface_direct_factory.cpp",
+ "src/ports/SkFontConfigTypeface.h",
"src/ports/SkFontMgr_FontConfigInterface.cpp",
- "src/ports/SkFontMgr_fontconfig.cpp",
- "src/ports/SkFontMgr_fontconfig_factory.cpp",
]
}
@@ -351,43 +401,52 @@ optional("fontmgr_fuchsia") {
} else {
deps = [ "//sdk/fidl/fuchsia.fonts" ]
}
+ public = [ "src/ports/SkFontMgr_fuchsia.h" ]
+ sources = [ "src/ports/SkFontMgr_fuchsia.cpp" ]
+}
+
+optional("fontmgr_mac_ct") {
+ enabled = skia_use_fonthost_mac
+
+ public = [
+ "include/ports/SkFontMgr_mac_ct.h",
+ "include/ports/SkTypeface_mac.h",
+ ]
sources = [
- "src/ports/SkFontMgr_fuchsia.cpp",
- "src/ports/SkFontMgr_fuchsia.h",
+ "src/ports/SkFontMgr_mac_ct.cpp",
+ "src/ports/SkScalerContext_mac_ct.cpp",
+ "src/ports/SkScalerContext_mac_ct.h",
+ "src/ports/SkTypeface_mac_ct.cpp",
+ "src/ports/SkTypeface_mac_ct.h",
]
-}
-optional("fontmgr_wasm") {
- enabled = target_cpu == "wasm"
- deps = []
+ if (is_mac) {
+ libs = [
+ # AppKit symbols NSFontWeightXXX may be dlsym'ed.
+ "AppKit.framework",
+ "ApplicationServices.framework",
+ ]
+ }
- # custom_embedded has the source for both embedding a font in the binary
- # (only used for the all-included build) and reading in a font from
- # raw bytes passed over the wire (a typical way to load fonts).
- if (!skia_enable_fontmgr_empty) {
- deps += [ ":typeface_freetype" ]
- sources = [ "src/ports/SkFontMgr_custom_embedded.cpp" ]
-
- # If we haven't opted for no fonts (empty) or fonts, but not the
- # built-in one (custom), then, we need to provide the mechanism for
- # using the built-in font.
- if (!skia_enable_fontmgr_custom) {
- sources += [
- "src/ports/SkFontMgr_custom.cpp",
- "src/ports/SkFontMgr_custom.h",
- "src/ports/SkFontMgr_custom_embedded_factory.cpp",
- ]
- }
+ if (is_ios) {
+ libs = [
+ "CoreFoundation.framework",
+ "CoreGraphics.framework",
+ "CoreText.framework",
+
+ # UIKit symbols UIFontWeightXXX may be dlsym'ed.
+ "UIKit.framework",
+ ]
}
}
optional("fontmgr_win") {
enabled = skia_enable_fontmgr_win
+ public = [ "include/ports/SkTypeface_win.h" ]
sources = [
"src/fonts/SkFontMgr_indirect.cpp",
"src/ports/SkFontMgr_win_dw.cpp",
- "src/ports/SkFontMgr_win_dw_factory.cpp",
"src/ports/SkScalerContext_win_dw.cpp",
"src/ports/SkTypeface_win_dw.cpp",
]
@@ -396,6 +455,7 @@ optional("fontmgr_win") {
optional("fontmgr_win_gdi") {
enabled = skia_enable_fontmgr_win_gdi
+ public = [ "include/ports/SkTypeface_win.h" ]
sources = [ "src/ports/SkFontHost_win.cpp" ]
libs = [ "Gdi32.lib" ]
}
@@ -432,6 +492,7 @@ if (skia_lex) {
args = [
rebase_path(sksllex_path),
rebase_path("bin/clang-format"),
+ rebase_path("bin/fetch-clang-format"),
rebase_path("src"),
]
}
@@ -498,6 +559,7 @@ if (skia_compile_processors) {
args = [
rebase_path(skslc_path),
rebase_path("bin/clang-format"),
+ rebase_path("bin/fetch-clang-format"),
]
args += rebase_path(skia_gpu_processor_sources)
}
@@ -632,10 +694,6 @@ optional("gpu") {
cflags_objcc += [ "-fobjc-arc" ]
}
- if (skia_enable_atlas_text) {
- sources += skia_atlas_text_sources
- }
-
if (is_debug) {
public_defines += [ "SK_ENABLE_DUMP_GPU" ]
}
@@ -803,7 +861,31 @@ optional("webp_encode") {
optional("wuffs") {
enabled = skia_use_wuffs
- public_defines = [ "SK_HAS_WUFFS_LIBRARY" ]
+ public_defines = [
+ "SK_HAS_WUFFS_LIBRARY",
+ # SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2 is temporary, used during a multiple step
+ # transition (perhaps a month or two in mid 2020), distributed across
+ # multiple repositories:
+ #
+ # 1. Let Skia work with either Wuffs v0.3 or v0.2. The default everywhere
+ # remains at v0.2, but users may now opt in to v0.3.
+ # 2a. Update users' Skia version (automatic if they update regularly).
+ # 2b. Update users to the latest Wuffs rev, which provides both versions.
+ # 3a. Have users opt in to v0.3.
+ # 3b. Update Skia's default configuration (and those who copy it) to v0.3.
+ # 4. Flip Skia-uses-Wuffs-v0.3 from opt-in to opt-out.
+ # 5. Remove the option for Skia to work wih Wuffs v0.2, which will remove
+ # this SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2 macro as well as many #ifdef's
+ # in SkWuffsCodec.cpp.
+ #
+ # Steps 2a and 2b can occur concurrently. Similarly for 3a and 3b.
+ #
+ # "Users" means software that uses Skia+Wuffs, such as Chromium or Flutter.
+ #
+ # Uncommenting the next line (as well as changing "0.2" to "0.3" in
+ # "etc/wuffs-v0.2.c" in third_party/wuffs/BUILD.gn) is step 3b.
+ # "SK_FAVOR_WUFFS_V_0_3_OVER_V_0_2",
+ ]
deps = [ "//third_party/wuffs" ]
sources = [ "src/codec/SkWuffsCodec.cpp" ]
@@ -860,6 +942,16 @@ component("skia") {
configs += skia_library_configs
public_deps = [
+ ":fontmgr_FontConfigInterface",
+ ":fontmgr_android",
+ ":fontmgr_custom_directory",
+ ":fontmgr_custom_embedded",
+ ":fontmgr_custom_empty",
+ ":fontmgr_fontconfig",
+ ":fontmgr_fuchsia",
+ ":fontmgr_mac_ct",
+ ":fontmgr_win",
+ ":fontmgr_win_gdi",
":gpu",
":pdf",
":skcms",
@@ -873,15 +965,7 @@ component("skia") {
":avx",
":compile_processors",
":crc32",
- ":fontmgr_android",
- ":fontmgr_custom",
- ":fontmgr_custom_empty",
- ":fontmgr_empty",
- ":fontmgr_fontconfig",
- ":fontmgr_fuchsia",
- ":fontmgr_wasm",
- ":fontmgr_win",
- ":fontmgr_win_gdi",
+ ":fontmgr_factory",
":gif",
":heif",
":hsw",
@@ -893,6 +977,7 @@ component("skia") {
":raw",
":sksl_interpreter",
":skvm_jit",
+ ":skx",
":sse2",
":sse41",
":sse42",
@@ -922,8 +1007,6 @@ component("skia") {
sources += [
"src/android/SkAndroidFrameworkUtils.cpp",
"src/android/SkAnimatedImage.cpp",
- "src/android/SkBitmapRegionCodec.cpp",
- "src/android/SkBitmapRegionDecoder.cpp",
"src/codec/SkAndroidCodec.cpp",
"src/codec/SkAndroidCodecAdapter.cpp",
"src/codec/SkBmpBaseCodec.cpp",
@@ -999,10 +1082,6 @@ component("skia") {
}
}
- if (skia_use_fonthost_mac) {
- sources += [ "src/ports/SkFontHost_mac.cpp" ]
- }
-
if (is_mac) {
sources += [
"src/ports/SkDebug_stdio.cpp",
@@ -1010,8 +1089,6 @@ component("skia") {
"src/ports/SkImageGeneratorCG.cpp",
]
libs += [
- # AppKit symbols NSFontWeightXXX may be dlsym'ed.
- "AppKit.framework",
"ApplicationServices.framework",
"OpenGL.framework",
]
@@ -1020,19 +1097,13 @@ component("skia") {
if (is_ios) {
sources += [
"src/ports/SkDebug_stdio.cpp",
- "src/ports/SkFontHost_mac.cpp",
"src/ports/SkImageEncoder_CG.cpp",
"src/ports/SkImageGeneratorCG.cpp",
]
libs += [
"CoreFoundation.framework",
- "CoreGraphics.framework",
- "CoreText.framework",
"ImageIO.framework",
"MobileCoreServices.framework",
-
- # UIKit symbols UIFontWeightXXX may be dlsym'ed.
- "UIKit.framework",
]
}
@@ -1063,8 +1134,6 @@ if (target_cpu == "wasm") {
"tools/debugger/DrawCommand.cpp",
"tools/debugger/JsonWriteBuffer.cpp",
]
-
- deps = [ ":fontmgr_wasm" ]
}
}
@@ -1117,6 +1186,7 @@ static_library("pathkit") {
"src/core/SkPathRef.cpp",
"src/core/SkPoint.cpp",
"src/core/SkRRect.cpp",
+ "src/core/SkReadBuffer.cpp",
"src/core/SkRect.cpp",
"src/core/SkSemaphore.cpp",
"src/core/SkStream.cpp",
@@ -1142,11 +1212,9 @@ group("modules") {
deps = [
"modules/particles",
"modules/skottie",
+ "modules/skparagraph",
"modules/skshaper",
]
- if (target_cpu == "wasm") {
- deps += [ "modules/skparagraph" ]
- }
}
# Targets guarded by skia_enable_tools may use //third_party freely.
@@ -1154,7 +1222,6 @@ if (skia_enable_tools) {
skia_public_includes = [
"client_utils/android",
"include/android",
- "include/atlastext",
"include/c",
"include/codec",
"include/config",
@@ -1223,10 +1290,21 @@ if (skia_enable_tools) {
include_dirs = [ "include/third_party/vulkan" ]
}
+ config("cpp14") {
+ if (is_win) {
+ cflags_cc = [ "/std:c++14" ]
+ } else {
+ cflags_cc = [ "-std=c++14" ]
+ }
+ }
+
source_set("public_headers_warnings_check") {
sources = [ "tools/public_headers_warnings_check.cpp" ]
configs -= [ "//gn:warnings_except_public_headers" ]
- configs += [ ":our_vulkan_headers" ]
+ configs += [
+ ":our_vulkan_headers",
+ ":cpp14",
+ ]
deps = [
":skia",
":skia.h",
@@ -1350,10 +1428,8 @@ if (skia_enable_tools) {
libs = []
if (skia_use_gl) {
- sources += [
- "tools/gpu/atlastext/GLTestAtlasTextRenderer.cpp",
- "tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp",
- ]
+ sources +=
+ [ "tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp" ]
if (is_ios) {
sources += [ "tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm" ]
libs += [ "OpenGLES.framework" ]
@@ -1389,8 +1465,14 @@ if (skia_enable_tools) {
}
if (skia_use_vulkan) {
+ sources += [ "tools/gpu/vk/VkTestContext.h" ]
sources += [ "tools/gpu/vk/VkTestContext.cpp" ]
+ sources += [ "tools/gpu/vk/VkTestHelper.h" ]
+ sources += [ "tools/gpu/vk/VkTestHelper.cpp" ]
+ sources += [ "tools/gpu/vk/VkTestUtils.h" ]
sources += [ "tools/gpu/vk/VkTestUtils.cpp" ]
+ sources += [ "tools/gpu/vk/VkYcbcrSamplerHelper.h" ]
+ sources += [ "tools/gpu/vk/VkYcbcrSamplerHelper.cpp" ]
}
if (skia_use_metal) {
sources += [ "tools/gpu/mtl/MtlTestContext.mm" ]
@@ -1402,7 +1484,9 @@ if (skia_enable_tools) {
if (skia_use_dawn) {
public_deps += [ "//third_party/externals/dawn/src/dawn:dawn_headers" ]
sources += [ "tools/gpu/dawn/DawnTestContext.cpp" ]
- cflags_cc = [ "-Wno-microsoft-cast" ]
+ if (is_clang) {
+ cflags_cc = [ "-Wno-microsoft-cast" ]
+ }
}
if (is_fuchsia && using_fuchsia_sdk) {
@@ -1527,6 +1611,8 @@ if (skia_enable_tools) {
":tool_utils",
"modules/skottie",
"modules/skottie:gm",
+ "modules/skparagraph",
+ "modules/skparagraph:gm",
"modules/skshaper",
]
if (is_skia_dev_build) {
@@ -1561,7 +1647,7 @@ if (skia_enable_tools) {
if (!skia_enable_fontmgr_android) {
sources -= [ "//tests/FontMgrAndroidParserTest.cpp" ]
}
- if (!(skia_use_freetype && skia_use_fontconfig)) {
+ if (!skia_enable_fontmgr_fontconfig) {
sources -= [ "//tests/FontMgrFontConfigTest.cpp" ]
}
deps = [
@@ -1570,6 +1656,7 @@ if (skia_enable_tools) {
":skia",
":skvm_builders",
":tool_utils",
+ "experimental/skrive:tests",
"modules/skottie:tests",
"modules/skparagraph:tests",
"modules/sksg:tests",
@@ -1711,6 +1798,10 @@ if (skia_enable_tools) {
}
}
if (target_cpu != "wasm") {
+ test_app("convert-to-nia") {
+ sources = [ "tools/convert-to-nia.cpp" ]
+ deps = [ ":skia" ]
+ }
test_app("imgcvt") {
sources = [ "tools/imgcvt.cpp" ]
deps = [
@@ -1806,7 +1897,7 @@ if (skia_enable_tools) {
":skia",
":tool_utils",
":trace",
- "modules/skparagraph:bench",
+ "modules/skparagraph",
"modules/skshaper",
]
}
@@ -1941,6 +2032,7 @@ if (skia_enable_tools) {
"fuzz/oss_fuzz/FuzzSKSL2Metal.cpp",
"fuzz/oss_fuzz/FuzzSKSL2Pipeline.cpp",
"fuzz/oss_fuzz/FuzzSKSL2SPIRV.cpp",
+ "fuzz/oss_fuzz/FuzzSVG.cpp",
"fuzz/oss_fuzz/FuzzSkDescriptorDeserialize.cpp",
"fuzz/oss_fuzz/FuzzTextBlobDeserialize.cpp",
"tools/UrlDataManager.cpp",
@@ -2066,10 +2158,7 @@ if (skia_enable_tools) {
test_app("skottie_android") {
is_shared_library = true
- sources = [
- "platform_tools/android/apps/skottie/src/main/cpp/JavaInputStreamAdaptor.cpp",
- "platform_tools/android/apps/skottie/src/main/cpp/native-lib.cpp",
- ]
+ sources = [ "platform_tools/android/apps/skottie/skottielib/src/main/cpp/native-lib.cpp" ]
libs = []
deps = [
@@ -2193,6 +2282,10 @@ if (skia_enable_tools) {
}
}
+ if (skia_use_direct3d) {
+ sources += [ "tools/sk_app/win/D3D12WindowContext_win.cpp" ]
+ }
+
if (skia_use_dawn) {
sources += [ "tools/sk_app/DawnWindowContext.cpp" ]
if (is_linux) {
@@ -2256,6 +2349,7 @@ if (skia_enable_tools) {
"tools/viewer/ParticlesSlide.cpp",
"tools/viewer/SKPSlide.cpp",
"tools/viewer/SampleSlide.cpp",
+ "tools/viewer/SkRiveSlide.cpp",
"tools/viewer/SkSLSlide.cpp",
"tools/viewer/SkottieSlide.cpp",
"tools/viewer/SlideDir.cpp",
@@ -2278,6 +2372,7 @@ if (skia_enable_tools) {
":skia",
":tool_utils",
":trace",
+ "experimental/skrive",
"modules/particles",
"modules/skottie",
"modules/skottie:utils",
@@ -2288,6 +2383,9 @@ if (skia_enable_tools) {
deps += [ ":experimental_xform" ]
sources += [ "gm/xform.cpp" ]
}
+ if (skia_use_vulkan) {
+ deps += [ "//third_party/spirv-tools:spvtools" ]
+ }
}
}
@@ -2306,8 +2404,7 @@ if (skia_enable_tools) {
}
}
- if (skia_use_gl && (is_linux || is_mac || is_ios) &&
- target_cpu != "mips64el" && target_cpu != "loongson3a") {
+ if (skia_use_gl && (is_linux || is_mac || is_ios)) {
test_app("SkiaSDLExample") {
sources = [ "example/SkiaSDLExample.cpp" ]
libs = []
diff --git a/chromium/third_party/skia/DEPS b/chromium/third_party/skia/DEPS
index 243cbfd0845..5b14f6d7b81 100644
--- a/chromium/third_party/skia/DEPS
+++ b/chromium/third_party/skia/DEPS
@@ -7,14 +7,14 @@ vars = {
deps = {
"buildtools" : "https://chromium.googlesource.com/chromium/buildtools.git@505de88083136eefd056e5ee4ca0f01fe9b33de8",
"common" : "https://skia.googlesource.com/common.git@9737551d7a52c3db3262db5856e6bcd62c462b92",
- "third_party/externals/angle2" : "https://chromium.googlesource.com/angle/angle.git@664376e20ab2e72b482a5790cbe5e4c9b9b6872f",
+ "third_party/externals/angle2" : "https://chromium.googlesource.com/angle/angle.git@6ef0387d581d9178177ee125777d025b16dcee85",
# Dawn requires jinja2 and markupsafe for the code generator, and glslang and shaderc for SPIRV compilation.
# When the Dawn revision is updated these should be updated from the Dawn DEPS as well.
- "third_party/externals/dawn" : "https://dawn.googlesource.com/dawn.git@75ef5963b477ceb3cfb8e4c6c666346dba6f08cd",
- "third_party/externals/glslang" : "https://chromium.googlesource.com/external/github.com/KhronosGroup/glslang@4fa68edd68197a8c77779942b5d973f89c621752",
+ "third_party/externals/dawn" : "https://dawn.googlesource.com/dawn.git@2a6cc4f8fb40beb27a3542528955df7790a42116",
+ "third_party/externals/glslang" : "https://chromium.googlesource.com/external/github.com/KhronosGroup/glslang@839704450200e407490c538418f4d1a493b789ab",
"third_party/externals/jinja2" : "https://chromium.googlesource.com/chromium/src/third_party/jinja2@b41863e42637544c2941b574c7877d3e1f663e25",
"third_party/externals/markupsafe" : "https://chromium.googlesource.com/chromium/src/third_party/markupsafe@8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
- "third_party/externals/shaderc" : "https://chromium.googlesource.com/external/github.com/google/shaderc@00ac5d82178cfb5679fe19194d5794fdb01cdd00",
+ "third_party/externals/shaderc" : "https://chromium.googlesource.com/external/github.com/google/shaderc@caa519ca532a6a3a0279509fce2ceb791c4f4651",
"third_party/externals/dng_sdk" : "https://android.googlesource.com/platform/external/dng_sdk.git@c8d0c9b1d16bfda56f15165d39e0ffa360a11123",
"third_party/externals/egl-registry" : "https://skia.googlesource.com/external/github.com/KhronosGroup/EGL-Registry@a0bca08de07c7d7651047bedc0b653cfaaa4f2ae",
"third_party/externals/expat" : "https://chromium.googlesource.com/external/github.com/libexpat/libexpat.git@e976867fb57a0cd87e3b0fe05d59e0ed63c6febb",
@@ -34,16 +34,16 @@ deps = {
"third_party/externals/piex" : "https://android.googlesource.com/platform/external/piex.git@bb217acdca1cc0c16b704669dd6f91a1b509c406",
"third_party/externals/sdl" : "https://skia.googlesource.com/third_party/sdl@5d7cfcca344034aff9327f77fc181ae3754e7a90",
"third_party/externals/sfntly" : "https://chromium.googlesource.com/external/github.com/googlei18n/sfntly.git@b55ff303ea2f9e26702b514cf6a3196a2e3e2974",
- "third_party/externals/spirv-cross" : "https://chromium.googlesource.com/external/github.com/KhronosGroup/SPIRV-Cross@7e0295abf81cc939ecb2644c88592d77407d18d3",
+ "third_party/externals/spirv-cross" : "https://chromium.googlesource.com/external/github.com/KhronosGroup/SPIRV-Cross@d385bf096f5dabbc4cdaeb6872b0f64be1a63ad0",
"third_party/externals/spirv-headers" : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Headers.git@c0df742ec0b8178ad58c68cff3437ad4b6a06e26",
"third_party/externals/spirv-tools" : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Tools.git@e95fbfb1f509ad7a7fdfb72ac35fe412d72fc4a4",
- "third_party/externals/swiftshader" : "https://swiftshader.googlesource.com/SwiftShader@d748e1651af8254eec5d4f5c561713dc85d14ab6",
+ "third_party/externals/swiftshader" : "https://swiftshader.googlesource.com/SwiftShader@eb0a25a189b75d950ae4f87c00f8d63f190d82a0",
#"third_party/externals/v8" : "https://chromium.googlesource.com/v8/v8.git@5f1ae66d5634e43563b2d25ea652dfb94c31a3b4",
- "third_party/externals/wuffs" : "https://skia.googlesource.com/external/github.com/google/wuffs.git@4080840928c0b05a80cda0d14ac2e2615f679f1a",
- "third_party/externals/zlib" : "https://chromium.googlesource.com/chromium/src/third_party/zlib@47af7c547f8551bd25424e56354a2ae1e9062859",
+ "third_party/externals/wuffs" : "https://skia.googlesource.com/external/github.com/google/wuffs.git@00cc8a50aa0c86b6bcb37e9ece8fb100047cc17b",
+ "third_party/externals/zlib" : "https://chromium.googlesource.com/chromium/src/third_party/zlib@eaf99a4e2009b0e5759e6070ad1760ac1dd75461",
"../src": {
- "url": "https://chromium.googlesource.com/chromium/src.git@a6a8a49a207789813f4b57bd8ec5a006037c1f76",
+ "url": "https://chromium.googlesource.com/chromium/src.git@6d759c2e5e1f8b1239a87c5f23123dbbe42789d7",
"condition": "checkout_chromium",
},
}
diff --git a/chromium/third_party/skia/RELEASE_NOTES.txt b/chromium/third_party/skia/RELEASE_NOTES.txt
index 88db0595385..07737029bcf 100644
--- a/chromium/third_party/skia/RELEASE_NOTES.txt
+++ b/chromium/third_party/skia/RELEASE_NOTES.txt
@@ -4,7 +4,71 @@ This file includes a list of high level updates for each milestone release.
* * *
+Milestone 85
+------------
+
+ * Added GrContext::oomed() which reports whether Skia has seen a GL_OUT_OF_MEMORY
+ error from Open GL [ES] or VK_ERROR_OUT_OF_*_MEMORY from Vulkan.
+ https://review.skia.org/298216
+
+ * Add option on SkSurface::flush to pass in a GrBackendSurfaceMutableState which
+ we will set the gpu backend surface to be at the end of the flush.
+ https://review.skia.org/295567
+
+ * Add GrContext function to set mutable state on a backend surface. Currently this
+ is only used for setting vulkan VkImage layout and queue family.
+ https://review.skia.org/293844
+
+ * SkSurface factores that take GrBackendTexture or GrBackendRenderTarget now always
+ call the release proc (if provided) on failure. SkSurface::replaceBackendTexture
+ also calls the release proc on failure.
+ https://review.skia.org/293762
+
+ * SkSurface::asyncRescaleAndReadPixels and SkSurfaceasyncRescaleAndReadPixelsYUV420
+ now require explicit GrContext submit to guarantee finite time before callback
+ is invoked.
+ https://review.skia.org/292840
+
+ * Add VkSharingMode field to GrVkImageInfo.
+ https://review.skia.org/293559
+
+ * Move SkBitmapRegionDecoder into client_utils/android.
+
+ * SkCanvas.clear and SkCanvas.drawColor now accept SkColor4f in addition to SkColor.
+
+ * Remove SkSurface::MakeFromBackendTextureAsRenderTarget.
+ This factory existed to work around issues with GL_TEXTURE_RECTANGLE that existed
+ in Chrome's command buffer. Those issues have since been resolved. Use
+ SkSurface::MakeFromBackendTexutre or SkSurface::MakeFromBackendRenderTarget instead.
+ https://review.skia.org/292719
+
+ * Adds submittedProc callback to GrFlushInfo which will be called when the work
+ from the flush call is submitted to the GPU. This is specifically useful for knowing
+ when semahpores sent with the flush have been submitted and can be waiting on.
+ https://review.skia.org/291078
+
+ * GrContext submit is now required to be called in order to send GPU work to the
+ actual GPU. The flush calls simply produces 3D API specific objects that are ready
+ to be submitted (e.g. command buffers). For the GL backend, the flush will still
+ send commands to the driver. However, clients should still assume the must call
+ submit which is where any glFlush that is need for sync objects will be called. There,
+ are flushAndSubmit() functions of GrContext, SkSurface, and SkImage that will act
+ like the previous flush() functions. This will flush the work and immediately call
+ submit.
+ https://review.skia.org/289033
+
+ * Remove deprecated version of flush calls on GrContext and SkSurface.
+ https://review.skia.org/2290540
+
+ * SkCanvas::drawVertices and drawPatch now support mapping an SkShader without explicit
+ texture coordinates. If they're not supplied, the local positions (vertex position or
+ patch cubic positions) will be directly used to sample the SkShader.
+ https://review.skia.org/290130
+
+* * *
+
Milestone 84
+------------
* Add api on GrContext, updateBackendTexture that will upload new data to a
GrBackendTexture.
@@ -67,6 +131,7 @@ Milestone 84
* * *
Milestone 83
+------------
* Remove localmatrix option from SkShaders::[Blend, Lerp]
@@ -83,6 +148,7 @@ Milestone 83
* * *
Milestone 82
+------------
* Removed drawBitmap and related functions from SkDevice; all public drawBitmap functions on
SkCanvas automatically wrap the bitmap in an SkImage and call the equivalent drawImage function.
@@ -149,6 +215,7 @@ Milestone 82
* * *
Milestone 81
+------------
* Added support for GL_NV_fence extension.
@@ -194,6 +261,7 @@ Milestone 81
* * *
Milestone 80
+------------
* For Vulkan backend, we now require that the VkDevice, Queue, and Instance outlive
either the destruction or abandoning of the GrContext. Additionally, all
@@ -235,6 +303,7 @@ Milestone 80
* * *
Milestone 79
+------------
* SkTextBlob::Iter to discover the glyph indices and typefaces in each run
https://skia-review.googlesource.com/246296
@@ -299,6 +368,7 @@ Milestone 79
* * *
Milestone 78
+------------
* SkDrawLooper is no longer supported in SkPaint or SkCanvas.
https://review.skia.org/230579
diff --git a/chromium/third_party/skia/bench/BitmapRegionDecoderBench.cpp b/chromium/third_party/skia/bench/BitmapRegionDecoderBench.cpp
index 52014b95064..c762373f62f 100644
--- a/chromium/third_party/skia/bench/BitmapRegionDecoderBench.cpp
+++ b/chromium/third_party/skia/bench/BitmapRegionDecoderBench.cpp
@@ -6,7 +6,9 @@
*/
#include "bench/BitmapRegionDecoderBench.h"
+#ifdef SK_ENABLE_ANDROID_UTILS
#include "bench/CodecBenchPriv.h"
+#include "client_utils/android/BitmapRegionDecoder.h"
#include "include/core/SkBitmap.h"
#include "src/core/SkOSFile.h"
@@ -36,7 +38,7 @@ bool BitmapRegionDecoderBench::isSuitableFor(Backend backend) {
}
void BitmapRegionDecoderBench::onDelayedSetup() {
- fBRD.reset(SkBitmapRegionDecoder::Create(fData, SkBitmapRegionDecoder::kAndroidCodec_Strategy));
+ fBRD = android::skia::BitmapRegionDecoder::Make(fData);
}
void BitmapRegionDecoderBench::onDraw(int n, SkCanvas* canvas) {
@@ -47,3 +49,4 @@ void BitmapRegionDecoderBench::onDraw(int n, SkCanvas* canvas) {
SkAssertResult(fBRD->decodeRegion(&bm, nullptr, fSubset, fSampleSize, ct, false, cs));
}
}
+#endif // SK_ENABLE_ANDROID_UTILS
diff --git a/chromium/third_party/skia/bench/BitmapRegionDecoderBench.h b/chromium/third_party/skia/bench/BitmapRegionDecoderBench.h
index 3d3372f4d61..5e87ea8b153 100644
--- a/chromium/third_party/skia/bench/BitmapRegionDecoderBench.h
+++ b/chromium/third_party/skia/bench/BitmapRegionDecoderBench.h
@@ -9,12 +9,18 @@
#define BitmapRegionDecoderBench_DEFINED
#include "bench/Benchmark.h"
-#include "include/android/SkBitmapRegionDecoder.h"
+#ifdef SK_ENABLE_ANDROID_UTILS
#include "include/core/SkData.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkString.h"
+namespace android {
+namespace skia {
+class BitmapRegionDecoder;
+}
+}
+
/**
* Benchmark Android's BitmapRegionDecoder for a particular colorType, sampleSize, and subset.
*
@@ -34,12 +40,13 @@ protected:
void onDelayedSetup() override;
private:
- SkString fName;
- std::unique_ptr<SkBitmapRegionDecoder> fBRD;
- sk_sp<SkData> fData;
- const SkColorType fColorType;
- const uint32_t fSampleSize;
- const SkIRect fSubset;
+ SkString fName;
+ std::unique_ptr<android::skia::BitmapRegionDecoder> fBRD;
+ sk_sp<SkData> fData;
+ const SkColorType fColorType;
+ const uint32_t fSampleSize;
+ const SkIRect fSubset;
typedef Benchmark INHERITED;
};
+#endif // SK_ENABLE_ANDROID_UTILS
#endif // BitmapRegionDecoderBench_DEFINED
diff --git a/chromium/third_party/skia/bench/BulkRectBench.cpp b/chromium/third_party/skia/bench/BulkRectBench.cpp
index 71f9c3bab3a..53132047eb2 100644
--- a/chromium/third_party/skia/bench/BulkRectBench.cpp
+++ b/chromium/third_party/skia/bench/BulkRectBench.cpp
@@ -12,7 +12,6 @@
#include "include/gpu/GrContext.h"
#include "include/utils/SkRandom.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/SkGr.h"
@@ -150,7 +149,7 @@ protected:
SkSimpleMatrixProvider matrixProvider(view);
GrPaint grPaint;
SkPaintToGrPaint(context, rtc->colorInfo(), paint, matrixProvider, &grPaint);
- rtc->drawQuadSet(GrNoClip(), std::move(grPaint), GrAA::kYes, view, batch, kRectCount);
+ rtc->drawQuadSet(nullptr, std::move(grPaint), GrAA::kYes, view, batch, kRectCount);
}
void drawSolidColorsRef(SkCanvas* canvas) const {
@@ -227,6 +226,15 @@ protected:
}
}
+ void onPerCanvasPostDraw(SkCanvas* canvas) override {
+ for (int i = 0; i < kImageCount; ++i) {
+ // For Vulkan we need to make sure the bench isn't holding onto any refs to the
+ // GrContext when we go to delete the vulkan context (which happens before the bench is
+ // deleted). So reset all the images here so they aren't holding GrContext refs.
+ fImages[i].reset();
+ }
+ }
+
void onDraw(int loops, SkCanvas* canvas) override {
for (int i = 0; i < loops; i++) {
if (kImageMode == ImageMode::kNone) {
diff --git a/chromium/third_party/skia/bench/ClipMaskBench.cpp b/chromium/third_party/skia/bench/ClipMaskBench.cpp
index c030b4a7f4d..d9c192795b5 100644
--- a/chromium/third_party/skia/bench/ClipMaskBench.cpp
+++ b/chromium/third_party/skia/bench/ClipMaskBench.cpp
@@ -14,59 +14,6 @@
#include "include/core/SkSurface.h"
#include "tools/ToolUtils.h"
-static void DrawMask(SkCanvas* canvas) {
- ToolUtils::draw_checkerboard(canvas, SK_ColorTRANSPARENT, SK_ColorGREEN, 10);
-}
-
-class ClipMaskBench : public Benchmark {
-public:
- using MaskMakerFunc = sk_sp<SkImage> (*)(int);
-
- ClipMaskBench(const char name[], const MaskMakerFunc maskMaker)
- : fName(SkStringPrintf("clipmask_%s", name))
- , fClip(maskMaker(kSize)) {}
-
-protected:
- const char* onGetName() override { return fName.c_str(); }
-
- void onDraw(int loops, SkCanvas* canvas) override {
- SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, fClip.get(), nullptr, 0);
-
- for (int i = 0; i < loops; ++i) {
- canvas->saveLayer(rec);
- canvas->drawColor(SK_ColorBLUE);
- canvas->restore();
- }
- }
-
-private:
- static constexpr int kSize = 400;
-
- SkString fName;
- sk_sp<SkImage> fClip;
-};
-
-DEF_BENCH(return new ClipMaskBench("a8", [](int size) -> sk_sp<SkImage> {
- sk_sp<SkSurface> surface = SkSurface::MakeRaster(SkImageInfo::MakeA8(size, size));
- DrawMask(surface->getCanvas());
- return surface->makeImageSnapshot();
-});)
-
-DEF_BENCH(return new ClipMaskBench("8888", [](int size) -> sk_sp<SkImage> {
- sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(size, size);
- DrawMask(surface->getCanvas());
- return surface->makeImageSnapshot();
-});)
-
-DEF_BENCH(return new ClipMaskBench("picture", [](int size) -> sk_sp<SkImage> {
- SkPictureRecorder recorder;
- DrawMask(recorder.beginRecording(size, size));
- return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(), SkISize::Make(size, size),
- nullptr, nullptr, SkImage::BitDepth::kU8,
- SkColorSpace::MakeSRGB());
-});)
-
-/////////
#include "include/core/SkPath.h"
#include "include/core/SkSurface.h"
diff --git a/chromium/third_party/skia/bench/ColorFilterBench.cpp b/chromium/third_party/skia/bench/ColorFilterBench.cpp
index 6757a0a4332..dd647c20957 100644
--- a/chromium/third_party/skia/bench/ColorFilterBench.cpp
+++ b/chromium/third_party/skia/bench/ColorFilterBench.cpp
@@ -138,8 +138,7 @@ const char RuntimeColorMatrix_GPU_SRC[] = R"(
m10, m11, m12, m13, m14,
m15, m16, m17, m18, m19;
void main(inout half4 c) {
- half nonZeroAlpha = max(c.a, 0.0001);
- c = half4(c.rgb / nonZeroAlpha, nonZeroAlpha);
+ c = unpremul(c);
half4x4 m = half4x4(m0, m5, m10, m15,
m1, m6, m11, m16,
diff --git a/chromium/third_party/skia/bench/CoverageBench.cpp b/chromium/third_party/skia/bench/CoverageBench.cpp
index 9d5411ed8ec..c94fa506d01 100644
--- a/chromium/third_party/skia/bench/CoverageBench.cpp
+++ b/chromium/third_party/skia/bench/CoverageBench.cpp
@@ -13,6 +13,7 @@
#include "include/core/SkPath.h"
#include "src/core/SkAutoPixmapStorage.h"
#include "src/core/SkDraw.h"
+#include "src/core/SkMatrixProvider.h"
#include "src/core/SkRasterClip.h"
class DrawPathBench : public Benchmark {
diff --git a/chromium/third_party/skia/bench/CreateBackendTextureBench.cpp b/chromium/third_party/skia/bench/CreateBackendTextureBench.cpp
index ab2afa7227b..9d3c4514150 100644
--- a/chromium/third_party/skia/bench/CreateBackendTextureBench.cpp
+++ b/chromium/third_party/skia/bench/CreateBackendTextureBench.cpp
@@ -44,6 +44,7 @@ private:
GrFlushInfo info;
info.fFlags = kSyncCpu_GrFlushFlag;
context->flush(info);
+ context->submit(true);
for (int i = 0; i < fBackendTextures.count(); ++i) {
if (fBackendTextures[i].isValid()) {
diff --git a/chromium/third_party/skia/bench/DashBench.cpp b/chromium/third_party/skia/bench/DashBench.cpp
index 99ca57635e3..df014a846af 100644
--- a/chromium/third_party/skia/bench/DashBench.cpp
+++ b/chromium/third_party/skia/bench/DashBench.cpp
@@ -151,7 +151,7 @@ static void make_unit_star(SkPath* path, int n) {
static void make_poly(SkPath* path) {
make_unit_star(path, 9);
- const SkMatrix matrix = SkMatrix::MakeScale(SkIntToScalar(100), SkIntToScalar(100));
+ const SkMatrix matrix = SkMatrix::Scale(100, 100);
path->transform(matrix);
}
diff --git a/chromium/third_party/skia/bench/DrawBitmapAABench.cpp b/chromium/third_party/skia/bench/DrawBitmapAABench.cpp
index 52a92f7a528..e57ecd9c664 100644
--- a/chromium/third_party/skia/bench/DrawBitmapAABench.cpp
+++ b/chromium/third_party/skia/bench/DrawBitmapAABench.cpp
@@ -54,11 +54,11 @@ private:
typedef Benchmark INHERITED;
};
-DEF_BENCH( return new DrawBitmapAABench(false, SkMatrix::MakeScale(1), "ident"); )
+DEF_BENCH( return new DrawBitmapAABench(false, SkMatrix::I(), "ident"); )
-DEF_BENCH( return new DrawBitmapAABench(false, SkMatrix::MakeScale(1.17f), "scale"); )
+DEF_BENCH( return new DrawBitmapAABench(false, SkMatrix::Scale(1.17f, 1.17f), "scale"); )
-DEF_BENCH( return new DrawBitmapAABench(false, SkMatrix::MakeTrans(17.5f, 17.5f), "translate"); )
+DEF_BENCH( return new DrawBitmapAABench(false, SkMatrix::Translate(17.5f, 17.5f), "translate"); )
DEF_BENCH(
SkMatrix m;
@@ -67,11 +67,11 @@ DEF_BENCH(
return new DrawBitmapAABench(false, m, "rotate");
)
-DEF_BENCH( return new DrawBitmapAABench(true, SkMatrix::MakeScale(1), "ident"); )
+DEF_BENCH( return new DrawBitmapAABench(true, SkMatrix::I(), "ident"); )
-DEF_BENCH( return new DrawBitmapAABench(true, SkMatrix::MakeScale(1.17f), "scale"); )
+DEF_BENCH( return new DrawBitmapAABench(true, SkMatrix::Scale(1.17f, 1.17f), "scale"); )
-DEF_BENCH( return new DrawBitmapAABench(true, SkMatrix::MakeTrans(17.5f, 17.5f), "translate"); )
+DEF_BENCH( return new DrawBitmapAABench(true, SkMatrix::Translate(17.5f, 17.5f), "translate"); )
DEF_BENCH(
SkMatrix m;
diff --git a/chromium/third_party/skia/bench/HairlinePathBench.cpp b/chromium/third_party/skia/bench/HairlinePathBench.cpp
index d57f616706b..5e29a136dc1 100644
--- a/chromium/third_party/skia/bench/HairlinePathBench.cpp
+++ b/chromium/third_party/skia/bench/HairlinePathBench.cpp
@@ -60,7 +60,7 @@ protected:
SkPath path;
this->makePath(&path);
if (fFlags & kBig_Flag) {
- const SkMatrix m = SkMatrix::MakeScale(SkIntToScalar(3), SkIntToScalar(3));
+ const SkMatrix m = SkMatrix::Scale(3, 3);
path.transform(m);
}
diff --git a/chromium/third_party/skia/bench/ImageCacheBudgetBench.cpp b/chromium/third_party/skia/bench/ImageCacheBudgetBench.cpp
index 0a98a96dfb5..5720368a6c1 100644
--- a/chromium/third_party/skia/bench/ImageCacheBudgetBench.cpp
+++ b/chromium/third_party/skia/bench/ImageCacheBudgetBench.cpp
@@ -46,12 +46,12 @@ void set_cache_budget(SkCanvas* canvas, int approxImagesInBudget) {
// to render an SkImage and add one additional resource for each image we'd like to fit.
GrContext* context = canvas->getGrContext();
SkASSERT(context);
- context->flush();
+ context->flushAndSubmit();
context->priv().testingOnly_purgeAllUnlockedResources();
sk_sp<SkImage> image;
make_images(&image, 1);
draw_image(canvas, image.get());
- context->flush();
+ context->flushAndSubmit();
int baselineCount;
context->getResourceCacheUsage(&baselineCount, nullptr);
baselineCount -= 1; // for the image's textures.
diff --git a/chromium/third_party/skia/bench/ImageCycleBench.cpp b/chromium/third_party/skia/bench/ImageCycleBench.cpp
index 1bb38d05ac0..548e345aad2 100644
--- a/chromium/third_party/skia/bench/ImageCycleBench.cpp
+++ b/chromium/third_party/skia/bench/ImageCycleBench.cpp
@@ -74,7 +74,7 @@ protected:
}
// Prevent any batching between "frames".
if (auto surf = canvas->getSurface()) {
- surf->flush();
+ surf->flushAndSubmit();
}
}
}
diff --git a/chromium/third_party/skia/bench/MatrixBench.cpp b/chromium/third_party/skia/bench/MatrixBench.cpp
index 7248d01f245..c2f5ea0a510 100644
--- a/chromium/third_party/skia/bench/MatrixBench.cpp
+++ b/chromium/third_party/skia/bench/MatrixBench.cpp
@@ -266,7 +266,7 @@ DEF_BENCH( return new InvertMapRectMatrixBench(
///////////////////////////////////////////////////////////////////////////////
-static SkMatrix make_trans() { return SkMatrix::MakeTrans(2, 3); }
+static SkMatrix make_trans() { return SkMatrix::Translate(2, 3); }
static SkMatrix make_scale() { SkMatrix m(make_trans()); m.postScale(1.5f, 0.5f); return m; }
static SkMatrix make_afine() { SkMatrix m(make_trans()); m.postRotate(15); return m; }
diff --git a/chromium/third_party/skia/bench/PathBench.cpp b/chromium/third_party/skia/bench/PathBench.cpp
index e78080b37bf..93824bc3452 100644
--- a/chromium/third_party/skia/bench/PathBench.cpp
+++ b/chromium/third_party/skia/bench/PathBench.cpp
@@ -58,7 +58,7 @@ protected:
SkPath path;
this->makePath(&path);
if (fFlags & kBig_Flag) {
- const SkMatrix m = SkMatrix::MakeScale(SkIntToScalar(10), SkIntToScalar(10));
+ const SkMatrix m = SkMatrix::Scale(10, 10);
path.transform(m);
}
diff --git a/chromium/third_party/skia/bench/PathOpsBench.cpp b/chromium/third_party/skia/bench/PathOpsBench.cpp
index c7df558bce1..9d86c2b8981 100644
--- a/chromium/third_party/skia/bench/PathOpsBench.cpp
+++ b/chromium/third_party/skia/bench/PathOpsBench.cpp
@@ -78,8 +78,6 @@ protected:
private:
typedef Benchmark INHERITED;
};
-
-
DEF_BENCH( return new PathOpsBench("sect", kIntersect_SkPathOp); )
DEF_BENCH( return new PathOpsBench("join", kUnion_SkPathOp); )
@@ -94,5 +92,131 @@ static SkPath makerects() {
}
return path;
}
-
DEF_BENCH( return new PathOpsSimplifyBench("rects", makerects()); )
+
+#include "include/core/SkPathBuilder.h"
+
+template <size_t N> struct ArrayPath {
+ SkPoint fPts[N];
+ uint8_t fVbs[N];
+ int fPIndex = 0, fVIndex = 0;
+
+ void moveTo(float x, float y) {
+ fVbs[fVIndex++] = (uint8_t)SkPathVerb::kMove;
+ fPts[fPIndex++] = {x, y};
+ }
+ void lineTo(float x, float y) {
+ fVbs[fVIndex++] = (uint8_t)SkPathVerb::kLine;
+ fPts[fPIndex++] = {x, y};
+ }
+ void quadTo(float x, float y, float x1, float y1) {
+ fVbs[fVIndex++] = (uint8_t)SkPathVerb::kQuad;
+ fPts[fPIndex++] = {x, y};
+ fPts[fPIndex++] = {x1, y1};
+ }
+ void cubicTo(float x, float y, float x1, float y1, float x2, float y2) {
+ fVbs[fVIndex++] = (uint8_t)SkPathVerb::kCubic;
+ fPts[fPIndex++] = {x, y};
+ fPts[fPIndex++] = {x1, y1};
+ fPts[fPIndex++] = {x2, y2};
+ }
+ void incReserve(int) {}
+};
+
+template <typename T> void run_builder(T& b, bool useReserve, int N) {
+ if (useReserve) {
+ b.incReserve(N * 12);
+ }
+
+ float x = 0, y = 0;
+ b.moveTo(x, y);
+ for (int i = 1; i < N; ++i) {
+ b.lineTo(x, y);
+ b.quadTo(x, y, x, y);
+ b.cubicTo(x, y, x, y, x, y);
+ }
+}
+
+enum class MakeType {
+ kPath,
+ kSnapshot,
+ kDetach,
+ kArray,
+};
+
+class PathBuilderBench : public Benchmark {
+ SkString fName;
+ MakeType fMakeType;
+ bool fUseReserve;
+
+ enum { N = 100 };
+ ArrayPath<N*12> fArrays;
+
+public:
+ PathBuilderBench(MakeType mt, bool reserve) : fMakeType(mt), fUseReserve(reserve) {
+ const char* typenames[] = { "path", "snapshot", "detach", "arrays" };
+
+ fName.printf("makepath_%s_%s", typenames[(int)mt], reserve ? "reserve" : "noreserve");
+ }
+
+ bool isSuitableFor(Backend backend) override {
+ return backend == kNonRendering_Backend;
+ }
+
+protected:
+ const char* onGetName() override {
+ return fName.c_str();
+ }
+
+ void onDelayedSetup() override {
+ run_builder(fArrays, false, N);
+ }
+
+ SkPath build() {
+ switch (fMakeType) {
+ case MakeType::kSnapshot:
+ case MakeType::kDetach: {
+ SkPathBuilder b;
+ run_builder(b, fUseReserve, N);
+ return MakeType::kSnapshot == fMakeType ? b.snapshot() : b.detach();
+ }
+ case MakeType::kPath: {
+ SkPath p;
+ run_builder(p, fUseReserve, N);
+ return p;
+ }
+ case MakeType::kArray: {
+ // ArrayPath<N*12> arrays;
+ // run_builder(arrays, false, N);
+ return SkPathBuilder::Make(fArrays.fPts, fArrays.fPIndex,
+ fArrays.fVbs, fArrays.fVIndex,
+ nullptr, 0, SkPathFillType::kWinding);
+ }
+ }
+ return SkPath();
+ }
+
+ void onDraw(int loops, SkCanvas* canvas) override {
+ for (int i = 0; i < loops; i++) {
+ for (int j = 0; j < 100; ++j) {
+ SkPath result = this->build();
+ // force bounds calc as part of the test
+ if (!result.getBounds().isFinite()) {
+ SkDebugf("should never get here!\n");
+ return;
+ }
+ }
+ }
+ }
+
+private:
+ typedef Benchmark INHERITED;
+};
+DEF_BENCH( return new PathBuilderBench(MakeType::kPath, false); )
+DEF_BENCH( return new PathBuilderBench(MakeType::kSnapshot, false); )
+DEF_BENCH( return new PathBuilderBench(MakeType::kDetach, false); )
+DEF_BENCH( return new PathBuilderBench(MakeType::kPath, true); )
+DEF_BENCH( return new PathBuilderBench(MakeType::kSnapshot, true); )
+DEF_BENCH( return new PathBuilderBench(MakeType::kDetach, true); )
+
+DEF_BENCH( return new PathBuilderBench(MakeType::kArray, true); )
diff --git a/chromium/third_party/skia/bench/QuickRejectBench.cpp b/chromium/third_party/skia/bench/QuickRejectBench.cpp
index daad4d4a413..86f97c5e0b3 100644
--- a/chromium/third_party/skia/bench/QuickRejectBench.cpp
+++ b/chromium/third_party/skia/bench/QuickRejectBench.cpp
@@ -53,7 +53,7 @@ class ConcatBench : public Benchmark {
void onDraw(int loops, SkCanvas* canvas) override {
while (loops --> 0) {
- canvas->setMatrix(SkMatrix::MakeScale(3.0f));
+ canvas->setMatrix(SkMatrix::Scale(3, 3));
canvas->concat(fMatrix);
}
}
diff --git a/chromium/third_party/skia/bench/RectanizerBench.cpp b/chromium/third_party/skia/bench/RectanizerBench.cpp
index 24dc1fe1b5d..833a39f736c 100644
--- a/chromium/third_party/skia/bench/RectanizerBench.cpp
+++ b/chromium/third_party/skia/bench/RectanizerBench.cpp
@@ -10,7 +10,7 @@
#include "include/private/SkTDArray.h"
#include "include/utils/SkRandom.h"
-#include "src/core/SkMathPriv.h"
+#include "src/gpu/GrRectanizerPow2.h"
#include "src/gpu/GrRectanizerSkyline.h"
/**
@@ -29,6 +29,7 @@ public:
static const int kHeight = 1024;
enum RectanizerType {
+ kPow2_RectanizerType,
kSkyline_RectanizerType,
};
@@ -40,9 +41,15 @@ public:
RectanizerBench(RectanizerType rectanizerType, RectType rectType)
: fName("rectanizer_")
+ , fRectanizerType(rectanizerType)
, fRectType(rectType) {
- fName.append("skyline_");
+ if (kPow2_RectanizerType == fRectanizerType) {
+ fName.append("pow2_");
+ } else {
+ SkASSERT(kSkyline_RectanizerType == fRectanizerType);
+ fName.append("skyline_");
+ }
if (kRand_RectType == fRectType) {
fName.append("rand");
@@ -66,7 +73,12 @@ protected:
void onDelayedSetup() override {
SkASSERT(nullptr == fRectanizer.get());
- fRectanizer.reset(new GrRectanizerSkyline(kWidth, kHeight));
+ if (kPow2_RectanizerType == fRectanizerType) {
+ fRectanizer.reset(new GrRectanizerPow2(kWidth, kHeight));
+ } else {
+ SkASSERT(kSkyline_RectanizerType == fRectanizerType);
+ fRectanizer.reset(new GrRectanizerSkyline(kWidth, kHeight));
+ }
}
void onDraw(int loops, SkCanvas* canvas) override {
@@ -99,14 +111,21 @@ protected:
private:
SkString fName;
+ RectanizerType fRectanizerType;
RectType fRectType;
- std::unique_ptr<GrRectanizerSkyline> fRectanizer;
+ std::unique_ptr<GrRectanizer> fRectanizer;
typedef Benchmark INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
+DEF_BENCH(return new RectanizerBench(RectanizerBench::kPow2_RectanizerType,
+ RectanizerBench::kRand_RectType);)
+DEF_BENCH(return new RectanizerBench(RectanizerBench::kPow2_RectanizerType,
+ RectanizerBench::kRandPow2_RectType);)
+DEF_BENCH(return new RectanizerBench(RectanizerBench::kPow2_RectanizerType,
+ RectanizerBench::kSmallPow2_RectType);)
DEF_BENCH(return new RectanizerBench(RectanizerBench::kSkyline_RectanizerType,
RectanizerBench::kRand_RectType);)
DEF_BENCH(return new RectanizerBench(RectanizerBench::kSkyline_RectanizerType,
diff --git a/chromium/third_party/skia/bench/SKPAnimationBench.cpp b/chromium/third_party/skia/bench/SKPAnimationBench.cpp
index 8cb9d8d9454..2bd3efb2868 100644
--- a/chromium/third_party/skia/bench/SKPAnimationBench.cpp
+++ b/chromium/third_party/skia/bench/SKPAnimationBench.cpp
@@ -28,7 +28,7 @@ void SKPAnimationBench::onPerCanvasPreDraw(SkCanvas* canvas) {
void SKPAnimationBench::drawPicture() {
for (int j = 0; j < this->tileRects().count(); ++j) {
- SkMatrix trans = SkMatrix::MakeTrans(-1.f * this->tileRects()[j].fLeft,
+ SkMatrix trans = SkMatrix::Translate(-1.f * this->tileRects()[j].fLeft,
-1.f * this->tileRects()[j].fTop);
fAnimation->preConcatFrameMatrix(fAnimationTime.nextRangeF(0, 1000), fDevBounds, &trans);
this->surfaces()[j]->getCanvas()->drawPicture(this->picture(), &trans, nullptr);
diff --git a/chromium/third_party/skia/bench/SKPBench.cpp b/chromium/third_party/skia/bench/SKPBench.cpp
index 539a76c0617..f8a480e987a 100644
--- a/chromium/third_party/skia/bench/SKPBench.cpp
+++ b/chromium/third_party/skia/bench/SKPBench.cpp
@@ -118,7 +118,7 @@ void SKPBench::onDraw(int loops, SkCanvas* canvas) {
}
// Ensure the GrContext doesn't combine ops across draw loops.
if (GrContext* context = canvas->getGrContext()) {
- context->flush();
+ context->flushAndSubmit();
}
}
}
@@ -129,7 +129,7 @@ void SKPBench::drawMPDPicture() {
void SKPBench::drawPicture() {
for (int j = 0; j < fTileRects.count(); ++j) {
- const SkMatrix trans = SkMatrix::MakeTrans(-fTileRects[j].fLeft / fScale,
+ const SkMatrix trans = SkMatrix::Translate(-fTileRects[j].fLeft / fScale,
-fTileRects[j].fTop / fScale);
fSurfaces[j]->getCanvas()->drawPicture(fPic.get(), &trans, nullptr);
}
@@ -160,7 +160,7 @@ void SKPBench::getGpuStats(SkCanvas* canvas, SkTArray<SkString>* keys, SkTArray<
}
// TODO refactor this out if we want to test other subclasses of skpbench
- context->flush();
+ context->flushAndSubmit();
context->freeGpuResources();
context->resetContext();
context->priv().getGpu()->resetShaderCacheForTesting();
diff --git a/chromium/third_party/skia/bench/TessellatePathBench.cpp b/chromium/third_party/skia/bench/TessellatePathBench.cpp
index dc0daf7d093..7788d9b2923 100644
--- a/chromium/third_party/skia/bench/TessellatePathBench.cpp
+++ b/chromium/third_party/skia/bench/TessellatePathBench.cpp
@@ -10,6 +10,8 @@
#include "src/core/SkPathPriv.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrOpFlushState.h"
+#include "src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h"
+#include "src/gpu/tessellate/GrResolveLevelCounter.h"
#include "src/gpu/tessellate/GrTessellatePathOp.h"
#include "src/gpu/tessellate/GrWangsFormula.h"
#include "tools/ToolUtils.h"
@@ -32,6 +34,26 @@ static SkPath make_cubic_path() {
// pre-allocated CPU buffers, rather than allocating and mapping GPU buffers.
class BenchmarkTarget : public GrMeshDrawOp::Target {
public:
+ BenchmarkTarget() {
+ GrMockOptions mockOptions;
+ mockOptions.fDrawInstancedSupport = true;
+ mockOptions.fMaxTessellationSegments = 64;
+ mockOptions.fMapBufferFlags = GrCaps::kCanMap_MapFlag;
+ mockOptions.fConfigOptions[(int)GrColorType::kAlpha_8].fRenderability =
+ GrMockOptions::ConfigOptions::Renderability::kMSAA;
+ mockOptions.fConfigOptions[(int)GrColorType::kAlpha_8].fTexturable = true;
+ mockOptions.fIntegerSupport = true;
+
+ GrContextOptions ctxOptions;
+ ctxOptions.fGpuPathRenderers = GpuPathRenderers::kTessellation;
+
+ fMockContext = GrContext::MakeMock(&mockOptions, ctxOptions);
+ }
+ const GrContext* mockContext() const { return fMockContext.get(); }
+ const GrCaps& caps() const override { return *fMockContext->priv().caps(); }
+ GrResourceProvider* resourceProvider() const override {
+ return fMockContext->priv().resourceProvider();
+ }
void resetAllocator() { fAllocator.reset(); }
SkArenaAlloc* allocator() override { return &fAllocator; }
void putBackVertices(int vertices, size_t vertexStride) override { /* no-op */ }
@@ -39,10 +61,10 @@ public:
void* makeVertexSpace(size_t vertexSize, int vertexCount, sk_sp<const GrBuffer>*,
int* startVertex) override {
if (vertexSize * vertexCount > sizeof(fStaticVertexData)) {
- SK_ABORT(SkStringPrintf(
- "FATAL: wanted %zu bytes of static vertex data; only have %zu.\n",
- vertexSize * vertexCount, SK_ARRAY_COUNT(fStaticVertexData)).c_str());
+ SK_ABORT("FATAL: wanted %zu bytes of static vertex data; only have %zu.\n",
+ vertexSize * vertexCount, SK_ARRAY_COUNT(fStaticVertexData));
}
+ *startVertex = 0;
return fStaticVertexData;
}
@@ -50,9 +72,8 @@ public:
int drawCount, sk_sp<const GrBuffer>* buffer, size_t* offsetInBytes) override {
int staticBufferCount = (int)SK_ARRAY_COUNT(fStaticDrawIndexedIndirectData);
if (drawCount > staticBufferCount) {
- SK_ABORT(SkStringPrintf(
- "FATAL: wanted %i static drawIndexedIndirect elements; only have %i.\n",
- drawCount, staticBufferCount).c_str());
+ SK_ABORT("FATAL: wanted %i static drawIndexedIndirect elements; only have %i.\n",
+ drawCount, staticBufferCount);
}
return fStaticDrawIndexedIndirectData;
}
@@ -70,16 +91,15 @@ public:
UNIMPL(const GrAppliedClip* appliedClip() const)
UNIMPL(GrAppliedClip detachAppliedClip())
UNIMPL(const GrXferProcessor::DstProxyView& dstProxyView() const)
- UNIMPL(GrResourceProvider* resourceProvider() const)
UNIMPL(GrStrikeCache* strikeCache() const)
UNIMPL(GrAtlasManager* atlasManager() const)
UNIMPL(SkTArray<GrSurfaceProxy*, true>* sampledProxyArray())
- UNIMPL(const GrCaps& caps() const)
UNIMPL(GrDeferredUploadTarget* deferredUploadTarget())
#undef UNIMPL
private:
- SkPoint fStaticVertexData[(kNumCubicsInChalkboard + 2) * 5];
+ sk_sp<GrContext> fMockContext;
+ SkPoint fStaticVertexData[(kNumCubicsInChalkboard + 2) * 8];
GrDrawIndexedIndirectCommand fStaticDrawIndexedIndirectData[32];
SkSTArenaAlloc<1024 * 1024> fAllocator;
};
@@ -88,20 +108,29 @@ private:
class GrTessellatePathOp::TestingOnly_Benchmark : public Benchmark {
public:
TestingOnly_Benchmark(const char* subName, SkPath path, const SkMatrix& m)
- : fOp(m, path, GrPaint(), GrAAType::kMSAA) {
+ : fOp(m, path, GrPaint(), GrAAType::kMSAA, GrTessellationPathRenderer::OpFlags::kNone) {
fName.printf("tessellate_%s", subName);
}
const char* onGetName() override { return fName.c_str(); }
bool isSuitableFor(Backend backend) final { return backend == kNonRendering_Backend; }
- class MiddleOutInnerTrianglesBench;
- class OuterCubicsBench;
- class CubicWedgesBench;
- class WangsFormulaBench;
+ class prepareMiddleOutStencilGeometry;
+ class prepareMiddleOutStencilGeometry_indirect;
+ class prepareIndirectOuterCubics;
+ class prepareTessellatedOuterCubics;
+ class prepareTessellatedCubicWedges;
+ class wangs_formula_cubic_log2;
+ class wangs_formula_cubic_log2_scale;
+ class wangs_formula_cubic_log2_affine;
+ class middle_out_triangulation;
private:
void onDraw(int loops, SkCanvas*) final {
+ if (!fTarget.mockContext()) {
+ SkDebugf("ERROR: could not create mock context.");
+ return;
+ }
for (int i = 0; i < loops; ++i) {
fOp.fTriangleBuffer.reset();
fOp.fDoStencilTriangleBuffer = false;
@@ -120,83 +149,92 @@ private:
SkString fName;
};
-class GrTessellatePathOp::TestingOnly_Benchmark::MiddleOutInnerTrianglesBench
- : public GrTessellatePathOp::TestingOnly_Benchmark {
-public:
- MiddleOutInnerTrianglesBench()
- : TestingOnly_Benchmark("prepareMiddleOutInnerTriangles",
- ToolUtils::make_star(SkRect::MakeWH(100, 100),
- kNumCubicsInChalkboard),
- SkMatrix::I()) {
- }
- void runBench(GrMeshDrawOp::Target* target, GrTessellatePathOp* op) override {
- int numBeziers;
- op->prepareMiddleOutInnerTriangles(target, &numBeziers);
- }
-};
+#define DEF_TESS_BENCH(NAME, PATH, MATRIX, TARGET, OP) \
+ class GrTessellatePathOp::TestingOnly_Benchmark::NAME \
+ : public GrTessellatePathOp::TestingOnly_Benchmark { \
+ public: \
+ NAME() : TestingOnly_Benchmark(#NAME, (PATH), (MATRIX)) {} \
+ void runBench(GrMeshDrawOp::Target* target, GrTessellatePathOp* op) override; \
+ }; \
+ DEF_BENCH( return new GrTessellatePathOp::TestingOnly_Benchmark::NAME(); ); \
+ void GrTessellatePathOp::TestingOnly_Benchmark::NAME::runBench( \
+ GrMeshDrawOp::Target* TARGET, GrTessellatePathOp* op)
+
+DEF_TESS_BENCH(prepareMiddleOutStencilGeometry, make_cubic_path(), SkMatrix::I(), target, op) {
+ op->prepareMiddleOutTrianglesAndCubics(target);
+}
-DEF_BENCH( return new GrTessellatePathOp::TestingOnly_Benchmark::MiddleOutInnerTrianglesBench(); );
+DEF_TESS_BENCH(prepareMiddleOutStencilGeometry_indirect, make_cubic_path(), SkMatrix::I(), target,
+ op) {
+ GrResolveLevelCounter resolveLevelCounter;
+ op->prepareMiddleOutTrianglesAndCubics(target, &resolveLevelCounter, true);
+}
-class GrTessellatePathOp::TestingOnly_Benchmark::OuterCubicsBench
- : public GrTessellatePathOp::TestingOnly_Benchmark {
-public:
- OuterCubicsBench()
- : TestingOnly_Benchmark("prepareOuterCubics", make_cubic_path(), SkMatrix::I()) {
- }
- void runBench(GrMeshDrawOp::Target* target, GrTessellatePathOp* op) override {
- op->prepareOuterCubics(target, kNumCubicsInChalkboard,
- CubicDataAlignment::kVertexBoundary);
- }
-};
+DEF_TESS_BENCH(prepareIndirectOuterCubics, make_cubic_path(), SkMatrix::I(), target, op) {
+ GrResolveLevelCounter resolveLevelCounter;
+ resolveLevelCounter.reset(op->fPath, SkMatrix::I(), 4);
+ op->prepareIndirectOuterCubics(target, resolveLevelCounter);
+}
-DEF_BENCH( return new GrTessellatePathOp::TestingOnly_Benchmark::OuterCubicsBench(); );
+DEF_TESS_BENCH(prepareTessellatedOuterCubics, make_cubic_path(), SkMatrix::I(), target, op) {
+ op->prepareTessellatedOuterCubics(target, kNumCubicsInChalkboard);
+}
-class GrTessellatePathOp::TestingOnly_Benchmark::CubicWedgesBench
- : public GrTessellatePathOp::TestingOnly_Benchmark {
-public:
- CubicWedgesBench()
- : TestingOnly_Benchmark("prepareCubicWedges", make_cubic_path(), SkMatrix::I()) {
+DEF_TESS_BENCH(prepareTessellatedCubicWedges, make_cubic_path(), SkMatrix::I(), target, op) {
+ op->prepareTessellatedCubicWedges(target);
+}
+
+static void benchmark_wangs_formula_cubic_log2(const SkMatrix& matrix, const SkPath& path) {
+ int sum = 0;
+ GrVectorXform xform(matrix);
+ for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
+ if (verb == SkPathVerb::kCubic) {
+ sum += GrWangsFormula::cubic_log2(4, pts, xform);
+ }
}
- void runBench(GrMeshDrawOp::Target* target, GrTessellatePathOp* op) override {
- op->prepareCubicWedges(target);
+ // Don't let the compiler optimize away GrWangsFormula::cubic_log2.
+ if (sum <= 0) {
+ SK_ABORT("sum should be > 0.");
}
-};
+}
-DEF_BENCH( return new GrTessellatePathOp::TestingOnly_Benchmark::CubicWedgesBench(););
+DEF_TESS_BENCH(wangs_formula_cubic_log2, make_cubic_path(), SkMatrix::I(), target, op) {
+ benchmark_wangs_formula_cubic_log2(op->fViewMatrix, op->fPath);
+}
-class GrTessellatePathOp::TestingOnly_Benchmark::WangsFormulaBench
- : public GrTessellatePathOp::TestingOnly_Benchmark {
-public:
- WangsFormulaBench(const char* suffix, const SkMatrix& matrix)
- : TestingOnly_Benchmark(SkStringPrintf("wangs_formula_cubic_log2%s", suffix).c_str(),
- make_cubic_path(), SkMatrix::I())
- , fMatrix(matrix) {
- }
- void runBench(GrMeshDrawOp::Target*, GrTessellatePathOp* op) override {
- int sum = 0;
- GrVectorXform xform(fMatrix);
- for (auto [verb, pts, w] : SkPathPriv::Iterate(op->fPath)) {
- if (verb == SkPathVerb::kCubic) {
- sum += GrWangsFormula::cubic_log2(4, pts, xform);
- }
- }
- // Don't let the compiler optimize away GrWangsFormula::cubic_log2.
- if (sum <= 0) {
- SK_ABORT("sum should be > 0.");
+DEF_TESS_BENCH(wangs_formula_cubic_log2_scale, make_cubic_path(), SkMatrix::Scale(1.1f, 0.9f),
+ target, op) {
+ benchmark_wangs_formula_cubic_log2(op->fViewMatrix, op->fPath);
+}
+
+DEF_TESS_BENCH(wangs_formula_cubic_log2_affine, make_cubic_path(),
+ SkMatrix::MakeAll(.9f,0.9f,0, 1.1f,1.1f,0, 0,0,1), target, op) {
+ benchmark_wangs_formula_cubic_log2(op->fViewMatrix, op->fPath);
+}
+
+DEF_TESS_BENCH(middle_out_triangulation,
+ ToolUtils::make_star(SkRect::MakeWH(500, 500), kNumCubicsInChalkboard),
+ SkMatrix::I(), target, op) {
+ int baseVertex;
+ auto vertexData = static_cast<SkPoint*>(target->makeVertexSpace(
+ sizeof(SkPoint), kNumCubicsInChalkboard, nullptr, &baseVertex));
+ GrMiddleOutPolygonTriangulator middleOut(vertexData, 3, kNumCubicsInChalkboard + 2);
+ for (auto [verb, pts, w] : SkPathPriv::Iterate(op->fPath)) {
+ switch (verb) {
+ case SkPathVerb::kMove:
+ middleOut.closeAndMove(pts[0]);
+ break;
+ case SkPathVerb::kLine:
+ middleOut.pushVertex(pts[1]);
+ break;
+ case SkPathVerb::kClose:
+ middleOut.close();
+ break;
+ case SkPathVerb::kQuad:
+ case SkPathVerb::kConic:
+ case SkPathVerb::kCubic:
+ SkUNREACHABLE;
}
+ middleOut.closeAndMove(pts[0]);
}
-private:
- SkMatrix fMatrix;
-};
-
-DEF_BENCH(
- return new GrTessellatePathOp::TestingOnly_Benchmark::WangsFormulaBench("", SkMatrix::I());
-);
-DEF_BENCH(
- return new GrTessellatePathOp::TestingOnly_Benchmark::WangsFormulaBench(
- "_scale", SkMatrix::MakeScale(1.1f, 0.9f));
-);
-DEF_BENCH(
- return new GrTessellatePathOp::TestingOnly_Benchmark::WangsFormulaBench(
- "_affine", SkMatrix::MakeAll(.9f,0.9f,0, 1.1f,1.1f,0, 0,0,1));
-);
+}
diff --git a/chromium/third_party/skia/bench/VertexColorSpaceBench.cpp b/chromium/third_party/skia/bench/VertexColorSpaceBench.cpp
index 1c64c92e7f9..3693eb9c7fa 100644
--- a/chromium/third_party/skia/bench/VertexColorSpaceBench.cpp
+++ b/chromium/third_party/skia/bench/VertexColorSpaceBench.cpp
@@ -333,7 +333,7 @@ public:
rtc->priv().testingOnly_addDrawOp(std::move(op));
}
- context->flush();
+ context->flushAndSubmit();
}
}
diff --git a/chromium/third_party/skia/bench/nanobench.cpp b/chromium/third_party/skia/bench/nanobench.cpp
index 81e1c352e1e..4db949dc9d4 100644
--- a/chromium/third_party/skia/bench/nanobench.cpp
+++ b/chromium/third_party/skia/bench/nanobench.cpp
@@ -11,7 +11,6 @@
#include "bench/AndroidCodecBench.h"
#include "bench/Benchmark.h"
-#include "bench/BitmapRegionDecoderBench.h"
#include "bench/CodecBench.h"
#include "bench/CodecBenchPriv.h"
#include "bench/GMBench.h"
@@ -20,7 +19,6 @@
#include "bench/SKPAnimationBench.h"
#include "bench/SKPBench.h"
#include "bench/SkGlyphCacheBench.h"
-#include "include/android/SkBitmapRegionDecoder.h"
#include "include/codec/SkAndroidCodec.h"
#include "include/codec/SkCodec.h"
#include "include/core/SkCanvas.h"
@@ -52,6 +50,11 @@
#include "experimental/svg/model/SkSVGDOM.h"
#endif // SK_XML
+#ifdef SK_ENABLE_ANDROID_UTILS
+#include "bench/BitmapRegionDecoderBench.h"
+#include "client_utils/android/BitmapRegionDecoder.h"
+#endif
+
#include <cinttypes>
#include <stdlib.h>
#include <thread>
@@ -212,6 +215,13 @@ struct GPUTarget : public Target {
ContextInfo contextInfo;
std::unique_ptr<GrContextFactory> factory;
+ ~GPUTarget() override {
+ // For Vulkan we need to release all our refs to the GrContext before destroy the vulkan
+ // context which happens at the end of this destructor. Thus we need to release the surface
+ // here which holds a ref to the GrContext.
+ surface.reset();
+ }
+
void setup() override {
this->contextInfo.testContext()->makeCurrent();
// Make sure we're done with whatever came before.
@@ -586,10 +596,10 @@ static Target* is_enabled(Benchmark* bench, const Config& config) {
#pragma warning ( pop )
#endif
+#ifdef SK_ENABLE_ANDROID_UTILS
static bool valid_brd_bench(sk_sp<SkData> encoded, SkColorType colorType, uint32_t sampleSize,
uint32_t minOutputSize, int* width, int* height) {
- std::unique_ptr<SkBitmapRegionDecoder> brd(
- SkBitmapRegionDecoder::Create(encoded, SkBitmapRegionDecoder::kAndroidCodec_Strategy));
+ auto brd = android::skia::BitmapRegionDecoder::Make(encoded);
if (nullptr == brd.get()) {
// This is indicates that subset decoding is not supported for a particular image format.
return false;
@@ -607,6 +617,7 @@ static bool valid_brd_bench(sk_sp<SkData> encoded, SkColorType colorType, uint32
*height = brd->height();
return true;
}
+#endif
static void cleanup_run(Target* target) {
delete target;
@@ -967,6 +978,7 @@ public:
fCurrentSampleSize = 0;
}
+#ifdef SK_ENABLE_ANDROID_UTILS
// Run the BRDBenches
// We intend to create benchmarks that model the use cases in
// android/libraries/social/tiledimage. In this library, an image is decoded in 512x512
@@ -1050,6 +1062,7 @@ public:
}
fCurrentColorType = 0;
}
+#endif // SK_ENABLE_ANDROID_UTILS
return nullptr;
}
@@ -1079,6 +1092,7 @@ public:
}
private:
+#ifdef SK_ENABLE_ANDROID_UTILS
enum SubsetType {
kTopLeft_SubsetType = 0,
kTopRight_SubsetType = 1,
@@ -1090,6 +1104,7 @@ private:
kLast_SubsetType = kZoom_SubsetType,
kLastSingle_SubsetType = kBottomRight_SubsetType,
};
+#endif
const BenchRegistry* fBenches;
const skiagm::GMRegistry* fGMs;
@@ -1117,10 +1132,12 @@ private:
int fCurrentUseMPD = 0;
int fCurrentCodec = 0;
int fCurrentAndroidCodec = 0;
+#ifdef SK_ENABLE_ANDROID_UTILS
int fCurrentBRDImage = 0;
+ int fCurrentSubsetType = 0;
+#endif
int fCurrentColorType = 0;
int fCurrentAlphaType = 0;
- int fCurrentSubsetType = 0;
int fCurrentSampleSize = 0;
int fCurrentAnimSKP = 0;
};
diff --git a/chromium/third_party/skia/bin/fetch-gn b/chromium/third_party/skia/bin/fetch-gn
index ee150e209d8..d0c791d1c39 100755
--- a/chromium/third_party/skia/bin/fetch-gn
+++ b/chromium/third_party/skia/bin/fetch-gn
@@ -24,7 +24,7 @@ with open(gnzip, 'wb') as f:
pkg = 'linux-amd64' if 'linux' in sys.platform else \
'mac-amd64' if 'darwin' in sys.platform else \
'windows-amd64'
- rev = '82d673acb802cee21534c796a59f8cdf26500f53'
+ rev = '9e993e3da82a9f4bc5c50c190afbcffd61e3d9e0'
url = 'https://chrome-infra-packages.appspot.com/dl/gn/gn/{}/+/git_revision:{}'.format(pkg,rev)
f.write(urlopen(url).read())
diff --git a/chromium/third_party/skia/build/fuchsia/fidl_gen_cpp b/chromium/third_party/skia/build/fuchsia/fidl_gen_cpp
index 6d2c10de970..0b47297c179 100755
--- a/chromium/third_party/skia/build/fuchsia/fidl_gen_cpp
+++ b/chromium/third_party/skia/build/fuchsia/fidl_gen_cpp
@@ -42,7 +42,6 @@ def main():
parser.add_argument('--json', dest='json', action='store', required=True)
parser.add_argument('--include-base', dest='include_base', action='store', required=True)
parser.add_argument('--output-base-cc', dest='output_base_cc', action='store', required=True)
- parser.add_argument('--output-c-header', dest='output_header_c', action='store', required=True)
parser.add_argument('--output-c-tables', dest='output_c_tables', action='store', required=True)
args = parser.parse_args()
@@ -54,8 +53,6 @@ def main():
fidlc_command = [
args.fidlc_bin,
- '--c-header',
- args.output_header_c,
'--tables',
args.output_c_tables,
'--json',
diff --git a/chromium/third_party/skia/build/fuchsia/sdk.gni b/chromium/third_party/skia/build/fuchsia/sdk.gni
index 97d3fe62049..d8f6131fe75 100644
--- a/chromium/third_party/skia/build/fuchsia/sdk.gni
+++ b/chromium/third_party/skia/build/fuchsia/sdk.gni
@@ -74,7 +74,7 @@ template("_fuchsia_fidl_library") {
_deps = [ "../pkg:fidl_cpp" ]
- library_name = string_replace(meta_json.name, "fuchsia.", "")
+ library_name = meta_json.name
library_name_json = "$library_name.json"
foreach(dep, meta_json.deps) {
@@ -95,10 +95,9 @@ template("_fuchsia_fidl_library") {
inputs = [ invoker.meta ]
outputs = [
- "$target_gen_dir/fuchsia/$library_name_slashes/c/fidl.h",
- "$target_gen_dir/fuchsia/$library_name_slashes/c/tables.c",
- "$target_gen_dir/fuchsia/$library_name_slashes/cpp/fidl.h",
- "$target_gen_dir/fuchsia/$library_name_slashes/cpp/fidl.cc",
+ "$target_gen_dir/$library_name_slashes/c/tables.c",
+ "$target_gen_dir/$library_name_slashes/cpp/fidl.h",
+ "$target_gen_dir/$library_name_slashes/cpp/fidl.cc",
]
args = [
@@ -115,11 +114,11 @@ template("_fuchsia_fidl_library") {
"--include-base",
rebase_path("$target_gen_dir"),
"--output-base-cc",
- rebase_path("$target_gen_dir/fuchsia/$library_name_slashes/cpp/fidl"),
- "--output-c-header",
- rebase_path("$target_gen_dir/fuchsia/$library_name_slashes/c/fidl.h"),
+ rebase_path("$target_gen_dir/$library_name_slashes/cpp/fidl"),
"--output-c-tables",
- rebase_path("$target_gen_dir/fuchsia/$library_name_slashes/c/tables.c"),
+ rebase_path("$target_gen_dir/$library_name_slashes/c/tables.c"),
+ "--output-c-header",
+ rebase_path("$target_gen_dir/$library_name_slashes/c/fidl.h"),
]
}
diff --git a/chromium/third_party/skia/include/android/SkBRDAllocator.h b/chromium/third_party/skia/client_utils/android/BRDAllocator.h
index ae842b74b17..904676d2889 100644
--- a/chromium/third_party/skia/include/android/SkBRDAllocator.h
+++ b/chromium/third_party/skia/client_utils/android/BRDAllocator.h
@@ -5,18 +5,21 @@
* found in the LICENSE file.
*/
-#ifndef SkBRDAllocator_DEFINED
-#define SkBRDAllocator_DEFINED
+#ifndef BRDAllocator_DEFINED
+#define BRDAllocator_DEFINED
#include "include/codec/SkCodec.h"
#include "include/core/SkBitmap.h"
+namespace android {
+namespace skia {
+
/**
* Abstract subclass of SkBitmap's allocator.
* Allows the allocator to indicate if the memory it allocates
* is zero initialized.
*/
-class SkBRDAllocator : public SkBitmap::Allocator {
+class BRDAllocator : public SkBitmap::Allocator {
public:
/**
@@ -26,4 +29,7 @@ public:
virtual SkCodec::ZeroInitialized zeroInit() const = 0;
};
-#endif // SkBRDAllocator_DEFINED
+} // namespace skia
+} // namespace android
+
+#endif // BRDAllocator_DEFINED
diff --git a/chromium/third_party/skia/src/android/SkBitmapRegionCodec.cpp b/chromium/third_party/skia/client_utils/android/BitmapRegionDecoder.cpp
index 081d0bbf3bc..8727a0bd8ab 100644
--- a/chromium/third_party/skia/src/android/SkBitmapRegionCodec.cpp
+++ b/chromium/third_party/skia/client_utils/android/BitmapRegionDecoder.cpp
@@ -5,17 +5,47 @@
* found in the LICENSE file.
*/
+#include "client_utils/android/BitmapRegionDecoder.h"
+#include "client_utils/android/BitmapRegionDecoderPriv.h"
#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)
+namespace android {
+namespace skia {
+
+std::unique_ptr<BitmapRegionDecoder> BitmapRegionDecoder::Make(sk_sp<SkData> data) {
+ auto codec = SkAndroidCodec::MakeFromData(std::move(data));
+ if (nullptr == codec) {
+ SkCodecPrintf("Error: Failed to create codec.\n");
+ return nullptr;
+ }
+
+ switch (codec->getEncodedFormat()) {
+ case SkEncodedImageFormat::kJPEG:
+ case SkEncodedImageFormat::kPNG:
+ case SkEncodedImageFormat::kWEBP:
+ case SkEncodedImageFormat::kHEIF:
+ break;
+ default:
+ return nullptr;
+ }
+
+ return std::unique_ptr<BitmapRegionDecoder>(new BitmapRegionDecoder(std::move(codec)));
+}
+
+BitmapRegionDecoder::BitmapRegionDecoder(std::unique_ptr<SkAndroidCodec> codec)
+ : fCodec(std::move(codec))
{}
-bool SkBitmapRegionCodec::decodeRegion(SkBitmap* bitmap, SkBRDAllocator* allocator,
+int BitmapRegionDecoder::width() const {
+ return fCodec->getInfo().width();
+}
+
+int BitmapRegionDecoder::height() const {
+ return fCodec->getInfo().height();
+}
+
+bool BitmapRegionDecoder::decodeRegion(SkBitmap* bitmap, BRDAllocator* allocator,
const SkIRect& desiredSubset, int sampleSize, SkColorType dstColorType,
bool requireUnpremul, sk_sp<SkColorSpace> dstColorSpace) {
@@ -116,3 +146,6 @@ bool SkBitmapRegionCodec::decodeRegion(SkBitmap* bitmap, SkBRDAllocator* allocat
return false;
}
}
+
+} // namespace skia
+} // namespace android
diff --git a/chromium/third_party/skia/client_utils/android/BitmapRegionDecoder.h b/chromium/third_party/skia/client_utils/android/BitmapRegionDecoder.h
new file mode 100644
index 00000000000..2996df3aee6
--- /dev/null
+++ b/chromium/third_party/skia/client_utils/android/BitmapRegionDecoder.h
@@ -0,0 +1,50 @@
+/*
+ * 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 BitmapRegionDecoder_DEFINED
+#define BitmapRegionDecoder_DEFINED
+
+#include "client_utils/android/BRDAllocator.h"
+#include "include/codec/SkAndroidCodec.h"
+#include "include/core/SkBitmap.h"
+#include "include/core/SkData.h"
+
+namespace android {
+namespace skia {
+
+class BitmapRegionDecoder final {
+public:
+ static std::unique_ptr<BitmapRegionDecoder> Make(sk_sp<SkData> data);
+
+ bool decodeRegion(SkBitmap* bitmap, BRDAllocator* allocator,
+ const SkIRect& desiredSubset, int sampleSize,
+ SkColorType colorType, bool requireUnpremul,
+ sk_sp<SkColorSpace> prefColorSpace);
+
+ SkEncodedImageFormat getEncodedFormat() { return fCodec->getEncodedFormat(); }
+
+ SkColorType computeOutputColorType(SkColorType requestedColorType) {
+ return fCodec->computeOutputColorType(requestedColorType);
+ }
+
+ sk_sp<SkColorSpace> computeOutputColorSpace(SkColorType outputColorType,
+ sk_sp<SkColorSpace> prefColorSpace = nullptr) {
+ return fCodec->computeOutputColorSpace(outputColorType, prefColorSpace);
+ }
+
+ int width() const;
+ int height() const;
+
+private:
+ BitmapRegionDecoder(std::unique_ptr<SkAndroidCodec> codec);
+
+ std::unique_ptr<SkAndroidCodec> fCodec;
+};
+
+} // namespace skia
+} // namespace android
+#endif // BitmapRegionDecoder_DEFINED
diff --git a/chromium/third_party/skia/src/android/SkBitmapRegionDecoderPriv.h b/chromium/third_party/skia/client_utils/android/BitmapRegionDecoderPriv.h
index 905d460c5c6..d63d4ef47c8 100644
--- a/chromium/third_party/skia/src/android/SkBitmapRegionDecoderPriv.h
+++ b/chromium/third_party/skia/client_utils/android/BitmapRegionDecoderPriv.h
@@ -5,8 +5,8 @@
* found in the LICENSE file.
*/
-#ifndef SkBitmapRegionDecoderPriv_DEFINED
-#define SkBitmapRegionDecoderPriv_DEFINED
+#ifndef BitmapRegionDecoderPriv_DEFINED
+#define BitmapRegionDecoderPriv_DEFINED
#include "include/core/SkRect.h"
@@ -58,4 +58,4 @@ inline SubsetType adjust_subset_rect(const SkISize& imageDims, SkIRect* subset,
return SubsetType::kFullyInside_SubsetType;
}
-#endif // SkBitmapRegionDecoderPriv_DEFINED
+#endif // BitmapRegionDecoderPriv_DEFINED
diff --git a/chromium/third_party/skia/demos.skia.org/Makefile b/chromium/third_party/skia/demos.skia.org/Makefile
new file mode 100644
index 00000000000..d3242d61e1a
--- /dev/null
+++ b/chromium/third_party/skia/demos.skia.org/Makefile
@@ -0,0 +1,4 @@
+.PHONY: local
+local:
+ echo "Go check out http://localhost:8123/demos/hello_world/index.html"
+ python2 -m SimpleHTTPServer 8123
diff --git a/chromium/third_party/skia/demos.skia.org/demos/hello_world/index.html b/chromium/third_party/skia/demos.skia.org/demos/hello_world/index.html
new file mode 100644
index 00000000000..4db88822578
--- /dev/null
+++ b/chromium/third_party/skia/demos.skia.org/demos/hello_world/index.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<title>Hello World Demo</title>
+<meta charset="utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<script type="text/javascript" src="https://particles.skia.org/static/canvaskit.js"></script>
+
+<style>
+ canvas {
+ border: 1px dashed grey;
+ }
+</style>
+
+<body>
+ <h1>Hello world</h1>
+
+ <canvas id=draw width=500 height=500></canvas>
+</body>
+
+<script type="text/javascript" charset="utf-8">
+ const ckLoaded = CanvasKitInit({locateFile: (file) => 'https://particles.skia.org/static/'+file});
+
+ ckLoaded.then((CanvasKit) => {
+ const surface = CanvasKit.MakeCanvasSurface('draw');
+ if (!surface) {
+ throw 'Could not make surface';
+ }
+
+ const paint = new CanvasKit.SkPaint();
+ paint.setColor(CanvasKit.RED);
+
+ const textPaint = new CanvasKit.SkPaint();
+ const textFont = new CanvasKit.SkFont(null, 20);
+
+ function drawFrame(canvas) {
+ canvas.drawRect(CanvasKit.LTRBRect(10, 10, 50, 50), paint);
+ canvas.drawText('If you see this, CanvasKit loaded!!', 5, 100, textPaint, textFont);
+ }
+ surface.requestAnimationFrame(drawFrame);
+ });
+
+</script>
diff --git a/chromium/third_party/skia/dm/DM.cpp b/chromium/third_party/skia/dm/DM.cpp
index d4df03d9a11..1a2e059a04f 100644
--- a/chromium/third_party/skia/dm/DM.cpp
+++ b/chromium/third_party/skia/dm/DM.cpp
@@ -154,7 +154,6 @@ static DEFINE_bool(rasterize_pdf, false, "Rasterize PDFs when possible.");
static DEFINE_bool(runVerifiers, false,
"if true, run SkQP-style verification of GM-produced images.");
-
#if defined(__MSVC_RUNTIME_CHECKS)
#include <rtcapi.h>
int RuntimeCheckErrorFunc(int errorType, const char* filename, int linenumber,
@@ -206,13 +205,13 @@ static void info(const char* fmt) {
}
}
-static SkTArray<SkString> gFailures;
+static SkTArray<SkString>* gFailures = new SkTArray<SkString>;
static void fail(const SkString& err) {
static SkSpinlock mutex;
SkAutoSpinlock lock(mutex);
SkDebugf("\n\nFAILURE: %s\n\n", err.c_str());
- gFailures.push_back(err);
+ gFailures->push_back(err);
}
struct Running {
@@ -231,19 +230,19 @@ static void dump_json() {
}
// We use a spinlock to make locking this in a signal handler _somewhat_ safe.
-static SkSpinlock gMutex;
-static int gPending;
-static SkTArray<Running> gRunning;
+static SkSpinlock* gMutex = new SkSpinlock;
+static int gPending;
+static SkTArray<Running>* gRunning = new SkTArray<Running>;
static void done(const char* config, const char* src, const char* srcOptions, const char* name) {
SkString id = SkStringPrintf("%s %s %s %s", config, src, srcOptions, name);
vlog("done %s\n", id.c_str());
int pending;
{
- SkAutoSpinlock lock(gMutex);
- for (int i = 0; i < gRunning.count(); i++) {
- if (gRunning[i].id == id) {
- gRunning.removeShuffle(i);
+ SkAutoSpinlock lock(*gMutex);
+ for (int i = 0; i < gRunning->count(); i++) {
+ if (gRunning->at(i).id == id) {
+ gRunning->removeShuffle(i);
break;
}
}
@@ -258,10 +257,10 @@ static void done(const char* config, const char* src, const char* srcOptions, co
int curr = sk_tools::getCurrResidentSetSizeMB(),
peak = sk_tools::getMaxResidentSetSizeMB();
- SkAutoSpinlock lock(gMutex);
+ SkAutoSpinlock lock(*gMutex);
info("\n%dMB RAM, %dMB peak, %d queued, %d active:\n",
- curr, peak, gPending - gRunning.count(), gRunning.count());
- for (auto& task : gRunning) {
+ curr, peak, gPending - gRunning->count(), gRunning->count());
+ for (auto& task : *gRunning) {
task.dump();
}
}
@@ -270,14 +269,14 @@ static void done(const char* config, const char* src, const char* srcOptions, co
static void start(const char* config, const char* src, const char* srcOptions, const char* name) {
SkString id = SkStringPrintf("%s %s %s %s", config, src, srcOptions, name);
vlog("start %s\n", id.c_str());
- SkAutoSpinlock lock(gMutex);
- gRunning.push_back({id,SkGetThreadID()});
+ SkAutoSpinlock lock(*gMutex);
+ gRunning->push_back({id,SkGetThreadID()});
}
static void find_culprit() {
// Assumes gMutex is locked.
SkThreadID thisThread = SkGetThreadID();
- for (auto& task : gRunning) {
+ for (auto& task : *gRunning) {
if (task.thread == thisThread) {
info("Likely culprit:\n");
task.dump();
@@ -300,7 +299,7 @@ static void find_culprit() {
#undef _
};
- SkAutoSpinlock lock(gMutex);
+ SkAutoSpinlock lock(*gMutex);
const DWORD code = e->ExceptionRecord->ExceptionCode;
info("\nCaught exception %u", code);
@@ -310,7 +309,7 @@ static void find_culprit() {
}
}
info(", was running:\n");
- for (auto& task : gRunning) {
+ for (auto& task : *gRunning) {
task.dump();
}
find_culprit();
@@ -339,13 +338,13 @@ static void find_culprit() {
static void (*previous_handler[max_of(SIGABRT,SIGBUS,SIGFPE,SIGILL,SIGSEGV,SIGTERM)+1])(int);
static void crash_handler(int sig) {
- SkAutoSpinlock lock(gMutex);
+ SkAutoSpinlock lock(*gMutex);
info("\nCaught signal %d [%s] (%dMB RAM, peak %dMB), was running:\n",
sig, strsignal(sig),
sk_tools::getCurrResidentSetSizeMB(), sk_tools::getMaxResidentSetSizeMB());
- for (auto& task : gRunning) {
+ for (auto& task : *gRunning) {
task.dump();
}
find_culprit();
@@ -398,10 +397,10 @@ struct Gold : public SkString {
}
};
};
-static SkTHashSet<Gold, Gold::Hash> gGold;
+static SkTHashSet<Gold, Gold::Hash>* gGold = new SkTHashSet<Gold, Gold::Hash>;
static void add_gold(JsonWriter::BitmapResult r) {
- gGold.add(Gold(r.config, r.sourceType, r.sourceOptions, r.name, r.md5));
+ gGold->add(Gold(r.config, r.sourceType, r.sourceOptions, r.name, r.md5));
}
static void gather_gold() {
@@ -417,12 +416,12 @@ static void gather_gold() {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#if defined(SK_BUILD_FOR_WIN)
- static const char* kNewline = "\r\n";
+ static constexpr char kNewline[] = "\r\n";
#else
- static const char* kNewline = "\n";
+ static constexpr char kNewline[] = "\n";
#endif
-static SkTHashSet<SkString> gUninterestingHashes;
+static SkTHashSet<SkString>* gUninterestingHashes = new SkTHashSet<SkString>;
static void gather_uninteresting_hashes() {
if (!FLAGS_uninterestingHashesFile.isEmpty()) {
@@ -439,10 +438,10 @@ static void gather_uninteresting_hashes() {
SkTArray<SkString> hashes;
SkStrSplit(contents.c_str(), kNewline, &hashes);
for (const SkString& hash : hashes) {
- gUninterestingHashes.add(hash);
+ gUninterestingHashes->add(hash);
}
info("FYI: loaded %d distinct uninteresting hashes from %d lines\n",
- gUninterestingHashes.count(), hashes.count());
+ gUninterestingHashes->count(), hashes.count());
}
}
@@ -457,10 +456,10 @@ struct TaggedSink : public std::unique_ptr<Sink> {
SkString tag;
};
-static const bool kMemcpyOK = true;
+static constexpr bool kMemcpyOK = true;
-static SkTArray<TaggedSrc, kMemcpyOK> gSrcs;
-static SkTArray<TaggedSink, kMemcpyOK> gSinks;
+static SkTArray<TaggedSrc, kMemcpyOK>* gSrcs = new SkTArray<TaggedSrc, kMemcpyOK>;
+static SkTArray<TaggedSink, kMemcpyOK>* gSinks = new SkTArray<TaggedSink, kMemcpyOK>;
static bool in_shard() {
static int N = 0;
@@ -471,7 +470,7 @@ static void push_src(const char* tag, ImplicitString options, Src* s) {
std::unique_ptr<Src> src(s);
if (in_shard() && FLAGS_src.contains(tag) &&
!CommandLineFlags::ShouldSkip(FLAGS_match, src->name().c_str())) {
- TaggedSrc& s = gSrcs.push_back();
+ TaggedSrc& s = gSrcs->push_back();
s.reset(src.release());
s.tag = tag;
s.options = options;
@@ -611,6 +610,7 @@ static void push_image_gen_src(Path path, ImageGenSrc::Mode mode, SkAlphaType al
push_src("image", folder, src);
}
+#ifdef SK_ENABLE_ANDROID_UTILS
static void push_brd_src(Path path, CodecSrc::DstColorType dstColorType, BRDSrc::Mode mode,
uint32_t sampleSize) {
SkString folder("brd_android_codec");
@@ -669,6 +669,7 @@ static void push_brd_srcs(Path path, bool gray) {
}
}
}
+#endif // SK_ENABLE_ANDROID_UTILS
static void push_codec_srcs(Path path) {
sk_sp<SkData> encoded(SkData::MakeFromFileName(path.c_str()));
@@ -797,6 +798,7 @@ static void push_codec_srcs(Path path) {
}
}
+#ifdef SK_ENABLE_ANDROID_UTILS
static const char* const brdExts[] = {
"jpg", "jpeg", "png", "webp",
"JPG", "JPEG", "PNG", "WEBP",
@@ -808,6 +810,7 @@ static void push_codec_srcs(Path path) {
break;
}
}
+#endif
}
// Push image generator GPU test.
@@ -902,7 +905,7 @@ static void push_sink(const SkCommandLineConfig& config, Sink* s) {
// Try a simple Src as a canary. If it fails, skip this sink.
struct : public Src {
- Result draw(SkCanvas* c) const override {
+ Result draw(GrContext*, SkCanvas* c) const override {
c->drawRect(SkRect::MakeWH(1,1), SkPaint());
return Result::Ok();
}
@@ -919,7 +922,7 @@ static void push_sink(const SkCommandLineConfig& config, Sink* s) {
exit(1);
}
- TaggedSink& ts = gSinks.push_back();
+ TaggedSink& ts = gSinks->push_back();
ts.reset(sink.release());
ts.tag = config.getTag();
}
@@ -946,6 +949,8 @@ static Sink* create_sink(const GrContextOptions& grCtxOptions, const SkCommandLi
return new GPUPrecompileTestingSink(gpuConfig, grCtxOptions);
} else if (gpuConfig->getUseDDLSink()) {
return new GPUDDLSink(gpuConfig, grCtxOptions);
+ } else if (gpuConfig->getOOPRish()) {
+ return new GPUOOPRSink(gpuConfig, grCtxOptions);
} else {
return new GPUSink(gpuConfig, grCtxOptions);
}
@@ -1067,7 +1072,7 @@ static bool gather_sinks(const GrContextOptions& grCtxOptions, bool defaultConfi
// If we're using the default configs, we're okay.
defaultConfigs ||
// Otherwise, make sure that all specified configs have become sinks.
- configs.count() == gSinks.count()) {
+ configs.count() == gSinks->count()) {
return true;
}
return false;
@@ -1098,7 +1103,7 @@ static bool is_blacklisted(const char* sink, const char* src,
// Even when a Task Sink reports to be non-threadsafe (e.g. GPU), we know things like
// .png encoding are definitely thread safe. This lets us offload that work to CPU threads.
-static SkTaskGroup gDefinitelyThreadSafeWork;
+static SkTaskGroup* gDefinitelyThreadSafeWork = new SkTaskGroup;
// The finest-grained unit of work we can run: draw a single Src into a single Sink,
// report any errors, and perhaps write out the output: a .png of the bitmap, or a raw stream.
@@ -1146,7 +1151,7 @@ struct Task {
// We're likely switching threads here, so we must capture by value, [=] or [foo,bar].
SkStreamAsset* data = stream.detachAsStream().release();
- gDefinitelyThreadSafeWork.add([task,name,bitmap,data]{
+ gDefinitelyThreadSafeWork->add([task,name,bitmap,data]{
std::unique_ptr<SkStreamAsset> ownedData(data);
std::unique_ptr<HashAndEncode> hashAndEncode;
@@ -1168,8 +1173,8 @@ struct Task {
}
if (!FLAGS_readPath.isEmpty() &&
- !gGold.contains(Gold(task.sink.tag, task.src.tag,
- task.src.options, name, md5))) {
+ !gGold->contains(Gold(task.sink.tag, task.src.tag,
+ task.src.options, name, md5))) {
fail(SkStringPrintf("%s not found for %s %s %s %s in %s",
md5.c_str(),
task.sink.tag.c_str(),
@@ -1204,21 +1209,18 @@ struct Task {
h = (int)CGRectGetHeight(bounds);
SkBitmap rasterized;
- rasterized.allocPixels(
- SkImageInfo::Make(w,h, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
+ rasterized.allocPixels(SkImageInfo::Make(
+ w, h, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
rasterized.eraseColor(SK_ColorWHITE);
- SkUniqueCFRef<CGColorSpaceRef> cs{
- CGColorSpaceCreateDeviceRGB()};
- CGBitmapInfo info = kCGBitmapByteOrder32Big
- | kCGImageAlphaPremultipliedLast;
+ SkUniqueCFRef<CGColorSpaceRef> cs{CGColorSpaceCreateDeviceRGB()};
+ CGBitmapInfo info = kCGBitmapByteOrder32Big |
+ (CGBitmapInfo)kCGImageAlphaPremultipliedLast;
- SkUniqueCFRef<CGContextRef> ctx{
- CGBitmapContextCreate(rasterized.getPixels(),
- w,h,8,rasterized.rowBytes(), cs.get(),info)};
+ SkUniqueCFRef<CGContextRef> ctx{CGBitmapContextCreate(
+ rasterized.getPixels(), w,h,8, rasterized.rowBytes(), cs.get(), info)};
CGContextDrawPDFPage(ctx.get(), page);
-
// Skip calling hashAndEncode->write(SkMD5*)... we want the .pdf's hash.
hashAndEncode.reset(new HashAndEncode(rasterized));
WriteToDisk(task, md5, "png", nullptr,0, &rasterized, hashAndEncode.get());
@@ -1346,7 +1348,7 @@ struct Task {
// If an MD5 is uninteresting, we want it noted in the JSON file,
// but don't want to dump it out as a .png (or whatever ext is).
- if (gUninterestingHashes.contains(md5)) {
+ if (gUninterestingHashes->contains(md5)) {
return;
}
@@ -1423,7 +1425,8 @@ struct Task {
// Unit tests don't fit so well into the Src/Sink model, so we give them special treatment.
-static SkTDArray<skiatest::Test> gParallelTests, gSerialTests;
+static SkTDArray<skiatest::Test>* gParallelTests = new SkTDArray<skiatest::Test>;
+static SkTDArray<skiatest::Test>* gSerialTests = new SkTDArray<skiatest::Test>;
static void gather_tests() {
if (!FLAGS_src.contains("tests")) {
@@ -1437,9 +1440,9 @@ static void gather_tests() {
continue;
}
if (test.needsGpu && FLAGS_gpu) {
- gSerialTests.push_back(test);
+ gSerialTests->push_back(test);
} else if (!test.needsGpu && FLAGS_cpu) {
- gParallelTests.push_back(test);
+ gParallelTests->push_back(test);
}
}
}
@@ -1521,7 +1524,7 @@ int main(int argc, char** argv) {
// TODO(dogben): This is a bit ugly. Find a cleaner way to do this.
bool defaultConfigs = true;
for (int i = 0; i < argc; i++) {
- static const char* kConfigArg = "--config";
+ static constexpr char kConfigArg[] = "--config";
if (strcmp(argv[i], kConfigArg) == 0) {
defaultConfigs = false;
break;
@@ -1531,42 +1534,44 @@ int main(int argc, char** argv) {
return 1;
}
gather_tests();
- gPending = gSrcs.count() * gSinks.count() + gParallelTests.count() + gSerialTests.count();
+ gPending = gSrcs->count() * gSinks->count() + gParallelTests->count() + gSerialTests->count();
info("%d srcs * %d sinks + %d tests == %d tasks\n",
- gSrcs.count(), gSinks.count(), gParallelTests.count() + gSerialTests.count(), gPending);
+ gSrcs->count(), gSinks->count(), gParallelTests->count() + gSerialTests->count(),
+ gPending);
// Kick off as much parallel work as we can, making note of any serial work we'll need to do.
SkTaskGroup parallel;
SkTArray<Task> serial;
- for (auto& sink : gSinks)
- for (auto& src : gSrcs) {
- if (src->veto(sink->flags()) ||
- is_blacklisted(sink.tag.c_str(), src.tag.c_str(),
- src.options.c_str(), src->name().c_str())) {
- SkAutoSpinlock lock(gMutex);
- gPending--;
- continue;
- }
+ for (TaggedSink& sink : *gSinks) {
+ for (TaggedSrc& src : *gSrcs) {
+ if (src->veto(sink->flags()) ||
+ is_blacklisted(sink.tag.c_str(), src.tag.c_str(),
+ src.options.c_str(), src->name().c_str())) {
+ SkAutoSpinlock lock(*gMutex);
+ gPending--;
+ continue;
+ }
- Task task(src, sink);
- if (src->serial() || sink->serial()) {
- serial.push_back(task);
- } else {
- parallel.add([task] { Task::Run(task); });
+ Task task(src, sink);
+ if (src->serial() || sink->serial()) {
+ serial.push_back(task);
+ } else {
+ parallel.add([task] { Task::Run(task); });
+ }
}
}
- for (auto test : gParallelTests) {
+ for (skiatest::Test& test : *gParallelTests) {
parallel.add([test, grCtxOptions] { run_test(test, grCtxOptions); });
}
// With the parallel work running, run serial tasks and tests here on main thread.
- for (auto task : serial) { Task::Run(task); }
- for (auto test : gSerialTests) { run_test(test, grCtxOptions); }
+ for (Task& task : serial) { Task::Run(task); }
+ for (skiatest::Test& test : *gSerialTests) { run_test(test, grCtxOptions); }
// Wait for any remaining parallel work to complete (including any spun off of serial tasks).
parallel.wait();
- gDefinitelyThreadSafeWork.wait();
+ gDefinitelyThreadSafeWork->wait();
// At this point we're back in single-threaded land.
@@ -1575,12 +1580,12 @@ int main(int argc, char** argv) {
// Make sure we've flushed all our results to disk.
dump_json();
- if (gFailures.count() > 0) {
+ if (!gFailures->empty()) {
info("Failures:\n");
- for (int i = 0; i < gFailures.count(); i++) {
- info("\t%s\n", gFailures[i].c_str());
+ for (const SkString& fail : *gFailures) {
+ info("\t%s\n", fail.c_str());
}
- info("%d failures\n", gFailures.count());
+ info("%d failures\n", gFailures->count());
return 1;
}
diff --git a/chromium/third_party/skia/dm/DMGpuTestProcs.cpp b/chromium/third_party/skia/dm/DMGpuTestProcs.cpp
index 736c472c3b3..e9369d5f46c 100644
--- a/chromium/third_party/skia/dm/DMGpuTestProcs.cpp
+++ b/chromium/third_party/skia/dm/DMGpuTestProcs.cpp
@@ -22,6 +22,9 @@ bool IsVulkanContextType(sk_gpu_test::GrContextFactory::ContextType type) {
bool IsMetalContextType(sk_gpu_test::GrContextFactory::ContextType type) {
return GrBackendApi::kMetal == GrContextFactory::ContextTypeBackend(type);
}
+bool IsDirect3DContextType(sk_gpu_test::GrContextFactory::ContextType type) {
+ return GrBackendApi::kDirect3D == GrContextFactory::ContextTypeBackend(type);
+}
bool IsRenderingGLContextType(sk_gpu_test::GrContextFactory::ContextType type) {
return IsGLContextType(type) && GrContextFactory::IsRenderingContext(type);
}
@@ -67,7 +70,7 @@ void RunWithGPUTestContexts(GrContextTestFn* test, GrContextTypeFilterFn* contex
// In case the test changed the current context make sure we move it back before
// calling flush.
ctxInfo.testContext()->makeCurrent();
- ctxInfo.grContext()->flush();
+ ctxInfo.grContext()->flushAndSubmit();
}
}
}
diff --git a/chromium/third_party/skia/dm/DMSrcSink.cpp b/chromium/third_party/skia/dm/DMSrcSink.cpp
index 5b2e161468c..8453871818a 100644
--- a/chromium/third_party/skia/dm/DMSrcSink.cpp
+++ b/chromium/third_party/skia/dm/DMSrcSink.cpp
@@ -68,6 +68,10 @@
#include "include/svg/SkSVGCanvas.h"
#include "src/xml/SkXMLWriter.h"
#endif
+
+#if defined(SK_ENABLE_ANDROID_UTILS)
+ #include "client_utils/android/BitmapRegionDecoder.h"
+#endif
#include "tests/TestUtils.h"
#include <cmath>
@@ -86,9 +90,18 @@ namespace DM {
GMSrc::GMSrc(skiagm::GMFactory factory) : fFactory(factory) {}
-Result GMSrc::draw(SkCanvas* canvas) const {
+Result GMSrc::draw(GrContext* context, SkCanvas* canvas) const {
std::unique_ptr<skiagm::GM> gm(fFactory());
SkString msg;
+
+ skiagm::DrawResult gpuSetupResult = gm->gpuSetup(context, &msg);
+ switch (gpuSetupResult) {
+ case skiagm::DrawResult::kOk : break;
+ case skiagm::DrawResult::kFail: return Result(Result::Status::Fatal, msg);
+ case skiagm::DrawResult::kSkip: return Result(Result::Status::Skip, msg);
+ default: SK_ABORT("");
+ }
+
skiagm::DrawResult drawResult = gm->draw(canvas, &msg);
switch (drawResult) {
case skiagm::DrawResult::kOk : return Result(Result::Status::Ok, msg);
@@ -120,6 +133,11 @@ std::unique_ptr<skiagm::verifiers::VerifierList> GMSrc::getVerifiers() const {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+static SkString get_scaled_name(const Path& path, float scale) {
+ return SkStringPrintf("%s_%.3f", SkOSPath::Basename(path.c_str()).c_str(), scale);
+}
+
+#ifdef SK_ENABLE_ANDROID_UTILS
BRDSrc::BRDSrc(Path path, Mode mode, CodecSrc::DstColorType dstColorType, uint32_t sampleSize)
: fPath(path)
, fMode(mode)
@@ -133,12 +151,9 @@ bool BRDSrc::veto(SinkFlags flags) const {
|| flags.approach != SinkFlags::kDirect;
}
-static SkBitmapRegionDecoder* create_brd(Path path) {
+static std::unique_ptr<android::skia::BitmapRegionDecoder> create_brd(Path path) {
sk_sp<SkData> encoded(SkData::MakeFromFileName(path.c_str()));
- if (!encoded) {
- return nullptr;
- }
- return SkBitmapRegionDecoder::Create(encoded, SkBitmapRegionDecoder::kAndroidCodec_Strategy);
+ return android::skia::BitmapRegionDecoder::Make(encoded);
}
static inline void alpha8_to_gray8(SkBitmap* bitmap) {
@@ -151,7 +166,7 @@ static inline void alpha8_to_gray8(SkBitmap* bitmap) {
}
}
-Result BRDSrc::draw(SkCanvas* canvas) const {
+Result BRDSrc::draw(GrContext*, SkCanvas* canvas) const {
SkColorType colorType = canvas->imageInfo().colorType();
if (kRGB_565_SkColorType == colorType &&
CodecSrc::kGetFromCanvas_DstColorType != fDstColorType)
@@ -169,7 +184,7 @@ Result BRDSrc::draw(SkCanvas* canvas) const {
break;
}
- std::unique_ptr<SkBitmapRegionDecoder> brd(create_brd(fPath));
+ auto brd = create_brd(fPath);
if (nullptr == brd.get()) {
return Result::Skip("Could not create brd for %s.", fPath.c_str());
}
@@ -273,7 +288,7 @@ Result BRDSrc::draw(SkCanvas* canvas) const {
}
SkISize BRDSrc::size() const {
- std::unique_ptr<SkBitmapRegionDecoder> brd(create_brd(fPath));
+ auto brd = create_brd(fPath);
if (brd) {
return {std::max(1, brd->width() / (int)fSampleSize),
std::max(1, brd->height() / (int)fSampleSize)};
@@ -281,10 +296,6 @@ SkISize BRDSrc::size() const {
return {0, 0};
}
-static SkString get_scaled_name(const Path& path, float scale) {
- return SkStringPrintf("%s_%.3f", SkOSPath::Basename(path.c_str()).c_str(), scale);
-}
-
Name BRDSrc::name() const {
// We will replicate the names used by CodecSrc so that images can
// be compared in Gold.
@@ -294,6 +305,8 @@ Name BRDSrc::name() const {
return get_scaled_name(fPath, 1.0f / (float) fSampleSize);
}
+#endif // SK_ENABLE_ANDROID_UTILS
+
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
static bool serial_from_path_name(const SkString& path) {
@@ -394,7 +407,7 @@ static void set_bitmap_color_space(SkImageInfo* info) {
*info = info->makeColorSpace(SkColorSpace::MakeSRGB());
}
-Result CodecSrc::draw(SkCanvas* canvas) const {
+Result CodecSrc::draw(GrContext*, SkCanvas* canvas) const {
sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
if (!encoded) {
return Result::Fatal("Couldn't read %s.", fPath.c_str());
@@ -508,7 +521,7 @@ Result CodecSrc::draw(SkCanvas* canvas) const {
return Result::Skip(
"Cannot decode frame %i to 565 (%s).", i, fPath.c_str());
}
- // Fall through.
+ [[fallthrough]];
default:
return Result::Fatal(
"Couldn't getPixels for frame %i in %s.", i, fPath.c_str());
@@ -779,7 +792,7 @@ bool AndroidCodecSrc::veto(SinkFlags flags) const {
|| flags.approach != SinkFlags::kDirect;
}
-Result AndroidCodecSrc::draw(SkCanvas* canvas) const {
+Result AndroidCodecSrc::draw(GrContext*, SkCanvas* canvas) const {
sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
if (!encoded) {
return Result::Fatal("Couldn't read %s.", fPath.c_str());
@@ -871,7 +884,7 @@ bool ImageGenSrc::veto(SinkFlags flags) const {
return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect;
}
-Result ImageGenSrc::draw(SkCanvas* canvas) const {
+Result ImageGenSrc::draw(GrContext*, SkCanvas* canvas) const {
if (kRGB_565_SkColorType == canvas->imageInfo().colorType()) {
return Result::Skip("Uninteresting to test image generator to 565.");
}
@@ -969,7 +982,7 @@ bool ColorCodecSrc::veto(SinkFlags flags) const {
return flags.type != SinkFlags::kRaster || flags.approach != SinkFlags::kDirect;
}
-Result ColorCodecSrc::draw(SkCanvas* canvas) const {
+Result ColorCodecSrc::draw(GrContext*, SkCanvas* canvas) const {
sk_sp<SkData> encoded(SkData::MakeFromFileName(fPath.c_str()));
if (!encoded) {
return Result::Fatal("Couldn't read %s.", fPath.c_str());
@@ -1034,7 +1047,7 @@ static DEFINE_int(skpViewportSize, 1000,
SKPSrc::SKPSrc(Path path) : fPath(path) { }
-Result SKPSrc::draw(SkCanvas* canvas) const {
+Result SKPSrc::draw(GrContext*, SkCanvas* canvas) const {
std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(fPath.c_str());
if (!stream) {
return Result::Fatal("Couldn't read %s.", fPath.c_str());
@@ -1076,7 +1089,7 @@ Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
BisectSrc::BisectSrc(Path path, const char* trail) : INHERITED(path), fTrail(trail) {}
-Result BisectSrc::draw(SkCanvas* canvas) const {
+Result BisectSrc::draw(GrContext* context, SkCanvas* canvas) const {
struct FoundPath {
SkPath fPath;
SkPaint fPaint;
@@ -1099,7 +1112,7 @@ Result BisectSrc::draw(SkCanvas* canvas) const {
PathFindingCanvas pathFinder(canvas->getBaseLayerSize().width(),
canvas->getBaseLayerSize().height());
- Result result = this->INHERITED::draw(&pathFinder);
+ Result result = this->INHERITED::draw(context, &pathFinder);
if (!result.isOk()) {
return result;
}
@@ -1127,9 +1140,12 @@ Result BisectSrc::draw(SkCanvas* canvas) const {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#if defined(SK_ENABLE_SKOTTIE)
+static DEFINE_bool(useLottieGlyphPaths, false,
+ "Prioritize embedded glyph paths over native fonts.");
+
SkottieSrc::SkottieSrc(Path path) : fPath(std::move(path)) {}
-Result SkottieSrc::draw(SkCanvas* canvas) const {
+Result SkottieSrc::draw(GrContext*, SkCanvas* canvas) const {
auto resource_provider =
skresources::DataURIResourceProviderProxy::Make(
skresources::FileResourceProvider::Make(SkOSPath::Dirname(fPath.c_str()),
@@ -1140,7 +1156,12 @@ Result SkottieSrc::draw(SkCanvas* canvas) const {
auto precomp_interceptor =
sk_make_sp<skottie_utils::ExternalAnimationPrecompInterceptor>(resource_provider,
kInterceptPrefix);
- auto animation = skottie::Animation::Builder()
+ uint32_t flags = 0;
+ if (FLAGS_useLottieGlyphPaths) {
+ flags |= skottie::Animation::Builder::kPreferEmbeddedFonts;
+ }
+
+ auto animation = skottie::Animation::Builder(flags)
.setResourceProvider(std::move(resource_provider))
.setPrecompInterceptor(std::move(precomp_interceptor))
.makeFromFile(fPath.c_str());
@@ -1230,7 +1251,7 @@ SVGSrc::SVGSrc(Path path)
}
}
-Result SVGSrc::draw(SkCanvas* canvas) const {
+Result SVGSrc::draw(GrContext*, SkCanvas* canvas) const {
if (!fDom) {
return Result::Fatal("Unable to parse file: %s", fName.c_str());
}
@@ -1281,8 +1302,10 @@ SkISize MSKPSrc::size(int i) const {
return i >= 0 && i < fPages.count() ? fPages[i].fSize.toCeil() : SkISize{0, 0};
}
-Result MSKPSrc::draw(SkCanvas* c) const { return this->draw(0, c); }
-Result MSKPSrc::draw(int i, SkCanvas* canvas) const {
+Result MSKPSrc::draw(GrContext* context, SkCanvas* c) const {
+ return this->draw(0, context, c);
+}
+Result MSKPSrc::draw(int i, GrContext*, SkCanvas* canvas) const {
if (this->pageCount() == 0) {
return Result::Fatal("Unable to parse MultiPictureDocument file: %s", fPath.c_str());
}
@@ -1310,7 +1333,7 @@ Name MSKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
Result NullSink::draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const {
- return src.draw(SkMakeNullCanvas().get());
+ return src.draw(nullptr, SkMakeNullCanvas().get());
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
@@ -1419,12 +1442,6 @@ bool GPUSink::readBack(SkSurface* surface, SkBitmap* dst) const {
SkISize size = surface->imageInfo().dimensions();
SkImageInfo info = SkImageInfo::Make(size, fColorType, fAlphaType, fColorSpace);
- if (info.colorType() == kRGB_565_SkColorType || info.colorType() == kARGB_4444_SkColorType ||
- info.colorType() == kRGB_888x_SkColorType) {
- // We don't currently support readbacks into these formats on the GPU backend. Convert to
- // 32 bit.
- info = SkImageInfo::Make(size, kRGBA_8888_SkColorType, kPremul_SkAlphaType, fColorSpace);
- }
dst->allocPixels(info);
return canvas->readPixels(*dst, 0, 0);
}
@@ -1463,15 +1480,15 @@ Result GPUSink::onDraw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log,
factory.abandonContexts();
}
SkCanvas* canvas = surface->getCanvas();
- Result result = src.draw(canvas);
+ Result result = src.draw(context, canvas);
if (!result.isOk()) {
return result;
}
- surface->flush();
+ surface->flushAndSubmit();
if (FLAGS_gpuStats) {
- canvas->getGrContext()->priv().dumpCacheStats(log);
- canvas->getGrContext()->priv().dumpGpuStats(log);
- canvas->getGrContext()->priv().dumpContextStats(log);
+ context->priv().dumpCacheStats(log);
+ context->priv().dumpGpuStats(log);
+ context->priv().dumpContextStats(log);
}
this->readBack(surface.get(), dst);
@@ -1557,12 +1574,13 @@ Result GPUPersistentCacheTestingSink::draw(const Src& src, SkBitmap* dst, SkWStr
SkBitmap reference;
SkString refLog;
SkDynamicMemoryWStream refStream;
- memoryCache.resetNumCacheMisses();
+ memoryCache.resetCacheStats();
Result refResult = this->onDraw(src, &reference, &refStream, &refLog, contextOptions);
if (!refResult.isOk()) {
return refResult;
}
SkASSERT(!memoryCache.numCacheMisses());
+ SkASSERT(!memoryCache.numCacheStores());
return compare_bitmaps(reference, *dst);
}
@@ -1616,10 +1634,95 @@ Result GPUPrecompileTestingSink::draw(const Src& src, SkBitmap* dst, SkWStream*
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-GPUDDLSink::GPUDDLSink(const SkCommandLineConfigGpu* config, const GrContextOptions& grCtxOptions)
- : INHERITED(config, grCtxOptions)
- , fRecordingThreadPool(SkExecutor::MakeLIFOThreadPool(1)) // TODO: this should be at least 2
- , fGPUThread(SkExecutor::MakeFIFOThreadPool(1, false)) {
+GPUOOPRSink::GPUOOPRSink(const SkCommandLineConfigGpu* config, const GrContextOptions& ctxOptions)
+ : INHERITED(config, ctxOptions) {
+}
+
+Result GPUOOPRSink::ooprDraw(const Src& src,
+ sk_sp<SkSurface> dstSurface,
+ GrContext* context) const {
+ SkSurfaceCharacterization dstCharacterization;
+ SkAssertResult(dstSurface->characterize(&dstCharacterization));
+
+ SkDeferredDisplayListRecorder recorder(dstCharacterization);
+
+ Result result = src.draw(context, recorder.getCanvas());
+ if (!result.isOk()) {
+ return result;
+ }
+
+ std::unique_ptr<SkDeferredDisplayList> ddl = recorder.detach();
+
+ SkDeferredDisplayList::ProgramIterator iter(context, ddl.get());
+ for (; !iter.done(); iter.next()) {
+ iter.compile();
+ }
+
+ SkAssertResult(dstSurface->draw(ddl.get()));
+
+ // TODO: remove this flush once DDLs are reffed by the drawing manager
+ context->flushAndSubmit();
+
+ ddl.reset();
+
+ return Result::Ok();
+}
+
+Result GPUOOPRSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log) const {
+ GrContextOptions contextOptions = this->baseContextOptions();
+ src.modifyGrContextOptions(&contextOptions);
+ contextOptions.fPersistentCache = nullptr;
+ contextOptions.fExecutor = nullptr;
+
+ GrContextFactory factory(contextOptions);
+
+ ContextInfo ctxInfo = factory.getContextInfo(this->contextType(), this->contextOverrides());
+ GrContext* context = ctxInfo.grContext();
+ if (!context) {
+ return Result::Fatal("Could not create context.");
+ }
+
+ SkASSERT(context->priv().getGpu());
+
+ GrBackendTexture backendTexture;
+ GrBackendRenderTarget backendRT;
+ sk_sp<SkSurface> surface = this->createDstSurface(context, src.size(),
+ &backendTexture, &backendRT);
+ if (!surface) {
+ return Result::Fatal("Could not create a surface.");
+ }
+
+ Result result = this->ooprDraw(src, surface, context);
+ if (!result.isOk()) {
+ return result;
+ }
+
+ if (FLAGS_gpuStats) {
+ context->priv().dumpCacheStats(log);
+ context->priv().dumpGpuStats(log);
+ context->priv().dumpContextStats(log);
+ }
+
+ if (!this->readBack(surface.get(), dst)) {
+ return Result::Fatal("Could not readback from surface.");
+ }
+
+ surface.reset();
+ if (backendTexture.isValid()) {
+ context->deleteBackendTexture(backendTexture);
+ }
+ if (backendRT.isValid()) {
+ context->priv().getGpu()->deleteTestingOnlyBackendRenderTarget(backendRT);
+ }
+
+ return Result::Ok();
+}
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+GPUDDLSink::GPUDDLSink(const SkCommandLineConfigGpu* config, const GrContextOptions& ctxOptions)
+ : INHERITED(config, ctxOptions)
+ , fRecordingExecutor(SkExecutor::MakeLIFOThreadPool(1))
+ , fGPUExecutor(SkExecutor::MakeFIFOThreadPool(1, false)) {
}
Result GPUDDLSink::ddlDraw(const Src& src,
@@ -1635,20 +1738,11 @@ Result GPUDDLSink::ddlDraw(const Src& src,
SkSurfaceCharacterization dstCharacterization;
SkAssertResult(dstSurface->characterize(&dstCharacterization));
- // 'gpuTestCtx/gpuThreadCtx' is being shifted to the gpuThread. Leave the main (this)
- // thread w/o a context.
- gpuTestCtx->makeNotCurrent();
-
- // Job one for the GPU thread is to make 'gpuTestCtx' current!
- gpuTaskGroup->add([gpuTestCtx] { gpuTestCtx->makeCurrent(); });
-
auto size = src.size();
SkPictureRecorder recorder;
- Result result = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
- SkIntToScalar(size.height())));
+ Result result = src.draw(gpuThreadCtx, recorder.beginRecording(SkIntToScalar(size.width()),
+ SkIntToScalar(size.height())));
if (!result.isOk()) {
- gpuTaskGroup->add([gpuTestCtx] { gpuTestCtx->makeNotCurrent(); });
- gpuTaskGroup->wait();
return result;
}
sk_sp<SkPicture> inputPicture(recorder.finishRecordingAsPicture());
@@ -1659,13 +1753,18 @@ Result GPUDDLSink::ddlDraw(const Src& src,
DDLPromiseImageHelper promiseImageHelper;
sk_sp<SkData> compressedPictureData = promiseImageHelper.deflateSKP(inputPicture.get());
if (!compressedPictureData) {
- gpuTaskGroup->add([gpuTestCtx] { gpuTestCtx->makeNotCurrent(); });
- gpuTaskGroup->wait();
return Result::Fatal("GPUDDLSink: Couldn't deflate SkPicture");
}
promiseImageHelper.createCallbackContexts(gpuThreadCtx);
+ // 'gpuTestCtx/gpuThreadCtx' is being shifted to the gpuThread. Leave the main (this)
+ // thread w/o a context.
+ gpuTestCtx->makeNotCurrent();
+
+ // Job one for the GPU thread is to make 'gpuTestCtx' current!
+ gpuTaskGroup->add([gpuTestCtx] { gpuTestCtx->makeCurrent(); });
+
// TODO: move the image upload to the utility thread
promiseImageHelper.uploadAllToGPU(gpuTaskGroup, gpuThreadCtx);
@@ -1697,7 +1796,8 @@ Result GPUDDLSink::ddlDraw(const Src& src,
dstSurface->draw(ddl);
});
- // This should be the only explicit flush for the entire DDL draw
+ // This should be the only explicit flush for the entire DDL draw.
+ // TODO: remove the flushes in do_gpu_stuff
gpuTaskGroup->add([gpuThreadCtx]() {
// We need to ensure all the GPU work is finished so
// the following 'deleteAllFromGPU' call will work
@@ -1708,6 +1808,7 @@ Result GPUDDLSink::ddlDraw(const Src& src,
GrFlushInfo flushInfoSyncCpu;
flushInfoSyncCpu.fFlags = kSyncCpu_GrFlushFlag;
gpuThreadCtx->flush(flushInfoSyncCpu);
+ gpuThreadCtx->submit(true);
});
// The backend textures are created on the gpuThread by the 'uploadAllToGPU' call.
@@ -1726,7 +1827,7 @@ Result GPUDDLSink::ddlDraw(const Src& src,
return Result::Ok();
}
-Result GPUDDLSink::draw(const Src& src, SkBitmap* dst, SkWStream* stream, SkString* log) const {
+Result GPUDDLSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log) const {
GrContextOptions contextOptions = this->baseContextOptions();
src.modifyGrContextOptions(&contextOptions);
contextOptions.fPersistentCache = nullptr;
@@ -1758,8 +1859,8 @@ Result GPUDDLSink::draw(const Src& src, SkBitmap* dst, SkWStream* stream, SkStri
SkASSERT(otherCtx->priv().getGpu());
#endif
- SkTaskGroup recordingTaskGroup(*fRecordingThreadPool);
- SkTaskGroup gpuTaskGroup(*fGPUThread);
+ SkTaskGroup recordingTaskGroup(*fRecordingExecutor);
+ SkTaskGroup gpuTaskGroup(*fGPUExecutor);
// Make sure 'mainCtx' is current
mainTestCtx->makeCurrent();
@@ -1822,7 +1923,7 @@ static Result draw_skdocument(const Src& src, SkDocument* doc, SkWStream* dst) {
if (!canvas) {
return Result::Fatal("SkDocument::beginPage(w,h) returned nullptr");
}
- Result result = src.draw(i, canvas);
+ Result result = src.draw(i, nullptr, canvas);
if (!result.isOk()) {
return result;
}
@@ -1893,7 +1994,7 @@ SKPSink::SKPSink() {}
Result SKPSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
auto size = SkSize::Make(src.size());
SkPictureRecorder recorder;
- Result result = src.draw(recorder.beginRecording(size.width(), size.height()));
+ Result result = src.draw(nullptr, recorder.beginRecording(size.width(), size.height()));
if (!result.isOk()) {
return result;
}
@@ -1905,7 +2006,7 @@ Result SKPSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const
Result DebugSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
DebugCanvas debugCanvas(src.size().width(), src.size().height());
- Result result = src.draw(&debugCanvas);
+ Result result = src.draw(nullptr, &debugCanvas);
if (!result.isOk()) {
return result;
}
@@ -1932,7 +2033,7 @@ Result SVGSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const
fPageIndex, pageCount);
}
}
- return src.draw(fPageIndex,
+ return src.draw(fPageIndex, nullptr,
SkSVGCanvas::Make(SkRect::MakeWH(SkIntToScalar(src.size().width()),
SkIntToScalar(src.size().height())),
dst)
@@ -1959,7 +2060,7 @@ Result RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) co
SkBitmap::kZeroPixels_AllocFlag);
SkCanvas canvas(*dst);
- return src.draw(&canvas);
+ return src.draw(nullptr, &canvas);
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
@@ -1974,7 +2075,7 @@ static Result draw_to_canvas(Sink* sink, SkBitmap* bitmap, SkWStream* stream, Sk
class ProxySrc : public Src {
public:
ProxySrc(SkISize size, const Fn& draw) : fSize(size), fDraw(draw) {}
- Result draw(SkCanvas* canvas) const override { return fDraw(canvas); }
+ Result draw(GrContext*, SkCanvas* canvas) const override { return fDraw(canvas); }
Name name() const override { return "ProxySrc"; }
SkISize size() const override { return fSize; }
private:
@@ -2023,7 +2124,7 @@ Result ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkSt
SkISize size = auto_compute_translate(&matrix, src.size().width(), src.size().height());
return draw_to_canvas(fSink.get(), bitmap, stream, log, size, [&](SkCanvas* canvas) {
canvas->concat(matrix);
- return src.draw(canvas);
+ return src.draw(nullptr, canvas);
});
}
@@ -2068,8 +2169,8 @@ Result ViaSerialization::draw(
// Record our Src into a picture.
auto size = src.size();
SkPictureRecorder recorder;
- Result result = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
- SkIntToScalar(size.height())));
+ Result result = src.draw(nullptr, recorder.beginRecording(SkIntToScalar(size.width()),
+ SkIntToScalar(size.height())));
if (!result.isOk()) {
return result;
}
@@ -2097,8 +2198,8 @@ ViaDDL::ViaDDL(int numReplays, int numDivisions, Sink* sink)
Result ViaDDL::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
auto size = src.size();
SkPictureRecorder recorder;
- Result result = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
- SkIntToScalar(size.height())));
+ Result result = src.draw(nullptr, recorder.beginRecording(SkIntToScalar(size.width()),
+ SkIntToScalar(size.height())));
if (!result.isOk()) {
return result;
}
@@ -2178,6 +2279,7 @@ Result ViaDDL::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkStrin
GrFlushInfo flushInfoSyncCpu;
flushInfoSyncCpu.fFlags = kSyncCpu_GrFlushFlag;
context->flush(flushInfoSyncCpu);
+ context->submit(true);
}
return Result::Ok();
};
@@ -2191,8 +2293,8 @@ Result ViaPicture::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkS
Result result = draw_to_canvas(fSink.get(), bitmap, stream, log, size, [&](SkCanvas* canvas) {
SkPictureRecorder recorder;
sk_sp<SkPicture> pic;
- Result result = src.draw(recorder.beginRecording(SkIntToScalar(size.width()),
- SkIntToScalar(size.height())));
+ Result result = src.draw(nullptr, recorder.beginRecording(SkIntToScalar(size.width()),
+ SkIntToScalar(size.height())));
if (!result.isOk()) {
return result;
}
diff --git a/chromium/third_party/skia/dm/DMSrcSink.h b/chromium/third_party/skia/dm/DMSrcSink.h
index 3dd109b4f66..184841a91e6 100644
--- a/chromium/third_party/skia/dm/DMSrcSink.h
+++ b/chromium/third_party/skia/dm/DMSrcSink.h
@@ -9,7 +9,6 @@
#define DMSrcSink_DEFINED
#include "gm/gm.h"
-#include "include/android/SkBitmapRegionDecoder.h"
#include "include/core/SkBBHFactory.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
@@ -87,15 +86,15 @@ struct SinkFlags {
struct Src {
virtual ~Src() {}
- virtual Result SK_WARN_UNUSED_RESULT draw(SkCanvas*) const = 0;
+ virtual Result SK_WARN_UNUSED_RESULT draw(GrContext*, SkCanvas*) const = 0;
virtual SkISize size() const = 0;
virtual Name name() const = 0;
virtual void modifyGrContextOptions(GrContextOptions* options) const {}
virtual bool veto(SinkFlags) const { return false; }
virtual int pageCount() const { return 1; }
- virtual Result SK_WARN_UNUSED_RESULT draw(int, SkCanvas* canvas) const {
- return this->draw(canvas);
+ virtual Result SK_WARN_UNUSED_RESULT draw(int, GrContext* context, SkCanvas* canvas) const {
+ return this->draw(context, canvas);
}
virtual SkISize size(int) const { return this->size(); }
// Force Tasks using this Src to run on the main thread?
@@ -131,7 +130,7 @@ class GMSrc : public Src {
public:
explicit GMSrc(skiagm::GMFactory);
- Result draw(SkCanvas*) const override;
+ Result draw(GrContext*, SkCanvas*) const override;
SkISize size() const override;
Name name() const override;
void modifyGrContextOptions(GrContextOptions* options) const override;
@@ -163,7 +162,7 @@ public:
};
CodecSrc(Path, Mode, DstColorType, SkAlphaType, float);
- Result draw(SkCanvas*) const override;
+ Result draw(GrContext*, SkCanvas*) const override;
SkISize size() const override;
Name name() const override;
bool veto(SinkFlags) const override;
@@ -181,7 +180,7 @@ class AndroidCodecSrc : public Src {
public:
AndroidCodecSrc(Path, CodecSrc::DstColorType, SkAlphaType, int sampleSize);
- Result draw(SkCanvas*) const override;
+ Result draw(GrContext*, SkCanvas*) const override;
SkISize size() const override;
Name name() const override;
bool veto(SinkFlags) const override;
@@ -194,6 +193,7 @@ private:
bool fRunSerially;
};
+#ifdef SK_ENABLE_ANDROID_UTILS
// Allows for testing of various implementations of Android's BitmapRegionDecoder
class BRDSrc : public Src {
public:
@@ -209,7 +209,7 @@ public:
BRDSrc(Path, Mode, CodecSrc::DstColorType, uint32_t);
- Result draw(SkCanvas*) const override;
+ Result draw(GrContext*, SkCanvas*) const override;
SkISize size() const override;
Name name() const override;
bool veto(SinkFlags) const override;
@@ -219,6 +219,7 @@ private:
CodecSrc::DstColorType fDstColorType;
uint32_t fSampleSize;
};
+#endif
class ImageGenSrc : public Src {
public:
@@ -228,7 +229,7 @@ public:
};
ImageGenSrc(Path, Mode, SkAlphaType, bool);
- Result draw(SkCanvas*) const override;
+ Result draw(GrContext*, SkCanvas*) const override;
SkISize size() const override;
Name name() const override;
bool veto(SinkFlags) const override;
@@ -245,7 +246,7 @@ class ColorCodecSrc : public Src {
public:
ColorCodecSrc(Path, bool decode_to_dst);
- Result draw(SkCanvas*) const override;
+ Result draw(GrContext*, SkCanvas*) const override;
SkISize size() const override;
Name name() const override;
bool veto(SinkFlags) const override;
@@ -258,7 +259,7 @@ class SKPSrc : public Src {
public:
explicit SKPSrc(Path path);
- Result draw(SkCanvas*) const override;
+ Result draw(GrContext*, SkCanvas*) const override;
SkISize size() const override;
Name name() const override;
private:
@@ -272,7 +273,7 @@ class BisectSrc : public SKPSrc {
public:
explicit BisectSrc(Path path, const char* trail);
- Result draw(SkCanvas*) const override;
+ Result draw(GrContext*, SkCanvas*) const override;
private:
SkString fTrail;
@@ -286,7 +287,7 @@ class SkottieSrc final : public Src {
public:
explicit SkottieSrc(Path path);
- Result draw(SkCanvas*) const override;
+ Result draw(GrContext*, SkCanvas*) const override;
SkISize size() const override;
Name name() const override;
bool veto(SinkFlags) const override;
@@ -314,7 +315,7 @@ class SVGSrc : public Src {
public:
explicit SVGSrc(Path path);
- Result draw(SkCanvas*) const override;
+ Result draw(GrContext*, SkCanvas*) const override;
SkISize size() const override;
Name name() const override;
bool veto(SinkFlags) const override;
@@ -334,8 +335,8 @@ public:
explicit MSKPSrc(Path path);
int pageCount() const override;
- Result draw(SkCanvas* c) const override;
- Result draw(int, SkCanvas*) const override;
+ Result draw(GrContext*, SkCanvas* c) const override;
+ Result draw(int, GrContext*, SkCanvas*) const override;
SkISize size() const override;
SkISize size(int) const override;
Name name() const override;
@@ -450,6 +451,21 @@ private:
typedef GPUSink INHERITED;
};
+// This sink attempts to emulate Chrome's OOP-R behavior. It:
+// doesn't use promise images
+// uses only a single thread for both DDL creation & drawing
+class GPUOOPRSink : public GPUSink {
+public:
+ GPUOOPRSink(const SkCommandLineConfigGpu*, const GrContextOptions&);
+
+ Result draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
+
+private:
+ Result ooprDraw(const Src&, sk_sp<SkSurface> dstSurface, GrContext*) const;
+
+ typedef GPUSink INHERITED;
+};
+
// This sink attempts to better simulate the Chrome DDL use-case. It:
// creates the DDLs on separate recording threads
// performs all the GPU work on a separate GPU thread
@@ -472,8 +488,8 @@ private:
sk_gpu_test::TestContext* gpuTestCtx,
GrContext* gpuThreadCtx) const;
- std::unique_ptr<SkExecutor> fRecordingThreadPool;
- std::unique_ptr<SkExecutor> fGPUThread;
+ std::unique_ptr<SkExecutor> fRecordingExecutor;
+ std::unique_ptr<SkExecutor> fGPUExecutor;
typedef GPUSink INHERITED;
};
diff --git a/chromium/third_party/skia/experimental/minimal_ios_mtl_skia_app/main.mm b/chromium/third_party/skia/experimental/minimal_ios_mtl_skia_app/main.mm
index a49c7f307d0..26ef3bdccc8 100644
--- a/chromium/third_party/skia/experimental/minimal_ios_mtl_skia_app/main.mm
+++ b/chromium/third_party/skia/experimental/minimal_ios_mtl_skia_app/main.mm
@@ -67,7 +67,7 @@ static void draw_example(SkSurface* surface, const SkPaint& paint, double rotati
draw_example(surface.get(), fPaint, rotation);
// Must flush *and* present for this to work!
- surface->flush();
+ surface->flushAndSubmit();
surface = nullptr;
id<MTLCommandBuffer> commandBuffer = [[self metalQueue] commandBuffer];
diff --git a/chromium/third_party/skia/experimental/skottiekit/compile.sh b/chromium/third_party/skia/experimental/skottiekit/compile.sh
index 34de427ce9a..1f4181c0009 100755
--- a/chromium/third_party/skia/experimental/skottiekit/compile.sh
+++ b/chromium/third_party/skia/experimental/skottiekit/compile.sh
@@ -62,10 +62,6 @@ if [[ $@ == *cpu* ]]; then
WASM_GPU="-DSK_SUPPORT_GPU=0 --pre-js $BASE_DIR/cpu.js -s USE_WEBGL2=0"
fi
-# Trim some skp-related code
-EXTRA_CFLAGS+=",\"-DSK_DISABLE_READBUFFER\""
-RELEASE_CONF+=" -DSK_DISABLE_READBUFFER"
-
SKOTTIE_LIB="$BUILD_DIR/libskottie.a \
$BUILD_DIR/libsksg.a"
@@ -134,6 +130,8 @@ echo "Compiling bitcode"
skia_use_wuffs=false \
skia_use_zlib=false \
skia_enable_fontmgr_empty=true \
+ skia_enable_fontmgr_custom_directory=false \
+ skia_enable_fontmgr_custom_embedded=false \
skia_enable_fontmgr_custom_empty=false \
skia_enable_sksl_interpreter=false \
\
@@ -163,11 +161,11 @@ ${EMCXX} \
$WASM_GPU \
-std=c++17 \
--bind \
+ --no-entry \
--pre-js $BASE_DIR/preamble.js \
--pre-js $BASE_DIR/helper.js \
--pre-js $BASE_DIR/interface.js \
--pre-js $BASE_DIR/postamble.js \
- --post-js $BASE_DIR/ready.js \
$BASE_DIR/skottiekit_bindings.cpp \
modules/skresources/src/SkResources.cpp \
$MANAGED_SKOTTIE_BINDINGS \
@@ -182,7 +180,7 @@ ${EMCXX} \
-s MODULARIZE=1 \
-s NO_EXIT_RUNTIME=1 \
-s STRICT=1 \
- -s TOTAL_MEMORY=128MB \
+ -s INITIAL_MEMORY=128MB \
-s WARN_UNALIGNED=1 \
-s WASM=1 \
-o $BUILD_DIR/skottiekit.js
diff --git a/chromium/third_party/skia/experimental/skottiekit/examples/ck.html b/chromium/third_party/skia/experimental/skottiekit/examples/ck.html
index 03b75ee8c6a..e936743feef 100644
--- a/chromium/third_party/skia/experimental/skottiekit/examples/ck.html
+++ b/chromium/third_party/skia/experimental/skottiekit/examples/ck.html
@@ -14,7 +14,7 @@
// loadKit resolves with CanvasKit.
const loadKit = CanvasKitInit({
locateFile: (file) => 'https://particles.skia.org/static/'+file,
- }).ready();
+ });
loadKit.then(() => {
const n = performance.now();
diff --git a/chromium/third_party/skia/experimental/skottiekit/examples/index.html b/chromium/third_party/skia/experimental/skottiekit/examples/index.html
index af02c799312..9c4e240c617 100644
--- a/chromium/third_party/skia/experimental/skottiekit/examples/index.html
+++ b/chromium/third_party/skia/experimental/skottiekit/examples/index.html
@@ -14,7 +14,7 @@
// loadKit resolves with SkottieKit.
const loadKit = SkottieKitInit({
locateFile: (file) => '/bin/'+file,
- }).ready();
+ });
loadKit.then(() => {
const n = performance.now();
diff --git a/chromium/third_party/skia/experimental/skottiekit/ready.js b/chromium/third_party/skia/experimental/skottiekit/ready.js
deleted file mode 100644
index 60f24862d9e..00000000000
--- a/chromium/third_party/skia/experimental/skottiekit/ready.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// See https://github.com/kripken/emscripten/issues/5820#issuecomment-385722568
-// for context on why the .then() that comes with Module breaks things (e.g. infinite loops)
-// and why the below fixes it.
-Module['ready'] = function() {
- return new Promise(function (resolve, reject) {
- Module['onAbort'] = reject;
- if (runtimeInitialized) {
- resolve(Module);
- } else {
- addOnPostRun(function() {
- resolve(Module);
- });
- }
- });
-}
-delete Module['then']; \ No newline at end of file
diff --git a/chromium/third_party/skia/experimental/skrive/BUILD.gn b/chromium/third_party/skia/experimental/skrive/BUILD.gn
new file mode 100644
index 00000000000..4f77a546d4f
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/BUILD.gn
@@ -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.
+
+import("../../gn/skia.gni")
+
+if (skia_enable_skrive) {
+ config("public_config") {
+ defines = [ "SK_ENABLE_SKRIVE" ]
+ include_dirs = [ "include" ]
+ }
+
+ component("skrive") {
+ check_includes = false
+ import("skrive.gni")
+ public_configs = [ ":public_config" ]
+ public = skia_skrive_public
+ sources = skia_skrive_sources
+ configs += [ "../../:skia_private" ]
+ deps = [ "../..:skia" ]
+ }
+
+ if (defined(is_skia_standalone)) {
+ if (skia_enable_tools) {
+ source_set("tests") {
+ testonly = true
+
+ configs += [
+ "../..:skia_private",
+ "../..:tests_config",
+ ]
+ sources = [
+ "tests/BinaryReader.cpp",
+ "tests/DomTypes.cpp",
+ "tests/JsonReader.cpp",
+ ]
+
+ deps = [
+ ":skrive",
+ "../..:gpu_tool_utils",
+ "../..:skia",
+ ]
+ }
+ }
+ }
+} else {
+ group("skrive") {
+ }
+ group("tests") {
+ }
+}
diff --git a/chromium/third_party/skia/experimental/skrive/include/SkRive.h b/chromium/third_party/skia/experimental/skrive/include/SkRive.h
new file mode 100644
index 00000000000..e4b2287bf51
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/include/SkRive.h
@@ -0,0 +1,266 @@
+/*
+ * 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 SkRive_DEFINED
+#define SkRive_DEFINED
+
+#include "include/core/SkBlendMode.h"
+#include "include/core/SkColor.h"
+#include "include/core/SkM44.h"
+#include "include/core/SkPaint.h"
+#include "include/core/SkPathTypes.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkString.h"
+
+#include <memory>
+#include <type_traits>
+#include <vector>
+
+class SkCanvas;
+class SkPaint;
+class SkStreamAsset;
+
+namespace skrive {
+
+#define ACTOR_ATTR(attr_name, attr_type, attr_default) \
+private: \
+ attr_type f##attr_name = attr_default; \
+public: \
+ const attr_type& get##attr_name() const { return f##attr_name; } \
+ void set##attr_name(const attr_type& v) { \
+ if (f##attr_name == v) return; \
+ f##attr_name = v; \
+ this->invalidate(); \
+ } \
+ void set##attr_name(attr_type&& v) { \
+ if (f##attr_name == v) return; \
+ f##attr_name = std::move(v); \
+ this->invalidate(); \
+ }
+
+class Node;
+
+class Component : public SkRefCnt {
+public:
+ ACTOR_ATTR(Name, SkString, SkString())
+
+ template <typename T>
+ std::enable_if_t<std::is_base_of<Component, T>::value, bool>
+ is() const {
+ if constexpr(std::is_same<Component, T>::value) {
+ return true;
+ } else {
+ return is_base_of<T>(fType);
+ }
+ }
+
+ template <typename T>
+ operator const T*() const {
+ return this->is<T>() ? reinterpret_cast<const T*>(this) : nullptr;
+ }
+
+ template <typename T>
+ operator T*() {
+ return this->is<T>() ? reinterpret_cast<T*>(this) : nullptr;
+ }
+
+ void revalidate();
+
+protected:
+ enum class Type : uint32_t {
+ kNode,
+ kShape,
+ kColorPaint,
+ kEllipse,
+ };
+
+ explicit Component(Type t) : fType(t) {}
+
+ void invalidate();
+
+ bool hasInval() const { return fDirty; }
+
+ virtual void onRevalidate() = 0;
+
+private:
+ friend class Node; // parent access
+
+ template <typename T>
+ static constexpr bool is_base_of(Type t);
+
+ const Type fType;
+
+ Node* fParent = nullptr;
+ bool fDirty = true;
+};
+
+class TransformableComponent : public Component {
+public:
+ ACTOR_ATTR(Translation , SkV2 , SkV2({0, 0}))
+ ACTOR_ATTR(Scale , SkV2 , SkV2({1, 1}))
+ ACTOR_ATTR(Rotation , float, 0 )
+ ACTOR_ATTR(Opacity , float, 1 )
+
+protected:
+ explicit TransformableComponent(Type t) : INHERITED(t) {}
+
+private:
+
+ using INHERITED = Component;
+};
+
+class Node : public TransformableComponent {
+public:
+ Node() : INHERITED(Type::kNode) {}
+
+ ACTOR_ATTR(CollapsedVisibility, bool , false )
+
+ void addChild(sk_sp<Component>);
+
+protected:
+ explicit Node(Type t) : INHERITED(t) {}
+
+private:
+ void onRevalidate() override;
+
+ std::vector<sk_sp<Component>> fChildren;
+
+ using INHERITED = TransformableComponent;
+};
+
+class Drawable : public Node {
+public:
+ ACTOR_ATTR(DrawOrder, size_t , 0 )
+ ACTOR_ATTR(BlendMode, SkBlendMode, SkBlendMode::kSrcOver)
+ ACTOR_ATTR(IsHidden , bool , false )
+
+protected:
+ explicit Drawable(Type t) : INHERITED(t) {}
+
+private:
+ using INHERITED = Node;
+};
+
+class Shape final : public Drawable {
+public:
+ Shape() : INHERITED(Type::kShape) {}
+
+ ACTOR_ATTR(TransformAffectsStroke, bool, true)
+
+private:
+ void onRevalidate() override;
+
+ using INHERITED = Drawable;
+};
+
+class Paint : public Component {
+public:
+ ACTOR_ATTR(Opacity , float , 1 )
+ ACTOR_ATTR(FillRule , SkPathFillType, SkPathFillType::kWinding )
+ ACTOR_ATTR(StrokeWidth, float , 1 )
+ ACTOR_ATTR(StrokeCap , SkPaint::Cap , SkPaint::Cap::kButt_Cap )
+ ACTOR_ATTR(StrokeJoin , SkPaint::Join , SkPaint::Join::kMiter_Join)
+
+ enum class StrokeTrim : uint8_t { kOff, kSequential, kSynced };
+ ACTOR_ATTR(StrokeTrim , StrokeTrim, StrokeTrim::kOff)
+ ACTOR_ATTR(StrokeTrimStart , float , 0)
+ ACTOR_ATTR(StrokeTrimEnd , float , 0)
+ ACTOR_ATTR(StrokeTrimOffset, float , 0)
+
+ void apply(SkPaint*) const;
+
+ SkPaint::Style style() const { return fStyle; }
+
+protected:
+ Paint(Type t, SkPaint::Style style) : INHERITED(t), fStyle(style) {}
+
+ virtual void onApply(SkPaint*) const = 0;
+
+private:
+ const SkPaint::Style fStyle;
+
+ using INHERITED = Component;
+};
+
+class ColorPaint final : public Paint {
+public:
+ explicit ColorPaint(SkPaint::Style style) : INHERITED(Type::kColorPaint, style) {}
+
+ ACTOR_ATTR(Color, SkColor4f, SkColors::kBlack)
+
+private:
+ void onRevalidate() override;
+
+ void onApply(SkPaint*) const override;
+
+ using INHERITED = Paint;
+};
+
+class Geometry : public TransformableComponent {
+protected:
+ explicit Geometry(Type t) : INHERITED(t) {}
+
+private:
+ using INHERITED = TransformableComponent;
+};
+
+class Ellipse final : public Geometry {
+public:
+ Ellipse() : INHERITED(Type::kEllipse) {}
+
+ ACTOR_ATTR(Width , float, 0)
+ ACTOR_ATTR(Height, float, 0)
+
+private:
+ void onRevalidate() override;
+
+ using INHERITED = Geometry;
+};
+
+template <typename T>
+constexpr bool Component::is_base_of(Type t) {
+ if (t == Type::kNode ) return std::is_base_of<T, Node >::value;
+ if (t == Type::kShape ) return std::is_base_of<T, Shape >::value;
+ if (t == Type::kColorPaint) return std::is_base_of<T, ColorPaint>::value;
+ if (t == Type::kEllipse ) return std::is_base_of<T, Ellipse >::value;
+
+ return false;
+}
+
+class Artboard final : public SkRefCnt {
+public:
+ ACTOR_ATTR(Root , sk_sp<Node>, nullptr )
+ ACTOR_ATTR(Name , SkString , SkString() )
+ ACTOR_ATTR(Color , SkColor4f , SkColors::kBlack)
+ ACTOR_ATTR(Size , SkV2 , SkV2({0,0}) )
+ ACTOR_ATTR(Origin , SkV2 , SkV2({0,0}) )
+ ACTOR_ATTR(Translation , SkV2 , SkV2({0,0}) )
+ ACTOR_ATTR(ClipContents, bool , false )
+
+ void render(SkCanvas*) const;
+
+private:
+ void invalidate() {}
+};
+
+class SK_API SkRive final : public SkNVRefCnt<SkRive> {
+public:
+ class Builder final {
+ public:
+ sk_sp<SkRive> make(std::unique_ptr<SkStreamAsset>);
+ };
+
+ const std::vector<sk_sp<Artboard>>& artboards() const { return fArtboards; }
+ std::vector<sk_sp<Artboard>>& artboards() { return fArtboards; }
+
+private:
+ std::vector<sk_sp<Artboard>> fArtboards;
+};
+
+} // skrive
+
+#endif // SkRive_DEFINED
diff --git a/chromium/third_party/skia/experimental/skrive/skrive.gni b/chromium/third_party/skia/experimental/skrive/skrive.gni
new file mode 100644
index 00000000000..9dc537d7c91
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/skrive.gni
@@ -0,0 +1,26 @@
+# Copyright 2020 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Things are easiest for everyone if these source paths are absolute.
+_src = get_path_info("src", "abspath")
+_include = get_path_info("include", "abspath")
+
+skia_skrive_public = [ "$_include/SkRive.h" ]
+
+skia_skrive_sources = [
+ "$_src/Artboard.cpp",
+ "$_src/Color.cpp",
+ "$_src/Component.cpp",
+ "$_src/Drawable.cpp",
+ "$_src/Ellipse.cpp",
+ "$_src/Node.cpp",
+ "$_src/Paint.cpp",
+ "$_src/Shape.cpp",
+ "$_src/SkRive.cpp",
+ "$_src/reader/BinaryReader.cpp",
+ "$_src/reader/JsonReader.cpp",
+ "$_src/reader/StreamReader.cpp",
+ "$_src/reader/StreamReader.h",
+]
diff --git a/chromium/third_party/skia/experimental/skrive/src/Artboard.cpp b/chromium/third_party/skia/experimental/skrive/src/Artboard.cpp
new file mode 100644
index 00000000000..662730d9ecb
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/src/Artboard.cpp
@@ -0,0 +1,133 @@
+/*
+ * 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 "experimental/skrive/include/SkRive.h"
+
+#include "experimental/skrive/src/reader/StreamReader.h"
+#include "include/core/SkCanvas.h"
+
+#include <tuple>
+#include <vector>
+
+namespace skrive {
+
+namespace internal {
+
+template <typename T>
+size_t parse_node(StreamReader*, T*);
+
+template <typename T, typename... Args>
+std::tuple<sk_sp<Component>, size_t> make_from_stream(StreamReader* sr, Args&&... args) {
+ auto node = sk_make_sp<T>(std::forward<Args>(args)...);
+
+ const auto parent_index = parse_node<T>(sr, node.get());
+
+ return std::make_tuple(std::move(node), parent_index);
+}
+
+std::tuple<sk_sp<Component>, size_t> parse_component(StreamReader* sr) {
+ StreamReader::AutoBlock block(sr);
+ switch (block.type()) {
+ case StreamReader::BlockType::kActorNode:
+ return make_from_stream<Node >(sr);
+ case StreamReader::BlockType::kActorShape:
+ return make_from_stream<Shape>(sr);
+ case StreamReader::BlockType::kColorFill:
+ return make_from_stream<ColorPaint>(sr, SkPaint::kFill_Style);
+ case StreamReader::BlockType::kColorStroke:
+ return make_from_stream<ColorPaint>(sr, SkPaint::kStroke_Style);
+ case StreamReader::BlockType::kActorEllipse:
+ return make_from_stream<Ellipse>(sr);
+ default:
+ break;
+ }
+
+ SkDebugf("!! unsupported node type: %d\n", block.type());
+ return {nullptr, 0};
+}
+
+sk_sp<Node> parse_components(StreamReader* sr) {
+ const auto count = sr->readLength16();
+
+ std::vector<sk_sp<Component>> components;
+ components.reserve(count);
+
+ for (size_t i = 0; i < count; ++i) {
+ auto [ component, parent_index ] = parse_component(sr);
+
+ if (component && parent_index < i && components[parent_index]) {
+ if (Node* node = *components[parent_index]) {
+ node->addChild(component);
+ }
+ }
+
+ components.push_back(std::move(component));
+ }
+
+ SkDebugf(".. parsed %zu components\n", components.size());
+
+ // hmm...
+ for (const auto& comp : components) {
+ if (comp && comp->is<Node>()) {
+ return sk_ref_sp(static_cast<Node*>(*comp));
+ }
+ }
+
+ return nullptr;
+}
+
+sk_sp<Artboard> parse_artboard(StreamReader* sr) {
+ auto ab = sk_make_sp<Artboard>();
+
+ ab->setName (sr->readString("name" ));
+ ab->setTranslation (sr->readV2 ("translation" ));
+ ab->setSize ({sr->readFloat ("width" ),
+ sr->readFloat ("height" )});
+ ab->setOrigin (sr->readV2 ("origin" ));
+ ab->setClipContents(sr->readBool ("clipContents"));
+ ab->setColor (sr->readColor ("color" ));
+
+ for (;;) {
+ StreamReader::AutoBlock block(sr);
+ if (block.type() == StreamReader::BlockType::kEoB) {
+ break;
+ }
+
+ switch (block.type()) {
+ case StreamReader::BlockType::kComponents:
+ ab->setRoot(parse_components(sr));
+ break;
+ default:
+ SkDebugf("!! Unsupported block type: %d\n", block.type());
+ break;
+ }
+ }
+
+ SkDebugf(".. parsed artboard \"%s\" [%f x %f]\n",
+ ab->getName().c_str(), ab->getSize().x, ab->getSize().y);
+
+ return ab;
+}
+
+} // namespace internal
+
+void Artboard::render(SkCanvas* canvas) const {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->translate(fTranslation.x, fTranslation.y);
+
+ SkPaint paint;
+ paint.setColor4f(fColor);
+
+ canvas->drawRect(SkRect::MakeWH(fSize.x, fSize.y), paint);
+
+ if (fRoot) {
+ fRoot->revalidate();
+
+ }
+}
+
+} // namespace skrive
diff --git a/chromium/third_party/skia/experimental/skrive/src/Color.cpp b/chromium/third_party/skia/experimental/skrive/src/Color.cpp
new file mode 100644
index 00000000000..e9c8b7e1195
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/src/Color.cpp
@@ -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.
+ */
+
+#include "experimental/skrive/include/SkRive.h"
+
+#include "experimental/skrive/src/reader/StreamReader.h"
+
+namespace skrive {
+
+namespace internal {
+
+template <typename T>
+size_t parse_node(StreamReader*, T*);
+
+extern void parse_fill_stroke(StreamReader*, Paint*);
+
+template <>
+size_t parse_node<ColorPaint>(StreamReader* sr, ColorPaint* node) {
+ const auto parent_index = parse_node<Paint>(sr, node);
+
+ node->setColor(sr->readColor("color"));
+
+ parse_fill_stroke(sr, node);
+
+ return parent_index;
+}
+
+} // namespace internal
+
+void ColorPaint::onRevalidate() {}
+
+void ColorPaint::onApply(SkPaint* paint) const {}
+
+} // namespace skrive
diff --git a/chromium/third_party/skia/experimental/skrive/src/Component.cpp b/chromium/third_party/skia/experimental/skrive/src/Component.cpp
new file mode 100644
index 00000000000..6df461b5232
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/src/Component.cpp
@@ -0,0 +1,59 @@
+/*
+ * 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 "experimental/skrive/include/SkRive.h"
+
+#include "experimental/skrive/src/reader/StreamReader.h"
+
+namespace skrive {
+namespace internal {
+
+template <typename T>
+size_t parse_node(StreamReader*, T*);
+
+template <>
+size_t parse_node<Component>(StreamReader* sr, Component* node) {
+ node->setName(sr->readString("name"));
+
+ const auto parent_index = sr->readUInt16("parent");
+
+ SkDebugf(".. %s -> %d\n", node->getName().c_str(), parent_index);
+
+ return parent_index;
+}
+
+template <>
+size_t parse_node<TransformableComponent>(StreamReader* sr, TransformableComponent* node) {
+ const auto parent_index = parse_node<Component>(sr, node);
+
+ node->setTranslation(sr->readV2("translation"));
+ node->setRotation(sr->readFloat("rotation"));
+ node->setScale(sr->readV2("scale"));
+ node->setOpacity(sr->readFloat("opacity"));
+
+ return parent_index;
+}
+
+} // namespace internal
+
+void Component::invalidate() {
+ auto* node = this;
+
+ do {
+ node->fDirty = true;
+ node = node->fParent;
+ } while (node && !node->hasInval());
+}
+
+void Component::revalidate() {
+ if (this->hasInval()) {
+ this->onRevalidate();
+ fDirty = false;
+ }
+}
+
+} // namespace skrive
diff --git a/chromium/third_party/skia/experimental/skrive/src/Drawable.cpp b/chromium/third_party/skia/experimental/skrive/src/Drawable.cpp
new file mode 100644
index 00000000000..4703f579b34
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/src/Drawable.cpp
@@ -0,0 +1,32 @@
+/*
+ * 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 "experimental/skrive/include/SkRive.h"
+
+#include "experimental/skrive/src/reader/StreamReader.h"
+
+namespace skrive::internal {
+template <typename T>
+size_t parse_node(StreamReader*, T*);
+
+template <>
+size_t parse_node<Drawable>(StreamReader* sr, Drawable* node) {
+ const auto parent_index = parse_node<Node>(sr, node);
+
+ node->setIsHidden(!sr->readBool("isVisible"));
+
+ const auto bm = sr->readUInt8("blendMode");
+ if (bm <= static_cast<uint8_t>(SkBlendMode::kLastMode)) {
+ node->setBlendMode(static_cast<SkBlendMode>(bm));
+ }
+
+ node->setDrawOrder(sr->readUInt16("drawOrder"));
+
+ return parent_index;
+}
+
+} // namespace skrive::internal
diff --git a/chromium/third_party/skia/experimental/skrive/src/Ellipse.cpp b/chromium/third_party/skia/experimental/skrive/src/Ellipse.cpp
new file mode 100644
index 00000000000..4ccb08f3be6
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/src/Ellipse.cpp
@@ -0,0 +1,32 @@
+/*
+ * 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 "experimental/skrive/include/SkRive.h"
+
+#include "experimental/skrive/src/reader/StreamReader.h"
+
+namespace skrive {
+namespace internal {
+
+template <typename T>
+size_t parse_node(StreamReader*, T*);
+
+template <>
+size_t parse_node<Ellipse>(StreamReader* sr, Ellipse* node) {
+ const auto parent_index = parse_node<TransformableComponent>(sr, node);
+
+ node->setWidth(sr->readFloat("width"));
+ node->setHeight(sr->readFloat("height"));
+
+ return parent_index;
+}
+
+} // namespace internal
+
+void Ellipse::onRevalidate() {}
+
+} // namespace skrive
diff --git a/chromium/third_party/skia/experimental/skrive/src/Node.cpp b/chromium/third_party/skia/experimental/skrive/src/Node.cpp
new file mode 100644
index 00000000000..f988a0f2f68
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/src/Node.cpp
@@ -0,0 +1,65 @@
+/*
+ * 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 "experimental/skrive/include/SkRive.h"
+
+#include "experimental/skrive/src/reader/StreamReader.h"
+
+#include <tuple>
+
+namespace skrive {
+namespace internal {
+
+template <typename T>
+size_t parse_node(StreamReader*, T*);
+
+template <>
+size_t parse_node<Node>(StreamReader* sr, Node* node) {
+ const auto parent_index = parse_node<TransformableComponent>(sr, node);
+
+ node->setCollapsedVisibility(sr->readBool("isCollapsed"));
+
+ if (sr->openArray("clips")) {
+ const auto count = sr->readLength8();
+
+ SkDebugf(".. %d clips\n", count);
+
+ for (size_t i = 0; i < count; ++i) {
+ if (sr->openObject("clip")) {
+ /*const auto clip_id =*/ sr->readUInt16("node");
+ /*const auto intersect =*/ sr->readBool("intersect");
+
+ // TODO: actually use clips
+ sr->closeObject();
+ }
+ }
+
+ sr->closeArray();
+ }
+
+ return parent_index;
+}
+
+} // namespace skrive
+
+void Node::addChild(sk_sp<Component> child) {
+ child->fParent = this;
+ fChildren.push_back(std::move(child));
+ this->invalidate();
+}
+
+void Node::onRevalidate() {
+ SkASSERT(this->hasInval());
+
+ for (const auto& child : fChildren) {
+ if (child) {
+ child->revalidate();
+ }
+ }
+}
+
+} // namespace internal
diff --git a/chromium/third_party/skia/experimental/skrive/src/Paint.cpp b/chromium/third_party/skia/experimental/skrive/src/Paint.cpp
new file mode 100644
index 00000000000..828f63ad782
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/src/Paint.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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 "experimental/skrive/include/SkRive.h"
+
+#include "experimental/skrive/src/reader/StreamReader.h"
+
+namespace skrive {
+
+namespace internal {
+
+template <typename T>
+size_t parse_node(StreamReader*, T*);
+
+template <>
+size_t parse_node<Paint>(StreamReader* sr, Paint* node) {
+ const auto parent_index = parse_node<Component>(sr, node);
+
+ node->setOpacity(sr->readFloat("opacity"));
+
+ return parent_index;
+}
+
+void parse_fill_stroke(StreamReader* sr, Paint* node) {
+ if (node->style() == SkPaint::kFill_Style) {
+ static constexpr SkPathFillType gFillTypeMap[] = {
+ SkPathFillType::kWinding, // 0
+ SkPathFillType::kEvenOdd, // 1
+ };
+ node->setFillRule(gFillTypeMap[std::min<size_t>(sr->readUInt8("fillRule"),
+ SK_ARRAY_COUNT(gFillTypeMap) - 1)]);
+ } else {
+ node->setStrokeWidth(sr->readFloat("width"));
+
+ static constexpr SkPaint::Cap gCapMap[] = {
+ SkPaint::kButt_Cap, // 0
+ SkPaint::kRound_Cap, // 1
+ SkPaint::kSquare_Cap, // 2
+ };
+ node->setStrokeCap(gCapMap[std::min<size_t>(sr->readUInt8("cap"),
+ SK_ARRAY_COUNT(gCapMap) - 1)]);
+
+ static constexpr SkPaint::Join gJoinMap[] = {
+ SkPaint::kMiter_Join, // 0
+ SkPaint::kRound_Join, // 1
+ SkPaint::kBevel_Join, // 2
+ };
+ node->setStrokeJoin(gJoinMap[std::min<size_t>(sr->readUInt8("join"),
+ SK_ARRAY_COUNT(gJoinMap) - 1)]);
+
+ static constexpr Paint::StrokeTrim gTrimMap[] = {
+ Paint::StrokeTrim::kOff, // 0
+ Paint::StrokeTrim::kSequential, // 1
+ Paint::StrokeTrim::kSynced, // 2
+ };
+ node->setStrokeTrim(gTrimMap[std::min<size_t>(sr->readUInt8("trim"),
+ SK_ARRAY_COUNT(gTrimMap) - 1)]);
+
+ if (node->getStrokeTrim() != Paint::StrokeTrim::kOff) {
+ node->setStrokeTrimStart (sr->readFloat("start" ));
+ node->setStrokeTrimEnd (sr->readFloat("end" ));
+ node->setStrokeTrimOffset(sr->readFloat("offset"));
+ }
+ }
+}
+
+} // namespace internal
+} // namespace skrive
diff --git a/chromium/third_party/skia/experimental/skrive/src/Shape.cpp b/chromium/third_party/skia/experimental/skrive/src/Shape.cpp
new file mode 100644
index 00000000000..1091216161d
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/src/Shape.cpp
@@ -0,0 +1,31 @@
+/*
+ * 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 "experimental/skrive/include/SkRive.h"
+
+#include "experimental/skrive/src/reader/StreamReader.h"
+
+namespace skrive {
+namespace internal {
+
+template <typename T>
+size_t parse_node(StreamReader*, T*);
+
+template <>
+size_t parse_node<Shape>(StreamReader* sr, Shape* node) {
+ const auto parent_index = parse_node<Drawable>(sr, node);
+
+ node->setTransformAffectsStroke(sr->readBool("transformAffectsStroke"));
+
+ return parent_index;
+}
+
+} // namespace internal
+
+void Shape::onRevalidate() {}
+
+} // namespace skrive
diff --git a/chromium/third_party/skia/experimental/skrive/src/SkRive.cpp b/chromium/third_party/skia/experimental/skrive/src/SkRive.cpp
new file mode 100644
index 00000000000..971b609d753
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/src/SkRive.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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 "experimental/skrive/include/SkRive.h"
+
+#include "experimental/skrive/src/reader/StreamReader.h"
+#include "include/core/SkStream.h"
+
+namespace skrive {
+
+namespace internal {
+
+extern sk_sp<Artboard> parse_artboard(StreamReader*);
+
+void parse_artboards(const sk_sp<SkRive>& skrive, StreamReader* sr) {
+ const size_t artboard_count = sr->readLength16();
+ skrive->artboards().reserve(artboard_count);
+
+ for (size_t i = 0; i < artboard_count; ++i) {
+ StreamReader::AutoBlock block(sr);
+ if (block.type() == StreamReader::BlockType::kEoB) {
+ break;
+ }
+ if (block.type() != StreamReader::BlockType::kActorArtboard) {
+ SkDebugf("!! Unexpected artboard block type: %d\n", block.type());
+ continue;
+ }
+
+ skrive->artboards().push_back(parse_artboard(sr));
+ }
+}
+
+static sk_sp<SkRive> parse_skrive(std::unique_ptr<StreamReader> sr) {
+ if (!sr) {
+ return nullptr;
+ }
+
+ const auto version = sr->readUInt32("version");
+ SkDebugf(".. loading version %d\n", version);
+
+ auto skrive = sk_make_sp<SkRive>();
+
+ for (;;) {
+ StreamReader::AutoBlock block(sr);
+ if (block.type() == StreamReader::BlockType::kEoB) {
+ break;
+ }
+
+ switch (block.type()) {
+ case StreamReader::BlockType::kArtboards:
+ parse_artboards(skrive, sr.get());
+ break;
+ default:
+ SkDebugf("!! Unsupported block type: %d\n", block.type());
+ break;
+ }
+ }
+
+ return skrive;
+}
+
+} // namespace internal
+
+sk_sp<SkRive> SkRive::Builder::make(std::unique_ptr<SkStreamAsset> stream) {
+ auto reader = internal::StreamReader::Make(std::move(stream));
+
+ return reader ? parse_skrive(std::move(reader))
+ : nullptr;
+}
+
+} // namespace skrive
diff --git a/chromium/third_party/skia/experimental/skrive/src/reader/BinaryReader.cpp b/chromium/third_party/skia/experimental/skrive/src/reader/BinaryReader.cpp
new file mode 100644
index 00000000000..f9c622c5335
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/src/reader/BinaryReader.cpp
@@ -0,0 +1,149 @@
+/*
+ * 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 "experimental/skrive/src/reader/StreamReader.h"
+#include "include/core/SkStream.h"
+#include "include/core/SkString.h"
+
+#include <vector>
+
+namespace skrive::internal {
+
+namespace {
+
+class BinaryReader final : public StreamReader {
+public:
+ explicit BinaryReader(std::unique_ptr<SkStreamAsset> stream)
+ : fStream(std::move(stream)) {}
+
+private:
+ bool validateSize(size_t sz) const {
+ const auto next_pos = fStream->getPosition() + sz,
+ block_end = fBlockStack.empty() ? fStream->getLength()
+ : fBlockStack.back().block_end;
+ return next_pos <= block_end;
+ }
+
+ bool readBool(const char[]) override {
+ uint8_t v;
+
+ return validateSize(sizeof(v)) && fStream->readU8(&v)
+ ? v == 1
+ : false;
+ }
+
+ float readFloat(const char[]) override {
+ float v;
+
+ return validateSize(sizeof(v)) && fStream->readScalar(&v)
+ ? v
+ : 0.0f;
+ }
+
+ uint8_t readUInt8(const char[]) override {
+ uint8_t v;
+
+ return validateSize(sizeof(v)) && fStream->readU8(&v)
+ ? v
+ : 0;
+ }
+
+ uint16_t readUInt16(const char[]) override {
+ uint16_t v;
+
+ return validateSize(sizeof(v)) && fStream->readU16(&v)
+ ? v
+ : 0;
+ }
+
+ uint32_t readUInt32(const char[]) override {
+ uint32_t v;
+
+ return validateSize(sizeof(v)) && fStream->readU32(&v)
+ ? v
+ : 0;
+ }
+
+ SkString readString(const char[]) override {
+ uint32_t length;
+ if (!validateSize(sizeof(length)) || !fStream->readU32(&length)) {
+ return SkString();
+ }
+
+ SkString str(length);
+ return validateSize(length) && fStream->read(str.writable_str(), length) == length
+ ? str
+ : SkString();
+ }
+
+ size_t readFloatArray(const char[], float dst[], size_t count) override {
+ if (!validateSize(count * sizeof(float))) {
+ return 0;
+ }
+
+ return fStream->read(dst, count * sizeof(float)) / sizeof(float);
+ }
+
+ uint8_t readLength8() override {
+ return this->readUInt8(nullptr);
+ }
+
+ uint16_t readLength16() override {
+ return this->readUInt16(nullptr);
+ }
+
+ // nops
+ bool openArray(const char[]) override { return true; }
+ void closeArray() override {}
+ bool openObject(const char[]) override { return true; }
+ void closeObject() override {}
+
+ BlockType openBlock() override {
+ uint8_t block_type;
+ uint32_t block_size;
+
+ if (this->validateSize(sizeof(block_type) + sizeof(block_size)) &&
+ fStream->readU8 (&block_type) &&
+ fStream->readU32(&block_size)) {
+ const auto block_end = std::min(fStream->getPosition() + block_size,
+ fStream->getLength());
+ fBlockStack.push_back({block_end});
+ return static_cast<BlockType>(block_type);
+ }
+
+ return BlockType::kEoB;
+ }
+
+ void closeBlock() override {
+ SkASSERT(!fBlockStack.empty());
+ SkASSERT(fStream->getPosition() <= fBlockStack.back().block_end);
+
+ if (fStream->getPosition() < fBlockStack.back().block_end) {
+ const auto skip = fBlockStack.back().block_end - fStream->getPosition();
+ SkDebugf("!! skipping %zu bytes in block\n", skip);
+ fStream->skip(skip);
+ }
+
+ fBlockStack.pop_back();
+ }
+
+ const std::unique_ptr<SkStreamAsset> fStream;
+
+ struct BlockRec {
+ size_t block_end;
+ };
+
+ std::vector<BlockRec> fBlockStack;
+};
+
+} // namespace
+
+std::unique_ptr<StreamReader> MakeBinaryStreamReader(std::unique_ptr<SkStreamAsset> stream) {
+ return std::make_unique<BinaryReader>(std::move(stream));
+}
+
+}
diff --git a/chromium/third_party/skia/experimental/skrive/src/reader/JsonReader.cpp b/chromium/third_party/skia/experimental/skrive/src/reader/JsonReader.cpp
new file mode 100644
index 00000000000..bbc42aa6946
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/src/reader/JsonReader.cpp
@@ -0,0 +1,251 @@
+/*
+ * 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 "experimental/skrive/src/reader/StreamReader.h"
+#include "include/core/SkString.h"
+#include "src/utils/SkJSON.h"
+
+#include <algorithm>
+#include <iterator>
+#include <memory>
+
+namespace skrive::internal {
+namespace {
+
+StreamReader::BlockType block_type(const char* type_name) {
+ static constexpr struct TypeMapEntry {
+ const char* name;
+ StreamReader::BlockType block_type;
+ } gTypeMap[] = {
+ {"artboard" , StreamReader::BlockType::kActorArtboard },
+ {"artboards" , StreamReader::BlockType::kArtboards },
+ {"colorFill" , StreamReader::BlockType::kColorFill },
+ {"colorStroke" , StreamReader::BlockType::kColorStroke },
+ {"ellipse" , StreamReader::BlockType::kActorEllipse },
+ {"gradientFill" , StreamReader::BlockType::kGradientFill },
+ {"gradientStroke" , StreamReader::BlockType::kGradientStroke },
+ {"node" , StreamReader::BlockType::kActorNode },
+ {"nodes" , StreamReader::BlockType::kComponents },
+ {"path" , StreamReader::BlockType::kActorPath },
+ {"radialGradientFill" , StreamReader::BlockType::kRadialGradientFill },
+ {"radialGradientStroke", StreamReader::BlockType::kRadialGradientStroke },
+ {"rectangle" , StreamReader::BlockType::kActorRectangle },
+ {"shape" , StreamReader::BlockType::kActorShape },
+ };
+
+ const TypeMapEntry key = { type_name, StreamReader::BlockType::kUnknown };
+ const auto* map_entry = std::lower_bound(std::begin(gTypeMap),
+ std::end (gTypeMap),
+ key,
+ [](const TypeMapEntry& a, const TypeMapEntry& b) {
+ return strcmp(a.name, b.name) < 0;
+ });
+
+ return (map_entry != std::end(gTypeMap) && !strcmp(map_entry->name, key.name))
+ ? map_entry->block_type
+ : StreamReader::BlockType::kUnknown;
+}
+
+class JsonReader final : public StreamReader {
+public:
+ explicit JsonReader(std::unique_ptr<skjson::DOM> dom)
+ : fDom(std::move(dom)) {
+ fContextStack.push_back({&fDom->root(), 0});
+ }
+
+ ~JsonReader() override {
+ SkASSERT(fContextStack.size() == 1);
+ }
+
+private:
+ template <typename T>
+ const T* readProp(const char label[]) {
+ auto& ctx = fContextStack.back();
+
+ if (ctx.fContainer->is<skjson::ObjectValue>()) {
+ return static_cast<const T*>(ctx.fContainer->as<skjson::ObjectValue>()[label]);
+ }
+
+ const skjson::ArrayValue* jarr = *ctx.fContainer;
+ SkASSERT(jarr);
+
+ return ctx.fMemberIndex < jarr->size()
+ ? static_cast<const T*>((*jarr)[ctx.fMemberIndex++])
+ : nullptr;
+ }
+
+ bool readBool(const char label[]) override {
+ const auto* jbool = this->readProp<skjson::BoolValue>(label);
+
+ return jbool ? **jbool : false;
+ }
+
+ float readFloat(const char label[]) override {
+ const auto* jnum = this->readProp<skjson::NumberValue>(label);
+
+ return jnum ? static_cast<float>(**jnum) : 0.0f;
+ }
+
+ uint8_t readUInt8(const char label[]) override {
+ return static_cast<uint8_t>(this->readUInt32(label));
+ }
+
+ uint16_t readUInt16(const char label[]) override {
+ return static_cast<uint16_t>(this->readUInt32(label));
+ }
+
+ uint32_t readUInt32(const char label[]) override {
+ const auto* jnum = this->readProp<skjson::NumberValue>(label);
+
+ return jnum ? static_cast<uint32_t>(**jnum) : 0;
+ }
+
+ SkString readString(const char label[]) override {
+ const auto* jstr = this->readProp<skjson::StringValue>(label);
+
+ return SkString(jstr ? jstr->begin() : nullptr);
+ }
+
+ size_t readFloatArray(const char label[], float dst[], size_t count) override {
+ const auto* jarr = this->readProp<skjson::ArrayValue>(label);
+
+ if (!jarr) {
+ return 0;
+ }
+
+ count = std::min(count, jarr->size());
+
+ for (size_t i = 0; i < count; ++i) {
+ const skjson::NumberValue* jnum = (*jarr)[i];
+ dst[i] = jnum ? static_cast<float>(**jnum) : 0.0f;
+ }
+
+ return count;
+ }
+
+ uint8_t readLength8() override {
+ return SkToU8(this->currentLength());
+ }
+
+ uint16_t readLength16() override {
+ return SkToU16(this->currentLength());
+ }
+
+ size_t currentLength() const {
+ const auto& ctx = fContextStack.back();
+ return ctx.fContainer->is<skjson::ObjectValue>()
+ ? ctx.fContainer->as<skjson::ObjectValue>().size()
+ : ctx.fContainer->as<skjson:: ArrayValue>().size();
+ }
+
+ bool openArray(const char label[]) override {
+ const auto* jarr = this->readProp<skjson::ArrayValue>(label);
+ if (!jarr) {
+ return false;
+ }
+
+ fContextStack.push_back({jarr, 0});
+ return true;
+ }
+
+ void closeArray() override {
+ SkASSERT(fContextStack.back().fContainer->is<skjson::ArrayValue>());
+ fContextStack.pop_back();
+ }
+
+ bool openObject(const char label[]) override {
+ const auto* jobj = this->readProp<skjson::ObjectValue>(label);
+ if (!jobj) {
+ return false;
+ }
+
+ fContextStack.push_back({jobj, 0});
+ return true;
+ }
+
+ void closeObject() override {
+ SkASSERT(fContextStack.back().fContainer->is<skjson::ObjectValue>());
+ fContextStack.pop_back();
+ }
+
+ // "Blocks" map to either objects or arrays. For object containers, the block type is encoded
+ // as the key; for array containers, the type is an explicit "type" property *inside* the block
+ // entry - which must be an object in this case.
+ BlockType openBlock() override {
+ switch (fContextStack.back().fContainer->getType()) {
+ case skjson::Value::Type::kObject: return this->openObjectBlock();
+ case skjson::Value::Type::kArray: return this->openArrayBlock();
+ default: break;
+ }
+ SkUNREACHABLE;
+ }
+
+ BlockType openObjectBlock() {
+ auto& ctx = fContextStack.back();
+ const auto& container = ctx.fContainer->as<skjson::ObjectValue>();
+
+ while (ctx.fMemberIndex < container.size()) {
+ const auto& m = container[ctx.fMemberIndex];
+ if (m.fValue.is<skjson::ObjectValue>() || m.fValue.is<skjson::ArrayValue>()) {
+ const auto btype = block_type(m.fKey.begin());
+ if (btype != BlockType::kUnknown) {
+ fContextStack.push_back({&m.fValue, 0});
+ return btype;
+ }
+ }
+
+ ctx.fMemberIndex++;
+ }
+
+ return BlockType::kEoB;
+ }
+
+ BlockType openArrayBlock() {
+ auto& ctx = fContextStack.back();
+ const auto& container = ctx.fContainer->as<skjson::ArrayValue>();
+
+ while (ctx.fMemberIndex < container.size()) {
+ const auto& m = container[ctx.fMemberIndex];
+ if (m.is<skjson::ObjectValue>()) {
+ if (const skjson::StringValue* jtype = m.as<skjson::ObjectValue>()["type"]) {
+ fContextStack.push_back({&m, 0});
+ return block_type(jtype->begin());
+ }
+ }
+
+ ctx.fMemberIndex++;
+ }
+
+ return BlockType::kEoB;
+ }
+
+ void closeBlock() override {
+ SkASSERT(fContextStack.size() > 1);
+ fContextStack.pop_back();
+ fContextStack.back().fMemberIndex++;
+ }
+
+ struct ContextRec {
+ const skjson::Value* fContainer;
+ size_t fMemberIndex;
+ };
+
+ const std::unique_ptr<skjson::DOM> fDom;
+
+ std::vector<ContextRec> fContextStack;
+};
+
+} // namespace
+
+std::unique_ptr<StreamReader> MakeJsonStreamReader(const char json[], size_t len) {
+ auto dom = std::make_unique<skjson::DOM>(json, len);
+
+ return dom->root().is<skjson::ObjectValue>() ? std::make_unique<JsonReader>(std::move(dom))
+ : nullptr;
+}
+
+} // namespace skrive::internal
diff --git a/chromium/third_party/skia/experimental/skrive/src/reader/StreamReader.cpp b/chromium/third_party/skia/experimental/skrive/src/reader/StreamReader.cpp
new file mode 100644
index 00000000000..23abc4ce886
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/src/reader/StreamReader.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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 "experimental/skrive/src/reader/StreamReader.h"
+
+#include "include/core/SkStream.h"
+
+#include <cstring>
+
+namespace skrive::internal {
+
+static constexpr char kBinaryPrefix[] = "FLARE";
+static constexpr size_t kBinaryPrefixSize = sizeof(kBinaryPrefix) - 1;
+
+extern std::unique_ptr<StreamReader> MakeJsonStreamReader(const char[], size_t);
+extern std::unique_ptr<StreamReader> MakeBinaryStreamReader(std::unique_ptr<SkStreamAsset>);
+
+std::unique_ptr<StreamReader> StreamReader::Make(const sk_sp<SkData>& data) {
+ if (data->size() >= kBinaryPrefixSize &&
+ !memcmp(data->data(), kBinaryPrefix, kBinaryPrefixSize)) {
+ auto reader = SkMemoryStream::Make(data);
+ reader->skip(kBinaryPrefixSize);
+
+ return MakeBinaryStreamReader(std::move(reader));
+ }
+
+ return MakeJsonStreamReader(static_cast<const char*>(data->data()), data->size());
+}
+
+std::unique_ptr<StreamReader> StreamReader::Make(std::unique_ptr<SkStreamAsset> stream) {
+ char buf[kBinaryPrefixSize];
+
+ if (stream->read(buf, kBinaryPrefixSize) == kBinaryPrefixSize) {
+ if (!strncmp(buf, kBinaryPrefix, kBinaryPrefixSize)) {
+ // binary stream - we can stay in streaming mode
+ return MakeBinaryStreamReader(std::move(stream));
+ }
+ } else {
+ // stream too short to hold anything useful
+ return nullptr;
+ }
+
+ if (!stream->rewind()) {
+ SkDebugf("!! failed to rewind stream.\n");
+ return nullptr;
+ }
+
+ // read to memory to figure what we're dealing with
+ return StreamReader::Make(SkData::MakeFromStream(stream.get(), stream->getLength()));
+}
+
+SkV2 StreamReader::readV2(const char label[]) {
+ SkV2 v2{0,0};
+
+ this->readFloatArray(label, reinterpret_cast<float*>(&v2), 2);
+
+ return v2;
+}
+
+SkColor4f StreamReader::readColor(const char label[]) {
+ SkColor4f color{0,0,0,1};
+
+ this->readFloatArray(label, reinterpret_cast<float*>(&color), 4);
+
+ return color;
+}
+
+} // namespace skrive::internal
diff --git a/chromium/third_party/skia/experimental/skrive/src/reader/StreamReader.h b/chromium/third_party/skia/experimental/skrive/src/reader/StreamReader.h
new file mode 100644
index 00000000000..c98fb558ebd
--- /dev/null
+++ b/chromium/third_party/skia/experimental/skrive/src/reader/StreamReader.h
@@ -0,0 +1,103 @@
+/*
+ * 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 SkRive_Streamreader_DEFINED
+#define SkRive_Streamreader_DEFINED
+
+#include <memory>
+
+#include "include/core/SkColor.h"
+#include "include/core/SkM44.h"
+#include "include/core/SkRefCnt.h"
+
+class SkStreamAsset;
+class SkString;
+
+namespace skrive::internal {
+
+class StreamReader {
+public:
+ virtual ~StreamReader() = default;
+
+ static std::unique_ptr<StreamReader> Make(std::unique_ptr<SkStreamAsset>);
+ static std::unique_ptr<StreamReader> Make(const sk_sp<SkData>&);
+
+ enum class BlockType : uint8_t {
+ kUnknown = 0,
+ kComponents = 1,
+ kActorNode = 2,
+
+ kActorShape = 100,
+ kActorPath = 101,
+ kColorFill = 102,
+ kColorStroke = 103,
+ kGradientFill = 104,
+ kGradientStroke = 105,
+ kRadialGradientFill = 106,
+ kRadialGradientStroke = 107,
+ kActorEllipse = 108,
+ kActorRectangle = 109,
+ kActorArtboard = 114,
+ kArtboards = 115,
+
+ // End-of-block marker
+ kEoB = 0xff,
+ };
+
+ // Sequential block API
+ virtual BlockType openBlock() = 0;
+ virtual void closeBlock() = 0;
+
+ // Keyed API
+ virtual bool openArray(const char label[]) = 0;
+ virtual void closeArray() = 0;
+ virtual bool openObject(const char label[]) = 0;
+ virtual void closeObject() = 0;
+
+ virtual bool readBool (const char label[]) = 0;
+ virtual float readFloat (const char label[]) = 0;
+ virtual uint8_t readUInt8 (const char label[]) = 0;
+ virtual uint16_t readUInt16(const char label[]) = 0;
+ virtual uint32_t readUInt32(const char label[]) = 0;
+ virtual SkString readString(const char label[]) = 0;
+
+ virtual uint8_t readLength8 () = 0;
+ virtual uint16_t readLength16() = 0;
+
+ SkColor4f readColor(const char label[]);
+ SkV2 readV2(const char label[]);
+
+ class AutoBlock final {
+ public:
+ explicit AutoBlock(StreamReader* reader)
+ : fReader(reader)
+ , fType(reader->openBlock()) {}
+
+ explicit AutoBlock(const std::unique_ptr<StreamReader>& reader)
+ : fReader(reader.get())
+ , fType(reader->openBlock()) {}
+
+ ~AutoBlock() {
+ if (fType != BlockType::kEoB) {
+ fReader->closeBlock();
+ }
+ }
+
+ BlockType type() const { return fType; }
+
+ private:
+ StreamReader* fReader;
+ BlockType fType;
+ };
+
+protected:
+ virtual size_t readFloatArray(const char label[], float dst[], size_t count) = 0;
+};
+
+}
+
+#endif // SkRiveStreamreader_DEFINED
diff --git a/chromium/third_party/skia/experimental/svg/model/SkSVGSVG.cpp b/chromium/third_party/skia/experimental/svg/model/SkSVGSVG.cpp
index a1cc8f75f0a..053f794a428 100644
--- a/chromium/third_party/skia/experimental/svg/model/SkSVGSVG.cpp
+++ b/chromium/third_party/skia/experimental/svg/model/SkSVGSVG.cpp
@@ -14,7 +14,7 @@ SkSVGSVG::SkSVGSVG() : INHERITED(SkSVGTag::kSvg) { }
bool SkSVGSVG::onPrepareToRender(SkSVGRenderContext* ctx) const {
auto viewPortRect = ctx->lengthContext().resolveRect(fX, fY, fWidth, fHeight);
- auto contentMatrix = SkMatrix::MakeTrans(viewPortRect.x(), viewPortRect.y());
+ auto contentMatrix = SkMatrix::Translate(viewPortRect.x(), viewPortRect.y());
auto viewPort = SkSize::Make(viewPortRect.width(), viewPortRect.height());
if (fViewBox.isValid()) {
diff --git a/chromium/third_party/skia/experimental/tools/web_to_mskp b/chromium/third_party/skia/experimental/tools/web_to_mskp
index c2df8a30cca..ba3d0fda753 100755
--- a/chromium/third_party/skia/experimental/tools/web_to_mskp
+++ b/chromium/third_party/skia/experimental/tools/web_to_mskp
@@ -12,12 +12,14 @@ else
EXAMPLE='"/c/Program Files (x86)/Google/Chrome/Application/chrome.exe"'
fi
-if [ $# -ne 3 ] || ! [ -x "$1" ]; then
+if [ $# -lt 3 ] || ! [ -x "$1" ]; then
cat >&2 << EOF
usage:
$0 CHROMIUM_BINARY SOURCE_URL DESTINATION_PATH
+ $0 CHROMIUM_BINARY SOURCE_URL DESTINATION_PATH OPTIONAL_WAIT_TIME # 5 second sleep before capture
e.g:
$0 $EXAMPLE https://www.google.com/ /tmp/foo.mskp
+ $0 $EXAMPLE https://www.google.com/ /tmp/foo.mskp 5
EOF
exit 1
fi
@@ -25,10 +27,11 @@ fi
EXE="$1"
URL="$2"
DST="$3"
+SLP=${4:-0} # sleep in seconds before capture. 4th param iff provided, else 0.
CRASH=~/tmp/headless_crash_dumps
mkdir -p "$CRASH"
-printf 'chrome.gpuBenchmarking.printPagesToSkPictures("%s");\nquit\n' "$DST" | \
+(sleep $SLP; printf 'chrome.gpuBenchmarking.printPagesToSkPictures("%s");\nquit\n' "$DST") | \
"$EXE" --headless --disable-gpu --repl -crash-dumps-dir="$CRASH" \
--no-sandbox --enable-gpu-benchmarking "$URL"
diff --git a/chromium/third_party/skia/experimental/tools/web_to_skp b/chromium/third_party/skia/experimental/tools/web_to_skp
index cde5dce645c..04dfcac78e0 100755
--- a/chromium/third_party/skia/experimental/tools/web_to_skp
+++ b/chromium/third_party/skia/experimental/tools/web_to_skp
@@ -12,12 +12,14 @@ else
EXAMPLE='"/c/Program Files (x86)/Google/Chrome/Application/chrome.exe"'
fi
-if [ $# -ne 3 ] || ! [ -x "$1" ]; then
+if [ $# -lt 3 ] || ! [ -x "$1" ]; then
cat >&2 << EOF
usage:
$0 CHROMIUM_BINARY SOURCE_URL DESTINATION_DIRECTORY
+ $0 CHROMIUM_BINARY SOURCE_URL DESTINATION_DIRECTORY OPTIONAL_WAIT_TIME # 5 second sleep before capture
e.g:
$0 $EXAMPLE https://www.google.com/ /tmp/
+ $0 $EXAMPLE https://www.google.com/ /tmp/ 5
EOF
exit 1
fi
@@ -25,10 +27,11 @@ fi
EXE="$1"
URL="$2"
DST="$3"
+SLP=${4:-0} # sleep in seconds before capture. 4th param iff provided, else 0.
CRASH=~/tmp/headless_crash_dumps
mkdir -p "$CRASH" "$DST"
-printf 'chrome.gpuBenchmarking.printToSkPicture("%s");\nquit\n' "$DST" | \
+(sleep $SLP; printf 'chrome.gpuBenchmarking.printToSkPicture("%s");\nquit\n' "$DST") | \
"$EXE" --headless --disable-gpu --repl -crash-dumps-dir="$CRASH" \
--no-sandbox --enable-gpu-benchmarking "$URL"
diff --git a/chromium/third_party/skia/experimental/wasm-skp-debugger/compile.sh b/chromium/third_party/skia/experimental/wasm-skp-debugger/compile.sh
index ead1d5a2a9d..462ae3d9a93 100755
--- a/chromium/third_party/skia/experimental/wasm-skp-debugger/compile.sh
+++ b/chromium/third_party/skia/experimental/wasm-skp-debugger/compile.sh
@@ -107,7 +107,9 @@ echo "Compiling bitcode"
skia_enable_skshaper=false \
skia_enable_ccpr=false \
skia_enable_nvpr=false \
- skia_enable_fontmgr_empty=false \
+ skia_enable_fontmgr_custom_directory=false \
+ skia_enable_fontmgr_custom_embedded=true \
+ skia_enable_fontmgr_custom_empty=false \
skia_enable_pdf=false"
# Build all the libs, we'll link the appropriate ones down below
@@ -129,8 +131,8 @@ ${EMCXX} \
-std=c++17 \
$WASM_GPU \
--pre-js $BASE_DIR/helper.js \
- --post-js $BASE_DIR/ready.js \
--bind \
+ --no-entry \
$BASE_DIR/fonts/NotoMono-Regular.ttf.cpp \
$BASE_DIR/debugger_bindings.cpp \
$BUILD_DIR/libdebugcanvas.a \
@@ -141,7 +143,7 @@ ${EMCXX} \
-s MODULARIZE=1 \
-s NO_EXIT_RUNTIME=1 \
-s STRICT=1 \
- -s TOTAL_MEMORY=128MB \
+ -s INITIAL_MEMORY=128MB \
-s WARN_UNALIGNED=1 \
-s WASM=1 \
-s USE_WEBGL2=1 \
diff --git a/chromium/third_party/skia/experimental/wasm-skp-debugger/debugger/index.html b/chromium/third_party/skia/experimental/wasm-skp-debugger/debugger/index.html
index aee2fc6563c..702108ae219 100644
--- a/chromium/third_party/skia/experimental/wasm-skp-debugger/debugger/index.html
+++ b/chromium/third_party/skia/experimental/wasm-skp-debugger/debugger/index.html
@@ -10,7 +10,7 @@ let surface;
DebuggerInit({
locateFile: (file) => '/node_modules/debugger/bin/'+file,
-}).ready().then((Debugger) => {
+}).then((Debugger) => {
const player = new Debugger.SkpDebugPlayer();
// Define an event handler for the file input dialog
diff --git a/chromium/third_party/skia/experimental/wasm-skp-debugger/debugger_bindings.cpp b/chromium/third_party/skia/experimental/wasm-skp-debugger/debugger_bindings.cpp
index 5b5090df096..b93480985b1 100644
--- a/chromium/third_party/skia/experimental/wasm-skp-debugger/debugger_bindings.cpp
+++ b/chromium/third_party/skia/experimental/wasm-skp-debugger/debugger_bindings.cpp
@@ -498,7 +498,7 @@ EMSCRIPTEN_BINDINGS(my_module) {
.smart_ptr<sk_sp<SkSurface>>("sk_sp<SkSurface>")
.function("width", &SkSurface::width)
.function("height", &SkSurface::height)
- .function("_flush", select_overload<void()>(&SkSurface::flush))
+ .function("_flush", select_overload<void()>(&SkSurface::flushAndSubmit))
.function("getCanvas", &SkSurface::getCanvas, allow_raw_pointers());
class_<SkCanvas>("SkCanvas")
.function("clear", optional_override([](SkCanvas& self, JSColor color)->void {
diff --git a/chromium/third_party/skia/experimental/wasm-skp-debugger/ready.js b/chromium/third_party/skia/experimental/wasm-skp-debugger/ready.js
deleted file mode 100644
index 60f24862d9e..00000000000
--- a/chromium/third_party/skia/experimental/wasm-skp-debugger/ready.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// See https://github.com/kripken/emscripten/issues/5820#issuecomment-385722568
-// for context on why the .then() that comes with Module breaks things (e.g. infinite loops)
-// and why the below fixes it.
-Module['ready'] = function() {
- return new Promise(function (resolve, reject) {
- Module['onAbort'] = reject;
- if (runtimeInitialized) {
- resolve(Module);
- } else {
- addOnPostRun(function() {
- resolve(Module);
- });
- }
- });
-}
-delete Module['then']; \ No newline at end of file
diff --git a/chromium/third_party/skia/gm/aarectmodes.cpp b/chromium/third_party/skia/gm/aarectmodes.cpp
index 9d593638e66..cd14096d13a 100644
--- a/chromium/third_party/skia/gm/aarectmodes.cpp
+++ b/chromium/third_party/skia/gm/aarectmodes.cpp
@@ -121,7 +121,7 @@ static sk_sp<SkShader> make_bg_shader() {
*bm.getAddr32(1, 0) = *bm.getAddr32(0, 1) = SkPackARGB32(0xFF, 0xCE,
0xCF, 0xCE);
- const SkMatrix m = SkMatrix::MakeScale(SkIntToScalar(6), SkIntToScalar(6));
+ const SkMatrix m = SkMatrix::Scale(SkIntToScalar(6), SkIntToScalar(6));
return bm.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, &m);
}
diff --git a/chromium/third_party/skia/gm/addarc.cpp b/chromium/third_party/skia/gm/addarc.cpp
index 77d0db7bdc6..eeed7d6ca28 100644
--- a/chromium/third_party/skia/gm/addarc.cpp
+++ b/chromium/third_party/skia/gm/addarc.cpp
@@ -38,7 +38,7 @@ protected:
SkPaint paint;
paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
paint.setStrokeWidth(15);
const SkScalar inset = paint.getStrokeWidth() + 4;
@@ -82,7 +82,7 @@ DEF_SIMPLE_GM(addarc_meas, canvas, 2*R + 40, 2*R + 40) {
SkPaint paint;
paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
SkPaint measPaint;
measPaint.setAntiAlias(true);
@@ -129,7 +129,7 @@ protected:
SkPaint paint;
paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
paint.setStrokeWidth(SK_Scalar1 / 2);
const SkScalar delta = paint.getStrokeWidth() * 3 / 2;
@@ -179,7 +179,7 @@ protected:
SkPaint paint;
paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
paint.setStrokeWidth(SK_Scalar1 / 2);
const SkScalar strokeWidth = paint.getStrokeWidth();
@@ -188,7 +188,7 @@ protected:
SkRandom rand;
// Reset style to fill. We only need stroke stype for producing delta and strokeWidth
- paint.setStyle(SkPaint::kFill_Style);
+ paint.setStroke(false);
SkScalar sign = 1;
while (r.width() > strokeWidth * 2) {
@@ -229,7 +229,7 @@ static void html_canvas_arc(SkPath* path, SkScalar x, SkScalar y, SkScalar r, Sk
DEF_SIMPLE_GM(manyarcs, canvas, 620, 330) {
SkPaint paint;
paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
canvas->translate(10, 10);
@@ -274,7 +274,7 @@ DEF_SIMPLE_GM(manyarcs, canvas, 620, 330) {
DEF_SIMPLE_GM(tinyanglearcs, canvas, 620, 330) {
SkPaint paint;
paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
canvas->translate(50, 50);
diff --git a/chromium/third_party/skia/gm/asyncrescaleandread.cpp b/chromium/third_party/skia/gm/asyncrescaleandread.cpp
index 0e808140192..f119144b192 100644
--- a/chromium/third_party/skia/gm/asyncrescaleandread.cpp
+++ b/chromium/third_party/skia/gm/asyncrescaleandread.cpp
@@ -43,6 +43,9 @@ static sk_sp<SkImage> do_read_and_scale(SkSurface* surface, const SkIRect& srcRe
SkFilterQuality quality) {
auto* context = new AsyncContext();
surface->asyncRescaleAndReadPixels(ii, srcRect, rescaleGamma, quality, async_callback, context);
+ if (auto ctx = surface->getContext()) {
+ ctx->submit();
+ }
while (!context->fCalled) {
// Only GPU should actually be asynchronous.
SkASSERT(surface->getCanvas()->getGrContext());
@@ -69,6 +72,9 @@ static sk_sp<SkImage> do_read_and_scale_yuv(SkSurface* surface, SkYUVColorSpace
AsyncContext context;
surface->asyncRescaleAndReadPixelsYUV420(yuvCS, SkColorSpace::MakeSRGB(), srcRect, size,
rescaleGamma, quality, async_callback, &context);
+ if (auto ctx = surface->getContext()) {
+ ctx->submit();
+ }
while (!context.fCalled) {
// Only GPU should actually be asynchronous.
SkASSERT(surface->getCanvas()->getGrContext());
@@ -99,6 +105,7 @@ static sk_sp<SkImage> do_read_and_scale_yuv(SkSurface* surface, SkYUVColorSpace
GrFlushInfo flushInfo;
flushInfo.fFlags = kSyncCpu_GrFlushFlag;
gr->flush(flushInfo);
+ gr->submit(true);
gr->deleteBackendTexture(backendTextures[0]);
gr->deleteBackendTexture(backendTextures[1]);
gr->deleteBackendTexture(backendTextures[2]);
diff --git a/chromium/third_party/skia/gm/atlastext.cpp b/chromium/third_party/skia/gm/atlastext.cpp
deleted file mode 100644
index 626b46bdf24..00000000000
--- a/chromium/third_party/skia/gm/atlastext.cpp
+++ /dev/null
@@ -1,199 +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/core/SkTypes.h"
-
-#if SK_SUPPORT_ATLAS_TEXT
-
-#include "gm/gm.h"
-#include "include/atlastext/SkAtlasTextContext.h"
-#include "include/atlastext/SkAtlasTextFont.h"
-#include "include/atlastext/SkAtlasTextRenderer.h"
-#include "include/atlastext/SkAtlasTextTarget.h"
-#include "include/core/SkBitmap.h"
-#include "include/core/SkBlendMode.h"
-#include "include/core/SkCanvas.h"
-#include "include/core/SkFont.h"
-#include "include/core/SkFontStyle.h"
-#include "include/core/SkFontTypes.h"
-#include "include/core/SkMatrix.h"
-#include "include/core/SkPaint.h"
-#include "include/core/SkPoint.h"
-#include "include/core/SkRefCnt.h"
-#include "include/core/SkScalar.h"
-#include "include/core/SkSize.h"
-#include "include/core/SkString.h"
-#include "include/core/SkTypeface.h"
-#include "include/utils/SkRandom.h"
-#include "src/utils/SkUTF.h"
-#include "tools/ToolUtils.h"
-#include "tools/gpu/atlastext/GLTestAtlasTextRenderer.h"
-#include "tools/gpu/atlastext/TestAtlasTextRenderer.h"
-
-#include <memory>
-#include <utility>
-
-class GrContext;
-class GrRenderTargetContext;
-
-// GM that draws text using the Atlas Text interface offscreen and then blits that to the canvas.
-
-static SkScalar draw_string(SkAtlasTextTarget* target, const SkString& text, SkScalar x, SkScalar y,
- uint32_t color, sk_sp<SkTypeface> typeface, float size) {
- if (!text.size()) {
- return x;
- }
- auto atlas_font = SkAtlasTextFont::Make(typeface, size);
- int cnt = SkUTF::CountUTF8(text.c_str(), text.size());
- std::unique_ptr<SkGlyphID[]> glyphs(new SkGlyphID[cnt]);
-
- // Using a paint to get the positions for each glyph.
- SkFont font;
- font.setSize(size);
- font.setTypeface(std::move(typeface));
-
- font.textToGlyphs(text.c_str(), text.size(), SkTextEncoding::kUTF8, glyphs.get(), cnt);
-
- std::unique_ptr<SkScalar[]> widths(new SkScalar[cnt]);
- font.getWidths(glyphs.get(), cnt, widths.get());
-
- std::unique_ptr<SkPoint[]> positions(new SkPoint[cnt]);
- positions[0] = {x, y};
- for (int i = 1; i < cnt; ++i) {
- positions[i] = {positions[i - 1].fX + widths[i - 1], y};
- }
-
- target->drawText(glyphs.get(), positions.get(), cnt, color, *atlas_font);
-
- // Return the width of the of draw.
- return positions[cnt - 1].fX + widths[cnt - 1] - positions[0].fX;
-}
-
-class AtlasTextGM : public skiagm::GpuGM {
-public:
- AtlasTextGM() = default;
-
-protected:
- SkString onShortName() override { return SkString("atlastext"); }
-
- SkISize onISize() override { return SkISize::Make(kSize, kSize); }
-
- void onOnceBeforeDraw() override {
- fRenderer = sk_gpu_test::MakeGLTestAtlasTextRenderer();
- if (!fRenderer) {
- return;
- }
- fContext = SkAtlasTextContext::Make(fRenderer);
- auto targetHandle = fRenderer->makeTargetHandle(kSize, kSize);
- if (!targetHandle) {
- return;
- }
-
- fTarget = SkAtlasTextTarget::Make(fContext, kSize, kSize, targetHandle);
-
- fTypefaces[0] = ToolUtils::create_portable_typeface("serif", SkFontStyle::Italic());
- fTypefaces[1] = ToolUtils::create_portable_typeface("sans-serif", SkFontStyle::Italic());
- fTypefaces[2] = ToolUtils::create_portable_typeface("serif", SkFontStyle::Normal());
- fTypefaces[3] = ToolUtils::create_portable_typeface("sans-serif", SkFontStyle::Normal());
- fTypefaces[4] = ToolUtils::create_portable_typeface("serif", SkFontStyle::Bold());
- fTypefaces[5] = ToolUtils::create_portable_typeface("sans-serif", SkFontStyle::Bold());
- }
-
- DrawResult onDraw(GrContext*,
- GrRenderTargetContext*,
- SkCanvas* canvas,
- SkString* errorMsg) override {
- if (!fRenderer) {
- *errorMsg = "No renderer... probably not supported.";
- return DrawResult::kSkip;
- }
- if (!fTarget || !fTarget->handle()) {
- *errorMsg = "No target... we can't continue.";
- return DrawResult::kFail;
- }
- fRenderer->clearTarget(fTarget->handle(), 0xFF808080);
- auto bmp = this->drawText();
- SkPaint paint;
- paint.setBlendMode(SkBlendMode::kSrc);
- canvas->drawBitmap(bmp, 0, 0);
- return DrawResult::kOk;
- }
-
-private:
- SkBitmap drawText() {
- static const int kSizes[] = {8, 13, 18, 23, 30};
-
- static const SkString kTexts[] = {SkString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
- SkString("abcdefghijklmnopqrstuvwxyz"),
- SkString("0123456789"),
- SkString("!@#$%^&*()<>[]{}")};
- SkScalar x = 0;
- SkScalar y = 10;
-
- SkRandom random;
- do {
- for (auto s : kSizes) {
- auto size = 2 * s;
- for (const auto& typeface : fTypefaces) {
- for (const auto& text : kTexts) {
- // Choose a random color but don't let alpha be too small to see.
- uint32_t color = random.nextU() | 0x40000000;
- fTarget->save();
- // Randomly add a little bit of perspective
- if (random.nextBool()) {
- SkMatrix persp;
- persp.reset();
- persp.setPerspY(0.0005f);
- persp.preTranslate(-x, -y + s);
- persp.postTranslate(x, y - s);
- fTarget->concat(persp);
- }
- // Randomly switch between positioning with a matrix vs x, y passed to draw.
- SkScalar drawX = x, drawY = y;
- if (random.nextBool()) {
- fTarget->translate(x, y);
- drawX = drawY = 0;
- }
- x += size +
- draw_string(fTarget.get(), text, drawX, drawY, color, typeface, size);
- x = SkScalarCeilToScalar(x);
- fTarget->restore();
- // Flush periodically to test continued drawing after a flush.
- if ((random.nextU() % 8) == 0) {
- fTarget->flush();
- }
- if (x + 100 > kSize) {
- x = 0;
- y += SkScalarCeilToScalar(size + 3);
- if (y > kSize) {
- fTarget->flush();
- return fRenderer->readTargetHandle(fTarget->handle());
- }
- }
- }
- }
- }
- } while (true);
- }
-
- static constexpr int kSize = 1280;
-
- sk_sp<SkTypeface> fTypefaces[6];
- sk_sp<sk_gpu_test::TestAtlasTextRenderer> fRenderer;
- std::unique_ptr<SkAtlasTextTarget> fTarget;
- sk_sp<SkAtlasTextContext> fContext;
-
- typedef GM INHERITED;
-};
-
-constexpr int AtlasTextGM::kSize;
-
-//////////////////////////////////////////////////////////////////////////////
-
-DEF_GM(return new AtlasTextGM;)
-
-#endif
diff --git a/chromium/third_party/skia/gm/backdrop_imagefilter_croprect.cpp b/chromium/third_party/skia/gm/backdrop_imagefilter_croprect.cpp
index a3f442b5876..d8611f95c90 100644
--- a/chromium/third_party/skia/gm/backdrop_imagefilter_croprect.cpp
+++ b/chromium/third_party/skia/gm/backdrop_imagefilter_croprect.cpp
@@ -54,8 +54,8 @@ static void draw_backdrop_filter_gm(SkCanvas* canvas, float outsetX, float outse
if (i == 1) {
// Backdrop mode, so save a layer using the image filter as the backdrop to filter
// content on initialization.
- canvas->saveLayer({nullptr, nullptr, imageFilter.get(), nullptr, nullptr,
- SkCanvas::kInitWithPrevious_SaveLayerFlag});
+ canvas->saveLayer(SkCanvas::SaveLayerRec(nullptr, nullptr, imageFilter.get(),
+ SkCanvas::kInitWithPrevious_SaveLayerFlag));
}
// Restore the saved layer (either a main layer that was just drawn into and needs to be
diff --git a/chromium/third_party/skia/gm/beziereffects.cpp b/chromium/third_party/skia/gm/beziereffects.cpp
index e61e0f39c59..327f8067cd4 100644
--- a/chromium/third_party/skia/gm/beziereffects.cpp
+++ b/chromium/third_party/skia/gm/beziereffects.cpp
@@ -78,11 +78,10 @@ public:
}
protected:
- BezierTestOp(GrClipEdgeType et, const SkRect& rect, const SkPMColor4f& color, int32_t classID)
+ BezierTestOp(const SkRect& rect, const SkPMColor4f& color, int32_t classID)
: INHERITED(classID)
, fRect(rect)
, fColor(color)
- , fEdgeType(et)
, fProcessorSet(SkBlendMode::kSrc) {
this->setBounds(rect, HasAABloat::kYes, IsHairline::kNo);
}
@@ -125,8 +124,6 @@ protected:
flushState->drawMesh(*fMesh);
}
- GrClipEdgeType edgeType() const { return fEdgeType; }
-
const SkRect& rect() const { return fRect; }
const SkPMColor4f& color() const { return fColor; }
@@ -136,7 +133,6 @@ protected:
private:
SkRect fRect;
SkPMColor4f fColor;
- GrClipEdgeType fEdgeType;
GrProcessorSet fProcessorSet;
GrProgramInfo* fProgramInfo = nullptr;
@@ -153,21 +149,20 @@ public:
const char* name() const final { return "BezierConicTestOp"; }
static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
- GrClipEdgeType et,
const SkRect& rect,
const SkPMColor4f& color,
const SkMatrix& klm) {
GrOpMemoryPool* pool = context->priv().opMemoryPool();
- return pool->allocate<BezierConicTestOp>(et, rect, color, klm);
+ return pool->allocate<BezierConicTestOp>(rect, color, klm);
}
private:
friend class ::GrOpMemoryPool; // for ctor
- BezierConicTestOp(GrClipEdgeType et, const SkRect& rect,
- const SkPMColor4f& color, const SkMatrix& klm)
- : INHERITED(et, rect, color, ClassID()), fKLM(klm) {}
+ BezierConicTestOp(const SkRect& rect, const SkPMColor4f& color, const SkMatrix& klm)
+ : INHERITED(rect, color, ClassID())
+ , fKLM(klm) {}
struct Vertex {
SkPoint fPosition;
@@ -175,8 +170,8 @@ private:
};
GrGeometryProcessor* makeGP(const GrCaps& caps, SkArenaAlloc* arena) final {
- auto tmp = GrConicEffect::Make(arena, this->color(), SkMatrix::I(), this->edgeType(),
- caps, SkMatrix::I(), false);
+ auto tmp = GrConicEffect::Make(arena, this->color(), SkMatrix::I(), caps, SkMatrix::I(),
+ false);
if (!tmp) {
return nullptr;
}
@@ -228,7 +223,7 @@ protected:
}
SkISize onISize() override {
- return SkISize::Make(kGrClipEdgeTypeCnt*kCellWidth, kNumConics*kCellHeight);
+ return SkISize::Make(kCellWidth, kNumConics*kCellHeight);
}
void onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
@@ -270,43 +265,39 @@ protected:
for (int row = 0; row < kNumConics; ++row) {
- for(int col = 0; col < kGrClipEdgeTypeCnt; ++col) {
- GrClipEdgeType et = (GrClipEdgeType) col;
+ SkScalar x = 0;
+ SkScalar y = row * h;
+ SkPoint controlPts[] = {
+ {x + baseControlPts[row][0].fX, y + baseControlPts[row][0].fY},
+ {x + baseControlPts[row][1].fX, y + baseControlPts[row][1].fY},
+ {x + baseControlPts[row][2].fX, y + baseControlPts[row][2].fY}
+ };
+
+ for (int i = 0; i < 3; ++i) {
+ canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
+ }
- SkScalar x = col * w;
- SkScalar y = row * h;
- SkPoint controlPts[] = {
- {x + baseControlPts[row][0].fX, y + baseControlPts[row][0].fY},
- {x + baseControlPts[row][1].fX, y + baseControlPts[row][1].fY},
- {x + baseControlPts[row][2].fX, y + baseControlPts[row][2].fY}
- };
+ canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
+ SkConic dst[4];
+ SkMatrix klm;
+ int cnt = ChopConic(controlPts, dst, weights[row]);
+ GrPathUtils::getConicKLM(controlPts, weights[row], &klm);
+
+ for (int c = 0; c < cnt; ++c) {
+ SkPoint* pts = dst[c].fPts;
for (int i = 0; i < 3; ++i) {
- canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
+ canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
}
- canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
-
- SkConic dst[4];
- SkMatrix klm;
- int cnt = ChopConic(controlPts, dst, weights[row]);
- GrPathUtils::getConicKLM(controlPts, weights[row], &klm);
+ SkRect bounds;
+ bounds.setBounds(pts, 3);
- for (int c = 0; c < cnt; ++c) {
- SkPoint* pts = dst[c].fPts;
- for (int i = 0; i < 3; ++i) {
- canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
- }
+ canvas->drawRect(bounds, boundsPaint);
- SkRect bounds;
- bounds.setBounds(pts, 3);
-
- canvas->drawRect(bounds, boundsPaint);
-
- std::unique_ptr<GrDrawOp> op = BezierConicTestOp::Make(context, et, bounds,
- kOpaqueBlack, klm);
- renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
- }
+ std::unique_ptr<GrDrawOp> op = BezierConicTestOp::Make(context, bounds,
+ kOpaqueBlack, klm);
+ renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
}
}
}
@@ -363,21 +354,21 @@ public:
const char* name() const override { return "BezierQuadTestOp"; }
static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
- GrClipEdgeType et,
const SkRect& rect,
const SkPMColor4f& color,
const GrPathUtils::QuadUVMatrix& devToUV) {
GrOpMemoryPool* pool = context->priv().opMemoryPool();
- return pool->allocate<BezierQuadTestOp>(et, rect, color, devToUV);
+ return pool->allocate<BezierQuadTestOp>(rect, color, devToUV);
}
private:
friend class ::GrOpMemoryPool; // for ctor
- BezierQuadTestOp(GrClipEdgeType et, const SkRect& rect,
- const SkPMColor4f& color, const GrPathUtils::QuadUVMatrix& devToUV)
- : INHERITED(et, rect, color, ClassID()), fDevToUV(devToUV) {}
+ BezierQuadTestOp(const SkRect& rect, const SkPMColor4f& color,
+ const GrPathUtils::QuadUVMatrix& devToUV)
+ : INHERITED(rect, color, ClassID())
+ , fDevToUV(devToUV) {}
struct Vertex {
SkPoint fPosition;
@@ -385,8 +376,8 @@ private:
};
GrGeometryProcessor* makeGP(const GrCaps& caps, SkArenaAlloc* arena) final {
- auto tmp = GrQuadEffect::Make(arena, this->color(), SkMatrix::I(), this->edgeType(),
- caps, SkMatrix::I(), false);
+ auto tmp = GrQuadEffect::Make(arena, this->color(), SkMatrix::I(), caps, SkMatrix::I(),
+ false);
if (!tmp) {
return nullptr;
}
@@ -434,7 +425,7 @@ protected:
}
SkISize onISize() override {
- return SkISize::Make(kGrClipEdgeTypeCnt*kCellWidth, kNumQuads*kCellHeight);
+ return SkISize::Make(kCellWidth, kNumQuads*kCellHeight);
}
void onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
@@ -468,44 +459,40 @@ protected:
boundsPaint.setStyle(SkPaint::kStroke_Style);
for (int row = 0; row < kNumQuads; ++row) {
- for(int col = 0; col < kGrClipEdgeTypeCnt; ++col) {
- GrClipEdgeType et = (GrClipEdgeType) col;
-
- SkScalar x = col * w;
- SkScalar y = row * h;
- SkPoint controlPts[] = {
- {x + baseControlPts[row][0].fX, y + baseControlPts[row][0].fY},
- {x + baseControlPts[row][1].fX, y + baseControlPts[row][1].fY},
- {x + baseControlPts[row][2].fX, y + baseControlPts[row][2].fY}
- };
-
- for (int i = 0; i < 3; ++i) {
- canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
- }
+ SkScalar x = 0;
+ SkScalar y = row * h;
+ SkPoint controlPts[] = {
+ {x + baseControlPts[row][0].fX, y + baseControlPts[row][0].fY},
+ {x + baseControlPts[row][1].fX, y + baseControlPts[row][1].fY},
+ {x + baseControlPts[row][2].fX, y + baseControlPts[row][2].fY}
+ };
+
+ for (int i = 0; i < 3; ++i) {
+ canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
+ }
- canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
+ canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
- SkPoint chopped[5];
- int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
+ SkPoint chopped[5];
+ int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
- for (int c = 0; c < cnt; ++c) {
- SkPoint* pts = chopped + 2 * c;
+ for (int c = 0; c < cnt; ++c) {
+ SkPoint* pts = chopped + 2 * c;
- for (int i = 0; i < 3; ++i) {
- canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
- }
+ for (int i = 0; i < 3; ++i) {
+ canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
+ }
- SkRect bounds;
- bounds.setBounds(pts, 3);
+ SkRect bounds;
+ bounds.setBounds(pts, 3);
- canvas->drawRect(bounds, boundsPaint);
+ canvas->drawRect(bounds, boundsPaint);
- GrPathUtils::QuadUVMatrix DevToUV(pts);
+ GrPathUtils::QuadUVMatrix DevToUV(pts);
- std::unique_ptr<GrDrawOp> op = BezierQuadTestOp::Make(context, et, bounds,
- kOpaqueBlack, DevToUV);
- renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
- }
+ std::unique_ptr<GrDrawOp> op = BezierQuadTestOp::Make(context, bounds,
+ kOpaqueBlack, DevToUV);
+ renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
}
}
}
diff --git a/chromium/third_party/skia/gm/bigrrectaaeffect.cpp b/chromium/third_party/skia/gm/bigrrectaaeffect.cpp
index 93c13c4fcbe..090d9504f82 100644
--- a/chromium/third_party/skia/gm/bigrrectaaeffect.cpp
+++ b/chromium/third_party/skia/gm/bigrrectaaeffect.cpp
@@ -91,9 +91,11 @@ protected:
SkRRect rrect = fRRect;
rrect.offset(SkIntToScalar(x + kGap), SkIntToScalar(y + kGap));
const auto& caps = *renderTargetContext->caps()->shaderCaps();
- auto fp = GrRRectEffect::Make(edgeType, rrect, caps);
- SkASSERT(fp);
- if (fp) {
+ auto [success, fp] = GrRRectEffect::Make(/*inputFP=*/nullptr, edgeType, rrect,
+ caps);
+ SkASSERT(success);
+ if (success) {
+ SkASSERT(fp);
GrPaint grPaint;
grPaint.setColor4f({ 0, 0, 0, 1.f });
grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
diff --git a/chromium/third_party/skia/gm/bleed.cpp b/chromium/third_party/skia/gm/bleed.cpp
index f024bbe44b7..4eeae738da7 100644
--- a/chromium/third_party/skia/gm/bleed.cpp
+++ b/chromium/third_party/skia/gm/bleed.cpp
@@ -26,267 +26,164 @@
#include "include/core/SkSurface.h"
#include "include/core/SkTileMode.h"
#include "include/core/SkTypes.h"
-#include "include/effects/SkGradientShader.h"
#include "include/gpu/GrContextOptions.h"
#include "include/private/SkTDArray.h"
#include "src/core/SkBlurMask.h"
#include "tools/ToolUtils.h"
-/** Holds either a bitmap or image to be rendered and a rect that indicates what part of the bitmap
- or image should be tested by the GM. The area outside of the rect is present to check
- for bleed due to filtering/blurring. */
-struct TestPixels {
- enum Type {
- kBitmap,
- kImage
- };
- Type fType;
- SkBitmap fBitmap;
- sk_sp<SkImage> fImage;
- SkIRect fRect; // The region of the bitmap/image that should be rendered.
-};
+/** Creates an image with two one-pixel wide borders around a checkerboard. The checkerboard is 2x2
+ checks where each check has as many pixels as is necessary to fill the interior. It returns
+ the image and a src rect that bounds the checkerboard portion. */
+std::tuple<sk_sp<SkImage>, SkIRect> make_ringed_image(int width, int height) {
+
+ // These are kRGBA_8888_SkColorType values.
+ static constexpr uint32_t kOuterRingColor = 0xFFFF0000,
+ kInnerRingColor = 0xFF0000FF,
+ kCheckColor1 = 0xFF000000,
+ kCheckColor2 = 0xFFFFFFFF;
-/** Creates a bitmap with two one-pixel rings around a checkerboard. The checkerboard is 2x2
- logically where each check has as many pixels as is necessary to fill the interior. The rect
- to draw is set to the checkerboard portion. */
-template<typename PIXEL_TYPE>
-bool make_ringed_bitmap(TestPixels* result, int width, int height,
- SkColorType ct, SkAlphaType at,
- PIXEL_TYPE outerRingColor, PIXEL_TYPE innerRingColor,
- PIXEL_TYPE checkColor1, PIXEL_TYPE checkColor2) {
SkASSERT(0 == width % 2 && 0 == height % 2);
SkASSERT(width >= 6 && height >= 6);
- result->fType = TestPixels::kBitmap;
- SkImageInfo info = SkImageInfo::Make(width, height, ct, at);
+ SkImageInfo info = SkImageInfo::Make(width, height, kRGBA_8888_SkColorType,
+ kPremul_SkAlphaType);
size_t rowBytes = SkAlign4(info.minRowBytes());
- result->fBitmap.allocPixels(info, rowBytes);
+ SkBitmap bitmap;
+ bitmap.allocPixels(info, rowBytes);
- PIXEL_TYPE* scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, 0);
+ uint32_t* scanline = bitmap.getAddr32(0, 0);
for (int x = 0; x < width; ++x) {
- scanline[x] = outerRingColor;
+ scanline[x] = kOuterRingColor;
}
- scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, 1);
- scanline[0] = outerRingColor;
+ scanline = bitmap.getAddr32(0, 1);
+ scanline[0] = kOuterRingColor;
for (int x = 1; x < width - 1; ++x) {
- scanline[x] = innerRingColor;
+ scanline[x] = kInnerRingColor;
}
- scanline[width - 1] = outerRingColor;
+ scanline[width - 1] = kOuterRingColor;
for (int y = 2; y < height / 2; ++y) {
- scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, y);
- scanline[0] = outerRingColor;
- scanline[1] = innerRingColor;
+ scanline = bitmap.getAddr32(0, y);
+ scanline[0] = kOuterRingColor;
+ scanline[1] = kInnerRingColor;
for (int x = 2; x < width / 2; ++x) {
- scanline[x] = checkColor1;
+ scanline[x] = kCheckColor1;
}
for (int x = width / 2; x < width - 2; ++x) {
- scanline[x] = checkColor2;
+ scanline[x] = kCheckColor2;
}
- scanline[width - 2] = innerRingColor;
- scanline[width - 1] = outerRingColor;
+ scanline[width - 2] = kInnerRingColor;
+ scanline[width - 1] = kOuterRingColor;
}
for (int y = height / 2; y < height - 2; ++y) {
- scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, y);
- scanline[0] = outerRingColor;
- scanline[1] = innerRingColor;
+ scanline = bitmap.getAddr32(0, y);
+ scanline[0] = kOuterRingColor;
+ scanline[1] = kInnerRingColor;
for (int x = 2; x < width / 2; ++x) {
- scanline[x] = checkColor2;
+ scanline[x] = kCheckColor2;
}
for (int x = width / 2; x < width - 2; ++x) {
- scanline[x] = checkColor1;
+ scanline[x] = kCheckColor1;
}
- scanline[width - 2] = innerRingColor;
- scanline[width - 1] = outerRingColor;
+ scanline[width - 2] = kInnerRingColor;
+ scanline[width - 1] = kOuterRingColor;
}
- scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, height - 2);
- scanline[0] = outerRingColor;
+ scanline = bitmap.getAddr32(0, height - 2);
+ scanline[0] = kOuterRingColor;
for (int x = 1; x < width - 1; ++x) {
- scanline[x] = innerRingColor;
+ scanline[x] = kInnerRingColor;
}
- scanline[width - 1] = outerRingColor;
+ scanline[width - 1] = kOuterRingColor;
- scanline = (PIXEL_TYPE*)result->fBitmap.getAddr(0, height - 1);
+ scanline = bitmap.getAddr32(0, height - 1);
for (int x = 0; x < width; ++x) {
- scanline[x] = outerRingColor;
+ scanline[x] = kOuterRingColor;
}
- result->fBitmap.setImmutable();
- result->fRect.setLTRB(2, 2, width - 2, height - 2);
- return true;
-}
-
-/** Create a black and white checked bitmap with 2 1-pixel rings around the outside edge.
- The inner ring is red and the outer ring is blue. */
-static bool make_ringed_color_bitmap(TestPixels* result, int width, int height) {
- const SkPMColor kBlue = SkPreMultiplyColor(SK_ColorBLUE);
- const SkPMColor kRed = SkPreMultiplyColor(SK_ColorRED);
- const SkPMColor kBlack = SkPreMultiplyColor(SK_ColorBLACK);
- const SkPMColor kWhite = SkPreMultiplyColor(SK_ColorWHITE);
- return make_ringed_bitmap<SkPMColor>(result, width, height, kN32_SkColorType,
- kPremul_SkAlphaType, kBlue, kRed, kBlack, kWhite);
-}
-
-/** Makes a alpha bitmap with 1 wide rect/ring of 0s, an inset of 1s, and the interior is a 2x2
- checker board of 3/4 and 1/2. The inner checkers are large enough to fill the interior with
- the 2x2 checker grid. */
-static bool make_ringed_alpha_bitmap(TestPixels* result, int width, int height) {
- constexpr uint8_t kZero = 0x00;
- constexpr uint8_t kHalf = 0x80;
- constexpr uint8_t k3Q = 0xC0;
- constexpr uint8_t kOne = 0xFF;
- return make_ringed_bitmap<uint8_t>(result, width, height, kAlpha_8_SkColorType,
- kPremul_SkAlphaType, kZero, kOne, k3Q, kHalf);
-}
-
-/** Helper to reuse above functions to produce images rather than bmps */
-static void bmp_to_image(TestPixels* result) {
- SkASSERT(TestPixels::kBitmap == result->fType);
- result->fImage = SkImage::MakeFromBitmap(result->fBitmap);
- SkASSERT(result->fImage);
- result->fType = TestPixels::kImage;
- result->fBitmap.reset();
-}
-
-/** Color image case. */
-bool make_ringed_color_image(TestPixels* result, int width, int height) {
- if (make_ringed_color_bitmap(result, width, height)) {
- bmp_to_image(result);
- return true;
- }
- return false;
-}
-
-/** Alpha image case. */
-bool make_ringed_alpha_image(TestPixels* result, int width, int height) {
- if (make_ringed_alpha_bitmap(result, width, height)) {
- bmp_to_image(result);
- return true;
- }
- return false;
-}
-
-static sk_sp<SkShader> make_shader() {
- constexpr SkPoint pts[] = { {0, 0}, {20, 20} };
- constexpr SkColor colors[] = { SK_ColorGREEN, SK_ColorYELLOW };
- return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kMirror);
+ bitmap.setImmutable();
+ return {SkImage::MakeFromBitmap(bitmap), {2, 2, width - 2, height - 2}};
}
-static sk_sp<SkShader> make_null_shader() { return nullptr; }
-
-enum BleedTest {
- kUseBitmap_BleedTest,
- kUseImage_BleedTest,
- kUseAlphaBitmap_BleedTest,
- kUseAlphaImage_BleedTest,
- kUseAlphaBitmapShader_BleedTest,
- kUseAlphaImageShader_BleedTest,
-};
-
-const struct {
- const char* fName;
- bool (*fPixelMaker)(TestPixels* result, int width, int height);
- sk_sp<SkShader> (*fShaderMaker)();
-} gBleedRec[] = {
- { "bleed", make_ringed_color_bitmap, make_null_shader },
- { "bleed_image", make_ringed_color_image, make_null_shader },
- { "bleed_alpha_bmp", make_ringed_alpha_bitmap, make_null_shader },
- { "bleed_alpha_image", make_ringed_alpha_image, make_null_shader },
- { "bleed_alpha_bmp_shader", make_ringed_alpha_bitmap, make_shader },
- { "bleed_alpha_image_shader", make_ringed_alpha_image, make_shader },
-};
-
-/** This GM exercises the behavior of the drawBitmapRect & drawImageRect calls. Specifically their
- handling of :
- - SrcRectConstraint(bleed vs.no - bleed)
- - handling of the sub - region feature(area - of - interest) of drawBitmap*
- - handling of 8888 vs. A8 (including presence of a shader in the A8 case).
- In particular, we should never see the padding outside of an SkBitmap's sub - region (green for
- 8888, 1/4 for alpha). In some instances we can see the two outer rings outside of the area o
- interest (i.e., the inner four checks) due to AA or filtering if allowed by the
- SrcRectConstraint.
-*/
-class BleedGM : public skiagm::GM {
+/**
+ * These GMs exercise the behavior of the drawImageRect and its SrcRectConstraint parameter. They
+ * tests various matrices, filter qualities, and interaction with mask filters. They also exercise
+ * the tiling image draws of SkGpuDevice by overriding the maximum texture size of the GrContext.
+ */
+class SrcRectConstraintGM : public skiagm::GM {
public:
- BleedGM(BleedTest bt) : fBT(bt){}
+ SrcRectConstraintGM(const char* shortName, SkCanvas::SrcRectConstraint constraint, bool batch)
+ : fShortName(shortName)
+ , fConstraint(constraint)
+ , fBatch(batch) {}
protected:
-
- SkString onShortName() override {
- return SkString(gBleedRec[fBT].fName);
- }
-
- SkISize onISize() override {
- return SkISize::Make(1200, 1080);
- }
-
- void drawPixels(SkCanvas* canvas, const TestPixels& pixels, const SkRect& src,
- const SkRect& dst, const SkPaint* paint,
- SkCanvas::SrcRectConstraint constraint) {
- if (TestPixels::kBitmap == pixels.fType) {
- canvas->drawBitmapRect(pixels.fBitmap, src, dst, paint, constraint);
+ SkString onShortName() override { return fShortName; }
+ SkISize onISize() override { return SkISize::Make(800, 1000); }
+
+ void drawImage(SkCanvas* canvas, sk_sp<SkImage> image,
+ SkIRect srcRect, SkRect dstRect, SkPaint* paint) {
+ if (fBatch) {
+ SkCanvas::ImageSetEntry imageSetEntry[1];
+ imageSetEntry[0].fImage = image;
+ imageSetEntry[0].fSrcRect = SkRect::Make(srcRect);
+ imageSetEntry[0].fDstRect = dstRect;
+ imageSetEntry[0].fAAFlags = paint->isAntiAlias() ? SkCanvas::kAll_QuadAAFlags
+ : SkCanvas::kNone_QuadAAFlags;
+ canvas->experimental_DrawEdgeAAImageSet(imageSetEntry, SK_ARRAY_COUNT(imageSetEntry),
+ /*dstClips=*/nullptr,
+ /*preViewMatrices=*/nullptr,
+ paint, fConstraint);
} else {
- canvas->drawImageRect(pixels.fImage.get(), src, dst, paint, constraint);
+ canvas->drawImageRect(image.get(), srcRect, dstRect, paint, fConstraint);
}
}
// Draw the area of interest of the small image
- void drawCase1(SkCanvas* canvas, int transX, int transY, bool aa,
- SkCanvas::SrcRectConstraint constraint, SkFilterQuality filter) {
-
- SkRect src = SkRect::Make(fSmallTestPixels.fRect);
+ void drawCase1(SkCanvas* canvas, int transX, int transY, bool aa, SkFilterQuality filter) {
SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY),
SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
SkPaint paint;
paint.setFilterQuality(filter);
- paint.setShader(fShader);
paint.setColor(SK_ColorBLUE);
paint.setAntiAlias(aa);
- this->drawPixels(canvas, fSmallTestPixels, src, dst, &paint, constraint);
+ drawImage(canvas, fSmallImage, fSmallSrcRect, dst, &paint);
}
// Draw the area of interest of the large image
- void drawCase2(SkCanvas* canvas, int transX, int transY, bool aa,
- SkCanvas::SrcRectConstraint constraint, SkFilterQuality filter) {
- SkRect src = SkRect::Make(fBigTestPixels.fRect);
+ void drawCase2(SkCanvas* canvas, int transX, int transY, bool aa, SkFilterQuality filter) {
SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY),
SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
SkPaint paint;
paint.setFilterQuality(filter);
- paint.setShader(fShader);
paint.setColor(SK_ColorBLUE);
paint.setAntiAlias(aa);
- this->drawPixels(canvas, fBigTestPixels, src, dst, &paint, constraint);
+ drawImage(canvas, fBigImage, fBigSrcRect, dst, &paint);
}
// Draw upper-left 1/4 of the area of interest of the large image
- void drawCase3(SkCanvas* canvas, int transX, int transY, bool aa,
- SkCanvas::SrcRectConstraint constraint, SkFilterQuality filter) {
- SkRect src = SkRect::MakeXYWH(SkIntToScalar(fBigTestPixels.fRect.fLeft),
- SkIntToScalar(fBigTestPixels.fRect.fTop),
- fBigTestPixels.fRect.width()/2.f,
- fBigTestPixels.fRect.height()/2.f);
+ void drawCase3(SkCanvas* canvas, int transX, int transY, bool aa, SkFilterQuality filter) {
+ SkIRect src = SkIRect::MakeXYWH(fBigSrcRect.fLeft,
+ fBigSrcRect.fTop,
+ fBigSrcRect.width()/2,
+ fBigSrcRect.height()/2);
SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY),
SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
SkPaint paint;
paint.setFilterQuality(filter);
- paint.setShader(fShader);
paint.setColor(SK_ColorBLUE);
paint.setAntiAlias(aa);
- this->drawPixels(canvas, fBigTestPixels, src, dst, &paint, constraint);
+ drawImage(canvas, fBigImage, src, dst, &paint);
}
// Draw the area of interest of the small image with a normal blur
- void drawCase4(SkCanvas* canvas, int transX, int transY, bool aa,
- SkCanvas::SrcRectConstraint constraint, SkFilterQuality filter) {
- SkRect src = SkRect::Make(fSmallTestPixels.fRect);
+ void drawCase4(SkCanvas* canvas, int transX, int transY, bool aa, SkFilterQuality filter) {
SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY),
SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
@@ -294,17 +191,14 @@ protected:
paint.setFilterQuality(filter);
paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle,
SkBlurMask::ConvertRadiusToSigma(3)));
- paint.setShader(fShader);
paint.setColor(SK_ColorBLUE);
paint.setAntiAlias(aa);
- this->drawPixels(canvas, fSmallTestPixels, src, dst, &paint, constraint);
+ drawImage(canvas, fSmallImage, fSmallSrcRect, dst, &paint);
}
// Draw the area of interest of the small image with a outer blur
- void drawCase5(SkCanvas* canvas, int transX, int transY, bool aa,
- SkCanvas::SrcRectConstraint constraint, SkFilterQuality filter) {
- SkRect src = SkRect::Make(fSmallTestPixels.fRect);
+ void drawCase5(SkCanvas* canvas, int transX, int transY, bool aa, SkFilterQuality filter) {
SkRect dst = SkRect::MakeXYWH(SkIntToScalar(transX), SkIntToScalar(transY),
SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
@@ -312,26 +206,22 @@ protected:
paint.setFilterQuality(filter);
paint.setMaskFilter(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle,
SkBlurMask::ConvertRadiusToSigma(7)));
- paint.setShader(fShader);
paint.setColor(SK_ColorBLUE);
paint.setAntiAlias(aa);
- this->drawPixels(canvas, fSmallTestPixels, src, dst, &paint, constraint);
+ drawImage(canvas, fSmallImage, fSmallSrcRect, dst, &paint);
}
void onOnceBeforeDraw() override {
- SkAssertResult(gBleedRec[fBT].fPixelMaker(&fSmallTestPixels, kSmallSize, kSmallSize));
- SkAssertResult(gBleedRec[fBT].fPixelMaker(&fBigTestPixels, 2 * kMaxTileSize,
- 2 * kMaxTileSize));
+ std::tie(fBigImage, fBigSrcRect) = make_ringed_image(2*kMaxTileSize, 2*kMaxTileSize);
+ std::tie(fSmallImage, fSmallSrcRect) = make_ringed_image(kSmallSize, kSmallSize);
}
void onDraw(SkCanvas* canvas) override {
- fShader = gBleedRec[fBT].fShaderMaker();
-
canvas->clear(SK_ColorGRAY);
- SkTDArray<SkMatrix> matrices;
+ std::vector<SkMatrix> matrices;
// Draw with identity
- *matrices.append() = SkMatrix::I();
+ matrices.push_back(SkMatrix::I());
// Draw with rotation and scale down in x, up in y.
SkMatrix m;
@@ -339,73 +229,56 @@ protected:
m.setTranslate(0, kBottom);
m.preRotate(15.f, 0, kBottom + kBlockSpacing);
m.preScale(0.71f, 1.22f);
- *matrices.append() = m;
+ matrices.push_back(m);
// Align the next set with the middle of the previous in y, translated to the right in x.
- SkPoint corners[] = {{0, 0}, { 0, kBottom }, { kWidth, kBottom }, {kWidth, 0} };
- matrices[matrices.count()-1].mapPoints(corners, 4);
+ SkPoint corners[] = {{0, 0}, {0, kBottom}, {kWidth, kBottom}, {kWidth, 0}};
+ matrices.back().mapPoints(corners, 4);
SkScalar y = (corners[0].fY + corners[1].fY + corners[2].fY + corners[3].fY) / 4;
- SkScalar x = std::max(std::max(corners[0].fX, corners[1].fX),
- std::max(corners[2].fX, corners[3].fX));
+ SkScalar x = std::max({corners[0].fX, corners[1].fX, corners[2].fX, corners[3].fX});
m.setTranslate(x, y);
m.preScale(0.2f, 0.2f);
- *matrices.append() = m;
+ matrices.push_back(m);
SkScalar maxX = 0;
- for (int antiAlias = 0; antiAlias < 2; ++antiAlias) {
+ for (bool antiAlias : {false, true}) {
canvas->save();
canvas->translate(maxX, 0);
- for (int m = 0; m < matrices.count(); ++m) {
+ for (const SkMatrix& matrix : matrices) {
canvas->save();
- canvas->concat(matrices[m]);
- bool aa = SkToBool(antiAlias);
-
- // First draw a column with no bleeding and no filtering
- this->drawCase1(canvas, kCol0X, kRow0Y, aa, SkCanvas::kStrict_SrcRectConstraint, kNone_SkFilterQuality);
- this->drawCase2(canvas, kCol0X, kRow1Y, aa, SkCanvas::kStrict_SrcRectConstraint, kNone_SkFilterQuality);
- this->drawCase3(canvas, kCol0X, kRow2Y, aa, SkCanvas::kStrict_SrcRectConstraint, kNone_SkFilterQuality);
- this->drawCase4(canvas, kCol0X, kRow3Y, aa, SkCanvas::kStrict_SrcRectConstraint, kNone_SkFilterQuality);
- this->drawCase5(canvas, kCol0X, kRow4Y, aa, SkCanvas::kStrict_SrcRectConstraint, kNone_SkFilterQuality);
-
- // Then draw a column with no bleeding and low filtering
- this->drawCase1(canvas, kCol1X, kRow0Y, aa, SkCanvas::kStrict_SrcRectConstraint, kLow_SkFilterQuality);
- this->drawCase2(canvas, kCol1X, kRow1Y, aa, SkCanvas::kStrict_SrcRectConstraint, kLow_SkFilterQuality);
- this->drawCase3(canvas, kCol1X, kRow2Y, aa, SkCanvas::kStrict_SrcRectConstraint, kLow_SkFilterQuality);
- this->drawCase4(canvas, kCol1X, kRow3Y, aa, SkCanvas::kStrict_SrcRectConstraint, kLow_SkFilterQuality);
- this->drawCase5(canvas, kCol1X, kRow4Y, aa, SkCanvas::kStrict_SrcRectConstraint, kLow_SkFilterQuality);
-
- // Then draw a column with no bleeding and high filtering
- this->drawCase1(canvas, kCol2X, kRow0Y, aa, SkCanvas::kStrict_SrcRectConstraint, kHigh_SkFilterQuality);
- this->drawCase2(canvas, kCol2X, kRow1Y, aa, SkCanvas::kStrict_SrcRectConstraint, kHigh_SkFilterQuality);
- this->drawCase3(canvas, kCol2X, kRow2Y, aa, SkCanvas::kStrict_SrcRectConstraint, kHigh_SkFilterQuality);
- this->drawCase4(canvas, kCol2X, kRow3Y, aa, SkCanvas::kStrict_SrcRectConstraint, kHigh_SkFilterQuality);
- this->drawCase5(canvas, kCol2X, kRow4Y, aa, SkCanvas::kStrict_SrcRectConstraint, kHigh_SkFilterQuality);
-
- // Then draw a column with bleeding and no filtering (bleed should have no effect w/out blur)
- this->drawCase1(canvas, kCol3X, kRow0Y, aa, SkCanvas::kFast_SrcRectConstraint, kNone_SkFilterQuality);
- this->drawCase2(canvas, kCol3X, kRow1Y, aa, SkCanvas::kFast_SrcRectConstraint, kNone_SkFilterQuality);
- this->drawCase3(canvas, kCol3X, kRow2Y, aa, SkCanvas::kFast_SrcRectConstraint, kNone_SkFilterQuality);
- this->drawCase4(canvas, kCol3X, kRow3Y, aa, SkCanvas::kFast_SrcRectConstraint, kNone_SkFilterQuality);
- this->drawCase5(canvas, kCol3X, kRow4Y, aa, SkCanvas::kFast_SrcRectConstraint, kNone_SkFilterQuality);
-
- // Then draw a column with bleeding and low filtering
- this->drawCase1(canvas, kCol4X, kRow0Y, aa, SkCanvas::kFast_SrcRectConstraint, kLow_SkFilterQuality);
- this->drawCase2(canvas, kCol4X, kRow1Y, aa, SkCanvas::kFast_SrcRectConstraint, kLow_SkFilterQuality);
- this->drawCase3(canvas, kCol4X, kRow2Y, aa, SkCanvas::kFast_SrcRectConstraint, kLow_SkFilterQuality);
- this->drawCase4(canvas, kCol4X, kRow3Y, aa, SkCanvas::kFast_SrcRectConstraint, kLow_SkFilterQuality);
- this->drawCase5(canvas, kCol4X, kRow4Y, aa, SkCanvas::kFast_SrcRectConstraint, kLow_SkFilterQuality);
-
- // Finally draw a column with bleeding and high filtering
- this->drawCase1(canvas, kCol5X, kRow0Y, aa, SkCanvas::kFast_SrcRectConstraint, kHigh_SkFilterQuality);
- this->drawCase2(canvas, kCol5X, kRow1Y, aa, SkCanvas::kFast_SrcRectConstraint, kHigh_SkFilterQuality);
- this->drawCase3(canvas, kCol5X, kRow2Y, aa, SkCanvas::kFast_SrcRectConstraint, kHigh_SkFilterQuality);
- this->drawCase4(canvas, kCol5X, kRow3Y, aa, SkCanvas::kFast_SrcRectConstraint, kHigh_SkFilterQuality);
- this->drawCase5(canvas, kCol5X, kRow4Y, aa, SkCanvas::kFast_SrcRectConstraint, kHigh_SkFilterQuality);
-
- SkPoint corners[] = { { 0, 0 },{ 0, kBottom },{ kWidth, kBottom },{ kWidth, 0 } };
- matrices[m].mapPoints(corners, 4);
- SkScalar x = kBlockSize + std::max(std::max(corners[0].fX, corners[1].fX),
- std::max(corners[2].fX, corners[3].fX));
+ canvas->concat(matrix);
+
+ // First draw a column with no filtering
+ this->drawCase1(canvas, kCol0X, kRow0Y, antiAlias, kNone_SkFilterQuality);
+ this->drawCase2(canvas, kCol0X, kRow1Y, antiAlias, kNone_SkFilterQuality);
+ this->drawCase3(canvas, kCol0X, kRow2Y, antiAlias, kNone_SkFilterQuality);
+ this->drawCase4(canvas, kCol0X, kRow3Y, antiAlias, kNone_SkFilterQuality);
+ this->drawCase5(canvas, kCol0X, kRow4Y, antiAlias, kNone_SkFilterQuality);
+
+ // Then draw a column with low filtering
+ this->drawCase1(canvas, kCol1X, kRow0Y, antiAlias, kLow_SkFilterQuality);
+ this->drawCase2(canvas, kCol1X, kRow1Y, antiAlias, kLow_SkFilterQuality);
+ this->drawCase3(canvas, kCol1X, kRow2Y, antiAlias, kLow_SkFilterQuality);
+ this->drawCase4(canvas, kCol1X, kRow3Y, antiAlias, kLow_SkFilterQuality);
+ this->drawCase5(canvas, kCol1X, kRow4Y, antiAlias, kLow_SkFilterQuality);
+
+ // Then draw a column with high filtering. Skip it if in kStrict mode and MIP
+ // mapping will be used. On GPU we allow bleeding at non-base levels because
+ // building a new MIP chain for the subset is expensive.
+ SkScalar scales[2];
+ SkAssertResult(matrix.getMinMaxScales(scales));
+ if (fConstraint != SkCanvas::kStrict_SrcRectConstraint || scales[0] >= 1.f) {
+ this->drawCase1(canvas, kCol2X, kRow0Y, antiAlias, kHigh_SkFilterQuality);
+ this->drawCase2(canvas, kCol2X, kRow1Y, antiAlias, kHigh_SkFilterQuality);
+ this->drawCase3(canvas, kCol2X, kRow2Y, antiAlias, kHigh_SkFilterQuality);
+ this->drawCase4(canvas, kCol2X, kRow3Y, antiAlias, kHigh_SkFilterQuality);
+ this->drawCase5(canvas, kCol2X, kRow4Y, antiAlias, kHigh_SkFilterQuality);
+ }
+
+ SkPoint innerCorners[] = {{0, 0}, {0, kBottom}, {kWidth, kBottom}, {kWidth, 0}};
+ matrix.mapPoints(innerCorners, 4);
+ SkScalar x = kBlockSize + std::max({innerCorners[0].fX, innerCorners[1].fX,
+ innerCorners[2].fX, innerCorners[3].fX});
maxX = std::max(maxX, x);
canvas->restore();
}
@@ -424,10 +297,7 @@ private:
static constexpr int kCol0X = kBlockSpacing;
static constexpr int kCol1X = 2*kBlockSpacing + kBlockSize;
static constexpr int kCol2X = 3*kBlockSpacing + 2*kBlockSize;
- static constexpr int kCol3X = 4*kBlockSpacing + 3*kBlockSize;
- static constexpr int kCol4X = 5*kBlockSpacing + 4*kBlockSize;
- static constexpr int kCol5X = 6*kBlockSpacing + 5*kBlockSize;
- static constexpr int kWidth = 7*kBlockSpacing + 6*kBlockSize;
+ static constexpr int kWidth = 4*kBlockSpacing + 3*kBlockSize;
static constexpr int kRow0Y = kBlockSpacing;
static constexpr int kRow1Y = 2*kBlockSpacing + kBlockSize;
@@ -438,23 +308,25 @@ private:
static constexpr int kSmallSize = 6;
static constexpr int kMaxTileSize = 32;
- TestPixels fBigTestPixels;
- TestPixels fSmallTestPixels;
-
- sk_sp<SkShader> fShader;
-
- const BleedTest fBT;
-
+ SkString fShortName;
+ sk_sp<SkImage> fBigImage;
+ sk_sp<SkImage> fSmallImage;
+ SkIRect fBigSrcRect;
+ SkIRect fSmallSrcRect;
+ SkCanvas::SrcRectConstraint fConstraint;
+ bool fBatch = false;
typedef GM INHERITED;
};
-
-DEF_GM( return new BleedGM(kUseBitmap_BleedTest); )
-DEF_GM( return new BleedGM(kUseImage_BleedTest); )
-DEF_GM( return new BleedGM(kUseAlphaBitmap_BleedTest); )
-DEF_GM( return new BleedGM(kUseAlphaImage_BleedTest); )
-DEF_GM( return new BleedGM(kUseAlphaBitmapShader_BleedTest); )
-DEF_GM( return new BleedGM(kUseAlphaImageShader_BleedTest); )
+DEF_GM(return new SrcRectConstraintGM("strict_constraint_no_red_allowed",
+ SkCanvas::kStrict_SrcRectConstraint,
+ /*batch=*/false););
+DEF_GM(return new SrcRectConstraintGM("strict_constraint_batch_no_red_allowed",
+ SkCanvas::kStrict_SrcRectConstraint,
+ /*batch=*/true););
+DEF_GM(return new SrcRectConstraintGM("fast_constraint_red_is_allowed",
+ SkCanvas::kFast_SrcRectConstraint,
+ /*batch=*/false););
///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/gm/blurroundrect.cpp b/chromium/third_party/skia/gm/blurroundrect.cpp
index 1637f4e20fe..fe608c5b6f6 100644
--- a/chromium/third_party/skia/gm/blurroundrect.cpp
+++ b/chromium/third_party/skia/gm/blurroundrect.cpp
@@ -58,6 +58,8 @@ class SimpleBlurRoundRectGM : public skiagm::GM {
SkISize onISize() override { return {1000, 500}; }
+ bool runAsBench() const override { return true; }
+
void onDraw(SkCanvas* canvas) override {
canvas->scale(1.5f, 1.5f);
canvas->translate(50,50);
diff --git a/chromium/third_party/skia/gm/bug6783.cpp b/chromium/third_party/skia/gm/bug6783.cpp
index 05e4cf19eaf..4f52e0914af 100644
--- a/chromium/third_party/skia/gm/bug6783.cpp
+++ b/chromium/third_party/skia/gm/bug6783.cpp
@@ -44,8 +44,7 @@ DEF_SIMPLE_GM(bug6783, canvas, 500, 500) {
sk_sp<SkImage> img = surface->makeImageSnapshot();
- SkMatrix m = SkMatrix::Concat(SkMatrix::MakeTrans(25, 214),
- SkMatrix::MakeScale(2, 2));
+ SkMatrix m = SkMatrix::Translate(25, 214) * SkMatrix::Scale(2, 2);
m.preSkew(0.5f, 0.5f);
// The bug was present at all filter levels, but you might not notice it at kNone.
diff --git a/chromium/third_party/skia/gm/circles.cpp b/chromium/third_party/skia/gm/circles.cpp
index 52d54d24569..bec7d6b3459 100644
--- a/chromium/third_party/skia/gm/circles.cpp
+++ b/chromium/third_party/skia/gm/circles.cpp
@@ -97,7 +97,7 @@ protected:
// AA with stroke style
SkPaint p;
p.setAntiAlias(true);
- p.setStyle(SkPaint::kStroke_Style);
+ p.setStroke(true);
p.setStrokeWidth(SkIntToScalar(3));
fPaints.push_back(p);
}
@@ -106,7 +106,7 @@ protected:
// AA with stroke style, width = 0
SkPaint p;
p.setAntiAlias(true);
- p.setStyle(SkPaint::kStroke_Style);
+ p.setStroke(true);
fPaints.push_back(p);
}
diff --git a/chromium/third_party/skia/gm/circulararcs.cpp b/chromium/third_party/skia/gm/circulararcs.cpp
index fbe3fe8d408..13dae6d850a 100644
--- a/chromium/third_party/skia/gm/circulararcs.cpp
+++ b/chromium/third_party/skia/gm/circulararcs.cpp
@@ -20,6 +20,13 @@
#include <functional>
+#include "include/effects/SkStrokeAndFillPathEffect.h"
+static void set_strokeandfill(SkPaint* paint) {
+ SkASSERT(paint->getPathEffect() == nullptr);
+ paint->setPathEffect(SkStrokeAndFillPathEffect::Make());
+ paint->setStroke(true);
+}
+
constexpr SkScalar kStarts[] = {0.f, 10.f, 30.f, 45.f, 90.f, 165.f, 180.f, 270.f};
constexpr SkScalar kSweeps[] = {1.f, 45.f, 90.f, 130.f, 180.f, 184.f, 300.f, 355.f};
constexpr SkScalar kDiameter = 40.f;
@@ -77,13 +84,13 @@ void draw_arcs(SkCanvas* canvas, std::function<void(SkPaint*)> configureStyle) {
#define DEF_ARC_GM(name) DEF_SIMPLE_GM(circular_arcs_##name, canvas, kW, kH)
DEF_ARC_GM(fill) {
- auto setFill = [] (SkPaint*p) { p->setStyle(SkPaint::kFill_Style); };
+ auto setFill = [] (SkPaint*p) { p->setStroke(false); };
draw_arcs(canvas, setFill);
}
DEF_ARC_GM(hairline) {
auto setHairline = [] (SkPaint* p) {
- p->setStyle(SkPaint::kStroke_Style);
+ p->setStroke(true);
p->setStrokeWidth(0.f);
};
draw_arcs(canvas, setHairline);
@@ -91,7 +98,7 @@ DEF_ARC_GM(hairline) {
DEF_ARC_GM(stroke_butt) {
auto setStroke = [](SkPaint* p) {
- p->setStyle(SkPaint::kStroke_Style);
+ p->setStroke(true);
p->setStrokeCap(SkPaint::kButt_Cap);
};
draw_arcs(canvas, setStroke);
@@ -99,7 +106,7 @@ DEF_ARC_GM(stroke_butt) {
DEF_ARC_GM(stroke_square) {
auto setStroke = [] (SkPaint* p) {
- p->setStyle(SkPaint::kStroke_Style);
+ p->setStroke(true);
p->setStrokeCap(SkPaint::kSquare_Cap);
};
draw_arcs(canvas, setStroke);
@@ -107,7 +114,7 @@ DEF_ARC_GM(stroke_square) {
DEF_ARC_GM(stroke_round) {
auto setStroke = [] (SkPaint* p) {
- p->setStyle(SkPaint::kStroke_Style);
+ p->setStroke(true);
p->setStrokeCap(SkPaint::kRound_Cap);
};
draw_arcs(canvas, setStroke);
@@ -115,7 +122,7 @@ DEF_ARC_GM(stroke_round) {
DEF_ARC_GM(stroke_and_fill_butt) {
auto setStroke = [] (SkPaint* p) {
- p->setStyle(SkPaint::kStrokeAndFill_Style);
+ set_strokeandfill(p);
p->setStrokeCap(SkPaint::kButt_Cap);
};
draw_arcs(canvas, setStroke);
@@ -123,7 +130,7 @@ DEF_ARC_GM(stroke_and_fill_butt) {
DEF_ARC_GM(stroke_and_fill_square) {
auto setStroke = [] (SkPaint* p) {
- p->setStyle(SkPaint::kStrokeAndFill_Style);
+ set_strokeandfill(p);
p->setStrokeCap(SkPaint::kSquare_Cap);
};
draw_arcs(canvas, setStroke);
@@ -131,7 +138,7 @@ DEF_ARC_GM(stroke_and_fill_square) {
DEF_ARC_GM(stroke_and_fill_round) {
auto setStroke = [] (SkPaint* p) {
- p->setStyle(SkPaint::kStrokeAndFill_Style);
+ set_strokeandfill(p);
p->setStrokeCap(SkPaint::kRound_Cap);
};
draw_arcs(canvas, setStroke);
@@ -174,16 +181,16 @@ DEF_SIMPLE_GM(circular_arcs_weird, canvas, 1000, 400) {
// fill
paints.push_back();
// stroke
- paints.push_back().setStyle(SkPaint::kStroke_Style);
+ paints.push_back().setStroke(true);
paints.back().setStrokeWidth(kS / 6.f);
// hairline
- paints.push_back().setStyle(SkPaint::kStroke_Style);
+ paints.push_back().setStroke(true);
paints.back().setStrokeWidth(0.f);
// stroke and fill
paints.push_back().setStyle(SkPaint::kStrokeAndFill_Style);
paints.back().setStrokeWidth(kS / 6.f);
// dash effect
- paints.push_back().setStyle(SkPaint::kStroke_Style);
+ paints.push_back().setStroke(true);
paints.back().setStrokeWidth(kS / 6.f);
constexpr SkScalar kDashIntervals[] = {kS / 15, 2 * kS / 15};
paints.back().setPathEffect(SkDashPathEffect::Make(kDashIntervals, 2, 0.f));
@@ -235,7 +242,7 @@ DEF_SIMPLE_GM(onebadarc, canvas, 100, 100) {
SkPaint p0;
p0.setColor(SK_ColorRED);
p0.setStrokeWidth(15.f);
- p0.setStyle(SkPaint::kStroke_Style);
+ p0.setStroke(true);
p0.setAlpha(100);
canvas->translate(20, 0);
canvas->drawPath(path, p0);
@@ -251,7 +258,7 @@ DEF_SIMPLE_GM(crbug_888453, canvas, 480, 150) {
SkPaint fill;
fill.setAntiAlias(true);
SkPaint hairline = fill;
- hairline.setStyle(SkPaint::kStroke_Style);
+ hairline.setStroke(true);
SkPaint stroke = hairline;
stroke.setStrokeWidth(2.0f);
int x = 4;
@@ -323,7 +330,7 @@ DEF_SIMPLE_GM(circular_arc_stroke_matrix, canvas, 820, 1090) {
SkPaint paint;
paint.setStrokeCap(cap);
paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
paint.setStrokeWidth(kStrokeWidth);
canvas->save();
canvas->translate(x * (2*kRadius + kPad), y * (2*kRadius + kPad));
diff --git a/chromium/third_party/skia/gm/clockwise.cpp b/chromium/third_party/skia/gm/clockwise.cpp
index 01ac28abf49..d19690a92bf 100644
--- a/chromium/third_party/skia/gm/clockwise.cpp
+++ b/chromium/third_party/skia/gm/clockwise.cpp
@@ -23,7 +23,6 @@
#include "include/private/SkColorData.h"
#include "src/gpu/GrBuffer.h"
#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrColorSpaceXform.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrGeometryProcessor.h"
@@ -189,7 +188,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();
fProgramInfo = this->createProgramInfo(context->priv().caps(), arena, writeView,
std::move(appliedClip), dstProxyView);
@@ -242,7 +241,7 @@ private:
// Test.
void ClockwiseGM::onDraw(GrContext* ctx, GrRenderTargetContext* rtc, SkCanvas* canvas) {
- rtc->clear(nullptr, { 0, 0, 0, 1 }, GrRenderTargetContext::CanClearFullscreen::kYes);
+ rtc->clear(SK_PMColor4fBLACK);
// Draw the test directly to the frame buffer.
rtc->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
@@ -254,11 +253,10 @@ void ClockwiseGM::onDraw(GrContext* ctx, GrRenderTargetContext* rtc, SkCanvas* c
ctx, rtcColorType, nullptr, SkBackingFit::kExact, {100, 200}, 1,
GrMipMapped::kNo, GrProtected::kNo, kTopLeft_GrSurfaceOrigin, SkBudgeted::kYes,
nullptr)) {
- topLeftRTC->clear(nullptr, SK_PMColor4fTRANSPARENT,
- GrRenderTargetContext::CanClearFullscreen::kYes);
+ topLeftRTC->clear(SK_PMColor4fTRANSPARENT);
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
- rtc->drawTexture(GrNoClip(), topLeftRTC->readSurfaceView(), rtc->colorInfo().alphaType(),
+ rtc->drawTexture(nullptr, topLeftRTC->readSurfaceView(), rtc->colorInfo().alphaType(),
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver, SK_PMColor4fWHITE,
{0, 0, 100, 200}, {100, 0, 200, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
@@ -270,11 +268,10 @@ void ClockwiseGM::onDraw(GrContext* ctx, GrRenderTargetContext* rtc, SkCanvas* c
ctx, rtcColorType, nullptr, SkBackingFit::kExact, {100, 200}, 1,
GrMipMapped::kNo, GrProtected::kNo, kBottomLeft_GrSurfaceOrigin, SkBudgeted::kYes,
nullptr)) {
- topLeftRTC->clear(nullptr, SK_PMColor4fTRANSPARENT,
- GrRenderTargetContext::CanClearFullscreen::kYes);
+ topLeftRTC->clear(SK_PMColor4fTRANSPARENT);
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, false, 0));
topLeftRTC->priv().testingOnly_addDrawOp(ClockwiseTestOp::Make(ctx, true, 100));
- rtc->drawTexture(GrNoClip(), topLeftRTC->readSurfaceView(), rtc->colorInfo().alphaType(),
+ rtc->drawTexture(nullptr, topLeftRTC->readSurfaceView(), rtc->colorInfo().alphaType(),
GrSamplerState::Filter::kNearest, SkBlendMode::kSrcOver, SK_PMColor4fWHITE,
{0, 0, 100, 200}, {200, 0, 300, 200}, GrAA::kNo, GrQuadAAFlags::kNone,
SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint, SkMatrix::I(),
diff --git a/chromium/third_party/skia/gm/complexclip.cpp b/chromium/third_party/skia/gm/complexclip.cpp
index 6e22dc0b208..e6bef93aaec 100644
--- a/chromium/third_party/skia/gm/complexclip.cpp
+++ b/chromium/third_party/skia/gm/complexclip.cpp
@@ -19,6 +19,7 @@
#include "include/core/SkString.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
+#include "include/effects/SkGradientShader.h"
#include "src/core/SkClipOpPriv.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"
@@ -239,7 +240,7 @@ DEF_SIMPLE_GM(clip_shader, canvas, 840, 650) {
canvas->translate(img->width() + 10, img->height() + 10);
canvas->clipShader(sh, SkClipOp::kIntersect);
canvas->save();
- SkMatrix lm = SkMatrix::MakeScale(1.0f / 5);
+ SkMatrix lm = SkMatrix::Scale(1.0f/5, 1.0f/5);
canvas->clipShader(img->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, &lm));
canvas->drawImage(img, 0, 0, nullptr);
@@ -262,3 +263,183 @@ DEF_SIMPLE_GM(clip_shader_layer, canvas, 430, 320) {
canvas->drawColor(0xFFFF0000);
canvas->restore();
}
+
+DEF_SIMPLE_GM(clip_shader_nested, canvas, 256, 256) {
+ float w = 64.f;
+ float h = 64.f;
+
+ const SkColor gradColors[] = {SK_ColorBLACK, SkColorSetARGB(128, 128, 128, 128)};
+ auto s = SkGradientShader::MakeRadial({0.5f * w, 0.5f * h}, 0.1f * w, gradColors, nullptr,
+ 2, SkTileMode::kRepeat, 0, nullptr);
+
+ SkPaint p;
+
+ // A large black rect affected by two gradient clips
+ canvas->save();
+ canvas->clipShader(s);
+ canvas->scale(2.f, 2.f);
+ canvas->clipShader(s);
+ canvas->drawRect(SkRect::MakeWH(w, h), p);
+ canvas->restore();
+
+ canvas->translate(0.f, 2.f * h);
+
+ // A small red rect, with no clipping
+ canvas->save();
+ p.setColor(SK_ColorRED);
+ canvas->drawRect(SkRect::MakeWH(w, h), p);
+ canvas->restore();
+}
+
+namespace {
+
+// Where is canvas->concat(persp) called relative to the clipShader calls.
+enum ConcatPerspective {
+ kConcatBeforeClips,
+ kConcatAfterClips,
+ kConcatBetweenClips
+};
+// Order in which clipShader(image) and clipShader(gradient) are specified; only meaningful
+// when CanvasPerspective is kConcatBetweenClips.
+enum ClipOrder {
+ kClipImageFirst,
+ kClipGradientFirst,
+
+ kDoesntMatter = kClipImageFirst
+};
+// Which shaders have perspective applied as a local matrix.
+enum LocalMatrix {
+ kNoLocalMat,
+ kImageWithLocalMat,
+ kGradientWithLocalMat,
+ kBothWithLocalMat
+};
+struct Config {
+ ConcatPerspective fConcat;
+ ClipOrder fOrder;
+ LocalMatrix fLM;
+};
+
+static void draw_banner(SkCanvas* canvas, Config config) {
+ SkString banner;
+ banner.append("Persp: ");
+
+ if (config.fConcat == kConcatBeforeClips || config.fLM == kBothWithLocalMat) {
+ banner.append("Both Clips");
+ } else {
+ SkASSERT((config.fConcat == kConcatBetweenClips && config.fLM == kNoLocalMat) ||
+ (config.fConcat == kConcatAfterClips && (config.fLM == kImageWithLocalMat ||
+ config.fLM == kGradientWithLocalMat)));
+ if ((config.fConcat == kConcatBetweenClips && config.fOrder == kClipImageFirst) ||
+ config.fLM == kGradientWithLocalMat) {
+ banner.append("Gradient");
+ } else {
+ SkASSERT(config.fOrder == kClipGradientFirst || config.fLM == kImageWithLocalMat);
+ banner.append("Image");
+ }
+ }
+ if (config.fLM != kNoLocalMat) {
+ banner.append(" (w/ LM, should equal top row)");
+ }
+
+ static const SkFont kFont(ToolUtils::create_portable_typeface(), 12);
+ canvas->drawString(banner.c_str(), 20.f, -30.f, kFont, SkPaint());
+};
+
+} // anonymous
+
+DEF_SIMPLE_GM(clip_shader_persp, canvas, 1370, 1030) {
+ // Each draw has a clipShader(image-shader), a clipShader(gradient-shader), a concat(persp-mat),
+ // and each shader may or may not be wrapped with a perspective local matrix.
+
+ // Pairs of configs that should match in appearance where first config doesn't use a local
+ // matrix (top row of GM) and the second does (bottom row of GM).
+ Config matches[][2] = {
+ // Everything has perspective
+ {{kConcatBeforeClips, kDoesntMatter, kNoLocalMat},
+ {kConcatAfterClips, kDoesntMatter, kBothWithLocalMat}},
+ // Image shader has perspective
+ {{kConcatBetweenClips, kClipGradientFirst, kNoLocalMat},
+ {kConcatAfterClips, kDoesntMatter, kImageWithLocalMat}},
+ // Gradient shader has perspective
+ {{kConcatBetweenClips, kClipImageFirst, kNoLocalMat},
+ {kConcatAfterClips, kDoesntMatter, kGradientWithLocalMat}}
+ };
+
+ // The image that is drawn
+ auto img = GetResourceAsImage("images/yellow_rose.png");
+ // Scale factor always applied to the image shader so that it tiles
+ SkMatrix scale = SkMatrix::Scale(1.f / 4.f, 1.f / 4.f);
+ // The perspective matrix applied wherever needed
+ SkPoint src[4];
+ SkRect::Make(img->dimensions()).toQuad(src);
+ SkPoint dst[4] = {{0, 80.f},
+ {img->width() + 28.f, -100.f},
+ {img->width() - 28.f, img->height() + 100.f},
+ {0.f, img->height() - 80.f}};
+ SkMatrix persp;
+ SkAssertResult(persp.setPolyToPoly(src, dst, 4));
+
+ SkMatrix perspScale = SkMatrix::Concat(persp, scale);
+
+ auto drawConfig = [&](Config config) {
+ canvas->save();
+
+ draw_banner(canvas, config);
+
+ // Make clipShaders (possibly with local matrices)
+ bool gradLM = config.fLM == kGradientWithLocalMat || config.fLM == kBothWithLocalMat;
+ const SkColor gradColors[] = {SK_ColorBLACK, SkColorSetARGB(128, 128, 128, 128)};
+ auto gradShader = SkGradientShader::MakeRadial({0.5f * img->width(), 0.5f * img->height()},
+ 0.1f * img->width(), gradColors, nullptr, 2,
+ SkTileMode::kRepeat, 0,
+ gradLM ? &persp : nullptr);
+ bool imageLM = config.fLM == kImageWithLocalMat || config.fLM == kBothWithLocalMat;
+ auto imgShader = img->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
+ imageLM ? perspScale : scale);
+
+ // Perspective before any clipShader
+ if (config.fConcat == kConcatBeforeClips) {
+ canvas->concat(persp);
+ }
+
+ // First clipshader
+ canvas->clipShader(config.fOrder == kClipImageFirst ? imgShader : gradShader);
+
+ // Perspective between clipShader
+ if (config.fConcat == kConcatBetweenClips) {
+ canvas->concat(persp);
+ }
+
+ // Second clipShader
+ canvas->clipShader(config.fOrder == kClipImageFirst ? gradShader : imgShader);
+
+ // Perspective after clipShader
+ if (config.fConcat == kConcatAfterClips) {
+ canvas->concat(persp);
+ }
+
+ // Actual draw and clip boundary are the same for all configs
+ canvas->clipRect(SkRect::MakeIWH(img->width(), img->height()));
+ canvas->clear(SK_ColorBLACK);
+ canvas->drawImage(img, 0, 0);
+
+ canvas->restore();
+ };
+
+ SkIRect grid = persp.mapRect(SkRect::Make(img->dimensions())).roundOut();
+ grid.fLeft -= 20; // manual adjust to look nicer
+
+ canvas->translate(10.f, 10.f);
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(matches); ++i) {
+ canvas->save();
+ canvas->translate(-grid.fLeft, -grid.fTop);
+ drawConfig(matches[i][0]);
+ canvas->translate(0.f, grid.height());
+ drawConfig(matches[i][1]);
+ canvas->restore();
+
+ canvas->translate(grid.width(), 0.f);
+ }
+}
diff --git a/chromium/third_party/skia/gm/composeshader.cpp b/chromium/third_party/skia/gm/composeshader.cpp
index 8ef08247be7..b4fdfd2f0fb 100644
--- a/chromium/third_party/skia/gm/composeshader.cpp
+++ b/chromium/third_party/skia/gm/composeshader.cpp
@@ -192,7 +192,7 @@ protected:
void onDraw(SkCanvas* canvas) override {
SkBlendMode mode = SkBlendMode::kDstOver;
- SkMatrix lm = SkMatrix::MakeTrans(0, squareLength * 0.5f);
+ SkMatrix lm = SkMatrix::Translate(0, squareLength * 0.5f);
sk_sp<SkShader> shaders[] = {
// gradient should appear over color bitmap
diff --git a/chromium/third_party/skia/gm/conicpaths.cpp b/chromium/third_party/skia/gm/conicpaths.cpp
index 1ba8b44735e..1375726c367 100644
--- a/chromium/third_party/skia/gm/conicpaths.cpp
+++ b/chromium/third_party/skia/gm/conicpaths.cpp
@@ -112,7 +112,7 @@ protected:
for (int aa = 0; aa < 2; ++aa) {
paint.setAntiAlias(SkToBool(aa));
for (int fh = 0; fh < 2; ++fh) {
- paint.setStyle(fh ? SkPaint::kStroke_Style : SkPaint::kFill_Style);
+ paint.setStroke(fh != 0);
const SkRect& bounds = fPaths[p].getBounds();
canvas->save();
@@ -148,7 +148,7 @@ DEF_SIMPLE_GM(arccirclegap, canvas, 250, 250) {
SkScalar radius = 1096.702150363923f;
SkPaint paint;
paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
canvas->drawCircle(c, radius, paint);
SkPath path;
path.moveTo(288.88884710654133f, -280.26680862609f);
@@ -164,7 +164,7 @@ DEF_SIMPLE_GM(largecircle, canvas, 250, 250) {
SkScalar radius = 1096.702150363923f;
SkPaint paint;
paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
canvas->drawCircle(c, radius, paint);
}
@@ -174,7 +174,7 @@ DEF_SIMPLE_GM(largeovals, canvas, 250, 250) {
SkRect r = SkRect::MakeXYWH(-520, -520, 5000, 4000);
SkPaint paint;
paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
paint.setStrokeWidth(100);
canvas->drawOval(r, paint);
r.offset(-15, -15);
@@ -188,7 +188,7 @@ DEF_SIMPLE_GM(largeovals, canvas, 250, 250) {
canvas->rotate(1.0f);
r.offset(55, 55);
paint.setColor(SK_ColorGRAY);
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
paint.setStrokeWidth(100);
canvas->drawOval(r, paint);
r.offset(-15, -15);
diff --git a/chromium/third_party/skia/gm/constcolorprocessor.cpp b/chromium/third_party/skia/gm/constcolorprocessor.cpp
index d72d91c1e8b..892fc962ab2 100644
--- a/chromium/third_party/skia/gm/constcolorprocessor.cpp
+++ b/chromium/third_party/skia/gm/constcolorprocessor.cpp
@@ -101,7 +101,7 @@ protected:
// translate by x,y for the canvas draws and the test target draws.
canvas->save();
canvas->translate(x, y);
- const SkMatrix viewMatrix = SkMatrix::MakeTrans(x, y);
+ const SkMatrix viewMatrix = SkMatrix::Translate(x, y);
SkSimpleMatrixProvider matrixProvider(viewMatrix);
// rect to draw
@@ -119,7 +119,7 @@ protected:
GrConstColorProcessor::InputMode mode = (GrConstColorProcessor::InputMode) m;
SkPMColor4f color = SkPMColor4f::FromBytes_RGBA(kColors[procColor]);
- auto fp = GrConstColorProcessor::Make(color, mode);
+ auto fp = GrConstColorProcessor::Make(/*inputFP=*/nullptr, color, mode);
grPaint.addColorFragmentProcessor(std::move(fp));
renderTargetContext->priv().testingOnly_addDrawOp(
diff --git a/chromium/third_party/skia/gm/convexpolyeffect.cpp b/chromium/third_party/skia/gm/convexpolyeffect.cpp
index 68d328926cc..f2654624a66 100644
--- a/chromium/third_party/skia/gm/convexpolyeffect.cpp
+++ b/chromium/third_party/skia/gm/convexpolyeffect.cpp
@@ -121,13 +121,13 @@ protected:
SkScalar x = 0;
for (int et = 0; et < kGrClipEdgeTypeCnt; ++et) {
- const SkMatrix m = SkMatrix::MakeTrans(x, y);
+ const SkMatrix m = SkMatrix::Translate(x, y);
SkPath p;
path->transform(m, &p);
GrClipEdgeType edgeType = (GrClipEdgeType) et;
- std::unique_ptr<GrFragmentProcessor> fp(GrConvexPolyEffect::Make(edgeType, p));
- if (!fp) {
+ auto [success, fp] = GrConvexPolyEffect::Make(/*inputFP=*/nullptr, edgeType, p);
+ if (!success) {
continue;
}
@@ -165,8 +165,8 @@ protected:
for (int et = 0; et < kGrClipEdgeTypeCnt; ++et) {
SkRect rect = iter.get()->makeOffset(x, y);
GrClipEdgeType edgeType = (GrClipEdgeType) et;
- std::unique_ptr<GrFragmentProcessor> fp(GrConvexPolyEffect::Make(edgeType, rect));
- if (!fp) {
+ auto [success, fp] = GrConvexPolyEffect::Make(/*inputFP=*/nullptr, edgeType, rect);
+ if (!success) {
continue;
}
diff --git a/chromium/third_party/skia/gm/dashcircle.cpp b/chromium/third_party/skia/gm/dashcircle.cpp
index c6d03048175..7942b34bb11 100644
--- a/chromium/third_party/skia/gm/dashcircle.cpp
+++ b/chromium/third_party/skia/gm/dashcircle.cpp
@@ -50,7 +50,7 @@ protected:
SkPaint refPaint;
refPaint.setAntiAlias(true);
refPaint.setColor(0xFFbf3f7f);
- refPaint.setStyle(SkPaint::kStroke_Style);
+ refPaint.setStroke(true);
refPaint.setStrokeWidth(1);
const SkScalar radius = 125;
SkRect oval = SkRect::MakeLTRB(-radius - 20, -radius - 20, radius + 20, radius + 20);
@@ -85,7 +85,7 @@ protected:
canvas->restore();
SkPaint p;
p.setAntiAlias(true);
- p.setStyle(SkPaint::kStroke_Style);
+ p.setStroke(true);
p.setStrokeWidth(10);
SkScalar intervals[4];
int intervalCount = dashExample.length;
@@ -175,10 +175,10 @@ protected:
rotate.setRotate(25.f);
static const SkMatrix kMatrices[]{
SkMatrix::I(),
- SkMatrix::MakeScale(1.2f),
+ SkMatrix::Scale(1.2f, 1.2f),
SkMatrix::MakeAll(1, 0, 0, 0, -1, 0, 0, 0, 1), // y flipper
SkMatrix::MakeAll(-1, 0, 0, 0, 1, 0, 0, 0, 1), // x flipper
- SkMatrix::MakeScale(0.7f),
+ SkMatrix::Scale(0.7f, 0.7f),
rotate,
SkMatrix::Concat(
SkMatrix::Concat(SkMatrix::MakeAll(-1, 0, 0, 0, 1, 0, 0, 0, 1), rotate),
@@ -188,7 +188,7 @@ protected:
SkPaint paint;
paint.setAntiAlias(true);
paint.setStrokeWidth(kStrokeWidth);
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
// Compute the union of bounds of all of our test cases.
SkRect bounds = SkRect::MakeEmpty();
@@ -242,7 +242,7 @@ DEF_SIMPLE_GM(maddash, canvas, 1600, 1600) {
SkPaint p;
p.setColor(SK_ColorRED);
p.setAntiAlias(true);
- p.setStyle(SkPaint::kStroke_Style);
+ p.setStroke(true);
p.setStrokeWidth(380);
SkScalar intvls[] = { 2.5, 10 /* 1200 */ };
diff --git a/chromium/third_party/skia/gm/dashcubics.cpp b/chromium/third_party/skia/gm/dashcubics.cpp
index 2d2157f7c3d..03bfe9008b3 100644
--- a/chromium/third_party/skia/gm/dashcubics.cpp
+++ b/chromium/third_party/skia/gm/dashcubics.cpp
@@ -31,7 +31,7 @@ static void flower(SkCanvas* canvas, const SkPath& path, SkScalar intervals[2],
SkPaint::Join join) {
SkPaint paint;
paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
paint.setStrokeJoin(join);
paint.setStrokeWidth(42);
canvas->drawPath(path, paint);
@@ -119,7 +119,7 @@ protected:
SkPaint hairlinePaint;
hairlinePaint.setAntiAlias(true);
- hairlinePaint.setStyle(SkPaint::kStroke_Style);
+ hairlinePaint.setStroke(true);
hairlinePaint.setStrokeCap(SkPaint::kRound_Cap);
hairlinePaint.setStrokeWidth(2);
SkPaint normalPaint = hairlinePaint;
diff --git a/chromium/third_party/skia/gm/dashing.cpp b/chromium/third_party/skia/gm/dashing.cpp
index 3a01dfd2547..578572cd85e 100644
--- a/chromium/third_party/skia/gm/dashing.cpp
+++ b/chromium/third_party/skia/gm/dashing.cpp
@@ -54,7 +54,7 @@ static void show_zero_len_dash(SkCanvas* canvas) {
SkPaint paint;
drawline(canvas, 2, 2, paint, SkIntToScalar(0));
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
paint.setStrokeWidth(SkIntToScalar(2));
canvas->translate(0, SkIntToScalar(20));
drawline(canvas, 4, 4, paint, SkIntToScalar(0));
@@ -66,30 +66,27 @@ class DashingGM : public skiagm::GM {
SkISize onISize() override { return {640, 340}; }
void onDraw(SkCanvas* canvas) override {
- constexpr struct {
+ struct Intervals {
int fOnInterval;
int fOffInterval;
- } gData[] = {
- { 1, 1 },
- { 4, 1 },
};
SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
canvas->translate(0, SK_ScalarHalf);
for (int width = 0; width <= 2; ++width) {
- for (size_t data = 0; data < SK_ARRAY_COUNT(gData); ++data) {
- for (int aa = 0; aa <= 1; ++aa) {
+ for (const Intervals& data : {Intervals{1, 1},
+ Intervals{4, 1}}) {
+ for (bool aa : {false, true}) {
int w = width * width * width;
- paint.setAntiAlias(SkToBool(aa));
+ paint.setAntiAlias(aa);
paint.setStrokeWidth(SkIntToScalar(w));
int scale = w ? w : 1;
- drawline(canvas, gData[data].fOnInterval * scale,
- gData[data].fOffInterval * scale,
+ drawline(canvas, data.fOnInterval * scale, data.fOffInterval * scale,
paint);
canvas->translate(0, SkIntToScalar(20));
}
@@ -159,7 +156,7 @@ class Dashing2GM : public skiagm::GM {
SkPaint paint;
paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
paint.setStrokeWidth(SkIntToScalar(6));
SkRect bounds = SkRect::MakeWH(SkIntToScalar(120), SkIntToScalar(120));
@@ -207,7 +204,7 @@ class Dashing3GM : public skiagm::GM {
bool circles) {
SkPaint p;
p.setColor(SK_ColorBLACK);
- p.setStyle(SkPaint::kStroke_Style);
+ p.setStroke(true);
p.setStrokeWidth(SkIntToScalar(strokeWidth));
if (circles) {
@@ -321,36 +318,31 @@ class Dashing4GM : public skiagm::GM {
SkISize onISize() override { return {640, 1100}; }
void onDraw(SkCanvas* canvas) override {
- constexpr struct {
+ struct Intervals {
int fOnInterval;
int fOffInterval;
- } gData[] = {
- { 1, 1 },
- { 4, 2 },
- { 0, 4 }, // test for zero length on interval
};
SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
canvas->translate(SkIntToScalar(20), SkIntToScalar(20));
canvas->translate(SK_ScalarHalf, SK_ScalarHalf);
for (int width = 0; width <= 2; ++width) {
- for (size_t data = 0; data < SK_ARRAY_COUNT(gData); ++data) {
- for (int aa = 0; aa <= 1; ++aa) {
- for (int cap = 0; cap <= 1; ++cap) {
+ for (const Intervals& data : {Intervals{1, 1},
+ Intervals{4, 2},
+ Intervals{0, 4}}) { // test for zero length on interval
+ for (bool aa : {false, true}) {
+ for (auto cap : {SkPaint::kRound_Cap, SkPaint::kSquare_Cap}) {
int w = width * width * width;
- paint.setAntiAlias(SkToBool(aa));
+ paint.setAntiAlias(aa);
paint.setStrokeWidth(SkIntToScalar(w));
-
- SkToBool(cap) ? paint.setStrokeCap(SkPaint::kSquare_Cap)
- : paint.setStrokeCap(SkPaint::kRound_Cap);
+ paint.setStrokeCap(cap);
int scale = w ? w : 1;
- drawline(canvas, gData[data].fOnInterval * scale,
- gData[data].fOffInterval * scale,
+ drawline(canvas, data.fOnInterval * scale, data.fOffInterval * scale,
paint);
canvas->translate(0, SkIntToScalar(20));
}
@@ -438,7 +430,7 @@ private:
};
SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStroke(true);
paint.setAntiAlias(fDoAA);
@@ -497,7 +489,7 @@ DEF_SIMPLE_GM(longpathdash, canvas, 612, 612) {
}
SkPaint p;
p.setAntiAlias(true);
- p.setStyle(SkPaint::kStroke_Style);
+ p.setStroke(true);
p.setStrokeWidth(1);
const SkScalar intervals[] = { 1, 1 };
p.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 0));
@@ -509,7 +501,7 @@ DEF_SIMPLE_GM(longpathdash, canvas, 612, 612) {
DEF_SIMPLE_GM(longlinedash, canvas, 512, 512) {
SkPaint p;
p.setAntiAlias(true);
- p.setStyle(SkPaint::kStroke_Style);
+ p.setStroke(true);
p.setStrokeWidth(80);
const SkScalar intervals[] = { 2, 2 };
@@ -520,7 +512,7 @@ DEF_SIMPLE_GM(longlinedash, canvas, 512, 512) {
DEF_SIMPLE_GM(longwavyline, canvas, 512, 512) {
SkPaint p;
p.setAntiAlias(true);
- p.setStyle(SkPaint::kStroke_Style);
+ p.setStroke(true);
p.setStrokeWidth(2);
SkPath wavy;
@@ -535,7 +527,7 @@ DEF_SIMPLE_GM(longwavyline, canvas, 512, 512) {
DEF_SIMPLE_GM(dashtextcaps, canvas, 512, 512) {
SkPaint p;
p.setAntiAlias(true);
- p.setStyle(SkPaint::kStroke_Style);
+ p.setStroke(true);
p.setStrokeWidth(10);
p.setStrokeCap(SkPaint::kRound_Cap);
p.setStrokeJoin(SkPaint::kRound_Join);
@@ -554,7 +546,7 @@ DEF_SIMPLE_GM(dash_line_zero_off_interval, canvas, 160, 330) {
SkPaint dashPaint;
dashPaint.setPathEffect(SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), 0.f));
SkASSERT(dashPaint.getPathEffect());
- dashPaint.setStyle(SkPaint::kStroke_Style);
+ dashPaint.setStroke(true);
dashPaint.setStrokeWidth(20.f);
static constexpr struct {
SkPoint fA, fB;
diff --git a/chromium/third_party/skia/gm/dftext_blob_persp.cpp b/chromium/third_party/skia/gm/dftext_blob_persp.cpp
index 9c38221a190..0e7c666c480 100644
--- a/chromium/third_party/skia/gm/dftext_blob_persp.cpp
+++ b/chromium/third_party/skia/gm/dftext_blob_persp.cpp
@@ -131,8 +131,8 @@ private:
persp.setPerspY(-0.0015f);
break;
}
- persp = SkMatrix::Concat(persp, SkMatrix::MakeTrans(-x, -y));
- persp = SkMatrix::Concat(SkMatrix::MakeTrans(x, y), persp);
+ persp = SkMatrix::Concat(persp, SkMatrix::Translate(-x, -y));
+ persp = SkMatrix::Concat(SkMatrix::Translate(x, y), persp);
canvas->concat(persp);
if (TranslateWithMatrix::kYes == translateWithMatrix) {
canvas->translate(x, y);
diff --git a/chromium/third_party/skia/gm/draw_bitmap_rect_skbug4374.cpp b/chromium/third_party/skia/gm/draw_bitmap_rect_skbug4374.cpp
index 52d17e331de..03770d3ff53 100644
--- a/chromium/third_party/skia/gm/draw_bitmap_rect_skbug4374.cpp
+++ b/chromium/third_party/skia/gm/draw_bitmap_rect_skbug4374.cpp
@@ -19,7 +19,7 @@ DEF_SIMPLE_GM(draw_bitmap_rect_skbug4734, canvas, 64, 64) {
SkRect rect = SkRect::Make(source.bounds());
rect.inset(0.5, 1.5);
SkRect dst;
- SkMatrix::MakeScale(8.0f).mapRect(&dst, rect);
+ SkMatrix::Scale(8, 8).mapRect(&dst, rect);
canvas->drawBitmapRect(source, rect, dst, nullptr);
}
}
diff --git a/chromium/third_party/skia/gm/drawable.cpp b/chromium/third_party/skia/gm/drawable.cpp
index 77800491f75..857467224e1 100644
--- a/chromium/third_party/skia/gm/drawable.cpp
+++ b/chromium/third_party/skia/gm/drawable.cpp
@@ -43,7 +43,7 @@ DEF_SIMPLE_GM(drawable, canvas, 180, 275) {
canvas->drawDrawable(drawable.get());
canvas->drawDrawable(drawable.get(), 0, 150);
- SkMatrix m = SkMatrix::MakeScale(1.5f, 0.8f);
+ SkMatrix m = SkMatrix::Scale(1.5f, 0.8f);
m.postTranslate(70, 0);
canvas->drawDrawable(drawable.get(), &m);
diff --git a/chromium/third_party/skia/gm/drawimageset.cpp b/chromium/third_party/skia/gm/drawimageset.cpp
index 345b5a9238b..870da11ec9f 100644
--- a/chromium/third_party/skia/gm/drawimageset.cpp
+++ b/chromium/third_party/skia/gm/drawimageset.cpp
@@ -34,12 +34,12 @@
// Makes a set of m x n tiled images to be drawn with SkCanvas::experimental_drawImageSetV1().
static void make_image_tiles(int tileW, int tileH, int m, int n, const SkColor colors[4],
- SkCanvas::ImageSetEntry set[]) {
+ SkCanvas::ImageSetEntry set[], const SkColor bgColor=SK_ColorLTGRAY) {
const int w = tileW * m;
const int h = tileH * n;
auto surf = SkSurface::MakeRaster(
SkImageInfo::Make(w, h, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
- surf->getCanvas()->clear(SK_ColorLTGRAY);
+ surf->getCanvas()->clear(bgColor);
static constexpr SkScalar kStripeW = 10;
static constexpr SkScalar kStripeSpacing = 30;
@@ -288,7 +288,68 @@ private:
SkCanvas::ImageSetEntry fSet[kM * kN];
};
+// This GM exercises alpha-only and color textures being combined correctly with the paint's color.
+class DrawImageSetAlphaOnlyGM : public GM {
+private:
+ SkString onShortName() override { return SkString("draw_image_set_alpha_only"); }
+ SkISize onISize() override { return {kM*kTileW, 2*kN*kTileH}; }
+ void onOnceBeforeDraw() override {
+ static constexpr SkColor kColors[] = {SK_ColorBLUE, SK_ColorTRANSPARENT,
+ SK_ColorRED, SK_ColorTRANSPARENT};
+ static constexpr SkColor kBGColor = SkColorSetARGB(128, 128, 128, 128);
+ make_image_tiles(kTileW, kTileH, kM, kN, kColors, fSet, kBGColor);
+
+ // Modify the alpha of the entries, decreasing by column, and convert even rows to
+ // alpha-only textures.
+ sk_sp<SkColorSpace> alphaSpace = SkColorSpace::MakeSRGB();
+ for (int y = 0; y < kN; ++y) {
+ for (int x = 0; x < kM; ++x) {
+ int i = y * kM + x;
+ fSet[i].fAlpha = (kM - x) / (float) kM;
+ if (y % 2 == 0) {
+ fSet[i].fImage = fSet[i].fImage->makeColorTypeAndColorSpace(
+ kAlpha_8_SkColorType, alphaSpace);
+ }
+ }
+ }
+
+ }
+
+ void onDraw(SkCanvas* canvas) override {
+ ToolUtils::draw_checkerboard(canvas, SK_ColorGRAY, SK_ColorDKGRAY, 25);
+
+ SkPaint paint;
+ paint.setFilterQuality(kLow_SkFilterQuality);
+ paint.setBlendMode(SkBlendMode::kSrcOver);
+ paint.setColor4f({0.2f, 0.8f, 0.4f, 1.f}); // colorizes even rows, no effect on odd rows
+
+ // Top rows use experimental edge set API
+ canvas->experimental_DrawEdgeAAImageSet(fSet, kM * kN, nullptr, nullptr, &paint,
+ SkCanvas::kFast_SrcRectConstraint);
+
+ canvas->translate(0.f, kN * kTileH);
+
+ // Bottom rows draw each image from the set using the regular API
+ for (int y = 0; y < kN; ++y) {
+ for (int x = 0; x < kM; ++x) {
+ int i = y * kM + x;
+ SkPaint entryPaint = paint;
+ entryPaint.setAlphaf(fSet[i].fAlpha * paint.getAlphaf());
+ canvas->drawImageRect(fSet[i].fImage.get(), fSet[i].fSrcRect, fSet[i].fDstRect,
+ &entryPaint, SkCanvas::kFast_SrcRectConstraint);
+ }
+ }
+ }
+
+ static constexpr int kM = 4;
+ static constexpr int kN = 4;
+ static constexpr int kTileW = 50;
+ static constexpr int kTileH = 50;
+ SkCanvas::ImageSetEntry fSet[kM * kN];
+};
+
DEF_GM(return new DrawImageSetGM();)
DEF_GM(return new DrawImageSetRectToRectGM();)
+DEF_GM(return new DrawImageSetAlphaOnlyGM();)
} // namespace skiagm
diff --git a/chromium/third_party/skia/gm/drawquadset.cpp b/chromium/third_party/skia/gm/drawquadset.cpp
index fc086ceaf68..fb24f9df1e0 100644
--- a/chromium/third_party/skia/gm/drawquadset.cpp
+++ b/chromium/third_party/skia/gm/drawquadset.cpp
@@ -25,7 +25,6 @@
#include "include/gpu/GrContext.h"
#include "include/private/GrTypesPriv.h"
#include "src/core/SkMatrixProvider.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrPaint.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/SkGr.h"
@@ -87,7 +86,7 @@ static void draw_gradient_tiles(SkCanvas* canvas, bool alignGradients) {
SkSimpleMatrixProvider matrixProvider(view);
GrPaint grPaint;
SkPaintToGrPaint(context, rtc->colorInfo(), paint, matrixProvider, &grPaint);
- rtc->fillRectWithEdgeAA(GrNoClip(), std::move(grPaint), GrAA::kYes,
+ rtc->fillRectWithEdgeAA(nullptr, std::move(grPaint), GrAA::kYes,
static_cast<GrQuadAAFlags>(aa), view, tile);
} else {
// Fallback to solid color on raster backend since the public API only has color
diff --git a/chromium/third_party/skia/gm/dstreadshuffle.cpp b/chromium/third_party/skia/gm/dstreadshuffle.cpp
index 9e6a7addb0a..1737009b885 100644
--- a/chromium/third_party/skia/gm/dstreadshuffle.cpp
+++ b/chromium/third_party/skia/gm/dstreadshuffle.cpp
@@ -100,6 +100,7 @@ protected:
SkFont font(ToolUtils::create_portable_typeface(), 100);
font.setEmbolden(true);
canvas->drawString(text, 0.f, 100.f, font, *paint);
+ break;
}
default:
break;
diff --git a/chromium/third_party/skia/gm/encode_color_types.cpp b/chromium/third_party/skia/gm/encode_color_types.cpp
new file mode 100644
index 00000000000..d496ae8c27f
--- /dev/null
+++ b/chromium/third_party/skia/gm/encode_color_types.cpp
@@ -0,0 +1,170 @@
+/*
+ * 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 "gm/gm.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkData.h"
+#include "include/core/SkEncodedImageFormat.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkSize.h"
+#include "include/core/SkString.h"
+#include "include/core/SkSurface.h"
+#include "tools/Resources.h"
+
+namespace skiagm {
+
+static const int imageWidth = 128;
+static const int imageHeight = 128;
+
+static sk_sp<SkImage> make_image(SkColorType colorType, SkAlphaType alphaType) {
+ const char* resource;
+ switch (colorType) {
+ case kGray_8_SkColorType:
+ if (alphaType != kOpaque_SkAlphaType) {
+ return nullptr;
+ }
+ resource = "images/grayscale.jpg";
+ break;
+ case kRGB_565_SkColorType:
+ case kRGB_888x_SkColorType:
+ case kRGB_101010x_SkColorType:
+ case kBGR_101010x_SkColorType:
+ if (alphaType != kOpaque_SkAlphaType) {
+ return nullptr;
+ }
+ resource = "images/color_wheel.jpg";
+ break;
+ default:
+ resource = (kOpaque_SkAlphaType == alphaType) ? "images/color_wheel.jpg"
+ : "images/rainbow-gradient.png";
+ break;
+ }
+
+ auto image = GetResourceAsImage(resource);
+ if (!image) {
+ return nullptr;
+ }
+
+ auto surface = SkSurface::MakeRaster(SkImageInfo::Make(image->width(), image->height(),
+ colorType, alphaType, image->refColorSpace()));
+ surface->getCanvas()->drawImage(image, 0, 0);
+ return surface->makeImageSnapshot();
+}
+
+// This GM looks different depending on the colortype used, so we use different
+// names to treat them as different GMs.
+// All Variants draw images in pairs:
+// - First as an image of the SkColorType of the destination
+// - Next as the result of encoding and decoding the first image
+enum class Variant {
+ // One pair, using an opaque image.
+ kOpaque,
+ // One pair, using a grayscale image.
+ kGray,
+ // An opaque pair followed by two more for premul and unpremul.
+ kNormal,
+};
+
+class EncodeColorTypesGM : public GM {
+public:
+ EncodeColorTypesGM(SkEncodedImageFormat format, int quality, Variant variant, const char* name)
+ : fFormat(format)
+ , fQuality(quality)
+ , fVariant(variant)
+ , fName(name)
+ {}
+
+protected:
+ SkString onShortName() override {
+ const char* variant = fVariant == Variant::kOpaque ? "opaque-":
+ fVariant == Variant::kGray ? "gray-" :
+ "" ;
+ return SkStringPrintf("encode-%scolor-types-%s", variant, fName);
+ }
+
+ SkISize onISize() override {
+ const int width = fVariant == Variant::kNormal ? imageWidth * 7 : imageWidth * 2;
+ return SkISize::Make(width, imageHeight);
+ }
+
+ DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
+ const auto colorType = canvas->imageInfo().colorType();
+ switch (fVariant) {
+ case Variant::kGray:
+ if (colorType != kGray_8_SkColorType) {
+ return DrawResult::kSkip;
+ }
+ break;
+ case Variant::kOpaque:
+ if (colorType != kRGB_565_SkColorType &&
+ colorType != kRGB_888x_SkColorType &&
+ colorType != kRGB_101010x_SkColorType &&
+ colorType != kBGR_101010x_SkColorType)
+ {
+ return DrawResult::kSkip;
+ }
+ break;
+ case Variant::kNormal:
+ if (colorType != kARGB_4444_SkColorType &&
+ colorType != kRGBA_8888_SkColorType &&
+ colorType != kBGRA_8888_SkColorType &&
+ colorType != kRGBA_1010102_SkColorType &&
+ colorType != kBGRA_1010102_SkColorType &&
+ colorType != kRGBA_F16Norm_SkColorType &&
+ colorType != kRGBA_F16_SkColorType &&
+ colorType != kRGBA_F32_SkColorType)
+ {
+ return DrawResult::kSkip;
+ }
+ break;
+ }
+ const SkAlphaType alphaTypes[] = {
+ kOpaque_SkAlphaType, kPremul_SkAlphaType, kUnpremul_SkAlphaType,
+ };
+
+ for (SkAlphaType alphaType : alphaTypes) {
+ auto src = make_image(colorType, alphaType);
+ auto decoded = src ? SkImage::MakeFromEncoded(src->encodeToData(fFormat, fQuality))
+ : nullptr;
+ if (!src || !decoded) {
+ break;
+ }
+
+ canvas->drawImage(src, 0.0f, 0.0f);
+ canvas->translate((float) imageWidth, 0.0f);
+
+ canvas->drawImage(decoded, 0.0f, 0.0f);
+ canvas->translate((float) imageWidth * 1.5, 0.0f);
+ }
+ return DrawResult::kOk;
+ }
+
+private:
+ const SkEncodedImageFormat fFormat;
+ const int fQuality;
+ const Variant fVariant;
+ const char* fName;
+
+ typedef GM INHERITED;
+};
+
+
+#define DEF_ENCODE_GM(format, quality, variant, name) \
+ static skiagm::GMRegistry SK_MACRO_CONCAT(SK_MACRO_APPEND_LINE(REG_), variant)(\
+ [](){return std::unique_ptr<skiagm::GM>([](){\
+ return new EncodeColorTypesGM(format, quality, Variant::variant, name);\
+ }());});
+
+#define DEF_VARIANTS(format, quality, name) \
+ DEF_ENCODE_GM(format, quality, kNormal, name); \
+ DEF_ENCODE_GM(format, quality, kOpaque, name); \
+ DEF_ENCODE_GM(format, quality, kGray, name);
+
+DEF_VARIANTS(SkEncodedImageFormat::kWEBP, 100, "webp-lossless")
+DEF_VARIANTS(SkEncodedImageFormat::kWEBP, 80, "webp-lossy")
+}
diff --git a/chromium/third_party/skia/gm/flippity.cpp b/chromium/third_party/skia/gm/flippity.cpp
index 05bfa938b53..71ce188202d 100644
--- a/chromium/third_party/skia/gm/flippity.cpp
+++ b/chromium/third_party/skia/gm/flippity.cpp
@@ -217,17 +217,14 @@ private:
canvas->restore();
}
- void drawRow(GrContext* context, SkCanvas* canvas,
- bool bottomLeftImage, bool drawSubset, bool drawScaled) {
-
- sk_sp<SkImage> referenceImage = make_reference_image(context, fLabels, bottomLeftImage);
+ void drawRow(SkCanvas* canvas, bool bottomLeftImage, bool drawSubset, bool drawScaled) {
canvas->save();
canvas->translate(kLabelSize, kLabelSize);
for (int i = 0; i < kNumMatrices; ++i) {
- this->drawImageWithMatrixAndLabels(canvas, referenceImage.get(), i,
- drawSubset, drawScaled);
+ this->drawImageWithMatrixAndLabels(canvas, fReferenceImages[bottomLeftImage].get(),
+ i, drawSubset, drawScaled);
canvas->translate(kCellSize, 0);
}
canvas->restore();
@@ -253,28 +250,46 @@ private:
SkASSERT(kNumLabels == fLabels.count());
}
- void onDraw(GrContext* context, GrRenderTargetContext*, SkCanvas* canvas) override {
+ DrawResult onGpuSetup(GrContext* context, SkString* errorMsg) override {
+ if (!context || context->abandoned()) {
+ return DrawResult::kSkip;
+ }
+
+ SkASSERT(context->priv().asDirectContext());
+
this->makeLabels(context);
+ fReferenceImages[0] = make_reference_image(context, fLabels, false);
+ fReferenceImages[1] = make_reference_image(context, fLabels, true);
+ if (!fReferenceImages[0] || !fReferenceImages[1]) {
+ *errorMsg = "Failed to create reference images.";
+ return DrawResult::kFail;
+ }
+
+ return DrawResult::kOk;
+ }
+
+ void onDraw(GrContext*, GrRenderTargetContext*, SkCanvas* canvas) override {
+ SkASSERT(fReferenceImages[0] && fReferenceImages[1]);
canvas->save();
// Top row gets TL image
- this->drawRow(context, canvas, false, false, false);
+ this->drawRow(canvas, false, false, false);
canvas->translate(0, kCellSize);
// Bottom row gets BL image
- this->drawRow(context, canvas, true, false, false);
+ this->drawRow(canvas, true, false, false);
canvas->translate(0, kCellSize);
// Third row gets subsets of BL images
- this->drawRow(context, canvas, true, true, false);
+ this->drawRow(canvas, true, true, false);
canvas->translate(0, kCellSize);
// Fourth row gets scaled subsets of BL images
- this->drawRow(context, canvas, true, true, true);
+ this->drawRow(canvas, true, true, true);
canvas->restore();
@@ -289,6 +304,7 @@ private:
private:
SkTArray<sk_sp<SkImage>> fLabels;
+ sk_sp<SkImage> fReferenceImages[2];
typedef GM INHERITED;
};
diff --git a/chromium/third_party/skia/gm/fontregen.cpp b/chromium/third_party/skia/gm/fontregen.cpp
index 87148154a1d..88b6da72222 100644
--- a/chromium/third_party/skia/gm/fontregen.cpp
+++ b/chromium/third_party/skia/gm/fontregen.cpp
@@ -86,7 +86,7 @@ class FontRegenGM : public skiagm::GpuGM {
paint.setColor(SK_ColorBLACK);
canvas->drawTextBlob(fBlobs[0], 10, 80, paint);
canvas->drawTextBlob(fBlobs[1], 10, 225, paint);
- context->flush();
+ context->flushAndSubmit();
paint.setColor(0xFF010101);
canvas->drawTextBlob(fBlobs[0], 10, 305, paint);
@@ -142,7 +142,7 @@ class BadAppleGM : public skiagm::GpuGM {
paint.setColor(0xFF111111);
canvas->drawTextBlob(fBlobs[0], 10, 260, paint);
canvas->drawTextBlob(fBlobs[1], 10, 500, paint);
- context->flush();
+ context->flushAndSubmit();
}
private:
diff --git a/chromium/third_party/skia/gm/fpcoordinateoverride.cpp b/chromium/third_party/skia/gm/fpcoordinateoverride.cpp
index c238da43777..dc445361fa1 100644
--- a/chromium/third_party/skia/gm/fpcoordinateoverride.cpp
+++ b/chromium/third_party/skia/gm/fpcoordinateoverride.cpp
@@ -38,8 +38,7 @@ public:
SampleCoordEffect(std::unique_ptr<GrFragmentProcessor> child)
: INHERITED(CLASS_ID, kNone_OptimizationFlags) {
- child->setSampledWithExplicitCoords();
- this->registerChildProcessor(std::move(child));
+ this->registerExplicitlySampledChild(std::move(child));
}
const char* name() const override { return "SampleCoordEffect"; }
diff --git a/chromium/third_party/skia/gm/fwidth_squircle.cpp b/chromium/third_party/skia/gm/fwidth_squircle.cpp
index 0386a02390b..33fd5665068 100644
--- a/chromium/third_party/skia/gm/fwidth_squircle.cpp
+++ b/chromium/third_party/skia/gm/fwidth_squircle.cpp
@@ -197,7 +197,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();
fProgramInfo = this->createProgramInfo(context->priv().caps(), arena, writeView,
std::move(appliedClip), dstProxyView);
diff --git a/chromium/third_party/skia/gm/gm.cpp b/chromium/third_party/skia/gm/gm.cpp
index 4a49c2ae7af..552188b465a 100644
--- a/chromium/third_party/skia/gm/gm.cpp
+++ b/chromium/third_party/skia/gm/gm.cpp
@@ -72,6 +72,11 @@ GM::GM(SkColor bgColor) {
GM::~GM() {}
+DrawResult GM::gpuSetup(GrContext* context, SkString* errorMsg) {
+ TRACE_EVENT1("GM", TRACE_FUNC, "name", TRACE_STR_COPY(this->getName()));
+ return this->onGpuSetup(context, errorMsg);
+}
+
DrawResult GM::draw(SkCanvas* canvas, SkString* errorMsg) {
TRACE_EVENT1("GM", TRACE_FUNC, "name", TRACE_STR_COPY(this->getName()));
this->drawBackground(canvas);
@@ -169,7 +174,7 @@ void GM::drawSizeBounds(SkCanvas* canvas, SkColor color) {
template GMRegistry* GMRegistry::gHead;
DrawResult GpuGM::onDraw(GrContext* ctx, GrRenderTargetContext* rtc, SkCanvas* canvas,
- SkString* errorMsg) {
+ SkString* errorMsg) {
this->onDraw(ctx, rtc, canvas);
return DrawResult::kOk;
}
diff --git a/chromium/third_party/skia/gm/gm.h b/chromium/third_party/skia/gm/gm.h
index 1bebe6b3c2d..b10d740c68c 100644
--- a/chromium/third_party/skia/gm/gm.h
+++ b/chromium/third_party/skia/gm/gm.h
@@ -110,6 +110,8 @@ namespace skiagm {
static constexpr char kErrorMsg_DrawSkippedGpuOnly[] = "This test is for GPU configs only.";
+ DrawResult gpuSetup(GrContext*, SkString* errorMsg);
+
DrawResult draw(SkCanvas* canvas) {
SkString errorMsg;
return this->draw(canvas, &errorMsg);
@@ -152,8 +154,10 @@ namespace skiagm {
virtual std::unique_ptr<verifiers::VerifierList> getVerifiers() const;
protected:
+ // onGpuSetup is called once before any other processing with a direct context.
+ virtual DrawResult onGpuSetup(GrContext*, SkString*) { return DrawResult::kOk; }
virtual void onOnceBeforeDraw();
- virtual DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg);
+ virtual DrawResult onDraw(SkCanvas*, SkString* errorMsg);
virtual void onDraw(SkCanvas*);
virtual SkISize onISize() = 0;
diff --git a/chromium/third_party/skia/gm/gpu_blur_utils.cpp b/chromium/third_party/skia/gm/gpu_blur_utils.cpp
index 0eba7d19790..60dcd22cfdc 100644
--- a/chromium/third_party/skia/gm/gpu_blur_utils.cpp
+++ b/chromium/third_party/skia/gm/gpu_blur_utils.cpp
@@ -9,15 +9,30 @@
#include "include/effects/SkGradientShader.h"
#include "src/core/SkGpuBlurUtils.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/effects/GrXfermodeFragmentProcessor.h"
#include "src/image/SkImage_Base.h"
-DEF_SIMPLE_GPU_GM(gpu_blur_utils, ctx, rtc, canvas, 985, 740) {
- auto srcII = SkImageInfo::Make(80, 80, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+static GrSurfaceProxyView blur(GrContext* ctx,
+ GrSurfaceProxyView src,
+ SkIRect dstB,
+ SkIRect srcB,
+ float sigmaX,
+ float sigmaY,
+ SkTileMode mode) {
+ auto resultRTC =
+ SkGpuBlurUtils::GaussianBlur(ctx, src, GrColorType::kRGBA_8888, kPremul_SkAlphaType,
+ nullptr, dstB, srcB, sigmaX, sigmaY, mode);
+ if (!resultRTC) {
+ return {};
+ }
+ return resultRTC->readSurfaceView();
+};
+
+static void run(GrContext* ctx, GrRenderTargetContext* rtc, bool subsetSrc, bool ref) {
+ auto srcII = SkImageInfo::Make(60, 60, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
auto surf = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kYes, srcII);
GrSurfaceProxyView src;
if (surf) {
@@ -57,57 +72,133 @@ DEF_SIMPLE_GPU_GM(gpu_blur_utils, ctx, rtc, canvas, 985, 740) {
if (!src) {
return;
}
- auto blur = [&](SkIRect dstB, SkIRect srcB, SkTileMode mode) -> GrSurfaceProxyView {
- const SkScalar sigmaX = src.width() /10.f;
- const SkScalar sigmaY = src.height()/10.f;
- auto resultRTC =
- SkGpuBlurUtils::GaussianBlur(ctx, src, GrColorType::kRGBA_8888, kPremul_SkAlphaType,
- nullptr, dstB, srcB, sigmaX, sigmaY, mode);
- if (!resultRTC) {
- return {};
- }
- return resultRTC->readSurfaceView();
- };
- SkVector trans = {};
- rtc->clear(SK_PMColor4fWHITE);
- const SkIRect dstRects[] = {
- SkIRect::MakeSize(src.dimensions()).makeOutset(src.width()/5, src.height()/5),
- SkIRect::MakeXYWH(0, 3*src.height()/4, src.width(), src.height()),
- SkIRect::MakeXYWH(0, src.height(), src.width(), src.height())
- };
+ SkIRect srcRect = SkIRect::MakeSize(src.dimensions());
+ if (subsetSrc) {
+ srcRect = SkIRect::MakeXYWH(2.f*srcRect.width() /8.f,
+ 1.f*srcRect.height()/8.f,
+ 5.f*srcRect.width() /8.f,
+ 6.f*srcRect.height()/8.f);
+ }
+ int srcW = srcRect.width();
+ int srcH = srcRect.height();
+ // Each set of rects is drawn in one test area so they probably should not abut or overlap
+ // to visualize the blurs separately.
+ const std::vector<SkIRect> dstRectSets[] = {
+ // encloses source bounds.
+ {
+ srcRect.makeOutset(srcW/5, srcH/5)
+ },
+
+ // partial overlap from above/below.
+ {
+ SkIRect::MakeXYWH(srcRect.x(), srcRect.y() + 3*srcH/4, srcW, srcH),
+ SkIRect::MakeXYWH(srcRect.x(), srcRect.y() - 3*srcH/4, srcW, srcH)
+ },
+
+ // adjacent to each side of src bounds.
+ {
+ srcRect.makeOffset( 0, srcH),
+ srcRect.makeOffset( srcW, 0),
+ srcRect.makeOffset( 0, -srcH),
+ srcRect.makeOffset(-srcW, 0),
+ },
- const SkIRect srcRects[] = {
- SkIRect::MakeSize(src.dimensions()),
+ // fully outside src bounds in one direction.
+ {
+ SkIRect::MakeXYWH(-6.f*srcW/8.f, -7.f*srcH/8.f, 4.f*srcW/8.f, 20.f*srcH/8.f)
+ .makeOffset(srcRect.topLeft()),
+ SkIRect::MakeXYWH(-1.f*srcW/8.f, -7.f*srcH/8.f, 16.f*srcW/8.f, 2.f*srcH/8.f)
+ .makeOffset(srcRect.topLeft()),
+ SkIRect::MakeXYWH(10.f*srcW/8.f, -3.f*srcH/8.f, 4.f*srcW/8.f, 16.f*srcH/8.f)
+ .makeOffset(srcRect.topLeft()),
+ SkIRect::MakeXYWH(-7.f*srcW/8.f, 14.f*srcH/8.f, 18.f*srcW/8.f, 1.f*srcH/8.f)
+ .makeOffset(srcRect.topLeft()),
+ },
+
+ // outside of src bounds in both directions.
+ {
+ SkIRect::MakeXYWH(-5.f*srcW/8.f, -5.f*srcH/8.f, 2.f*srcW/8.f, 2.f*srcH/8.f)
+ .makeOffset(srcRect.topLeft()),
+ SkIRect::MakeXYWH(-5.f*srcW/8.f, 12.f*srcH/8.f, 2.f*srcW/8.f, 2.f*srcH/8.f)
+ .makeOffset(srcRect.topLeft()),
+ SkIRect::MakeXYWH(12.f*srcW/8.f, -5.f*srcH/8.f, 2.f*srcW/8.f, 2.f*srcH/8.f)
+ .makeOffset(srcRect.topLeft()),
+ SkIRect::MakeXYWH(12.f*srcW/8.f, 12.f*srcH/8.f, 2.f*srcW/8.f, 2.f*srcH/8.f)
+ .makeOffset(srcRect.topLeft()),
+ },
};
const auto& caps = *ctx->priv().caps();
- static constexpr SkScalar kPad = 5;
-
- for (const auto& srcRect : srcRects) {
- SkIRect testArea = SkIRect::MakeSize(srcRect.size());
- testArea.outset(testArea.width(), testArea.height());
- for (const auto& dstRect : dstRects) {
- for (int t = 0; t < kSkTileModeCount; ++t) {
- auto mode = static_cast<SkTileMode>(t);
- GrSamplerState sampler(SkTileModeToWrapMode(mode),
- GrSamplerState::Filter::kNearest);
- SkMatrix m = SkMatrix::MakeTrans(trans.x() - testArea.x(),
- trans.y() - testArea.y());
- // Draw the src subset in the tile mode faded as a reference before drawing the blur
- // on top
- {
- auto fp = GrTextureEffect::MakeSubset(src, kPremul_SkAlphaType, SkMatrix::I(),
- sampler, SkRect::Make(srcRect), caps);
- GrPaint paint;
- paint.addColorFragmentProcessor(std::move(fp));
- static constexpr float kAlpha = 0.2f;
- paint.setColor4f({kAlpha, kAlpha, kAlpha, kAlpha});
- rtc->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, m,
- SkRect::Make(testArea));
+
+ static constexpr SkScalar kPad = 10;
+ SkVector trans = {kPad, kPad};
+
+ rtc->clear(SK_PMColor4fWHITE);
+
+ SkIRect testArea = srcRect;
+ testArea.outset(testArea.width(), testArea.height());
+ for (const auto& dstRectSet : dstRectSets) {
+ for (int t = 0; t < kSkTileModeCount; ++t) {
+ auto mode = static_cast<SkTileMode>(t);
+ GrSamplerState sampler(SkTileModeToWrapMode(mode), GrSamplerState::Filter::kNearest);
+ SkMatrix m = SkMatrix::Translate(trans.x() - testArea.x(), trans.y() - testArea.y());
+ // Draw the src subset in the tile mode faded as a reference before drawing the blur
+ // on top.
+ {
+ auto fp = GrTextureEffect::MakeSubset(src, kPremul_SkAlphaType, SkMatrix::I(),
+ sampler, SkRect::Make(srcRect), caps);
+ GrPaint paint;
+ paint.addColorFragmentProcessor(std::move(fp));
+ static constexpr float kAlpha = 0.2f;
+ paint.setColor4f({kAlpha, kAlpha, kAlpha, kAlpha});
+ rtc->drawRect(nullptr, std::move(paint), GrAA::kNo, m, SkRect::Make(testArea));
+ }
+ // If we're in ref mode we will create a temp image that has the original image
+ // tiled into it and then do a clamp blur with adjusted params that should produce
+ // the same result as the original params.
+ std::unique_ptr<GrRenderTargetContext> refSrc;
+ SkIRect refRect;
+ if (ref) {
+ // Blow up testArea into a much larger rect so that our clamp blur will not
+ // reach anywhere near the edge of our temp surface.
+ refRect = testArea.makeOutset(testArea.width(), testArea.height());
+ refSrc = GrRenderTargetContext::Make(ctx, GrColorType::kRGBA_8888, nullptr,
+ SkBackingFit::kApprox, refRect.size());
+ refSrc->clear(SK_PMColor4fWHITE);
+ // Setup an effect to put the original src rect at the correct logical place
+ // in the temp where the temp's origin is at the top left of refRect.
+ SkMatrix tm = SkMatrix::Translate(refRect.left(), refRect.top());
+ auto fp = GrTextureEffect::MakeSubset(src, kPremul_SkAlphaType, tm, sampler,
+ SkRect::Make(srcRect), caps);
+ GrPaint paint;
+ paint.addColorFragmentProcessor(std::move(fp));
+ refSrc->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
+ SkRect::Make(refRect.size()));
+ }
+ // Do a blur for each dstRect in the set over our testArea-sized background.
+ for (const auto& dstRect : dstRectSet) {
+ // Setup the normal blur args.
+ const SkScalar sigmaX = src.width() / 10.f;
+ const SkScalar sigmaY = src.height() / 10.f;
+ auto blurSrc = src;
+ auto blurMode = mode;
+ auto blurDstRect = dstRect;
+ auto blurSrcRect = srcRect;
+ if (ref) {
+ // Move the dst rect to be relative to our temp surface.
+ blurDstRect = dstRect.makeOffset(-refRect.topLeft());
+ // Our new src is the entire temp containing the tiled original.
+ blurSrcRect = SkIRect::MakeSize(refRect.size());
+ // This shouldn't really matter because we should have made a large enough
+ // temp that the edges don't come into play. But this puts us on a simpler
+ // path through SkGpuBlurUtils.
+ blurMode = SkTileMode::kClamp;
+ blurSrc = refSrc->readSurfaceView();
}
// Blur using the rect and draw on top.
- if (auto blurView = blur(dstRect, srcRect, mode)) {
+ if (auto blurView = blur(ctx, blurSrc, blurDstRect, blurSrcRect, sigmaX, sigmaY,
+ blurMode)) {
auto fp = GrTextureEffect::Make(blurView, kPremul_SkAlphaType, SkMatrix::I(),
sampler, caps);
GrPaint paint;
@@ -117,21 +208,9 @@ DEF_SIMPLE_GPU_GM(gpu_blur_utils, ctx, rtc, canvas, 985, 740) {
SkBlendMode::kSrcOver);
paint.addColorFragmentProcessor(std::move(fp));
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
- rtc->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, m,
+ rtc->fillRectToRect(nullptr, std::move(paint), GrAA::kNo, m,
SkRect::Make(dstRect), SkRect::Make(blurView.dimensions()));
}
- // Show the rect that's being blurred.
- {
- GrPaint paint;
- static constexpr float kAlpha = 0.3f;
- paint.setColor4f({0, 0, 0, kAlpha});
- SkPaint stroke;
- stroke.setStyle(SkPaint::kStroke_Style);
- stroke.setStrokeWidth(1.f);
- GrStyle style(stroke);
- auto srcR = SkRect::Make(srcRect).makeOutset(0.5f, 0.5f);
- rtc->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, m, srcR, &style);
- }
// Show the outline of the dst rect. Mostly for kDecal but also allows visual
// confirmation that the resulting blur is the right size and in the right place.
{
@@ -143,12 +222,36 @@ DEF_SIMPLE_GPU_GM(gpu_blur_utils, ctx, rtc, canvas, 985, 740) {
stroke.setStrokeWidth(1.f);
GrStyle style(stroke);
auto dstR = SkRect::Make(dstRect).makeOutset(0.5f, 0.5f);
- rtc->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, m, dstR, &style);
+ rtc->drawRect(nullptr, std::move(paint), GrAA::kNo, m, dstR, &style);
}
- trans.fX += testArea.width() + kPad;
}
- trans.fX = 0;
- trans.fY += testArea.height() + kPad;
+ // Show the rect that's being blurred.
+ {
+ GrPaint paint;
+ static constexpr float kAlpha = 0.3f;
+ paint.setColor4f({0, 0, 0, kAlpha});
+ SkPaint stroke;
+ stroke.setStyle(SkPaint::kStroke_Style);
+ stroke.setStrokeWidth(1.f);
+ GrStyle style(stroke);
+ auto srcR = SkRect::Make(srcRect).makeOutset(0.5f, 0.5f);
+ rtc->drawRect(nullptr, std::move(paint), GrAA::kNo, m, srcR, &style);
+ }
+ trans.fX += testArea.width() + kPad;
}
+ trans.fX = kPad;
+ trans.fY += testArea.height() + kPad;
}
}
+
+DEF_SIMPLE_GPU_GM(gpu_blur_utils, ctx, rtc, canvas, 765, 955) { run(ctx, rtc, false, false); }
+
+DEF_SIMPLE_GPU_GM(gpu_blur_utils_ref, ctx, rtc, canvas, 765, 955) { run(ctx, rtc, false, true); }
+
+DEF_SIMPLE_GPU_GM(gpu_blur_utils_subset_rect, ctx, rtc, canvas, 485, 730) {
+ run(ctx, rtc, true, false);
+}
+
+DEF_SIMPLE_GPU_GM(gpu_blur_utils_subset_ref, ctx, rtc, canvas, 485, 730) {
+ run(ctx, rtc, true, true);
+}
diff --git a/chromium/third_party/skia/gm/hittestpath.cpp b/chromium/third_party/skia/gm/hittestpath.cpp
index d482e49380c..694b9146cd3 100644
--- a/chromium/third_party/skia/gm/hittestpath.cpp
+++ b/chromium/third_party/skia/gm/hittestpath.cpp
@@ -34,32 +34,40 @@ static void test_hittest(SkCanvas* canvas, const SkPath& path) {
}
}
-DEF_SIMPLE_GM(hittestpath, canvas, 700, 460) {
- SkPath path;
- SkRandom rand;
+DEF_SIMPLE_GM_CAN_FAIL(hittestpath, canvas, errorMsg, 700, 460) {
+ if (canvas->getGrContext()) {
+ // GPU rasterization results vary greatly from platform to platform. We can't use them as
+ // an expected result for our internal SkPath::contains().
+ *errorMsg = "This test is for CPU configs only.";
+ return skiagm::DrawResult::kSkip;
+ }
- int scale = 300;
- for (int i = 0; i < 4; ++i) {
- // get the random values deterministically
- SkScalar randoms[12];
- for (int index = 0; index < (int) SK_ARRAY_COUNT(randoms); ++index) {
- randoms[index] = rand.nextUScalar1();
- }
- path.lineTo(randoms[0] * scale, randoms[1] * scale);
- path.quadTo(randoms[2] * scale, randoms[3] * scale,
- randoms[4] * scale, randoms[5] * scale);
- path.cubicTo(randoms[6] * scale, randoms[7] * scale,
- randoms[8] * scale, randoms[9] * scale,
- randoms[10] * scale, randoms[11] * scale);
+ SkPath path;
+ SkRandom rand;
+
+ int scale = 300;
+ for (int i = 0; i < 4; ++i) {
+ // get the random values deterministically
+ SkScalar randoms[12];
+ for (int index = 0; index < (int) SK_ARRAY_COUNT(randoms); ++index) {
+ randoms[index] = rand.nextUScalar1();
}
+ path.lineTo(randoms[0] * scale, randoms[1] * scale);
+ path.quadTo(randoms[2] * scale, randoms[3] * scale,
+ randoms[4] * scale, randoms[5] * scale);
+ path.cubicTo(randoms[6] * scale, randoms[7] * scale,
+ randoms[8] * scale, randoms[9] * scale,
+ randoms[10] * scale, randoms[11] * scale);
+ }
- path.setFillType(SkPathFillType::kEvenOdd);
- path.offset(SkIntToScalar(20), SkIntToScalar(20));
+ path.setFillType(SkPathFillType::kEvenOdd);
+ path.offset(SkIntToScalar(20), SkIntToScalar(20));
- test_hittest(canvas, path);
+ test_hittest(canvas, path);
- canvas->translate(SkIntToScalar(scale), 0);
- path.setFillType(SkPathFillType::kWinding);
+ canvas->translate(SkIntToScalar(scale), 0);
+ path.setFillType(SkPathFillType::kWinding);
- test_hittest(canvas, path);
+ test_hittest(canvas, path);
+ return skiagm::DrawResult::kOk;
}
diff --git a/chromium/third_party/skia/gm/image_pict.cpp b/chromium/third_party/skia/gm/image_pict.cpp
index 37ecefc8534..b9a9060d137 100644
--- a/chromium/third_party/skia/gm/image_pict.cpp
+++ b/chromium/third_party/skia/gm/image_pict.cpp
@@ -94,7 +94,7 @@ protected:
}
void drawSet(SkCanvas* canvas) const {
- SkMatrix matrix = SkMatrix::MakeTrans(-100, -100);
+ SkMatrix matrix = SkMatrix::Translate(-100, -100);
canvas->drawPicture(fPicture, &matrix, nullptr);
canvas->drawImage(fImage0.get(), 150, 0);
canvas->drawImage(fImage1.get(), 300, 0);
@@ -294,7 +294,7 @@ protected:
}
void drawSet(SkCanvas* canvas) const {
- SkMatrix matrix = SkMatrix::MakeTrans(-100, -100);
+ SkMatrix matrix = SkMatrix::Translate(-100, -100);
canvas->drawPicture(fPicture, &matrix, nullptr);
// Draw the tex first, so it doesn't hit a lucky cache from the raster version. This
diff --git a/chromium/third_party/skia/gm/image_shader.cpp b/chromium/third_party/skia/gm/image_shader.cpp
index cfce7a7ba0a..318dbafb29c 100644
--- a/chromium/third_party/skia/gm/image_shader.cpp
+++ b/chromium/third_party/skia/gm/image_shader.cpp
@@ -122,7 +122,7 @@ protected:
canvas->translate(0, 120);
const SkTileMode tile = SkTileMode::kRepeat;
- const SkMatrix localM = SkMatrix::MakeTrans(-50, -50);
+ const SkMatrix localM = SkMatrix::Translate(-50, -50);
SkPaint paint;
paint.setShader(image->makeShader(tile, tile, &localM));
paint.setAntiAlias(true);
diff --git a/chromium/third_party/skia/gm/imagefilters.cpp b/chromium/third_party/skia/gm/imagefilters.cpp
index 116d69f00e5..09f84fbb038 100644
--- a/chromium/third_party/skia/gm/imagefilters.cpp
+++ b/chromium/third_party/skia/gm/imagefilters.cpp
@@ -134,7 +134,7 @@ static void draw_set(SkCanvas* canvas, sk_sp<SkImageFilter> filters[], int count
canvas->save();
SkRRect rr = SkRRect::MakeRectXY(r.makeOffset(dx, dy), 20, 20);
canvas->clipRRect(rr, true);
- canvas->saveLayer({ &rr.getBounds(), nullptr, filters[i].get(), nullptr, nullptr, 0 });
+ canvas->saveLayer(SkCanvas::SaveLayerRec(&rr.getBounds(), nullptr, filters[i].get(), 0));
canvas->drawColor(0x40FFFFFF);
canvas->restore();
canvas->restore();
diff --git a/chromium/third_party/skia/gm/imagefilterstransformed.cpp b/chromium/third_party/skia/gm/imagefilterstransformed.cpp
index 298dde6cd52..bc91411c6b1 100644
--- a/chromium/third_party/skia/gm/imagefilterstransformed.cpp
+++ b/chromium/third_party/skia/gm/imagefilterstransformed.cpp
@@ -25,7 +25,9 @@
#include "include/core/SkTypes.h"
#include "include/effects/SkGradientShader.h"
#include "include/effects/SkImageFilters.h"
+#include "tools/Resources.h"
#include "tools/ToolUtils.h"
+#include "tools/timer/TimeUtils.h"
#include <utility>
@@ -161,3 +163,56 @@ DEF_SIMPLE_GM(rotate_imagefilter, canvas, 500, 500) {
canvas->translate(0, 150);
}
}
+
+class ImageFilterMatrixWLocalMatrix : public skiagm::GM {
+public:
+
+ // Start at 132 degrees, since that resulted in a skipped draw before the fix to
+ // SkLocalMatrixImageFilter's computeFastBounds() function.
+ ImageFilterMatrixWLocalMatrix() : fDegrees(132.f) {}
+
+protected:
+ SkString onShortName() override {
+ return SkString("imagefilter_matrix_localmatrix");
+ }
+
+ SkISize onISize() override {
+ return SkISize::Make(512, 512);
+ }
+
+ bool onAnimate(double nanos) override {
+ // Animate the rotation angle to ensure the local matrix bounds modifications work
+ // for a variety of transformations.
+ fDegrees = TimeUtils::Scaled(1e-9f * nanos, 360.f);
+ return true;
+ }
+
+ void onOnceBeforeDraw() override {
+ fImage = GetResourceAsImage("images/mandrill_256.png");
+ }
+
+ void onDraw(SkCanvas* canvas) override {
+ SkMatrix localMatrix;
+ localMatrix.preTranslate(128, 128);
+ localMatrix.preScale(2.0f, 2.0f);
+
+ // This matrix applies a rotate around the center of the image (prior to the simulated
+ // hi-dpi 2x device scale).
+ SkMatrix filterMatrix;
+ filterMatrix.setRotate(fDegrees, 64, 64);
+
+ sk_sp<SkImageFilter> filter =
+ SkImageFilter::MakeMatrixFilter(filterMatrix, kLow_SkFilterQuality, nullptr)
+ ->makeWithLocalMatrix(localMatrix);
+
+ SkPaint p;
+ p.setImageFilter(filter);
+ canvas->drawImage(fImage.get(), 128, 128, &p);
+ }
+
+private:
+ SkScalar fDegrees;
+ sk_sp<SkImage> fImage;
+};
+
+DEF_GM(return new ImageFilterMatrixWLocalMatrix();)
diff --git a/chromium/third_party/skia/gm/imagefromyuvtextures.cpp b/chromium/third_party/skia/gm/imagefromyuvtextures.cpp
index f9d28efe22e..bcb153458c0 100644
--- a/chromium/third_party/skia/gm/imagefromyuvtextures.cpp
+++ b/chromium/third_party/skia/gm/imagefromyuvtextures.cpp
@@ -28,7 +28,11 @@
#include "include/private/SkTo.h"
#include "src/core/SkMathPriv.h"
#include "src/core/SkYUVMath.h"
+#include "src/gpu/GrContextPriv.h"
#include "tools/Resources.h"
+#include "tools/gpu/YUVUtils.h"
+
+using sk_gpu_test::YUVABackendReleaseContext;
class GrRenderTargetContext;
@@ -46,11 +50,7 @@ protected:
SkISize onISize() override { return {1420, 610}; }
- void onOnceBeforeDraw() override {
- fRGBABmp = this->createBmpAndPlanes("images/mandrill_32.png", fYUVABmps);
- }
-
- SkBitmap createBmpAndPlanes(const char* name, SkBitmap yuvaBmps[4]) {
+ static SkBitmap CreateBmpAndPlanes(const char* name, SkBitmap yuvaBmps[4]) {
SkBitmap bmp;
if (!GetResourceAsBitmap(name, &bmp)) {
return {};
@@ -120,43 +120,22 @@ protected:
return rgbaBmp;
}
- void createYUVTextures(SkBitmap bmps[4], GrContext* context, GrBackendTexture textures[4]) {
+ static bool CreateYUVBackendTextures(GrContext* context, SkBitmap bmps[4],
+ SkYUVAIndex indices[4],
+ YUVABackendReleaseContext* beContext) {
for (int i = 0; i < 4; ++i) {
- textures[i] = context->createBackendTexture(bmps[i].pixmap(), GrRenderable::kNo,
- GrProtected::kNo);
- }
- }
-
- void createResultTexture(GrContext* context, SkISize size, GrBackendTexture* resultTexture) {
- *resultTexture = context->createBackendTexture(
- size.width(), size.height(), kRGBA_8888_SkColorType, SkColors::kTransparent,
- GrMipMapped::kNo, GrRenderable::kYes, GrProtected::kNo);
- }
-
- void deleteBackendTextures(GrContext* context, GrBackendTexture textures[], int n) {
- if (context->abandoned()) {
- return;
- }
-
- GrFlushInfo flushInfo;
- flushInfo.fFlags = kSyncCpu_GrFlushFlag;
- context->flush(flushInfo);
+ GrBackendTexture tmp = context->createBackendTexture(bmps[i].pixmap(),
+ GrRenderable::kNo,
+ GrProtected::kNo);
+ if (!tmp.isValid()) {
+ return false;
+ }
- for (int i = 0; i < n; ++i) {
- context->deleteBackendTexture(textures[i]);
+ beContext->set(i, tmp);
}
- }
- void onDraw(GrContext* context, GrRenderTargetContext*, SkCanvas* canvas) override {
- GrBackendTexture yuvaTextures[4];
-
- this->createYUVTextures(fYUVABmps, context, yuvaTextures);
- SkYUVAIndex indices[4];
for (int i = 0; i < 4; ++i) {
- if (!yuvaTextures[i].isValid()) {
- return;
- }
- auto chanMask = yuvaTextures[i].getBackendFormat().channelMask();
+ auto chanMask = beContext->beTexture(i).getBackendFormat().channelMask();
// We expect the single channel bitmaps to produce single channel textures.
SkASSERT(chanMask && SkIsPow2(chanMask));
if (chanMask & kGray_SkColorChannelFlag) {
@@ -167,25 +146,107 @@ protected:
indices[i].fIndex = i;
}
- // We remake this image before each draw because if any draw flattens it to RGBA then
- // all subsequent draws use the RGBA texture.
- auto makeImage1 = [&]() {
- return SkImage::MakeFromYUVATextures(context,
- kJPEG_SkYUVColorSpace,
- yuvaTextures,
- indices,
- fRGBABmp.dimensions(),
- kTopLeft_GrSurfaceOrigin);
- };
+ return true;
+ }
+
+ sk_sp<SkImage> makeYUVAImage(GrContext* context) {
+ auto releaseContext = new YUVABackendReleaseContext(context);
+ SkYUVAIndex indices[4];
+
+ if (!CreateYUVBackendTextures(context, fYUVABmps, indices, releaseContext)) {
+ YUVABackendReleaseContext::Unwind(context, releaseContext);
+ return nullptr;
+ }
- GrBackendTexture resultTexture;
- this->createResultTexture(context, fRGBABmp.dimensions(), &resultTexture);
- auto image2 = SkImage::MakeFromYUVTexturesCopyWithExternalBackend(context,
- kJPEG_SkYUVColorSpace,
- yuvaTextures,
- kTopLeft_GrSurfaceOrigin,
- resultTexture);
+ return SkImage::MakeFromYUVATextures(context,
+ kJPEG_SkYUVColorSpace,
+ releaseContext->beTextures(),
+ indices,
+ fRGBABmp.dimensions(),
+ kTopLeft_GrSurfaceOrigin,
+ nullptr,
+ YUVABackendReleaseContext::Release,
+ releaseContext);
+ }
+
+ sk_sp<SkImage> createReferenceImage(GrContext* context) {
+ auto planeReleaseContext = new YUVABackendReleaseContext(context);
+ SkYUVAIndex indices[4];
+ if (!CreateYUVBackendTextures(context, fYUVABmps, indices, planeReleaseContext)) {
+ YUVABackendReleaseContext::Unwind(context, planeReleaseContext);
+ return nullptr;
+ }
+
+ GrBackendTexture resultTexture = context->createBackendTexture(
+ fRGBABmp.dimensions().width(), fRGBABmp.dimensions().height(),
+ kRGBA_8888_SkColorType, SkColors::kTransparent,
+ GrMipMapped::kNo, GrRenderable::kYes, GrProtected::kNo);
+ if (!resultTexture.isValid()) {
+ YUVABackendReleaseContext::Unwind(context, planeReleaseContext);
+ return nullptr;
+ }
+
+ auto rgbaReleaseContext = new YUVABackendReleaseContext(context);
+ rgbaReleaseContext->set(0, resultTexture);
+
+ auto tmp = SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
+ context,
+ kJPEG_SkYUVColorSpace,
+ planeReleaseContext->beTextures(),
+ indices,
+ fRGBABmp.dimensions(),
+ kTopLeft_GrSurfaceOrigin,
+ resultTexture,
+ nullptr,
+ YUVABackendReleaseContext::Release,
+ rgbaReleaseContext);
+ YUVABackendReleaseContext::Unwind(context, planeReleaseContext);
+ return tmp;
+ }
+
+ DrawResult onGpuSetup(GrContext* context, SkString* errorMsg) override {
+ if (!context || context->abandoned()) {
+ return DrawResult::kSkip;
+ }
+
+ SkASSERT(context->priv().asDirectContext());
+
+ fRGBABmp = CreateBmpAndPlanes("images/mandrill_32.png", fYUVABmps);
+
+ // We make a version of this image for each draw because, if any draw flattens it to
+ // RGBA, then all subsequent draws would use the RGBA texture.
+ for (int i = 0; i < kNumImages; ++i) {
+ fYUVAImages[i] = this->makeYUVAImage(context);
+ if (!fYUVAImages[i]) {
+ *errorMsg = "Couldn't create src YUVA image.";
+ return DrawResult::kFail;
+ }
+ }
+
+ fReferenceImage = this->createReferenceImage(context);
+ if (!fReferenceImage) {
+ *errorMsg = "Couldn't create reference YUVA image.";
+ return DrawResult::kFail;
+ }
+
+ // Some backends (e.g., Vulkan) require all work be completed for backend textures
+ // before they are deleted. Since we don't know when we'll next have access to a
+ // direct context, flush all the work now.
+ GrFlushInfo flushInfoSyncCpu;
+ flushInfoSyncCpu.fFlags = kSyncCpu_GrFlushFlag;
+ context->flush(flushInfoSyncCpu);
+ context->submit(true);
+
+ return DrawResult::kOk;
+ }
+
+ SkImage* getYUVAImage(int index) {
+ SkASSERT(index >= 0 && index < kNumImages);
+ return fYUVAImages[index].get();
+ }
+
+ void onDraw(GrContext*, GrRenderTargetContext*, SkCanvas* canvas) override {
auto draw_image = [canvas](SkImage* image, SkFilterQuality fq) -> SkSize {
if (!image) {
return {0, 0};
@@ -225,6 +286,7 @@ protected:
};
canvas->translate(kPad, kPad);
+ int imageIndex = 0;
using DrawSig = SkSize(SkImage* image, SkFilterQuality fq);
using DF = std::function<DrawSig>;
for (const auto& draw : {DF(draw_image), DF(draw_image_rect), DF(draw_image_shader)}) {
@@ -235,12 +297,12 @@ protected:
kMedium_SkFilterQuality, kHigh_SkFilterQuality}) {
canvas->save();
canvas->scale(scale, scale);
- auto s1 = draw(makeImage1().get(), fq);
+ auto s1 = draw(this->getYUVAImage(imageIndex++), fq);
canvas->restore();
canvas->translate(kPad + SkScalarCeilToScalar(scale*s1.width()), 0);
canvas->save();
canvas->scale(scale, scale);
- auto s2 = draw(image2.get(), fq);
+ auto s2 = draw(fReferenceImage.get(), fq);
canvas->restore();
canvas->translate(kPad + SkScalarCeilToScalar(scale*s2.width()), 0);
h = std::max({h, s1.height(), s2.height()});
@@ -249,15 +311,17 @@ protected:
canvas->translate(0, kPad + SkScalarCeilToScalar(scale*h));
}
}
-
- this->deleteBackendTextures(context, &resultTexture, 1);
- this->deleteBackendTextures(context, yuvaTextures, 4);
}
private:
- SkBitmap fRGBABmp;
+ SkBitmap fRGBABmp; // TODO: oddly, it looks like this could just be an SkISize
SkBitmap fYUVABmps[4];
+ // 3 draws x 3 scales x 4 filter qualities
+ static constexpr int kNumImages = 3 * 3 * 4;
+ sk_sp<SkImage> fYUVAImages[kNumImages];
+ sk_sp<SkImage> fReferenceImage;
+
static constexpr SkScalar kPad = 10.0f;
typedef GM INHERITED;
diff --git a/chromium/third_party/skia/gm/localmatriximagefilter.cpp b/chromium/third_party/skia/gm/localmatriximagefilter.cpp
index 9a9902d461b..30186c95750 100644
--- a/chromium/third_party/skia/gm/localmatriximagefilter.cpp
+++ b/chromium/third_party/skia/gm/localmatriximagefilter.cpp
@@ -59,9 +59,9 @@ DEF_SIMPLE_GM(localmatriximagefilter, canvas, 640, 640) {
};
const SkMatrix matrices[] = {
- SkMatrix::MakeScale(SK_ScalarHalf, SK_ScalarHalf),
- SkMatrix::MakeScale(2, 2),
- SkMatrix::MakeTrans(10, 10)
+ SkMatrix::Scale(SK_ScalarHalf, SK_ScalarHalf),
+ SkMatrix::Scale(2, 2),
+ SkMatrix::Translate(10, 10)
};
const SkScalar spacer = image0->width() * 3.0f / 2;
diff --git a/chromium/third_party/skia/gm/localmatriximageshader.cpp b/chromium/third_party/skia/gm/localmatriximageshader.cpp
index d08748dce39..da838e263ec 100644
--- a/chromium/third_party/skia/gm/localmatriximageshader.cpp
+++ b/chromium/third_party/skia/gm/localmatriximageshader.cpp
@@ -34,7 +34,7 @@ static sk_sp<SkImage> make_image(SkCanvas* rootCanvas, SkColor color) {
DEF_SIMPLE_GM(localmatriximageshader, canvas, 250, 250) {
sk_sp<SkImage> redImage = make_image(canvas, SK_ColorRED);
- SkMatrix translate = SkMatrix::MakeTrans(100.0f, 0.0f);
+ SkMatrix translate = SkMatrix::Translate(100.0f, 0.0f);
SkMatrix rotate;
rotate.setRotate(45.0f);
sk_sp<SkShader> redImageShader = redImage->makeShader(&translate);
@@ -72,7 +72,7 @@ DEF_SIMPLE_GM(localmatriximageshader_filtering, canvas, 256, 256) {
auto image = GetResourceAsImage("images/mandrill_256.png");
SkPaint p;
p.setFilterQuality(kHigh_SkFilterQuality);
- SkMatrix m = SkMatrix::MakeScale(2.0f);
+ SkMatrix m = SkMatrix::Scale(2, 2);
p.setShader(image->makeShader()->makeWithLocalMatrix(m));
canvas->drawRect(SkRect::MakeXYWH(0, 0, 256, 256), p);
diff --git a/chromium/third_party/skia/gm/localmatrixshader.cpp b/chromium/third_party/skia/gm/localmatrixshader.cpp
index 08e27e98025..de73ff99600 100644
--- a/chromium/third_party/skia/gm/localmatrixshader.cpp
+++ b/chromium/third_party/skia/gm/localmatrixshader.cpp
@@ -19,6 +19,8 @@
#include "include/core/SkShader.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTypes.h"
+#include "include/effects/SkGradientShader.h"
+#include "tools/Resources.h"
#include "tools/ToolUtils.h"
static sk_sp<SkImage> make_image(SkCanvas* rootCanvas) {
@@ -74,8 +76,8 @@ DEF_SIMPLE_GM(localmatrixshader_nested, canvas, 450, 1200) {
},
};
- static const auto inner = SkMatrix::MakeScale(2, 2),
- outer = SkMatrix::MakeTrans(20, 20);
+ static const auto inner = SkMatrix::Scale(2, 2),
+ outer = SkMatrix::Translate(20, 20);
SkPaint border;
border.setAntiAlias(true);
@@ -109,3 +111,98 @@ DEF_SIMPLE_GM(localmatrixshader_nested, canvas, 450, 1200) {
canvas->scale(2, 2);
drawColumn();
}
+
+DEF_SIMPLE_GM(localmatrixshader_persp, canvas, 542, 266) {
+ auto image = GetResourceAsImage("images/yellow_rose.png");
+
+ SkBitmap downsized;
+ downsized.allocPixels(image->imageInfo().makeWH(128, 128));
+ image->scalePixels(downsized.pixmap(), kLow_SkFilterQuality);
+ image = SkImage::MakeFromBitmap(downsized);
+ SkRect imgRect = SkRect::MakeIWH(image->width(), image->height());
+
+ // scale matrix
+ SkMatrix scale = SkMatrix::Scale(1.f / 5.f, 1.f / 5.f);
+
+ // perspective matrix
+ SkPoint src[4];
+ imgRect.toQuad(src);
+ SkPoint dst[4] = {{0, 10.f},
+ {image->width() + 28.f, -100.f},
+ {image->width() - 28.f, image->height() + 100.f},
+ {0.f, image->height() - 10.f}};
+ SkMatrix persp;
+ SkAssertResult(persp.setPolyToPoly(src, dst, 4));
+
+ // combined persp * scale
+ SkMatrix perspScale = SkMatrix::Concat(persp, scale);
+
+ auto draw = [&](sk_sp<SkShader> shader, bool applyPerspToCTM) {
+ canvas->save();
+ canvas->clipRect(imgRect);
+ if (applyPerspToCTM) {
+ canvas->concat(persp);
+ }
+ SkPaint imgShaderPaint;
+ imgShaderPaint.setShader(std::move(shader));
+ canvas->drawPaint(imgShaderPaint);
+ canvas->restore();
+
+ canvas->translate(10.f + image->width(), 0.f); // advance
+ };
+
+ // SkImageShader
+ canvas->save();
+ // 4 variants that all attempt to apply sample at persp * scale w/ an image shader
+ // 1. scale provided to SkImage::makeShader(...) but drawn with persp
+ auto s1 = image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, &scale);
+ draw(s1, true);
+
+ // 2. persp provided to SkImage::makeShader, then wrapped in scale makeWithLocalMatrix
+ // These pre-concat, so it ends up as persp * scale.
+ auto s2 = image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, &persp)
+ ->makeWithLocalMatrix(scale);
+ draw(s2, false);
+
+ // 3. Providing pre-computed persp*scale to SkImage::makeShader()
+ auto s3 = image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, &perspScale);
+ draw(s3, false);
+
+ // 4. Providing pre-computed persp*scale to makeWithLocalMatrix
+ auto s4 = image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat)
+ ->makeWithLocalMatrix(perspScale);
+ draw(s4, false);
+ canvas->restore();
+
+ canvas->translate(0.f, 10.f + image->height()); // advance to next row
+
+ // SkGradientShader
+ const SkColor kGradColors[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
+ canvas->save();
+ // 1. scale provided to Make, drawn with persp
+ auto g1 = SkGradientShader::MakeRadial({imgRect.centerX(), imgRect.centerY()},
+ imgRect.width() / 2.f, kGradColors, nullptr, 2,
+ SkTileMode::kRepeat, 0, &scale);
+ draw(g1, true);
+
+ // 2. persp provided to Make, then wrapped with makeWithLocalMatrix (pre-concat as before).
+ auto g2 = SkGradientShader::MakeRadial({imgRect.centerX(), imgRect.centerY()},
+ imgRect.width() / 2.f, kGradColors, nullptr, 2,
+ SkTileMode::kRepeat, 0, &persp)
+ ->makeWithLocalMatrix(scale);
+ draw(g2, false);
+
+ // 3. Provide per-computed persp*scale to Make
+ auto g3 = SkGradientShader::MakeRadial({imgRect.centerX(), imgRect.centerY()},
+ imgRect.width() / 2.f, kGradColors, nullptr, 2,
+ SkTileMode::kRepeat, 0, &perspScale);
+ draw(g3, false);
+
+ // 4. Providing pre-computed persp*scale to makeWithLocalMatrix
+ auto g4 = SkGradientShader::MakeRadial({imgRect.centerX(), imgRect.centerY()},
+ imgRect.width() / 2.f, kGradColors, nullptr, 2,
+ SkTileMode::kRepeat)
+ ->makeWithLocalMatrix(perspScale);
+ draw(g4, false);
+ canvas->restore();
+}
diff --git a/chromium/third_party/skia/gm/mac_aa_explorer.cpp b/chromium/third_party/skia/gm/mac_aa_explorer.cpp
index 599973562ed..572ddf59046 100644
--- a/chromium/third_party/skia/gm/mac_aa_explorer.cpp
+++ b/chromium/third_party/skia/gm/mac_aa_explorer.cpp
@@ -50,7 +50,7 @@ static CGContextRef make_cg_ctx(const SkPixmap& pm) {
switch (pm.colorType()) {
case kRGBA_8888_SkColorType:
- info = kCGBitmapByteOrder32Host | kCGImageAlphaNoneSkipFirst;
+ info = kCGBitmapByteOrder32Host | (CGBitmapInfo)kCGImageAlphaNoneSkipFirst;
cs = CGColorSpaceCreateDeviceRGB();
break;
case kGray_8_SkColorType:
diff --git a/chromium/third_party/skia/gm/offsetimagefilter.cpp b/chromium/third_party/skia/gm/offsetimagefilter.cpp
index 7a006cc8c6f..47ed99c99eb 100644
--- a/chromium/third_party/skia/gm/offsetimagefilter.cpp
+++ b/chromium/third_party/skia/gm/offsetimagefilter.cpp
@@ -86,7 +86,7 @@ private:
// Draw a boundary rect around the intersection of the clip rect and crop rect.
SkRect cropRectFloat;
- SkMatrix::MakeScale(scale, scale).mapRect(&cropRectFloat, SkRect::Make(cropRect));
+ SkMatrix::Scale(scale, scale).mapRect(&cropRectFloat, SkRect::Make(cropRect));
if (clipRect.intersect(cropRectFloat)) {
SkPaint strokePaint;
strokePaint.setStyle(SkPaint::kStroke_Style);
diff --git a/chromium/third_party/skia/gm/patheffects.cpp b/chromium/third_party/skia/gm/patheffects.cpp
index 37715f1b361..695d5e24f04 100644
--- a/chromium/third_party/skia/gm/patheffects.cpp
+++ b/chromium/third_party/skia/gm/patheffects.cpp
@@ -237,3 +237,58 @@ private:
};
DEF_GM(return new ComboPathEfectsGM;)
+#include "include/effects/SkStrokeAndFillPathEffect.h"
+
+// Test that we can replicate SkPaint::kStrokeAndFill_Style
+// with a patheffect. We expect the 2nd and 3rd columns to draw the same.
+DEF_SIMPLE_GM(stroke_and_fill_patheffect, canvas, 900, 450) {
+ const float kStrokeWidth = 20;
+
+ typedef void (*Maker)(SkPath*);
+ const Maker makers[] = {
+ [](SkPath* path) {
+ path->addOval({0, 0, 100, 100}, SkPathDirection::kCW);
+ },
+ [](SkPath* path) {
+ path->addOval({0, 0, 100, 100}, SkPathDirection::kCCW);
+ },
+ [](SkPath* path) {
+ path->moveTo(0, 0).lineTo(100, 100).lineTo(0, 100).lineTo(100, 0).close();
+ },
+ };
+
+ const struct {
+ SkPaint::Style fStyle;
+ float fWidth;
+ bool fUsePE;
+ bool fExpectStrokeAndFill;
+ } rec[] = {
+ { SkPaint::kStroke_Style, 0, false, false },
+ { SkPaint::kFill_Style, 0, true, false },
+ { SkPaint::kStroke_Style, 0, true, false },
+ { SkPaint::kStrokeAndFill_Style, kStrokeWidth, false, true },
+ { SkPaint::kStroke_Style, kStrokeWidth, true, true },
+ { SkPaint::kStrokeAndFill_Style, kStrokeWidth, true, true },
+ };
+
+ SkPaint paint;
+ canvas->translate(20, 20);
+ for (auto maker : makers) {
+ SkPath path;
+ maker(&path);
+
+ canvas->save();
+ for (const auto& r : rec) {
+ paint.setStyle(r.fStyle);
+ paint.setStrokeWidth(r.fWidth);
+ paint.setPathEffect(r.fUsePE ? SkStrokeAndFillPathEffect::Make() : nullptr);
+ paint.setColor(r.fExpectStrokeAndFill ? SK_ColorGRAY : SK_ColorBLACK);
+
+ canvas->drawPath(path, paint);
+ canvas->translate(150, 0);
+ }
+ canvas->restore();
+
+ canvas->translate(0, 150);
+ }
+}
diff --git a/chromium/third_party/skia/gm/perspshaders.cpp b/chromium/third_party/skia/gm/perspshaders.cpp
index bcccb4b3270..3092cdf515a 100644
--- a/chromium/third_party/skia/gm/perspshaders.cpp
+++ b/chromium/third_party/skia/gm/perspshaders.cpp
@@ -209,7 +209,7 @@ static SkPath make_path() {
DEF_SIMPLE_GM(perspective_clip, canvas, 800, 800) {
SkPath path = make_path();
auto shader = GetResourceAsImage("images/mandrill_128.png")
- ->makeShader(SkMatrix::MakeScale(3, 3));
+ ->makeShader(SkMatrix::Scale(3, 3));
SkPaint paint;
paint.setColor({0.75, 0.75, 0.75, 1});
diff --git a/chromium/third_party/skia/gm/pictureimagegenerator.cpp b/chromium/third_party/skia/gm/pictureimagegenerator.cpp
index 758b5f51aab..b4534207457 100644
--- a/chromium/third_party/skia/gm/pictureimagegenerator.cpp
+++ b/chromium/third_party/skia/gm/pictureimagegenerator.cpp
@@ -170,7 +170,7 @@ protected:
SkPaint p;
p.setAlphaf(configs[i].opacity);
- SkMatrix m = SkMatrix::MakeScale(configs[i].scaleX, configs[i].scaleY);
+ SkMatrix m = SkMatrix::Scale(configs[i].scaleX, configs[i].scaleY);
if (configs[i].scaleX < 0) {
m.postTranslate(SkIntToScalar(configs[i].size.width()), 0);
}
diff --git a/chromium/third_party/skia/gm/preservefillrule.cpp b/chromium/third_party/skia/gm/preservefillrule.cpp
index 26ff7f67d2c..c5df4da52f3 100644
--- a/chromium/third_party/skia/gm/preservefillrule.cpp
+++ b/chromium/third_party/skia/gm/preservefillrule.cpp
@@ -85,15 +85,15 @@ private:
star7_winding.setFillType(SkPathFillType::kWinding);
SkPath star7_evenOdd = star7_winding;
- star7_evenOdd.transform(SkMatrix::MakeTrans(0, fStarSize));
+ star7_evenOdd.transform(SkMatrix::Translate(0, fStarSize));
star7_evenOdd.setFillType(SkPathFillType::kEvenOdd);
SkPath star5_winding = ToolUtils::make_star(starRect, 5);
- star5_winding.transform(SkMatrix::MakeTrans(fStarSize, 0));
+ star5_winding.transform(SkMatrix::Translate(fStarSize, 0));
star5_winding.setFillType(SkPathFillType::kWinding);
SkPath star5_evenOdd = star5_winding;
- star5_evenOdd.transform(SkMatrix::MakeTrans(0, fStarSize));
+ star5_evenOdd.transform(SkMatrix::Translate(0, fStarSize));
star5_evenOdd.setFillType(SkPathFillType::kEvenOdd);
SkPaint paint;
@@ -106,7 +106,7 @@ private:
canvas->drawPath(star7_evenOdd, paint);
canvas->drawPath(star5_winding, paint);
canvas->drawPath(star5_evenOdd, paint);
- rtc->flush(SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo());
+ rtc->flush(SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo(), nullptr);
// Ensure the path cache is behaving in such a way that we are actually testing what we
// think we are.
diff --git a/chromium/third_party/skia/gm/recordopts.cpp b/chromium/third_party/skia/gm/recordopts.cpp
index 3d0bd161862..2eb58ab4bdc 100644
--- a/chromium/third_party/skia/gm/recordopts.cpp
+++ b/chromium/third_party/skia/gm/recordopts.cpp
@@ -162,7 +162,7 @@ DEF_SIMPLE_GM(recordopts, canvas, (kTestRectSize+1)*2, (kTestRectSize+1)*15) {
TestVariantSequence drawTestSequence = funcs[k];
drawTestSequence(canvas, shapeColor, no_detector_install);
if (context) {
- context->flush();
+ context->flushAndSubmit();
}
canvas->translate(SkIntToScalar(kTestRectSize) + SkIntToScalar(1), SkIntToScalar(0));
{
@@ -172,7 +172,7 @@ DEF_SIMPLE_GM(recordopts, canvas, (kTestRectSize+1)*2, (kTestRectSize+1)*15) {
shapeColor, no_detector_install);
recorder.finishRecordingAsPicture()->playback(canvas);
if (context) {
- context->flush();
+ context->flushAndSubmit();
}
}
canvas->restore();
@@ -207,7 +207,7 @@ DEF_SIMPLE_GM(recordopts, canvas, (kTestRectSize+1)*2, (kTestRectSize+1)*15) {
canvas->save();
drawTestSequence(canvas, shapeColor, detectorInstallFunc);
if (context) {
- context->flush();
+ context->flushAndSubmit();
}
canvas->translate(SkIntToScalar(kTestRectSize) + SkIntToScalar(1), SkIntToScalar(0));
{
@@ -217,7 +217,7 @@ DEF_SIMPLE_GM(recordopts, canvas, (kTestRectSize+1)*2, (kTestRectSize+1)*15) {
shapeColor, detectorInstallFunc);
recorder.finishRecordingAsPicture()->playback(canvas);
if (context) {
- context->flush();
+ context->flushAndSubmit();
}
}
diff --git a/chromium/third_party/skia/gm/rectangletexture.cpp b/chromium/third_party/skia/gm/rectangletexture.cpp
index 9bcc4cde902..246d02beaae 100644
--- a/chromium/third_party/skia/gm/rectangletexture.cpp
+++ b/chromium/third_party/skia/gm/rectangletexture.cpp
@@ -30,15 +30,11 @@
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrContext.h"
#include "include/gpu/GrTypes.h"
-#include "include/gpu/gl/GrGLFunctions.h"
-#include "include/gpu/gl/GrGLInterface.h"
-#include "include/gpu/gl/GrGLTypes.h"
-#include "include/private/GrTypesPriv.h"
+#include "src/core/SkAutoPixmapStorage.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrGpu.h"
-#include "src/gpu/gl/GrGLContext.h"
+#include "src/gpu/gl/GrGLCaps.h"
#include "src/gpu/gl/GrGLDefines.h"
-#include "src/gpu/gl/GrGLUtil.h"
#include <algorithm>
#include <cstdint>
@@ -98,70 +94,38 @@ private:
SkUNREACHABLE;
}
- static const GrGLContext* GetGLContextIfSupported(GrContext* context) {
- if (context->backend() != GrBackendApi::kOpenGL) {
- return nullptr;
- }
- auto* caps = static_cast<const GrGLCaps*>(context->priv().caps());
- if (!caps->rectangleTextureSupport()) {
- return nullptr;
- }
- return context->priv().getGpu()->glContextForTesting();
- }
-
sk_sp<SkImage> createRectangleTextureImg(GrContext* context, GrSurfaceOrigin origin,
const SkBitmap content) {
SkASSERT(content.colorType() == kRGBA_8888_SkColorType);
-
- const GrGLContext* glCtx = GetGLContextIfSupported(context);
- if (!glCtx) {
+ auto format = GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_RECTANGLE);
+ auto bet = context->createBackendTexture(content.width(), content.height(), format,
+ GrMipMapped::kNo, GrRenderable::kNo);
+ if (!bet.isValid()) {
return nullptr;
}
-
- const GrGLInterface* gl = glCtx->glInterface();
- // Useful for debugging whether errors result from use of RECTANGLE
- // static constexpr GrGLenum kTarget = GR_GL_TEXTURE_2D;
- static constexpr GrGLenum kTarget = GR_GL_TEXTURE_RECTANGLE;
- GrGLuint id = 0;
- GR_GL_CALL(gl, GenTextures(1, &id));
- GR_GL_CALL(gl, BindTexture(kTarget, id));
- GR_GL_CALL(gl, TexParameteri(kTarget, GR_GL_TEXTURE_MAG_FILTER, GR_GL_NEAREST));
- GR_GL_CALL(gl, TexParameteri(kTarget, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
- GR_GL_CALL(gl, TexParameteri(kTarget, GR_GL_TEXTURE_WRAP_S, GR_GL_CLAMP_TO_EDGE));
- GR_GL_CALL(gl, TexParameteri(kTarget, GR_GL_TEXTURE_WRAP_T, GR_GL_CLAMP_TO_EDGE));
- std::unique_ptr<uint32_t[]> tempPixels;
- auto src = content.getAddr32(0, 0);
- int h = content.height();
- int w = content.width();
+ const SkPixmap* pm = &content.pixmap();
+ SkAutoPixmapStorage tempPM;
if (origin == kBottomLeft_GrSurfaceOrigin) {
- tempPixels.reset(new uint32_t[w * h]);
- for (int y = 0; y < h; ++y) {
- std::copy_n(src + w*(h - y - 1), w, tempPixels.get() + w*y);
+ tempPM.alloc(pm->info());
+ const uint32_t* src = pm->addr32();
+ uint32_t* dst = tempPM.writable_addr32(0, content.height() - 1);
+ for (int y = 0; y < content.height(); ++y,
+ src += pm->rowBytesAsPixels(),
+ dst -= tempPM.rowBytesAsPixels()) {
+ std::copy_n(src, content.width(), dst);
}
- src = tempPixels.get();
+ pm = &tempPM;
}
- GR_GL_CALL(gl, TexImage2D(kTarget, 0, GR_GL_RGBA, w, h, 0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE,
- src));
-
- context->resetContext();
- GrGLTextureInfo info;
- info.fID = id;
- info.fTarget = kTarget;
- info.fFormat = GR_GL_RGBA8;
-
- GrBackendTexture rectangleTex(w, h, GrMipMapped::kNo, info);
-
- if (sk_sp<SkImage> image = SkImage::MakeFromAdoptedTexture(
- context, rectangleTex, origin, content.colorType(), content.alphaType())) {
- return image;
+ if (!context->updateBackendTexture(bet, pm, 1, nullptr, nullptr)) {
+ context->deleteBackendTexture(bet);
}
- GR_GL_CALL(gl, DeleteTextures(1, &id));
- return nullptr;
+ return SkImage::MakeFromAdoptedTexture(context, bet, origin, kRGBA_8888_SkColorType);
}
DrawResult onDraw(GrContext* context, GrRenderTargetContext*, SkCanvas* canvas,
SkString* errorMsg) override {
- if (!GetGLContextIfSupported(context)) {
+ if (context->backend() != GrBackendApi::kOpenGL_GrBackend ||
+ !static_cast<const GrGLCaps*>(context->priv().caps())->rectangleTextureSupport()) {
*errorMsg = "This GM requires an OpenGL context that supports texture rectangles.";
return DrawResult::kSkip;
}
diff --git a/chromium/third_party/skia/gm/rrects.cpp b/chromium/third_party/skia/gm/rrects.cpp
index bf3b0afb1da..f164f2982e4 100644
--- a/chromium/third_party/skia/gm/rrects.cpp
+++ b/chromium/third_party/skia/gm/rrects.cpp
@@ -120,8 +120,9 @@ protected:
rrect.offset(SkIntToScalar(x), SkIntToScalar(y));
GrClipEdgeType edgeType = (GrClipEdgeType) et;
const auto& caps = *renderTargetContext->caps()->shaderCaps();
- auto fp = GrRRectEffect::Make(edgeType, rrect, caps);
- if (fp) {
+ auto [success, fp] = GrRRectEffect::Make(/*inputFP=*/nullptr,
+ edgeType, rrect, caps);
+ if (success) {
GrPaint grPaint;
grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
grPaint.addCoverageFragmentProcessor(std::move(fp));
diff --git a/chromium/third_party/skia/gm/runtimeshader.cpp b/chromium/third_party/skia/gm/runtimeshader.cpp
index ef5ee712694..63be548cc85 100644
--- a/chromium/third_party/skia/gm/runtimeshader.cpp
+++ b/chromium/third_party/skia/gm/runtimeshader.cpp
@@ -48,8 +48,8 @@ class RuntimeShader : public skiagm::GM {
DEF_GM(return new RuntimeShader;)
static sk_sp<SkShader> make_shader(sk_sp<SkImage> img, SkISize size) {
- SkMatrix scale = SkMatrix::MakeScale(size.width() / (float)img->width(),
- size.height() / (float)img->height());
+ SkMatrix scale = SkMatrix::Scale(size.width() / (float)img->width(),
+ size.height() / (float)img->height());
return img->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, &scale);
}
@@ -102,9 +102,9 @@ class ThresholdRT : public skiagm::GM {
fAfter = make_shader(GetResourceAsImage("images/dog.jpg"), size);
const char code[] = R"(
- in fragmentProcessor before_map;
- in fragmentProcessor after_map;
- in fragmentProcessor threshold_map;
+ in shader before_map;
+ in shader after_map;
+ in shader threshold_map;
uniform float cutoff;
uniform float slope;
@@ -118,7 +118,7 @@ class ThresholdRT : public skiagm::GM {
half4 before = sample(before_map, xy);
half4 after = sample(after_map, xy);
- float m = smooth_cutoff(sample(threshold_map, xy).r);
+ float m = smooth_cutoff(sample(threshold_map, xy).a);
color = mix(before, after, half(m));
}
)";
@@ -135,12 +135,7 @@ class ThresholdRT : public skiagm::GM {
SkISize onISize() override { return {256, 256}; }
- DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
- if (canvas->getGrContext() == nullptr) {
- // until SkSL can handle child processors on the raster backend
- return DrawResult::kSkip;
- }
-
+ void onDraw(SkCanvas* canvas) override {
struct {
float cutoff, slope;
} uni = {
@@ -164,8 +159,6 @@ class ThresholdRT : public skiagm::GM {
draw(256, 0, fThreshold);
draw( 0, 256, fBefore);
draw(256, 256, fAfter);
-
- return DrawResult::kOk;
}
bool onAnimate(double nanos) override {
@@ -237,3 +230,90 @@ class SpiralRT : public skiagm::GM {
}
};
DEF_GM(return new SpiralRT;)
+
+class ColorCubeRT : public skiagm::GM {
+ sk_sp<SkImage> fMandrill, fMandrillSepia, fIdentityCube, fSepiaCube;
+ sk_sp<SkRuntimeEffect> fEffect;
+
+ void onOnceBeforeDraw() override {
+ fMandrill = GetResourceAsImage("images/mandrill_256.png");
+ fMandrillSepia = GetResourceAsImage("images/mandrill_sepia.png");
+ fIdentityCube = GetResourceAsImage("images/lut_identity.png");
+ fSepiaCube = GetResourceAsImage("images/lut_sepia.png");
+
+ const char code[] = R"(
+ in shader input;
+ in shader color_cube;
+
+ uniform float rg_scale;
+ uniform float rg_bias;
+ uniform float b_scale;
+ uniform float inv_size;
+
+ void main(float2 xy, inout half4 color) {
+ float4 c = float4(unpremul(sample(input, xy)));
+
+ // Map to cube coords:
+ float3 cubeCoords = float3(c.rg * rg_scale + rg_bias, c.b * b_scale);
+
+ // Compute slice coordinate
+ float2 coords1 = float2((floor(cubeCoords.b) + cubeCoords.r) * inv_size, cubeCoords.g);
+ float2 coords2 = float2(( ceil(cubeCoords.b) + cubeCoords.r) * inv_size, cubeCoords.g);
+
+ // Two bilinear fetches, plus a manual lerp for the third axis:
+ color = mix(sample(color_cube, coords1), sample(color_cube, coords2),
+ half(fract(cubeCoords.b)));
+
+ // Premul again
+ color.rgb *= color.a;
+ }
+ )";
+ auto [effect, error] = SkRuntimeEffect::Make(SkString(code));
+ if (!effect) {
+ SkDebugf("runtime error %s\n", error.c_str());
+ }
+ fEffect = effect;
+ }
+
+ SkString onShortName() override { return SkString("color_cube_rt"); }
+
+ SkISize onISize() override { return {512, 512}; }
+
+ void onDraw(SkCanvas* canvas) override {
+ // First we draw the unmodified image, and a copy that was sepia-toned in Photoshop:
+ canvas->drawImage(fMandrill, 0, 0);
+ canvas->drawImage(fMandrillSepia, 0, 256);
+
+ // LUT dimensions should be (kSize^2, kSize)
+ constexpr float kSize = 16.0f;
+
+ SkRuntimeShaderBuilder builder(fEffect);
+ builder.input("rg_scale") = (kSize - 1) / kSize;
+ builder.input("rg_bias") = 0.5f / kSize;
+ builder.input("b_scale") = kSize - 1;
+ builder.input("inv_size") = 1.0f / kSize;
+
+ builder.child("input") = fMandrill->makeShader();
+
+ // TODO: Move filter quality to the shader itself. We need to enforce at least kLow here
+ // so that we bilerp the color cube image.
+ SkPaint paint;
+ paint.setFilterQuality(kLow_SkFilterQuality);
+
+ // TODO: Should we add SkImage::makeNormalizedShader() to handle this automatically?
+ SkMatrix normalize = SkMatrix::Scale(1.0f / (kSize * kSize), 1.0f / kSize);
+
+ // Now draw the image with an identity color cube - it should look like the original
+ builder.child("color_cube") = fIdentityCube->makeShader(normalize);
+ paint.setShader(builder.makeShader(nullptr, true));
+ canvas->translate(256, 0);
+ canvas->drawRect({ 0, 0, 256, 256 }, paint);
+
+ // ... and with a sepia-tone color cube. This should match the sepia-toned image.
+ builder.child("color_cube") = fSepiaCube->makeShader(normalize);
+ paint.setShader(builder.makeShader(nullptr, true));
+ canvas->translate(0, 256);
+ canvas->drawRect({ 0, 0, 256, 256 }, paint);
+ }
+};
+DEF_GM(return new ColorCubeRT;)
diff --git a/chromium/third_party/skia/gm/sample_matrix_constant.cpp b/chromium/third_party/skia/gm/sample_matrix_constant.cpp
index 36a3be99364..45e26e67dd6 100644
--- a/chromium/third_party/skia/gm/sample_matrix_constant.cpp
+++ b/chromium/third_party/skia/gm/sample_matrix_constant.cpp
@@ -9,7 +9,6 @@
#include "include/effects/SkGradientShader.h"
#include "src/core/SkMatrixProvider.h"
#include "src/gpu/GrBitmapTextureMaker.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrRenderTargetContextPriv.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
@@ -21,9 +20,12 @@ public:
static constexpr GrProcessor::ClassID CLASS_ID = (GrProcessor::ClassID) 1;
SampleMatrixConstantEffect(std::unique_ptr<GrFragmentProcessor> child)
- : INHERITED(CLASS_ID, kNone_OptimizationFlags) {
- child->setSampleMatrix(SkSL::SampleMatrix(SkSL::SampleMatrix::Kind::kVariable));
- this->registerChildProcessor(std::move(child));
+ : INHERITED(CLASS_ID, kNone_OptimizationFlags) {
+ this->registerChild(std::move(child),
+ SkSL::SampleMatrix::MakeConstUniform(
+ "float3x3(float3(0.5, 0.0, 0.0), "
+ "float3(0.0, 0.5, 0.0), "
+ "float3(0.0, 0.0, 1.0))"));
}
const char* name() const override { return "SampleMatrixConstantEffect"; }
@@ -33,12 +35,8 @@ public:
return nullptr;
}
- void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {
- }
-
- bool onIsEqual(const GrFragmentProcessor& that) const override {
- return this == &that;
- }
+ void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
+ bool onIsEqual(const GrFragmentProcessor& that) const override { return this == &that; }
private:
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
@@ -48,7 +46,7 @@ private:
class GLSLSampleMatrixConstantEffect : public GrGLSLFragmentProcessor {
void emitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
- SkString sample = this->invokeChildWithMatrix(0, args, "float3x3(0.5)");
+ SkString sample = this->invokeChild(0, args);
fragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, sample.c_str());
}
};
@@ -57,43 +55,54 @@ GrGLSLFragmentProcessor* SampleMatrixConstantEffect::onCreateGLSLInstance() cons
return new GLSLSampleMatrixConstantEffect();
}
+DEF_SIMPLE_GPU_GM(sample_matrix_constant, ctx, rtCtx, canvas, 1024, 256) {
+ auto wrap = [](std::unique_ptr<GrFragmentProcessor> baseFP) {
+ return std::unique_ptr<GrFragmentProcessor>(
+ new SampleMatrixConstantEffect(std::move(baseFP)));
+ };
+ auto draw = [rtCtx, &wrap](std::unique_ptr<GrFragmentProcessor> baseFP, int tx, int ty) {
+ auto fp = wrap(std::move(baseFP));
+ GrPaint paint;
+ paint.addColorFragmentProcessor(std::move(fp));
+ rtCtx->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::Translate(tx, ty),
+ SkRect::MakeIWH(256, 256));
+ };
+ auto draw2 = [rtCtx, &wrap](std::unique_ptr<GrFragmentProcessor> baseFP, int tx, int ty) {
+ auto fp = wrap(wrap(std::move(baseFP)));
+ GrPaint paint;
+ paint.addColorFragmentProcessor(std::move(fp));
+ rtCtx->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::Translate(tx, ty),
+ SkRect::MakeIWH(256, 256));
+ };
-DEF_SIMPLE_GPU_GM(sample_matrix_constant, ctx, rtCtx, canvas, 512, 256) {
{
- SkRect bounds = SkRect::MakeIWH(256, 256);
SkBitmap bmp;
GetResourceAsBitmap("images/mandrill_256.png", &bmp);
GrBitmapTextureMaker maker(ctx, bmp, GrImageTexGenPolicy::kDraw);
auto view = maker.view(GrMipMapped::kNo);
std::unique_ptr<GrFragmentProcessor> imgFP =
GrTextureEffect::Make(std::move(view), bmp.alphaType(), SkMatrix());
- auto fp = std::unique_ptr<GrFragmentProcessor>(
- new SampleMatrixConstantEffect(std::move(imgFP)));
-
- GrPaint paint;
- paint.addCoverageFragmentProcessor(std::move(fp));
- rtCtx->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
+ draw(std::move(imgFP), 0, 0);
+ view = maker.view(GrMipMapped::kNo);
+ imgFP =
+ GrTextureEffect::Make(std::move(view), bmp.alphaType(), SkMatrix());
+ draw2(std::move(imgFP), 256, 0);
}
{
- GrPaint paint;
- SkRect bounds = SkRect::MakeLTRB(256, 0, 512, 256);
static constexpr SkColor colors[] = { 0xff00ff00, 0xffff00ff };
- static constexpr SkScalar pos[] = { 0.0f, 1.0f };
- const SkPoint pts[] = {{ 256, 0 }, { 512, 0 }};
+ const SkPoint pts[] = {{ 0, 0 }, { 256, 0 }};
- auto shader = SkGradientShader::MakeLinear(pts, colors, pos,
+ auto shader = SkGradientShader::MakeLinear(pts, colors, nullptr,
SK_ARRAY_COUNT(colors),
- SkTileMode::kRepeat);
+ SkTileMode::kClamp);
SkMatrix matrix;
SkSimpleMatrixProvider matrixProvider(matrix);
GrColorInfo colorInfo;
GrFPArgs args(ctx, matrixProvider, kHigh_SkFilterQuality, &colorInfo);
std::unique_ptr<GrFragmentProcessor> gradientFP = as_SB(shader)->asFragmentProcessor(args);
- auto fp = std::unique_ptr<GrFragmentProcessor>(
- new SampleMatrixConstantEffect(std::move(gradientFP)));
- paint.addCoverageFragmentProcessor(std::move(fp));
- rtCtx->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
+ draw(std::move(gradientFP), 512, 0);
+ gradientFP = as_SB(shader)->asFragmentProcessor(args);
+ draw2(std::move(gradientFP), 768, 0);
}
}
-
diff --git a/chromium/third_party/skia/gm/sample_matrix_variable.cpp b/chromium/third_party/skia/gm/sample_matrix_variable.cpp
index 3b345028b26..185f654e678 100644
--- a/chromium/third_party/skia/gm/sample_matrix_variable.cpp
+++ b/chromium/third_party/skia/gm/sample_matrix_variable.cpp
@@ -9,7 +9,6 @@
#include "include/effects/SkGradientShader.h"
#include "src/core/SkMatrixProvider.h"
#include "src/gpu/GrBitmapTextureMaker.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrRenderTargetContextPriv.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
@@ -20,13 +19,13 @@ class SampleMatrixVariableEffect : public GrFragmentProcessor {
public:
static constexpr GrProcessor::ClassID CLASS_ID = (GrProcessor::ClassID) 2;
- SampleMatrixVariableEffect(std::unique_ptr<GrFragmentProcessor> child, float xOffset,
+ SampleMatrixVariableEffect(std::unique_ptr<GrFragmentProcessor> child,
+ float xOffset,
float yOffset)
- : INHERITED(CLASS_ID, kNone_OptimizationFlags)
- , fXOffset(xOffset)
- , fYOffset(yOffset) {
- child->setSampleMatrix(SkSL::SampleMatrix(SkSL::SampleMatrix::Kind::kVariable));
- this->registerChildProcessor(std::move(child));
+ : INHERITED(CLASS_ID, kNone_OptimizationFlags)
+ , fXOffset(xOffset)
+ , fYOffset(yOffset) {
+ this->registerChild(std::move(child), SkSL::SampleMatrix::MakeVariable());
}
const char* name() const override { return "SampleMatrixVariableEffect"; }
@@ -36,12 +35,8 @@ public:
return nullptr;
}
- void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {
- }
-
- bool onIsEqual(const GrFragmentProcessor& that) const override {
- return this == &that;
- }
+ void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
+ bool onIsEqual(const GrFragmentProcessor& that) const override { return this == &that; }
private:
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
@@ -50,7 +45,6 @@ private:
float fYOffset;
typedef GrFragmentProcessor INHERITED;
-
friend class GLSLSampleMatrixVariableEffect;
};
@@ -74,31 +68,31 @@ GrGLSLFragmentProcessor* SampleMatrixVariableEffect::onCreateGLSLInstance() cons
}
DEF_SIMPLE_GPU_GM(sample_matrix_variable, ctx, rtCtx, canvas, 512, 256) {
+ auto draw = [rtCtx](std::unique_ptr<GrFragmentProcessor> baseFP, float ofsX, float ofsY,
+ int tx, int ty) {
+ auto fp = std::unique_ptr<GrFragmentProcessor>(
+ new SampleMatrixVariableEffect(std::move(baseFP), ofsX, ofsY));
+ GrPaint paint;
+ paint.addColorFragmentProcessor(std::move(fp));
+ rtCtx->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::Translate(tx, ty),
+ SkRect::MakeIWH(256, 256));
+ };
+
{
- SkRect bounds = SkRect::MakeIWH(256, 256);
SkBitmap bmp;
GetResourceAsBitmap("images/mandrill_256.png", &bmp);
GrBitmapTextureMaker maker(ctx, bmp, GrImageTexGenPolicy::kDraw);
auto view = maker.view(GrMipMapped::kNo);
std::unique_ptr<GrFragmentProcessor> imgFP =
GrTextureEffect::Make(std::move(view), bmp.alphaType(), SkMatrix());
- imgFP->setSampleMatrix(SkSL::SampleMatrix::Kind::kVariable);
- auto fp = std::unique_ptr<GrFragmentProcessor>(
- new SampleMatrixVariableEffect(std::move(imgFP), -128, 256));
-
- GrPaint paint;
- paint.addCoverageFragmentProcessor(std::move(fp));
- rtCtx->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
+ draw(std::move(imgFP), -128, 256, 0, 0);
}
{
- GrPaint paint;
- SkRect bounds = SkRect::MakeLTRB(256, 0, 512, 256);
static constexpr SkColor colors[] = { 0xff00ff00, 0xffff00ff };
- static constexpr SkScalar pos[] = { 0.0f, 1.0f };
const SkPoint pts[] = {{ 256, 0 }, { 512, 0 }};
- auto shader = SkGradientShader::MakeLinear(pts, colors, pos,
+ auto shader = SkGradientShader::MakeLinear(pts, colors, nullptr,
SK_ARRAY_COUNT(colors),
SkTileMode::kRepeat);
SkMatrix matrix;
@@ -106,10 +100,6 @@ DEF_SIMPLE_GPU_GM(sample_matrix_variable, ctx, rtCtx, canvas, 512, 256) {
GrColorInfo colorInfo;
GrFPArgs args(ctx, matrixProvider, kHigh_SkFilterQuality, &colorInfo);
std::unique_ptr<GrFragmentProcessor> gradientFP = as_SB(shader)->asFragmentProcessor(args);
- gradientFP->setSampleMatrix(SkSL::SampleMatrix::Kind::kVariable);
- auto fp = std::unique_ptr<GrFragmentProcessor>(
- new SampleMatrixVariableEffect(std::move(gradientFP), -0.5, 1));
- paint.addCoverageFragmentProcessor(std::move(fp));
- rtCtx->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
+ draw(std::move(gradientFP), -0.5f, 1.0f, 256, 0);
}
}
diff --git a/chromium/third_party/skia/gm/samplelocations.cpp b/chromium/third_party/skia/gm/samplelocations.cpp
index 8ae5e0327cd..108fa3de13e 100644
--- a/chromium/third_party/skia/gm/samplelocations.cpp
+++ b/chromium/third_party/skia/gm/samplelocations.cpp
@@ -22,7 +22,6 @@
#include "include/private/SkColorData.h"
#include "src/gpu/GrBuffer.h"
#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrColorSpaceXform.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrGeometryProcessor.h"
@@ -275,7 +274,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();
fProgramInfo = this->createProgramInfo(context->priv().caps(), arena, writeView,
std::move(appliedClip), dstProxyView);
@@ -354,7 +353,7 @@ DrawResult SampleLocationsGM::onDraw(
0xffff>()
);
- offscreenRTC->clear(nullptr, {0,1,0,1}, GrRenderTargetContext::CanClearFullscreen::kYes);
+ offscreenRTC->clear({0,1,0,1});
// Stencil.
offscreenRTC->priv().testingOnly_addDrawOp(
@@ -364,11 +363,11 @@ DrawResult SampleLocationsGM::onDraw(
GrPaint coverPaint;
coverPaint.setColor4f({1,0,0,1});
coverPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrcOver));
- rtc->priv().stencilRect(GrNoClip(), &kStencilCover, std::move(coverPaint), GrAA::kNo,
+ rtc->priv().stencilRect(nullptr, &kStencilCover, std::move(coverPaint), GrAA::kNo,
SkMatrix::I(), SkRect::MakeWH(200, 200));
// Copy offscreen texture to canvas.
- rtc->drawTexture(GrNoClip(), offscreenRTC->readSurfaceView(),
+ rtc->drawTexture(nullptr, offscreenRTC->readSurfaceView(),
offscreenRTC->colorInfo().alphaType(),
GrSamplerState::Filter::kNearest, SkBlendMode::kSrc, SK_PMColor4fWHITE,
{0,0,200,200}, {0,0,200,200}, GrAA::kNo, GrQuadAAFlags::kNone,
diff --git a/chromium/third_party/skia/gm/savelayer.cpp b/chromium/third_party/skia/gm/savelayer.cpp
index 2f619d888f3..9ce7be1cc92 100644
--- a/chromium/third_party/skia/gm/savelayer.cpp
+++ b/chromium/third_party/skia/gm/savelayer.cpp
@@ -50,7 +50,7 @@ static void save_layer_unclipped(SkCanvas* canvas,
SkPaint paint;
paint.setAlphaf(0.25f);
SkRect rect = SkRect::MakeLTRB(l, t, r, b);
- canvas->saveLayer({ &rect, &paint, nullptr, nullptr, nullptr,
+ canvas->saveLayer({ &rect, &paint, nullptr,
(SkCanvas::SaveLayerFlags) SkCanvasPriv::kDontClipToLayer_SaveLayerFlag });
}
@@ -108,8 +108,8 @@ DEF_SIMPLE_GM(picture_savelayer, canvas, 320, 640) {
canvas->translate(100 * i, 0);
auto flag = i ?
(SkCanvas::SaveLayerFlags) SkCanvasPriv::kDontClipToLayer_SaveLayerFlag : 0;
- canvas->saveLayer({ &rect1, &paint1, nullptr, nullptr, nullptr, flag});
- canvas->saveLayer({ &rect2, &paint2, nullptr, nullptr, nullptr, flag});
+ canvas->saveLayer(SkCanvas::SaveLayerRec(&rect1, &paint1, nullptr, flag));
+ canvas->saveLayer(SkCanvas::SaveLayerRec(&rect2, &paint2, nullptr, flag));
canvas->drawRect(rect3, paint3);
canvas->restore();
canvas->restore();
@@ -134,116 +134,6 @@ DEF_SIMPLE_GM(savelayer_initfromprev, canvas, 256, 256) {
canvas->restore();
};
-static void draw_mask(SkCanvas* canvas, int size) {
- const SkScalar cx = size * SK_ScalarHalf,
- cy = cx;
- const SkColor colors[] = { 0x00000000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000,
- 0xffff0000, 0x00000000, 0xffff0000, 0x00000000 };
-
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setShader(SkGradientShader::MakeSweep(cx, cy, colors, nullptr, SK_ARRAY_COUNT(colors)));
- canvas->drawPaint(paint);
-
- paint.setShader(SkGradientShader::MakeRadial({cx, cy}, size / 4, colors, nullptr, 2,
- SkTileMode::kClamp));
- canvas->drawCircle(cx, cy, size / 4, paint);
-}
-
-DEF_SIMPLE_GM(savelayer_clipmask, canvas, 1200, 1200) {
- static constexpr int kSize = 100;
- static constexpr SkRect kLayerBounds = { kSize * 0.25f, kSize * 0.25f,
- kSize * 0.75f, kSize * 0.75f };
- static constexpr struct {
- const SkRect* bounds;
- const SkScalar matrix[9];
- } kConfigs[] = {
- { nullptr, { 1 , 0 , 0, 0 , 1 , 0, 0, 0, 1 } },
- { nullptr, { 2 , 0 , 0, 0 , 2 , 0, 0, 0, 1 } },
- { nullptr, { 2 , 0 , -50, 0 , 2 , -50, 0, 0, 1 } },
- { nullptr, { 0.707f, -0.707f, 50, 0.707f, 0.707f, -20, 0, 0, 1 } },
- { nullptr, { 0.5f , 0 , 25, 0 , 0.5f , 25, 0, 0, 1 } },
-
- { &kLayerBounds, { 1 , 0 , 0, 0 , 1 , 0, 0, 0, 1 } },
- { &kLayerBounds, { 2 , 0 , 0, 0 , 2 , 0, 0, 0, 1 } },
- { &kLayerBounds, { 2 , 0 , -50, 0 , 2 , -50, 0, 0, 1 } },
- { &kLayerBounds, { 0.707f, -0.707f, 50, 0.707f, 0.707f, -20, 0, 0, 1 } },
- { &kLayerBounds, { 0.5f , 0 , 25, 0 , 0.5f , 25, 0, 0, 1 } },
- };
-
- using MaskMakerFunc = sk_sp<SkImage> (*)(int size);
- static const MaskMakerFunc kMaskMakers[] = {
- [](int size) -> sk_sp<SkImage> {
- auto surf = SkSurface::MakeRaster(SkImageInfo::MakeA8(size, size));
- draw_mask(surf->getCanvas(), size);
- return surf->makeImageSnapshot();
- },
-
- [](int size) -> sk_sp<SkImage> {
- auto surf = SkSurface::MakeRasterN32Premul(size, size);
- draw_mask(surf->getCanvas(), size);
- return surf->makeImageSnapshot();
- },
-
- [](int size) -> sk_sp<SkImage> {
- SkPictureRecorder recorder;
- draw_mask(recorder.beginRecording(size, size), size);
- return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
- SkISize::Make(size, size),
- nullptr, nullptr,
- SkImage::BitDepth::kU8,
- SkColorSpace::MakeSRGB());
- }
- };
-
- using PaintMakerFunc = SkPaint (*)();
- static const PaintMakerFunc kPaintMakers[] = {
- []() -> SkPaint { return SkPaint(); },
- []() -> SkPaint {
- SkPaint p; p.setImageFilter(SkImageFilters::Blur(2, 2, nullptr)); return p;
- },
- []() -> SkPaint { SkPaint p; p.setBlendMode(SkBlendMode::kSrcOut); return p; },
- };
-
- canvas->drawColor(0xffcccccc);
-
- SkMatrix clipMatrix;
- SkCanvas::SaveLayerRec rec;
- rec.fClipMatrix = &clipMatrix;
-
- for (const auto& paintMaker : kPaintMakers) {
- auto layerPaint = paintMaker();
- rec.fPaint = &layerPaint;
-
- for (const auto& maskMaker : kMaskMakers) {
- sk_sp<SkImage> mask = maskMaker(kSize);
- rec.fClipMask = mask.get();
-
- canvas->save();
- for (const auto cfg : kConfigs) {
- rec.fBounds = cfg.bounds;
- clipMatrix.set9(cfg.matrix);
- canvas->saveLayer(rec);
-
- SkPaint paint;
- paint.setColor(0xff0000ff);
- canvas->drawRect(SkRect::MakeWH(50, 50), paint);
- paint.setColor(0xffff0000);
- canvas->drawRect(SkRect::MakeXYWH(50, 0, 50, 50), paint);
- paint.setColor(0xff00ff00);
- canvas->drawRect(SkRect::MakeXYWH(50, 50, 50, 50), paint);
- paint.setColor(0xffffff00);
- canvas->drawRect(SkRect::MakeXYWH(0, 50, 50, 50), paint);
-
- canvas->restore();
- canvas->translate(120, 0);
- }
- canvas->restore();
- canvas->translate(0, 120);
- }
- }
-}
-
DEF_SIMPLE_GM(savelayer_coverage, canvas, 500, 500) {
canvas->saveLayer(nullptr, nullptr);
@@ -282,65 +172,6 @@ DEF_SIMPLE_GM(savelayer_coverage, canvas, 500, 500) {
canvas->restore();
}
-DEF_SIMPLE_GM(savelayer_clipmask_maskfilter, canvas, 500, 500) {
- // Offscreen surface for making the clip mask and mask filter images
- auto surf = SkSurface::MakeRaster(SkImageInfo::MakeA8(100, 100));
- SkPaint maskPaint;
- maskPaint.setColor(SK_ColorWHITE);
- maskPaint.setAntiAlias(true);
-
- // Draw a centered circle for the mask filter
- surf->getCanvas()->clear(SK_ColorTRANSPARENT);
- surf->getCanvas()->drawCircle(50.f, 50.f, 50.f, maskPaint);
- auto maskFilterImage = surf->makeImageSnapshot();
- sk_sp<SkMaskFilter> maskFilter = SkShaderMaskFilter::Make(maskFilterImage->makeShader());
-
- // Cut out a cross for the clip mask
- surf->getCanvas()->clear(SK_ColorTRANSPARENT);
- surf->getCanvas()->drawRect(SkRect::MakeLTRB(0.f, 0.f, 40.f, 40.f), maskPaint);
- surf->getCanvas()->drawRect(SkRect::MakeLTRB(60.f, 0.f, 100.f, 40.f), maskPaint);
- surf->getCanvas()->drawRect(SkRect::MakeLTRB(0.f, 60.f, 40.f, 100.f), maskPaint);
- surf->getCanvas()->drawRect(SkRect::MakeLTRB(60.f, 60.f, 100.f, 100.f), maskPaint);
- auto clipMaskImage = surf->makeImageSnapshot();
- SkMatrix clipMatrix = SkMatrix::I();
- SkRect clipBounds = SkRect::MakeWH(100, 100);
-
- // On the main canvas, save a 100x100 layer three times, applying clip mask, mask filter, or
- // both, translating across the GM for each configuration. Since the mask filter is provided
- // on the layer restore paint, it must be ignored by the restore since coverage is not well
- // defined.
- canvas->clear(SK_ColorGRAY);
-
- canvas->translate(25.f, 0.f);
-
- // Clip mask only
- SkCanvas::SaveLayerRec rec;
- rec.fBounds = &clipBounds;
- rec.fClipMask = clipMaskImage.get();
- rec.fClipMatrix = &clipMatrix;
- canvas->saveLayer(rec);
- canvas->clear(SK_ColorWHITE);
- canvas->restore();
-
- canvas->translate(125.f, 0.f);
-
- // Mask filter only (should be ignored, producing a white square)
- maskPaint.setMaskFilter(maskFilter);
- rec.fClipMask = nullptr;
- rec.fPaint = &maskPaint;
- canvas->saveLayer(rec);
- canvas->clear(SK_ColorWHITE);
- canvas->restore();
-
- canvas->translate(125.f, 0.f);
-
- // Both (mask filter is ignored, but clip mask should not, so should look like first draw)
- rec.fClipMask = clipMaskImage.get();
- canvas->saveLayer(rec);
- canvas->clear(SK_ColorWHITE);
- canvas->restore();
-}
-
static void draw_cell(SkCanvas* canvas, sk_sp<SkTextBlob> blob, SkColor c, SkScalar w, SkScalar h,
bool useDrawBehind) {
SkRect r = SkRect::MakeWH(w, h);
diff --git a/chromium/third_party/skia/gm/sharedcorners.cpp b/chromium/third_party/skia/gm/sharedcorners.cpp
index e9f871620d9..5c9b270bcdc 100644
--- a/chromium/third_party/skia/gm/sharedcorners.cpp
+++ b/chromium/third_party/skia/gm/sharedcorners.cpp
@@ -121,7 +121,7 @@ protected:
path.close();
}
SkScalar scale = kBoxSize / std::max(path.getBounds().height(), path.getBounds().width());
- path.transform(SkMatrix::MakeScale(scale, scale));
+ path.transform(SkMatrix::Scale(scale, scale));
this->drawRow(canvas, path);
canvas->translate(0, kBoxSize + kPadSize);
diff --git a/chromium/third_party/skia/gm/strokefill.cpp b/chromium/third_party/skia/gm/strokefill.cpp
index 095da77edfc..0357ef2ffb5 100644
--- a/chromium/third_party/skia/gm/strokefill.cpp
+++ b/chromium/third_party/skia/gm/strokefill.cpp
@@ -21,6 +21,13 @@
#include "src/core/SkTextFormatParams.h"
#include "tools/ToolUtils.h"
+#include "include/effects/SkStrokeAndFillPathEffect.h"
+static void set_strokeandfill(SkPaint* paint) {
+ SkASSERT(paint->getPathEffect() == nullptr);
+ paint->setPathEffect(SkStrokeAndFillPathEffect::Make());
+ paint->setStroke(true);
+}
+
/* Generated on a Mac with:
* paint.setTypeface(SkTypeface::CreateByName("Papyrus"));
* paint.getTextPath("H", 1, 100, 80, &textPath);
@@ -238,107 +245,107 @@ static SkPath hiragino_maru_gothic_pro_dash() {
static void show_bold(SkCanvas* canvas, const char* text,
SkScalar x, SkScalar y, const SkPaint& paint, const SkFont& font) {
- canvas->drawString(text, x, y, font, paint);
- SkFont f(font);
- f.setEmbolden(true);
- canvas->drawString(text, x, y + 120, f, paint);
+ canvas->drawString(text, x, y, font, paint);
+ SkFont f(font);
+ f.setEmbolden(true);
+ canvas->drawString(text, x, y + 120, f, paint);
}
static void path_bold(SkCanvas* canvas, const SkPath& path,
const SkPaint& paint, float textSize) {
- SkPaint p(paint);
- canvas->drawPath(path, p);
- p.setStyle(SkPaint::kStrokeAndFill_Style);
- SkScalar fakeBoldScale = SkScalarInterpFunc(textSize,
- kStdFakeBoldInterpKeys, kStdFakeBoldInterpValues,
- kStdFakeBoldInterpLength);
- SkScalar extra = textSize * fakeBoldScale;
- p.setStrokeWidth(extra);
- canvas->save();
- canvas->translate(0, 120);
- canvas->drawPath(path, p);
- canvas->restore();
+ SkPaint p(paint);
+ canvas->drawPath(path, p);
+ set_strokeandfill(&p);
+ SkScalar fakeBoldScale = SkScalarInterpFunc(textSize,
+ kStdFakeBoldInterpKeys, kStdFakeBoldInterpValues,
+ kStdFakeBoldInterpLength);
+ SkScalar extra = textSize * fakeBoldScale;
+ p.setStrokeWidth(extra);
+ canvas->save();
+ canvas->translate(0, 120);
+ canvas->drawPath(path, p);
+ canvas->restore();
}
DEF_SIMPLE_GM_BG_NAME(strokefill, canvas, 640, 480, SK_ColorWHITE,
SkString("stroke-fill")) {
- SkScalar x = SkIntToScalar(100);
- SkScalar y = SkIntToScalar(88);
+ SkScalar x = SkIntToScalar(100);
+ SkScalar y = SkIntToScalar(88);
- // use the portable typeface to generically test the fake bold code everywhere
- // (as long as the freetype option to do the bolding itself isn't enabled)
- SkFont font(ToolUtils::create_portable_typeface("serif", SkFontStyle()), 100);
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStrokeWidth(SkIntToScalar(5));
+ // use the portable typeface to generically test the fake bold code everywhere
+ // (as long as the freetype option to do the bolding itself isn't enabled)
+ SkFont font(ToolUtils::create_portable_typeface("serif", SkFontStyle()), 100);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStrokeWidth(SkIntToScalar(5));
- // use paths instead of text to test the path data on all platforms, since the
- // Mac-specific font may change or is not available everywhere
- path_bold(canvas, papyrus_hello(), paint, font.getSize());
- path_bold(canvas, hiragino_maru_gothic_pro_dash(), paint, font.getSize());
+ // use paths instead of text to test the path data on all platforms, since the
+ // Mac-specific font may change or is not available everywhere
+ path_bold(canvas, papyrus_hello(), paint, font.getSize());
+ path_bold(canvas, hiragino_maru_gothic_pro_dash(), paint, font.getSize());
- show_bold(canvas, "Hi There", x + SkIntToScalar(430), y, paint, font);
+ show_bold(canvas, "Hi There", x + SkIntToScalar(430), y, paint, font);
- paint.setStyle(SkPaint::kStrokeAndFill_Style);
+ set_strokeandfill(&paint);
- SkPath path;
- path.setFillType(SkPathFillType::kWinding);
- path.addCircle(x, y + SkIntToScalar(200), SkIntToScalar(50), SkPathDirection::kCW);
- path.addCircle(x, y + SkIntToScalar(200), SkIntToScalar(40), SkPathDirection::kCCW);
- canvas->drawPath(path, paint);
+ SkPath path;
+ path.setFillType(SkPathFillType::kWinding);
+ path.addCircle(x, y + SkIntToScalar(200), SkIntToScalar(50), SkPathDirection::kCW);
+ path.addCircle(x, y + SkIntToScalar(200), SkIntToScalar(40), SkPathDirection::kCCW);
+ canvas->drawPath(path, paint);
- SkPath path2;
- path2.setFillType(SkPathFillType::kWinding);
- path2.addCircle(x + SkIntToScalar(120), y + SkIntToScalar(200), SkIntToScalar(50), SkPathDirection::kCCW);
- path2.addCircle(x + SkIntToScalar(120), y + SkIntToScalar(200), SkIntToScalar(40), SkPathDirection::kCW);
- canvas->drawPath(path2, paint);
+ SkPath path2;
+ path2.setFillType(SkPathFillType::kWinding);
+ path2.addCircle(x + SkIntToScalar(120), y + SkIntToScalar(200), SkIntToScalar(50), SkPathDirection::kCCW);
+ path2.addCircle(x + SkIntToScalar(120), y + SkIntToScalar(200), SkIntToScalar(40), SkPathDirection::kCW);
+ canvas->drawPath(path2, paint);
- path2.reset();
- path2.addCircle(x + SkIntToScalar(240), y + SkIntToScalar(200), SkIntToScalar(50), SkPathDirection::kCCW);
- canvas->drawPath(path2, paint);
- SkASSERT(SkPathPriv::CheapIsFirstDirection(path2, SkPathPriv::kCCW_FirstDirection));
+ path2.reset();
+ path2.addCircle(x + SkIntToScalar(240), y + SkIntToScalar(200), SkIntToScalar(50), SkPathDirection::kCCW);
+ canvas->drawPath(path2, paint);
+ SkASSERT(SkPathPriv::CheapIsFirstDirection(path2, SkPathPriv::kCCW_FirstDirection));
- path2.reset();
- SkASSERT(!SkPathPriv::CheapComputeFirstDirection(path2, nullptr));
- path2.addCircle(x + SkIntToScalar(360), y + SkIntToScalar(200), SkIntToScalar(50), SkPathDirection::kCW);
- SkASSERT(SkPathPriv::CheapIsFirstDirection(path2, SkPathPriv::kCW_FirstDirection));
- canvas->drawPath(path2, paint);
+ path2.reset();
+ SkASSERT(!SkPathPriv::CheapComputeFirstDirection(path2, nullptr));
+ path2.addCircle(x + SkIntToScalar(360), y + SkIntToScalar(200), SkIntToScalar(50), SkPathDirection::kCW);
+ SkASSERT(SkPathPriv::CheapIsFirstDirection(path2, SkPathPriv::kCW_FirstDirection));
+ canvas->drawPath(path2, paint);
- SkRect r = SkRect::MakeXYWH(x - SkIntToScalar(50), y + SkIntToScalar(280),
- SkIntToScalar(100), SkIntToScalar(100));
- SkPath path3;
- path3.setFillType(SkPathFillType::kWinding);
- path3.addRect(r, SkPathDirection::kCW);
- r.inset(SkIntToScalar(10), SkIntToScalar(10));
- path3.addRect(r, SkPathDirection::kCCW);
- canvas->drawPath(path3, paint);
+ SkRect r = SkRect::MakeXYWH(x - SkIntToScalar(50), y + SkIntToScalar(280),
+ SkIntToScalar(100), SkIntToScalar(100));
+ SkPath path3;
+ path3.setFillType(SkPathFillType::kWinding);
+ path3.addRect(r, SkPathDirection::kCW);
+ r.inset(SkIntToScalar(10), SkIntToScalar(10));
+ path3.addRect(r, SkPathDirection::kCCW);
+ canvas->drawPath(path3, paint);
- r = SkRect::MakeXYWH(x + SkIntToScalar(70), y + SkIntToScalar(280),
- SkIntToScalar(100), SkIntToScalar(100));
- SkPath path4;
- path4.setFillType(SkPathFillType::kWinding);
- path4.addRect(r, SkPathDirection::kCCW);
- r.inset(SkIntToScalar(10), SkIntToScalar(10));
- path4.addRect(r, SkPathDirection::kCW);
- canvas->drawPath(path4, paint);
+ r = SkRect::MakeXYWH(x + SkIntToScalar(70), y + SkIntToScalar(280),
+ SkIntToScalar(100), SkIntToScalar(100));
+ SkPath path4;
+ path4.setFillType(SkPathFillType::kWinding);
+ path4.addRect(r, SkPathDirection::kCCW);
+ r.inset(SkIntToScalar(10), SkIntToScalar(10));
+ path4.addRect(r, SkPathDirection::kCW);
+ canvas->drawPath(path4, paint);
- r = SkRect::MakeXYWH(x + SkIntToScalar(190), y + SkIntToScalar(280),
- SkIntToScalar(100), SkIntToScalar(100));
- path4.reset();
- SkASSERT(!SkPathPriv::CheapComputeFirstDirection(path4, nullptr));
- path4.addRect(r, SkPathDirection::kCCW);
- SkASSERT(SkPathPriv::CheapIsFirstDirection(path4, SkPathPriv::kCCW_FirstDirection));
- path4.moveTo(0, 0); // test for crbug.com/247770
- canvas->drawPath(path4, paint);
+ r = SkRect::MakeXYWH(x + SkIntToScalar(190), y + SkIntToScalar(280),
+ SkIntToScalar(100), SkIntToScalar(100));
+ path4.reset();
+ SkASSERT(!SkPathPriv::CheapComputeFirstDirection(path4, nullptr));
+ path4.addRect(r, SkPathDirection::kCCW);
+ SkASSERT(SkPathPriv::CheapIsFirstDirection(path4, SkPathPriv::kCCW_FirstDirection));
+ path4.moveTo(0, 0); // test for crbug.com/247770
+ canvas->drawPath(path4, paint);
- r = SkRect::MakeXYWH(x + SkIntToScalar(310), y + SkIntToScalar(280),
- SkIntToScalar(100), SkIntToScalar(100));
- path4.reset();
- SkASSERT(!SkPathPriv::CheapComputeFirstDirection(path4, nullptr));
- path4.addRect(r, SkPathDirection::kCW);
- SkASSERT(SkPathPriv::CheapIsFirstDirection(path4, SkPathPriv::kCW_FirstDirection));
- path4.moveTo(0, 0); // test for crbug.com/247770
- canvas->drawPath(path4, paint);
+ r = SkRect::MakeXYWH(x + SkIntToScalar(310), y + SkIntToScalar(280),
+ SkIntToScalar(100), SkIntToScalar(100));
+ path4.reset();
+ SkASSERT(!SkPathPriv::CheapComputeFirstDirection(path4, nullptr));
+ path4.addRect(r, SkPathDirection::kCW);
+ SkASSERT(SkPathPriv::CheapIsFirstDirection(path4, SkPathPriv::kCW_FirstDirection));
+ path4.moveTo(0, 0); // test for crbug.com/247770
+ canvas->drawPath(path4, paint);
}
DEF_SIMPLE_GM(bug339297, canvas, 640, 480) {
diff --git a/chromium/third_party/skia/gm/swizzle.cpp b/chromium/third_party/skia/gm/swizzle.cpp
new file mode 100644
index 00000000000..2d298b2d726
--- /dev/null
+++ b/chromium/third_party/skia/gm/swizzle.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019 Google LLC.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm/gm.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkMatrix.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkTypes.h"
+#include "include/gpu/GrContext.h"
+#include "src/gpu/GrBitmapTextureMaker.h"
+#include "src/gpu/GrContextPriv.h"
+#include "src/gpu/GrFragmentProcessor.h"
+#include "src/gpu/GrRenderTargetContext.h"
+#include "src/gpu/GrRenderTargetContextPriv.h"
+#include "src/gpu/ops/GrFillRectOp.h"
+#include "tools/Resources.h"
+#include "tools/ToolUtils.h"
+
+DEF_SIMPLE_GPU_GM(swizzle, ctx, rtCtx, canvas, 512, 512) {
+ SkRect bounds = SkRect::MakeIWH(512, 512);
+
+ SkBitmap bmp;
+ GetResourceAsBitmap("images/mandrill_512_q075.jpg", &bmp);
+ GrBitmapTextureMaker maker(ctx, bmp, GrImageTexGenPolicy::kDraw);
+ auto view = maker.view(GrMipMapped::kNo);
+ if (!view) {
+ return;
+ }
+ std::unique_ptr<GrFragmentProcessor> imgFP =
+ GrTextureEffect::Make(std::move(view), bmp.alphaType(), SkMatrix());
+ auto fp = GrFragmentProcessor::SwizzleOutput(std::move(imgFP), GrSwizzle("grb1"));
+
+ GrPaint grPaint;
+ grPaint.addColorFragmentProcessor(std::move(fp));
+
+ rtCtx->priv().testingOnly_addDrawOp(
+ GrFillRectOp::MakeNonAARect(ctx, std::move(grPaint), SkMatrix(), bounds));
+}
diff --git a/chromium/third_party/skia/gm/tessellation.cpp b/chromium/third_party/skia/gm/tessellation.cpp
index 64c4a83410f..bb92397933b 100644
--- a/chromium/third_party/skia/gm/tessellation.cpp
+++ b/chromium/third_party/skia/gm/tessellation.cpp
@@ -92,16 +92,21 @@ private:
return new Impl;
}
- 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;
const SkMatrix fViewMatrix;
};
SkString TessellationTestTriShader::getTessControlShaderGLSL(
- const char* versionAndExtensionDecls, const GrShaderCaps&) const {
+ const GrGLSLPrimitiveProcessor*, const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&, const GrShaderCaps&) const {
SkString code(versionAndExtensionDecls);
code.append(R"(
layout(vertices = 3) out;
@@ -119,7 +124,8 @@ SkString TessellationTestTriShader::getTessControlShaderGLSL(
}
SkString TessellationTestTriShader::getTessEvaluationShaderGLSL(
- const char* versionAndExtensionDecls, const GrShaderCaps&) const {
+ const GrGLSLPrimitiveProcessor*, const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&, const GrShaderCaps&) const {
SkString code(versionAndExtensionDecls);
code.append(R"(
layout(triangles, equal_spacing, cw) in;
@@ -204,16 +210,21 @@ private:
return new Impl;
}
- 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;
const SkMatrix fViewMatrix;
};
SkString TessellationTestRectShader::getTessControlShaderGLSL(
- const char* versionAndExtensionDecls, const GrShaderCaps& caps) const {
+ const GrGLSLPrimitiveProcessor*, const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&, const GrShaderCaps& caps) const {
SkString code(versionAndExtensionDecls);
code.append(R"(
layout(vertices = 1) out;
@@ -235,7 +246,8 @@ SkString TessellationTestRectShader::getTessControlShaderGLSL(
}
SkString TessellationTestRectShader::getTessEvaluationShaderGLSL(
- const char* versionAndExtensionDecls, const GrShaderCaps& caps) const {
+ const GrGLSLPrimitiveProcessor*, const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&, const GrShaderCaps& caps) const {
SkString code(versionAndExtensionDecls);
code.appendf(R"(
layout(quads, equal_spacing, cw) in;
diff --git a/chromium/third_party/skia/gm/texelsubset.cpp b/chromium/third_party/skia/gm/texelsubset.cpp
index d957403c8a4..75d335b4695 100644
--- a/chromium/third_party/skia/gm/texelsubset.cpp
+++ b/chromium/third_party/skia/gm/texelsubset.cpp
@@ -154,7 +154,7 @@ protected:
std::move(fp1),
drawRect,
localRect.makeOffset(kT),
- SkMatrix::MakeTrans(-kT))) {
+ SkMatrix::Translate(-kT))) {
renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
}
@@ -164,7 +164,7 @@ protected:
// rather than a texture subset as a comparison.
drawRect = localRect.makeOffset(x, y);
SkMatrix subsetTextureMatrix = SkMatrix::Concat(
- SkMatrix::MakeTrans(-texelSubset.topLeft()), textureMatrices[tm]);
+ SkMatrix::Translate(-texelSubset.topLeft()), textureMatrices[tm]);
auto fp2 = GrTextureEffect::Make(subsetView, fBitmap.alphaType(),
subsetTextureMatrix,
diff --git a/chromium/third_party/skia/gm/tilemodes_alpha.cpp b/chromium/third_party/skia/gm/tilemodes_alpha.cpp
index 83a6d2f09c0..08a63d035c2 100644
--- a/chromium/third_party/skia/gm/tilemodes_alpha.cpp
+++ b/chromium/third_party/skia/gm/tilemodes_alpha.cpp
@@ -27,7 +27,7 @@ DEF_SIMPLE_GM(tilemodes_alpha, canvas, 512, 512) {
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
SkRect rect = SkRect::MakeXYWH(128 * x + 1, 128 * y + 1, 126, 126);
- SkMatrix matrix = SkMatrix::MakeTrans(rect.x(), rect.y());
+ SkMatrix matrix = SkMatrix::Translate(rect.x(), rect.y());
SkPaint paint(SkColor4f{0, 0, 0, 0.5f});
paint.setShader(image->makeShader(kModes[x], kModes[y], &matrix));
canvas->drawRect(rect, paint);
diff --git a/chromium/third_party/skia/gm/userfont.cpp b/chromium/third_party/skia/gm/userfont.cpp
index c80337315b8..7be73d7768a 100644
--- a/chromium/third_party/skia/gm/userfont.cpp
+++ b/chromium/third_party/skia/gm/userfont.cpp
@@ -16,11 +16,23 @@
#include "tools/Resources.h"
static sk_sp<SkTypeface> make_tf() {
- SkCustomTypefaceBuilder builder(128);
+ SkCustomTypefaceBuilder builder;
SkFont font;
- font.setSize(1.0f);
+ const float upem = font.getTypefaceOrDefault()->getUnitsPerEm();
+
+ // request a big size, to improve precision at the fontscaler level
+ font.setSize(upem);
font.setHinting(SkFontHinting::kNone);
+ // so we can scale our paths back down to 1-point
+ const SkMatrix scale = SkMatrix::Scale(1.0f/upem, 1.0f/upem);
+
+ {
+ SkFontMetrics metrics;
+ font.getMetrics(&metrics);
+ builder.setMetrics(metrics, 1.0f/upem);
+ }
+
// Steal the first 128 chars from the default font
for (SkGlyphID index = 0; index <= 127; ++index) {
SkGlyphID glyph = font.unicharToGlyph(index);
@@ -31,7 +43,7 @@ static sk_sp<SkTypeface> make_tf() {
font.getPath(glyph, &path);
// we use the charcode to be our glyph index, since we have no cmap table
- builder.setGlyph(index, width, path);
+ builder.setGlyph(index, width/upem, path.makeTransform(scale));
}
return builder.detach();
@@ -39,51 +51,70 @@ static sk_sp<SkTypeface> make_tf() {
#include "include/core/SkTextBlob.h"
+static sk_sp<SkTypeface> round_trip(sk_sp<SkTypeface> tf) {
+ auto data = tf->serialize();
+ SkMemoryStream stream(data->data(), data->size());
+ return SkTypeface::MakeDeserialize(&stream);
+}
+
class UserFontGM : public skiagm::GM {
sk_sp<SkTypeface> fTF;
- sk_sp<SkTextBlob> fBlob;
- SkPath fPath;
public:
UserFontGM() {}
void onOnceBeforeDraw() override {
fTF = make_tf();
+ // test serialization
+ fTF = round_trip(fTF);
+ }
- SkFont font(fTF);
- font.setSize(100);
+ static sk_sp<SkTextBlob> make_blob(sk_sp<SkTypeface> tf, float size, float* spacing) {
+ SkFont font(tf);
+ font.setSize(size);
font.setEdging(SkFont::Edging::kAntiAlias);
-
- std::vector<SkGlyphID> array;
- auto expand8to16 = [&](const char str[]) {
- for (int i = 0; str[i]; ++i) {
- array.push_back(str[i]);
- }
- };
-
- expand8to16("User Typeface");
- fBlob = SkTextBlob::MakeFromText(array.data(), array.size() * sizeof(SkGlyphID),
- font, SkTextEncoding::kGlyphID);
-
+ *spacing = font.getMetrics(nullptr);
+ return SkTextBlob::MakeFromString("Typeface", font);
}
bool runAsBench() const override { return true; }
SkString onShortName() override { return SkString("user_typeface"); }
- SkISize onISize() override { return {512, 512}; }
+ SkISize onISize() override { return {810, 452}; }
void onDraw(SkCanvas* canvas) override {
- SkScalar x = 20,
- y = 250;
-
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- canvas->drawRect(fBlob->bounds().makeOffset(x, y), paint);
+ auto waterfall = [&](sk_sp<SkTypeface> tf) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+
+ float spacing;
+ float x = 20,
+ y = 16;
+ for (float size = 9; size <= 100; size *= 1.25f) {
+ auto blob = make_blob(tf, size, &spacing);
+
+ // shared baseline
+ if (tf == nullptr) {
+ paint.setColor(0xFFDDDDDD);
+ canvas->drawRect({0, y, 810, y+1}, paint);
+ }
+
+ paint.setColor(0xFFCCCCCC);
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawRect(blob->bounds().makeOffset(x, y), paint);
+
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setColor(SK_ColorBLACK);
+ canvas->drawTextBlob(blob, x, y, paint);
+
+ y += SkScalarRoundToInt(spacing * 1.25f + 2);
+ }
+ };
- paint.setStyle(SkPaint::kFill_Style);
- paint.setColor(SK_ColorRED);
- canvas->drawTextBlob(fBlob, x, y, paint);
+ waterfall(nullptr);
+ canvas->translate(400, 0);
+ waterfall(fTF);
}
};
DEF_GM(return new UserFontGM;)
diff --git a/chromium/third_party/skia/gm/vertices.cpp b/chromium/third_party/skia/gm/vertices.cpp
index 683ca464a4a..d01bce2b307 100644
--- a/chromium/third_party/skia/gm/vertices.cpp
+++ b/chromium/third_party/skia/gm/vertices.cpp
@@ -41,7 +41,7 @@ static sk_sp<SkShader> make_shader1(SkScalar shaderScale) {
SK_ColorMAGENTA, SK_ColorBLUE, SK_ColorYELLOW,
};
const SkPoint pts[] = {{kShaderSize / 4, 0}, {3 * kShaderSize / 4, kShaderSize}};
- const SkMatrix localMatrix = SkMatrix::MakeScale(shaderScale, shaderScale);
+ const SkMatrix localMatrix = SkMatrix::Scale(shaderScale, shaderScale);
sk_sp<SkShader> grad = SkGradientShader::MakeLinear(pts, colors, nullptr,
SK_ARRAY_COUNT(colors),
@@ -51,8 +51,8 @@ static sk_sp<SkShader> make_shader1(SkScalar shaderScale) {
return shaderScale == 1
? grad
: sk_make_sp<SkLocalMatrixShader>(
- sk_make_sp<SkLocalMatrixShader>(std::move(grad), SkMatrix::MakeTrans(-10, 0)),
- SkMatrix::MakeTrans(10, 0));
+ sk_make_sp<SkLocalMatrixShader>(std::move(grad), SkMatrix::Translate(-10, 0)),
+ SkMatrix::Translate(10, 0));
}
static sk_sp<SkShader> make_shader2() {
@@ -374,8 +374,8 @@ DEF_SIMPLE_GM(vertices_data_lerp, canvas, 256, 256) {
SkPaint paint;
const char* gProg = R"(
- in fragmentProcessor c0;
- in fragmentProcessor c1;
+ in shader c0;
+ in shader c1;
varying float vtx_lerp;
void main(float2 p, inout half4 color) {
half4 col0 = sample(c0, p);
@@ -384,7 +384,7 @@ DEF_SIMPLE_GM(vertices_data_lerp, canvas, 256, 256) {
}
)";
auto [effect, errorText] = SkRuntimeEffect::Make(SkString(gProg));
- SkMatrix scale = SkMatrix::MakeScale(2);
+ SkMatrix scale = SkMatrix::Scale(2, 2);
sk_sp<SkShader> children[] = {
GetResourceAsImage("images/mandrill_256.png")->makeShader(),
GetResourceAsImage("images/color_wheel.png")->makeShader(scale),
@@ -544,7 +544,7 @@ static sk_sp<SkVertices> make_cone(Attr::Usage u, const char* markerName) {
return builder.detach();
}
-DEF_SIMPLE_GM(vertices_custom_matrices, canvas, 400, 300) {
+DEF_SIMPLE_GM(vertices_custom_matrices, canvas, 400, 400) {
ToolUtils::draw_checkerboard(canvas);
const char* kViewSpace = "local_to_view";
@@ -600,4 +600,29 @@ DEF_SIMPLE_GM(vertices_custom_matrices, canvas, 400, 300) {
draw(150, 250, make_cone(Attr::Usage::kVector, kWorldSpace), vectorProg, 0.5f);
draw(250, 250, make_cone(Attr::Usage::kNormalVector, kWorldSpace), vectorProg, 0.5f);
draw(350, 250, make_cone(Attr::Usage::kPosition, kWorldSpace), vectorProg, 0.5f);
+
+ draw( 50, 350, make_cone(Attr::Usage::kVector, nullptr), vectorProg, 0.5f);
+ draw(150, 350, make_cone(Attr::Usage::kNormalVector, nullptr), vectorProg, 0.5f);
+
+ // For canvas-space positions, color them according to their position relative to the center.
+ // We do this test twice, with and without saveLayer. That ensures that we get the canvas CTM,
+ // not just a local-to-device matrix, which exposes effect authors to an implementation detail.
+
+ const char* ctmPositionProg250 = R"(
+ varying float3 vtx_pos;
+ void main(float2 p, inout half4 color) {
+ color.rgb = (half3(vtx_pos) - half3(250, 350, 0)) / 50 + 0.5;
+ }
+ )";
+ draw(250, 350, make_cone(Attr::Usage::kPosition, nullptr), ctmPositionProg250, 0.5f);
+
+ const char* ctmPositionProg350 = R"(
+ varying float3 vtx_pos;
+ void main(float2 p, inout half4 color) {
+ color.rgb = (half3(vtx_pos) - half3(350, 350, 0)) / 50 + 0.5;
+ }
+ )";
+ canvas->saveLayer({ 300, 300, 400, 400 }, nullptr);
+ draw(350, 350, make_cone(Attr::Usage::kPosition, nullptr), ctmPositionProg350, 0.5f);
+ canvas->restore();
}
diff --git a/chromium/third_party/skia/gm/wacky_yuv_formats.cpp b/chromium/third_party/skia/gm/wacky_yuv_formats.cpp
index bb4f82c78ea..9df0bef173b 100644
--- a/chromium/third_party/skia/gm/wacky_yuv_formats.cpp
+++ b/chromium/third_party/skia/gm/wacky_yuv_formats.cpp
@@ -47,6 +47,7 @@
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrGpu.h"
#include "tools/ToolUtils.h"
+#include "tools/gpu/YUVUtils.h"
#include <math.h>
#include <string.h>
@@ -54,6 +55,7 @@
#include <memory>
#include <utility>
+using sk_gpu_test::YUVABackendReleaseContext;
class GrRenderTargetContext;
static const int kTileWidthHeight = 128;
@@ -1125,7 +1127,7 @@ protected:
kLabelHeight + numRows * (wh + kPad));
}
- void onOnceBeforeDraw() override {
+ void createBitmaps() {
SkPoint origin = { kTileWidthHeight/2.0f, kTileWidthHeight/2.0f };
float outerRadius = kTileWidthHeight/2.0f - 20.0f;
float innerRadius = 20.0f;
@@ -1158,11 +1160,14 @@ protected:
const SkYUVAIndex yuvaIndices[4],
int numTextures,
SkISize imageSize) {
- GrBackendTexture shrunkTextures[4];
+ auto releaseContext = new YUVABackendReleaseContext(context);
for (int i = 0; i < numTextures; ++i) {
- SkColorType ct = get_color_type(yuvaTextures[i].getBackendFormat());
+ const GrBackendTexture& curTex = yuvaTextures[i];
+
+ SkColorType ct = get_color_type(curTex.getBackendFormat());
if (ct == kUnknown_SkColorType || !context->colorTypeSupportedAsSurface(ct)) {
+ YUVABackendReleaseContext::Unwind(context, releaseContext);
return nullptr;
}
@@ -1170,33 +1175,35 @@ protected:
// We disallow resizing AYUV and Y410 formats on the GPU bc resizing them w/ a
// premul draw combines the YUV channels w/ the A channel in an inappropriate
// manner.
+ YUVABackendReleaseContext::Unwind(context, releaseContext);
return nullptr;
}
- SkISize shrunkPlaneSize = { yuvaTextures[i].width() / 2, yuvaTextures[i].height() / 2 };
+ SkISize shrunkPlaneSize = {curTex.width() / 2, curTex.height() / 2 };
- sk_sp<SkImage> wrappedOrig = SkImage::MakeFromTexture(context, yuvaTextures[i],
+ sk_sp<SkImage> wrappedOrig = SkImage::MakeFromTexture(context, curTex,
kTopLeft_GrSurfaceOrigin,
ct,
kPremul_SkAlphaType,
nullptr);
- shrunkTextures[i] = context->createBackendTexture(shrunkPlaneSize.width(),
- shrunkPlaneSize.height(),
- yuvaTextures[i].getBackendFormat(),
- GrMipMapped::kNo,
- GrRenderable::kYes);
- if (!shrunkTextures[i].isValid()) {
+ GrBackendTexture tmp = context->createBackendTexture(shrunkPlaneSize.width(),
+ shrunkPlaneSize.height(),
+ curTex.getBackendFormat(),
+ GrMipMapped::kNo,
+ GrRenderable::kYes);
+ if (!tmp.isValid()) {
+ YUVABackendReleaseContext::Unwind(context, releaseContext);
return nullptr;
}
- // Store this away so it will be cleaned up at the end.
- fBackendTextures.push_back(shrunkTextures[i]);
+ releaseContext->set(i, tmp);
- sk_sp<SkSurface> s = SkSurface::MakeFromBackendTexture(context, shrunkTextures[i],
+ sk_sp<SkSurface> s = SkSurface::MakeFromBackendTexture(context, tmp,
kTopLeft_GrSurfaceOrigin, 0,
ct, nullptr, nullptr);
if (!s) {
+ YUVABackendReleaseContext::Unwind(context, releaseContext);
return nullptr;
}
SkCanvas* c = s->getCanvas();
@@ -1208,20 +1215,23 @@ protected:
SkRect::MakeWH(shrunkPlaneSize.width(), shrunkPlaneSize.height()),
&paint);
- s->flush();
+ s->flushAndSubmit();
}
SkISize shrunkImageSize = { imageSize.width() / 2, imageSize.height() / 2 };
return SkImage::MakeFromYUVATextures(context,
yuvColorSpace,
- shrunkTextures,
+ releaseContext->beTextures(),
yuvaIndices,
shrunkImageSize,
- kTopLeft_GrSurfaceOrigin);
+ kTopLeft_GrSurfaceOrigin,
+ nullptr,
+ YUVABackendReleaseContext::Release,
+ releaseContext);
}
- void createImages(GrContext* context) {
+ bool createImages(GrContext* context) {
int counter = 0;
for (bool opaque : { false, true }) {
for (int cs = kJPEG_SkYUVColorSpace; cs <= kLastEnum_SkYUVColorSpace; ++cs) {
@@ -1235,30 +1245,33 @@ protected:
int numTextures = create_YUV(planes, format, resultBMs, opaque);
if (context) {
+ fGpuGeneratedImages = true;
+
if (context->abandoned()) {
- return;
+ return false;
}
if (!is_format_natively_supported(context, format)) {
continue;
}
- GrBackendTexture yuvaTextures[4];
- SkPixmap yuvaPixmaps[4];
+ auto releaseContext = new YUVABackendReleaseContext(context);
for (int i = 0; i < numTextures; ++i) {
- yuvaTextures[i] = create_yuva_texture(context, resultBMs[i]);
- if (yuvaTextures[i].isValid()) {
- fBackendTextures.push_back(yuvaTextures[i]);
+ GrBackendTexture tmp = create_yuva_texture(context, resultBMs[i]);
+ if (!tmp.isValid()) {
+ YUVABackendReleaseContext::Unwind(context, releaseContext);
+ return false;
}
- yuvaPixmaps[i] = resultBMs[i].pixmap();
+ releaseContext->set(i, tmp);
}
SkYUVAIndex yuvaIndices[4];
const auto& planarConfig = YUVAFormatPlanarConfig(format);
bool externalAlphaPlane = !opaque && !planarConfig.hasAlpha();
- if (!planarConfig.getYUVAIndices(yuvaTextures, numTextures,
+ if (!planarConfig.getYUVAIndices(releaseContext->beTextures(), numTextures,
externalAlphaPlane, yuvaIndices)) {
+ YUVABackendReleaseContext::Unwind(context, releaseContext);
continue;
}
@@ -1268,10 +1281,11 @@ protected:
format,
(SkYUVColorSpace)cs,
opaque,
- yuvaTextures,
+ releaseContext->beTextures(),
yuvaIndices,
numTextures,
fOriginalBMs[opaque].dimensions());
+ YUVABackendReleaseContext::Unwind(context, releaseContext);
} else {
int counterMod = counter % 3;
if (fUseDomain && counterMod == 0) {
@@ -1280,35 +1294,51 @@ protected:
counterMod = 1;
}
+ const SkISize imgSize { fOriginalBMs[opaque].width(),
+ fOriginalBMs[opaque].height() };
+
switch (counterMod) {
- case 0:
- fImages[opaque][cs][format] = SkImage::MakeFromYUVATexturesCopy(
- context,
- (SkYUVColorSpace)cs,
- yuvaTextures,
- yuvaIndices,
- { fOriginalBMs[opaque].width(), fOriginalBMs[opaque].height() },
- kTopLeft_GrSurfaceOrigin);
- break;
- case 1:
- fImages[opaque][cs][format] = SkImage::MakeFromYUVATextures(
- context,
- (SkYUVColorSpace)cs,
- yuvaTextures,
- yuvaIndices,
- { fOriginalBMs[opaque].width(), fOriginalBMs[opaque].height() },
- kTopLeft_GrSurfaceOrigin);
- break;
- case 2:
- default:
- fImages[opaque][cs][format] = SkImage::MakeFromYUVAPixmaps(
- context,
- (SkYUVColorSpace)cs,
- yuvaPixmaps,
- yuvaIndices,
- { fOriginalBMs[opaque].width(), fOriginalBMs[opaque].height() },
- kTopLeft_GrSurfaceOrigin, true);
- break;
+ case 0:
+ fImages[opaque][cs][format] = SkImage::MakeFromYUVATexturesCopy(
+ context,
+ (SkYUVColorSpace)cs,
+ releaseContext->beTextures(),
+ yuvaIndices,
+ imgSize,
+ kTopLeft_GrSurfaceOrigin);
+ YUVABackendReleaseContext::Unwind(context, releaseContext);
+ break;
+ case 1:
+ fImages[opaque][cs][format] = SkImage::MakeFromYUVATextures(
+ context,
+ (SkYUVColorSpace)cs,
+ releaseContext->beTextures(),
+ yuvaIndices,
+ imgSize,
+ kTopLeft_GrSurfaceOrigin,
+ nullptr,
+ YUVABackendReleaseContext::Release,
+ releaseContext);
+ break;
+ case 2:
+ default: {
+ // TODO: we did a lot of work to delete these here
+ YUVABackendReleaseContext::Unwind(context, releaseContext);
+
+ SkPixmap yuvaPixmaps[4];
+ for (int i = 0; i < numTextures; ++i) {
+ yuvaPixmaps[i] = resultBMs[i].pixmap();
+ }
+
+ fImages[opaque][cs][format] = SkImage::MakeFromYUVAPixmaps(
+ context,
+ (SkYUVColorSpace)cs,
+ yuvaPixmaps,
+ yuvaIndices,
+ imgSize,
+ kTopLeft_GrSurfaceOrigin, true);
+ break;
+ }
}
++counter;
}
@@ -1322,11 +1352,38 @@ protected:
}
}
}
+
+ if (context) {
+ // Some backends (e.g., Vulkan) require all work be completed for backend textures
+ // before they are deleted. Since we don't know when we'll next have access to a
+ // direct context, flush all the work now.
+ GrFlushInfo flushInfoSyncCpu;
+ flushInfoSyncCpu.fFlags = kSyncCpu_GrFlushFlag;
+ context->flush(flushInfoSyncCpu);
+ context->submit(true);
+ }
+
+ return true;
}
- void onDraw(SkCanvas* canvas) override {
- this->createImages(canvas->getGrContext());
+ DrawResult onGpuSetup(GrContext* context, SkString* errorMsg) override {
+ this->createBitmaps();
+ if (context && context->abandoned()) {
+ // This isn't a GpuGM so a null 'context' is okay but an abandoned context
+ // if forbidden.
+ return DrawResult::kSkip;
+ }
+
+ if (!this->createImages(context)) {
+ *errorMsg = "Failed to create YUV images";
+ return DrawResult::kFail;
+ }
+
+ return DrawResult::kOk;
+ }
+
+ void onDraw(SkCanvas* canvas) override {
float cellWidth = kTileWidthHeight, cellHeight = kTileWidthHeight;
if (fUseDomain) {
cellWidth *= 1.5f;
@@ -1338,7 +1395,7 @@ protected:
SkRect srcRect = SkRect::MakeWH(fOriginalBMs[0].width(), fOriginalBMs[0].height());
SkRect dstRect = SkRect::MakeXYWH(kLabelWidth, 0.f, srcRect.width(), srcRect.height());
if (fQuarterSize) {
- if (canvas->getGrContext()) {
+ if (fGpuGeneratedImages) {
// The src is only shrunk on the GPU
srcRect = SkRect::MakeWH(fOriginalBMs[0].width()/2.0f,
fOriginalBMs[0].height()/2.0f);
@@ -1396,29 +1453,16 @@ protected:
dstRect.offset(cellWidth + kPad, 0.f);
}
}
- if (auto context = canvas->getGrContext()) {
- if (!context->abandoned()) {
- context->flush();
- GrGpu* gpu = context->priv().getGpu();
- SkASSERT(gpu);
- gpu->testingOnly_flushGpuAndSync();
- for (const auto& tex : fBackendTextures) {
- context->deleteBackendTexture(tex);
- }
- fBackendTextures.reset();
- }
- }
- SkASSERT(!fBackendTextures.count());
}
private:
SkBitmap fOriginalBMs[2];
sk_sp<SkImage> fImages[2][kLastEnum_SkYUVColorSpace + 1][kLast_YUVFormat + 1];
- SkTArray<GrBackendTexture> fBackendTextures;
bool fUseTargetColorSpace;
bool fUseDomain;
bool fQuarterSize;
sk_sp<SkColorSpace> fTargetColorSpace;
+ bool fGpuGeneratedImages = false;
typedef GM INHERITED;
};
@@ -1443,12 +1487,12 @@ protected:
SkISize onISize() override {
int numCols = 4; // (transparent, opaque) x (untagged, tagged)
- int numRows = 5; // original, YUV, subset, readPixels, makeNonTextureImage
+ int numRows = 5; // original, YUV, subset, makeNonTextureImage, readPixels
return SkISize::Make(numCols * (kTileWidthHeight + kPad) + kPad,
numRows * (kTileWidthHeight + kPad) + kPad);
}
- void onOnceBeforeDraw() override {
+ void createBitmaps() {
SkPoint origin = { kTileWidthHeight/2.0f, kTileWidthHeight/2.0f };
float outerRadius = kTileWidthHeight/2.0f - 20.0f;
float innerRadius = 20.0f;
@@ -1470,7 +1514,7 @@ protected:
fTargetColorSpace = SkColorSpace::MakeSRGB()->makeColorSpin();
}
- void createImages(GrContext* context) {
+ bool createImages(GrContext* context) {
for (bool opaque : { false, true }) {
PlaneData planes;
extract_planes(fOriginalBMs[opaque], kJPEG_SkYUVColorSpace, &planes);
@@ -1482,36 +1526,81 @@ protected:
auto& planarConfig = YUVAFormatPlanarConfig(kAYUV_YUVFormat);
int numPlanes = planarConfig.numPlanes();
- GrBackendTexture yuvaTextures[4];
+ auto releaseContext = new YUVABackendReleaseContext(context);
+ auto srgbReleaseContext = new YUVABackendReleaseContext(context);
+
for (int i = 0; i < numPlanes; ++i) {
- yuvaTextures[i] = create_yuva_texture(context, resultBMs[i]);
- if (yuvaTextures[i].isValid()) {
- fBackendTextures.push_back(yuvaTextures[i]);
+ GrBackendTexture tmp = create_yuva_texture(context, resultBMs[i]);
+ if (!tmp.isValid()) {
+ YUVABackendReleaseContext::Unwind(context, releaseContext);
+ YUVABackendReleaseContext::Unwind(context, srgbReleaseContext);
+ return false;
+ }
+
+ releaseContext->set(i, tmp);
+
+ tmp = create_yuva_texture(context, resultBMs[i]);
+ if (!tmp.isValid()) {
+ YUVABackendReleaseContext::Unwind(context, releaseContext);
+ YUVABackendReleaseContext::Unwind(context, srgbReleaseContext);
+ return false;
}
+
+ srgbReleaseContext->set(i, tmp);
}
SkYUVAIndex yuvaIndices[4];
- planarConfig.getYUVAIndices(yuvaTextures, numPlanes, false, yuvaIndices);
+ planarConfig.getYUVAIndices(releaseContext->beTextures(), numPlanes,
+ false, yuvaIndices);
+
fImages[opaque][0] = SkImage::MakeFromYUVATextures(
context,
kJPEG_SkYUVColorSpace,
- yuvaTextures,
+ releaseContext->beTextures(),
yuvaIndices,
{ fOriginalBMs[opaque].width(), fOriginalBMs[opaque].height() },
- kTopLeft_GrSurfaceOrigin);
+ kTopLeft_GrSurfaceOrigin, nullptr,
+ YUVABackendReleaseContext::Release, releaseContext);
fImages[opaque][1] = SkImage::MakeFromYUVATextures(
context,
kJPEG_SkYUVColorSpace,
- yuvaTextures,
+ srgbReleaseContext->beTextures(),
yuvaIndices,
{ fOriginalBMs[opaque].width(), fOriginalBMs[opaque].height() },
kTopLeft_GrSurfaceOrigin,
- SkColorSpace::MakeSRGB());
+ SkColorSpace::MakeSRGB(),
+ YUVABackendReleaseContext::Release, srgbReleaseContext);
}
+
+ // Some backends (e.g., Vulkan) require all work be completed for backend textures before
+ // they are deleted. Since we don't know when we'll next have access to a direct context,
+ // flush all the work now.
+ GrFlushInfo flushInfoSyncCpu;
+ flushInfoSyncCpu.fFlags = kSyncCpu_GrFlushFlag;
+ context->flush(flushInfoSyncCpu);
+ context->submit(true);
+
+ return true;
+ }
+
+ DrawResult onGpuSetup(GrContext* context, SkString* errorMsg) override {
+ if (!context || context->abandoned()) {
+ return DrawResult::kSkip;
+ }
+
+ SkASSERT(context->priv().asDirectContext());
+
+ this->createBitmaps();
+ if (!this->createImages(context)) {
+ *errorMsg = "Failed to create YUV images";
+ return DrawResult::kFail;
+ }
+
+ return DrawResult::kOk;
}
void onDraw(GrContext* context, GrRenderTargetContext*, SkCanvas* canvas) override {
- this->createImages(context);
+ SkASSERT(fImages[0][0] && fImages[0][1] && fImages[1][0] && fImages[1][1]);
int x = kPad;
for (int tagged : { 0, 1 }) {
@@ -1530,7 +1619,7 @@ protected:
y += kTileWidthHeight + kPad;
auto subset = yuv->makeSubset(SkIRect::MakeWH(kTileWidthHeight / 2,
- kTileWidthHeight / 2));
+ kTileWidthHeight / 2));
canvas->drawImage(subset, x, y);
y += kTileWidthHeight + kPad;
@@ -1546,21 +1635,11 @@ protected:
x += kTileWidthHeight + kPad;
}
}
-
- context->flush();
- GrGpu* gpu = context->priv().getGpu();
- SkASSERT(gpu);
- gpu->testingOnly_flushGpuAndSync();
- for (const auto& tex : fBackendTextures) {
- context->deleteBackendTexture(tex);
- }
- fBackendTextures.reset();
}
private:
SkBitmap fOriginalBMs[2];
sk_sp<SkImage> fImages[2][2];
- SkTArray<GrBackendTexture> fBackendTextures;
sk_sp<SkColorSpace> fTargetColorSpace;
typedef GM INHERITED;
diff --git a/chromium/third_party/skia/gm/widebuttcaps.cpp b/chromium/third_party/skia/gm/widebuttcaps.cpp
new file mode 100644
index 00000000000..b2df5fecd38
--- /dev/null
+++ b/chromium/third_party/skia/gm/widebuttcaps.cpp
@@ -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.
+ */
+
+#include "gm/gm.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkPath.h"
+#include "include/core/SkPoint.h"
+
+static constexpr float kStrokeWidth = 100;
+
+class WideButtCaps : public skiagm::GM {
+public:
+ WideButtCaps() {}
+
+protected:
+
+ SkString onShortName() override {
+ return SkString("widebuttcaps");
+ }
+
+ SkISize onISize() override {
+ return SkISize::Make(120 * 4, 120 * 3 + 140);
+ }
+
+ void onOnceBeforeDraw() override {
+ fStrokePaint.setAntiAlias(true);
+ fStrokePaint.setStrokeWidth(kStrokeWidth);
+ fStrokePaint.setColor(SK_ColorGREEN);
+ fStrokePaint.setStyle(SkPaint::kStroke_Style);
+ }
+
+ void onDraw(SkCanvas* canvas) override {
+ SkAutoCanvasRestore arc(canvas, true);
+ canvas->translate(60, 60);
+ canvas->clear(SK_ColorBLACK);
+
+ this->drawStrokes(canvas,
+ SkPath().lineTo(10,0).lineTo(10,10),
+ SkPath().cubicTo(10,0, 10,0, 10,10));
+ canvas->translate(0, 120);
+
+ this->drawStrokes(canvas,
+ SkPath().lineTo(0,-10).lineTo(0,10),
+ SkPath().cubicTo(0,-10, 0,-10, 0,10));
+ canvas->translate(0, 120);
+
+ this->drawStrokes(canvas,
+ SkPath().lineTo(0,-10).lineTo(10,-10).lineTo(10,10).lineTo(0,10),
+ SkPath().cubicTo(0,-10, 10,10, 0,10));
+ canvas->translate(0, 140);
+
+ this->drawStrokes(canvas,
+ SkPath().lineTo(0,-10).lineTo(10,-10).lineTo(10,0).lineTo(0,0),
+ SkPath().cubicTo(0,-10, 10,0, 0,0));
+ canvas->translate(0, 120);
+ }
+
+ void drawStrokes(SkCanvas* canvas, const SkPath& path, const SkPath& cubic) {
+ SkAutoCanvasRestore arc(canvas, true);
+ fStrokePaint.setStrokeJoin(SkPaint::kBevel_Join);
+ canvas->drawPath(path, fStrokePaint);
+
+ canvas->translate(120, 0);
+ fStrokePaint.setStrokeJoin(SkPaint::kRound_Join);
+ canvas->drawPath(path, fStrokePaint);
+
+ canvas->translate(120, 0);
+ fStrokePaint.setStrokeJoin(SkPaint::kMiter_Join);
+ canvas->drawPath(path, fStrokePaint);
+
+ canvas->translate(120, 0);
+ canvas->drawPath(cubic, fStrokePaint);
+ }
+
+private:
+ SkPaint fStrokePaint;
+ typedef GM INHERITED;
+};
+
+DEF_GM( return new WideButtCaps; )
diff --git a/chromium/third_party/skia/gm/windowrectangles.cpp b/chromium/third_party/skia/gm/windowrectangles.cpp
index d7714ff0e37..1e38bf0d9ab 100644
--- a/chromium/third_party/skia/gm/windowrectangles.cpp
+++ b/chromium/third_party/skia/gm/windowrectangles.cpp
@@ -30,7 +30,6 @@
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrClip.h"
#include "src/gpu/GrContextPriv.h"
-#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrFragmentProcessor.h"
#include "src/gpu/GrPaint.h"
#include "src/gpu/GrRecordingContextPriv.h"
@@ -108,6 +107,9 @@ DrawResult WindowRectanglesGM::onCoverClipStack(const SkClipStack& stack, SkCanv
SkClipOp op = element->getOp();
bool isAA = element->isAA();
switch (element->getDeviceSpaceType()) {
+ case SkClipStack::Element::DeviceSpaceType::kShader:
+ canvas->clipShader(element->refShader(), op);
+ break;
case SkClipStack::Element::DeviceSpaceType::kPath:
canvas->clipPath(element->getDeviceSpacePath(), op, isAA);
break;
@@ -161,7 +163,7 @@ private:
class MaskOnlyClipBase : public GrClip {
private:
bool quickContains(const SkRect&) const final { return false; }
- bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const final { return false; }
+ bool isRRect(SkRRect* rr, GrAA*) const final { return false; }
};
/**
@@ -172,11 +174,15 @@ public:
AlphaOnlyClip(GrSurfaceProxyView mask, int x, int y) : fMask(std::move(mask)), fX(x), fY(y) {}
private:
+ SkIRect getConservativeBounds() const final {
+ return SkIRect::MakeXYWH(fX, fY, fMask.width(), fMask.height());
+ }
+
bool apply(GrRecordingContext* ctx, GrRenderTargetContext*, bool, bool, GrAppliedClip* out,
SkRect* bounds) const override {
GrSamplerState samplerState(GrSamplerState::WrapMode::kClampToBorder,
GrSamplerState::Filter::kNearest);
- auto m = SkMatrix::MakeTrans(-fX, -fY);
+ auto m = SkMatrix::Translate(-fX, -fY);
auto subset = SkRect::Make(fMask.dimensions());
auto domain = bounds->makeOffset(-fX, -fY).makeInset(0.5, 0.5);
auto fp = GrTextureEffect::MakeSubset(fMask, kPremul_SkAlphaType, m, samplerState, subset,
@@ -193,12 +199,12 @@ private:
/**
* Makes a clip object that enforces the stencil clip bit. Used to visualize the stencil mask.
*/
-static GrStencilClip make_stencil_only_clip() {
- return GrStencilClip(SkClipStack::kEmptyGenID);
+static GrStencilClip make_stencil_only_clip(GrRenderTargetContext* rtc) {
+ return GrStencilClip(rtc->dimensions(), SkClipStack::kEmptyGenID);
};
DrawResult WindowRectanglesMaskGM::onCoverClipStack(const SkClipStack& stack, SkCanvas* canvas,
- SkString* errorMsg) {
+ SkString* errorMsg) {
GrContext* ctx = canvas->getGrContext();
GrRenderTargetContext* rtc = canvas->internal_private_accessTopLayerRenderTargetContext();
if (!ctx || !rtc) {
@@ -238,12 +244,13 @@ void WindowRectanglesMaskGM::visualizeAlphaMask(GrContext* ctx, GrRenderTargetCo
// Draw a checker pattern into the alpha mask so we can visualize the regions left untouched by
// the clip mask generation.
this->stencilCheckerboard(maskRTC.get(), true);
- maskRTC->clear(nullptr, SK_PMColor4fWHITE, GrRenderTargetContext::CanClearFullscreen::kYes);
+ maskRTC->clear(SK_PMColor4fWHITE);
GrPaint stencilPaint;
stencilPaint.setCoverageSetOpXPFactory(SkRegion::kDifference_Op, false);
- maskRTC->priv().stencilRect(make_stencil_only_clip(), &GrUserStencilSettings::kUnused,
+ GrStencilClip stencilClip = make_stencil_only_clip(maskRTC.get());
+ maskRTC->priv().stencilRect(&stencilClip, &GrUserStencilSettings::kUnused,
std::move(stencilPaint), GrAA::kNo, SkMatrix::I(),
- SkRect::MakeIWH(maskRTC->width(), maskRTC->height()));
+ SkRect::Make(maskRTC->dimensions()));
reducedClip.drawAlphaClipMask(maskRTC.get());
int x = kCoverRect.x() - kDeviceRect.x(),
@@ -252,8 +259,8 @@ void WindowRectanglesMaskGM::visualizeAlphaMask(GrContext* ctx, GrRenderTargetCo
// Now visualize the alpha mask by drawing a rect over the area where it is defined. The regions
// inside window rectangles or outside the scissor should still have the initial checkerboard
// intact. (This verifies we didn't spend any time modifying those pixels in the mask.)
- AlphaOnlyClip clip(maskRTC->readSurfaceView(), x, y);
- rtc->drawRect(clip, std::move(paint), GrAA::kYes, SkMatrix::I(),
+ AlphaOnlyClip alphaClip(maskRTC->readSurfaceView(), x, y);
+ rtc->drawRect(&alphaClip, std::move(paint), GrAA::kYes, SkMatrix::I(),
SkRect::Make(SkIRect::MakeXYWH(x, y, maskRTC->width(), maskRTC->height())));
}
@@ -274,7 +281,8 @@ void WindowRectanglesMaskGM::visualizeStencilMask(GrContext* ctx, GrRenderTarget
// Now visualize the stencil mask by covering the entire render target. The regions inside
// window rectangles or outside the scissor should still have the initial checkerboard intact.
// (This verifies we didn't spend any time modifying those pixels in the mask.)
- rtc->drawPaint(make_stencil_only_clip(), std::move(paint), SkMatrix::I());
+ GrStencilClip clip = make_stencil_only_clip(rtc);
+ rtc->drawPaint(&clip, std::move(paint), SkMatrix::I());
}
void WindowRectanglesMaskGM::stencilCheckerboard(GrRenderTargetContext* rtc, bool flip) {
@@ -288,7 +296,7 @@ void WindowRectanglesMaskGM::stencilCheckerboard(GrRenderTargetContext* rtc, boo
0>()
);
- rtc->priv().clearStencilClip(GrFixedClip::Disabled(), false);
+ rtc->priv().clearStencilClip(SkIRect::MakeSize(rtc->dimensions()), false);
for (int y = 0; y < kDeviceRect.height(); y += kMaskCheckerSize) {
for (int x = (y & 1) == flip ? 0 : kMaskCheckerSize;
@@ -296,7 +304,7 @@ void WindowRectanglesMaskGM::stencilCheckerboard(GrRenderTargetContext* rtc, boo
SkIRect checker = SkIRect::MakeXYWH(x, y, kMaskCheckerSize, kMaskCheckerSize);
GrPaint paint;
paint.setXPFactory(GrDisableColorXPFactory::Get());
- rtc->priv().stencilRect(GrNoClip(), &kSetClip, std::move(paint), GrAA::kNo,
+ rtc->priv().stencilRect(nullptr, &kSetClip, std::move(paint), GrAA::kNo,
SkMatrix::I(), SkRect::Make(checker));
}
}
diff --git a/chromium/third_party/skia/gm/xfermodes.cpp b/chromium/third_party/skia/gm/xfermodes.cpp
index 6ddabe75c1d..d98b7f010ac 100644
--- a/chromium/third_party/skia/gm/xfermodes.cpp
+++ b/chromium/third_party/skia/gm/xfermodes.cpp
@@ -154,7 +154,7 @@ class XfermodesGM : public skiagm::GM {
canvas->saveLayer(&bounds, &p);
restoreNeeded = true;
p.setBlendMode(SkBlendMode::kSrcOver);
- // Fall through.
+ [[fallthrough]];
}
case kQuarterClear_SrcType: {
SkScalar halfW = SkIntToScalar(W) / 2;
@@ -175,7 +175,7 @@ class XfermodesGM : public skiagm::GM {
SkScalar h = SkIntToScalar(H);
SkRect r = SkRect::MakeXYWH(x, y + h / 4, w, h * 23 / 60);
canvas->clipRect(r);
- // Fall through.
+ [[fallthrough]];
}
case kRectangle_SrcType: {
SkScalar w = SkIntToScalar(W);
@@ -188,10 +188,10 @@ class XfermodesGM : public skiagm::GM {
}
case kSmallRectangleImageWithAlpha_SrcType:
m.postScale(SK_ScalarHalf, SK_ScalarHalf, x, y);
- // Fall through.
+ [[fallthrough]];
case kRectangleImageWithAlpha_SrcType:
p.setAlpha(0x88);
- // Fall through.
+ [[fallthrough]];
case kRectangleImage_SrcType: {
SkAutoCanvasRestore acr(canvas, true);
canvas->concat(m);
diff --git a/chromium/third_party/skia/gm/ycbcrimage.cpp b/chromium/third_party/skia/gm/ycbcrimage.cpp
new file mode 100644
index 00000000000..a508ea5e028
--- /dev/null
+++ b/chromium/third_party/skia/gm/ycbcrimage.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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 "gm/gm.h"
+
+// This test only works with the Vulkan backend.
+#ifdef SK_VULKAN
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkImage.h"
+#include "include/core/SkPaint.h"
+#include "include/core/SkSize.h"
+#include "include/core/SkString.h"
+#include "include/gpu/GrContext.h"
+#include "src/gpu/GrContextPriv.h"
+#include "tools/gpu/vk/VkYcbcrSamplerHelper.h"
+
+static void release_ycbcrhelper(void* releaseContext) {
+ VkYcbcrSamplerHelper* ycbcrHelper = reinterpret_cast<VkYcbcrSamplerHelper*>(releaseContext);
+ delete ycbcrHelper;
+}
+
+namespace skiagm {
+
+// This GM exercises the native YCbCr image format on Vulkan
+class YCbCrImageGM : public GpuGM {
+public:
+ YCbCrImageGM() {
+ this->setBGColor(0xFFCCCCCC);
+ }
+
+protected:
+
+ SkString onShortName() override {
+ return SkString("ycbcrimage");
+ }
+
+ SkISize onISize() override {
+ return SkISize::Make(2*kPad+kImageSize, 2*kPad+kImageSize);
+ }
+
+ DrawResult createYCbCrImage(GrContext* context, SkString* errorMsg) {
+ std::unique_ptr<VkYcbcrSamplerHelper> ycbcrHelper(new VkYcbcrSamplerHelper(context));
+
+ if (!ycbcrHelper->isYCbCrSupported()) {
+ *errorMsg = "YCbCr sampling not supported.";
+ return skiagm::DrawResult::kSkip;
+ }
+
+ if (!ycbcrHelper->createBackendTexture(kImageSize, kImageSize)) {
+ *errorMsg = "Failed to create I420 backend texture.";
+ return skiagm::DrawResult::kFail;
+ }
+
+ SkASSERT(!fYCbCrImage);
+ fYCbCrImage = SkImage::MakeFromTexture(context, ycbcrHelper->backendTexture(),
+ kTopLeft_GrSurfaceOrigin, kRGB_888x_SkColorType,
+ kPremul_SkAlphaType, nullptr,
+ release_ycbcrhelper, ycbcrHelper.get());
+ if (!fYCbCrImage) {
+ *errorMsg = "Failed to create I420 image.";
+ return DrawResult::kFail;
+ }
+
+ ycbcrHelper.release();
+ return DrawResult::kOk;
+ }
+
+ DrawResult onGpuSetup(GrContext* context, SkString* errorMsg) override {
+ if (!context || context->abandoned()) {
+ return DrawResult::kSkip;
+ }
+
+ SkASSERT(context->priv().asDirectContext());
+
+ if (context->backend() != GrBackendApi::kVulkan) {
+ *errorMsg = "This GM requires a Vulkan context.";
+ return DrawResult::kSkip;
+ }
+
+ DrawResult result = this->createYCbCrImage(context, errorMsg);
+ if (result != DrawResult::kOk) {
+ return result;
+ }
+
+ return DrawResult::kOk;
+ }
+
+ DrawResult onDraw(GrContext*, GrRenderTargetContext*, SkCanvas* canvas, SkString*) override {
+ SkASSERT(fYCbCrImage);
+
+ SkPaint paint;
+ paint.setFilterQuality(kLow_SkFilterQuality);
+
+ canvas->drawImage(fYCbCrImage, kPad, kPad, &paint);
+ return DrawResult::kOk;
+ }
+
+private:
+ static const int kImageSize = 112;
+ static const int kPad = 8;
+
+ sk_sp<SkImage> fYCbCrImage;
+
+ typedef GpuGM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+DEF_GM(return new YCbCrImageGM;)
+
+} // skiagm
+
+#endif // SK_VULKAN
diff --git a/chromium/third_party/skia/gm/yuvtorgbeffect.cpp b/chromium/third_party/skia/gm/yuvtorgbeffect.cpp
index 25f8c4c5f57..61c3f0576fb 100644
--- a/chromium/third_party/skia/gm/yuvtorgbeffect.cpp
+++ b/chromium/third_party/skia/gm/yuvtorgbeffect.cpp
@@ -24,7 +24,6 @@
#include "include/gpu/GrContext.h"
#include "include/private/GrTypesPriv.h"
#include "src/gpu/GrBitmapTextureMaker.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrFragmentProcessor.h"
#include "src/gpu/GrPaint.h"
@@ -342,7 +341,7 @@ protected:
SkScalar x = kTestPad;
// Columns are non-subsetted followed by subsetted with each WrapMode in a row
for (uint32_t j = 0; j < GrSamplerState::kWrapModeCount + 1; ++j) {
- SkMatrix ctm = SkMatrix::MakeTrans(x, y);
+ SkMatrix ctm = SkMatrix::Translate(x, y);
ctm.postScale(10.f, 10.f);
const SkRect* subset = j > 0 ? &kColorRect : nullptr;
@@ -362,7 +361,7 @@ protected:
GrPaint grPaint;
grPaint.addColorFragmentProcessor(std::move(fp));
renderTargetContext->drawRect(
- GrNoClip(), std::move(grPaint), GrAA::kYes, ctm, rect);
+ nullptr, std::move(grPaint), GrAA::kYes, ctm, rect);
}
x += rect.width() + kTestPad;
}
diff --git a/chromium/third_party/skia/gn/BUILD.gn b/chromium/third_party/skia/gn/BUILD.gn
index 04e2f8f536d..894d3121be5 100644
--- a/chromium/third_party/skia/gn/BUILD.gn
+++ b/chromium/third_party/skia/gn/BUILD.gn
@@ -15,6 +15,7 @@ declare_args() {
extra_ldflags = []
malloc = ""
+ werror = false
xcode_sysroot = ""
}
@@ -97,9 +98,6 @@ config("default") {
"/utf-8", # Set Source and Executable character sets to UTF-8.
]
cflags_cc += [ "/std:c++17" ]
- if (is_clang) {
- cflags += [ "-fms-compatibility-version=19" ] # 2015
- }
defines += [
"_CRT_SECURE_NO_WARNINGS", # Disables warnings about sscanf().
"_HAS_EXCEPTIONS=0", # Disables exceptions in MSVC STL.
@@ -152,17 +150,6 @@ config("default") {
"-mfpu=neon",
"-mthumb",
]
- } else if (current_cpu == "loongson3a") {
- asmflags += [ "-march=loongson3a" ]
- cflags += [
- "-march=loongson3a",
-
- # Causes an internal compiler error.
- "-DSKCMS_PORTABLE",
- ]
- } else if (current_cpu == "mips64el") {
- asmflags += [ "-march=mips64" ]
- cflags += [ "-march=mips64" ]
} else if (current_cpu == "x86" && !is_win) {
asmflags += [ "-m32" ]
cflags += [
@@ -435,12 +422,17 @@ config("warnings") {
"-Wno-unused-template",
"-Wno-zero-as-null-pointer-constant",
"-Wno-thread-safety-negative",
+ "-Wno-non-c-typedef-for-linkage", # Dawn, not Skia per se.
]
cflags_cc += [
"-Wno-abstract-vbase-init",
"-Wno-weak-vtables",
]
+ # Turn back on after -Wno-conversion.
+ # This only affects public headers... see :warnings_except_public_headers.
+ cflags += [ "-Wsign-conversion" ]
+
# We are unlikely to want to fix these.
cflags += [
"-Wno-covered-switch-default",
@@ -488,13 +480,13 @@ config("warnings") {
"-Wdeprecated-writable-str",
]
}
- if (!is_win || is_clang) {
- cflags += [ "-Wno-implicit-fallthrough" ]
- }
}
config("warnings_except_public_headers") {
if (!is_win || is_clang) {
- cflags = [ "-Wno-unused-parameter" ]
+ cflags = [
+ "-Wno-sign-conversion",
+ "-Wno-unused-parameter",
+ ]
}
}
diff --git a/chromium/third_party/skia/gn/BUILDCONFIG.gn b/chromium/third_party/skia/gn/BUILDCONFIG.gn
index 5fb933aa81f..cc2e16e25f2 100644
--- a/chromium/third_party/skia/gn/BUILDCONFIG.gn
+++ b/chromium/third_party/skia/gn/BUILDCONFIG.gn
@@ -29,8 +29,6 @@ declare_args() {
clang_win = ""
clang_win_version = ""
-
- werror = false
}
declare_args() {
is_debug = !is_official_build
diff --git a/chromium/third_party/skia/gn/compile_processors.py b/chromium/third_party/skia/gn/compile_processors.py
index 922b6539de1..c006532df4f 100755
--- a/chromium/third_party/skia/gn/compile_processors.py
+++ b/chromium/third_party/skia/gn/compile_processors.py
@@ -11,14 +11,21 @@ import sys
skslc = sys.argv[1]
clangFormat = sys.argv[2]
-processors = sys.argv[3:]
+fetchClangFormat = sys.argv[3]
+processors = sys.argv[4:]
+
+exeSuffix = '.exe' if sys.platform.startswith('win') else '';
+
for p in processors:
print("Recompiling " + p + "...")
try:
+ if not os.path.isfile(clangFormat + exeSuffix):
+ subprocess.check_call([sys.executable, fetchClangFormat]);
+
noExt, _ = os.path.splitext(p)
head, tail = os.path.split(noExt)
targetDir = os.path.join(head, "generated")
- if not os.path.exists(targetDir):
+ if not os.path.isdir(targetDir):
os.mkdir(targetDir)
target = os.path.join(targetDir, tail)
subprocess.check_output([skslc, p, target + ".h"])
diff --git a/chromium/third_party/skia/gn/core.gni b/chromium/third_party/skia/gn/core.gni
index 2a01d410460..7f2d32d2af7 100644
--- a/chromium/third_party/skia/gn/core.gni
+++ b/chromium/third_party/skia/gn/core.gni
@@ -58,6 +58,7 @@ skia_core_public = [
"$_include/core/SkOverdrawCanvas.h",
"$_include/core/SkPaint.h",
"$_include/core/SkPath.h",
+ "$_include/core/SkPathBuilder.h",
"$_include/core/SkPathEffect.h",
"$_include/core/SkPathMeasure.h",
"$_include/core/SkPixelRef.h",
@@ -234,8 +235,10 @@ skia_core_sources = [
"$_src/core/SkImageFilter_Base.h",
"$_src/core/SkImageGenerator.cpp",
"$_src/core/SkImageInfo.cpp",
+ "$_src/core/SkLRUCache.h",
"$_src/core/SkLatticeIter.cpp",
"$_src/core/SkLatticeIter.h",
+ "$_src/core/SkLegacyGpuBlurUtils.cpp",
"$_src/core/SkLineClipper.cpp",
"$_src/core/SkLocalMatrixImageFilter.cpp",
"$_src/core/SkLocalMatrixImageFilter.h",
@@ -270,7 +273,6 @@ skia_core_sources = [
"$_src/core/SkOSFile.h",
"$_src/core/SkOpts.cpp",
"$_src/core/SkOpts.h",
- "$_src/core/SkOpts_skx.cpp",
"$_src/core/SkOrderedReadBuffer.h",
"$_src/core/SkOverdrawCanvas.cpp",
"$_src/core/SkPaint.cpp",
@@ -278,6 +280,7 @@ skia_core_sources = [
"$_src/core/SkPaintPriv.cpp",
"$_src/core/SkPaintPriv.h",
"$_src/core/SkPath.cpp",
+ "$_src/core/SkPathBuilder.cpp",
"$_src/core/SkPathEffect.cpp",
"$_src/core/SkPathMeasure.cpp",
"$_src/core/SkPathPriv.h",
@@ -301,7 +304,6 @@ skia_core_sources = [
"$_src/core/SkRasterPipelineBlitter.cpp",
"$_src/core/SkReadBuffer.cpp",
"$_src/core/SkReadBuffer.h",
- "$_src/core/SkReader32.h",
"$_src/core/SkRecord.cpp",
"$_src/core/SkRecordDraw.cpp",
"$_src/core/SkRecordOpts.cpp",
diff --git a/chromium/third_party/skia/gn/flutter_defines.gni b/chromium/third_party/skia/gn/flutter_defines.gni
index e400fc3d2dc..90d6933726f 100644
--- a/chromium/third_party/skia/gn/flutter_defines.gni
+++ b/chromium/third_party/skia/gn/flutter_defines.gni
@@ -11,11 +11,11 @@ flutter_defines = [
# Remove software rasterizers to save some code size.
"SK_DISABLE_AAA",
- # Flutter doesn't deserialize anything.
- "SK_DISABLE_READBUFFER",
+ # Flutter doesn't deserialize effects.
"SK_DISABLE_EFFECT_DESERIALIZATION",
# Staging
+ "SK_SUPPORT_LEGACY_MATRIX_FACTORIES",
# Fast low-precision software rendering isn't a priority for Flutter.
"SK_DISABLE_LEGACY_SHADERCONTEXT",
diff --git a/chromium/third_party/skia/gn/gm.gni b/chromium/third_party/skia/gn/gm.gni
index c4266a17e0e..4ae72fb4070 100644
--- a/chromium/third_party/skia/gn/gm.gni
+++ b/chromium/third_party/skia/gn/gm.gni
@@ -156,6 +156,7 @@ gm_sources = [
"$_gm/emptypath.cpp",
"$_gm/encode.cpp",
"$_gm/encode_alpha_jpeg.cpp",
+ "$_gm/encode_color_types.cpp",
"$_gm/encode_platform.cpp",
"$_gm/encode_srgb.cpp",
"$_gm/exoticformats.cpp",
@@ -348,6 +349,7 @@ gm_sources = [
"$_gm/stroketext.cpp",
"$_gm/subsetshader.cpp",
"$_gm/surface.cpp",
+ "$_gm/swizzle.cpp",
"$_gm/tablecolorfilter.cpp",
"$_gm/tallstretchedbitmaps.cpp",
"$_gm/tessellation.cpp",
@@ -384,16 +386,15 @@ gm_sources = [
"$_gm/vertices.cpp",
"$_gm/verylargebitmap.cpp",
"$_gm/wacky_yuv_formats.cpp",
+ "$_gm/widebuttcaps.cpp",
"$_gm/windowrectangles.cpp",
"$_gm/xfermodeimagefilter.cpp",
"$_gm/xfermodes.cpp",
"$_gm/xfermodes2.cpp",
"$_gm/xfermodes3.cpp",
+ "$_gm/ycbcrimage.cpp",
"$_gm/yuv420_odd_dim.cpp",
"$_gm/yuvtorgbeffect.cpp",
]
-gl_gm_sources = [
- "$_gm/atlastext.cpp",
- "$_gm/rectangletexture.cpp",
-]
+gl_gm_sources = [ "$_gm/rectangletexture.cpp" ]
diff --git a/chromium/third_party/skia/gn/gn_to_bp.py b/chromium/third_party/skia/gn/gn_to_bp.py
index 4dac40dee15..4256993fe23 100755
--- a/chromium/third_party/skia/gn/gn_to_bp.py
+++ b/chromium/third_party/skia/gn/gn_to_bp.py
@@ -169,7 +169,6 @@ cc_defaults {
cc_defaults {
name: "skia_deps",
shared_libs: [
- "libandroidicu",
"libdng_sdk",
"libexpat",
"libft2",
@@ -230,10 +229,15 @@ cc_defaults {
"skia_deps",
"skia_pgo_no_profile_use"
],
+ shared_libs: [
+ "libandroidicu",
+ "libharfbuzz_ng",
+ ],
static_libs: [
"libskia",
],
cflags: [
+ "-DSK_SHAPER_HARFBUZZ_AVAILABLE",
"-Wno-implicit-fallthrough",
"-Wno-unused-parameter",
"-Wno-unused-variable",
@@ -284,30 +288,31 @@ cc_test {
# We'll run GN to get the main source lists and include directories for Skia.
def generate_args(target_os, enable_gpu):
d = {
- 'is_official_build': 'true',
+ 'is_official_build': 'true',
# gn_to_bp_utils' GetArchSources will take care of architecture-specific
# files.
- 'target_cpu': '"none"',
+ 'target_cpu': '"none"',
- 'skia_enable_android_utils': 'true',
+ 'skia_enable_android_utils': 'true',
# Use the custom FontMgr, as the framework will handle fonts.
- 'skia_enable_fontmgr_custom': 'false',
- 'skia_enable_fontmgr_custom_empty': 'true',
- 'skia_enable_fontmgr_android': 'false',
- 'skia_enable_fontmgr_win': 'false',
- 'skia_enable_fontmgr_win_gdi': 'false',
- 'skia_use_fonthost_mac': 'false',
+ 'skia_enable_fontmgr_custom_directory': 'false',
+ 'skia_enable_fontmgr_custom_embedded': 'false',
+ 'skia_enable_fontmgr_custom_empty': 'true',
+ 'skia_enable_fontmgr_android': 'false',
+ 'skia_enable_fontmgr_win': 'false',
+ 'skia_enable_fontmgr_win_gdi': 'false',
+ 'skia_use_fonthost_mac': 'false',
# enable features used in skia_nanobench
- 'skia_enable_sksl_interpreter': 'true',
- 'skia_tools_require_resources': 'true',
-
- 'skia_use_freetype': 'true',
- 'skia_use_fontconfig': 'false',
- 'skia_use_fixed_gamma_text': 'true',
- 'skia_include_multiframe_procs': 'false',
- 'skia_libgifcodec_path': '"third_party/libgifcodec"',
+ 'skia_enable_sksl_interpreter': 'true',
+ 'skia_tools_require_resources': 'true',
+
+ 'skia_use_freetype': 'true',
+ 'skia_use_fontconfig': 'false',
+ 'skia_use_fixed_gamma_text': 'true',
+ 'skia_include_multiframe_procs': 'false',
+ 'skia_libgifcodec_path': '"third_party/libgifcodec"',
}
d['target_os'] = target_os
if target_os == '"android"':
@@ -490,7 +495,8 @@ with open('Android.bp', 'w') as Android_bp:
defs['sse41'] +
defs['sse42'] +
defs['avx' ] +
- defs['hsw' ])),
+ defs['hsw' ] +
+ defs['skx' ])),
'dm_includes' : bpfmt(8, dm_includes),
'dm_srcs' : bpfmt(8, dm_srcs),
diff --git a/chromium/third_party/skia/gn/gn_to_bp_utils.py b/chromium/third_party/skia/gn/gn_to_bp_utils.py
index 088be3617c0..3deeb2bcd8a 100755
--- a/chromium/third_party/skia/gn/gn_to_bp_utils.py
+++ b/chromium/third_party/skia/gn/gn_to_bp_utils.py
@@ -36,7 +36,12 @@ def GrabDependentValues(js, name, value_type, list_to_extend, exclude):
# Skia components, gms, tests, etc).
for dep in js['targets'][name]['deps']:
if 'modules' in dep:
- continue # Modules require special handling -- skip for now.
+ skip = True
+ for white_list in ['skshaper', 'skparagraph']:
+ if white_list in dep:
+ skip = False
+ if skip:
+ continue # Modules require special handling -- skip for now.
if 'third_party' in dep:
continue # We've handled all third-party DEPS as static or shared_libs.
if 'none' in dep:
diff --git a/chromium/third_party/skia/gn/gpu.gni b/chromium/third_party/skia/gn/gpu.gni
index 2310000a0b3..789a2614140 100644
--- a/chromium/third_party/skia/gn/gpu.gni
+++ b/chromium/third_party/skia/gn/gpu.gni
@@ -11,6 +11,7 @@ skia_gpu_sources = [
"$_include/gpu/GrBackendDrawableInfo.h",
"$_include/gpu/GrBackendSemaphore.h",
"$_include/gpu/GrBackendSurface.h",
+ "$_include/gpu/GrBackendSurfaceMutableState.h",
"$_include/gpu/GrConfig.h",
"$_include/gpu/GrContext.h",
"$_include/gpu/GrContextOptions.h",
@@ -35,8 +36,10 @@ skia_gpu_sources = [
"$_src/gpu/GrAuditTrail.h",
"$_src/gpu/GrAutoLocaleSetter.h",
"$_src/gpu/GrBackendSurface.cpp",
+ "$_src/gpu/GrBackendSurfaceMutableStateImpl.h",
"$_src/gpu/GrBackendTextureImageGenerator.cpp",
"$_src/gpu/GrBackendTextureImageGenerator.h",
+ "$_src/gpu/GrBackendUtils.h",
"$_src/gpu/GrBaseContextPriv.h",
"$_src/gpu/GrBitmapTextureMaker.cpp",
"$_src/gpu/GrBitmapTextureMaker.h",
@@ -105,6 +108,7 @@ skia_gpu_sources = [
"$_src/gpu/GrGpuResource.h",
"$_src/gpu/GrGpuResourceCacheAccess.h",
"$_src/gpu/GrGpuResourcePriv.h",
+ "$_src/gpu/GrHashMapWithCache.h",
"$_src/gpu/GrImageContext.cpp",
"$_src/gpu/GrImageContextPriv.h",
"$_src/gpu/GrImageInfo.h",
@@ -151,6 +155,9 @@ skia_gpu_sources = [
"$_src/gpu/GrProxyProvider.h",
"$_src/gpu/GrRecordingContext.cpp",
"$_src/gpu/GrRecordingContextPriv.h",
+ "$_src/gpu/GrRectanizer.h",
+ "$_src/gpu/GrRectanizerPow2.cpp",
+ "$_src/gpu/GrRectanizerPow2.h",
"$_src/gpu/GrRectanizerSkyline.cpp",
"$_src/gpu/GrRectanizerSkyline.h",
"$_src/gpu/GrReducedClip.cpp",
@@ -174,6 +181,8 @@ skia_gpu_sources = [
"$_src/gpu/GrResourceProvider.cpp",
"$_src/gpu/GrResourceProvider.h",
"$_src/gpu/GrResourceProviderPriv.h",
+ "$_src/gpu/GrRingBuffer.cpp",
+ "$_src/gpu/GrRingBuffer.h",
"$_src/gpu/GrSPIRVUniformHandler.cpp",
"$_src/gpu/GrSPIRVUniformHandler.h",
"$_src/gpu/GrSPIRVVaryingHandler.cpp",
@@ -244,6 +253,8 @@ skia_gpu_sources = [
"$_src/gpu/GrTransferFromRenderTask.h",
"$_src/gpu/GrTriangulator.cpp",
"$_src/gpu/GrTriangulator.h",
+ "$_src/gpu/GrUniformDataManager.cpp",
+ "$_src/gpu/GrUniformDataManager.h",
"$_src/gpu/GrUserStencilSettings.h",
"$_src/gpu/GrWaitRenderTask.cpp",
"$_src/gpu/GrWaitRenderTask.h",
@@ -275,6 +286,8 @@ skia_gpu_sources = [
"$_src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h",
"$_src/gpu/effects/GrMatrixConvolutionEffect.cpp",
"$_src/gpu/effects/GrMatrixConvolutionEffect.h",
+ "$_src/gpu/effects/GrMatrixEffect.cpp",
+ "$_src/gpu/effects/GrMatrixEffect.h",
"$_src/gpu/effects/GrOvalEffect.cpp",
"$_src/gpu/effects/GrOvalEffect.h",
"$_src/gpu/effects/GrPorterDuffXferProcessor.cpp",
@@ -321,14 +334,10 @@ skia_gpu_sources = [
"$_src/gpu/effects/generated/GrLumaColorFilterEffect.h",
"$_src/gpu/effects/generated/GrMagnifierEffect.cpp",
"$_src/gpu/effects/generated/GrMagnifierEffect.h",
- "$_src/gpu/effects/generated/GrMatrixEffect.cpp",
- "$_src/gpu/effects/generated/GrMatrixEffect.h",
"$_src/gpu/effects/generated/GrMixerEffect.cpp",
"$_src/gpu/effects/generated/GrMixerEffect.h",
"$_src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp",
"$_src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h",
- "$_src/gpu/effects/generated/GrPremulInputFragmentProcessor.cpp",
- "$_src/gpu/effects/generated/GrPremulInputFragmentProcessor.h",
"$_src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp",
"$_src/gpu/effects/generated/GrRGBToHSLFilterEffect.h",
"$_src/gpu/effects/generated/GrRRectBlurEffect.cpp",
@@ -359,8 +368,6 @@ skia_gpu_sources = [
"$_src/gpu/ops/GrAtlasTextOp.h",
"$_src/gpu/ops/GrClearOp.cpp",
"$_src/gpu/ops/GrClearOp.h",
- "$_src/gpu/ops/GrClearStencilClipOp.cpp",
- "$_src/gpu/ops/GrClearStencilClipOp.h",
"$_src/gpu/ops/GrDashLinePathRenderer.cpp",
"$_src/gpu/ops/GrDashLinePathRenderer.h",
"$_src/gpu/ops/GrDashOp.cpp",
@@ -439,8 +446,11 @@ skia_gpu_sources = [
"$_src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h",
"$_src/gpu/tessellate/GrMidpointContourParser.h",
"$_src/gpu/tessellate/GrPathShader.h",
+ "$_src/gpu/tessellate/GrResolveLevelCounter.h",
"$_src/gpu/tessellate/GrStencilPathShader.cpp",
"$_src/gpu/tessellate/GrStencilPathShader.h",
+ "$_src/gpu/tessellate/GrStrokeGeometry.cpp",
+ "$_src/gpu/tessellate/GrStrokeGeometry.h",
"$_src/gpu/tessellate/GrTessellatePathOp.cpp",
"$_src/gpu/tessellate/GrTessellatePathOp.h",
"$_src/gpu/tessellate/GrTessellationPathRenderer.cpp",
@@ -455,14 +465,14 @@ skia_gpu_sources = [
"$_src/gpu/text/GrDistanceFieldAdjustTable.h",
"$_src/gpu/text/GrSDFMaskFilter.cpp",
"$_src/gpu/text/GrSDFMaskFilter.h",
+ "$_src/gpu/text/GrSDFTOptions.cpp",
+ "$_src/gpu/text/GrSDFTOptions.h",
"$_src/gpu/text/GrStrikeCache.cpp",
"$_src/gpu/text/GrStrikeCache.h",
"$_src/gpu/text/GrTextBlob.cpp",
"$_src/gpu/text/GrTextBlob.h",
"$_src/gpu/text/GrTextBlobCache.cpp",
"$_src/gpu/text/GrTextBlobCache.h",
- "$_src/gpu/text/GrTextContext.cpp",
- "$_src/gpu/text/GrTextContext.h",
"$_src/gpu/text/GrTextTarget.h",
# GLSL
@@ -741,16 +751,20 @@ skia_direct3d_sources = [
"$_include/gpu/d3d/GrD3DTypes.h",
"$_include/gpu/d3d/GrD3DTypesMinimal.h",
"$_include/private/GrD3DTypesPriv.h",
- "$_src/gpu/d3d/GrD3DAttachmentViewManager.cpp",
- "$_src/gpu/d3d/GrD3DAttachmentViewManager.h",
"$_src/gpu/d3d/GrD3DBuffer.cpp",
"$_src/gpu/d3d/GrD3DBuffer.h",
"$_src/gpu/d3d/GrD3DCaps.cpp",
"$_src/gpu/d3d/GrD3DCaps.h",
"$_src/gpu/d3d/GrD3DCommandList.cpp",
"$_src/gpu/d3d/GrD3DCommandList.h",
+ "$_src/gpu/d3d/GrD3DConstantRingBuffer.cpp",
+ "$_src/gpu/d3d/GrD3DConstantRingBuffer.h",
+ "$_src/gpu/d3d/GrD3DCpuDescriptorManager.cpp",
+ "$_src/gpu/d3d/GrD3DCpuDescriptorManager.h",
"$_src/gpu/d3d/GrD3DDescriptorHeap.cpp",
"$_src/gpu/d3d/GrD3DDescriptorHeap.h",
+ "$_src/gpu/d3d/GrD3DDescriptorTableManager.cpp",
+ "$_src/gpu/d3d/GrD3DDescriptorTableManager.h",
"$_src/gpu/d3d/GrD3DGpu.cpp",
"$_src/gpu/d3d/GrD3DGpu.h",
"$_src/gpu/d3d/GrD3DOpsRenderPass.cpp",
@@ -759,6 +773,8 @@ skia_direct3d_sources = [
"$_src/gpu/d3d/GrD3DPipelineState.h",
"$_src/gpu/d3d/GrD3DPipelineStateBuilder.cpp",
"$_src/gpu/d3d/GrD3DPipelineStateBuilder.h",
+ "$_src/gpu/d3d/GrD3DPipelineStateDataManager.cpp",
+ "$_src/gpu/d3d/GrD3DPipelineStateDataManager.h",
"$_src/gpu/d3d/GrD3DRenderTarget.cpp",
"$_src/gpu/d3d/GrD3DRenderTarget.h",
"$_src/gpu/d3d/GrD3DResourceProvider.cpp",
@@ -863,13 +879,3 @@ skia_native_gpu_sources = [
"$_src/gpu/gl/mac/GrGLMakeNativeInterface_mac.cpp",
"$_src/gpu/gl/win/GrGLMakeNativeInterface_win.cpp",
]
-
-skia_atlas_text_sources = [
- "$_include/atlastext/SkAtlasTextContext.h",
- "$_include/atlastext/SkAtlasTextFont.h",
- "$_include/atlastext/SkAtlasTextRenderer.h",
- "$_include/atlastext/SkAtlasTextTarget.h",
- "$_src/atlastext/SkAtlasTextContext.cpp",
- "$_src/atlastext/SkAtlasTextTarget.cpp",
- "$_src/atlastext/SkInternalAtlasTextContext.cpp",
-]
diff --git a/chromium/third_party/skia/gn/opts.gni b/chromium/third_party/skia/gn/opts.gni
index 4c0cead1122..3d0f3896f3a 100644
--- a/chromium/third_party/skia/gn/opts.gni
+++ b/chromium/third_party/skia/gn/opts.gni
@@ -18,3 +18,4 @@ sse41 = [ "$_src/opts/SkOpts_sse41.cpp" ]
sse42 = [ "$_src/opts/SkOpts_sse42.cpp" ]
avx = [ "$_src/opts/SkOpts_avx.cpp" ]
hsw = [ "$_src/opts/SkOpts_hsw.cpp" ]
+skx = [ "$_src/opts/SkOpts_skx.cpp" ]
diff --git a/chromium/third_party/skia/gn/rm.py b/chromium/third_party/skia/gn/rm.py
new file mode 100755
index 00000000000..daac924ba85
--- /dev/null
+++ b/chromium/third_party/skia/gn/rm.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+#
+# Copyright 2016 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import shutil
+import sys
+
+dst, = sys.argv[1:]
+
+if os.path.exists(dst):
+ if os.path.isdir(dst):
+ shutil.rmtree(dst)
+ else:
+ os.remove(dst)
diff --git a/chromium/third_party/skia/gn/run_sksllex.py b/chromium/third_party/skia/gn/run_sksllex.py
index 5a970df784d..cc427ff51a7 100755
--- a/chromium/third_party/skia/gn/run_sksllex.py
+++ b/chromium/third_party/skia/gn/run_sksllex.py
@@ -11,11 +11,19 @@ import sys
sksllex = sys.argv[1]
clangFormat = sys.argv[2]
-src = sys.argv[3]
+fetchClangFormat = sys.argv[3]
+src = sys.argv[4]
+
+exeSuffix = '.exe' if sys.platform.startswith('win') else '';
+
try:
subprocess.check_output([sksllex, src + "/sksl/lex/sksl.lex", "Lexer",
"Token", src + "/sksl/SkSLLexer.h", src +
"/sksl/SkSLLexer.cpp"])
+
+ if not os.path.isfile(clangFormat + exeSuffix):
+ subprocess.check_call([sys.executable, fetchClangFormat]);
+
subprocess.check_call(clangFormat + " -i \"" + src + "/sksl/SkSLLexer.h\"",
shell=True)
subprocess.check_call(clangFormat + " -i \"" + src +
diff --git a/chromium/third_party/skia/gn/samples.gni b/chromium/third_party/skia/gn/samples.gni
index ae173e5058c..b80073b704c 100644
--- a/chromium/third_party/skia/gn/samples.gni
+++ b/chromium/third_party/skia/gn/samples.gni
@@ -43,6 +43,7 @@ samples_sources = [
"$_samplecode/SampleFillType.cpp",
"$_samplecode/SampleFilter2.cpp",
"$_samplecode/SampleFilterQuality.cpp",
+ "$_samplecode/SampleFitCubicToCircle.cpp",
"$_samplecode/SampleFlutterAnimate.cpp",
"$_samplecode/SampleGlyphTransform.cpp",
"$_samplecode/SampleGradients.cpp",
diff --git a/chromium/third_party/skia/gn/shared_sources.gni b/chromium/third_party/skia/gn/shared_sources.gni
index 71500113a63..e710a0e0b6f 100644
--- a/chromium/third_party/skia/gn/shared_sources.gni
+++ b/chromium/third_party/skia/gn/shared_sources.gni
@@ -26,4 +26,5 @@ skia_opts = {
sse42_sources = sse42
avx_sources = avx
hsw_sources = hsw
+ skx_sources = skx
}
diff --git a/chromium/third_party/skia/gn/skia.gni b/chromium/third_party/skia/gn/skia.gni
index a649bf2bf28..f4b35e83060 100644
--- a/chromium/third_party/skia/gn/skia.gni
+++ b/chromium/third_party/skia/gn/skia.gni
@@ -23,6 +23,7 @@ declare_args() {
skia_enable_gpu = true
skia_enable_pdf = true
skia_enable_skottie = !(is_win && is_component_build)
+ skia_enable_skrive = true
skia_enable_sksl_interpreter = is_skia_dev_build
skia_enable_skvm_jit =
is_skia_dev_build && ((target_cpu == "x64" && (is_linux || is_mac)) ||
@@ -48,7 +49,7 @@ declare_args() {
skia_use_ffmpeg = false
skia_use_fixed_gamma_text = is_android
skia_use_fontconfig = is_linux
- skia_use_fonthost_mac = is_mac
+ skia_use_fonthost_mac = is_mac || is_ios
skia_use_freetype = is_android || is_fuchsia || is_linux
skia_use_harfbuzz = true
skia_use_gl = !is_fuchsia
@@ -92,11 +93,13 @@ declare_args() {
}
declare_args() {
- skia_enable_atlas_text = is_skia_dev_build && skia_enable_gpu
skia_enable_fontmgr_android = skia_use_expat && skia_use_freetype
- skia_enable_fontmgr_custom =
- is_linux && skia_use_freetype && !skia_use_fontconfig
- skia_enable_fontmgr_custom_empty = is_fuchsia && skia_use_freetype
+ skia_enable_fontmgr_custom_directory = skia_use_freetype && !is_fuchsia
+ skia_enable_fontmgr_custom_embedded = skia_use_freetype && !is_fuchsia
+ skia_enable_fontmgr_custom_empty = skia_use_freetype
+ skia_enable_fontmgr_fontconfig = skia_use_freetype && skia_use_fontconfig
+ skia_enable_fontmgr_FontConfigInterface =
+ skia_use_freetype && skia_use_fontconfig
skia_enable_nvpr = !skia_enable_flutter_defines
skia_enable_spirv_validation = is_skia_dev_build && is_debug && !skia_use_dawn
skia_use_dng_sdk =
@@ -108,5 +111,30 @@ declare_args() {
skia_use_vma = skia_use_vulkan
}
+declare_args() {
+ # skia_fontmgr_factory should define SkFontMgr::Factory()
+ if (skia_enable_fontmgr_empty) {
+ skia_fontmgr_factory = "src/ports/SkFontMgr_empty_factory.cpp"
+ } else if (is_android && skia_enable_fontmgr_android) {
+ skia_fontmgr_factory = "src/ports/SkFontMgr_android_factory.cpp"
+ } else if (is_win && skia_enable_fontmgr_win) {
+ skia_fontmgr_factory = "src/ports/SkFontMgr_win_dw_factory.cpp"
+ } else if ((is_mac || is_ios) && skia_use_fonthost_mac) {
+ skia_fontmgr_factory = "src/ports/SkFontMgr_mac_ct_factory.cpp"
+ } else if (skia_enable_fontmgr_fontconfig) {
+ skia_fontmgr_factory = "src/ports/SkFontMgr_fontconfig_factory.cpp"
+ } else if (skia_enable_fontmgr_custom_directory) {
+ skia_fontmgr_factory = "src/ports/SkFontMgr_custom_directory_factory.cpp"
+ } else if (skia_enable_fontmgr_custom_embedded) {
+ skia_fontmgr_factory = "src/ports/SkFontMgr_custom_embedded_factory.cpp"
+ } else if (skia_enable_fontmgr_custom_empty) {
+ skia_fontmgr_factory = "src/ports/SkFontMgr_custom_empty_factory.cpp"
+ } else {
+ #"src/ports/SkFontMgr_FontConfigInterface_factory.cpp" #WontFix
+ #"src/ports/SkFontMgr_win_gdi_factory.cpp" # WontFix
+ skia_fontmgr_factory = "src/ports/SkFontMgr_empty_factory.cpp"
+ }
+}
+
# Our tools require static linking (they use non-exported symbols), and the GPU backend.
skia_enable_tools = skia_enable_tools && !is_component_build && skia_enable_gpu
diff --git a/chromium/third_party/skia/gn/sksl.gni b/chromium/third_party/skia/gn/sksl.gni
index 7653c34304d..104c4af5550 100644
--- a/chromium/third_party/skia/gn/sksl.gni
+++ b/chromium/third_party/skia/gn/sksl.gni
@@ -7,34 +7,70 @@
_src = get_path_info("../src", "abspath")
skia_sksl_sources = [
+ "$_src/sksl/SkSLASTFile.h",
"$_src/sksl/SkSLASTNode.cpp",
+ "$_src/sksl/SkSLASTNode.h",
"$_src/sksl/SkSLByteCode.cpp",
+ "$_src/sksl/SkSLByteCode.h",
"$_src/sksl/SkSLByteCodeGenerator.cpp",
+ "$_src/sksl/SkSLByteCodeGenerator.h",
"$_src/sksl/SkSLCFGGenerator.cpp",
+ "$_src/sksl/SkSLCFGGenerator.h",
"$_src/sksl/SkSLCompiler.cpp",
+ "$_src/sksl/SkSLCompiler.h",
+ "$_src/sksl/SkSLContext.h",
+ "$_src/sksl/SkSLDefines.h",
+ "$_src/sksl/SkSLErrorReporter.h",
+ "$_src/sksl/SkSLExternalValue.h",
+ "$_src/sksl/SkSLFileOutputStream.h",
"$_src/sksl/SkSLIRGenerator.cpp",
+ "$_src/sksl/SkSLIRGenerator.h",
"$_src/sksl/SkSLLexer.cpp",
+ "$_src/sksl/SkSLLexer.h",
+ "$_src/sksl/SkSLMemoryLayout.h",
+ "$_src/sksl/SkSLOutputStream.h",
"$_src/sksl/SkSLParser.cpp",
+ "$_src/sksl/SkSLParser.h",
+ "$_src/sksl/SkSLPosition.h",
"$_src/sksl/SkSLSampleMatrix.cpp",
+ "$_src/sksl/SkSLSampleMatrix.h",
"$_src/sksl/SkSLSectionAndParameterHelper.cpp",
+ "$_src/sksl/SkSLSectionAndParameterHelper.h",
"$_src/sksl/SkSLString.cpp",
+ "$_src/sksl/SkSLString.h",
+ "$_src/sksl/SkSLStringStream.h",
"$_src/sksl/SkSLUtil.cpp",
+ "$_src/sksl/SkSLUtil.h",
"$_src/sksl/ir/SkSLSetting.cpp",
+ "$_src/sksl/ir/SkSLSetting.h",
"$_src/sksl/ir/SkSLSymbolTable.cpp",
+ "$_src/sksl/ir/SkSLSymbolTable.h",
"$_src/sksl/ir/SkSLType.cpp",
+ "$_src/sksl/ir/SkSLType.h",
"$_src/sksl/ir/SkSLVariableReference.cpp",
+ "$_src/sksl/ir/SkSLVariableReference.h",
]
skia_sksl_gpu_sources = [
"$_src/sksl/SkSLCPPCodeGenerator.cpp",
+ "$_src/sksl/SkSLCPPCodeGenerator.h",
"$_src/sksl/SkSLCPPUniformCTypes.cpp",
+ "$_src/sksl/SkSLCPPUniformCTypes.h",
+ "$_src/sksl/SkSLCodeGenerator.h",
"$_src/sksl/SkSLGLSLCodeGenerator.cpp",
+ "$_src/sksl/SkSLGLSLCodeGenerator.h",
"$_src/sksl/SkSLHCodeGenerator.cpp",
+ "$_src/sksl/SkSLHCodeGenerator.h",
"$_src/sksl/SkSLMetalCodeGenerator.cpp",
+ "$_src/sksl/SkSLMetalCodeGenerator.h",
"$_src/sksl/SkSLOutputStream.cpp",
+ "$_src/sksl/SkSLOutputStream.h",
"$_src/sksl/SkSLPipelineStageCodeGenerator.cpp",
+ "$_src/sksl/SkSLPipelineStageCodeGenerator.h",
"$_src/sksl/SkSLSPIRVCodeGenerator.cpp",
+ "$_src/sksl/SkSLSPIRVCodeGenerator.h",
"$_src/sksl/SkSLSPIRVtoHLSL.cpp",
+ "$_src/sksl/SkSLSPIRVtoHLSL.h",
]
skia_gpu_processor_sources = [
@@ -53,10 +89,8 @@ skia_gpu_processor_sources = [
"$_src/gpu/effects/GrHSLToRGBFilterEffect.fp",
"$_src/gpu/effects/GrLumaColorFilterEffect.fp",
"$_src/gpu/effects/GrMagnifierEffect.fp",
- "$_src/gpu/effects/GrMatrixEffect.fp",
"$_src/gpu/effects/GrMixerEffect.fp",
"$_src/gpu/effects/GrOverrideInputFragmentProcessor.fp",
- "$_src/gpu/effects/GrPremulInputFragmentProcessor.fp",
"$_src/gpu/effects/GrRGBToHSLFilterEffect.fp",
"$_src/gpu/effects/GrRRectBlurEffect.fp",
"$_src/gpu/effects/GrRectBlurEffect.fp",
diff --git a/chromium/third_party/skia/gn/tests.gni b/chromium/third_party/skia/gn/tests.gni
index 63354fc526d..70ef573bbcb 100644
--- a/chromium/third_party/skia/gn/tests.gni
+++ b/chromium/third_party/skia/gn/tests.gni
@@ -15,7 +15,9 @@ tests_sources = [
"$_tests/ApplyGammaTest.cpp",
"$_tests/ArenaAllocTest.cpp",
"$_tests/AsADashTest.cpp",
+ "$_tests/BRDTest.cpp",
"$_tests/BackendAllocationTest.cpp",
+ "$_tests/BackendSurfaceMutableStateTest.cpp",
"$_tests/BadIcoTest.cpp",
"$_tests/BitSetTest.cpp",
"$_tests/BitmapCopyTest.cpp",
@@ -101,6 +103,7 @@ tests_sources = [
"$_tests/GrCCPRTest.cpp",
"$_tests/GrContextAbandonTest.cpp",
"$_tests/GrContextFactoryTest.cpp",
+ "$_tests/GrContextOOM.cpp",
"$_tests/GrFinishedFlushTest.cpp",
"$_tests/GrMemoryPoolTest.cpp",
"$_tests/GrMeshTest.cpp",
@@ -111,6 +114,7 @@ tests_sources = [
"$_tests/GrQuadBufferTest.cpp",
"$_tests/GrQuadCropTest.cpp",
"$_tests/GrStyledShapeTest.cpp",
+ "$_tests/GrSubmittedFlushTest.cpp",
"$_tests/GrSurfaceTest.cpp",
"$_tests/GrTAllocatorTest.cpp",
"$_tests/GrTRecorderTest.cpp",
@@ -182,7 +186,9 @@ tests_sources = [
"$_tests/PaintImageFilterTest.cpp",
"$_tests/PaintTest.cpp",
"$_tests/ParametricStageTest.cpp",
+ "$_tests/ParseColorTest.cpp",
"$_tests/ParsePathTest.cpp",
+ "$_tests/PathBuilderTest.cpp",
"$_tests/PathCoverageTest.cpp",
"$_tests/PathMeasureTest.cpp",
"$_tests/PathRendererCacheTests.cpp",
@@ -209,7 +215,6 @@ tests_sources = [
"$_tests/RandomTest.cpp",
"$_tests/ReadPixelsTest.cpp",
"$_tests/ReadWriteAlphaTest.cpp",
- "$_tests/Reader32Test.cpp",
"$_tests/RecordDrawTest.cpp",
"$_tests/RecordOptsTest.cpp",
"$_tests/RecordPatternTest.cpp",
diff --git a/chromium/third_party/skia/gn/toolchain/BUILD.gn b/chromium/third_party/skia/gn/toolchain/BUILD.gn
index 1832835f1ab..45177109462 100644
--- a/chromium/third_party/skia/gn/toolchain/BUILD.gn
+++ b/chromium/third_party/skia/gn/toolchain/BUILD.gn
@@ -42,9 +42,12 @@ declare_args() {
dlsymutil_pool_depth = exec_script("num_cpus.py", [], "value")
}
+# For 'shell' see https://ninja-build.org/manual.html#ref_rule_command
if (host_os == "win") {
- stamp = "cmd.exe /c echo >"
+ shell = "cmd.exe /c "
+ stamp = "$shell echo >"
} else {
+ shell = ""
stamp = "touch"
}
@@ -64,10 +67,10 @@ toolchain("msvc") {
if (target_cpu == "x86") {
# Toolchain asset includes a script that configures for x86 building.
# We don't support x86 builds with local MSVC installations.
- env_setup = "cmd /c $win_sdk/bin/SetEnv.cmd /x86 && "
+ env_setup = "$shell $win_sdk/bin/SetEnv.cmd /x86 && "
} else if (target_cpu == "arm64") {
# ARM64 compiler is incomplete - it relies on DLLs located in the host toolchain directory.
- env_setup = "cmd /C set \"PATH=%PATH%;$win_vc\\Tools\\MSVC\\$win_toolchain_version\\bin\\HostX64\\x64\" && "
+ env_setup = "$shell set \"PATH=%PATH%;$win_vc\\Tools\\MSVC\\$win_toolchain_version\\bin\\HostX64\\x64\" && "
}
cl_m32_flag = ""
@@ -266,7 +269,8 @@ template("gcc_like_toolchain") {
} else {
rspfile = "{{output}}.rsp"
rspfile_content = "{{inputs}}"
- command = "$ar rcs {{output}} @$rspfile"
+ rm_py = rebase_path("../rm.py")
+ command = "$shell python \"$rm_py\" \"{{output}}\" && $ar rcs {{output}} @$rspfile"
}
outputs =
diff --git a/chromium/third_party/skia/gn/utils.gni b/chromium/third_party/skia/gn/utils.gni
index 1b968fc3c13..9b181dcb692 100644
--- a/chromium/third_party/skia/gn/utils.gni
+++ b/chromium/third_party/skia/gn/utils.gni
@@ -81,6 +81,10 @@ skia_utils_sources = [
"$_src/utils/SkWhitelistTypefaces.cpp",
#mac
+ "$_src/utils/mac/SkCGBase.h",
+ "$_src/utils/mac/SkCGGeometry.h",
+ "$_src/utils/mac/SkCTFontSmoothBehavior.cpp",
+ "$_src/utils/mac/SkCTFontSmoothBehavior.h",
"$_src/utils/mac/SkCreateCGImageRef.cpp",
"$_src/utils/mac/SkUniqueCFRef.h",
diff --git a/chromium/third_party/skia/go.mod b/chromium/third_party/skia/go.mod
index 34f4a138efa..f8265f4f9e5 100644
--- a/chromium/third_party/skia/go.mod
+++ b/chromium/third_party/skia/go.mod
@@ -3,7 +3,8 @@ module go.skia.org/skia
go 1.12
require (
- cloud.google.com/go/storage v1.8.0
+ cloud.google.com/go v0.59.0 // indirect
+ cloud.google.com/go/storage v1.10.0
github.com/99designs/goodies v0.0.0-20140916053233-ec7f410f2ff2 // indirect
github.com/Azure/go-autorest v11.1.2+incompatible // indirect
github.com/VividCortex/godaemon v0.0.0-20150910212227-3d9f6e0b234f // indirect
@@ -16,23 +17,29 @@ require (
github.com/huin/goserial v0.0.0-20121012073615-7b90efdb22b1 // indirect
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 // indirect
github.com/jackc/pgx v3.2.0+incompatible // indirect
+ github.com/kisielk/errcheck v1.3.0 // indirect
github.com/luci/gtreap v0.0.0-20161228054646-35df89791e8f // indirect
github.com/pkg/errors v0.9.1
- github.com/prometheus/common v0.10.0 // indirect
+ github.com/prometheus/client_golang v1.7.1 // indirect
github.com/rogpeppe/go-internal v1.5.0 // indirect
- github.com/stretchr/testify v1.5.1
- github.com/vektra/mockery v1.1.1 // indirect
- go.chromium.org/luci v0.0.0-20200514021706-fa8dd98fcf00 // indirect
- go.skia.org/infra v0.0.0-20200513214741-b48b7541705b
+ github.com/stretchr/testify v1.6.1
+ github.com/vektra/mockery v1.1.2 // indirect
+ go.chromium.org/luci v0.0.0-20200624214209-c1ada0c7a303 // indirect
+ go.opencensus.io v0.22.4 // indirect
+ go.skia.org/infra v0.0.0-20200624212929-6c6f866a7d58
golang.org/x/exp v0.0.0-20200228211341-fcea875c7e85 // indirect
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 // indirect
golang.org/x/mobile v0.0.0-20191002175909-6d0d39b2ca82 // indirect
- golang.org/x/net v0.0.0-20200513185701-a91f0712d120 // indirect
+ golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
- golang.org/x/sys v0.0.0-20200513112337-417ce2331b5c // indirect
- golang.org/x/tools v0.0.0-20200513201620-d5fe73897c97 // indirect
+ golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 // indirect
+ golang.org/x/text v0.3.3 // indirect
+ golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff // indirect
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
- google.golang.org/api v0.24.0
- google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884 // indirect
+ google.golang.org/api v0.28.0
+ google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad // indirect
+ google.golang.org/grpc v1.30.0 // indirect
+ google.golang.org/protobuf v1.25.0 // indirect
+ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e // indirect
)
diff --git a/chromium/third_party/skia/go.sum b/chromium/third_party/skia/go.sum
index e5ff346e551..9b2f969b714 100644
--- a/chromium/third_party/skia/go.sum
+++ b/chromium/third_party/skia/go.sum
@@ -25,6 +25,10 @@ cloud.google.com/go v0.56.0 h1:WRz29PgAsVEyPSDHyk+0fpEkwEFyfhHn+JbksT6gIL4=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0 h1:EpMNVUorLiZIELdMZbCYX/ByTFCdoYopYAGxaGVz9ms=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
+cloud.google.com/go v0.58.0 h1:vtAfVc723K3xKq1BQydk/FyCldnaNFhGhpJxaJzgRMQ=
+cloud.google.com/go v0.58.0/go.mod h1:W+9FnSUw6nhVwXlFcp1eL+krq5+HQUJeUogSeJZZiWg=
+cloud.google.com/go v0.59.0 h1:BM3svUDU3itpc2m5cu5wCyThIYNDlFlts9GASw31GW8=
+cloud.google.com/go v0.59.0/go.mod h1:qJxNOVCRTxHfwLhvDxxSI9vQc1zI59b9pEglp1Iv60E=
cloud.google.com/go/bigquery v1.0.1 h1:hL+ycaJpVE9M7nLoiXb/Pn10ENE2u+oddxbD8uu0ZVU=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
@@ -33,6 +37,7 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM
cloud.google.com/go/bigquery v1.6.0 h1:ajp/DjpiCHO71SyIhwb83YsUGAyWuzVvMko+9xCsJLw=
cloud.google.com/go/bigquery v1.6.0/go.mod h1:hyFDG0qSGdHNz8Q6nDN8rYIkld0q/+5uBZaelxiDLfE=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
+cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/bigtable v1.3.0 h1:PAplkJLXheOLlK5PPyy4/HXtPzHn+1/LaYDWIeGxnio=
cloud.google.com/go/bigtable v1.3.0/go.mod h1:z5EyKrPE8OQmeg4h5MNdKvuSnI9CCT49Ki3f23aBzio=
cloud.google.com/go/datastore v1.0.0 h1:Kt+gOPPp2LEPWp8CSfxhsM8ik9CcyE/gYu+0r+RnZvM=
@@ -52,6 +57,8 @@ cloud.google.com/go/pubsub v1.2.0 h1:Lpy6hKgdcl7a3WGSfJIFmxmcdjSpP6OmBEfcOv1Y680
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
+cloud.google.com/go/pubsub v1.4.0 h1:76oR7VBOkL7ivoIrFKyW0k7YDCRelrlxktIzQiIUGgg=
+cloud.google.com/go/pubsub v1.4.0/go.mod h1:LFrqilwgdw4X2cJS9ALgzYmMu+ULyrUN6IHV3CPK4TM=
cloud.google.com/go/spanner v1.2.0/go.mod h1:LfwGAsK42Yz8IeLsd/oagGFBqTXt3xVWtm8/KD2vrEI=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0 h1:RPUcBvDeYgQFMfQu1eBMq6piD1SXmLH+vK3qjewZPus=
@@ -62,6 +69,10 @@ cloud.google.com/go/storage v1.7.0 h1:DzdLPI8Em+DEk7IzA2a10ivq3mxIEASC9GeNJ6FFt5
cloud.google.com/go/storage v1.7.0/go.mod h1:jGMIBwF+L/tL6WN/W5InNgYYu4HP0DvGB6rQ1mufWfs=
cloud.google.com/go/storage v1.8.0 h1:86K1Gel7BQ9/WmNWn7dTKMvTLFzwtBe5FNqYbi9X35g=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
+cloud.google.com/go/storage v1.9.0 h1:oXnZyBjHB6hC8TnSle0AWW6pGJ29EuSo5ww+SFmdNBg=
+cloud.google.com/go/storage v1.9.0/go.mod h1:m+/etGaqZbylxaNT876QGXqEHp4PR2Rq5GMqICWb9bU=
+cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA=
+cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
contrib.go.opencensus.io/exporter/stackdriver v0.13.1 h1:RX9W6FelAqTVnBi/bRXJLXr9n18v4QkQwZYIdnNS51I=
contrib.go.opencensus.io/exporter/stackdriver v0.13.1/go.mod h1:z2tyTZtPmQ2HvWH4cOmVDgtY+1lomfKdbLnkJvZdc8c=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
@@ -84,6 +95,8 @@ github.com/GeertJohan/go.rice v1.0.0 h1:KkI6O9uMaQU3VEKaj01ulavtF7o1fWT7+pk/4voi
github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0=
github.com/Jeffail/gabs/v2 v2.5.0 h1:ERXffrksCEPjKVDWbZDBcOwrpXctXfeFGXxOQh1umOE=
github.com/Jeffail/gabs/v2 v2.5.0/go.mod h1:xCn81vdHKxFUuWWAaD5jCTQDNPBMh5pPs9IJ+NcziBI=
+github.com/Jeffail/gabs/v2 v2.5.1 h1:ANfZYjpMlfTTKebycu4X1AgkVWumFVDYQl7JwOr4mDk=
+github.com/Jeffail/gabs/v2 v2.5.1/go.mod h1:xCn81vdHKxFUuWWAaD5jCTQDNPBMh5pPs9IJ+NcziBI=
github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
@@ -93,6 +106,7 @@ github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuN
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
+github.com/OneOfOne/struct2ts v1.0.4/go.mod h1:GbIenlFXroS2wRhpYXHEq7y7HWsY3SFBIKxkqzbnAsU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/goquery v1.5.1 h1:PSPBGne8NIUWw+/7vFBV+kG2J/5MOjbzc7154OaKCSE=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
@@ -109,6 +123,7 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/andybalholm/cascadia v1.2.0 h1:vuRCkM5Ozh/BfmsaTm26kbjm0mIOM3yS5Ek/F5h18aE=
@@ -142,6 +157,26 @@ github.com/aws/aws-sdk-go v1.30.25 h1:89NXJkfpjnMEnsxkP8MVX+LDsoiLCSqevraLb5y4Mj
github.com/aws/aws-sdk-go v1.30.25/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.30.26 h1:wP0N6DBb/3EyHTtWNz4jzgGVi1l290zoFGfu4HFGeM0=
github.com/aws/aws-sdk-go v1.30.26/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.30.27 h1:9gPjZWVDSoQrBO2AvqrWObS6KAZByfEJxQoCYo4ZfK0=
+github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.30.28 h1:SaPM7dlmp7h3Lj1nJ4jdzOkTdom08+g20k7AU5heZYg=
+github.com/aws/aws-sdk-go v1.30.28/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.30.29 h1:NXNqBS9hjOCpDL8SyCyl38gZX3LLLunKOJc5E7vJ8P0=
+github.com/aws/aws-sdk-go v1.30.29/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.31.0 h1:ITLZ0oy7IOB1NGt2Ee75bLevBaH1jaAXE2eyGbPRbCg=
+github.com/aws/aws-sdk-go v1.31.0/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.31.7 h1:TCA+pXKvzDMA3vVqhK21cCy5GarC8pTQb/DrVOWI3iY=
+github.com/aws/aws-sdk-go v1.31.7/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.31.8 h1:qbA8nsLYcqtGjMGDogqykuO0LyUONkP9YlsKu1SVV5M=
+github.com/aws/aws-sdk-go v1.31.8/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.31.9 h1:n+b34ydVfgC30j0Qm69yaapmjejQPW2BoDBX7Uy/tLI=
+github.com/aws/aws-sdk-go v1.31.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.31.10 h1:33jOMifUSdOP9pvNEOj+PGwljzunc8bJvKKNF/JuGzo=
+github.com/aws/aws-sdk-go v1.31.10/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.31.11 h1:Uz7VGg3giOV9Z4SlLdXO6RHafArHbK59vSc6mnzYjGU=
+github.com/aws/aws-sdk-go v1.31.11/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.31.14 h1:uRC2riabEXPMHl1CDylsfCod5DKjiOSXhYvxg/Eb9V8=
+github.com/aws/aws-sdk-go v1.31.14/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
@@ -306,6 +341,8 @@ github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
@@ -319,6 +356,10 @@ github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0=
+github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-github/v29 v29.0.3 h1:IktKCTwU//aFHnpA+2SLIi7Oo9uhAzgsdZNbcAqhgdc=
@@ -327,6 +368,8 @@ github.com/google/go-licenses v0.0.0-20200227160636-0fa8c766a591 h1:eVR9gT5gBPTH
github.com/google/go-licenses v0.0.0-20200227160636-0fa8c766a591/go.mod h1:JWeTIGPLQ9gF618ZOdlUitd1gRR/l99WOkHOlmR/UVA=
github.com/google/go-licenses v0.0.0-20200511085313-e4cf7a36ee79 h1:/kgCkStHv3ZHqBwe7NPs0NWFt5GbufTrjcHKJm1Osvk=
github.com/google/go-licenses v0.0.0-20200511085313-e4cf7a36ee79/go.mod h1:EiGoSZYaoyOKTmTfBpX5D5odFoqz4uXoSgtvxKLeOYo=
+github.com/google/go-licenses v0.0.0-20200602185517-f29a4c695c3d h1:r8YwMrdIrMvQUlRJT/D5BCIy42bMMxS7zxV89k0i3ik=
+github.com/google/go-licenses v0.0.0-20200602185517-f29a4c695c3d/go.mod h1:g1VOUGKZYIqe8lDq2mL7plhAWXqrEaGUs7eIjthN1sk=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -343,6 +386,7 @@ github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -468,6 +512,8 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
@@ -483,6 +529,8 @@ github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0 h1:reN85Pxc5larApoH1keMBiu2GWtPqXQ1nc9gx+jOU+E=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
+github.com/kisielk/errcheck v1.3.0 h1:LT9MIcYaA4MhK2jGb1DIWjJY8nnzC/bBqgKYhbWq+lk=
+github.com/kisielk/errcheck v1.3.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -542,6 +590,10 @@ github.com/mitchellh/mapstructure v1.2.2 h1:dxe5oCinTXiTIcfgmZecdCzPmAJKd46KsCWc
github.com/mitchellh/mapstructure v1.2.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.3.0 h1:iDwIio/3gk2QtLLEsqU5lInaMzos0hDTz8a6lazSFVw=
github.com/mitchellh/mapstructure v1.3.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.3.1 h1:cCBH2gTD2K0OtLlv/Y5H01VQCqmlDxz30kS5Y5bqfLA=
+github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg=
+github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
@@ -575,6 +627,7 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
@@ -582,6 +635,8 @@ github.com/otiai10/copy v1.0.2 h1:DDNipYy6RkIkjMwy+AWzgKiNTyj2RUI9yEMeETEpVyc=
github.com/otiai10/copy v1.0.2/go.mod h1:c7RpqBkwMom4bYTSkLSym4VSJz/XtncWRAj/J4PEIMY=
github.com/otiai10/copy v1.1.1 h1:PH7IFlRQ6Fv9vYmuXbDRLdgTHoP1w483kPNUP2bskpo=
github.com/otiai10/copy v1.1.1/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw=
+github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k=
+github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
@@ -593,6 +648,8 @@ github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtb
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI=
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
+github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw=
+github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/peterh/liner v1.1.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/peterh/liner v1.2.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
@@ -614,6 +671,10 @@ github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD
github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_golang v1.6.0 h1:YVPodQOcK15POxhgARIvnDRVpLcuK8mglnMrWfyrw6A=
github.com/prometheus/client_golang v1.6.0/go.mod h1:ZLOG9ck3JLRdB5MgO8f+lLTe83AXG6ro35rLTxvnIl4=
+github.com/prometheus/client_golang v1.7.0 h1:wCi7urQOGBsYcQROHqpUUX4ct84xp40t9R9JX0FuA/U=
+github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
+github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
+github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
@@ -642,6 +703,10 @@ github.com/prometheus/procfs v0.0.10 h1:QJQN3jYQhkamO4mhfUWqdDH2asK7ONOI9MTWjyAx
github.com/prometheus/procfs v0.0.10/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia5qI=
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/prometheus/procfs v0.1.0 h1:jhMy6QXfi3y2HEzFoyuCj40z4OZIIHHPtFyCMftmvKA=
+github.com/prometheus/procfs v0.1.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
+github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
@@ -671,6 +736,10 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/skia-dev/go-systemd v0.0.0-20181025131956-1cc903e82ae4 h1:KPlmEyLo5r9hnWZq8O0B0Rj4AcRv/tJMqEgS6p0JMeQ=
github.com/skia-dev/go-systemd v0.0.0-20181025131956-1cc903e82ae4/go.mod h1:TUH3112UTh2tzE4XSwBwt7bCKnQbI7TPpAd0cbQ9RzY=
+github.com/skia-dev/go2ts v1.1.0 h1:jcd0AIOe7PxizwPsInBQA8X3cgLm4tGint/LMIKb1DE=
+github.com/skia-dev/go2ts v1.1.0/go.mod h1:pE59J8wf5IHSMtPhH8PmWq5ZTLt6p1Ih+4ODd9fkGXk=
+github.com/skia-dev/go2ts v1.3.0 h1:0MJfc4SBAlx+7ZeGsQA5zCKg59hcNapoi7AdqIGT9lo=
+github.com/skia-dev/go2ts v1.3.0/go.mod h1:pE59J8wf5IHSMtPhH8PmWq5ZTLt6p1Ih+4ODd9fkGXk=
github.com/skia-dev/google-api-go-client v0.10.1-0.20200109184256-16c3d6f408b2 h1:Id5JdSD66PKQQiiVFG1VXDVCT5U3DcDzJSReXRxKRLk=
github.com/skia-dev/google-api-go-client v0.10.1-0.20200109184256-16c3d6f408b2/go.mod h1:N0iTzjbw95ZVfOL7wVngmVXE2kG0NP+LYlq3QMwf9Qo=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -720,6 +789,10 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.0 h1:jlIyCplCJFULU/01vCkhKuTyc3OorI3bJFuw6obfgho=
+github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
@@ -732,6 +805,9 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/unrolled/secure v1.0.7 h1:BcQHp3iKZyZCKj5gRqwQG+5urnGBF00wGgoPPwtheVQ=
github.com/unrolled/secure v1.0.7/go.mod h1:uGc1OcRF8gCVBA+ANksKmvM85Hka6SZtQIbrKc3sHS4=
+github.com/unrolled/secure v1.0.8 h1:JaMvKbe4CRt8oyxVXn+xY+6jlqd7pyJNSVkmsBxxQsM=
+github.com/unrolled/secure v1.0.8/go.mod h1:fO+mEan+FLB0CdEnHf6Q4ZZVNqG+5fuLFnP8p0BXDPI=
+github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/vektra/mockery v0.0.0-20181123154057-e78b021dcbb5 h1:Xim2mBRFdXzXmKRO8DJg/FJtn/8Fj9NOEpO6+WuMPmk=
@@ -742,6 +818,8 @@ github.com/vektra/mockery v1.1.0 h1:P8cgAIM8zkpMud24keNCOrc1Fvd+nt1cmztK8ei/HXs=
github.com/vektra/mockery v1.1.0/go.mod h1:VcfZjKaFOPO+MpN4ZvwPjs4c48lkq1o3Ym8yHZJu0jU=
github.com/vektra/mockery v1.1.1 h1:tSw+5rMJKNTHWu12FfS8k5sU4Z8+7WsslcQdibtRgHI=
github.com/vektra/mockery v1.1.1/go.mod h1:VcfZjKaFOPO+MpN4ZvwPjs4c48lkq1o3Ym8yHZJu0jU=
+github.com/vektra/mockery v1.1.2 h1:uc0Yn67rJpjt8U/mAZimdCKn9AeA97BOkjpmtBSlfP4=
+github.com/vektra/mockery v1.1.2/go.mod h1:VcfZjKaFOPO+MpN4ZvwPjs4c48lkq1o3Ym8yHZJu0jU=
github.com/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc=
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs=
@@ -799,6 +877,64 @@ go.chromium.org/luci v0.0.0-20200512212603-d4bc79d85e4a h1:TOLBKdWKe+AjZib64Kgse
go.chromium.org/luci v0.0.0-20200512212603-d4bc79d85e4a/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
go.chromium.org/luci v0.0.0-20200514021706-fa8dd98fcf00 h1:6yUpK5/wUO+6kk27g8s4BHqrpH3fcBXF324pe+29HrM=
go.chromium.org/luci v0.0.0-20200514021706-fa8dd98fcf00/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200515024543-2c12eb51855f h1:z0WwiAYXwM8lSNE2TTI1Tpb5CZB2avXxwVD6kp5YXXw=
+go.chromium.org/luci v0.0.0-20200515024543-2c12eb51855f/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200516014619-ad87be4122fc h1:65cY8veo1OJckoGp9kEm7ceh98fd9hFDvbEciyl+s9Y=
+go.chromium.org/luci v0.0.0-20200516014619-ad87be4122fc/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200517015940-a4f4b073be33 h1:BovFCllMqHeCztxmDuubjJfv3yax7027zuPJYuQs4lU=
+go.chromium.org/luci v0.0.0-20200517015940-a4f4b073be33/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200519013512-8b5a1cbea884 h1:lLNMxIFXfqyE7azbApM5/WM+7LQp3d8JkKnKqX6Cm8A=
+go.chromium.org/luci v0.0.0-20200519013512-8b5a1cbea884/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200520021201-88b3eca655d0 h1:gLmv2w+XctPdD9Efsnu20x+mxYT5YhcjGDOtDwFHHTU=
+go.chromium.org/luci v0.0.0-20200520021201-88b3eca655d0/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200521015543-ca04aca21808 h1:Ev+amipbJHdTsWMg/7bjfagGxe+Y2cCsV2jFTv4KXuo=
+go.chromium.org/luci v0.0.0-20200521015543-ca04aca21808/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200522032345-09f90024e34d h1:dczu65GQ+3ZA9lBDVWwrxikF1zm7QAKVWc06kluGGJY=
+go.chromium.org/luci v0.0.0-20200522032345-09f90024e34d/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200522081855-29d5a88a1316 h1:0YgB/Hk5PuPq0Q/0yD8h+/x7L43378mFM9R8VOBqLH8=
+go.chromium.org/luci v0.0.0-20200522081855-29d5a88a1316/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200523054546-f0cbbf49e27f h1:jA8gzR8ENqD5O5xisx8/0NHdqJjg04rlaMDxa4oVVco=
+go.chromium.org/luci v0.0.0-20200523054546-f0cbbf49e27f/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200524184858-ab1d1916efef h1:n0YmaJQFhbnBvVQB/FETGkva8pCbT637Clp7K7bC9QY=
+go.chromium.org/luci v0.0.0-20200524184858-ab1d1916efef/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200526012907-6aaf9821073c h1:lL+V5nazifwK27w9oKF83yHbObKJqMVJOZ0lP2lt//I=
+go.chromium.org/luci v0.0.0-20200526012907-6aaf9821073c/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200527050003-08773ee1fd99 h1:0YtUSYRgpmNqantY7z8MjAsLscRuELXJcAPLU7QkJIQ=
+go.chromium.org/luci v0.0.0-20200527050003-08773ee1fd99/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200528030809-4fafa61b2ec1 h1:ejFyKIul/rCJSD64b9MXFo3RiVQjtpz5bghmQT0uHE8=
+go.chromium.org/luci v0.0.0-20200528030809-4fafa61b2ec1/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200529044848-7e5bce570be3 h1:CemjuuinBFQO9z3/CEfJpRfXHAhqj2NzsnAoPV9GYdo=
+go.chromium.org/luci v0.0.0-20200529044848-7e5bce570be3/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200530010316-74c9d53547b2 h1:POIExLlsGsdfjf33bDnTQoUVAiHRkouD0iHCaODliZk=
+go.chromium.org/luci v0.0.0-20200530010316-74c9d53547b2/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200530205650-69abefee5f1a h1:lX9MkmpQztfZDYNh+T5C8A+wDoYaHVl8rLdEI7VNpCc=
+go.chromium.org/luci v0.0.0-20200530205650-69abefee5f1a/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200531062644-3e6d1e814914 h1:ZtNuLMJ+8/UL2dAQsQwtHZvoFd+bvIYr8fvYdpeFtpE=
+go.chromium.org/luci v0.0.0-20200531062644-3e6d1e814914/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200602010101-22381a3ca5d8 h1:nh9cuIW15llNjMU5w0/AM3cLOV6X1yg3RtUevykUIO4=
+go.chromium.org/luci v0.0.0-20200602010101-22381a3ca5d8/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200603035826-6f83db364f7f h1:7JuZujdZDxrgVL5ZEs2gY//MMIPJXrtPlTK2T+qlGig=
+go.chromium.org/luci v0.0.0-20200603035826-6f83db364f7f/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200604042319-a5a7ce1799fa h1:E42yWOcJQIhOnOGH6by9wWIQT7H7pyyBsYJVlOsLrI4=
+go.chromium.org/luci v0.0.0-20200604042319-a5a7ce1799fa/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200605045204-39c0f2d93834 h1:9v7x9nGhW8VpQxHTmCDLEE1aORWrO33u6c2UUAUUMWg=
+go.chromium.org/luci v0.0.0-20200605045204-39c0f2d93834/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200605231454-b70b93d4ae6d h1:wQ9yA9PJfTskgIfszZS+y9n7oNrYNutFZxItzpjQM+g=
+go.chromium.org/luci v0.0.0-20200605231454-b70b93d4ae6d/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200606210838-0cf95fe43711 h1:w40rE6vljasTHsgSantm2YEmUgO3V8AfNcx+RBp0bmQ=
+go.chromium.org/luci v0.0.0-20200606210838-0cf95fe43711/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200607214229-335dfe308d12 h1:SW4K2pCWkD9JJIJejDmMdvsmoaOBLdgk/a5J3WcPggU=
+go.chromium.org/luci v0.0.0-20200607214229-335dfe308d12/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200610031951-aa35210c29b0 h1:t1mvHoACc3BTwLszzxklvj5DhFgeF2bM0srv6yPP4r4=
+go.chromium.org/luci v0.0.0-20200610031951-aa35210c29b0/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200616031706-d0fdf43f911f h1:YzAEJZzV9ML+5k5a99zUa0TVzg5LguU0Mh680T9H7Go=
+go.chromium.org/luci v0.0.0-20200616031706-d0fdf43f911f/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200617043411-34dd37734506 h1:SimW6kdpOPUzQxbfsGjmC6/MGj2+2Qe9JFfUPtWH4Ac=
+go.chromium.org/luci v0.0.0-20200617043411-34dd37734506/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200620051646-b4124b2326a0 h1:KbTWugpDXgM5wSYWAlmp0NPxxj65l3COVTbPxJaoUXs=
+go.chromium.org/luci v0.0.0-20200620051646-b4124b2326a0/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
+go.chromium.org/luci v0.0.0-20200624214209-c1ada0c7a303 h1:P3/DuOPaxxznXpgYVLBevVnGSGFZsxwA1MYOCG+pufg=
+go.chromium.org/luci v0.0.0-20200624214209-c1ada0c7a303/go.mod h1:MIQewVTLvOvc0UioV0JNqTNO/RspKFS0XEeoKrOxsdM=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
@@ -811,6 +947,8 @@ go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto=
+go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.skia.org/infra v0.0.0-20200426051548-d5561681c574 h1:ncyx3a9Y+Z+dWmTxoZpiP+KAugNHXzBuCN8cgiajXwU=
go.skia.org/infra v0.0.0-20200426051548-d5561681c574/go.mod h1:oBRD8ErmsFrK7iGrag6lV1O0mGWUHkUEKnJMz5bLIuo=
go.skia.org/infra v0.0.0-20200427173615-ee504c19b426 h1:TgOSfFggLtGANTRzWQZcnIFJvzsjVugqbCewJrs0fHk=
@@ -847,6 +985,58 @@ go.skia.org/infra v0.0.0-20200512194548-951341df22eb h1:2SaF0/4WKl7qK4dnuL6Kqwub
go.skia.org/infra v0.0.0-20200512194548-951341df22eb/go.mod h1:nLrngGIDY14mGE2QHyNdZwVdFjFy1fiQt8BuITWnQUE=
go.skia.org/infra v0.0.0-20200513214741-b48b7541705b h1:CvAf0vQNYfGestzVEnPlC/FivS0lOO2Yy4GGMu+9wd8=
go.skia.org/infra v0.0.0-20200513214741-b48b7541705b/go.mod h1:tBQDukWk2xVQloTQm8u0NEMLogJotYLaIIRGaW8ptzU=
+go.skia.org/infra v0.0.0-20200514203654-68437497a177 h1:dkJUApDvQd0YelLlTtOw8e2t+rPiqTi0BXROdTPstvo=
+go.skia.org/infra v0.0.0-20200514203654-68437497a177/go.mod h1:ZYLSLco+ZPsUvsLIuHQ4imULI2iQpIsqjJgQV51nJYQ=
+go.skia.org/infra v0.0.0-20200515201715-a7a36bfa3904 h1:zBqjjxRqYNanPs/u1eG+OS5ES2NDze5+YgUHpR/ECiw=
+go.skia.org/infra v0.0.0-20200515201715-a7a36bfa3904/go.mod h1:RgvrC4IwpwLL8pGY6Ky+jvo4ESN6QIhDCTLuQRMLS+Y=
+go.skia.org/infra v0.0.0-20200517003836-a97023535be0 h1:5Y3+W824N7nyN6jtRQ5nVIR4+F6X82yanNCKy3+mfZk=
+go.skia.org/infra v0.0.0-20200517003836-a97023535be0/go.mod h1:wUNkV36PKChD+FqXnbutU+CTrowS34zogZxR7dM9/Qw=
+go.skia.org/infra v0.0.0-20200517051906-a6ca5c350a27 h1:uoETWhQd19HZtOCpyrtJF2N40JKJRSBDc8r/H+RrFwE=
+go.skia.org/infra v0.0.0-20200517051906-a6ca5c350a27/go.mod h1:r4menQ81DCh2Z8F1VQrVwTF6MfjF+SjiNBNuhw/zOVk=
+go.skia.org/infra v0.0.0-20200518163317-d13378041764 h1:TxP8bWoGbxkKe/7qy42lzKWjLR0lQgXHdL+xEfPcFE0=
+go.skia.org/infra v0.0.0-20200518163317-d13378041764/go.mod h1:YUonajNEXmp2zXY4nCjq71u2jS3buVVmcwRJkqPemt4=
+go.skia.org/infra v0.0.0-20200519192145-3e17804945b5 h1:b7XWeRG85a6L6XyM3nwUkLr4Pxji7f50v3fmTUyQdac=
+go.skia.org/infra v0.0.0-20200519192145-3e17804945b5/go.mod h1:TrfsolBfPGSzcdhyDUunXeiiib2qh8QdR03x0e2DDvY=
+go.skia.org/infra v0.0.0-20200521012806-adfecbf4d12b h1:1/XcccQg9+H2mnXdngmy9S9gqwVQGbctktDXRWq55C4=
+go.skia.org/infra v0.0.0-20200521012806-adfecbf4d12b/go.mod h1:TrfsolBfPGSzcdhyDUunXeiiib2qh8QdR03x0e2DDvY=
+go.skia.org/infra v0.0.0-20200521174639-5a4c3706743c h1:0w6wK5H9yJFYubuABdlN0mm/fYF5+16ZC27bh2JII9s=
+go.skia.org/infra v0.0.0-20200521174639-5a4c3706743c/go.mod h1:TrfsolBfPGSzcdhyDUunXeiiib2qh8QdR03x0e2DDvY=
+go.skia.org/infra v0.0.0-20200522021524-374ac39a37f3 h1:oyfXrRT5bcy9ov2cDmv9JK2jUj2SU7TGuZouUtAD7uA=
+go.skia.org/infra v0.0.0-20200522021524-374ac39a37f3/go.mod h1:TrfsolBfPGSzcdhyDUunXeiiib2qh8QdR03x0e2DDvY=
+go.skia.org/infra v0.0.0-20200524051606-dbb4c0a8b550 h1:y5cO+QUeKajZ4+0KBLLvqO1YXtQI0pLfds+xbfGUm30=
+go.skia.org/infra v0.0.0-20200524051606-dbb4c0a8b550/go.mod h1:TrfsolBfPGSzcdhyDUunXeiiib2qh8QdR03x0e2DDvY=
+go.skia.org/infra v0.0.0-20200526214647-c7b51d93a48c h1:bFMJCTNpW7Dg5aQXgtmCLmmyNjP3YRsntszb6zqZOtQ=
+go.skia.org/infra v0.0.0-20200526214647-c7b51d93a48c/go.mod h1:TrfsolBfPGSzcdhyDUunXeiiib2qh8QdR03x0e2DDvY=
+go.skia.org/infra v0.0.0-20200527211736-fd92f6d87408 h1:oZCbx0/QT0YDZpM4zXQmjnb/V2y9lVGLFkmRBMACojE=
+go.skia.org/infra v0.0.0-20200527211736-fd92f6d87408/go.mod h1:TrfsolBfPGSzcdhyDUunXeiiib2qh8QdR03x0e2DDvY=
+go.skia.org/infra v0.0.0-20200529025909-067ee0d9cae2 h1:2jMoZlANXkH0DxmTkTdfw9Zow1/s/HBUZqD0bu3aoHA=
+go.skia.org/infra v0.0.0-20200529025909-067ee0d9cae2/go.mod h1:j3HKJ6UWFS8tfOIpvG6v5W/j+Adn29iDhccrSXUvNNY=
+go.skia.org/infra v0.0.0-20200529222451-b641a303256d h1:31V/uagC9bhiRoYqPnGRaIx2pzYcOhGBNuFPXukSn6w=
+go.skia.org/infra v0.0.0-20200529222451-b641a303256d/go.mod h1:dJEDl07151HEE01+fxbLF++Q/vg05jY5ncsnZnoMpKI=
+go.skia.org/infra v0.0.0-20200530052006-537aafa16b0c h1:KjVTmo/5MWxcVq9TFJbMPqd/qtvtpUpNU3SNmoKyyNE=
+go.skia.org/infra v0.0.0-20200530052006-537aafa16b0c/go.mod h1:LhPONsfnCn1CZ+8hUZwizdGjKpwhOLVBbTpeLQKotLI=
+go.skia.org/infra v0.0.0-20200531235413-49ee856d9221 h1:mwwLw4G9yVKLrATCCojYJaGLDzYO3hxqTuPxRJUIi6M=
+go.skia.org/infra v0.0.0-20200531235413-49ee856d9221/go.mod h1:FGT/VEEXbjSkv4BLKOaOTIwnN5UuOVq+otgfuRNnyuo=
+go.skia.org/infra v0.0.0-20200601172913-661352160768 h1:2Ost47UuFoayaOOw9ViWobzVllXGSzG9PvD7BMxjx+0=
+go.skia.org/infra v0.0.0-20200601172913-661352160768/go.mod h1:kHaLU+44ROLRPXzBM8T+I228aI5I3iLyQJfl7jKgNV0=
+go.skia.org/infra v0.0.0-20200602205122-4b2f488e41f2 h1:BDmPEnFuRjA1hse1mrtENFdNWI/xbeuK1Ud+zjOGpPY=
+go.skia.org/infra v0.0.0-20200602205122-4b2f488e41f2/go.mod h1:V3DIL+P3Z02iAcrN6fv12VdGmcGk0Ilnll9AaJMwcJ8=
+go.skia.org/infra v0.0.0-20200603202721-a6e610f118bb h1:E5FJMOSsxV2rO8BQCCoWmHupW452aZnsPxmyucdSZ2U=
+go.skia.org/infra v0.0.0-20200603202721-a6e610f118bb/go.mod h1:fWqpZS0bMv6mNkxuLcBO3QT99/esXYMStxWBump650A=
+go.skia.org/infra v0.0.0-20200604211856-3c19627e244c h1:b+GM2TnLzcrLmErKUhfAAo+2LszF4ytZ0a3JRxPcsTg=
+go.skia.org/infra v0.0.0-20200604211856-3c19627e244c/go.mod h1:rZheB7d1g56dFa1+ppg+MM+eLIFOU0FtWjOH9qt0+js=
+go.skia.org/infra v0.0.0-20200605163027-b867fb6b6232 h1:1Ijp82P9IWeUQxp5GksR9lNpewQrapamOoL5bM4U6Zg=
+go.skia.org/infra v0.0.0-20200605163027-b867fb6b6232/go.mod h1:rUspbipWPw+4biwgLMMx4G+N98efd9fe9bGN5w3McX0=
+go.skia.org/infra v0.0.0-20200607051952-f5b0a6c1ff19 h1:r7jv7+kc3/GWF6V6F41DGewz8I88JPZ/8SJgIOzAO4g=
+go.skia.org/infra v0.0.0-20200607051952-f5b0a6c1ff19/go.mod h1:rUspbipWPw+4biwgLMMx4G+N98efd9fe9bGN5w3McX0=
+go.skia.org/infra v0.0.0-20200616030136-5b68b7891c11 h1:7mRcsdA0SA+ZBlr/hIaqyObrLOJJiLoNDtIQfcm4HXM=
+go.skia.org/infra v0.0.0-20200616030136-5b68b7891c11/go.mod h1:zZzuuDGdQ4PWDlSeT6XES2oeGAN0MC3Si7jAqktPpj0=
+go.skia.org/infra v0.0.0-20200616185547-28019d8c7381 h1:ufnikxI51+amDAf+4DtT31CmmfF0qAyRHMxt44rqp9o=
+go.skia.org/infra v0.0.0-20200616185547-28019d8c7381/go.mod h1:zZzuuDGdQ4PWDlSeT6XES2oeGAN0MC3Si7jAqktPpj0=
+go.skia.org/infra v0.0.0-20200620150920-23b7fda631d5 h1:3vYt68R8Bw8eYBbuh0e/olkspGyJqIbcfMNGJjc1x3A=
+go.skia.org/infra v0.0.0-20200620150920-23b7fda631d5/go.mod h1:pMsp+TR1J9uXYYdx1eb5CN6l89l0h9jloETXMKmesPM=
+go.skia.org/infra v0.0.0-20200624212929-6c6f866a7d58 h1:z1yyY9tpiiqrgeskjVoJhTZoI7xXRc8tQYEACM7I8TA=
+go.skia.org/infra v0.0.0-20200624212929-6c6f866a7d58/go.mod h1:pMsp+TR1J9uXYYdx1eb5CN6l89l0h9jloETXMKmesPM=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
@@ -880,6 +1070,12 @@ golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROx
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200602180216-279210d13fed h1:g4KENRiCMEx58Q7/ecwfT0N2o8z35Fnbsjig/Alf2T4=
+golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM=
+golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -923,6 +1119,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -977,6 +1175,16 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f h1:QBjCr1Fz5kw158VqdE9JfI9cJ
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120 h1:EZ3cVSzKOlJxAd8e8YAJ7no8nNypTxexh/YE/xW3ZEY=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0=
+golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 h1:eDrdRpKgkcCqKZQwyZRyeFZgfqt37SL7Kv3tok06cKE=
+golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200528225125-3c3fba18258b h1:IYiJPiJfzktmDAO1HQiwjMjwjlYKHAL7KzeD544RJPs=
+golang.org/x/net v0.0.0-20200528225125-3c3fba18258b/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
+golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1065,12 +1273,28 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25 h1:OKbAoGs4fGM5cPLlVQLZGYkFC
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200513112337-417ce2331b5c h1:kISX68E8gSkNYAFRFiDU8rl5RIn1sJYKYb/r2vMLDrU=
golang.org/x/sys v0.0.0-20200513112337-417ce2331b5c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9 h1:YTzHMGlqJu67/uEo1lBv0n3wBXhXNeUbB1XfN2vmTm0=
+golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
+golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o=
+golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y=
+golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200620081246-981b61492c35 h1:wb/9mP8eUAmHfkM8RmpeLq6nUA7c2i5+bQOtcDftjaE=
+golang.org/x/sys v0.0.0-20200620081246-981b61492c35/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8=
+golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
@@ -1084,6 +1308,7 @@ golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181112210238-4b1f3b6b1646/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190213135902-6bedcd10978a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
@@ -1175,6 +1400,51 @@ golang.org/x/tools v0.0.0-20200513022744-65e69ff2d148 h1:X3wiF+nWEwv11fBoJVQN0dS
golang.org/x/tools v0.0.0-20200513022744-65e69ff2d148/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200513201620-d5fe73897c97 h1:DAuln/hGp+aJiHpID1Y1hYzMEPP5WLwtZHPb50mN0OE=
golang.org/x/tools v0.0.0-20200513201620-d5fe73897c97/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d h1:n6zwymXmN9rCClNNmCWwV3qwMmBcRw/WeIGDK8Qnzk4=
+golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200515220128-d3bf790afa53 h1:vmsb6v0zUdmUlXfwKaYrHPPRCV0lHq/IwNIf0ASGjyQ=
+golang.org/x/tools v0.0.0-20200515220128-d3bf790afa53/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200519015757-0d0afa43d58a h1:gILuVKC+ZPD6g/tj6zBOdnOH1ZHI0zZ86+KLMogc6/s=
+golang.org/x/tools v0.0.0-20200519015757-0d0afa43d58a/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200519205726-57a9e4404bf7 h1:nm4zDh9WvH4jiuUpMY5RUsvOwrtTVVAsUaCdLW71hfY=
+golang.org/x/tools v0.0.0-20200519205726-57a9e4404bf7/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200520220537-cf2d1e09c845 h1:F4gQH8TKyCccYDuNHX5TfZwiM8QWnPbSPUFE96qvGbs=
+golang.org/x/tools v0.0.0-20200520220537-cf2d1e09c845/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200521211927-2b542361a4fc h1:6m2YO+AmBApbUOmhsghW+IfRyZOY4My4UYvQQrEpHfY=
+golang.org/x/tools v0.0.0-20200521211927-2b542361a4fc/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375 h1:SjQ2+AKWgZLc1xej6WSzL+Dfs5Uyd5xcZH1mGC411IA=
+golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200526224456-8b020aee10d2 h1:21BqcH/onxtGHn1A2GDOJjZnbt4Nlez629S3eaR+eYs=
+golang.org/x/tools v0.0.0-20200526224456-8b020aee10d2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200527183253-8e7acdbce89d h1:SR+e35rACZFBohNb4Om1ibX6N3iO0FtdbwqGSuD9dBU=
+golang.org/x/tools v0.0.0-20200527183253-8e7acdbce89d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200528185414-6be401e3f76e h1:jTL1CJ2kmavapMVdBKy6oVrhBHByRCMfykS45+lEFQk=
+golang.org/x/tools v0.0.0-20200528185414-6be401e3f76e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200529172331-a64b76657301 h1:G6CNEgFU8/XwexSnuFw+Jq/WePjRitgy6ofBcPnAIPo=
+golang.org/x/tools v0.0.0-20200529172331-a64b76657301/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200530233709-52effbd89c51 h1:Wec8/IO8hAraBf0it7/dPQYOslIrgM938wZYNkLnOYc=
+golang.org/x/tools v0.0.0-20200530233709-52effbd89c51/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200601175630-2caf76543d99 h1:deddXmhOJb/bvD/4M/j2AUMrhHeh6GkqykJSCWyTNVk=
+golang.org/x/tools v0.0.0-20200601175630-2caf76543d99/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200604042327-9b20fe4cabe8 h1:8Xr1qwxn90MXYKftwNxIO2g4J+26naghxFS5rYiTZww=
+golang.org/x/tools v0.0.0-20200604042327-9b20fe4cabe8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200604183345-4d5ea46c79fe h1:nHJ3EpvC/Nk6Gc4FTwTQ3YOBAODRx412L5jEPjgJcEg=
+golang.org/x/tools v0.0.0-20200604183345-4d5ea46c79fe/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200606014950-c42cb6316fb6 h1:5Y8c5HBW6hBYnGEE3AbJPV0R8RsQmg1/eaJrpvasns0=
+golang.org/x/tools v0.0.0-20200606014950-c42cb6316fb6/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200609164405-eb789aa7ce50/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200615222825-6aa8f57aacd9 h1:cwgUY+1ja2qxWb2dyaCoixaA66WGWmrijSlxaM+JM/g=
+golang.org/x/tools v0.0.0-20200615222825-6aa8f57aacd9/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200617042924-7f3f4b10a808 h1:t4rDo0JMqBOEHVnboBBPY/e1U1exx2OO5lL/TcfJM28=
+golang.org/x/tools v0.0.0-20200617042924-7f3f4b10a808/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2 h1:FD4wDsP+CQUqh2V12OBOt90pLHVToe58P++fUu3ggV4=
+golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200619210111-0f592d2728bb h1:/7SQoPdMxZ0c/Zu9tBJgMbRE/BmK6i9QXflNJXKAmw0=
+golang.org/x/tools v0.0.0-20200619210111-0f592d2728bb/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff h1:foic6oVZ4MKltJC6MXzuFZFswE7NCjjtc0Hxbyblawc=
+golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1211,6 +1481,14 @@ google.golang.org/api v0.23.0 h1:YlvGEOq2NA2my8cZ/9V8BcEO9okD48FlJcdqN0xJL3s=
google.golang.org/api v0.23.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.24.0 h1:cG03eaksBzhfSIk7JRGctfp3lanklcOM/mTGvow7BbQ=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.25.0 h1:LodzhlzZEUfhXzNUMIfVlf9Gr6Ua5MMtoFWh7+f47qA=
+google.golang.org/api v0.25.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.26.0 h1:VJZ8h6E8ip82FRpQl848c5vAadxlTXrUh8RzQzSRm08=
+google.golang.org/api v0.26.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.27.0 h1:L02vxokXh9byvvyTw3PLA4MmNri7cY29nliyK4MnIxY=
+google.golang.org/api v0.27.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.28.0 h1:jMF5hhVfMkTZwHW1SDpKq5CkgWLXOb31Foaca9Zr3oM=
+google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -1280,6 +1558,43 @@ google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380 h1:xriR1EgvKfkKxIo
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884 h1:fiNLklpBwWK1mth30Hlwk+fcdBmIALlgF5iy77O37Ig=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200514193133-8feb7f20f2a2 h1:RwW6+LxyOQJ7oeoZ76GIJlwt/O0J5cN2fk+q/jK27kQ=
+google.golang.org/genproto v0.0.0-20200514193133-8feb7f20f2a2/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
+google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587 h1:1Ym+vvUpq1ZHvxzn34gENJX8U4aKO+vhy2P/2+Xl6qQ=
+google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
+google.golang.org/genproto v0.0.0-20200519141106-08726f379972 h1:6ydLqG65DIMNJf6p97WudGsmd1w3Ickm/LiZnBrREPI=
+google.golang.org/genproto v0.0.0-20200519141106-08726f379972/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
+google.golang.org/genproto v0.0.0-20200521103424-e9a78aa275b7 h1:JUs1uIDQ46c7iI0QuMPzAHqXaSmqKF0f9freFMk2ivs=
+google.golang.org/genproto v0.0.0-20200521103424-e9a78aa275b7/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece h1:1YM0uhfumvoDu9sx8+RyWwTI63zoCQvI23IYFRlvte0=
+google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200528110217-3d3490e7e671/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200528191852-705c0b31589b h1:nl5tymnV+50ACFZUDAP+xFCe3Zh3SWdMDx+ernZSKNA=
+google.golang.org/genproto v0.0.0-20200528191852-705c0b31589b/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200601130524-0f60399e6634 h1:yUEnIJPm1I2GGauN1xOkwj6gXw/3t1R+HA1r/cdnkHE=
+google.golang.org/genproto v0.0.0-20200601130524-0f60399e6634/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200602104108-2bb8d6132df6 h1:fsxmG3uIxSjgTNy6zSkdHSyElfRV0Tq+yzS+Ukjthx0=
+google.golang.org/genproto v0.0.0-20200602104108-2bb8d6132df6/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200603110839-e855014d5736 h1:+IE3xTD+6Eb7QWG5JFp+dQr/XjKpjmrNkh4pdjTdHEs=
+google.golang.org/genproto v0.0.0-20200603110839-e855014d5736/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200604104852-0b0486081ffb h1:ek2py5bOqzR7MR/6obzk0rXUgYCLmjyLnaO9ssT+l6w=
+google.golang.org/genproto v0.0.0-20200604104852-0b0486081ffb/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200605102947-12044bf5ea91 h1:ES+5k7Xz+sYByd2L7mvcanaIuY0Iz3L3O6OhN+cRdu8=
+google.golang.org/genproto v0.0.0-20200605102947-12044bf5ea91/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200608115520-7c474a2e3482/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200615140333-fd031eab31e7 h1:1N7l1PuXZwEK7OhHdmKQROOM75PnUjABGwvVRbLBgFk=
+google.golang.org/genproto v0.0.0-20200615140333-fd031eab31e7/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200617032506-f1bdc9086088 h1:XXo4PvhJkaWYIkwn7bX7mcdB8RdcOvn12HbaUUAwX3E=
+google.golang.org/genproto v0.0.0-20200617032506-f1bdc9086088/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790 h1:FGjyjrQGURdc98leD1P65IdQD9Zlr4McvRcqIlV6OSs=
+google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200620020550-bd6e04640131 h1:IXNofpkLhv80L3TJQvj2YQLnMHZgAktycswvtXwQiRk=
+google.golang.org/genproto v0.0.0-20200620020550-bd6e04640131/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200623002339-fbb79eadd5eb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad h1:uAwc13+y0Y8QZLTYhLCu6lHhnG99ecQU5FYTj8zxAng=
+google.golang.org/genproto v0.0.0-20200624020401-64a14ca9d1ad/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU=
@@ -1304,6 +1619,8 @@ google.golang.org/grpc v1.29.0 h1:2pJjwYOdkZ9HlN4sWRYBg9ttH5bCOlsueaM+b/oYjwo=
google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE=
+google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -1312,6 +1629,13 @@ google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zim
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -1330,6 +1654,8 @@ gopkg.in/ini.v1 v1.55.0 h1:E8yzL5unfpW3M6fz/eB7Cb5MQAYSZ7GKo4Qth+N2sgQ=
gopkg.in/ini.v1 v1.55.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.56.0 h1:DPMeDvGTM54DXbPkVIZsp19fp/I2K7zwA/itHYHKo8Y=
gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww=
+gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/olivere/elastic.v5 v5.0.85 h1:GwBqEsvRIHVfCQVXDHYi9LHec2yEkc3GNKh9WB8G/es=
gopkg.in/olivere/elastic.v5 v5.0.85/go.mod h1:M3WNlsF+WhYn7api4D87NIflwTV/c0iVs8cqfWhK+68=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
@@ -1355,6 +1681,20 @@ gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86 h1:OfFoIUYv/me30yv7XlMy4F9RJw8DEm8WQ6QG1Ph4bH0=
+gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200601152816-913338de1bd2 h1:VEmvx0P+GVTgkNu2EdTN988YCZPcD3lo9AoczZpucwc=
+gopkg.in/yaml.v3 v3.0.0-20200601152816-913338de1bd2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200602174320-3e3e88ca92fa h1:5lGs+2OAqZvyIo1XjvoyXoDb8g6k9uAg2WTflQT/yl8=
+gopkg.in/yaml.v3 v3.0.0-20200602174320-3e3e88ca92fa/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200603094226-e3079894b1e8 h1:jL/vaozO53FMfZLySWM+4nulF3gQEC6q5jH90LPomDo=
+gopkg.in/yaml.v3 v3.0.0-20200603094226-e3079894b1e8/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo=
+gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -1365,18 +1705,27 @@ honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXe
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8=
+honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.18.2 h1:wG5g5ZmSVgm5B+eHMIbI9EGATS2L8Z72rda19RIEgY8=
k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78=
+k8s.io/api v0.18.3 h1:2AJaUQdgUZLoDZHrun21PW2Nx9+ll6cUzvn3IKhSIn0=
+k8s.io/api v0.18.3/go.mod h1:UOaMwERbqJMfeeeHc8XJKawj4P9TgDRnViIqqBeH2QA=
k8s.io/apimachinery v0.18.2 h1:44CmtbmkzVDAhCpRVSiP2R5PPrC2RtlIv/MoB8xpdRA=
k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
+k8s.io/apimachinery v0.18.3 h1:pOGcbVAhxADgUYnjS08EFXs9QMl8qaH5U4fr5LGUrSk=
+k8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
k8s.io/client-go v0.18.2 h1:aLB0iaD4nmwh7arT2wIn+lMnAq7OswjaejkQ8p9bBYE=
k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU=
+k8s.io/client-go v0.18.3 h1:QaJzz92tsN67oorwzmoB0a9r9ZVHuD5ryjbCKP0U22k=
+k8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
+k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg=
diff --git a/chromium/third_party/skia/include/android/SkBitmapRegionDecoder.h b/chromium/third_party/skia/include/android/SkBitmapRegionDecoder.h
deleted file mode 100644
index 18ba90b7741..00000000000
--- a/chromium/third_party/skia/include/android/SkBitmapRegionDecoder.h
+++ /dev/null
@@ -1,92 +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 SkBitmapRegionDecoder_DEFINED
-#define SkBitmapRegionDecoder_DEFINED
-
-#include "include/android/SkBRDAllocator.h"
-#include "include/core/SkBitmap.h"
-#include "include/core/SkEncodedImageFormat.h"
-#include "include/core/SkStream.h"
-
-/*
- * This class aims to provide an interface to test multiple implementations of
- * SkBitmapRegionDecoder.
- */
-class SK_API SkBitmapRegionDecoder {
-public:
-
- enum Strategy {
- kAndroidCodec_Strategy, // Uses SkAndroidCodec for scaling and subsetting
- };
-
- /*
- * @param data Refs the data while this object exists, unrefs on destruction
- * @param strategy Strategy used for scaling and subsetting
- * @return Tries to create an SkBitmapRegionDecoder, returns NULL on failure
- */
- static SkBitmapRegionDecoder* Create(sk_sp<SkData>, Strategy strategy);
-
- /*
- * @param stream Takes ownership of the stream
- * @param strategy Strategy used for scaling and subsetting
- * @return Tries to create an SkBitmapRegionDecoder, returns NULL on failure
- */
- static SkBitmapRegionDecoder* Create(
- SkStreamRewindable* stream, Strategy strategy);
-
- /*
- * Decode a scaled region of the encoded image stream
- *
- * @param bitmap Container for decoded pixels. It is assumed that the pixels
- * are initially unallocated and will be allocated by this function.
- * @param allocator Allocator for the pixels. If this is NULL, the default
- * allocator (HeapAllocator) will be used.
- * @param desiredSubset Subset of the original image to decode.
- * @param sampleSize An integer downscaling factor for the decode.
- * @param colorType Preferred output colorType.
- * New implementations should return NULL if they do not support
- * decoding to this color type.
- * The old kOriginal_Strategy will decode to a default color type
- * if this color type is unsupported.
- * @param requireUnpremul If the image is not opaque, we will use this to determine the
- * alpha type to use.
- * @param prefColorSpace If non-null and supported, this is the color space that we will
- * decode into. Otherwise, we will choose a default.
- *
- */
- virtual bool decodeRegion(SkBitmap* bitmap, SkBRDAllocator* allocator,
- const SkIRect& desiredSubset, int sampleSize,
- SkColorType colorType, bool requireUnpremul,
- sk_sp<SkColorSpace> prefColorSpace = nullptr) = 0;
-
- virtual SkEncodedImageFormat getEncodedFormat() = 0;
-
- virtual SkColorType computeOutputColorType(SkColorType requestedColorType) = 0;
-
- virtual sk_sp<SkColorSpace> computeOutputColorSpace(SkColorType outputColorType,
- sk_sp<SkColorSpace> prefColorSpace = nullptr) = 0;
-
-
- int width() const { return fWidth; }
- int height() const { return fHeight; }
-
- virtual ~SkBitmapRegionDecoder() {}
-
-protected:
-
- SkBitmapRegionDecoder(int width, int height)
- : fWidth(width)
- , fHeight(height)
- {}
-
-private:
- const int fWidth;
- const int fHeight;
-};
-
-#endif
diff --git a/chromium/third_party/skia/include/atlastext/SkAtlasTextContext.h b/chromium/third_party/skia/include/atlastext/SkAtlasTextContext.h
deleted file mode 100644
index d13ec51e231..00000000000
--- a/chromium/third_party/skia/include/atlastext/SkAtlasTextContext.h
+++ /dev/null
@@ -1,42 +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 SkAtlasTextContext_DEFINED
-#define SkAtlasTextContext_DEFINED
-
-#include "include/core/SkRefCnt.h"
-
-class SkAtlasTextRenderer;
-class SkInternalAtlasTextContext;
-
-SkAtlasTextRenderer* SkGetAtlasTextRendererFromInternalContext(class SkInternalAtlasTextContext&);
-
-/**
- * Class that Atlas Text client uses to register their SkAtlasTextRenderer implementation and
- * to create one or more SkAtlasTextTargets (destination surfaces for text rendering).
- */
-class SK_API SkAtlasTextContext : public SkRefCnt {
-public:
- static sk_sp<SkAtlasTextContext> Make(sk_sp<SkAtlasTextRenderer>);
-
- SkAtlasTextRenderer* renderer() const {
- return SkGetAtlasTextRendererFromInternalContext(*fInternalContext);
- }
-
- SkInternalAtlasTextContext& internal() { return *fInternalContext; }
-
-private:
- SkAtlasTextContext() = delete;
- SkAtlasTextContext(const SkAtlasTextContext&) = delete;
- SkAtlasTextContext& operator=(const SkAtlasTextContext&) = delete;
-
- SkAtlasTextContext(sk_sp<SkAtlasTextRenderer>);
-
- std::unique_ptr<SkInternalAtlasTextContext> fInternalContext;
-};
-
-#endif
diff --git a/chromium/third_party/skia/include/atlastext/SkAtlasTextFont.h b/chromium/third_party/skia/include/atlastext/SkAtlasTextFont.h
deleted file mode 100644
index 8bab5bfc85a..00000000000
--- a/chromium/third_party/skia/include/atlastext/SkAtlasTextFont.h
+++ /dev/null
@@ -1,38 +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 SkAtlasTextFont_DEFINED
-#define SkAtlasTextFont_DEFINED
-
-#include "include/core/SkFont.h"
-#include "include/core/SkRefCnt.h"
-#include "include/core/SkTypeface.h"
-
-/** Represents a font at a size. TODO: What else do we need here (skewX, scaleX, vertical, ...)? */
-class SK_API SkAtlasTextFont : public SkRefCnt {
-public:
- static sk_sp<SkAtlasTextFont> Make(sk_sp<SkTypeface> typeface, SkScalar size) {
- return sk_sp<SkAtlasTextFont>(new SkAtlasTextFont(std::move(typeface), size));
- }
-
- SkTypeface* typeface() const { return fTypeface.get(); }
-
- sk_sp<SkTypeface> refTypeface() const { return fTypeface; }
-
- SkScalar size() const { return fSize; }
-
- SkFont makeFont() const { return SkFont(fTypeface, fSize); }
-
-private:
- SkAtlasTextFont(sk_sp<SkTypeface> typeface, SkScalar size)
- : fTypeface(std::move(typeface)), fSize(size) {}
-
- sk_sp<SkTypeface> fTypeface;
- SkScalar fSize;
-};
-
-#endif
diff --git a/chromium/third_party/skia/include/atlastext/SkAtlasTextRenderer.h b/chromium/third_party/skia/include/atlastext/SkAtlasTextRenderer.h
deleted file mode 100644
index e572bb6e52d..00000000000
--- a/chromium/third_party/skia/include/atlastext/SkAtlasTextRenderer.h
+++ /dev/null
@@ -1,72 +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/core/SkPoint3.h"
-#include "include/core/SkRefCnt.h"
-
-#ifndef SkAtlasTextRenderer_DEFINED
-#define SkAtlasTextRenderer_DEFINED
-
-/**
- * This is the base class for a renderer implemented by the SkAtlasText client. The
- * SkAtlasTextContext issues texture creations, deletions, uploads, and vertex draws to the
- * renderer. The renderer must perform those actions in the order called to correctly render
- * the text drawn to SkAtlasTextTargets.
- */
-class SK_API SkAtlasTextRenderer : public SkRefCnt {
-public:
- enum class AtlasFormat {
- /** Unsigned normalized 8 bit single channel format. */
- kA8
- };
-
- struct SDFVertex {
- /** Position in device space (not normalized). The third component is w (not z). */
- SkPoint3 fPosition;
- /** Color, same value for all four corners of a glyph quad. */
- uint32_t fColor;
- /** Texture coordinate (in texel units, not normalized). */
- int16_t fTextureCoordX;
- int16_t fTextureCoordY;
- };
-
- virtual ~SkAtlasTextRenderer() = default;
-
- /**
- * Create a texture of the provided format with dimensions 'width' x 'height'
- * and return a unique handle.
- */
- virtual void* createTexture(AtlasFormat, int width, int height) = 0;
-
- /**
- * Delete the texture with the passed handle.
- */
- virtual void deleteTexture(void* textureHandle) = 0;
-
- /**
- * Place the pixel data specified by 'data' in the texture with handle
- * 'textureHandle' in the rectangle ['x', 'x' + 'width') x ['y', 'y' + 'height').
- * 'rowBytes' specifies the byte offset between successive rows in 'data' and will always be
- * a multiple of the number of bytes per pixel.
- * The pixel format of data is the same as that of 'textureHandle'.
- */
- virtual void setTextureData(void* textureHandle, const void* data, int x, int y, int width,
- int height, size_t rowBytes) = 0;
-
- /**
- * Draws glyphs using SDFs. The SDF data resides in 'textureHandle'. The array
- * 'vertices' provides interleaved device-space positions, colors, and
- * texture coordinates. There are are 4 * 'quadCnt' entries in 'vertices'.
- */
- virtual void drawSDFGlyphs(void* targetHandle, void* textureHandle, const SDFVertex vertices[],
- int quadCnt) = 0;
-
- /** Called when a SkAtlasTextureTarget is destroyed. */
- virtual void targetDeleted(void* targetHandle) = 0;
-};
-
-#endif
diff --git a/chromium/third_party/skia/include/atlastext/SkAtlasTextTarget.h b/chromium/third_party/skia/include/atlastext/SkAtlasTextTarget.h
deleted file mode 100644
index ca8eca71930..00000000000
--- a/chromium/third_party/skia/include/atlastext/SkAtlasTextTarget.h
+++ /dev/null
@@ -1,100 +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 SkAtlasTextTarget_DEFINED
-#define SkAtlasTextTarget_DEFINED
-
-#include "include/core/SkRefCnt.h"
-#include "include/core/SkScalar.h"
-#include "include/private/SkDeque.h"
-
-#include <memory>
-
-class SkAtlasTextContext;
-class SkAtlasTextFont;
-class SkMatrix;
-struct SkPoint;
-
-/** Represents a client-created renderable surface and is used to draw text into the surface. */
-class SK_API SkAtlasTextTarget {
-public:
- virtual ~SkAtlasTextTarget();
-
- /**
- * Creates a text drawing target. ‘handle’ is used to identify this rendering surface when
- * draws are flushed to the SkAtlasTextContext's SkAtlasTextRenderer.
- */
- static std::unique_ptr<SkAtlasTextTarget> Make(sk_sp<SkAtlasTextContext>,
- int width,
- int height,
- void* handle);
-
- /**
- * Enqueues a text draw in the target. The caller provides an array of glyphs and their
- * positions. The meaning of 'color' here is interpreted by the client's SkAtlasTextRenderer
- * when it actually renders the text.
- */
- virtual void drawText(const SkGlyphID[], const SkPoint[], int glyphCnt, uint32_t color,
- const SkAtlasTextFont&) = 0;
-
- /** Issues all queued text draws to SkAtlasTextRenderer. */
- virtual void flush() = 0;
-
- int width() const { return fWidth; }
- int height() const { return fHeight; }
-
- void* handle() const { return fHandle; }
-
- SkAtlasTextContext* context() const { return fContext.get(); }
-
- /** Saves the current matrix in a stack. Returns the prior depth of the saved matrix stack. */
- int save();
- /** Pops the top matrix on the stack if the stack is not empty. */
- void restore();
- /**
- * Pops the matrix stack until the stack depth is count. Does nothing if the depth is already
- * less than count.
- */
- void restoreToCount(int count);
-
- /** Pre-translates the current CTM. */
- void translate(SkScalar dx, SkScalar dy);
- /** Pre-scales the current CTM. */
- void scale(SkScalar sx, SkScalar sy);
- /** Pre-rotates the current CTM about the origin. */
- void rotate(SkScalar degrees);
- /** Pre-rotates the current CTM about the (px, py). */
- void rotate(SkScalar degrees, SkScalar px, SkScalar py);
- /** Pre-skews the current CTM. */
- void skew(SkScalar sx, SkScalar sy);
- /** Pre-concats the current CTM. */
- void concat(const SkMatrix& matrix);
-
-protected:
- SkAtlasTextTarget(sk_sp<SkAtlasTextContext>, int width, int height, void* handle);
-
- const SkMatrix& ctm() const { return *static_cast<const SkMatrix*>(fMatrixStack.back()); }
-
- void* const fHandle;
- const sk_sp<SkAtlasTextContext> fContext;
- const int fWidth;
- const int fHeight;
-
-private:
- SkDeque fMatrixStack;
- int fSaveCnt;
-
- SkMatrix* accessCTM() const {
- return static_cast<SkMatrix*>(const_cast<void*>(fMatrixStack.back()));
- }
-
- SkAtlasTextTarget() = delete;
- SkAtlasTextTarget(const SkAtlasTextContext&) = delete;
- SkAtlasTextTarget& operator=(const SkAtlasTextContext&) = delete;
-};
-
-#endif
diff --git a/chromium/third_party/skia/include/core/SkCanvas.h b/chromium/third_party/skia/include/core/SkCanvas.h
index 975aab059b6..36c4d3eeaeb 100644
--- a/chromium/third_party/skia/include/core/SkCanvas.h
+++ b/chromium/third_party/skia/include/core/SkCanvas.h
@@ -684,35 +684,6 @@ public:
, fSaveLayerFlags(saveLayerFlags)
{}
- /** Experimental. Not ready for general use.
- Sets fBounds, fPaint, fBackdrop, fClipMask, fClipMatrix, and fSaveLayerFlags.
- clipMatrix uses alpha channel of image, transformed by clipMatrix, to clip
- layer when drawn to SkCanvas.
-
- @param bounds layer dimensions; may be nullptr
- @param paint graphics state applied to layer when overlaying prior
- layer; may be nullptr
- @param backdrop If not null, this causes the current layer to be filtered by
- backdrop, and then drawn into the new layer
- (respecting the current clip).
- If null, the new layer is initialized with transparent-black.
- @param clipMask clip applied to layer; may be nullptr
- @param clipMatrix matrix applied to clipMask; may be nullptr to use
- identity matrix
- @param saveLayerFlags SaveLayerRec options to modify layer
- @return SaveLayerRec fully specified
- */
- SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
- const SkImage* clipMask, const SkMatrix* clipMatrix,
- SaveLayerFlags saveLayerFlags)
- : fBounds(bounds)
- , fPaint(paint)
- , fBackdrop(backdrop)
- , fClipMask(clipMask)
- , fClipMatrix(clipMatrix)
- , fSaveLayerFlags(saveLayerFlags)
- {}
-
/** hints at layer size limit */
const SkRect* fBounds = nullptr;
@@ -727,12 +698,6 @@ public:
*/
const SkImageFilter* fBackdrop = nullptr;
- /** clips layer with mask alpha */
- const SkImage* fClipMask = nullptr;
-
- /** transforms mask alpha used to clip */
- const SkMatrix* fClipMatrix = nullptr;
-
/** preserves LCD text, creates with prior layer contents */
SaveLayerFlags fSaveLayerFlags = 0;
};
@@ -1130,7 +1095,17 @@ public:
example: https://fiddle.skia.org/c/@Canvas_drawColor
*/
- void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver);
+ void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver) {
+ this->drawColor(SkColor4f::FromColor(color), mode);
+ }
+
+ /** Fills clip with color color.
+ mode determines how ARGB is combined with destination.
+
+ @param color SkColor4f representing unpremultiplied color.
+ @param mode SkBlendMode used to combine source color and destination
+ */
+ void drawColor(const SkColor4f& color, SkBlendMode mode = SkBlendMode::kSrcOver);
/** Fills clip with color color using SkBlendMode::kSrc.
This has the effect of replacing all pixels contained by clip with color.
@@ -1138,6 +1113,15 @@ public:
@param color unpremultiplied ARGB
*/
void clear(SkColor color) {
+ this->clear(SkColor4f::FromColor(color));
+ }
+
+ /** Fills clip with color color using SkBlendMode::kSrc.
+ This has the effect of replacing all pixels contained by clip with color.
+
+ @param color SkColor4f representing unpremultiplied color.
+ */
+ void clear(const SkColor4f& color) {
this->drawColor(color, SkBlendMode::kSrc);
}
@@ -1486,8 +1470,8 @@ public:
/** Draws SkRect src of SkImage image, scaled and translated to fill SkRect dst.
Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
- If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
- SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader.
If paint contains SkMaskFilter, generate mask from image bounds.
If generated mask extends beyond image bounds, replicate image edge colors, just
@@ -1518,8 +1502,8 @@ public:
boundaries. Additionally transform draw using clip, SkMatrix, and optional SkPaint
paint.
- If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
- SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader.
If paint contains SkMaskFilter, generate mask from image bounds.
If generated mask extends beyond image bounds, replicate image edge colors, just
@@ -1548,8 +1532,8 @@ public:
/** Draws SkImage image, scaled and translated to fill SkRect dst, using clip, SkMatrix,
and optional SkPaint paint.
- If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
- SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader.
If paint contains SkMaskFilter, generate mask from image bounds.
If generated mask extends beyond image bounds, replicate image edge colors, just
@@ -1572,8 +1556,8 @@ public:
/** Draws SkRect src of SkImage image, scaled and translated to fill SkRect dst.
Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
- If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
- SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader.
If paint contains SkMaskFilter, generate mask from image bounds.
If generated mask extends beyond image bounds, replicate image edge colors, just
@@ -1601,8 +1585,8 @@ public:
isrc is on integer pixel boundaries; dst may include fractional boundaries.
Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
- If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
- SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader.
If paint contains SkMaskFilter, generate mask from image bounds.
If generated mask extends beyond image bounds, replicate image edge colors, just
@@ -1633,8 +1617,8 @@ public:
/** Draws SkImage image, scaled and translated to fill SkRect dst,
using clip, SkMatrix, and optional SkPaint paint.
- If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
- SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader.
If paint contains SkMaskFilter, generate mask from image bounds.
If generated mask extends beyond image bounds, replicate image edge colors, just
@@ -1645,10 +1629,6 @@ public:
current CTM, so will reflect the dst rect geometry and is equivalent to
drawRect(dst).
- constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to
- sample within image; set to kFast_SrcRectConstraint allows sampling outside to
- improve performance.
-
@param image SkImage containing pixels, dimensions, and format
@param dst destination SkRect of image to draw to
@param paint SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
@@ -1665,8 +1645,8 @@ public:
Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
- If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
- SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader.
If paint contains SkMaskFilter, generate mask from image bounds. If paint
SkFilterQuality set to kNone_SkFilterQuality, disable pixel filtering. For all
other values of paint SkFilterQuality, use kLow_SkFilterQuality to filter pixels.
@@ -1692,8 +1672,8 @@ public:
Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
- If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
- SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader.
If paint contains SkMaskFilter, generate mask from image bounds. If paint
SkFilterQuality set to kNone_SkFilterQuality, disable pixel filtering. For all
other values of paint SkFilterQuality, use kLow_SkFilterQuality to filter pixels.
@@ -1717,8 +1697,8 @@ public:
/** Draws SkBitmap bitmap, with its top-left corner at (left, top),
using clip, SkMatrix, and optional SkPaint paint.
- If SkPaint paint is not nullptr, apply SkColorFilter, alpha, SkImageFilter,
- SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.
+ If SkPaint paint is not nullptr, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If bitmap is kAlpha_8_SkColorType, apply SkShader.
If paint contains SkMaskFilter, generate mask from bitmap bounds.
If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
@@ -1738,8 +1718,8 @@ public:
/** Draws SkRect src of SkBitmap bitmap, scaled and translated to fill SkRect dst.
Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
- If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
- SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If bitmap is kAlpha_8_SkColorType, apply SkShader.
If paint contains SkMaskFilter, generate mask from bitmap bounds.
If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
@@ -1766,8 +1746,8 @@ public:
isrc is on integer pixel boundaries; dst may include fractional boundaries.
Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
- If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
- SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If bitmap is kAlpha_8_SkColorType, apply SkShader.
If paint contains SkMaskFilter, generate mask from bitmap bounds.
If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
@@ -1794,8 +1774,8 @@ public:
bitmap bounds is on integer pixel boundaries; dst may include fractional boundaries.
Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
- If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
- SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If bitmap is kAlpha_8_SkColorType, apply SkShader.
If paint contains SkMaskFilter, generate mask from bitmap bounds.
If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
@@ -1856,8 +1836,8 @@ public:
Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
- If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
- SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader.
If paint contains SkMaskFilter, generate mask from image bounds. If paint
SkFilterQuality set to kNone_SkFilterQuality, disable pixel filtering. For all
other values of paint SkFilterQuality, use kLow_SkFilterQuality to filter pixels.
@@ -1987,7 +1967,7 @@ public:
size is 12 point.
All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
- SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By
+ SkColorFilter, and SkImageFilter; apply to text. By
default, draws filled black glyphs.
@param text character code points or glyphs drawn
@@ -2015,7 +1995,7 @@ public:
size is 12 point.
All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
- SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By
+ SkColorFilter, and SkImageFilter; apply to text. By
default, draws filled black glyphs.
@param str character code points drawn,
@@ -2044,7 +2024,7 @@ public:
size is 12 point.
All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
- SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By
+ SkColorFilter, and SkImageFilter; apply to text. By
default, draws filled black glyphs.
@param str character code points drawn,
@@ -2070,7 +2050,7 @@ public:
SkTextEncoding must be set to SkTextEncoding::kGlyphID.
Elements of paint: anti-alias, SkBlendMode, color including alpha,
- SkColorFilter, SkPaint dither, SkDrawLooper, SkMaskFilter, SkPathEffect, SkShader, and
+ SkColorFilter, SkPaint dither, SkMaskFilter, SkPathEffect, SkShader, and
SkPaint::Style; apply to blob. If SkPaint contains SkPaint::kStroke_Style:
SkPaint miter limit, SkPaint::Cap, SkPaint::Join, and SkPaint stroke width;
apply to SkPath created from blob.
@@ -2095,7 +2075,7 @@ public:
SkTextEncoding must be set to SkTextEncoding::kGlyphID.
Elements of paint: SkPathEffect, SkMaskFilter, SkShader, SkColorFilter,
- SkImageFilter, and SkDrawLooper; apply to blob.
+ and SkImageFilter; apply to blob.
@param blob glyphs, positions, and their paints' text size, typeface, and so on
@param x horizontal offset applied to blob
@@ -2164,8 +2144,11 @@ public:
}
/** Draws SkVertices vertices, a triangle mesh, using clip and SkMatrix.
- If vertices texs and vertices colors are defined in vertices, and SkPaint paint
- contains SkShader, SkBlendMode mode combines vertices colors with SkShader.
+ If paint contains an SkShader and vertices does not contain texCoords, the shader
+ is mapped using the vertices' positions.
+
+ If vertices colors are defined in vertices, and SkPaint paint contains SkShader,
+ SkBlendMode mode combines vertices colors with SkShader.
@param vertices triangle mesh to draw
@param mode combines vertices colors with SkShader, if both are present
@@ -2183,8 +2166,11 @@ public:
}
/** Draws SkVertices vertices, a triangle mesh, using clip and SkMatrix.
- If vertices texs and vertices colors are defined in vertices, and SkPaint paint
- contains SkShader, SkBlendMode mode combines vertices colors with SkShader.
+ If paint contains an SkShader and vertices does not contain texCoords, the shader
+ is mapped using the vertices' positions.
+
+ If vertices colors are defined in vertices, and SkPaint paint contains SkShader,
+ SkBlendMode mode combines vertices colors with SkShader.
@param vertices triangle mesh to draw
@param mode combines vertices colors with SkShader, if both are present
@@ -2217,7 +2203,8 @@ public:
bottom-right, bottom-left order.
If paint contains SkShader, SkPoint array texCoords maps SkShader as texture to
- corners in top-left, top-right, bottom-right, bottom-left order.
+ corners in top-left, top-right, bottom-right, bottom-left order. If texCoords is
+ nullptr, SkShader is mapped using positions (derived from cubics).
@param cubics SkPath cubic array, sharing common points
@param colors color array, one for each corner
@@ -2245,7 +2232,8 @@ public:
bottom-right, bottom-left order.
If paint contains SkShader, SkPoint array texCoords maps SkShader as texture to
- corners in top-left, top-right, bottom-right, bottom-left order.
+ corners in top-left, top-right, bottom-right, bottom-left order. If texCoords is
+ nullptr, SkShader is mapped using positions (derived from cubics).
@param cubics SkPath cubic array, sharing common points
@param colors color array, one for each corner
@@ -2733,8 +2721,7 @@ private:
void internalDrawPaint(const SkPaint& paint);
void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy);
void internalSaveBehind(const SkRect*);
- void internalDrawDevice(SkBaseDevice*, const SkPaint*, SkImage* clipImage,
- const SkMatrix& clipMatrix);
+ void internalDrawDevice(SkBaseDevice*, const SkPaint*);
void internalConcat44(const SkM44&);
diff --git a/chromium/third_party/skia/include/core/SkColorFilter.h b/chromium/third_party/skia/include/core/SkColorFilter.h
index 1222862f399..b9f680835a6 100644
--- a/chromium/third_party/skia/include/core/SkColorFilter.h
+++ b/chromium/third_party/skia/include/core/SkColorFilter.h
@@ -11,70 +11,44 @@
#include "include/core/SkBlendMode.h"
#include "include/core/SkColor.h"
#include "include/core/SkFlattenable.h"
-#include "include/core/SkRefCnt.h"
-class GrColorInfo;
-class GrFragmentProcessor;
-class GrRecordingContext;
-class SkArenaAlloc;
-class SkBitmap;
class SkColorMatrix;
-class SkColorSpace;
-struct SkStageRec;
-
-namespace skvm {
- class Builder;
- struct F32;
- struct Uniforms;
- struct Color;
-}
/**
- * ColorFilters are optional objects in the drawing pipeline. When present in
- * a paint, they are called with the "src" colors, and return new colors, which
- * are then passed onto the next stage (either ImageFilter or Xfermode).
- *
- * All subclasses are required to be reentrant-safe : it must be legal to share
- * the same instance between several threads.
- */
+* ColorFilters are optional objects in the drawing pipeline. When present in
+* a paint, they are called with the "src" colors, and return new colors, which
+* are then passed onto the next stage (either ImageFilter or Xfermode).
+*
+* All subclasses are required to be reentrant-safe : it must be legal to share
+* the same instance between several threads.
+*/
class SK_API SkColorFilter : public SkFlattenable {
public:
// DEPRECATED. skbug.com/8941
- bool asColorMode(SkColor* color, SkBlendMode* mode) const {
- return this->onAsAColorMode(color, mode);
- }
+ bool asColorMode(SkColor* color, SkBlendMode* mode) const;
/** If the filter can be represented by a source color plus Mode, this
* returns true, and sets (if not NULL) the color and mode appropriately.
* If not, this returns false and ignores the parameters.
*/
- bool asAColorMode(SkColor* color, SkBlendMode* mode) const {
- return this->onAsAColorMode(color, mode);
- }
+ bool asAColorMode(SkColor* color, SkBlendMode* mode) const;
/** If the filter can be represented by a 5x4 matrix, this
* returns true, and sets the matrix appropriately.
* If not, this returns false and ignores the parameter.
*/
- bool asAColorMatrix(float matrix[20]) const {
- return this->onAsAColorMatrix(matrix);
- }
-
- bool appendStages(const SkStageRec& rec, bool shaderIsOpaque) const;
-
- skvm::Color program(skvm::Builder*, skvm::Color,
- SkColorSpace* dstCS, skvm::Uniforms*, SkArenaAlloc*) const;
+ bool asAColorMatrix(float matrix[20]) const;
+ // deprecated, use isAlphaUnchanged()
enum Flags {
- /** If set the filter methods will not change the alpha channel of the colors.
- */
kAlphaUnchanged_Flag = 1 << 0,
};
+ uint32_t getFlags() const;
+
- /** Returns the flags for this filter. Override in subclasses to return custom flags.
- */
- virtual uint32_t getFlags() const { return 0; }
+ // Returns true if the filter is guaranteed to never change the alpha of a color it filters.
+ bool isAlphaUnchanged() const;
SkColor filterColor(SkColor) const;
@@ -92,52 +66,13 @@ public:
*/
sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter> inner) const;
-#if SK_SUPPORT_GPU
- /**
- * A subclass may implement this factory function to work with the GPU backend. It returns
- * a GrFragmentProcessor that implemets 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:
- SkColorFilter() {}
-
- 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;
+ SkColorFilter() = default;
+ friend class SkColorFilterBase;
typedef SkFlattenable INHERITED;
};
diff --git a/chromium/third_party/skia/include/core/SkColorSpace.h b/chromium/third_party/skia/include/core/SkColorSpace.h
index f64b5702d67..9bc14afad01 100644
--- a/chromium/third_party/skia/include/core/SkColorSpace.h
+++ b/chromium/third_party/skia/include/core/SkColorSpace.h
@@ -86,8 +86,6 @@ static constexpr skcms_Matrix3x3 kDisplayP3 = {{
{ 0.241182f, 0.692236f, 0.0665819f },
{ -0.00104941f, 0.0418818f, 0.784378f },
}};
-// TODO: skia:9792 We originally misnamed this matrix... delete this incorrect alias?
-static constexpr skcms_Matrix3x3 kDCIP3 = kDisplayP3;
static constexpr skcms_Matrix3x3 kRec2020 = {{
{ 0.673459f, 0.165661f, 0.125100f },
diff --git a/chromium/third_party/skia/include/core/SkDeferredDisplayList.h b/chromium/third_party/skia/include/core/SkDeferredDisplayList.h
index f63d94636da..ef14f17ce10 100644
--- a/chromium/third_party/skia/include/core/SkDeferredDisplayList.h
+++ b/chromium/third_party/skia/include/core/SkDeferredDisplayList.h
@@ -21,6 +21,8 @@ class SkDeferredDisplayListPriv;
class GrRenderTask;
class GrRenderTargetProxy;
struct GrCCPerOpsTaskPaths;
+#else
+using GrRenderTargetProxy = SkRefCnt;
#endif
/*
@@ -83,6 +85,7 @@ private:
};
SK_API SkDeferredDisplayList(const SkSurfaceCharacterization& characterization,
+ sk_sp<GrRenderTargetProxy> fTargetProxy,
sk_sp<LazyProxyData>);
#if SK_SUPPORT_GPU
@@ -108,6 +111,7 @@ private:
SkTArray<sk_sp<GrRenderTask>> fRenderTasks;
SkTArray<GrRecordingContext::ProgramData> fProgramData;
+ sk_sp<GrRenderTargetProxy> fTargetProxy;
sk_sp<LazyProxyData> fLazyProxyData;
#endif
};
diff --git a/chromium/third_party/skia/include/core/SkDeferredDisplayListRecorder.h b/chromium/third_party/skia/include/core/SkDeferredDisplayListRecorder.h
index ecb61f851b4..6e38c93a294 100644
--- a/chromium/third_party/skia/include/core/SkDeferredDisplayListRecorder.h
+++ b/chromium/third_party/skia/include/core/SkDeferredDisplayListRecorder.h
@@ -158,6 +158,7 @@ private:
#if SK_SUPPORT_GPU
sk_sp<GrContext> fContext;
+ sk_sp<GrRenderTargetProxy> fTargetProxy;
sk_sp<SkDeferredDisplayList::LazyProxyData> fLazyProxyData;
sk_sp<SkSurface> fSurface;
#endif
diff --git a/chromium/third_party/skia/include/core/SkDrawLooper.h b/chromium/third_party/skia/include/core/SkDrawLooper.h
index 529fdb99cd1..0273a18c058 100644
--- a/chromium/third_party/skia/include/core/SkDrawLooper.h
+++ b/chromium/third_party/skia/include/core/SkDrawLooper.h
@@ -23,12 +23,7 @@ class SkPaint;
struct SkRect;
/** \class SkDrawLooper
- Subclasses of SkDrawLooper can be attached to a SkPaint. Where they are,
- and something is drawn to a canvas with that paint, the looper subclass will
- be called, allowing it to modify the canvas and/or paint for that draw call.
- More than that, via the next() method, the looper can modify the draw to be
- invoked multiple times (hence the name loop-er), allow it to perform effects
- like shadows or frame/fills, that require more than one pass.
+ DEPRECATED: No longer supported in Skia.
*/
class SK_API SkDrawLooper : public SkFlattenable {
public:
diff --git a/chromium/third_party/skia/include/core/SkFlattenable.h b/chromium/third_party/skia/include/core/SkFlattenable.h
index eede64f3317..bb9d70faef6 100644
--- a/chromium/third_party/skia/include/core/SkFlattenable.h
+++ b/chromium/third_party/skia/include/core/SkFlattenable.h
@@ -28,7 +28,7 @@ public:
enum Type {
kSkColorFilter_Type,
kSkDrawable_Type,
- kSkDrawLooper_Type,
+ kSkDrawLooper_Type, // no longer used internally by Skia
kSkImageFilter_Type,
kSkMaskFilter_Type,
kSkPathEffect_Type,
@@ -95,12 +95,23 @@ private:
typedef SkRefCnt INHERITED;
};
-#define SK_REGISTER_FLATTENABLE(type) SkFlattenable::Register(#type, type::CreateProc)
-
-#define SK_FLATTENABLE_HOOKS(type) \
- static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&); \
- friend class SkFlattenable::PrivateInitializer; \
- Factory getFactory() const override { return type::CreateProc; } \
- const char* getTypeName() const override { return #type; }
+#if defined(SK_DISABLE_EFFECT_DESERIALIZATION)
+ #define SK_REGISTER_FLATTENABLE(type) do{}while(false)
+
+ #define SK_FLATTENABLE_HOOKS(type) \
+ static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&); \
+ friend class SkFlattenable::PrivateInitializer; \
+ Factory getFactory() const override { return nullptr; } \
+ const char* getTypeName() const override { return #type; }
+#else
+ #define SK_REGISTER_FLATTENABLE(type) \
+ SkFlattenable::Register(#type, type::CreateProc)
+
+ #define SK_FLATTENABLE_HOOKS(type) \
+ static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&); \
+ friend class SkFlattenable::PrivateInitializer; \
+ Factory getFactory() const override { return type::CreateProc; } \
+ const char* getTypeName() const override { return #type; }
+#endif
#endif
diff --git a/chromium/third_party/skia/include/core/SkFontStyle.h b/chromium/third_party/skia/include/core/SkFontStyle.h
index 50b5bd026da..dfb2ec9dc4d 100644
--- a/chromium/third_party/skia/include/core/SkFontStyle.h
+++ b/chromium/third_party/skia/include/core/SkFontStyle.h
@@ -74,7 +74,7 @@ public:
}
private:
- uint32_t fValue;
+ int32_t fValue;
};
#endif
diff --git a/chromium/third_party/skia/include/core/SkImage.h b/chromium/third_party/skia/include/core/SkImage.h
index db885397354..2a359446211 100644
--- a/chromium/third_party/skia/include/core/SkImage.h
+++ b/chromium/third_party/skia/include/core/SkImage.h
@@ -493,16 +493,21 @@ public:
/** Creates an SkImage by storing the specified YUVA planes into an image, to be rendered
via multitexturing.
- @param context GPU context
- @param yuvColorSpace How the YUV values are converted to RGB
- @param yuvaTextures array of (up to four) YUVA textures on GPU which contain the,
- possibly interleaved, YUVA planes
- @param yuvaIndices array indicating which texture in yuvaTextures, and channel
- in that texture, maps to each component of YUVA.
- @param imageSize size of the resulting image
- @param imageOrigin origin of the resulting image.
- @param imageColorSpace range of colors of the resulting image; may be nullptr
- @return created SkImage, or nullptr
+ When all the provided backend textures can be released 'textureReleaseProc' will be called
+ with 'releaseContext'. It will be called even if this method fails.
+
+ @param context GPU context
+ @param yuvColorSpace How the YUV values are converted to RGB
+ @param yuvaTextures array of (up to four) YUVA textures on GPU which contain the,
+ possibly interleaved, YUVA planes
+ @param yuvaIndices array indicating which texture in yuvaTextures, and channel
+ in that texture, maps to each component of YUVA.
+ @param imageSize size of the resulting image
+ @param imageOrigin origin of the resulting image.
+ @param imageColorSpace range of colors of the resulting image; may be nullptr
+ @param textureReleaseProc called when the backend textures can be released
+ @param releaseContext state passed to textureReleaseProc
+ @return created SkImage, or nullptr
*/
static sk_sp<SkImage> MakeFromYUVATextures(GrContext* context,
SkYUVColorSpace yuvColorSpace,
@@ -510,7 +515,9 @@ public:
const SkYUVAIndex yuvaIndices[4],
SkISize imageSize,
GrSurfaceOrigin imageOrigin,
- sk_sp<SkColorSpace> imageColorSpace = nullptr);
+ sk_sp<SkColorSpace> imageColorSpace = nullptr,
+ TextureReleaseProc textureReleaseProc = nullptr,
+ ReleaseContext releaseContext = nullptr);
/** Creates SkImage from pixmap array representing YUVA data.
SkImage is uploaded to GPU back-end using context.
@@ -767,6 +774,9 @@ public:
SkTileMode rules to fill drawn area outside SkImage. localMatrix permits
transforming SkImage before SkCanvas matrix is applied.
+ Note: since no filter-quality is specified, it will be determined at draw time using
+ the paint.
+
@param tmx tiling in the x direction
@param tmy tiling in the y direction
@param localMatrix SkImage transformation, or nullptr
@@ -778,6 +788,9 @@ public:
return this->makeShader(tmx, tmy, &localMatrix);
}
+ sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, const SkMatrix* localMatrix,
+ SkFilterQuality) const;
+
/** Creates SkShader from SkImage. SkShader dimensions are taken from SkImage. SkShader uses
SkShader::kClamp_TileMode to fill drawn area outside SkImage. localMatrix permits
transforming SkImage before SkCanvas matrix is applied.
@@ -841,8 +854,13 @@ public:
*/
GrSemaphoresSubmitted flush(GrContext* context, const GrFlushInfo& flushInfo);
- /** Version of flush() that uses a default GrFlushInfo. */
- void flush(GrContext*);
+ /** Version of flush() that uses a default GrFlushInfo. Also submits the flushed work to the
+ GPU.
+ */
+ void flushAndSubmit(GrContext*);
+
+ /** Deprecated. */
+ void flush(GrContext* context) { this->flushAndSubmit(context); }
/** Retrieves the back-end texture. If SkImage has no back-end texture, an invalid
object is returned. Call GrBackendTexture::isValid to determine if the result
diff --git a/chromium/third_party/skia/include/core/SkImageInfo.h b/chromium/third_party/skia/include/core/SkImageInfo.h
index 8ba9b406d72..b4c2c56cae7 100644
--- a/chromium/third_party/skia/include/core/SkImageInfo.h
+++ b/chromium/third_party/skia/include/core/SkImageInfo.h
@@ -55,17 +55,11 @@ static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) {
///////////////////////////////////////////////////////////////////////////////
-/** Temporary macro that allows us to add new color types without breaking Chrome compile. */
-#define SK_EXTENDED_COLOR_TYPES
-
/** \enum SkImageInfo::SkColorType
- Describes how pixel bits encode color. A pixel may be an alpha mask, a
- grayscale, RGB, or ARGB.
+ Describes how pixel bits encode color. A pixel may be an alpha mask, a grayscale, RGB, or ARGB.
- kN32_SkColorType selects the native 32-bit ARGB format. On little endian
- processors, pixels containing 8-bit ARGB components pack into 32-bit
- kBGRA_8888_SkColorType. On big endian processors, pixels pack into 32-bit
- kRGBA_8888_SkColorType.
+ kN32_SkColorType selects the native 32-bit ARGB format for the current configuration. This can
+ lead to inconsistent results across platforms, so use with caution.
*/
enum SkColorType {
kUnknown_SkColorType, //!< uninitialized
@@ -80,27 +74,30 @@ enum SkColorType {
kRGB_101010x_SkColorType, //!< pixel with 10 bits each for red, green, blue; in 32-bit word
kBGR_101010x_SkColorType, //!< pixel with 10 bits each for blue, green, red; in 32-bit word
kGray_8_SkColorType, //!< pixel with grayscale level in 8-bit byte
- kRGBA_F16Norm_SkColorType, //!< pixel with half floats in [0,1] for red, green, blue, alpha; in 64-bit word
- kRGBA_F16_SkColorType, //!< pixel with half floats for red, green, blue, alpha; in 64-bit word
+ kRGBA_F16Norm_SkColorType, //!< pixel with half floats in [0,1] for red, green, blue, alpha;
+ // in 64-bit word
+ kRGBA_F16_SkColorType, //!< pixel with half floats for red, green, blue, alpha;
+ // in 64-bit word
kRGBA_F32_SkColorType, //!< pixel using C float for red, green, blue, alpha; in 128-bit word
// The following 6 colortypes are just for reading from - not for rendering to
- kR8G8_unorm_SkColorType, //<! pixel with a uint8_t for red and green
+ kR8G8_unorm_SkColorType, //!< pixel with a uint8_t for red and green
- kA16_float_SkColorType, //<! pixel with a half float for alpha
- kR16G16_float_SkColorType, //<! pixel with a half float for red and green
+ kA16_float_SkColorType, //!< pixel with a half float for alpha
+ kR16G16_float_SkColorType, //!< pixel with a half float for red and green
- kA16_unorm_SkColorType, //<! pixel with a little endian uint16_t for alpha
- kR16G16_unorm_SkColorType, //<! pixel with a little endian uint16_t for red and green
- kR16G16B16A16_unorm_SkColorType,//<! pixel with a little endian uint16_t for red, green, blue, and alpha
+ kA16_unorm_SkColorType, //!< pixel with a little endian uint16_t for alpha
+ kR16G16_unorm_SkColorType, //!< pixel with a little endian uint16_t for red and green
+ kR16G16B16A16_unorm_SkColorType, //!< pixel with a little endian uint16_t for red, green, blue
+ // and alpha
kLastEnum_SkColorType = kR16G16B16A16_unorm_SkColorType, //!< last valid value
#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
- kN32_SkColorType = kBGRA_8888_SkColorType,//!< native ARGB 32-bit encoding
+ kN32_SkColorType = kBGRA_8888_SkColorType,//!< native 32-bit BGRA encoding
#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
- kN32_SkColorType = kRGBA_8888_SkColorType,//!< native ARGB 32-bit encoding
+ kN32_SkColorType = kRGBA_8888_SkColorType,//!< native 32-bit RGBA encoding
#else
#error "SK_*32_SHIFT values must correspond to BGRA or RGBA byte order"
@@ -139,11 +136,11 @@ SK_API bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alph
Describes color range of YUV pixels. The color mapping from YUV to RGB varies
depending on the source. YUV pixels may be generated by JPEG images, standard
video streams, or high definition video streams. Each has its own mapping from
- YUV and RGB.
+ YUV to RGB.
JPEG YUV values encode the full range of 0 to 255 for all three components.
- Video YUV values range from 16 to 235 for all three components. Details of
- encoding and conversion to RGB are described in YCbCr color space.
+ Video YUV values range from 16 to 235 for Y and from 16 to 240 for U and V.
+ Details of encoding and conversion to RGB are described in YCbCr color space.
The identity colorspace exists to provide a utility mapping from Y to R, U to G and V to B.
It can be used to visualize the YUV planes or to explicitly post process the YUV channels.
@@ -584,20 +581,22 @@ public:
@return width() times bytesPerPixel() as unsigned 64-bit integer
*/
- uint64_t minRowBytes64() const { return sk_64_mul(this->width(), this->bytesPerPixel()); }
+ uint64_t minRowBytes64() const {
+ return (uint64_t)sk_64_mul(this->width(), this->bytesPerPixel());
+ }
/** Returns minimum bytes per row, computed from pixel width() and SkColorType, which
specifies bytesPerPixel(). SkBitmap maximum value for row bytes must fit
in 31 bits.
- @return width() times bytesPerPixel() as signed 32-bit integer
+ @return width() times bytesPerPixel() as size_t
*/
size_t minRowBytes() const {
uint64_t minRowBytes = this->minRowBytes64();
if (!SkTFitsIn<int32_t>(minRowBytes)) {
return 0;
}
- return SkTo<int32_t>(minRowBytes);
+ return (size_t)minRowBytes;
}
/** Returns byte offset of pixel from pixel base address.
diff --git a/chromium/third_party/skia/include/core/SkMatrix.h b/chromium/third_party/skia/include/core/SkMatrix.h
index dca1a110622..f54bb557cdc 100644
--- a/chromium/third_party/skia/include/core/SkMatrix.h
+++ b/chromium/third_party/skia/include/core/SkMatrix.h
@@ -63,27 +63,12 @@ public:
@param sy vertical scale factor
@return SkMatrix with scale
*/
- static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar sx, SkScalar sy) {
+ static SkMatrix SK_WARN_UNUSED_RESULT Scale(SkScalar sx, SkScalar sy) {
SkMatrix m;
m.setScale(sx, sy);
return m;
}
- /** Sets SkMatrix to scale by (scale, scale). Returned matrix is:
-
- | scale 0 0 |
- | 0 scale 0 |
- | 0 0 1 |
-
- @param scale horizontal and vertical scale factor
- @return SkMatrix with scale
- */
- static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar scale) {
- SkMatrix m;
- m.setScale(scale, scale);
- return m;
- }
-
/** Sets SkMatrix to translate by (dx, dy). Returned matrix is:
| 1 0 dx |
@@ -94,23 +79,43 @@ public:
@param dy vertical translation
@return SkMatrix with translation
*/
- static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkScalar dx, SkScalar dy) {
+ static SkMatrix SK_WARN_UNUSED_RESULT Translate(SkScalar dx, SkScalar dy) {
SkMatrix m;
m.setTranslate(dx, dy);
return m;
}
+ static SkMatrix SK_WARN_UNUSED_RESULT Translate(SkVector t) { return Translate(t.x(), t.y()); }
+ static SkMatrix SK_WARN_UNUSED_RESULT Translate(SkIVector t) { return Translate(t.x(), t.y()); }
- /** Sets SkMatrix to translate by (t.x(), t.y()). Returned matrix is:
+ /** Sets SkMatrix to rotate by |deg| about a pivot point at (0, 0).
- | 1 0 t.x() |
- | 0 1 t.y() |
- | 0 0 1 |
-
- @param t translation vector
- @return SkMatrix with translation
+ @param deg rotation angle in degrees (positive rotates clockwise)
+ @return SkMatrix with rotation
*/
+ static SkMatrix SK_WARN_UNUSED_RESULT RotateDeg(SkScalar deg) {
+ SkMatrix m;
+ m.setRotate(deg);
+ return m;
+ }
+ static SkMatrix SK_WARN_UNUSED_RESULT RotateRad(SkScalar rad) {
+ return RotateDeg(SkRadiansToDegrees(rad));
+ }
+
+#ifdef SK_SUPPORT_LEGACY_MATRIX_FACTORIES
+ // DEPRECATED
+ static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkScalar dx, SkScalar dy) {
+ return Translate(dx, dy);
+ }
+ static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar sx, SkScalar sy) {
+ return Scale(sx, sy);
+ }
+ static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar scale) {
+ return Scale(scale, scale);
+ }
static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkVector t) { return MakeTrans(t.x(), t.y()); }
static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkIVector t) { return MakeTrans(t.x(), t.y()); }
+ // end DEPRECATED
+#endif
/** Sets SkMatrix to:
@@ -1677,6 +1682,10 @@ public:
return result;
}
+ friend SkMatrix operator*(const SkMatrix& a, const SkMatrix& b) {
+ return Concat(a, b);
+ }
+
/** Sets internal cache to unknown state. Use to force update after repeated
modifications to SkMatrix element reference returned by operator[](int index).
*/
@@ -1708,7 +1717,7 @@ public:
fMat[kMPersp1] = 0;
fMat[kMPersp2] = 1;
- unsigned mask = 0;
+ int mask = 0;
if (sx != 1 || sy != 1) {
mask |= kScale_Mask;
}
@@ -1752,12 +1761,12 @@ private:
kPerspective_Mask |
kRectStaysRect_Mask;
- SkScalar fMat[9];
- mutable uint32_t fTypeMask;
+ SkScalar fMat[9];
+ mutable int32_t fTypeMask;
constexpr SkMatrix(SkScalar sx, SkScalar kx, SkScalar tx,
SkScalar ky, SkScalar sy, SkScalar ty,
- SkScalar p0, SkScalar p1, SkScalar p2, uint32_t typeMask)
+ SkScalar p0, SkScalar p1, SkScalar p2, int typeMask)
: fMat{sx, kx, tx,
ky, sy, ty,
p0, p1, p2}
@@ -1773,18 +1782,18 @@ private:
SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||
((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask)
== (kUnknown_Mask | kOnlyPerspectiveValid_Mask));
- fTypeMask = SkToU8(mask);
+ fTypeMask = mask;
}
void orTypeMask(int mask) {
SkASSERT((mask & kORableMasks) == mask);
- fTypeMask = SkToU8(fTypeMask | mask);
+ fTypeMask |= mask;
}
void clearTypeMask(int mask) {
// only allow a valid mask
SkASSERT((mask & kAllMasks) == mask);
- fTypeMask = fTypeMask & ~mask;
+ fTypeMask &= ~mask;
}
TypeMask getPerspectiveTypeMaskOnly() const {
@@ -1882,7 +1891,6 @@ private:
friend class SkPerspIter;
friend class SkMatrixPriv;
- friend class SkReader32;
friend class SerializationTest;
};
SK_END_REQUIRE_DENSE
diff --git a/chromium/third_party/skia/include/core/SkMilestone.h b/chromium/third_party/skia/include/core/SkMilestone.h
index 5f118966174..1cc0de26203 100644
--- a/chromium/third_party/skia/include/core/SkMilestone.h
+++ b/chromium/third_party/skia/include/core/SkMilestone.h
@@ -5,5 +5,5 @@
* found in the LICENSE file.
*/
#ifndef SK_MILESTONE
-#define SK_MILESTONE 84
+#define SK_MILESTONE 85
#endif
diff --git a/chromium/third_party/skia/include/core/SkPaint.h b/chromium/third_party/skia/include/core/SkPaint.h
index 86b511b5c55..96d0b714475 100644
--- a/chromium/third_party/skia/include/core/SkPaint.h
+++ b/chromium/third_party/skia/include/core/SkPaint.h
@@ -235,6 +235,11 @@ public:
*/
void setStyle(Style style);
+ /**
+ * Set paint's style to kStroke if true, or kFill if false.
+ */
+ void setStroke(bool);
+
/** Retrieves alpha and RGB, unpremultiplied, packed into 32 bits.
Use helpers SkColorGetA(), SkColorGetR(), SkColorGetG(), and SkColorGetB() to extract
a color component.
@@ -316,9 +321,10 @@ public:
*/
SkScalar getStrokeWidth() const { return fWidth; }
- /** Sets the thickness of the pen used by the paint to
- outline the shape.
- Has no effect if width is less than zero.
+ /** Sets the thickness of the pen used by the paint to outline the shape.
+ A stroke-width of zero is treated as "hairline" width. Hairlines are always exactly one
+ pixel wide in device space (their thickness does not change as the canvas is scaled).
+ Negative stroke-widths are invalid; setting a negative width will have no effect.
@param width zero thickness for hairline; greater than zero for pen thickness
@@ -589,7 +595,6 @@ public:
@param imageFilter how SkImage is sampled when transformed
- example: https://fiddle.skia.org/c/@Draw_Looper_Methods
example: https://fiddle.skia.org/c/@Paint_setImageFilter
*/
void setImageFilter(sk_sp<SkImageFilter> imageFilter);
diff --git a/chromium/third_party/skia/include/core/SkPath.h b/chromium/third_party/skia/include/core/SkPath.h
index 9f6b3e8e491..a2e7c34ed78 100644
--- a/chromium/third_party/skia/include/core/SkPath.h
+++ b/chromium/third_party/skia/include/core/SkPath.h
@@ -1322,6 +1322,17 @@ public:
this->transform(matrix, this, pc);
}
+ SkPath makeTransform(const SkMatrix& m,
+ SkApplyPerspectiveClip pc = SkApplyPerspectiveClip::kYes) const {
+ SkPath dst;
+ this->transform(m, &dst, pc);
+ return dst;
+ }
+
+ SkPath makeScale(SkScalar sx, SkScalar sy) {
+ return this->makeTransform(SkMatrix::Scale(sx, sy), SkApplyPerspectiveClip::kNo);
+ }
+
/** Returns last point on SkPath in lastPt. Returns false if SkPoint array is empty,
storing (0, 0) if lastPt is not nullptr.
@@ -1748,6 +1759,8 @@ public:
bool isValid() const { return this->isValidImpl() && fPathRef->isValid(); }
private:
+ SkPath(sk_sp<SkPathRef>, SkPathFillType, bool isVolatile);
+
sk_sp<SkPathRef> fPathRef;
int fLastMoveToIndex;
mutable std::atomic<uint8_t> fConvexity; // SkPathConvexityType
@@ -1832,6 +1845,7 @@ private:
friend class SkAutoPathBoundsUpdate;
friend class SkAutoDisableOvalCheck;
friend class SkAutoDisableDirectionCheck;
+ friend class SkPathBuilder;
friend class SkPathEdgeIter;
friend class SkPathWriter;
friend class SkOpBuilder;
diff --git a/chromium/third_party/skia/include/core/SkPathBuilder.h b/chromium/third_party/skia/include/core/SkPathBuilder.h
new file mode 100644
index 00000000000..3269f49e2fc
--- /dev/null
+++ b/chromium/third_party/skia/include/core/SkPathBuilder.h
@@ -0,0 +1,101 @@
+/*
+ * 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 SkPathBuilder_DEFINED
+#define SkPathBuilder_DEFINED
+
+#include "include/core/SkMatrix.h"
+#include "include/core/SkPath.h"
+#include "include/core/SkPathTypes.h"
+#include "include/private/SkTDArray.h"
+
+class SkPathBuilder {
+public:
+ SkPathBuilder();
+ ~SkPathBuilder();
+
+ SkPath snapshot(); // the builder is unchanged after returning this path
+ SkPath detach(); // the builder is reset to empty after returning this path
+
+ void setFillType(SkPathFillType ft) { fFillType = ft; }
+ void setIsVolatile(bool isVolatile) { fIsVolatile = isVolatile; }
+
+ SkPathBuilder& reset();
+
+ SkPathBuilder& moveTo(SkPoint pt);
+ SkPathBuilder& lineTo(SkPoint pt);
+ SkPathBuilder& quadTo(SkPoint pt1, SkPoint pt2);
+ SkPathBuilder& conicTo(SkPoint pt1, SkPoint pt2, SkScalar w);
+ SkPathBuilder& cubicTo(SkPoint pt1, SkPoint pt2, SkPoint pt3);
+ SkPathBuilder& close();
+
+ SkPathBuilder& moveTo(SkScalar x, SkScalar y) { return this->moveTo(SkPoint::Make(x, y)); }
+ SkPathBuilder& lineTo(SkScalar x, SkScalar y) { return this->lineTo(SkPoint::Make(x, y)); }
+ SkPathBuilder& quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
+ return this->quadTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2));
+ }
+ SkPathBuilder& quadTo(const SkPoint pts[2]) { return this->quadTo(pts[0], pts[1]); }
+ SkPathBuilder& conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w) {
+ return this->conicTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2), w);
+ }
+ SkPathBuilder& conicTo(const SkPoint pts[2], SkScalar w) {
+ return this->conicTo(pts[0], pts[1], w);
+ }
+ SkPathBuilder& cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3) {
+ return this->cubicTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2), SkPoint::Make(x3, y3));
+ }
+ SkPathBuilder& cubicTo(const SkPoint pts[3]) {
+ return this->cubicTo(pts[0], pts[1], pts[2]);
+ }
+
+ SkPathBuilder& addRect(const SkRect&, SkPathDirection, unsigned startIndex);
+ SkPathBuilder& addOval(const SkRect&, SkPathDirection, unsigned startIndex);
+ SkPathBuilder& addRRect(const SkRRect&, SkPathDirection, unsigned startIndex);
+
+ SkPathBuilder& addRect(const SkRect& rect, SkPathDirection dir = SkPathDirection::kCW) {
+ return this->addRect(rect, dir, 0);
+ }
+ SkPathBuilder& addOval(const SkRect& rect, SkPathDirection dir = SkPathDirection::kCW) {
+ return this->addOval(rect, dir, 0);
+ }
+ SkPathBuilder& addRRect(const SkRRect& rect, SkPathDirection dir = SkPathDirection::kCW) {
+ return this->addRRect(rect, dir, 0);
+ }
+
+ void incReserve(int extraPtCount, int extraVerbCount);
+ void incReserve(int extraPtCount) {
+ this->incReserve(extraPtCount, extraPtCount);
+ }
+
+ static SkPath Make(const SkPoint[], int pointCount,
+ const uint8_t[], int verbCount,
+ const SkScalar[], int conicWeightCount,
+ SkPathFillType, bool isVolatile = false);
+
+private:
+ SkTDArray<SkPoint> fPts;
+ SkTDArray<uint8_t> fVerbs;
+ SkTDArray<SkScalar> fConicWeights;
+
+ SkPathFillType fFillType;
+ bool fIsVolatile;
+
+ unsigned fSegmentMask;
+ SkPoint fLastMovePoint;
+ bool fNeedsMoveVerb;
+
+ int countVerbs() const { return fVerbs.count(); }
+
+ void ensureMove() {
+ if (fNeedsMoveVerb) {
+ this->moveTo(fLastMovePoint);
+ }
+ }
+};
+
+#endif
+
diff --git a/chromium/third_party/skia/include/core/SkPixmap.h b/chromium/third_party/skia/include/core/SkPixmap.h
index d7beb295687..8cacfd07df1 100644
--- a/chromium/third_party/skia/include/core/SkPixmap.h
+++ b/chromium/third_party/skia/include/core/SkPixmap.h
@@ -369,7 +369,7 @@ public:
const uint8_t* addr8(int x, int y) const {
SkASSERT((unsigned)x < (unsigned)fInfo.width());
SkASSERT((unsigned)y < (unsigned)fInfo.height());
- return (const uint8_t*)((const char*)this->addr8() + y * fRowBytes + (x << 0));
+ return (const uint8_t*)((const char*)this->addr8() + (size_t)y * fRowBytes + (x << 0));
}
/** Returns readable pixel address at (x, y).
@@ -387,7 +387,7 @@ public:
const uint16_t* addr16(int x, int y) const {
SkASSERT((unsigned)x < (unsigned)fInfo.width());
SkASSERT((unsigned)y < (unsigned)fInfo.height());
- return (const uint16_t*)((const char*)this->addr16() + y * fRowBytes + (x << 1));
+ return (const uint16_t*)((const char*)this->addr16() + (size_t)y * fRowBytes + (x << 1));
}
/** Returns readable pixel address at (x, y).
@@ -405,7 +405,7 @@ public:
const uint32_t* addr32(int x, int y) const {
SkASSERT((unsigned)x < (unsigned)fInfo.width());
SkASSERT((unsigned)y < (unsigned)fInfo.height());
- return (const uint32_t*)((const char*)this->addr32() + y * fRowBytes + (x << 2));
+ return (const uint32_t*)((const char*)this->addr32() + (size_t)y * fRowBytes + (x << 2));
}
/** Returns readable pixel address at (x, y).
@@ -423,7 +423,7 @@ public:
const uint64_t* addr64(int x, int y) const {
SkASSERT((unsigned)x < (unsigned)fInfo.width());
SkASSERT((unsigned)y < (unsigned)fInfo.height());
- return (const uint64_t*)((const char*)this->addr64() + y * fRowBytes + (x << 3));
+ return (const uint64_t*)((const char*)this->addr64() + (size_t)y * fRowBytes + (x << 3));
}
/** Returns readable pixel address at (x, y).
diff --git a/chromium/third_party/skia/include/core/SkString.h b/chromium/third_party/skia/include/core/SkString.h
index 0982e003374..6f1d972da28 100644
--- a/chromium/third_party/skia/include/core/SkString.h
+++ b/chromium/third_party/skia/include/core/SkString.h
@@ -181,8 +181,10 @@ public:
char& operator[](size_t n) { return this->writable_str()[n]; }
void reset();
- /** Destructive resize, does not preserve contents. */
- void resize(size_t len) { this->set(nullptr, len); }
+ /** String contents are preserved on resize. (For destructive resize, `set(nullptr, length)`.)
+ * `resize` automatically reserves an extra byte at the end of the buffer for a null terminator.
+ */
+ void resize(size_t len);
void set(const SkString& src) { *this = src; }
void set(const char text[]);
void set(const char text[], size_t len);
@@ -219,6 +221,7 @@ public:
void prependScalar(SkScalar value) { this->insertScalar((size_t)-1, value); }
void printf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
+ void printVAList(const char format[], va_list);
void appendf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
void appendVAList(const char format[], va_list);
void prependf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
@@ -239,20 +242,18 @@ public:
private:
struct Rec {
public:
- constexpr Rec(uint32_t len, int32_t refCnt)
- : fLength(len), fRefCnt(refCnt), fBeginningOfData(0)
- { }
+ constexpr Rec(uint32_t len, int32_t refCnt) : fLength(len), fRefCnt(refCnt) {}
static sk_sp<Rec> Make(const char text[], size_t len);
- uint32_t fLength; // logically size_t, but we want it to stay 32bits
- mutable std::atomic<int32_t> fRefCnt;
- char fBeginningOfData;
-
char* data() { return &fBeginningOfData; }
const char* data() const { return &fBeginningOfData; }
-
void ref() const;
void unref() const;
bool unique() const;
+
+ uint32_t fLength; // logically size_t, but we want it to stay 32 bits
+ mutable std::atomic<int32_t> fRefCnt;
+ char fBeginningOfData = '\0';
+
private:
// Ensure the unsized delete is called.
void operator delete(void* p) { ::operator delete(p); }
diff --git a/chromium/third_party/skia/include/core/SkSurface.h b/chromium/third_party/skia/include/core/SkSurface.h
index 62698bb8155..bf151c05dea 100644
--- a/chromium/third_party/skia/include/core/SkSurface.h
+++ b/chromium/third_party/skia/include/core/SkSurface.h
@@ -28,6 +28,7 @@ class SkPaint;
class SkSurfaceCharacterization;
class GrBackendRenderTarget;
class GrBackendSemaphore;
+class GrBackendSurfaceMutableState;
class GrBackendTexture;
class GrContext;
class GrRecordingContext;
@@ -183,6 +184,10 @@ public:
not exceed context capabilities, and the context must be able to support
back-end textures.
+ Upon success textureReleaseProc is called when it is safe to delete the texture in the
+ backend API (accounting only for use of the texture by this surface). If SkSurface creation
+ fails textureReleaseProc is called before this function returns.
+
If SK_SUPPORT_GPU is defined as zero, has no effect and returns nullptr.
@param context GPU context
@@ -214,6 +219,10 @@ public:
not exceed context capabilities, and the context must be able to support
back-end render targets.
+ Upon success releaseProc is called when it is safe to delete the render target in the
+ backend API (accounting only for use of the render target by this surface). If SkSurface
+ creation fails releaseProc is called before this function returns.
+
If SK_SUPPORT_GPU is defined as zero, has no effect and returns nullptr.
@param context GPU context
@@ -221,8 +230,8 @@ public:
@param colorSpace range of colors
@param surfaceProps LCD striping orientation and setting for device independent
fonts; may be nullptr
- @param releaseProc function called when texture can be released
- @param releaseContext state passed to textureReleaseProc
+ @param releaseProc function called when backendRenderTarget can be released
+ @param releaseContext state passed to releaseProc
@return SkSurface if all parameters are valid; otherwise, nullptr
*/
static sk_sp<SkSurface> MakeFromBackendRenderTarget(GrContext* context,
@@ -234,29 +243,8 @@ public:
RenderTargetReleaseProc releaseProc = nullptr,
ReleaseContext releaseContext = nullptr);
- /** Wraps a GPU-backed texture into SkSurface. Caller must ensure backendTexture is
- valid for the lifetime of returned SkSurface. If sampleCnt greater than zero,
- creates an intermediate MSAA SkSurface which is used for drawing backendTexture.
-
- SkSurface is returned if all parameters are valid. backendTexture is valid if
- its pixel configuration agrees with colorSpace and context; for instance, if
- backendTexture has an sRGB configuration, then context must support sRGB,
- and colorSpace must be present. Further, backendTexture width and height must
- not exceed context capabilities.
-
- Returned SkSurface is available only for drawing into, and cannot generate an
- SkImage.
-
- If SK_SUPPORT_GPU is defined as zero, has no effect and returns nullptr.
-
- @param context GPU context
- @param backendTexture texture residing on GPU
- @param sampleCnt samples per pixel, or 0 to disable full scene anti-aliasing
- @param colorSpace range of colors; may be nullptr
- @param surfaceProps LCD striping orientation and setting for device independent
- fonts; may be nullptr
- @return SkSurface if all parameters are valid; otherwise, nullptr
- */
+#if GR_TEST_UTILS
+ // TODO: Remove this.
static sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(GrContext* context,
const GrBackendTexture& backendTexture,
GrSurfaceOrigin origin,
@@ -264,6 +252,7 @@ public:
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
const SkSurfaceProps* surfaceProps);
+#endif
#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
/** Private.
@@ -454,6 +443,10 @@ public:
SkSurfaceCharacterization::isCompatible can be used to determine if a given backend texture
is compatible with a specific surface characterization.
+ Upon success textureReleaseProc is called when it is safe to delete the texture in the
+ backend API (accounting only for use of the texture by this surface). If SkSurface creation
+ fails textureReleaseProc is called before this function returns.
+
@param context GPU context
@param characterization characterization of the desired surface
@param backendTexture texture residing on GPU
@@ -586,6 +579,10 @@ public:
used. The GrBackendFormat and dimensions of replacement texture must match that of
the original.
+ Upon success textureReleaseProc is called when it is safe to delete the texture in the
+ backend API (accounting only for use of the texture by this surface). If SkSurface creation
+ fails textureReleaseProc is called before this function returns.
+
@param backendTexture the new backing texture for the surface
@param mode Retain or discard current Content
@param textureReleaseProc function called when texture can be released
@@ -652,8 +649,7 @@ public:
/** Draws SkSurface contents to canvas, with its top-left corner at (x, y).
- If SkPaint paint is not nullptr, apply SkColorFilter, alpha, SkImageFilter,
- SkBlendMode, and SkDrawLooper.
+ If SkPaint paint is not nullptr, apply SkColorFilter, alpha, SkImageFilter, and SkBlendMode.
@param canvas SkCanvas drawn into
@param x horizontal offset in SkCanvas
@@ -818,7 +814,8 @@ public:
When the pixel data is ready the caller's ReadPixelsCallback is called with a
AsyncReadResult containing pixel data in the requested color type, alpha type, and color
space. The AsyncReadResult will have count() == 1. Upon failure the callback is called
- with nullptr for AsyncReadResult.
+ with nullptr for AsyncReadResult. For a GPU surface this flushes work but a submit must
+ occur to guarantee a finite time before the callback is called.
The data is valid for the lifetime of AsyncReadResult with the exception that if the
SkSurface is GPU-backed the data is immediately invalidated if the GrContext is abandoned
@@ -846,7 +843,9 @@ public:
When the pixel data is ready the caller's ReadPixelsCallback is called with a
AsyncReadResult containing the planar data. The AsyncReadResult will have count() == 3.
- Upon failure the callback is called with nullptr for AsyncReadResult.
+ Upon failure the callback is called with nullptr for AsyncReadResult. For a GPU surface this
+ flushes work but a submit must occur to guarantee a finite time before the callback is
+ called.
The data is valid for the lifetime of AsyncReadResult with the exception that if the
SkSurface is GPU-backed the data is immediately invalidated if the GrContext is abandoned
@@ -916,21 +915,26 @@ public:
Skia will correctly order its own draws and pixel operations. This must to be used to ensure
correct ordering when the surface backing store is accessed outside Skia (e.g. direct use of
the 3D API or a windowing system). GrContext has additional flush and submit methods that
- apply to all surfaces and images created from a GrContext.
+ apply to all surfaces and images created from a GrContext. This is equivalent to calling
+ SkSurface::flush with a default GrFlushInfo followed by GrContext::submit.
*/
void flushAndSubmit();
- /**
- * Deprecated.
- */
- void flush() { this->flushAndSubmit(); }
-
enum class BackendSurfaceAccess {
kNoAccess, //!< back-end object will not be used by client
kPresent, //!< back-end surface will be used for presenting to screen
};
- /** Issues pending SkSurface commands to the GPU-backed API and resolves any SkSurface MSAA.
+ /** Issues pending SkSurface commands to the GPU-backed API objects and resolves any SkSurface
+ MSAA. A call to GrContext::submit is always required to ensure work is actually sent to the
+ gpu. Some specific API details:
+ GL: Commands are actually sent to the driver, but glFlush is never called. Thus some
+ sync objects from the flush will not be valid until a submission occurs.
+
+ Vulkan/Metal/D3D/Dawn: Commands are recorded to the backend APIs corresponding command
+ buffer or encoder objects. However, these objects are not sent to the gpu until a
+ submission occurs.
+
The work that is submitted to the GPU will be dependent on the BackendSurfaceAccess that is
passed in.
@@ -946,13 +950,19 @@ public:
The GrFlushInfo describes additional options to flush. Please see documentation at
GrFlushInfo for more info.
- If the return is GrSemaphoresSubmitted::kYes, only initialized GrBackendSemaphores will
- have been submitted and can be waited on (it is possible Skia failed to create a subset of
- the semaphores). If this call returns GrSemaphoresSubmitted::kNo, the GPU backend will not
- have submitted any semaphores to be signaled on the GPU. Thus the client should not have
- the GPU wait on any of the semaphores passed in with the GrFlushInfo. Regardless of whether
- semaphores were submitted to the GPU or not, the client is still responsible for deleting
- any initialized semaphores.
+ If the return is GrSemaphoresSubmitted::kYes, only initialized GrBackendSemaphores will be
+ submitted to the gpu during the next submit call (it is possible Skia failed to create a
+ subset of the semaphores). The client should not wait on these semaphores until after submit
+ has been called, but must keep them alive until then. If a submit flag was passed in with
+ the flush these valid semaphores can we waited on immediately. If this call returns
+ GrSemaphoresSubmitted::kNo, the GPU backend will not submit any semaphores to be signaled on
+ the GPU. Thus the client should not have the GPU wait on any of the semaphores passed in
+ with the GrFlushInfo. Regardless of whether semaphores were submitted to the GPU or not, the
+ client is still responsible for deleting any initialized semaphores.
+ Regardleess of semaphore submission the context will still be flushed. It should be
+ emphasized that a return value of GrSemaphoresSubmitted::kNo does not mean the flush did not
+ happen. It simply means there were no semaphores submitted to the GPU. A caller should only
+ take this as a failure if they passed in semaphores to be submitted.
Pending surface commands are flushed regardless of the return result.
@@ -961,27 +971,48 @@ public:
*/
GrSemaphoresSubmitted flush(BackendSurfaceAccess access, const GrFlushInfo& info);
- /** Deprecated
- */
- GrSemaphoresSubmitted flush(BackendSurfaceAccess access, GrFlushFlags flags,
- int numSemaphores, GrBackendSemaphore signalSemaphores[],
- GrGpuFinishedProc finishedProc = nullptr,
- GrGpuFinishedContext finishedContext = nullptr);
+ /** Issues pending SkSurface commands to the GPU-backed API objects and resolves any SkSurface
+ MSAA. A call to GrContext::submit is always required to ensure work is actually sent to the
+ gpu. Some specific API details:
+ GL: Commands are actually sent to the driver, but glFlush is never called. Thus some
+ sync objects from the flush will not be valid until a submission occurs.
- /** The below enum and flush call are deprecated
- */
- enum FlushFlags {
- kNone_FlushFlags = 0,
- // flush will wait till all submitted GPU work is finished before returning.
- kSyncCpu_FlushFlag = 0x1,
- };
- GrSemaphoresSubmitted flush(BackendSurfaceAccess access, FlushFlags flags,
- int numSemaphores, GrBackendSemaphore signalSemaphores[]);
+ Vulkan/Metal/D3D/Dawn: Commands are recorded to the backend APIs corresponding command
+ buffer or encoder objects. However, these objects are not sent to the gpu until a
+ submission occurs.
- /** Deprecated.
+ The GrFlushInfo describes additional options to flush. Please see documentation at
+ GrFlushInfo for more info.
+
+ If a GrBackendSurfaceMutableState is passed in, at the end of the flush we will transition
+ the surface to be in the state requested by the GrBackendSurfaceMutableState. If the surface
+ (or SkImage or GrBackendSurface wrapping the same backend object) is used again after this
+ flush the state may be changed and no longer match what is requested here. This is often
+ used if the surface will be used for presenting or external use and the client wants backend
+ object to be prepped for that use. A finishedProc or semaphore on the GrFlushInfo will also
+ include the work for any requested state change.
+
+ If the return is GrSemaphoresSubmitted::kYes, only initialized GrBackendSemaphores will be
+ submitted to the gpu during the next submit call (it is possible Skia failed to create a
+ subset of the semaphores). The client should not wait on these semaphores until after submit
+ has been called, but must keep them alive until then. If a submit flag was passed in with
+ the flush these valid semaphores can we waited on immediately. If this call returns
+ GrSemaphoresSubmitted::kNo, the GPU backend will not submit any semaphores to be signaled on
+ the GPU. Thus the client should not have the GPU wait on any of the semaphores passed in
+ with the GrFlushInfo. Regardless of whether semaphores were submitted to the GPU or not, the
+ client is still responsible for deleting any initialized semaphores.
+ Regardleess of semaphore submission the context will still be flushed. It should be
+ emphasized that a return value of GrSemaphoresSubmitted::kNo does not mean the flush did not
+ happen. It simply means there were no semaphores submitted to the GPU. A caller should only
+ take this as a failure if they passed in semaphores to be submitted.
+
+ Pending surface commands are flushed regardless of the return result.
+
+ @param info flush options
+ @param access optional state change request after flush
*/
- GrSemaphoresSubmitted flushAndSignalSemaphores(int numSemaphores,
- GrBackendSemaphore signalSemaphores[]);
+ GrSemaphoresSubmitted flush(const GrFlushInfo& info,
+ const GrBackendSurfaceMutableState* newState = nullptr);
/** Inserts a list of GPU semaphores that the current GPU-backed API must wait on before
executing any more commands on the GPU for this surface. Skia will take ownership of the
diff --git a/chromium/third_party/skia/include/core/SkTypes.h b/chromium/third_party/skia/include/core/SkTypes.h
index 860105d5377..93eeb548ff1 100644
--- a/chromium/third_party/skia/include/core/SkTypes.h
+++ b/chromium/third_party/skia/include/core/SkTypes.h
@@ -263,12 +263,6 @@
# undef SK_DIRECT3D
#endif
-#if !defined(SK_SUPPORT_ATLAS_TEXT)
-# define SK_SUPPORT_ATLAS_TEXT 0
-#elif SK_SUPPORT_ATLAS_TEXT && !SK_SUPPORT_GPU
-# error "SK_SUPPORT_ATLAS_TEXT requires SK_SUPPORT_GPU"
-#endif
-
#if !defined(SkUNREACHABLE)
# if defined(_MSC_VER) && !defined(__clang__)
# define SkUNREACHABLE __assume(false)
@@ -285,22 +279,20 @@
# define SK_DUMP_GOOGLE3_STACK()
#endif
-#ifdef SK_BUILD_FOR_WIN
- // Lets visual studio follow error back to source
- #define SK_DUMP_LINE_FORMAT(message) \
- SkDebugf("%s(%d): fatal error: \"%s\"\n", __FILE__, __LINE__, message)
-#else
- #define SK_DUMP_LINE_FORMAT(message) \
- SkDebugf("%s:%d: fatal error: \"%s\"\n", __FILE__, __LINE__, message)
-#endif
-
#ifndef SK_ABORT
-# define SK_ABORT(message) \
+# ifdef SK_BUILD_FOR_WIN
+ // This style lets Visual Studio follow errors back to the source file.
+# define SK_DUMP_LINE_FORMAT "%s(%d)"
+# else
+# define SK_DUMP_LINE_FORMAT "%s:%d"
+# endif
+# define SK_ABORT(message, ...) \
do { \
- SK_DUMP_LINE_FORMAT(message); \
- SK_DUMP_GOOGLE3_STACK(); \
- sk_abort_no_print(); \
- SkUNREACHABLE; \
+ SkDebugf(SK_DUMP_LINE_FORMAT ": fatal error: \"" message "\"\n", \
+ __FILE__, __LINE__, ##__VA_ARGS__); \
+ SK_DUMP_GOOGLE3_STACK(); \
+ sk_abort_no_print(); \
+ SkUNREACHABLE; \
} while (false)
#endif
@@ -325,12 +317,7 @@
/**
- * SK_PMCOLOR_BYTE_ORDER can be used to query the byte order of SkPMColor at compile time. The
- * relationship between the byte order and shift values depends on machine endianness. If the shift
- * order is R=0, G=8, B=16, A=24 then ((char*)&pmcolor)[0] will produce the R channel on a little
- * endian machine and the A channel on a big endian machine. Thus, given those shifts values,
- * SK_PMCOLOR_BYTE_ORDER(R,G,B,A) will be true on a little endian machine and
- * SK_PMCOLOR_BYTE_ORDER(A,B,G,R) will be true on a big endian machine.
+ * SK_PMCOLOR_BYTE_ORDER can be used to query the byte order of SkPMColor at compile time.
*/
#ifdef SK_CPU_BENDIAN
# define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3) \
@@ -461,16 +448,16 @@ SK_API extern void sk_abort_no_print(void);
// x - 4;
// }
#define SkASSERT_RELEASE(cond) \
- static_cast<void>( (cond) ? (void)0 : []{ SK_ABORT("assert(" #cond ")"); }() )
+ static_cast<void>( (cond) ? (void)0 : []{ SK_ABORT("assert(%s)", #cond); }() )
#ifdef SK_DEBUG
#define SkASSERT(cond) SkASSERT_RELEASE(cond)
#define SkASSERTF(cond, fmt, ...) static_cast<void>( (cond) ? (void)0 : [&]{ \
SkDebugf(fmt"\n", __VA_ARGS__); \
- SK_ABORT("assert(" #cond ")"); \
+ SK_ABORT("assert(%s)", #cond); \
}() )
- #define SkDEBUGFAIL(message) SK_ABORT(message)
- #define SkDEBUGFAILF(fmt, ...) SkASSERTF(false, fmt, ##__VA_ARGS__)
+ #define SkDEBUGFAIL(message) SK_ABORT("%s", message)
+ #define SkDEBUGFAILF(fmt, ...) SK_ABORT(fmt, ##__VA_ARGS__)
#define SkDEBUGCODE(...) __VA_ARGS__
#define SkDEBUGF(...) SkDebugf(__VA_ARGS__)
#define SkAssertResult(cond) SkASSERT(cond)
@@ -547,7 +534,7 @@ template <typename T> static constexpr bool SkIsAlignPtr(T x) {
typedef uint32_t SkFourByteTag;
static inline constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d) {
- return (((uint8_t)a << 24) | ((uint8_t)b << 16) | ((uint8_t)c << 8) | (uint8_t)d);
+ return (((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | (uint32_t)d);
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/include/core/SkVertices.h b/chromium/third_party/skia/include/core/SkVertices.h
index 0f666f83c87..ec76488b155 100644
--- a/chromium/third_party/skia/include/core/SkVertices.h
+++ b/chromium/third_party/skia/include/core/SkVertices.h
@@ -64,6 +64,9 @@ public:
* the vertex shader. For positions or vectors, markerName identifies what matrix is used in
* the vertex shader to transform the data. Those names should match a named transform on the
* CTM stack, created by calling SkCanvas::markCTM().
+ *
+ * For attributes with a usage of kVector, kNormalVector, or kPosition, a null markerName
+ * will transform the attribute by the canvas CTM matrix.
*/
struct Attribute {
enum class Type : uint8_t {
diff --git a/chromium/third_party/skia/include/docs/SkPDFDocument.h b/chromium/third_party/skia/include/docs/SkPDFDocument.h
index db525b99b7b..28b07f5b467 100644
--- a/chromium/third_party/skia/include/docs/SkPDFDocument.h
+++ b/chromium/third_party/skia/include/docs/SkPDFDocument.h
@@ -88,13 +88,18 @@ public:
// and then a value of the proper type according to the spec.
void appendInt(const char* owner, const char* name, int value);
void appendFloat(const char* owner, const char* name, float value);
- void appendString(const char* owner, const char* name, const char* value);
+ void appendName(const char* owner, const char* attrName, const char* value);
+ void appendString(const char* owner, const char* attrName, const char* value);
void appendFloatArray(const char* owner,
const char* name,
const std::vector<float>& value);
+ // Deprecated.
void appendStringArray(const char* owner,
- const char* name,
- const std::vector<SkString>& value);
+ const char* attrName,
+ const std::vector<SkString>& values);
+ void appendNodeIdArray(const char* owner,
+ const char* attrName,
+ const std::vector<int>& nodeIds);
private:
friend class ::SkPDFTagTree;
@@ -116,10 +121,6 @@ struct StructureElementNode {
SkString fAlt;
SkString fLang;
- // Deprecated. Use fChildVector instead.
- StructureElementNode* fChildren = nullptr;
- size_t fChildCount = 0;
-
// Deprecated. Use fTypeString instead.
DocumentStructureType fType = DocumentStructureType::kNonStruct;
};
diff --git a/chromium/third_party/skia/include/effects/SkBlurDrawLooper.h b/chromium/third_party/skia/include/effects/SkBlurDrawLooper.h
index 4a1ae83142a..77d9ae50c92 100644
--- a/chromium/third_party/skia/include/effects/SkBlurDrawLooper.h
+++ b/chromium/third_party/skia/include/effects/SkBlurDrawLooper.h
@@ -5,15 +5,13 @@
* found in the LICENSE file.
*/
-
#ifndef SkBlurDrawLooper_DEFINED
#define SkBlurDrawLooper_DEFINED
#include "include/core/SkDrawLooper.h"
/**
- * Draws a shadow of the object (possibly offset), and then draws the original object in
- * its original position.
+ * DEPRECATED: No longer supported in Skia.
*/
namespace SkBlurDrawLooper {
sk_sp<SkDrawLooper> SK_API Make(SkColor4f color, SkColorSpace* cs,
diff --git a/chromium/third_party/skia/include/effects/SkLayerDrawLooper.h b/chromium/third_party/skia/include/effects/SkLayerDrawLooper.h
index 8d10e8c2d63..f11727e5e32 100644
--- a/chromium/third_party/skia/include/effects/SkLayerDrawLooper.h
+++ b/chromium/third_party/skia/include/effects/SkLayerDrawLooper.h
@@ -13,6 +13,9 @@
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
+/**
+ * DEPRECATED: No longer supported by Skia.
+ */
class SK_API SkLayerDrawLooper : public SkDrawLooper {
public:
~SkLayerDrawLooper() override;
diff --git a/chromium/third_party/skia/include/effects/SkLumaColorFilter.h b/chromium/third_party/skia/include/effects/SkLumaColorFilter.h
index 038461d3d2c..0d6eacb0ae2 100644
--- a/chromium/third_party/skia/include/effects/SkLumaColorFilter.h
+++ b/chromium/third_party/skia/include/effects/SkLumaColorFilter.h
@@ -30,30 +30,14 @@ class SkRasterPipeline;
* not luminance, a dot-product of linear color channels. So at least
* SkLumaColorFilter and feColorMatrix+luminanceToAlpha agree there.)
*/
-
- #include "include/core/SkFlattenable.h"
-
-class SK_API SkLumaColorFilter : public SkColorFilter {
+class SK_API SkLumaColorFilter {
public:
static sk_sp<SkColorFilter> Make();
-#if SK_SUPPORT_GPU
- std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(GrRecordingContext*,
- const GrColorInfo&) const override;
-#endif
-
-protected:
- void flatten(SkWriteBuffer&) const override;
-
private:
- SK_FLATTENABLE_HOOKS(SkLumaColorFilter)
-
- SkLumaColorFilter();
- bool onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const override;
- skvm::Color onProgram(skvm::Builder*, skvm::Color,
- SkColorSpace* dstCS, skvm::Uniforms*, SkArenaAlloc*) const override;
+ friend class SkFlattenable;
- typedef SkColorFilter INHERITED;
+ static void RegisterFlattenable();
};
#endif
diff --git a/chromium/third_party/skia/include/effects/SkRuntimeEffect.h b/chromium/third_party/skia/include/effects/SkRuntimeEffect.h
index 3d812523d55..d570de6a013 100644
--- a/chromium/third_party/skia/include/effects/SkRuntimeEffect.h
+++ b/chromium/third_party/skia/include/effects/SkRuntimeEffect.h
@@ -95,9 +95,6 @@ public:
const SkMatrix* localMatrix,
bool isOpaque);
- sk_sp<SkColorFilter> makeColorFilter(sk_sp<SkData> inputs,
- sk_sp<SkColorFilter> children[],
- size_t childCount);
sk_sp<SkColorFilter> makeColorFilter(sk_sp<SkData> inputs);
const SkString& source() const { return fSkSL; }
diff --git a/chromium/third_party/skia/include/effects/SkStrokeAndFillPathEffect.h b/chromium/third_party/skia/include/effects/SkStrokeAndFillPathEffect.h
new file mode 100644
index 00000000000..fbde6493340
--- /dev/null
+++ b/chromium/third_party/skia/include/effects/SkStrokeAndFillPathEffect.h
@@ -0,0 +1,28 @@
+/*
+ * 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 SkStrokeAndFillPathEffect_DEFINED
+#define SkStrokeAndFillPathEffect_DEFINED
+
+#include "include/core/SkPaint.h"
+#include "include/core/SkPathEffect.h"
+#include "include/pathops/SkPathOps.h"
+
+class SK_API SkStrokeAndFillPathEffect {
+public:
+ /* If the paint is set to stroke, this will add the stroke and fill geometries
+ * together (hoping that the winding-direction works out).
+ *
+ * If the paint is set to fill, this effect is ignored.
+ *
+ * Note that if the paint is set to stroke and the stroke-width is 0, then
+ * this will turn the geometry into just a fill.
+ */
+ static sk_sp<SkPathEffect> Make();
+};
+
+#endif
diff --git a/chromium/third_party/skia/include/gpu/GrBackendSurface.h b/chromium/third_party/skia/include/gpu/GrBackendSurface.h
index 373d23f92cc..6e52b118db2 100644
--- a/chromium/third_party/skia/include/gpu/GrBackendSurface.h
+++ b/chromium/third_party/skia/include/gpu/GrBackendSurface.h
@@ -8,6 +8,7 @@
#ifndef GrBackendSurface_DEFINED
#define GrBackendSurface_DEFINED
+#include "include/gpu/GrBackendSurfaceMutableState.h"
#include "include/gpu/GrTypes.h"
#include "include/gpu/gl/GrGLTypes.h"
#include "include/gpu/mock/GrMockTypes.h"
@@ -19,6 +20,7 @@
#include "include/gpu/dawn/GrDawnTypes.h"
#endif
+class GrBackendSurfaceMutableStateImpl;
class GrVkImageLayout;
class GrGLTextureParameters;
@@ -224,7 +226,7 @@ private:
class SK_API GrBackendTexture {
public:
// Creates an invalid backend texture.
- GrBackendTexture() : fIsValid(false) {}
+ GrBackendTexture();
// The GrGLTextureInfo must have a valid fFormat.
GrBackendTexture(int width,
@@ -232,9 +234,11 @@ public:
GrMipMapped,
const GrGLTextureInfo& glInfo);
+#ifdef SK_VULKAN
GrBackendTexture(int width,
int height,
const GrVkImageInfo& vkInfo);
+#endif
#ifdef SK_METAL
GrBackendTexture(int width,
@@ -319,6 +323,13 @@ public:
// in pointer and returns true. Otherwise returns false if the backend API is not Mock.
bool getMockTextureInfo(GrMockTextureInfo*) const;
+ // If the client changes any of the mutable backend of the GrBackendTexture they should call
+ // this function to inform Skia that those values have changed. The backend API specific state
+ // that can be set from this function are:
+ //
+ // Vulkan: VkImageLayout and QueueFamilyIndex
+ void setMutableState(const GrBackendSurfaceMutableState&);
+
// Returns true if we are working with protected content.
bool isProtected() const;
@@ -333,6 +344,8 @@ public:
#endif
private:
+ friend class GrVkGpu; // for getMutableState
+ sk_sp<GrBackendSurfaceMutableStateImpl> getMutableState() const;
#ifdef SK_GL
friend class GrGLTexture;
@@ -347,12 +360,10 @@ private:
#ifdef SK_VULKAN
friend class GrVkTexture;
- friend class GrVkGpu; // for getGrVkImageLayout
GrBackendTexture(int width,
int height,
const GrVkImageInfo& vkInfo,
- sk_sp<GrVkImageLayout> layout);
- sk_sp<GrVkImageLayout> getGrVkImageLayout() const;
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState);
#endif
#ifdef SK_DIRECT3D
@@ -390,12 +401,14 @@ private:
#ifdef SK_DAWN
GrDawnTextureInfo fDawnInfo;
#endif
+
+ sk_sp<GrBackendSurfaceMutableStateImpl> fMutableState;
};
class SK_API GrBackendRenderTarget {
public:
// Creates an invalid backend texture.
- GrBackendRenderTarget() : fIsValid(false) {}
+ GrBackendRenderTarget();
// The GrGLTextureInfo must have a valid fFormat.
GrBackendRenderTarget(int width,
@@ -412,6 +425,7 @@ public:
const GrDawnRenderTargetInfo& dawnInfo);
#endif
+#ifdef SK_VULKAN
/** Deprecated, use version that does not take stencil bits. */
GrBackendRenderTarget(int width,
int height,
@@ -419,6 +433,7 @@ public:
int stencilBits,
const GrVkImageInfo& vkInfo);
GrBackendRenderTarget(int width, int height, int sampleCnt, const GrVkImageInfo& vkInfo);
+#endif
#ifdef SK_METAL
GrBackendRenderTarget(int width,
@@ -495,6 +510,13 @@ public:
// in pointer and returns true. Otherwise returns false if the backend API is not Mock.
bool getMockRenderTargetInfo(GrMockRenderTargetInfo*) const;
+ // If the client changes any of the mutable backend of the GrBackendTexture they should call
+ // this function to inform Skia that those values have changed. The backend API specific state
+ // that can be set from this function are:
+ //
+ // Vulkan: VkImageLayout and QueueFamilyIndex
+ void setMutableState(const GrBackendSurfaceMutableState&);
+
// Returns true if we are working with protected content.
bool isProtected() const;
@@ -507,12 +529,15 @@ public:
#endif
private:
- friend class GrVkGpu; // for getGrVkImageLayout
- sk_sp<GrVkImageLayout> getGrVkImageLayout() const;
+ friend class GrVkGpu; // for getMutableState
+ sk_sp<GrBackendSurfaceMutableStateImpl> getMutableState() const;
+#ifdef SK_VULKAN
friend class GrVkRenderTarget;
GrBackendRenderTarget(int width, int height, int sampleCnt, const GrVkImageInfo& vkInfo,
- sk_sp<GrVkImageLayout> layout);
+ sk_sp<GrBackendSurfaceMutableStateImpl> mutableState);
+#endif
+
#ifdef SK_DIRECT3D
friend class GrD3DGpu;
friend class GrD3DRenderTarget;
@@ -550,6 +575,7 @@ private:
#ifdef SK_DAWN
GrDawnRenderTargetInfo fDawnInfo;
#endif
+ sk_sp<GrBackendSurfaceMutableStateImpl> fMutableState;
};
#endif
diff --git a/chromium/third_party/skia/include/gpu/GrBackendSurfaceMutableState.h b/chromium/third_party/skia/include/gpu/GrBackendSurfaceMutableState.h
new file mode 100644
index 00000000000..6425cb52260
--- /dev/null
+++ b/chromium/third_party/skia/include/gpu/GrBackendSurfaceMutableState.h
@@ -0,0 +1,66 @@
+/*
+ * 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 GrBackendSurfaceMutableState_DEFINED
+#define GrBackendSurfaceMutableState_DEFINED
+
+#include "include/gpu/GrTypes.h"
+
+#ifdef SK_VULKAN
+#include "include/private/GrVkTypesPriv.h"
+#endif
+
+/**
+ * Since Skia and clients can both modify gpu textures and their connected state, Skia needs a way
+ * for clients to inform us if they have modifiend any of this state. In order to not need setters
+ * for every single API and state, we use this class to be a generic wrapper around all the mutable
+ * state. This class is used for calls that inform Skia of these texture/image state changes by the
+ * client as well as for requesting state changes to be done by Skia. The backend specific state
+ * that is wrapped by this class are:
+ *
+ * Vulkan: VkImageLayout and QueueFamilyIndex
+ */
+class GrBackendSurfaceMutableState {
+public:
+#ifdef SK_VULKAN
+ GrBackendSurfaceMutableState(VkImageLayout layout, uint32_t queueFamilyIndex)
+ : fVkState(layout, queueFamilyIndex)
+ , fBackend(GrBackend::kVulkan) {}
+#endif
+
+ GrBackendSurfaceMutableState& operator=(const GrBackendSurfaceMutableState& that) {
+ switch (fBackend) {
+ case GrBackend::kVulkan:
+#ifdef SK_VULKAN
+ SkASSERT(that.fBackend == GrBackend::kVulkan);
+ fVkState = that.fVkState;
+#endif
+ break;
+
+ default:
+ (void)that;
+ SkUNREACHABLE;
+ }
+ fBackend = that.fBackend;
+ return *this;
+ }
+
+private:
+ friend class GrBackendSurfaceMutableStateImpl;
+ friend class GrVkGpu;
+
+ union {
+ char fDummy;
+#ifdef SK_VULKAN
+ GrVkSharedImageInfo fVkState;
+#endif
+ };
+
+ GrBackend fBackend;
+};
+
+#endif
diff --git a/chromium/third_party/skia/include/gpu/GrContext.h b/chromium/third_party/skia/include/gpu/GrContext.h
index 9dcba2ca2f4..64137383687 100644
--- a/chromium/third_party/skia/include/gpu/GrContext.h
+++ b/chromium/third_party/skia/include/gpu/GrContext.h
@@ -36,7 +36,6 @@ class GrResourceProvider;
class GrStrikeCache;
class GrSurfaceProxy;
class GrSwizzle;
-class GrTextContext;
class GrTextureProxy;
struct GrVkBackendContext;
@@ -62,7 +61,10 @@ public:
/**
* The Vulkan context (VkQueue, VkDevice, VkInstance) must be kept alive until the returned
- * GrContext is first destroyed or abandoned.
+ * GrContext is destroyed. This also means that any objects created with this GrContext (e.g.
+ * SkSurfaces, SkImages, etc.) must also be released as they may hold refs on the GrContext.
+ * Once all these objects and the GrContext are released, then it is safe to delete the vulkan
+ * objects.
*/
static sk_sp<GrContext> MakeVulkan(const GrVkBackendContext&, const GrContextOptions&);
static sk_sp<GrContext> MakeVulkan(const GrVkBackendContext&);
@@ -98,6 +100,7 @@ public:
~GrContext() override;
+ // TODO: Remove this from public after migrating Chrome.
sk_sp<GrContextThreadSafeProxy> threadSafeProxy();
/**
@@ -133,7 +136,10 @@ public:
* API calls may crash.
*
* For Vulkan, even if the device becomes lost, the VkQueue, VkDevice, or VkInstance used to
- * create the GrContext must be alive before calling abandonContext.
+ * create the GrContext must be kept alive even after abandoning the context. Those objects must
+ * live for the lifetime of the GrContext object itself. The reason for this is so that
+ * we can continue to delete any outstanding GrBackendTextures/RenderTargets which must be
+ * cleaned up even in a device lost state.
*/
void abandonContext() override;
@@ -146,6 +152,23 @@ public:
bool abandoned() override;
/**
+ * Checks if the underlying 3D API reported an out-of-memory error. If this returns true it is
+ * reset and will return false until another out-of-memory error is reported by the 3D API. If
+ * the context is abandoned then this will report false.
+ *
+ * Currently this is implemented for:
+ *
+ * OpenGL [ES] - Note that client calls to glGetError() may swallow GL_OUT_OF_MEMORY errors and
+ * therefore hide the error from Skia. Also, it is not advised to use this in combination with
+ * enabling GrContextOptions::fSkipGLErrorChecks. That option may prevent GrContext from ever
+ * checking the GL context for OOM.
+ *
+ * Vulkan - Reports true if VK_ERROR_OUT_OF_HOST_MEMORY or VK_ERROR_OUT_OF_DEVICE_MEMORY has
+ * occurred.
+ */
+ bool oomed();
+
+ /**
* This is similar to abandonContext() however the underlying 3D context is not yet lost and
* the GrContext will cleanup all allocated resources before returning. After returning it will
* assume that the underlying context may no longer be valid.
@@ -296,7 +319,6 @@ public:
///////////////////////////////////////////////////////////////////////////
// Misc.
-
/**
* Inserts a list of GPU semaphores that the current GPU-backed API must wait on before
* executing any more commands on the GPU. Skia will take ownership of the underlying semaphores
@@ -307,82 +329,56 @@ public:
bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores);
/**
- * Call to ensure all drawing to the context has been issued to the underlying 3D API.
- */
- void flushAndSubmit() { this->flush(GrFlushInfo(), GrPrepareForExternalIORequests()); }
-
- /**
- * Deprecated.
+ * Call to ensure all drawing to the context has been flushed and submitted to the underlying 3D
+ * API. This is equivalent to calling GrContext::flush with a default GrFlushInfo followed by
+ * GrContext::submit.
*/
- void flush() { this->flushAndSubmit(); }
+ void flushAndSubmit() {
+ this->flush(GrFlushInfo());
+ this->submit();
+ }
/**
- * Call to ensure all drawing to the context has been issued to the underlying 3D API.
+ * Call to ensure all drawing to the context has been flushed to underlying 3D API specific
+ * objects. A call to GrContext::submit is always required to ensure work is actually sent to
+ * the gpu. Some specific API details:
+ * GL: Commands are actually sent to the driver, but glFlush is never called. Thus some
+ * sync objects from the flush will not be valid until a submission occurs.
+ *
+ * Vulkan/Metal/D3D/Dawn: Commands are recorded to the backend APIs corresponding command
+ * buffer or encoder objects. However, these objects are not sent to the gpu until a
+ * submission occurs.
*
- * If the return is GrSemaphoresSubmitted::kYes, only initialized GrBackendSemaphores will have
- * been submitted and can be waited on (it is possible Skia failed to create a subset of the
- * semaphores). If this call returns GrSemaphoresSubmitted::kNo, the GPU backend will not have
- * submitted any semaphores to be signaled on the GPU. Thus the client should not have the GPU
- * wait on any of the semaphores passed in with the GrFlushInfo. Regardless of whether
- * semaphores were submitted to the GPU or not, the client is still responsible for deleting any
- * initialized semaphores.
+ * If the return is GrSemaphoresSubmitted::kYes, only initialized GrBackendSemaphores will be
+ * submitted to the gpu during the next submit call (it is possible Skia failed to create a
+ * subset of the semaphores). The client should not wait on these semaphores until after submit
+ * has been called, and must keep them alive until then. If this call returns
+ * GrSemaphoresSubmitted::kNo, the GPU backend will not submit any semaphores to be signaled on
+ * the GPU. Thus the client should not have the GPU wait on any of the semaphores passed in with
+ * the GrFlushInfo. Regardless of whether semaphores were submitted to the GPU or not, the
+ * client is still responsible for deleting any initialized semaphores.
* Regardleess of semaphore submission the context will still be flushed. It should be
* emphasized that a return value of GrSemaphoresSubmitted::kNo does not mean the flush did not
* happen. It simply means there were no semaphores submitted to the GPU. A caller should only
* take this as a failure if they passed in semaphores to be submitted.
*/
- GrSemaphoresSubmitted flush(const GrFlushInfo& info) {
- return this->flush(info, GrPrepareForExternalIORequests());
- }
+ GrSemaphoresSubmitted flush(const GrFlushInfo& info);
/**
- * Call to ensure all drawing to the context has been issued to the underlying 3D API.
+ * Submit outstanding work to the gpu from all previously un-submitted flushes. The return
+ * value of the submit will indicate whether or not the submission to the GPU was successful.
*
- * If this call returns GrSemaphoresSubmitted::kNo, the GPU backend will not have created or
- * added any semaphores to signal on the GPU. Thus the client should not have the GPU wait on
- * any of the semaphores passed in with the GrFlushInfo. However, any pending commands to the
- * context will still be flushed. It should be emphasized that a return value of
- * GrSemaphoresSubmitted::kNo does not mean the flush did not happen. It simply means there were
- * no semaphores submitted to the GPU. A caller should only take this as a failure if they
- * passed in semaphores to be submitted.
+ * If the call returns true, all previously passed in semaphores in flush calls will have been
+ * submitted to the GPU and they can safely be waited on. The caller should wait on those
+ * semaphores or perform some other global synchronization before deleting the semaphores.
*
- * If the GrPrepareForExternalIORequests contains valid gpu backed SkSurfaces or SkImages, Skia
- * will put the underlying backend objects into a state that is ready for external uses. See
- * declaration of GrPreopareForExternalIORequests for more details.
- */
- GrSemaphoresSubmitted flush(const GrFlushInfo&, const GrPrepareForExternalIORequests&);
-
- /**
- * Deprecated.
- */
- GrSemaphoresSubmitted flush(GrFlushFlags flags, int numSemaphores,
- GrBackendSemaphore signalSemaphores[],
- GrGpuFinishedProc finishedProc = nullptr,
- GrGpuFinishedContext finishedContext = nullptr) {
- GrFlushInfo info;
- info.fFlags = flags;
- info.fNumSemaphores = numSemaphores;
- info.fSignalSemaphores = signalSemaphores;
- info.fFinishedProc = finishedProc;
- info.fFinishedContext = finishedContext;
- return this->flush(info);
- }
-
- /**
- * Deprecated.
- */
- GrSemaphoresSubmitted flushAndSignalSemaphores(int numSemaphores,
- GrBackendSemaphore signalSemaphores[]) {
- GrFlushInfo info;
- info.fNumSemaphores = numSemaphores;
- info.fSignalSemaphores = signalSemaphores;
- return this->flush(info);
- }
-
- /**
- * Placeholder no-op submit call.
+ * If it returns false, then those same semaphores will not have been submitted and we will not
+ * try to submit them again. The caller is free to delete the semaphores at any time.
+ *
+ * If the syncCpu flag is true this function will return once the gpu has finished with all
+ * submitted work.
*/
- bool submit(bool syncToCpu = false);
+ bool submit(bool syncCpu = false);
/**
* Checks whether any asynchronous work is complete and if so calls related callbacks.
@@ -472,8 +468,8 @@ public:
* If possible, create a backend texture initialized to a particular color. The client should
* ensure that the returned backend texture is valid. The client can pass in a finishedProc
* to be notified when the data has been uploaded by the gpu and the texture can be deleted. The
- * client can assume the upload work has been submitted to the gpu. The finishedProc will always
- * get called even if we failed to create the GrBackendTexture.
+ * client is required to call GrContext::submit to send the upload work to the gpu. The
+ * finishedProc will always get called even if we failed to create the GrBackendTexture.
* For the Vulkan backend the layout of the created VkImage will be:
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
*/
@@ -490,8 +486,8 @@ public:
* If possible, create a backend texture initialized to a particular color. The client should
* ensure that the returned backend texture is valid. The client can pass in a finishedProc
* to be notified when the data has been uploaded by the gpu and the texture can be deleted. The
- * client can assume the upload work has been submitted to the gpu. The finishedProc will always
- * get called even if we failed to create the GrBackendTexture.
+ * client is required to call GrContext::submit to send the upload work to the gpu. The
+ * finishedProc will always get called even if we failed to create the GrBackendTexture.
* If successful, the created backend texture will be compatible with the provided
* SkColorType.
* For the Vulkan backend the layout of the created VkImage will be:
@@ -510,9 +506,9 @@ public:
* If possible, create a backend texture initialized to a particular color that is
* compatible with the provided characterization. The client should ensure that the
* returned backend texture is valid. The client can pass in a finishedProc to be notified when
- * the data has been uploaded by the gpu and the texture can be deleted. The client can assume
- * the upload work has been submitted to the gpu. The finishedProc will always get called even
- * if we failed to create the GrBackendTexture.
+ * the data has been uploaded by the gpu and the texture can be deleted. The client is required
+ * to call GrContext::submit to send the upload work to the gpu. The finishedProc will always
+ * get called even if we failed to create the GrBackendTexture.
* For the Vulkan backend the layout of the created VkImage will be:
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL if texturaeble
* VK_IMAGE_LAYOUT_UNDEFINED if not textureable
@@ -526,11 +522,12 @@ public:
* If possible, create a backend texture initialized with the provided pixmap data. The client
* should ensure that the returned backend texture is valid. The client can pass in a
* finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
- * deleted. The client can assume the upload work has been submitted to the gpu. The
- * finishedProc will always get called even if we failed to create the GrBackendTexture.
+ * deleted. The client is required to call GrContext::submit to send the upload work to the gpu.
+ * The finishedProc will always get called even if we failed to create the GrBackendTexture.
* If successful, the created backend texture will be compatible with the provided
* pixmap(s). Compatible, in this case, means that the backend format will be the result
- * of calling defaultBackendFormat on the base pixmap's colortype.
+ * of calling defaultBackendFormat on the base pixmap's colortype. The src data can be deleted
+ * when this call returns.
* If numLevels is 1 a non-mipMapped texture will result. If a mipMapped texture is desired
* the data for all the mipmap levels must be provided. In the mipmapped case all the
* colortypes of the provided pixmaps must be the same. Additionally, all the miplevels
@@ -558,8 +555,8 @@ public:
* If possible, updates a backend texture to be filled to a particular color. The client should
* check the return value to see if the update was successful. The client can pass in a
* finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
- * deleted. The client can assume the upload work has been submitted to the gpu. The
- * finishedProc will always get called even if we failed to update the GrBackendTexture.
+ * deleted. The client is required to call GrContext::submit to send the upload work to the gpu.
+ * The finishedProc will always get called even if we failed to update the GrBackendTexture.
* For the Vulkan backend after a successful update the layout of the created VkImage will be:
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
*/
@@ -572,10 +569,11 @@ public:
* If possible, updates a backend texture filled with the provided pixmap data. The client
* should check the return value to see if the update was successful. The client can pass in a
* finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
- * deleted. The client can assume the upload work has been submitted to the gpu. The
- * finishedProc will always get called even if we failed to create the GrBackendTexture.
+ * deleted. The client is required to call GrContext::submit to send the upload work to the gpu.
+ * The finishedProc will always get called even if we failed to create the GrBackendTexture.
* The backend texture must be compatible with the provided pixmap(s). Compatible, in this case,
- * means that the backend format is compatible with the base pixmap's colortype.
+ * means that the backend format is compatible with the base pixmap's colortype. The src data
+ * can be deleted when this call returns.
* If the backend texture is mip mapped, the data for all the mipmap levels must be provided.
* In the mipmapped case all the colortypes of the provided pixmaps must be the same.
* Additionally, all the miplevels must be sized correctly (please see
@@ -604,8 +602,8 @@ public:
*If possible, create a compressed backend texture initialized to a particular color. The
* client should ensure that the returned backend texture is valid. The client can pass in a
* finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
- * deleted. The client can assume the upload work has been submitted to the gpu. The
- * finishedProc will always get called even if we failed to create the GrBackendTexture.
+ * deleted. The client is required to call GrContext::submit to send the upload work to the gpu.
+ * The finishedProc will always get called even if we failed to create the GrBackendTexture.
* For the Vulkan backend the layout of the created VkImage will be:
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
*/
@@ -629,8 +627,8 @@ public:
* If possible, create a backend texture initialized with the provided raw data. The client
* should ensure that the returned backend texture is valid. The client can pass in a
* finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
- * deleted. The client can assume the upload work has been submitted to the gpu. The
- * finishedProc will always get called even if we failed to create the GrBackendTexture
+ * deleted. The client is required to call GrContext::submit to send the upload work to the gpu.
+ * The finishedProc will always get called even if we failed to create the GrBackendTexture
* If numLevels is 1 a non-mipMapped texture will result. If a mipMapped texture is desired
* the data for all the mipmap levels must be provided. Additionally, all the miplevels
* must be sized correctly (please see SkMipMap::ComputeLevelSize and ComputeLevelCount).
@@ -653,6 +651,26 @@ public:
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr);
+ /**
+ * Updates the state of the GrBackendTexture/RenderTarget to have the passed in
+ * GrBackendSurfaceMutableState. All objects that wrap the backend surface (i.e. SkSurfaces and
+ * SkImages) will also be aware of this state change. This call does not submit the state change
+ * to the gpu, but requires the client to call GrContext::submit to send it to the GPU. The work
+ * for this call is ordered linearly with all other calls that require GrContext::submit to be
+ * called (e.g updateBackendTexture and flush). If finishedProc is not null then it will be
+ * called with finishedContext after the state transition is known to have occurred on the GPU.
+ *
+ * See GrBackendSurfaceMutableState to see what state can be set via this call.
+ */
+ bool setBackendTextureState(const GrBackendTexture&,
+ const GrBackendSurfaceMutableState&,
+ GrGpuFinishedProc finishedProc = nullptr,
+ GrGpuFinishedContext finishedContext = nullptr);
+ bool setBackendRenderTargetState(const GrBackendRenderTarget&,
+ const GrBackendSurfaceMutableState&,
+ GrGpuFinishedProc finishedProc = nullptr,
+ GrGpuFinishedContext finishedContext = nullptr);
+
void deleteBackendTexture(GrBackendTexture);
// This interface allows clients to pre-compile shaders and populate the runtime program cache.
@@ -680,16 +698,14 @@ public:
#endif
protected:
- GrContext(GrBackendApi, const GrContextOptions&, int32_t contextID = SK_InvalidGenID);
+ GrContext(sk_sp<GrContextThreadSafeProxy>);
- bool init(sk_sp<const GrCaps>) override;
+ bool init() override;
GrContext* asDirectContext() override { return this; }
virtual GrAtlasManager* onGetAtlasManager() = 0;
- sk_sp<GrContextThreadSafeProxy> fThreadSafeProxy;
-
private:
// fTaskGroup must appear before anything that uses it (e.g. fGpu), so that it is destroyed
// after all of its users. Clients of fTaskGroup will generally want to ensure that they call
diff --git a/chromium/third_party/skia/include/gpu/GrContextOptions.h b/chromium/third_party/skia/include/gpu/GrContextOptions.h
index 5bdf37687c1..2f3d5b92e5e 100644
--- a/chromium/third_party/skia/include/gpu/GrContextOptions.h
+++ b/chromium/third_party/skia/include/gpu/GrContextOptions.h
@@ -134,16 +134,20 @@ struct SK_API GrContextOptions {
/**
* Below this threshold size in device space distance field fonts won't be used. Distance field
- * fonts don't support hinting which is more important at smaller sizes. A negative value means
- * use the default threshold.
+ * fonts don't support hinting which is more important at smaller sizes.
*/
- float fMinDistanceFieldFontSize = -1.f;
+ float fMinDistanceFieldFontSize = 18;
/**
- * Above this threshold size in device space glyphs are drawn as individual paths. A negative
- * value means use the default threshold.
+ * Above this threshold size in device space glyphs are drawn as individual paths.
*/
- float fGlyphsAsPathsFontSize = -1.f;
+#if defined(SK_BUILD_FOR_ANDROID)
+ float fGlyphsAsPathsFontSize = 384;
+#elif defined(SK_BUILD_FOR_MAC)
+ float fGlyphsAsPathsFontSize = 256;
+#else
+ float fGlyphsAsPathsFontSize = 324;
+#endif
/**
* Can the glyph atlas use multiple textures. If allowed, the each texture's size is bound by
@@ -258,17 +262,14 @@ struct SK_API GrContextOptions {
bool fClearAllTextures = false;
/**
- * Include or exclude specific GPU path renderers.
+ * Randomly generate a (false) GL_OUT_OF_MEMORY error
*/
- GpuPathRenderers fGpuPathRenderers = GpuPathRenderers::kDefault;
-#endif
+ bool fRandomGLOOM = false;
-#if SK_SUPPORT_ATLAS_TEXT
/**
- * Controls whether distance field glyph vertices always have 3 components even when the view
- * matrix does not have perspective.
+ * Include or exclude specific GPU path renderers.
*/
- Enable fDistanceFieldGlyphVerticesAlwaysHaveW = Enable::kDefault;
+ GpuPathRenderers fGpuPathRenderers = GpuPathRenderers::kDefault;
#endif
GrDriverBugWorkarounds fDriverBugWorkarounds;
diff --git a/chromium/third_party/skia/include/gpu/GrContextThreadSafeProxy.h b/chromium/third_party/skia/include/gpu/GrContextThreadSafeProxy.h
index bfd37ac77e1..ca4cb313dcd 100644
--- a/chromium/third_party/skia/include/gpu/GrContextThreadSafeProxy.h
+++ b/chromium/third_party/skia/include/gpu/GrContextThreadSafeProxy.h
@@ -8,11 +8,16 @@
#ifndef GrContextThreadSafeProxy_DEFINED
#define GrContextThreadSafeProxy_DEFINED
-#include "include/private/GrContext_Base.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkRefCnt.h"
+#include "include/gpu/GrContextOptions.h"
+#include "include/gpu/GrTypes.h"
+
+#include <atomic>
class GrBackendFormat;
+class GrCaps;
class GrContextThreadSafeProxyPriv;
-struct SkImageInfo;
class SkSurfaceCharacterization;
class SkSurfaceProps;
@@ -20,9 +25,9 @@ class SkSurfaceProps;
* Can be used to perform actions related to the generating GrContext in a thread safe manner. The
* proxy does not access the 3D API (e.g. OpenGL) that backs the generating GrContext.
*/
-class SK_API GrContextThreadSafeProxy : public GrContext_Base {
+class SK_API GrContextThreadSafeProxy final : public SkNVRefCnt<GrContextThreadSafeProxy> {
public:
- ~GrContextThreadSafeProxy() override;
+ ~GrContextThreadSafeProxy();
/**
* Create a surface characterization for a DDL that will be replayed into the GrContext
@@ -73,13 +78,13 @@ public:
*
* The caller should check that the returned format is valid.
*/
- GrBackendFormat defaultBackendFormat(SkColorType ct, GrRenderable renderable) const {
- return INHERITED::defaultBackendFormat(ct, renderable);
- }
+ GrBackendFormat defaultBackendFormat(SkColorType ct, GrRenderable renderable) const;
+
+ bool isValid() const { return nullptr != fCaps; }
bool operator==(const GrContextThreadSafeProxy& that) const {
// Each GrContext should only ever have a single thread-safe proxy.
- SkASSERT((this == &that) == (this->contextID() == that.contextID()));
+ SkASSERT((this == &that) == (this->fContextID == that.fContextID));
return this == &that;
}
@@ -93,11 +98,21 @@ private:
friend class GrContextThreadSafeProxyPriv; // for ctor and hidden methods
// DDL TODO: need to add unit tests for backend & maybe options
- GrContextThreadSafeProxy(GrBackendApi, const GrContextOptions&, uint32_t contextID);
+ GrContextThreadSafeProxy(GrBackendApi, const GrContextOptions&);
+
+ void abandonContext();
+ bool abandoned() const;
- bool init(sk_sp<const GrCaps>) override;
+ // TODO: This should be part of the constructor but right now we have a chicken-and-egg problem
+ // with GrContext where we get the caps by creating a GPU which requires a context (see the
+ // `init` method on GrContext_Base).
+ void init(sk_sp<const GrCaps>);
- typedef GrContext_Base INHERITED;
+ const GrBackendApi fBackend;
+ const GrContextOptions fOptions;
+ const uint32_t fContextID;
+ sk_sp<const GrCaps> fCaps;
+ std::atomic<bool> fAbandoned{false};
};
#endif
diff --git a/chromium/third_party/skia/include/gpu/GrTypes.h b/chromium/third_party/skia/include/gpu/GrTypes.h
index e7d4f7e4c8c..b6f5e6fb39a 100644
--- a/chromium/third_party/skia/include/gpu/GrTypes.h
+++ b/chromium/third_party/skia/include/gpu/GrTypes.h
@@ -227,13 +227,16 @@ static const uint32_t kAll_GrBackendState = 0xffffffff;
enum GrFlushFlags {
kNone_GrFlushFlags = 0,
- // flush will wait till all submitted GPU work is finished before returning.
+ // Deprecated: Use syncCpu call on submit instead.
kSyncCpu_GrFlushFlag = 0x1,
};
typedef void* GrGpuFinishedContext;
typedef void (*GrGpuFinishedProc)(GrGpuFinishedContext finishedContext);
+typedef void* GrGpuSubmittedContext;
+typedef void (*GrGpuSubmittedProc)(GrGpuSubmittedContext submittedContext, bool success);
+
/**
* Struct to supply options to flush calls.
*
@@ -241,7 +244,8 @@ typedef void (*GrGpuFinishedProc)(GrGpuFinishedContext finishedContext);
* passes in an array of fNumSemaphores GrBackendSemaphores. In general these GrBackendSemaphore's
* can be either initialized or not. If they are initialized, the backend uses the passed in
* semaphore. If it is not initialized, a new semaphore is created and the GrBackendSemaphore
- * object is initialized with that semaphore.
+ * object is initialized with that semaphore. The semaphores are not sent to the GPU until the next
+ * GrContext::submit call is made. See the GrContext::submit for more information.
*
* The client will own and be responsible for deleting the underlying semaphores that are stored
* and returned in initialized GrBackendSemaphore objects. The GrBackendSemaphore objects
@@ -251,52 +255,40 @@ typedef void (*GrGpuFinishedProc)(GrGpuFinishedContext finishedContext);
* from this flush call and all previous flush calls has finished on the GPU. If the flush call
* fails due to an error and nothing ends up getting sent to the GPU, the finished proc is called
* immediately.
+ *
+ * If a submittedProc is provided, the submittedProc will be called when all work from this flush
+ * call is submitted to the GPU. If the flush call fails due to an error and nothing will get sent
+ * to the GPU, the submitted proc is called immediately. It is possibly that when work is finally
+ * submitted, that the submission actual fails. In this case we will not reattempt to do the
+ * submission. Skia notifies the client of these via the success bool passed into the submittedProc.
+ * The submittedProc is useful to the client to know when semaphores that were sent with the flush
+ * have actually been submitted to the GPU so that they can be waited on (or deleted if the submit
+ * fails).
+ * Note about GL: In GL work gets sent to the driver immediately during the flush call, but we don't
+ * really know when the driver sends the work to the GPU. Therefore, we treat the submitted proc as
+ * we do in other backends. It will be called when the next GrContext::submit is called after the
+ * flush (or possibly during the flush if there is no work to be done for the flush). The main use
+ * case for the submittedProc is to know when semaphores have been sent to the GPU and even in GL
+ * it is required to call GrContext::submit to flush them. So a client should be able to treat all
+ * backend APIs the same in terms of how the submitted procs are treated.
*/
struct GrFlushInfo {
- GrFlushFlags fFlags = kNone_GrFlushFlags;
- int fNumSemaphores = 0;
- GrBackendSemaphore* fSignalSemaphores = nullptr;
- GrGpuFinishedProc fFinishedProc = nullptr;
+ GrFlushFlags fFlags = kNone_GrFlushFlags;
+ int fNumSemaphores = 0;
+ GrBackendSemaphore* fSignalSemaphores = nullptr;
+ GrGpuFinishedProc fFinishedProc = nullptr;
GrGpuFinishedContext fFinishedContext = nullptr;
+ GrGpuSubmittedProc fSubmittedProc = nullptr;
+ GrGpuSubmittedContext fSubmittedContext = nullptr;
};
/**
- * Enum used as return value when flush with semaphores so the client knows whether the semaphores
- * were submitted to GPU or not.
+ * Enum used as return value when flush with semaphores so the client knows whether the valid
+ * semaphores will be submitted on the next GrContext::submit call.
*/
enum class GrSemaphoresSubmitted : bool {
kNo = false,
kYes = true
};
-/**
- * Array of SkImages and SkSurfaces which Skia will prepare for external use when passed into a
- * flush call on GrContext. All the SkImages and SkSurfaces must be GPU backed.
- *
- * If fPrepareSurfaceForPresent is not nullptr, then it must be an array the size of fNumSurfaces.
- * Each entry in the array corresponds to the SkSurface at the same index in the fSurfaces array. If
- * an entry is true, then that surface will be prepared for both external use and present.
- *
- * Currently this only has an effect if the backend API is Vulkan. In this case, all the underlying
- * VkImages associated with the SkImages and SkSurfaces will be transitioned into the VkQueueFamily
- * in which they were originally wrapped or created with. This allows a client to wrap a VkImage
- * from a queue which is different from the graphics queue and then have Skia transition it back to
- * that queue without needing to delete the SkImage or SkSurface. If the an SkSurface is also
- * flagged to be prepared for present, then its VkImageLayout will be set to
- * VK_IMAGE_LAYOUT_PRESENT_SRC_KHR if the VK_KHR_swapchain extension has been enabled for the
- * GrContext and the original queue is not VK_QUEUE_FAMILY_EXTERNAL or VK_QUEUE_FAMILY_FOREIGN_EXT.
- *
- * If an SkSurface or SkImage is used again, it will be transitioned back to the graphics queue and
- * whatever layout is needed for its use.
- */
-struct GrPrepareForExternalIORequests {
- int fNumImages = 0;
- SkImage** fImages = nullptr;
- int fNumSurfaces = 0;
- SkSurface** fSurfaces = nullptr;
- bool* fPrepareSurfaceForPresent = nullptr;
-
- bool hasRequests() const { return fNumImages || fNumSurfaces; }
-};
-
#endif
diff --git a/chromium/third_party/skia/include/gpu/gl/GrGLInterface.h b/chromium/third_party/skia/include/gpu/gl/GrGLInterface.h
index 17655bdbedb..c571314cae4 100644
--- a/chromium/third_party/skia/include/gpu/gl/GrGLInterface.h
+++ b/chromium/third_party/skia/include/gpu/gl/GrGLInterface.h
@@ -49,6 +49,13 @@ struct SK_API GrGLInterface : public SkRefCnt {
private:
typedef SkRefCnt INHERITED;
+#if GR_GL_CHECK_ERROR
+ // This is here to avoid having our debug code that checks for a GL error after most GL calls
+ // accidentally swallow an OOM that should be reported.
+ mutable bool fOOMed = false;
+ bool fSuppressErrorLogging = false;
+#endif
+
public:
GrGLInterface();
@@ -57,6 +64,19 @@ public:
// extensions.
bool validate() const;
+#if GR_GL_CHECK_ERROR
+ GrGLenum checkError(const char* location, const char* call) const;
+ bool checkAndResetOOMed() const;
+ void suppressErrorLogging();
+#endif
+
+#if GR_TEST_UTILS
+ GrGLInterface(const GrGLInterface& that)
+ : fStandard(that.fStandard)
+ , fExtensions(that.fExtensions)
+ , fFunctions(that.fFunctions) {}
+#endif
+
// Indicates the type of GL implementation
union {
GrGLStandard fStandard;
diff --git a/chromium/third_party/skia/include/gpu/mock/GrMockTypes.h b/chromium/third_party/skia/include/gpu/mock/GrMockTypes.h
index b4c55c81d5b..897a83105eb 100644
--- a/chromium/third_party/skia/include/gpu/mock/GrMockTypes.h
+++ b/chromium/third_party/skia/include/gpu/mock/GrMockTypes.h
@@ -110,12 +110,12 @@ struct GrMockOptions {
// GrCaps options.
bool fMipMapSupport = false;
bool fDrawInstancedSupport = false;
- bool fTessellationSupport = false;
bool fHalfFloatVertexAttributeSupport = false;
uint32_t fMapBufferFlags = 0;
int fMaxTextureSize = 2048;
int fMaxRenderTargetSize = 2048;
int fMaxVertexAttributes = 16;
+ int fMaxTessellationSegments = 0;
ConfigOptions fConfigOptions[kGrColorTypeCnt];
ConfigOptions fCompressedOptions[SkImage::kCompressionTypeCount];
diff --git a/chromium/third_party/skia/include/gpu/vk/GrVkMemoryAllocator.h b/chromium/third_party/skia/include/gpu/vk/GrVkMemoryAllocator.h
index 5102496b831..b25d5458d90 100644
--- a/chromium/third_party/skia/include/gpu/vk/GrVkMemoryAllocator.h
+++ b/chromium/third_party/skia/include/gpu/vk/GrVkMemoryAllocator.h
@@ -50,11 +50,43 @@ public:
kGpuWritesCpuReads,
};
- virtual bool allocateMemoryForImage(VkImage image, AllocationPropertyFlags flags,
- GrVkBackendMemory*) = 0;
+ // DEPRECATED: Use and implement allocateImageMemory instead
+ virtual bool allocateMemoryForImage(VkImage, AllocationPropertyFlags, GrVkBackendMemory*) {
+ // The default implementation here is so clients can delete this virtual as the switch to
+ // the new one which returns a VkResult.
+ return false;
+ }
+
+ virtual VkResult allocateImageMemory(VkImage image, AllocationPropertyFlags flags,
+ GrVkBackendMemory* memory) {
+ bool result = this->allocateMemoryForImage(image, flags, memory);
+ // VK_ERROR_INITIALIZATION_FAILED is a bogus result to return from this function, but it is
+ // just something to return that is not VK_SUCCESS and can't be interpreted by a caller to
+ // mean something specific happened like device lost or oom. This will be removed once we
+ // update clients to implement this virtual.
+ return result ? VK_SUCCESS : VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ // DEPRECATED: Use and implement allocateBufferMemory instead
+ virtual bool allocateMemoryForBuffer(VkBuffer, BufferUsage, AllocationPropertyFlags,
+ GrVkBackendMemory*) {
+ // The default implementation here is so clients can delete this virtual as the switch to
+ // the new one which returns a VkResult.
+ return false;
+ }
+
+ virtual VkResult allocateBufferMemory(VkBuffer buffer,
+ BufferUsage usage,
+ AllocationPropertyFlags flags,
+ GrVkBackendMemory* memory) {
+ bool result = this->allocateMemoryForBuffer(buffer, usage, flags, memory);
+ // VK_ERROR_INITIALIZATION_FAILED is a bogus result to return from this function, but it is
+ // just something to return that is not VK_SUCCESS and can't be interpreted by a caller to
+ // mean something specific happened like device lost or oom. This will be removed once we
+ // update clients to implement this virtual.
+ return result ? VK_SUCCESS : VK_ERROR_INITIALIZATION_FAILED;
+ }
- virtual bool allocateMemoryForBuffer(VkBuffer buffer, BufferUsage usage,
- AllocationPropertyFlags flags, GrVkBackendMemory*) = 0;
// Fills out the passed in GrVkAlloc struct for the passed in GrVkBackendMemory.
virtual void getAllocInfo(const GrVkBackendMemory&, GrVkAlloc*) const = 0;
@@ -62,7 +94,15 @@ public:
// Maps the entire allocation and returns a pointer to the start of the allocation. The
// implementation may map more memory than just the allocation, but the returned pointer must
// point at the start of the memory for the requested allocation.
- virtual void* mapMemory(const GrVkBackendMemory&) = 0;
+ virtual void* mapMemory(const GrVkBackendMemory&) { return nullptr; }
+ virtual VkResult mapMemory(const GrVkBackendMemory& memory, void** data) {
+ *data = this->mapMemory(memory);
+ // VK_ERROR_INITIALIZATION_FAILED is a bogus result to return from this function, but it is
+ // just something to return that is not VK_SUCCESS and can't be interpreted by a caller to
+ // mean something specific happened like device lost or oom. This will be removed once we
+ // update clients to implement this virtual.
+ return *data ? VK_SUCCESS : VK_ERROR_INITIALIZATION_FAILED;
+ }
virtual void unmapMemory(const GrVkBackendMemory&) = 0;
// The following two calls are used for managing non-coherent memory. The offset is relative to
@@ -70,10 +110,18 @@ public:
// must make sure that the offset + size passed in is less that or equal to the allocation size.
// It is the responsibility of the implementation to make sure all alignment requirements are
// followed. The client should not have to deal with any sort of alignment issues.
- virtual void flushMappedMemory(const GrVkBackendMemory&, VkDeviceSize offset,
- VkDeviceSize size) = 0;
- virtual void invalidateMappedMemory(const GrVkBackendMemory&, VkDeviceSize offset,
- VkDeviceSize size)= 0;
+ virtual void flushMappedMemory(const GrVkBackendMemory&, VkDeviceSize, VkDeviceSize) {}
+ virtual VkResult flushMemory(const GrVkBackendMemory& memory, VkDeviceSize offset,
+ VkDeviceSize size) {
+ this->flushMappedMemory(memory, offset, size);
+ return VK_SUCCESS;
+ }
+ virtual void invalidateMappedMemory(const GrVkBackendMemory&, VkDeviceSize, VkDeviceSize) {}
+ virtual VkResult invalidateMemory(const GrVkBackendMemory& memory, VkDeviceSize offset,
+ VkDeviceSize size) {
+ this->invalidateMappedMemory(memory, offset, size);
+ return VK_SUCCESS;
+ }
virtual void freeMemory(const GrVkBackendMemory&) = 0;
diff --git a/chromium/third_party/skia/include/gpu/vk/GrVkTypes.h b/chromium/third_party/skia/include/gpu/vk/GrVkTypes.h
index c7353677d5c..e869238899b 100644
--- a/chromium/third_party/skia/include/gpu/vk/GrVkTypes.h
+++ b/chromium/third_party/skia/include/gpu/vk/GrVkTypes.h
@@ -105,7 +105,7 @@ struct GrVkYcbcrConversionInfo {
VkChromaLocation yChromaOffset,
VkFilter chromaFilter,
VkBool32 forceExplicitReconstruction,
- uint64_t externalFormat,
+ int64_t externalFormat,
VkFormatFeatureFlags externalFormatFeatures)
: GrVkYcbcrConversionInfo(VK_FORMAT_UNDEFINED, externalFormat, ycbcrModel, ycbcrRange,
xChromaOffset, yChromaOffset, chromaFilter,
@@ -135,7 +135,7 @@ struct GrVkYcbcrConversionInfo {
// The external format. Must be non-zero for external images, zero otherwise.
// Should be compatible to be used in a VkExternalFormatANDROID struct.
- uint64_t fExternalFormat;
+ int64_t fExternalFormat;
VkSamplerYcbcrModelConversion fYcbcrModel;
VkSamplerYcbcrRange fYcbcrRange;
@@ -149,6 +149,12 @@ struct GrVkYcbcrConversionInfo {
VkFormatFeatureFlags fFormatFeatures;
};
+/*
+ * When wrapping a GrBackendTexture or GrBackendRendenderTarget, the fCurrentQueueFamily should
+ * either be VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_EXTERNAL, or VK_QUEUE_FAMILY_FOREIGN_EXT. If
+ * fSharingMode is VK_SHARING_MODE_EXCLUSIVE then fCurrentQueueFamily can also be the graphics
+ * queue index passed into Skia.
+ */
struct GrVkImageInfo {
VkImage fImage;
GrVkAlloc fAlloc;
@@ -159,6 +165,7 @@ struct GrVkImageInfo {
uint32_t fCurrentQueueFamily;
GrProtected fProtected;
GrVkYcbcrConversionInfo fYcbcrConversionInfo;
+ VkSharingMode fSharingMode;
GrVkImageInfo()
: fImage(VK_NULL_HANDLE)
@@ -169,7 +176,8 @@ struct GrVkImageInfo {
, fLevelCount(0)
, fCurrentQueueFamily(VK_QUEUE_FAMILY_IGNORED)
, fProtected(GrProtected::kNo)
- , fYcbcrConversionInfo() {}
+ , fYcbcrConversionInfo()
+ , fSharingMode(VK_SHARING_MODE_EXCLUSIVE) {}
GrVkImageInfo(VkImage image,
GrVkAlloc alloc,
@@ -179,7 +187,8 @@ struct GrVkImageInfo {
uint32_t levelCount,
uint32_t currentQueueFamily = VK_QUEUE_FAMILY_IGNORED,
GrProtected isProtected = GrProtected::kNo,
- GrVkYcbcrConversionInfo ycbcrConversionInfo = GrVkYcbcrConversionInfo())
+ GrVkYcbcrConversionInfo ycbcrConversionInfo = GrVkYcbcrConversionInfo(),
+ VkSharingMode sharingMode = VK_SHARING_MODE_EXCLUSIVE)
: fImage(image)
, fAlloc(alloc)
, fImageTiling(imageTiling)
@@ -188,18 +197,20 @@ struct GrVkImageInfo {
, fLevelCount(levelCount)
, fCurrentQueueFamily(currentQueueFamily)
, fProtected(isProtected)
- , fYcbcrConversionInfo(ycbcrConversionInfo) {}
+ , fYcbcrConversionInfo(ycbcrConversionInfo)
+ , fSharingMode(sharingMode) {}
- GrVkImageInfo(const GrVkImageInfo& info, VkImageLayout layout)
+ GrVkImageInfo(const GrVkImageInfo& info, VkImageLayout layout, uint32_t familyQueueIndex)
: fImage(info.fImage)
, fAlloc(info.fAlloc)
, fImageTiling(info.fImageTiling)
, fImageLayout(layout)
, fFormat(info.fFormat)
, fLevelCount(info.fLevelCount)
- , fCurrentQueueFamily(info.fCurrentQueueFamily)
+ , fCurrentQueueFamily(familyQueueIndex)
, fProtected(info.fProtected)
- , fYcbcrConversionInfo(info.fYcbcrConversionInfo) {}
+ , fYcbcrConversionInfo(info.fYcbcrConversionInfo)
+ , fSharingMode(info.fSharingMode) {}
#if GR_TEST_UTILS
bool operator==(const GrVkImageInfo& that) const {
@@ -207,7 +218,8 @@ struct GrVkImageInfo {
fImageTiling == that.fImageTiling && fImageLayout == that.fImageLayout &&
fFormat == that.fFormat && fLevelCount == that.fLevelCount &&
fCurrentQueueFamily == that.fCurrentQueueFamily && fProtected == that.fProtected &&
- fYcbcrConversionInfo == that.fYcbcrConversionInfo;
+ fYcbcrConversionInfo == that.fYcbcrConversionInfo &&
+ fSharingMode == that.fSharingMode;
}
#endif
};
diff --git a/chromium/third_party/skia/include/ports/SkFontMgr_mac_ct.h b/chromium/third_party/skia/include/ports/SkFontMgr_mac_ct.h
new file mode 100644
index 00000000000..45cba65b5da
--- /dev/null
+++ b/chromium/third_party/skia/include/ports/SkFontMgr_mac_ct.h
@@ -0,0 +1,27 @@
+/*
+ * 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 SkFontMgr_mac_ct_DEFINED
+#define SkFontMgr_mac_ct_DEFINED
+
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkTypes.h"
+
+#ifdef SK_BUILD_FOR_MAC
+#import <ApplicationServices/ApplicationServices.h>
+#endif
+
+#ifdef SK_BUILD_FOR_IOS
+#include <CoreText/CoreText.h>
+#endif
+
+class SkFontMgr;
+
+/** Create a font manager for CoreText. If the collection is nullptr the system default will be used. */
+SK_API extern sk_sp<SkFontMgr> SkFontMgr_New_CoreText(CTFontCollectionRef);
+
+#endif // SkFontMgr_mac_ct_DEFINED
diff --git a/chromium/third_party/skia/include/private/GrContext_Base.h b/chromium/third_party/skia/include/private/GrContext_Base.h
index b5b3119361f..326c9107724 100644
--- a/chromium/third_party/skia/include/private/GrContext_Base.h
+++ b/chromium/third_party/skia/include/private/GrContext_Base.h
@@ -16,6 +16,7 @@
class GrBaseContextPriv;
class GrCaps;
class GrContext;
+class GrContextThreadSafeProxy;
class GrImageContext;
class GrRecordingContext;
@@ -26,7 +27,7 @@ public:
/*
* The 3D API backing this context
*/
- SK_API GrBackendApi backend() const { return fBackend; }
+ SK_API GrBackendApi backend() const;
/*
* Retrieve the default GrBackendFormat for a given SkColorType and renderability.
@@ -39,6 +40,9 @@ public:
SK_API GrBackendFormat compressedBackendFormat(SkImage::CompressionType) const;
+ // TODO: When the public version is gone, rename to refThreadSafeProxy and add raw ptr ver.
+ sk_sp<GrContextThreadSafeProxy> threadSafeProxy();
+
// Provides access to functions that aren't part of the public API.
GrBaseContextPriv priv();
const GrBaseContextPriv priv() const;
@@ -46,9 +50,9 @@ public:
protected:
friend class GrBaseContextPriv; // for hidden functions
- GrContext_Base(GrBackendApi backend, const GrContextOptions& options, uint32_t contextID);
+ GrContext_Base(sk_sp<GrContextThreadSafeProxy>);
- virtual bool init(sk_sp<const GrCaps>);
+ virtual bool init();
/**
* An identifier for this context. The id is used by all compatible contexts. For example,
@@ -57,7 +61,7 @@ protected:
* a third thread with a direct context, then all three contexts will report the same id.
* It is an error for an image to be used with contexts that report different ids.
*/
- uint32_t contextID() const { return fContextID; }
+ uint32_t contextID() const;
bool matches(GrContext_Base* candidate) const {
return candidate->contextID() == this->contextID();
@@ -66,7 +70,7 @@ protected:
/*
* The options in effect for this context
*/
- const GrContextOptions& options() const { return fOptions; }
+ const GrContextOptions& options() const;
const GrCaps* caps() const;
sk_sp<const GrCaps> refCaps() const;
@@ -75,12 +79,9 @@ protected:
virtual GrRecordingContext* asRecordingContext() { return nullptr; }
virtual GrContext* asDirectContext() { return nullptr; }
-private:
- const GrBackendApi fBackend;
- const GrContextOptions fOptions;
- const uint32_t fContextID;
- sk_sp<const GrCaps> fCaps;
+ sk_sp<GrContextThreadSafeProxy> fThreadSafeProxy;
+private:
typedef SkRefCnt INHERITED;
};
diff --git a/chromium/third_party/skia/include/private/GrImageContext.h b/chromium/third_party/skia/include/private/GrImageContext.h
index 9dc0acb8154..65d30642bc5 100644
--- a/chromium/third_party/skia/include/private/GrImageContext.h
+++ b/chromium/third_party/skia/include/private/GrImageContext.h
@@ -18,10 +18,6 @@ class GrImageContext : public GrContext_Base {
public:
~GrImageContext() override;
- SK_API GrBackendFormat defaultBackendFormat(SkColorType ct, GrRenderable renderable) const {
- return INHERITED::defaultBackendFormat(ct, renderable);
- }
-
// Provides access to functions that aren't part of the public API.
GrImageContextPriv priv();
const GrImageContextPriv priv() const;
@@ -29,7 +25,7 @@ public:
protected:
friend class GrImageContextPriv; // for hidden functions
- GrImageContext(GrBackendApi, const GrContextOptions&, uint32_t contextID);
+ GrImageContext(sk_sp<GrContextThreadSafeProxy>);
SK_API virtual void abandonContext();
SK_API virtual bool abandoned();
@@ -44,7 +40,6 @@ protected:
private:
std::unique_ptr<GrProxyProvider> fProxyProvider;
- bool fAbandoned = false;
// In debug builds we guard against improper thread handling
// This guard is passed to the GrDrawingManager and, from there to all the
diff --git a/chromium/third_party/skia/include/private/GrRecordingContext.h b/chromium/third_party/skia/include/private/GrRecordingContext.h
index 921731c5dd0..945ed3e9e61 100644
--- a/chromium/third_party/skia/include/private/GrRecordingContext.h
+++ b/chromium/third_party/skia/include/private/GrRecordingContext.h
@@ -75,8 +75,8 @@ protected:
std::unique_ptr<SkArenaAlloc> fRecordTimeAllocator;
};
- GrRecordingContext(GrBackendApi, const GrContextOptions&, uint32_t contextID);
- bool init(sk_sp<const GrCaps>) override;
+ GrRecordingContext(sk_sp<GrContextThreadSafeProxy>);
+ bool init() override;
void setupDrawingManager(bool sortOpsTasks, bool reduceOpsTaskSplitting);
void abandonContext() override;
diff --git a/chromium/third_party/skia/include/private/GrResourceKey.h b/chromium/third_party/skia/include/private/GrResourceKey.h
index 977eecf25ed..ee39e903048 100644
--- a/chromium/third_party/skia/include/private/GrResourceKey.h
+++ b/chromium/third_party/skia/include/private/GrResourceKey.h
@@ -62,7 +62,7 @@ protected:
} else {
size_t bytes = that.size();
SkASSERT(SkIsAlign4(bytes));
- fKey.reset(SkToInt(bytes / sizeof(uint32_t)));
+ fKey.reset(bytes / sizeof(uint32_t));
memcpy(fKey.get(), that.fKey.get(), bytes);
this->validate();
}
@@ -103,10 +103,10 @@ protected:
class Builder {
public:
Builder(GrResourceKey* key, uint32_t domain, int data32Count) : fKey(key) {
- SkASSERT(data32Count >= 0);
+ size_t count = SkToSizeT(data32Count);
SkASSERT(domain != kInvalidDomain);
- key->fKey.reset(kMetaDataCnt + data32Count);
- int size = (data32Count + kMetaDataCnt) * sizeof(uint32_t);
+ key->fKey.reset(kMetaDataCnt + count);
+ size_t size = (count + kMetaDataCnt) * sizeof(uint32_t);
SkASSERT(SkToU16(size) == size);
SkASSERT(SkToU16(domain) == domain);
key->fKey[kDomainAndSize_MetaDataIdx] = domain | (size << 16);
@@ -128,7 +128,7 @@ protected:
SkASSERT(fKey);
SkDEBUGCODE(size_t dataCount = fKey->internalSize() / sizeof(uint32_t) - kMetaDataCnt;)
SkASSERT(SkToU32(dataIdx) < dataCount);
- return fKey->fKey[kMetaDataCnt + dataIdx];
+ return fKey->fKey[(int)kMetaDataCnt + dataIdx];
}
private:
diff --git a/chromium/third_party/skia/include/private/GrSharedEnums.h b/chromium/third_party/skia/include/private/GrSharedEnums.h
index d745b70bd43..cdb0f80b14d 100644
--- a/chromium/third_party/skia/include/private/GrSharedEnums.h
+++ b/chromium/third_party/skia/include/private/GrSharedEnums.h
@@ -15,17 +15,15 @@
/**
* 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/include/private/GrSingleOwner.h b/chromium/third_party/skia/include/private/GrSingleOwner.h
index 6369ae82c88..0bbaeb7849f 100644
--- a/chromium/third_party/skia/include/private/GrSingleOwner.h
+++ b/chromium/third_party/skia/include/private/GrSingleOwner.h
@@ -14,30 +14,39 @@
#include "include/private/SkMutex.h"
#include "include/private/SkThreadID.h"
+#define GR_ASSERT_SINGLE_OWNER(obj) \
+ GrSingleOwner::AutoEnforce debug_SingleOwner(obj, __FILE__, __LINE__);
+
// This is a debug tool to verify an object is only being used from one thread at a time.
class GrSingleOwner {
public:
GrSingleOwner() : fOwner(kIllegalThreadID), fReentranceCount(0) {}
struct AutoEnforce {
- AutoEnforce(GrSingleOwner* so) : fSO(so) { fSO->enter(); }
- ~AutoEnforce() { fSO->exit(); }
+ AutoEnforce(GrSingleOwner* so, const char* file, int line)
+ : fFile(file), fLine(line), fSO(so) {
+ fSO->enter(file, line);
+ }
+ ~AutoEnforce() { fSO->exit(fFile, fLine); }
+ const char* fFile;
+ int fLine;
GrSingleOwner* fSO;
};
private:
- void enter() {
+ void enter(const char* file, int line) {
SkAutoMutexExclusive lock(fMutex);
SkThreadID self = SkGetThreadID();
- SkASSERT(fOwner == self || fOwner == kIllegalThreadID);
+ SkASSERTF(fOwner == self || fOwner == kIllegalThreadID, "%s:%d Single owner failure.",
+ file, line);
fReentranceCount++;
fOwner = self;
}
- void exit() {
+ void exit(const char* file, int line) {
SkAutoMutexExclusive lock(fMutex);
- SkASSERT(fOwner == SkGetThreadID());
+ SkASSERTF(fOwner == SkGetThreadID(), "%s:%d Single owner failure.", file, line);
fReentranceCount--;
if (fReentranceCount == 0) {
fOwner = kIllegalThreadID;
@@ -49,6 +58,7 @@ private:
int fReentranceCount SK_GUARDED_BY(fMutex);
};
#else
+#define GR_ASSERT_SINGLE_OWNER(obj)
class GrSingleOwner {}; // Provide a dummy implementation so we can pass pointers to constructors
#endif
diff --git a/chromium/third_party/skia/include/private/GrTypesPriv.h b/chromium/third_party/skia/include/private/GrTypesPriv.h
index 03ac124c0d4..21e13b80ccd 100644
--- a/chromium/third_party/skia/include/private/GrTypesPriv.h
+++ b/chromium/third_party/skia/include/private/GrTypesPriv.h
@@ -99,6 +99,13 @@ enum class GrTexturable : bool {
kYes = true
};
+// A DDL recorder has its own proxy provider and proxy cache. This enum indicates if
+// a given proxy provider is one of these special ones.
+enum class GrDDLProvider : bool {
+ kNo = false,
+ kYes = true
+};
+
/**
* Formats for masks, used by the font cache. Important that these are 0-based.
*/
@@ -114,18 +121,16 @@ static const int kMaskFormatCount = kLast_GrMaskFormat + 1;
/**
* Return the number of bytes-per-pixel for the specified mask format.
*/
-static inline int GrMaskFormatBytesPerPixel(GrMaskFormat format) {
+inline constexpr int GrMaskFormatBytesPerPixel(GrMaskFormat format) {
SkASSERT(format < kMaskFormatCount);
// kA8 (0) -> 1
// kA565 (1) -> 2
// kARGB (2) -> 4
- static const int sBytesPerPixel[] = {1, 2, 4};
- static_assert(SK_ARRAY_COUNT(sBytesPerPixel) == kMaskFormatCount, "array_size_mismatch");
static_assert(kA8_GrMaskFormat == 0, "enum_order_dependency");
static_assert(kA565_GrMaskFormat == 1, "enum_order_dependency");
static_assert(kARGB_GrMaskFormat == 2, "enum_order_dependency");
- return sBytesPerPixel[(int)format];
+ return SkTo<int>(1u << format);
}
/** Ownership rules for external GPU resources imported into Skia. */
@@ -650,10 +655,8 @@ static inline GrClipEdgeType GrInvertProcessorEdgeType(const GrClipEdgeType edge
return GrClipEdgeType::kFillBW;
case GrClipEdgeType::kInverseFillAA:
return GrClipEdgeType::kFillAA;
- case GrClipEdgeType::kHairlineAA:
- SK_ABORT("Hairline fill isn't invertible.");
}
- return GrClipEdgeType::kFillAA; // suppress warning.
+ SkUNREACHABLE;
}
/**
diff --git a/chromium/third_party/skia/include/private/GrVkTypesPriv.h b/chromium/third_party/skia/include/private/GrVkTypesPriv.h
index 49b392c52b5..b46cf8bf914 100644
--- a/chromium/third_party/skia/include/private/GrVkTypesPriv.h
+++ b/chromium/third_party/skia/include/private/GrVkTypesPriv.h
@@ -11,7 +11,7 @@
#include "include/core/SkRefCnt.h"
#include "include/gpu/vk/GrVkTypes.h"
-class GrVkImageLayout;
+class GrBackendSurfaceMutableStateImpl;
// This struct is to used to store the the actual information about the vulkan backend image on the
// GrBackendTexture and GrBackendRenderTarget. When a client calls getVkImageInfo on a
@@ -20,8 +20,7 @@ class GrVkImageLayout;
// current VkImageLayout which can be shared with an internal GrVkImage so that layout updates can
// be seen by all users of the image.
struct GrVkBackendSurfaceInfo {
- GrVkBackendSurfaceInfo(GrVkImageInfo info, GrVkImageLayout* layout)
- : fImageInfo(info), fLayout(layout) {}
+ GrVkBackendSurfaceInfo(GrVkImageInfo info) : fImageInfo(info) {}
void cleanup();
@@ -31,11 +30,7 @@ struct GrVkBackendSurfaceInfo {
// attempt to unref the old fLayout on this object.
void assign(const GrVkBackendSurfaceInfo&, bool isValid);
- void setImageLayout(VkImageLayout layout);
-
- sk_sp<GrVkImageLayout> getGrVkImageLayout() const;
-
- GrVkImageInfo snapImageInfo() const;
+ GrVkImageInfo snapImageInfo(const GrBackendSurfaceMutableStateImpl*) const;
bool isProtected() const { return fImageInfo.fProtected == GrProtected::kYes; }
#if GR_TEST_UTILS
@@ -44,7 +39,43 @@ struct GrVkBackendSurfaceInfo {
private:
GrVkImageInfo fImageInfo;
- GrVkImageLayout* fLayout;
+};
+
+class GrVkSharedImageInfo {
+public:
+ GrVkSharedImageInfo(VkImageLayout layout, uint32_t queueFamilyIndex)
+ : fLayout(layout)
+ , fQueueFamilyIndex(queueFamilyIndex) {}
+
+ GrVkSharedImageInfo& operator=(const GrVkSharedImageInfo& that) {
+ fLayout = that.getImageLayout();
+ fQueueFamilyIndex = that.getQueueFamilyIndex();
+ return *this;
+ }
+
+ void setImageLayout(VkImageLayout layout) {
+ // Defaulting to use std::memory_order_seq_cst
+ fLayout.store(layout);
+ }
+
+ VkImageLayout getImageLayout() const {
+ // Defaulting to use std::memory_order_seq_cst
+ return fLayout.load();
+ }
+
+ void setQueueFamilyIndex(uint32_t queueFamilyIndex) {
+ // Defaulting to use std::memory_order_seq_cst
+ fQueueFamilyIndex.store(queueFamilyIndex);
+ }
+
+ uint32_t getQueueFamilyIndex() const {
+ // Defaulting to use std::memory_order_seq_cst
+ return fQueueFamilyIndex.load();
+ }
+
+private:
+ std::atomic<VkImageLayout> fLayout;
+ std::atomic<uint32_t> fQueueFamilyIndex;
};
#endif
diff --git a/chromium/third_party/skia/include/private/SkChecksum.h b/chromium/third_party/skia/include/private/SkChecksum.h
index 8e2a4ba5248..6339239d65c 100644
--- a/chromium/third_party/skia/include/private/SkChecksum.h
+++ b/chromium/third_party/skia/include/private/SkChecksum.h
@@ -11,14 +11,9 @@
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/private/SkNoncopyable.h"
+#include "include/private/SkOpts_spi.h"
#include "include/private/SkTLogic.h"
-// #include "src/core/SkOpts.h"
-// It's sort of pesky to be able to include SkOpts.h here, so we'll just re-declare what we need.
-namespace SkOpts {
- extern uint32_t (*hash_fn)(const void*, size_t, uint32_t);
-}
-
class SkChecksum : SkNoncopyable {
public:
/**
diff --git a/chromium/third_party/skia/include/private/SkColorData.h b/chromium/third_party/skia/include/private/SkColorData.h
index 2090ab4b7ee..aba610eacf6 100644
--- a/chromium/third_party/skia/include/private/SkColorData.h
+++ b/chromium/third_party/skia/include/private/SkColorData.h
@@ -435,6 +435,7 @@ static inline uint32_t Sk4f_toL32(const Sk4f& px) {
using SkPMColor4f = SkRGBA4f<kPremul_SkAlphaType>;
constexpr SkPMColor4f SK_PMColor4fTRANSPARENT = { 0, 0, 0, 0 };
+constexpr SkPMColor4f SK_PMColor4fBLACK = { 0, 0, 0, 1 };
constexpr SkPMColor4f SK_PMColor4fWHITE = { 1, 1, 1, 1 };
constexpr SkPMColor4f SK_PMColor4fILLEGAL = { SK_FloatNegativeInfinity,
SK_FloatNegativeInfinity,
diff --git a/chromium/third_party/skia/include/private/SkFixed.h b/chromium/third_party/skia/include/private/SkFixed.h
index af858efc89c..6e8990f574b 100644
--- a/chromium/third_party/skia/include/private/SkFixed.h
+++ b/chromium/third_party/skia/include/private/SkFixed.h
@@ -62,7 +62,7 @@ typedef int32_t SkFixed;
SkASSERT(n >= -32768 && n <= 32767);
// Left shifting a negative value has undefined behavior in C, so we cast to unsigned before
// shifting.
- return (unsigned)n << 16;
+ return (SkFixed)( (unsigned)n << 16 );
}
#else
// Left shifting a negative value has undefined behavior in C, so we cast to unsigned before
@@ -76,13 +76,13 @@ typedef int32_t SkFixed;
#define SkFixedFloorToInt(x) ((x) >> 16)
static inline SkFixed SkFixedRoundToFixed(SkFixed x) {
- return (x + SK_FixedHalf) & 0xFFFF0000;
+ return (SkFixed)( (uint32_t)(x + SK_FixedHalf) & 0xFFFF0000 );
}
static inline SkFixed SkFixedCeilToFixed(SkFixed x) {
- return (x + SK_Fixed1 - 1) & 0xFFFF0000;
+ return (SkFixed)( (uint32_t)(x + SK_Fixed1 - 1) & 0xFFFF0000 );
}
static inline SkFixed SkFixedFloorToFixed(SkFixed x) {
- return x & 0xFFFF0000;
+ return (SkFixed)( (uint32_t)x & 0xFFFF0000 );
}
#define SkFixedAbs(x) SkAbs32(x)
diff --git a/chromium/third_party/skia/include/private/SkImageInfoPriv.h b/chromium/third_party/skia/include/private/SkImageInfoPriv.h
index 582867162f6..6a3c0d17362 100644
--- a/chromium/third_party/skia/include/private/SkImageInfoPriv.h
+++ b/chromium/third_party/skia/include/private/SkImageInfoPriv.h
@@ -74,7 +74,7 @@ static int SkColorTypeShiftPerPixel(SkColorType ct) {
}
static inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) {
- return width * SkColorTypeBytesPerPixel(ct);
+ return (size_t)(width * SkColorTypeBytesPerPixel(ct));
}
static inline bool SkColorTypeIsValid(unsigned value) {
@@ -85,7 +85,7 @@ static inline size_t SkColorTypeComputeOffset(SkColorType ct, int x, int y, size
if (kUnknown_SkColorType == ct) {
return 0;
}
- return y * rowBytes + (x << SkColorTypeShiftPerPixel(ct));
+ return (size_t)y * rowBytes + ((size_t)x << SkColorTypeShiftPerPixel(ct));
}
static inline bool SkColorTypeIsNormalized(SkColorType ct) {
diff --git a/chromium/third_party/skia/include/private/SkOpts_spi.h b/chromium/third_party/skia/include/private/SkOpts_spi.h
new file mode 100644
index 00000000000..528e322113b
--- /dev/null
+++ b/chromium/third_party/skia/include/private/SkOpts_spi.h
@@ -0,0 +1,21 @@
+/*
+ * 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 SkOpts_spi_DEFINED
+#define SkOpts_spi_DEFINED
+
+#include "include/core/SkTypes.h"
+
+// These are exposed as SK_SPI (e.g. SkParagraph), the rest of SkOpts is
+// declared in src/core
+
+namespace SkOpts {
+ // The fastest high quality 32-bit hash we can provide on this platform.
+ extern uint32_t SK_SPI (*hash_fn)(const void* data, size_t bytes, uint32_t seed);
+}
+
+#endif
diff --git a/chromium/third_party/skia/include/private/SkPathRef.h b/chromium/third_party/skia/include/private/SkPathRef.h
index 7afe4f9a52e..f9533d72615 100644
--- a/chromium/third_party/skia/include/private/SkPathRef.h
+++ b/chromium/third_party/skia/include/private/SkPathRef.h
@@ -42,6 +42,24 @@ class SkWBuffer;
class SK_API SkPathRef final : public SkNVRefCnt<SkPathRef> {
public:
+ SkPathRef(SkTDArray<SkPoint> points, SkTDArray<uint8_t> verbs, SkTDArray<SkScalar> weights,
+ unsigned segmentMask)
+ : fPoints(std::move(points))
+ , fVerbs(std::move(verbs))
+ , fConicWeights(std::move(weights))
+ {
+ fBoundsIsDirty = true; // this also invalidates fIsFinite
+ fGenerationID = kEmptyGenID;
+ fSegmentMask = segmentMask;
+ fIsOval = false;
+ fIsRRect = false;
+ // The next two values don't matter unless fIsOval or fIsRRect are true.
+ fRRectOrOvalIsCCW = false;
+ fRRectOrOvalStartIdx = 0xAC;
+ SkDEBUGCODE(fEditorsAttached.store(0);)
+ SkDEBUGCODE(this->validate();)
+ }
+
class Editor {
public:
Editor(sk_sp<SkPathRef>* pathRef,
diff --git a/chromium/third_party/skia/include/private/SkSemaphore.h b/chromium/third_party/skia/include/private/SkSemaphore.h
index 265847b5e83..d7318be5779 100644
--- a/chromium/third_party/skia/include/private/SkSemaphore.h
+++ b/chromium/third_party/skia/include/private/SkSemaphore.h
@@ -19,7 +19,7 @@ public:
constexpr SkSemaphore(int count = 0) : fCount(count), fOSSemaphore(nullptr) {}
// Cleanup the underlying OS semaphore.
- ~SkSemaphore();
+ SK_SPI ~SkSemaphore();
// Increment the counter n times.
// Generally it's better to call signal(n) instead of signal() n times.
@@ -30,7 +30,7 @@ public:
void wait();
// If the counter is positive, decrement it by 1 and return true, otherwise return false.
- bool try_wait();
+ SK_SPI bool try_wait();
private:
// This implementation follows the general strategy of
@@ -44,8 +44,8 @@ private:
// moving the count from >=0 to <0 or vice-versa, i.e. sleeping or waking threads.
struct OSSemaphore;
- void osSignal(int n);
- void osWait();
+ SK_SPI void osSignal(int n);
+ SK_SPI void osWait();
std::atomic<int> fCount;
SkOnce fOSSemaphoreOnce;
diff --git a/chromium/third_party/skia/include/private/SkTArray.h b/chromium/third_party/skia/include/private/SkTArray.h
index 78ce51b270a..cc59aa6ba8b 100644
--- a/chromium/third_party/skia/include/private/SkTArray.h
+++ b/chromium/third_party/skia/include/private/SkTArray.h
@@ -20,10 +20,15 @@
#include <new>
#include <utility>
-/** When MEM_MOVE is true T will be bit copied when moved.
- When MEM_MOVE is false, T will be copy constructed / destructed.
- In all cases T will be default-initialized on allocation,
- and its destructor will be called from this object's destructor.
+/** SkTArray<T> implements a typical, mostly std::vector-like array.
+ Each T will be default-initialized on allocation, and ~T will be called on destruction.
+
+ MEM_MOVE controls the behavior when a T needs to be moved (e.g. when the array is resized)
+ - true: T will be bit-copied via memcpy.
+ - false: T will be moved via move-constructors.
+
+ Modern implementations of std::vector<T> will generally provide similar performance
+ characteristics when used with appropriate care. Consider using std::vector<T> in new code.
*/
template <typename T, bool MEM_MOVE = false> class SkTArray {
public:
@@ -47,10 +52,23 @@ public:
}
SkTArray(SkTArray&& that) {
- // TODO: If 'that' owns its memory why don't we just steal the pointer?
- this->init(that.fCount);
- that.move(fItemArray);
- that.fCount = 0;
+ if (that.fOwnMemory) {
+ fItemArray = that.fItemArray;
+ fCount = that.fCount;
+ fAllocCount = that.fAllocCount;
+ fOwnMemory = true;
+ fReserved = that.fReserved;
+
+ that.fItemArray = nullptr;
+ that.fCount = 0;
+ that.fAllocCount = 0;
+ that.fOwnMemory = true;
+ that.fReserved = false;
+ } else {
+ this->init(that.fCount);
+ that.move(fItemArray);
+ that.fCount = 0;
+ }
}
/**
@@ -351,6 +369,9 @@ public:
return fItemArray[i];
}
+ T& at(int i) { return (*this)[i]; }
+ const T& at(int i) const { return (*this)[i]; }
+
/**
* equivalent to operator[](0)
*/
@@ -455,7 +476,7 @@ private:
fReserved = false;
} else {
fAllocCount = std::max(count, std::max(kMinHeapAllocCount, reserveCount));
- fItemArray = (T*)sk_malloc_throw(fAllocCount, sizeof(T));
+ fItemArray = (T*)sk_malloc_throw((size_t)fAllocCount, sizeof(T));
fOwnMemory = true;
fReserved = reserveCount > 0;
}
@@ -505,7 +526,7 @@ private:
}
template <bool E = MEM_MOVE> std::enable_if_t<!E, void> move(void* dst) {
for (int i = 0; i < fCount; ++i) {
- new (static_cast<char*>(dst) + sizeof(T) * i) T(std::move(fItemArray[i]));
+ new (static_cast<char*>(dst) + sizeof(T) * (size_t)i) T(std::move(fItemArray[i]));
fItemArray[i].~T();
}
}
@@ -551,7 +572,7 @@ private:
fAllocCount = Sk64_pin_to_s32(newAllocCount);
SkASSERT(fAllocCount >= newCount);
- T* newItemArray = (T*)sk_malloc_throw(fAllocCount, sizeof(T));
+ T* newItemArray = (T*)sk_malloc_throw((size_t)fAllocCount, sizeof(T));
this->move(newItemArray);
if (fOwnMemory) {
sk_free(fItemArray);
diff --git a/chromium/third_party/skia/include/private/SkTDArray.h b/chromium/third_party/skia/include/private/SkTDArray.h
index 33d4d7cc2ba..9d475f6f8ea 100644
--- a/chromium/third_party/skia/include/private/SkTDArray.h
+++ b/chromium/third_party/skia/include/private/SkTDArray.h
@@ -17,6 +17,13 @@
#include <initializer_list>
#include <utility>
+/** SkTDArray<T> implements a std::vector-like array for raw data-only objects that do not require
+ construction or destruction. The constructor and destructor for T will not be called; T objects
+ will always be moved via raw memcpy. Newly created T objects will contain uninitialized memory.
+
+ In most cases, std::vector<T> can provide a similar level of performance for POD objects when
+ used with appropriate care. In new code, consider std::vector<T> instead.
+*/
template <typename T> class SkTDArray {
public:
SkTDArray() : fArray(nullptr), fReserve(0), fCount(0) {}
@@ -365,7 +372,7 @@ private:
SkASSERT_RELEASE( SkTFitsIn<int>(reserve) );
fReserve = SkTo<int>(reserve);
- fArray = (T*)sk_realloc_throw(fArray, fReserve * sizeof(T));
+ fArray = (T*)sk_realloc_throw(fArray, (size_t)fReserve * sizeof(T));
}
};
diff --git a/chromium/third_party/skia/include/private/SkTemplates.h b/chromium/third_party/skia/include/private/SkTemplates.h
index 477bbcb397f..1edf8120e4b 100644
--- a/chromium/third_party/skia/include/private/SkTemplates.h
+++ b/chromium/third_party/skia/include/private/SkTemplates.h
@@ -114,6 +114,10 @@ public:
return fArray[index];
}
+ // aliases matching other types like std::vector
+ const T* data() const { return fArray; }
+ T* data() { return fArray; }
+
private:
std::unique_ptr<T[]> fArray;
SkDEBUGCODE(int fCount = 0;)
@@ -203,6 +207,11 @@ public:
return fArray[index];
}
+ // aliases matching other types like std::vector
+ const T* data() const { return fArray; }
+ T* data() { return fArray; }
+ size_t size() const { return fCount; }
+
private:
#if defined(SK_BUILD_FOR_GOOGLE3)
// Stack frame size is limited for SK_BUILD_FOR_GOOGLE3. 4k is less than the actual max, but some functions
diff --git a/chromium/third_party/skia/include/third_party/skcms/skcms.h b/chromium/third_party/skia/include/third_party/skcms/skcms.h
index 486844abae8..eec1442f7c1 100644
--- a/chromium/third_party/skia/include/third_party/skcms/skcms.h
+++ b/chromium/third_party/skia/include/third_party/skcms/skcms.h
@@ -307,6 +307,9 @@ SKCMS_API bool skcms_PrimariesToXYZD50(float rx, float ry,
float wx, float wy,
skcms_Matrix3x3* toXYZD50);
+// Call before your first call to skcms_Transform() to skip runtime CPU detection.
+SKCMS_API void skcms_DisableRuntimeCPUDetection(void);
+
// Utilities for programmatically constructing profiles
static inline void skcms_Init(skcms_ICCProfile* p) {
memset(p, 0, sizeof(*p));
diff --git a/chromium/third_party/skia/include/utils/SkCamera.h b/chromium/third_party/skia/include/utils/SkCamera.h
index 1d018fb29a2..51a7d4d6b07 100644
--- a/chromium/third_party/skia/include/utils/SkCamera.h
+++ b/chromium/third_party/skia/include/utils/SkCamera.h
@@ -10,6 +10,7 @@
#ifndef SkCamera_DEFINED
#define SkCamera_DEFINED
+#include "include/core/SkM44.h"
#include "include/core/SkMatrix.h"
#include "include/private/SkNoncopyable.h"
@@ -21,76 +22,17 @@
class SkCanvas;
// DEPRECATED
-struct SkUnit3D {
- SkScalar fX, fY, fZ;
-
- void set(SkScalar x, SkScalar y, SkScalar z) {
- fX = x; fY = y; fZ = z;
- }
- static SkScalar Dot(const SkUnit3D&, const SkUnit3D&);
- static void Cross(const SkUnit3D&, const SkUnit3D&, SkUnit3D* cross);
-};
-
-// DEPRECATED
-struct SkPoint3D {
- SkScalar fX, fY, fZ;
-
- void set(SkScalar x, SkScalar y, SkScalar z) {
- fX = x; fY = y; fZ = z;
- }
- SkScalar normalize(SkUnit3D*) const;
-};
-typedef SkPoint3D SkVector3D;
-
-// DEPRECATED
-struct SkMatrix3D {
- SkScalar fMat[3][4];
-
- void reset();
-
- void setRow(int row, SkScalar a, SkScalar b, SkScalar c, SkScalar d = 0) {
- SkASSERT((unsigned)row < 3);
- fMat[row][0] = a;
- fMat[row][1] = b;
- fMat[row][2] = c;
- fMat[row][3] = d;
- }
-
- void setRotateX(SkScalar deg);
- void setRotateY(SkScalar deg);
- void setRotateZ(SkScalar deg);
- void setTranslate(SkScalar x, SkScalar y, SkScalar z);
-
- void preRotateX(SkScalar deg);
- void preRotateY(SkScalar deg);
- void preRotateZ(SkScalar deg);
- void preTranslate(SkScalar x, SkScalar y, SkScalar z);
-
- void setConcat(const SkMatrix3D& a, const SkMatrix3D& b);
- void mapPoint(const SkPoint3D& src, SkPoint3D* dst) const;
- void mapVector(const SkVector3D& src, SkVector3D* dst) const;
-
- void mapPoint(SkPoint3D* v) const {
- this->mapPoint(*v, v);
- }
-
- void mapVector(SkVector3D* v) const {
- this->mapVector(*v, v);
- }
-};
-
-// DEPRECATED
class SkPatch3D {
public:
SkPatch3D();
void reset();
- void transform(const SkMatrix3D&, SkPatch3D* dst = nullptr) const;
+ void transform(const SkM44&, SkPatch3D* dst = nullptr) const;
// dot a unit vector with the patch's normal
SkScalar dotWith(SkScalar dx, SkScalar dy, SkScalar dz) const;
- SkScalar dotWith(const SkVector3D& v) const {
- return this->dotWith(v.fX, v.fY, v.fZ);
+ SkScalar dotWith(const SkV3& v) const {
+ return this->dotWith(v.x, v.y, v.z);
}
// deprecated, but still here for animator (for now)
@@ -99,8 +41,8 @@ public:
private:
public: // make public for SkDraw3D for now
- SkVector3D fU, fV;
- SkPoint3D fOrigin;
+ SkV3 fU, fV;
+ SkV3 fOrigin;
friend class SkCamera3D;
};
@@ -114,10 +56,10 @@ public:
void update();
void patchToMatrix(const SkPatch3D&, SkMatrix* matrix) const;
- SkPoint3D fLocation; // origin of the camera's space
- SkPoint3D fAxis; // view direction
- SkPoint3D fZenith; // up direction
- SkPoint3D fObserver; // eye position (may not be the same as the origin)
+ SkV3 fLocation; // origin of the camera's space
+ SkV3 fAxis; // view direction
+ SkV3 fZenith; // up direction
+ SkV3 fObserver; // eye position (may not be the same as the origin)
private:
mutable SkMatrix fOrientation;
@@ -154,8 +96,8 @@ public:
private:
struct Rec {
- Rec* fNext;
- SkMatrix3D fMatrix;
+ Rec* fNext;
+ SkM44 fMatrix;
};
Rec* fRec;
Rec fInitialRec;
diff --git a/chromium/third_party/skia/include/utils/SkCustomTypeface.h b/chromium/third_party/skia/include/utils/SkCustomTypeface.h
index 36640999898..61f32afed5e 100644
--- a/chromium/third_party/skia/include/utils/SkCustomTypeface.h
+++ b/chromium/third_party/skia/include/utils/SkCustomTypeface.h
@@ -8,6 +8,7 @@
#ifndef SkCustomTypeface_DEFINED
#define SkCustomTypeface_DEFINED
+#include "include/core/SkFontMetrics.h"
#include "include/core/SkImage.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
@@ -20,19 +21,21 @@ class SkStream;
class SkCustomTypefaceBuilder {
public:
- SkCustomTypefaceBuilder(int numGlyphs);
+ SkCustomTypefaceBuilder();
void setGlyph(SkGlyphID, float advance, const SkPath&);
void setGlyph(SkGlyphID, float advance, const SkPath&, const SkPaint&);
void setGlyph(SkGlyphID, float advance, sk_sp<SkImage>, float scale);
void setGlyph(SkGlyphID, float advance, sk_sp<SkPicture>);
+ void setMetrics(const SkFontMetrics& fm, float scale = 1);
+
sk_sp<SkTypeface> detach();
private:
- int fGlyphCount;
std::vector<SkPath> fPaths;
std::vector<float> fAdvances;
+ SkFontMetrics fMetrics;
static sk_sp<SkTypeface> Deserialize(SkStream*);
diff --git a/chromium/third_party/skia/include/utils/SkRandom.h b/chromium/third_party/skia/include/utils/SkRandom.h
index 0678010362a..ba40732b9cf 100644
--- a/chromium/third_party/skia/include/utils/SkRandom.h
+++ b/chromium/third_party/skia/include/utils/SkRandom.h
@@ -49,7 +49,7 @@ public:
* Returns value [0...1) as an IEEE float
*/
float nextF() {
- unsigned int floatint = 0x3f800000 | (this->nextU() >> 9);
+ int floatint = 0x3f800000 | (int)(this->nextU() >> 9);
float f = SkBits2Float(floatint) - 1.0f;
return f;
}
diff --git a/chromium/third_party/skia/modules/canvaskit/BUILD.gn b/chromium/third_party/skia/modules/canvaskit/BUILD.gn
index f227840a4f6..861db54b1a8 100644
--- a/chromium/third_party/skia/modules/canvaskit/BUILD.gn
+++ b/chromium/third_party/skia/modules/canvaskit/BUILD.gn
@@ -6,6 +6,10 @@
component("viewer_wasm") {
testonly = true
include_dirs = [ "../.." ]
- sources = [ "../../tools/viewer/SampleSlide.cpp" ]
+ sources = [
+ "../../tools/viewer/SKPSlide.cpp",
+ "../../tools/viewer/SampleSlide.cpp",
+ "../../tools/viewer/SvgSlide.cpp",
+ ]
deps = [ "../..:samples" ]
}
diff --git a/chromium/third_party/skia/modules/canvaskit/CHANGELOG.md b/chromium/third_party/skia/modules/canvaskit/CHANGELOG.md
index 51f388f1112..7facb95265b 100644
--- a/chromium/third_party/skia/modules/canvaskit/CHANGELOG.md
+++ b/chromium/third_party/skia/modules/canvaskit/CHANGELOG.md
@@ -7,9 +7,103 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
+ - Added `CanvasKit.MakeImageFromCanvasImageSource` which takes either an HTMLImageElement,
+ SVGImageElement, HTMLVideoElement, HTMLCanvasElement, ImageBitmap, or OffscreenCanvas and returns
+ an SkImage. This function is an alternative to `CanvasKit.MakeImageFromEncoded` for creating
+ SkImages when loading and decoding images. In the future, codesize of CanvasKit may be able to be
+ reduced by removing image codecs in wasm, if browser APIs for decoding images are used along with
+ `CanvasKit.MakeImageFromCanvasImageSource` instead of `CanvasKit.MakeImageFromEncoded`.
+ - Three usage examples of `CanvasKit.MakeImageFromCanvasImageSource` in core.spec.ts.
+ - Added support for asynchronous callbacks in perfs and tests.
+ - `CanvasKit.SkPath.MakeFromVerbsPointsWeights` and `CanvasKit.SkPath.addVerbsPointsWeights` for
+ supplying many path operations (e.g. moveTo, cubicTo) at once.
+ - The object returned by `CanvasKit.malloc` now has a `subarray` method which works exactly like
+ the normal TypedArray version. The TypedArray which it returns is also backed by WASM memory
+ and when passed into CanvasKit will be used w/o copying the data (just like
+ `Malloc.toTypedArray`).
+
+### Changed
+ - In all places where color arrays are accepted (gradient makers, drawAtlas, and MakeSkVertices),
+ You can now provide either flat Float32Arrays of float colors, Uint32Arrays of int colors, or
+ 2d Arrays of Float32Array(4) colors. The one thing you should not pass is an Array of numbers,
+ since canvaskit wouldn't be able to tell whether they're ints or floats without checking them all.
+ The fastest choice for gradients is the flat Float32Array, the fastest choice for drawAtlas and
+ MakeSkVertices is the flat Uint32Array.
+ - Color arrays may also be objects created with CanvasKit.Malloc
+
+### Fixed
+ - `TextStyle.color` can correctly be a Malloc'd Float32Array.
+
+### Deprecated
+ - `CanvasKit.MakePathFromCmds` has been renamed to `CanvasKit.SkPath.MakeFromCmds`. The alias
+ will be removed in an upcoming release.
+
+## [0.16.2] - 2020-06-05
+
+### Fixed
+ - A bug where loading fonts (and other memory intensive calls) would cause CanvasKit
+ to infrequently crash with
+ `TypeError: Cannot perform %TypedArray%.prototype.set on a neutered ArrayBuffer`.
+ - Incorrectly freeing Malloced colors passed into computeTonalColors.
+
+## [0.16.1] - 2020-06-04
+
+### Fixed
+ - Colors are unsigned to be compatible with Flutter Web and previous behavior, not
+ signed ints.
+
+## [0.16.0] - 2020-06-03
+
+### Added
+ - Support for wide-gamut color spaces DisplayP3 and AdobeRGB. However, correct representation on a
+ WCG monitor requires that the browser is rendering everything to the DisplayP3 or AdobeRGB
+ profile, since there is not yet any way to indicate to the browser that a canvas element has a
+ non-sRGB color space. See color support example in extra.html. Only supported for WebGL2 backed
+ surfaces.
+ - Added `SkSurface.reportBackendType` which returns either 'CPU' or 'GPU'.
+ - Added `SkSurface.imageInfo` which returns an ImageInfo object describing the size and color
+ properties of the surface. colorSpace is added to ImageInfo everywhere it is used.
+ - `CanvasKit.Free` to explicitly clean up memory after `CanvasKit.Malloc`. All memory allocated
+ with `CanvasKit.Malloc` must be released with `CanvasKit.Free` or it will be leaked. This can
+ improve performance by reducing the copying of data between the JS and WASM side.
+ - `CanvasKit.ColorAsInt`, `SkPaint.setColorComponents`, `SkPaint.setColorInt`,
+ `SkCanvas.drawColorComponents`, `SkCanvas.drawColorInt` for when clients want
+ to avoid the overhead of allocating an array for color components and only need 8888 color.
+
+### Changed
+ - We now compile/ship with Emscripten v1.39.16.
+ - `CanvasKit.MakeCanvasSurface` accepts a new enum specifying one of the three color space and
+ pixel format combinations supported by CanvasKit.
+ - all `_Make*Shader` functions now accept a color space argument at the end. leaving it off or
+ passing null makes it behave as it did before, defaulting to sRGB
+ - `SkPaint.setColor` accepts a new color space argument, defaulting to sRGB.
+ - Fewer allocations required to send Color and Matrices between JS and WASM layer.
+ - All APIs that take a 1 dimensional array should also accept the object returned by Malloc. It is
+ recommended to pass the Malloc object, as the TypedArray could be invalidated any time
+ CanvasKit needs to allocate memory and needs to resize to accommodate.
+
+### Breaking
+ - `CanvasKitInit(...)` now directly returns a Promise. As such, `CanvasKitInit(...).ready()`
+ has been removed.
+ - `CanvasKit.MakeCanvasSurface` no longer accepts width/height arguments to override those on
+ the canvas element. Use the canvas element's width/height attributes to dictate the size of
+ the drawing area, and use CSS width/height to set the size it will appear on the page
+ (it is rescaled after drawing when css sizing applies).
+ - Memory returned by `CanvasKit.Malloc` will no longer be automatically cleaned up. Clients
+ must use `CanvasKit.Free` to release the memory.
+ - `CanvasKit.Malloc` no longer directly returns a TypedArray, but an object that can produce
+ them with toTypedArray(). This is to avoid "detached ArrayBuffer" errors:
+ <https://github.com/emscripten-core/emscripten/issues/6747>
+
+### Fixed
+ - WebGL context is no longer created with "antialias" flag. Using "antialias" caused poor AA
+ quality in Ganesh when trying to do coverage-based AA with MSAA unknowingly enabled. It also
+ reduced performance.
+
+## [0.15.0] - 2020-05-14
+
+### Added
- Support for DOMMatrix on all APIs that take SkMatrix (i.e. arrays or Float32Arrays of length 6/9/16).
- - `CanvasKit.MakeWebGLCanvasSurface` takes an option for WebGL version to make it easier to specify
- v1 or v2.
- setEdging and setEmbeddedBitmaps to SkFont. You can disable the ability to draw aliased fonts (and save some code
size) with the compile.sh argument `no_alias_font`.
@@ -20,7 +114,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- CanvasKit colors are now represented with a TypedArray of four floats.
- - Safari now defaults to using WebGL1 instead of WebGL2 (skbug.com/10171)
+ - Calls to `getError` should be disabled. This may cause a performance improvement in some scenarios.
### Removed
- SkPaint.setColorf is obsolete and removed. setColor accepts a CanvasKit color which is
@@ -31,6 +125,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `SkCanvas.concat44` has been folded into concat (which now takes 3x2, 3x3, or 4x4 matrices). It will
be removed soon.
+### Fixed
+ - Memory leak in paragraph binding code (https://github.com/flutter/flutter/issues/56938)
+ - Safari now properly uses WebGL1 instead of WebGL2 when WebGL2 is not available (skbug.com/10171).
+
## [0.14.0] - 2020-03-18
### Added
diff --git a/chromium/third_party/skia/modules/canvaskit/Makefile b/chromium/third_party/skia/modules/canvaskit/Makefile
index 006771cd143..772a4a39b0e 100644
--- a/chromium/third_party/skia/modules/canvaskit/Makefile
+++ b/chromium/third_party/skia/modules/canvaskit/Makefile
@@ -80,6 +80,9 @@ test-continuous:
echo "Also assuming make debug or release has also been run by a user (if needed)"
npx karma start ./karma.conf.js --no-single-run --watch-poll
+test-continuous-headless:
+ npx karma start ./karma.conf.js --no-single-run --watch-poll --headless
+
.PHONY: perf
perf:
npx karma start ./karma.bench.conf.js --single-run
@@ -91,5 +94,5 @@ docker-compile:
mkdir -p ${SKIA_ROOT}/out/canvaskit_wasm_docker
docker run --rm --volume ${SKIA_ROOT}:/SRC \
--volume ${SKIA_ROOT}/out/canvaskit_wasm_docker:/OUT \
- gcr.io/skia-public/canvaskit-emsdk:1.39.6_v1 \
+ gcr.io/skia-public/canvaskit-emsdk:1.39.16_v1 \
/SRC/infra/canvaskit/build_canvaskit.sh
diff --git a/chromium/third_party/skia/modules/canvaskit/README.md b/chromium/third_party/skia/modules/canvaskit/README.md
index 32e5e1097d4..48a197021f7 100644
--- a/chromium/third_party/skia/modules/canvaskit/README.md
+++ b/chromium/third_party/skia/modules/canvaskit/README.md
@@ -4,7 +4,16 @@ To compile CanvasKit, you will first need to [install `emscripten`][1]. This
will set the environment `EMSDK` (among others) which is required for
compilation.
-# Compile and Test Locally
+[1]: https://emscripten.org/docs/getting_started/downloads.html
+
+## MacOS specific notes
+Make sure you have Python3 installed, otherwise the downloading emscripten toolchain
+can fail with errors about SSL certificates. <https://github.com/emscripten-core/emsdk/pull/273>
+
+See also <https://github.com/emscripten-core/emscripten/issues/9036#issuecomment-532092743>
+for a solution to Python3 using the wrong certificates.
+
+# Compile and Run Local Example
```
make release # make debug is much faster and has better error messages
@@ -23,7 +32,67 @@ any of the "extras", one might run:
Such a stripped-down version is about half the size of the default release build.
-[1]: https://emscripten.org/docs/getting_started/downloads.html
+# Unit tests, performance tests, and coverage.
+
+To run unit tests and compute test coverage on a debug gpu build
+
+```
+make debug
+make test-continuous
+```
+
+This reads karma.conf.js, and opens a chrome browser and begins running all the test
+in `test/` it will detect changes to the tests in that directory and automatically
+run again, however it will automatically rebuild and reload canvaskit. Closing the
+chrome window will just cause it to re-opened. Kill the karma process to stop continuous
+monitoring for changes.
+
+The tests are run with whichever build of canvaskit you last made. be sure to also
+test with `release`, `debug_cpu`, and `release_cpu`. testing with release builds will
+expose problems in closure compilation and usually forgotten externs.
+
+## Coverage
+
+Coverage will be automatically computed when running test-continuous locally. Note that
+the results will only be useful when testing a debug build. Open
+`coverage/<browser version>/index.html` For a summary and detailed line-by-line result.
+
+## Measuring Performance
+
+To measure the runtime of all benchmarks in `perf/`
+
+```
+make release
+make perf
+```
+
+Performacnce benchmarks also use karma, with a different config `karma.bench.conf.js`.
+It will run once and print results.
+
+Typically, you'd want to run these at head, and with your CL to observe the effect of some
+optimization.
+
+## Adding tests
+
+The tests in `tests/` and `perf/` are grouped into files by topic.
+Within each file there are `describe` blocks further organizing the tests, and within those
+`it()` functions which test particular behaviors. `describe` and `it` are jasmine methods
+which can both be temporarily renamed `fdescribe` and `fit`. Which causes jasmine to only those.
+
+We have also defined `gm` which is a method for defining a test which draws something to a canvas
+that is shapshotted and reported to gold.skia.org, where you can compare it with the snapshot at
+head.
+
+## Testing from Gerrit
+
+When submitting a CL in gerrit, click "choose tryjobs" and type canvaskit to filter them.
+select all of them, which at the time of this writing is four jobs, for each combination
+of perf/test gpu/cpu.
+
+The performance results are reported to perf.skia.org
+gold results are reported to gold.skia.org
+
+Coverage is not measured while running tests this way.
# Infrastructure Playbook
@@ -51,9 +120,9 @@ sdk and verified/fixed any build issues that have arisen.
5. Edit `$SKIA_ROOT/infra/canvaskit/docker/Makefile` to have the same version
from step 2. It's easiest to keep the `emsdk-base` and `canvaskit-emsdk` versions
be in lock-step.
- 6. In `$SKIA_ROOT/infra/canvaskit/docker/`, make `publish_canvaskit_emsdk`.
+ 6. In `$SKIA_ROOT/infra/canvaskit/docker/`, run `make publish_canvaskit_emsdk`.
7. In `$SKIA_ROOT/infra/bots/recipe_modules/build/`, update `canvaskit.py`
- and `pathkit.py` to have `DOCKER_IMAAGE` point to the desired tagged Docker
+ and `pathkit.py` to have `DOCKER_IMAGE` point to the desired tagged Docker
containers from steps 2 and 5 (which should be the same).
9. In `$SKIA_ROOT/infra/bots/`, run `make train` to re-train the recipes.
10. Optional: Run something like `git grep 1\\.38\\.` in `$SKIA_ROOT` to see if
diff --git a/chromium/third_party/skia/modules/canvaskit/canvaskit/README.md b/chromium/third_party/skia/modules/canvaskit/canvaskit/README.md
index d71507e24af..6288299f5fd 100644
--- a/chromium/third_party/skia/modules/canvaskit/canvaskit/README.md
+++ b/chromium/third_party/skia/modules/canvaskit/canvaskit/README.md
@@ -10,16 +10,16 @@ To use the library, run `npm install canvaskit-wasm` and then simply include it:
<script src="/node_modules/canvaskit-wasm/bin/canvaskit.js"></script>
CanvasKitInit({
locateFile: (file) => '/node_modules/canvaskit-wasm/bin/'+file,
- }).ready().then((CanvasKit) => {
+ }).then((CanvasKit) => {
// Code goes here using CanvasKit
});
As with all npm packages, there's a freely available CDN via unpkg.com:
- <script src="https://unpkg.com/canvaskit-wasm@0.3.0/bin/canvaskit.js"></script>
+ <script src="https://unpkg.com/canvaskit-wasm@0.16.0/bin/canvaskit.js"></script>
CanvasKitInit({
- locateFile: (file) => 'https://unpkg.com/canvaskit-wasm@0.3.0/bin/'+file,
- }).ready().then(...)
+ locateFile: (file) => 'https://unpkg.com/canvaskit-wasm@0.16.0/bin/'+file,
+ }).then(...)
## Node
To use CanvasKit in Node, it's similar to the browser:
@@ -27,7 +27,7 @@ To use CanvasKit in Node, it's similar to the browser:
const CanvasKitInit = require('/node_modules/canvaskit-wasm/bin/canvaskit.js');
CanvasKitInit({
locateFile: (file) => __dirname + '/bin/'+file,
- }).ready().then((CanvasKit) => {
+ }).then((CanvasKit) => {
// Code goes here using CanvasKit
});
@@ -41,7 +41,7 @@ used with a few configuration changes.
In the JS code, use require():
const CanvasKitInit = require('canvaskit-wasm/bin/canvaskit.js')
- CanvasKitInit().ready().then((CanvasKit) => {
+ CanvasKitInit().then((CanvasKit) => {
// Code goes here using CanvasKit
});
@@ -106,4 +106,4 @@ See more examples in `example.html` and `node.example.js`.
Please file bugs at [skbug.com](skbug.com).
It may be convenient to use [our online fiddle](jsfiddle.skia.org/canvaskit) to demonstrate any issues encountered.
-See CONTRIBUTING.md for more information on sending pull requests. \ No newline at end of file
+See CONTRIBUTING.md for more information on sending pull requests.
diff --git a/chromium/third_party/skia/modules/canvaskit/canvaskit/example.html b/chromium/third_party/skia/modules/canvaskit/canvaskit/example.html
index d52b74fed77..68f343f05de 100644
--- a/chromium/third_party/skia/modules/canvaskit/canvaskit/example.html
+++ b/chromium/third_party/skia/modules/canvaskit/canvaskit/example.html
@@ -36,9 +36,11 @@
<canvas id=gradient1 width=300 height=300></canvas>
<canvas id=patheffect width=300 height=300></canvas>
<canvas id=paths width=200 height=200></canvas>
+<canvas id=pathperson width=300 height=300></canvas>
<canvas id=ink width=300 height=300></canvas>
<canvas id=surfaces width=300 height=300></canvas>
<canvas id=atlas width=300 height=300></canvas>
+<canvas id=decode width=300 height=300></canvas>
<h2> CanvasKit can allow for text shaping (e.g. breaking, kerning)</h2>
<canvas id=shape1 width=600 height=600></canvas>
@@ -50,20 +52,24 @@
<script type="text/javascript" charset="utf-8">
var CanvasKit = null;
+ var cdn = 'https://storage.googleapis.com/skia-cdn/misc/';
- var robotoData = null;
- var notoserifData = null;
+ const ckLoaded = CanvasKitInit({locateFile: (file) => '/node_modules/canvaskit/bin/'+file});
- var mandrillData = null;
- var cdn = 'https://storage.googleapis.com/skia-cdn/misc/';
- CanvasKitInit({
- locateFile: (file) => '/node_modules/canvaskit/bin/'+file,
- }).ready().then((CK) => {
+ const loadRoboto = fetch(cdn + 'Roboto-Regular.ttf').then((response) => response.arrayBuffer());
+ const loadNotoSerif = fetch(cdn + 'NotoSerif-Regular.ttf').then((response) => response.arrayBuffer());
+ const loadTestImage = fetch(cdn + 'test.png').then((response) => response.arrayBuffer());
+
+ // Examples which only require canvaskit
+ ckLoaded.then((CK) => {
CanvasKit = CK;
- DrawingExample(CanvasKit, robotoData);
PathExample(CanvasKit);
InkExample(CanvasKit);
-
+ PathPersonExample(CanvasKit);
+ VertexAPI1(CanvasKit);
+ GradiantAPI1(CanvasKit);
+ TextOnPathAPI1(CanvasKit);
+ SurfaceAPI1(CanvasKit);
CanvasAPI1(CanvasKit);
CanvasAPI2(CanvasKit);
CanvasAPI3(CanvasKit);
@@ -72,40 +78,16 @@
CanvasAPI6(CanvasKit);
CanvasAPI7(CanvasKit);
CanvasAPI8(CanvasKit);
-
- VertexAPI1(CanvasKit);
-
- GradiantAPI1(CanvasKit);
-
- TextShapingAPI1(CanvasKit, notoserifData);
- TextShapingAPI2(CanvasKit, notoserifData);
- TextOnPathAPI1(CanvasKit);
-
- SurfaceAPI1(CanvasKit);
-
- AtlasAPI1(CanvasKit, mandrillData);
- });
-
- fetch(cdn + 'Roboto-Regular.ttf').then((resp) => {
- resp.arrayBuffer().then((buffer) => {
- robotoData = buffer;
- DrawingExample(CanvasKit, robotoData);
- });
- });
-
- fetch(cdn + 'NotoSerif-Regular.ttf').then((resp) => {
- resp.arrayBuffer().then((buffer) => {
- notoserifData = buffer;
- TextShapingAPI1(CanvasKit, notoserifData);
- TextShapingAPI2(CanvasKit, notoserifData);
- });
});
- // Mandrill test image
- fetch(cdn + 'test.png').then((response) => response.arrayBuffer()).then((buffer) => {
- mandrillData = buffer;
- AtlasAPI1(CanvasKit, mandrillData);
+ // Examples requiring external resources
+ Promise.all([ckLoaded, loadRoboto]).then((results) => {DrawingExample(...results)});
+ Promise.all([ckLoaded, loadNotoSerif]).then((results) => {
+ TextShapingAPI1(...results);
+ TextShapingAPI2(...results);
});
+ Promise.all([ckLoaded, loadTestImage]).then((results) => {AtlasAPI1(...results)});
+ Promise.all([ckLoaded, loadTestImage]).then((results) => {DecodeAPI(...results)});
function DrawingExample(CanvasKit, robotoData) {
if (!robotoData || !CanvasKit) {
@@ -175,6 +157,38 @@
// textFont.delete();
}
+ function PathPersonExample(CanvasKit) {
+ const surface = CanvasKit.MakeSWCanvasSurface('pathperson');
+ if (!surface) {
+ console.error('Could not make surface');
+ return;
+ }
+
+ function drawFrame(canvas) {
+ const paint = new CanvasKit.SkPaint();
+ paint.setStrokeWidth(1.0);
+ paint.setAntiAlias(true);
+ paint.setColor(CanvasKit.Color(0, 0, 0, 1.0));
+ paint.setStyle(CanvasKit.PaintStyle.Stroke);
+
+ const path = new CanvasKit.SkPath();
+ path.moveTo(10, 10);
+ path.lineTo(100, 10);
+ path.moveTo(10, 10);
+ path.lineTo(10, 200);
+ path.moveTo(10, 100);
+ path.lineTo(100,100);
+ path.moveTo(10, 200);
+ path.lineTo(100, 200);
+
+ canvas.drawPath(path, paint);
+ path.delete();
+ paint.delete();
+ }
+ // Intentionally just draw frame once
+ surface.drawOnce(drawFrame);
+ }
+
function PathExample(CanvasKit) {
const surface = CanvasKit.MakeSWCanvasSurface('paths');
if (!surface) {
@@ -1091,6 +1105,7 @@
height: 50,
alphaType: CanvasKit.AlphaType.Premul,
colorType: CanvasKit.ColorType.RGBA_8888,
+ colorSpace: CanvasKit.SkColorSpace.SRGB,
});
if (!subSurface) {
@@ -1167,8 +1182,8 @@
dsts.push(0, .8, 200, 100);
const colors = new CanvasKit.SkColorBuilder();
- colors.push(CanvasKit.Color(85, 170, 10, 0.5)); // light green
- colors.push(CanvasKit.Color(51, 51, 191, 0.5)); // light blue
+ colors.push(CanvasKit.ColorAsInt(85, 170, 10, 128)); // light green
+ colors.push(CanvasKit.ColorAsInt(51, 51, 191, 128)); // light blue
let i = 0;
@@ -1200,4 +1215,23 @@
surface.requestAnimationFrame(drawFrame);
}
+
+ async function DecodeAPI(CanvasKit, imgData) {
+ if (!CanvasKit || !imgData) {
+ return;
+ }
+ const surface = CanvasKit.MakeCanvasSurface('decode');
+ if (!surface) {
+ console.error('Could not make surface');
+ return;
+ }
+ const blob = new Blob([ imgData ]);
+ // ImageBitmap is not supported in Safari
+ const imageBitmap = await createImageBitmap(blob);
+ const img = await CanvasKit.MakeImageFromCanvasImageSource(imageBitmap);
+
+ surface.drawOnce((canvas) => {
+ canvas.drawImage(img, 0, 0, null);
+ });
+ }
</script>
diff --git a/chromium/third_party/skia/modules/canvaskit/canvaskit/extra.html b/chromium/third_party/skia/modules/canvaskit/canvaskit/extra.html
index 8b0d08a1c7e..720273cf175 100644
--- a/chromium/third_party/skia/modules/canvaskit/canvaskit/extra.html
+++ b/chromium/third_party/skia/modules/canvaskit/canvaskit/extra.html
@@ -34,118 +34,117 @@
<h2> 3D perspective transformations </h2>
<canvas id=camera3d width=500 height=500></canvas>
+<canvas id=glyphgame width=500 height=500></canvas>
-<h2> Use of offscreen surfaces </h2>
-<canvas id=surfaces width=500 height=500></canvas>
+<h2> Support for extended color spaces </h2>
+<a href="chrome://flags/#force-color-profile">Force P3 profile</a>
+<canvas id=colorsupport width=300 height=300></canvas>
<script type="text/javascript" src="/node_modules/canvaskit/bin/canvaskit.js"></script>
<script type="text/javascript" charset="utf-8">
var CanvasKit = null;
- var legoJSON = null;
- var drinksJSON = null;
- var confettiJSON = null;
- var onboardingJSON = null;
- var multiFrameJSON = null;
- var fullBounds = {fLeft: 0, fTop: 0, fRight: 500, fBottom: 500};
-
- var robotoData = null;
- var notoserifData = null;
-
- var flightAnimGif = null;
- var skpData = null;
var cdn = 'https://storage.googleapis.com/skia-cdn/misc/';
- const ckLoaded = CanvasKitInit({
- locateFile: (file) => '/node_modules/canvaskit/bin/'+file,
- }).ready();
- ckLoaded.then((CK) => {
- CanvasKit = CK;
- // Set bounds to fix the 4:3 resolution of the legos
- SkottieExample(CanvasKit, 'sk_legos', legoJSON,
- {fLeft: -50, fTop: 0, fRight: 350, fBottom: 300});
- // Re-size to fit
- SkottieExample(CanvasKit, 'sk_drinks', drinksJSON, fullBounds);
- SkottieExample(CanvasKit, 'sk_party', confettiJSON, fullBounds);
- SkottieExample(CanvasKit, 'sk_onboarding', onboardingJSON, fullBounds);
- SkottieExample(CanvasKit, 'sk_animated_gif', multiFrameJSON, fullBounds, {
- 'image_0.png': flightAnimGif,
- });
- ParticlesAPI1(CanvasKit);
- ParagraphAPI1(CanvasKit, robotoData);
+ const ckLoaded = CanvasKitInit({locateFile: (file) => '/node_modules/canvaskit/bin/'+file});
- RTShaderAPI1(CanvasKit);
+ const loadLegoJSON = fetch(cdn + 'lego_loader.json').then((response) => response.text());
+ const loadDrinksJSON = fetch(cdn + 'drinks.json').then((response) => response.text());
+ const loadConfettiJSON = fetch(cdn + 'confetti.json').then((response) => response.text());
+ const loadOnboardingJSON = fetch(cdn + 'onboarding.json').then((response) => response.text());
+ const loadMultiframeJSON = fetch(cdn + 'skottie_sample_multiframe.json').then((response) => response.text());
- SkpExample(CanvasKit, skpData);
-
- SurfaceAPI1(CanvasKit);
- });
+ const loadFlightGif = fetch(cdn + 'flightAnim.gif').then((response) => response.arrayBuffer());
+ const loadSkp = fetch(cdn + 'picture2.skp').then((response) => response.arrayBuffer());
+ const loadFont = fetch(cdn + 'Roboto-Regular.ttf').then((response) => response.arrayBuffer());
+ const loadDog = fetch(cdn + 'dog.jpg').then((response) => response.arrayBuffer());
+ const loadMandrill = fetch(cdn + 'mandrill_256.png').then((response) => response.arrayBuffer());
+ const loadBrickTex = fetch(cdn + 'brickwork-texture.jpg').then((response) => response.arrayBuffer());
+ const loadBrickBump = fetch(cdn + 'brickwork_normal-map.jpg').then((response) => response.arrayBuffer());
- fetch(cdn + 'lego_loader.json').then((resp) => {
- resp.text().then((str) => {
- legoJSON = str;
- SkottieExample(CanvasKit, 'sk_legos', legoJSON,
- {fLeft: -50, fTop: 0, fRight: 350, fBottom: 300});
- });
- });
+ const curves = {
+ "MaxCount": 1000,
+ "Drawable": {
+ "Type": "SkCircleDrawable",
+ "Radius": 2
+ },
+ "EffectCode": [`
+ void effectSpawn(inout Effect effect) {
+ effect.rate = 200;
+ effect.color = float4(1, 0, 0, 1);
+ }
+ `
+ ],
+ "Code": [`
+ void spawn(inout Particle p) {
+ p.lifetime = 3 + rand(p.seed);
+ p.vel.y = -50;
+ }
+
+ void update(inout Particle p) {
+ float w = mix(15, 3, p.age);
+ p.pos.x = sin(radians(p.age * 320)) * mix(25, 10, p.age) + mix(-w, w, rand(p.seed));
+ if (rand(p.seed) < 0.5) { p.pos.x = -p.pos.x; }
+
+ p.color.g = (mix(75, 220, p.age) + mix(-30, 30, rand(p.seed))) / 255;
+ }
+ `
+ ],
+ "Bindings": []
+ };
- fetch(cdn + 'drinks.json').then((resp) => {
- resp.text().then((str) => {
- drinksJSON = str;
- SkottieExample(CanvasKit, 'sk_drinks', drinksJSON, fullBounds);
- });
+ const spiralSkSL = `
+ uniform float rad_scale;
+ uniform float2 in_center;
+ uniform float4 in_colors0;
+ uniform float4 in_colors1;
+
+ void main(float2 p, inout half4 color) {
+ float2 pp = p - in_center;
+ float radius = sqrt(dot(pp, pp));
+ radius = sqrt(radius);
+ float angle = atan(pp.y / pp.x);
+ float t = (angle + 3.1415926/2) / (3.1415926);
+ t += radius * rad_scale;
+ t = fract(t);
+ color = half4(mix(in_colors0, in_colors1, t));
+ }`;
+
+ // Examples which only require canvaskit
+ ckLoaded.then((CK) => {
+ CanvasKit = CK;
+ ParticlesAPI1(CanvasKit);
+ RTShaderAPI1(CanvasKit);
+ ColorSupport(CanvasKit);
});
- fetch(cdn + 'confetti.json').then((resp) => {
- resp.text().then((str) => {
- confettiJSON = str;
- SkottieExample(CanvasKit, 'sk_party', confettiJSON, fullBounds);
- });
+ // Examples requiring external resources.
+ // Set bounds to fix the 4:3 resolution of the legos
+ Promise.all([ckLoaded, loadLegoJSON]).then(([ck, jsonstr]) => {
+ SkottieExample(ck, 'sk_legos', jsonstr, {fLeft: -50, fTop: 0, fRight: 350, fBottom: 300});
});
-
- fetch(cdn + 'onboarding.json').then((resp) => {
- resp.text().then((str) => {
- onboardingJSON = str;
- SkottieExample(CanvasKit, 'sk_onboarding', onboardingJSON, fullBounds);
- });
+ // Re-size to fit
+ let fullBounds = {fLeft: 0, fTop: 0, fRight: 500, fBottom: 500};
+ Promise.all([ckLoaded, loadDrinksJSON]).then(([ck, jsonstr]) => {
+ SkottieExample(ck, 'sk_drinks', jsonstr, fullBounds);
});
-
- fetch(cdn + 'skottie_sample_multiframe.json').then((resp) => {
- resp.text().then((str) => {
- multiFrameJSON = str;
- SkottieExample(CanvasKit, 'sk_animated_gif', multiFrameJSON, fullBounds, {
- 'image_0.png': flightAnimGif,
- });
- });
+ Promise.all([ckLoaded, loadConfettiJSON]).then(([ck, jsonstr]) => {
+ SkottieExample(ck, 'sk_party', jsonstr, fullBounds);
});
-
- fetch(cdn + 'flightAnim.gif').then((resp) => {
- resp.arrayBuffer().then((buffer) => {
- flightAnimGif = buffer;
- SkottieExample(CanvasKit, 'sk_animated_gif', multiFrameJSON, fullBounds, {
- 'image_0.png': flightAnimGif,
- });
- });
+ Promise.all([ckLoaded, loadOnboardingJSON]).then(([ck, jsonstr]) => {
+ SkottieExample(ck, 'sk_onboarding', jsonstr, fullBounds);
});
-
- fetch(cdn + 'Roboto-Regular.ttf').then((resp) => {
- resp.arrayBuffer().then((buffer) => {
- robotoData = buffer;
- ParagraphAPI1(CanvasKit, robotoData);
- });
+ Promise.all([ckLoaded, loadMultiframeJSON, loadFlightGif]).then(([ck, jsonstr, gif]) => {
+ SkottieExample(ck, 'sk_animated_gif', jsonstr, fullBounds, {'image_0.png': gif});
});
- fetch(cdn + 'picture2.skp').then((response) => response.arrayBuffer()).then((buffer) => {
- skpData = buffer;
- SkpExample(CanvasKit, skpData);
+ Promise.all([ckLoaded, loadFont]).then((results) => {
+ ParagraphAPI1(...results);
+ GlyphGame(...results)
});
-
- const loadDog = fetch(cdn + 'dog.jpg').then((response) => response.arrayBuffer());
- const loadMandrill = fetch(cdn + 'mandrill_256.png').then((response) => response.arrayBuffer());
- const loadBrickTex = fetch(cdn + 'brickwork-texture.jpg').then((response) => response.arrayBuffer());
- const loadBrickBump = fetch(cdn + 'brickwork_normal-map.jpg').then((response) => response.arrayBuffer());
- Promise.all([ckLoaded, loadBrickTex, loadBrickBump]).then((results) => {Camera3D(...results)});
+ Promise.all([ckLoaded, loadSkp]).then((results) => {SkpExample(...results)});
+ Promise.all([ckLoaded, loadBrickTex, loadBrickBump, loadFont]).then((results) => {Camera3D(...results)});
function SkottieExample(CanvasKit, id, jsonStr, bounds, assets) {
if (!CanvasKit || !jsonStr) {
@@ -209,107 +208,6 @@
surface.requestAnimationFrame(drawFrame);
}
-const curves = {
- "MaxCount": 1000,
- "Drawable": {
- "Type": "SkCircleDrawable",
- "Radius": 2
- },
- "EffectCode": [
- "void effectSpawn(inout Effect effect) {",
- " effect.rate = 200;",
- " effect.color = float4(1, 0, 0, 1);",
- "}",
- ""
- ],
- "Code": [
- "void spawn(inout Particle p) {",
- " p.lifetime = 3 + rand(p.seed);",
- " p.vel.y = -50;",
- "}",
- "",
- "void update(inout Particle p) {",
- " float w = mix(15, 3, p.age);",
- " p.pos.x = sin(radians(p.age * 320)) * mix(25, 10, p.age) + mix(-w, w, rand(p.seed));",
- " if (rand(p.seed) < 0.5) { p.pos.x = -p.pos.x; }",
- "",
- " p.color.g = (mix(75, 220, p.age) + mix(-30, 30, rand(p.seed))) / 255;",
- "}",
- ""
- ],
- "Bindings": []
-};
-
- function SurfaceAPI1(CanvasKit) {
- const surface = CanvasKit.MakeCanvasSurface('surfaces');
- if (!surface) {
- console.error('Could not make surface');
- return;
- }
- console.log('SurfaceAPI1 top surface type = '+surface.reportBackendType() );
- const context = CanvasKit.currentContext();
- const canvas = surface.getCanvas();
-
- //create a subsurface as a temporary workspace.
- const subSurface = surface.makeSurface({
- width: 50,
- height: 50,
- alphaType: CanvasKit.AlphaType.Premul,
- colorType: CanvasKit.ColorType.RGBA_8888,
- });
-
- if (!subSurface) {
- console.error('Could not make subsurface');
- return;
- }
- console.log('SurfaceAPI1 subSurface type = '+subSurface.reportBackendType() );
-
- // draw a small "scene"
- const paint = new CanvasKit.SkPaint();
- paint.setColor(CanvasKit.Color(139, 228, 135, 0.95)); // greenish
- paint.setStyle(CanvasKit.PaintStyle.Fill);
- paint.setAntiAlias(true);
-
- const subCanvas = subSurface.getCanvas();
- subCanvas.clear(CanvasKit.BLACK);
- subCanvas.drawRect(CanvasKit.LTRBRect(5, 15, 45, 40), paint);
-
- paint.setColor(CanvasKit.Color(214, 93, 244)); // purplish
- for (let i = 0; i < 10; i++) {
- const x = Math.random() * 50;
- const y = Math.random() * 50;
-
- subCanvas.drawOval(CanvasKit.XYWHRect(x, y, 6, 6), paint);
- }
-
- // Snap it off as an SkImage - this image will be in the form the
- // parent surface prefers (e.g. Texture for GPU / Raster for CPU).
- const img = subSurface.makeImageSnapshot();
-
- // clean up the temporary surface
- subSurface.delete();
- paint.delete();
-
- // Make it repeat a bunch with a shader
- const pattern = img.makeShader(CanvasKit.TileMode.Repeat, CanvasKit.TileMode.Mirror);
- const patternPaint = new CanvasKit.SkPaint();
- patternPaint.setShader(pattern);
-
- let i = 0;
-
- function drawFrame() {
- i++;
- CanvasKit.setCurrentContext(context);
- canvas.clear(CanvasKit.WHITE);
-
- canvas.drawOval(CanvasKit.LTRBRect(i % 60, i % 60, 300 - (i% 60), 300 - (i % 60)), patternPaint);
- surface.flush();
- window.requestAnimationFrame(drawFrame);
- }
- window.requestAnimationFrame(drawFrame);
-
- }
-
function ParagraphAPI1(CanvasKit, fontData) {
if (!CanvasKit || !fontData) {
return;
@@ -372,23 +270,6 @@ const curves = {
return surface;
}
- const spiralSkSL = `
- uniform float rad_scale;
- uniform float2 in_center;
- uniform float4 in_colors0;
- uniform float4 in_colors1;
-
- void main(float2 p, inout half4 color) {
- float2 pp = p - in_center;
- float radius = sqrt(dot(pp, pp));
- radius = sqrt(radius);
- float angle = atan(pp.y / pp.x);
- float t = (angle + 3.1415926/2) / (3.1415926);
- t += radius * rad_scale;
- t = fract(t);
- color = half4(mix(in_colors0, in_colors1, t));
- }`;
-
function RTShaderAPI1(CanvasKit) {
if (!CanvasKit) {
return;
@@ -448,9 +329,9 @@ const curves = {
}
const prog = `
- in fragmentProcessor before_map;
- in fragmentProcessor after_map;
- in fragmentProcessor threshold_map;
+ in shader before_map;
+ in shader after_map;
+ in shader threshold_map;
uniform float cutoff;
uniform float slope;
@@ -557,10 +438,37 @@ const curves = {
surface.drawOnce(drawFrame);
}
- function Camera3D(canvas, textureImgData, normalImgData) {
- if (!canvas) {
-
+ // Return the inverse of an SkM44. throw an error if it's not invertible
+ function mustInvert(m) {
+ const m2 = CanvasKit.SkM44.invert(m);
+ if (m2 === null) {
+ throw "Matrix not invertible";
}
+ return m2;
+ }
+
+ // TODO(nifong): This function is in desperate need of some explanation of what it does
+ // cam is a object having eye, coa, up, near, far, angle
+ function saveCamera(canvas, /* rect */ area, /* scalar */ zscale, cam) {
+ const camera = CanvasKit.SkM44.lookat(cam.eye, cam.coa, cam.up);
+ const perspective = CanvasKit.SkM44.perspective(cam.near, cam.far, cam.angle);
+ // Calculate viewport scale. Even through we know these values are all constants in this
+ // example it might be handy to change the size later.
+ const center = [(area.fLeft + area.fRight)/2, (area.fTop + area.fBottom)/2, 0];
+ const viewScale = [(area.fRight - area.fLeft)/2, (area.fBottom - area.fTop)/2, zscale];
+ const viewport = CanvasKit.SkM44.multiply(
+ CanvasKit.SkM44.translated(center),
+ CanvasKit.SkM44.scaled(viewScale));
+
+ // want "world" to be in our big coordinates (e.g. area), so apply this inverse
+ // as part of our "camera".
+ canvas.concat(CanvasKit.SkM44.multiply(viewport, perspective));
+ canvas.concat(CanvasKit.SkM44.multiply(camera, mustInvert(viewport)));
+ // Mark the matrix to make it available to the shader by this name.
+ canvas.markCTM('local_to_world');
+ }
+
+ function Camera3D(canvas, textureImgData, normalImgData, robotoData) {
const surface = CanvasKit.MakeCanvasSurface('camera3d');
if (!surface) {
console.error('Could not make surface');
@@ -586,13 +494,15 @@ const curves = {
const rr = CanvasKit.RRectXY(CanvasKit.LTRBRect(margin, margin,
vSphereRadius - margin, vSphereRadius - margin), margin*2.5, margin*2.5);
- const camNear = 0.05;
- const camFar = 4;
const camAngle = Math.PI / 12;
-
- const camEye = [0, 0, 1 / Math.tan(camAngle/2) - 1];
- const camCOA = [0, 0, 0];
- const camUp = [0, 1, 0];
+ const cam = {
+ 'eye' : [0, 0, 1 / Math.tan(camAngle/2) - 1],
+ 'coa' : [0, 0, 0],
+ 'up' : [0, 1, 0],
+ 'near' : 0.05,
+ 'far' : 4,
+ 'angle': camAngle,
+ };
let mouseDown = false;
let clickDown = [0, 0]; // location of click down
@@ -619,8 +529,8 @@ const curves = {
const children = [textureShader, normalShader];
const prog = `
- in fragmentProcessor color_map;
- in fragmentProcessor normal_map;
+ in shader color_map;
+ in shader normal_map;
uniform float3 lightPos;
layout (marker=local_to_world) uniform float4x4 localToWorld;
@@ -706,34 +616,6 @@ const curves = {
return m2[10]
}
- // Return the inverse of an SkM44. throw an error if it's not invertible
- function mustInvert(m) {
- var m2 = CanvasKit.SkM44.invert(m);
- if (m2 === null) {
- throw "Matrix not invertible";
- }
- return m2;
- }
-
- function saveCamera(canvas, /* rect */ area, /* scalar */ zscale) {
- const camera = CanvasKit.SkM44.lookat(camEye, camCOA, camUp);
- const perspective = CanvasKit.SkM44.perspective(camNear, camFar, camAngle);
- // Calculate viewport scale. Even through we know these values are all constants in this
- // example it might be handy to change the size later.
- const center = [(area.fLeft + area.fRight)/2, (area.fTop + area.fBottom)/2, 0];
- const viewScale = [(area.fRight - area.fLeft)/2, (area.fBottom - area.fTop)/2, zscale];
- const viewport = CanvasKit.SkM44.multiply(
- CanvasKit.SkM44.translated(center),
- CanvasKit.SkM44.scaled(viewScale));
-
- // want "world" to be in our big coordinates (e.g. area), so apply this inverse
- // as part of our "camera".
- canvas.concat(CanvasKit.SkM44.multiply(viewport, perspective));
- canvas.concat(CanvasKit.SkM44.multiply(camera, mustInvert(viewport)));
- // Mark the matrix to make it available to the shader by this name.
- canvas.markCTM('local_to_world');
- }
-
function setClickToWorld(canvas, matrix) {
const l2d = canvas.getLocalToDevice();
worldToClick = CanvasKit.SkM44.multiply(mustInvert(matrix), l2d);
@@ -763,7 +645,7 @@ const curves = {
canvas.save();
canvas.translate(vSphereCenter[0] - vSphereRadius/2, vSphereCenter[1] - vSphereRadius/2);
// pass surface dimensions as viewport size.
- saveCamera(canvas, CanvasKit.LTRBRect(0, 0, vSphereRadius, vSphereRadius), vSphereRadius/2);
+ saveCamera(canvas, CanvasKit.LTRBRect(0, 0, vSphereRadius, vSphereRadius), vSphereRadius/2, cam);
setClickToWorld(canvas, clickM);
for (let f of faces) {
const saveCount = canvas.getSaveCount();
@@ -890,4 +772,172 @@ const curves = {
surface.requestAnimationFrame(drawFrame);
}
+
+ // Shows a hidden message by rotating all the characters in a kind of way that makes you
+ // search with your mouse.
+ function GlyphGame(canvas, robotoData) {
+ const surface = CanvasKit.MakeCanvasSurface('glyphgame');
+ if (!surface) {
+ console.error('Could not make surface');
+ return;
+ }
+ const sizeX = document.getElementById('glyphgame').width;
+ const sizeY = document.getElementById('glyphgame').height;
+ const halfDim = Math.min(sizeX, sizeY) / 2;
+ const margin = 50;
+ const marginTop = 25;
+ let rotX = 0; // expected to be updated in interact()
+ let rotY = 0;
+ let pointer = [500, 450];
+ const radPerPixel = 0.005; // radians of subject rotation per pixel distance moved by mouse.
+
+ const camAngle = Math.PI / 12;
+ const cam = {
+ 'eye' : [0, 0, 1 / Math.tan(camAngle/2) - 1],
+ 'coa' : [0, 0, 0],
+ 'up' : [0, 1, 0],
+ 'near' : 0.02,
+ 'far' : 4,
+ 'angle': camAngle,
+ };
+
+ let lastImage = null;
+
+ const fontMgr = CanvasKit.SkFontMgr.FromData([robotoData]);
+
+ const paraStyle = new CanvasKit.ParagraphStyle({
+ textStyle: {
+ color: CanvasKit.Color(105, 56, 16), // brown
+ fontFamilies: ['Roboto'],
+ fontSize: 28,
+ },
+ textAlign: CanvasKit.TextAlign.Left,
+ });
+ const hStyle = CanvasKit.RectHeightStyle.Max;
+ const wStyle = CanvasKit.RectWidthStyle.Tight;
+
+ const quotes = [
+ 'Some activities superficially familiar to you are merely stupid and should be avoided for your safety, although they are not illegal as such. These include: giving your bank account details to the son of the Nigerian Minister of Finance; buying title to bridges, skyscrapers, spacecraft, planets, or other real assets; murder; selling your identity; and entering into financial contracts with entities running Economics 2.0 or higher.',
+ // Charles Stross - Accelerando
+ 'If only there were evil people somewhere insidiously committing evil deeds, and it were necessary only to separate them from the rest of us and destroy them. But the line dividing good and evil cuts through the heart of every human being. And who is willing to destroy a piece of his own heart?',
+ // Aleksandr Solzhenitsyn - The Gulag Archipelago
+ 'There is one metaphor of which the moderns are very fond; they are always saying, “You can’t put the clock back.” The simple and obvious answer is “You can.” A clock, being a piece of human construction, can be restored by the human finger to any figure or hour. In the same way society, being a piece of human construction, can be reconstructed upon any plan that has ever existed.',
+ // G. K. Chesterton - What's Wrong With The World?
+ ];
+
+ // pick one at random
+ const text = quotes[Math.floor(Math.random()*3)];
+ const builder = CanvasKit.ParagraphBuilder.Make(paraStyle, fontMgr);
+ builder.addText(text);
+ const paragraph = builder.build();
+ const font = new CanvasKit.SkFont(null, 18);
+ // wrap the text to a given width.
+ paragraph.layout(sizeX - margin*2);
+
+ // to rotate every glyph individually, calculate the bounding rect of each one,
+ // construct an array of rects and paragraphs that would draw each glyph individually.
+ const letters = Array(text.length);
+ for (let i = 0; i < text.length; i++) {
+ const r = paragraph.getRectsForRange(i, i+1, hStyle, wStyle)[0];
+ // The character is drawn with drawParagraph so we can pass the paraStyle,
+ // and have our character be the exact size and shape the paragraph expected
+ // when it wrapped the text. canvas.drawText wouldn't cut it.
+ const tmpbuilder = CanvasKit.ParagraphBuilder.Make(paraStyle, fontMgr);
+ tmpbuilder.addText(text[i]);
+ const para = tmpbuilder.build();
+ para.layout(100);
+ letters[i] = {
+ 'r': r,
+ 'para': para,
+ };
+ }
+
+ function drawFrame(canvas) {
+ // persistence of vision effect is done by drawing the past frame as an image,
+ // then covering with semitransparent background color.
+ if (lastImage) {
+ canvas.drawImage(lastImage, 0, 0, null);
+ canvas.drawColor(CanvasKit.Color(171, 244, 255, 0.1)); // sky blue, almost transparent
+ } else {
+ canvas.clear(CanvasKit.Color(171, 244, 255)); // sky blue, opaque
+ }
+ canvas.save();
+ // Set up 3D view enviroment
+ saveCamera(canvas, CanvasKit.LTRBRect(0, 0, sizeX, sizeY), halfDim, cam);
+
+ // Rotate the whole paragraph as a unit.
+ const paraRotPoint = [halfDim, halfDim, 1];
+ canvas.concat(CanvasKit.SkM44.multiply(
+ CanvasKit.SkM44.translated(paraRotPoint),
+ CanvasKit.SkM44.rotated([0,1,0], rotX),
+ CanvasKit.SkM44.rotated([1,0,0], rotY * 0.2),
+ CanvasKit.SkM44.translated(CanvasKit.SkVector.mulScalar(paraRotPoint, -1)),
+ ));
+
+ // Rotate every glyph in the paragraph individually.
+ let i = 0;
+ for (const letter of letters) {
+ canvas.save();
+ let r = letter['r'];
+ // rotate about the center of the glyph's rect.
+ rotationPoint = [
+ margin + r.fLeft + (r.fRight - r.fLeft) / 2,
+ marginTop + r.fTop + (r.fBottom - r.fTop) / 2,
+ 0
+ ];
+ distanceFromPointer = CanvasKit.SkVector.dist(pointer, rotationPoint.slice(0, 2));
+ // Rotate more around the Y-axis depending on the glyph's distance from the pointer.
+ canvas.concat(CanvasKit.SkM44.multiply(
+ CanvasKit.SkM44.translated(rotationPoint),
+ // note that I'm rotating around the x axis first, undoing some of the rotation done to the whole
+ // paragraph above, where x came second. If I rotated y first, a lot of letters would end up
+ // upside down, which is a bit too hard to unscramble.
+ CanvasKit.SkM44.rotated([1,0,0], rotY * -0.6),
+ CanvasKit.SkM44.rotated([0,1,0], distanceFromPointer * -0.035),
+ CanvasKit.SkM44.translated(CanvasKit.SkVector.mulScalar(rotationPoint, -1)),
+ ));
+ canvas.drawParagraph(letter['para'], margin + r.fLeft, marginTop + r.fTop);
+ i++;
+ canvas.restore();
+ }
+ canvas.restore();
+ lastImage = surface.makeImageSnapshot();
+ }
+
+ function interact(e) {
+ pointer = [e.offsetX, e.offsetY]
+ rotX = (pointer[0] - halfDim) * radPerPixel;
+ rotY = (pointer[1] - halfDim) * radPerPixel * -1;
+ surface.requestAnimationFrame(drawFrame);
+ };
+
+ document.getElementById('glyphgame').addEventListener('pointermove', interact);
+ surface.requestAnimationFrame(drawFrame);
+ }
+
+ function ColorSupport(CanvasKit) {
+ const surface = CanvasKit.MakeCanvasSurface('colorsupport', CanvasKit.SkColorSpace.ADOBE_RGB);
+ if (!surface) {
+ console.error('Could not make surface');
+ return;
+ }
+ const canvas = surface.getCanvas();
+
+ // If the surface is correctly initialized with a higher bit depth color type,
+ // And chrome is compositing it into a buffer with the P3 color space,
+ // then the inner round rect should be distinct and less saturated than the full red background.
+ // Even if the monitor it is viewed on cannot accurately represent that color space.
+
+ let red = CanvasKit.Color4f(1, 0, 0, 1);
+ let paint = new CanvasKit.SkPaint();
+ paint.setColor(red, CanvasKit.SkColorSpace.ADOBE_RGB);
+ canvas.drawPaint(paint);
+ paint.setColor(red, CanvasKit.SkColorSpace.DISPLAY_P3);
+ canvas.drawRoundRect(CanvasKit.LTRBRect(50, 50, 250, 250), 30, 30, paint);
+ paint.setColor(red, CanvasKit.SkColorSpace.SRGB);
+ canvas.drawRoundRect(CanvasKit.LTRBRect(100, 100, 200, 200), 30, 30, paint);
+
+ surface.flush();
+ surface.delete();
+ }
</script>
diff --git a/chromium/third_party/skia/modules/canvaskit/canvaskit/node.example.js b/chromium/third_party/skia/modules/canvaskit/canvaskit/node.example.js
index 04e7950c24c..557dc09ff7c 100644
--- a/chromium/third_party/skia/modules/canvaskit/canvaskit/node.example.js
+++ b/chromium/third_party/skia/modules/canvaskit/canvaskit/node.example.js
@@ -4,7 +4,7 @@ const path = require('path');
CanvasKitInit({
locateFile: (file) => __dirname + '/bin/'+file,
-}).ready().then((CanvasKit) => {
+}).then((CanvasKit) => {
let canvas = CanvasKit.MakeCanvas(300, 300);
let img = fs.readFileSync(path.join(__dirname, 'test.png'));
@@ -111,4 +111,4 @@ function starPath(CanvasKit, X=128, Y=128, R=116) {
p.lineTo(X + R * Math.cos(a), Y + R * Math.sin(a));
}
return p;
-} \ No newline at end of file
+}
diff --git a/chromium/third_party/skia/modules/canvaskit/canvaskit/package.json b/chromium/third_party/skia/modules/canvaskit/canvaskit/package.json
index d94c602495b..8577a172204 100644
--- a/chromium/third_party/skia/modules/canvaskit/canvaskit/package.json
+++ b/chromium/third_party/skia/modules/canvaskit/canvaskit/package.json
@@ -1,6 +1,6 @@
{
"name": "canvaskit-wasm",
- "version": "0.14.0",
+ "version": "0.16.2",
"description": "A WASM version of Skia's Canvas API",
"main": "bin/canvaskit.js",
"homepage": "https://github.com/google/skia/tree/master/modules/canvaskit",
diff --git a/chromium/third_party/skia/modules/canvaskit/canvaskit/viewer.html b/chromium/third_party/skia/modules/canvaskit/canvaskit/viewer.html
index f201f82a050..69c2a69a3a9 100644
--- a/chromium/third_party/skia/modules/canvaskit/canvaskit/viewer.html
+++ b/chromium/third_party/skia/modules/canvaskit/canvaskit/viewer.html
@@ -15,63 +15,200 @@
<script type="text/javascript" src="/node_modules/canvaskit/bin/canvaskit.js"></script>
<script type="text/javascript" charset="utf-8">
- var CanvasKit = null;
+ const flags = {};
+ for (pair of location.hash.substring(1).split(',')) {
+ // Parse "values" as an array in case the value has a colon (e.g., "slide:http://...").
+ const [key, ...values] = pair.split(':');
+ flags[key] = values.join(':');
+ }
+ window.onhashchange = function() {
+ location.reload();
+ };
+
CanvasKitInit({
locateFile: (file) => '/node_modules/canvaskit/bin/'+file,
- }).ready().then((CK) => {
- CanvasKit = CK;
- ViewerMain(CanvasKit);
+ }).then((CK) => {
+ if (!CK) {
+ throw 'CanvasKit not available.';
+ }
+ LoadSlide(CK);
});
- function ViewerMain(CanvasKit) {
- if (!CanvasKit) {
- console.error('CanvasKit not available.');
- return;
+ function LoadSlide(CanvasKit) {
+ if (!CanvasKit.MakeSlide || !CanvasKit.MakeSkpSlide || !CanvasKit.MakeSvgSlide) {
+ throw 'Not compiled with Viewer.';
}
- if (!CanvasKit.MakeSlide) {
- console.error('Not compiled with Viewer.');
- return;
+ const slideName = flags.slide || 'PathText';
+ if (slideName.endsWith('.skp') || slideName.endsWith('.svg')) {
+ fetch(slideName).then(function(response) {
+ if (response.status != 200) {
+ throw 'Error fetching ' + slideName;
+ }
+ if (slideName.endsWith('.skp')) {
+ response.arrayBuffer().then((data) => ViewerMain(
+ CanvasKit, CanvasKit.MakeSkpSlide(slideName, data)));
+ } else {
+ response.text().then((text) => ViewerMain(
+ CanvasKit, CanvasKit.MakeSvgSlide(slideName, text)));
+ }
+ });
+ } else {
+ ViewerMain(CanvasKit, CanvasKit.MakeSlide(slideName));
}
+ }
+ function ViewerMain(CanvasKit, slide) {
+ if (!slide) {
+ throw 'Failed to parse slide.'
+ }
+ const width = window.innerWidth;
+ const height = window.innerHeight;
const htmlCanvas = document.getElementById('viewer_canvas');
- htmlCanvas.width = window.innerWidth;
- htmlCanvas.height = window.innerHeight;
+ htmlCanvas.width = width;
+ htmlCanvas.height = height;
+ slide.load(width, height);
- const surface = CanvasKit.MakeCanvasSurface(htmlCanvas);
+ // For the msaa flag, only check if the key exists in flags. That way we don't need to assign it
+ // a value in the location hash. i.e.,: http://.../viewer.html#msaa
+ const doMSAA = ('msaa' in flags);
+ // Create the WebGL context with our desired attribs before calling MakeWebGLCanvasSurface.
+ CanvasKit.GetWebGLContext(htmlCanvas, {antialias: doMSAA});
+ const surface = CanvasKit.MakeWebGLCanvasSurface(htmlCanvas, null);
if (!surface) {
- console.error('Could not make surface');
- return;
+ throw 'Could not make canvas surface';
+ }
+ if (doMSAA && surface.sampleCnt() <= 1) {
+ // We requested antialias on the canvas but did not get MSAA. Since we don't know what type of
+ // AA is in use right now (if any), this surface is unusable.
+ throw 'MSAA rendering to the on-screen canvas is not supported. ' +
+ 'Please try again without MSAA.';
}
- const slideName = 'WavyPathText';
- const slide = CanvasKit.MakeSlide(slideName);
- if (!slide) {
- console.error('Could not make slide ' + slideName);
- return;
+ window.onmousedown = (event) => (event.button === 0) && Mouse(CanvasKit.InputState.Down, event);
+ window.onmouseup = (event) => (event.button === 0) && Mouse(CanvasKit.InputState.Up, event);
+ window.onmousemove = (event) => Mouse(CanvasKit.InputState.Move, event);
+ window.onkeypress = function(event) {
+ if (slide.onChar(event.keyCode)) {
+ ScheduleDraw();
+ return false;
+ } else {
+ switch (event.keyCode) {
+ case 's'.charCodeAt(0):
+ // 's' is the magic key in the native viewer app that turns on FPS monitoring. Toggle
+ // forced animation when it is pressed in order to get fps logs.
+ // HINT: Launch chrome with --disable-frame-rate-limit and --disable-gpu-vsync in order
+ // to measure frame rates above 60.
+ ScheduleDraw.forceAnimation = !ScheduleDraw.forceAnimation;
+ ScheduleDraw();
+ break;
+ }
+ }
+ return true;
+ }
+ window.onkeydown = function(event) {
+ const upArrowCode = 38;
+ if (event.keyCode === upArrowCode) {
+ ScaleCanvas((event.shiftKey) ? Infinity : 1.1);
+ return false;
+ }
+ const downArrowCode = 40;
+ if (event.keyCode === downArrowCode) {
+ ScaleCanvas((event.shiftKey) ? 0 : 1/1.1);
+ return false;
+ }
+ return true;
}
- slide.load(htmlCanvas.width, htmlCanvas.height);
+ let [canvasScale, canvasTranslateX, canvasTranslateY] = [1, 0, 0];
+ function ScaleCanvas(factor) {
+ factor = Math.min(Math.max(1/(5*canvasScale), factor), 5/canvasScale);
+ canvasTranslateX *= factor;
+ canvasTranslateY *= factor;
+ canvasScale *= factor;
+ ScheduleDraw();
+ }
+ function TranslateCanvas(dx, dy) {
+ canvasTranslateX += dx;
+ canvasTranslateY += dy;
+ ScheduleDraw();
+ }
- const fps = {
- frames: 0,
- startMs: window.performance.now()
- };
+ function Mouse(state, event) {
+ let modifierKeys = CanvasKit.ModifierKey.None;
+ if (event.shiftKey) {
+ modifierKeys |= CanvasKit.ModifierKey.Shift;
+ }
+ if (event.altKey) {
+ modifierKeys |= CanvasKit.ModifierKey.Option;
+ }
+ if (event.ctrlKey) {
+ modifierKeys |= CanvasKit.ModifierKey.Ctrl;
+ }
+ if (event.metaKey) {
+ modifierKeys |= CanvasKit.ModifierKey.Command;
+ }
+ let [dx, dy] = [event.pageX - this.lastX, event.pageY - this.lastY];
+ this.lastX = event.pageX;
+ this.lastY = event.pageY;
+ if (slide.onMouse(event.pageX, event.pageY, state, modifierKeys)) {
+ ScheduleDraw();
+ return false;
+ } else if (event.buttons & 1) { // Left-button pressed.
+ TranslateCanvas(dx, dy);
+ return false;
+ }
+ return true;
+ }
+
+ function ScheduleDraw() {
+ if (ScheduleDraw.hasPendingAnimationRequest) {
+ // It's possible for this ScheduleDraw() method to be called multiple times before an
+ // animation callback actually gets invoked. Make sure we only ever have one single
+ // requestAnimationFrame scheduled at a time, because otherwise we can get stuck in a
+ // position where multiple callbacks are coming in on a single compositing frame, and then
+ // rescheduling multiple more for the next frame.
+ return;
+ }
+ ScheduleDraw.hasPendingAnimationRequest = true;
+ surface.requestAnimationFrame((canvas) => {
+ ScheduleDraw.hasPendingAnimationRequest = false;
- surface.requestAnimationFrame(function(canvas) {
- slide.draw(canvas);
- ++fps.frames;
+ canvas.save();
+ canvas.translate(canvasTranslateX, canvasTranslateY);
+ canvas.scale(canvasScale, canvasScale);
+ canvas.clear(CanvasKit.WHITE);
+ slide.draw(canvas);
+ canvas.restore();
+ // HINT: Launch chrome with --disable-frame-rate-limit and --disable-gpu-vsync in order to
+ // allow this to go faster than 60fps.
+ const ms = (ScheduleDraw.fps && ScheduleDraw.fps.markFrameComplete()) ||
+ window.performance.now();
+ if (slide.animate(ms * 1e6) || ScheduleDraw.forceAnimation) {
+ ScheduleDraw.fps = ScheduleDraw.fps || new FPSMeter(ms);
+ ScheduleDraw();
+ } else {
+ delete ScheduleDraw.fps;
+ }
+ });
+ }
+
+ ScheduleDraw();
+ }
+
+ function FPSMeter(startMs) {
+ this.frames = 0;
+ this.startMs = startMs;
+ this.markFrameComplete = () => {
+ ++this.frames;
const ms = window.performance.now();
- const sec = (ms - fps.startMs) / 1000;
+ const sec = (ms - this.startMs) / 1000;
if (sec > 2) {
- console.log(Math.round(fps.frames / sec) + ' fps');
- fps.frames = 0;
- fps.startMs = ms;
+ console.log(Math.round(this.frames / sec) + ' fps');
+ this.frames = 0;
+ this.startMs = ms;
}
-
- if (slide.animate(ms * 1e6)) {
- surface.requestAnimationFrame(arguments.callee);
- }
- });
+ return ms;
+ };
}
</script>
diff --git a/chromium/third_party/skia/modules/canvaskit/canvaskit_bindings.cpp b/chromium/third_party/skia/modules/canvaskit/canvaskit_bindings.cpp
index 5823f0abadd..e9c195ee117 100644
--- a/chromium/third_party/skia/modules/canvaskit/canvaskit_bindings.cpp
+++ b/chromium/third_party/skia/modules/canvaskit/canvaskit_bindings.cpp
@@ -12,6 +12,7 @@
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorFilter.h"
+#include "include/core/SkColorSpace.h"
#include "include/core/SkData.h"
#include "include/core/SkDrawable.h"
#include "include/core/SkEncodedImageFormat.h"
@@ -66,7 +67,7 @@
#include "include/gpu/gl/GrGLInterface.h"
#include "include/gpu/gl/GrGLTypes.h"
-#include <GL/gl.h>
+#include <GLES3/gl3.h>
#include <emscripten/html5.h>
#endif
@@ -99,7 +100,8 @@ struct OptionalMatrix : SkMatrix {
SkColor4f ptrToSkColor4f(uintptr_t /* float* */ cPtr) {
float* fourFloats = reinterpret_cast<float*>(cPtr);
- SkColor4f color = { fourFloats[0], fourFloats[1], fourFloats[2], fourFloats[3] };
+ SkColor4f color;
+ memcpy(&color, fourFloats, 4 * sizeof(float));
return color;
}
@@ -109,14 +111,31 @@ struct SimpleImageInfo {
int height;
SkColorType colorType;
SkAlphaType alphaType;
- // TODO color spaces?
+ sk_sp<SkColorSpace> colorSpace;
};
SkImageInfo toSkImageInfo(const SimpleImageInfo& sii) {
- return SkImageInfo::Make(sii.width, sii.height, sii.colorType, sii.alphaType);
+ return SkImageInfo::Make(sii.width, sii.height, sii.colorType, sii.alphaType, sii.colorSpace);
}
#ifdef SK_GL
+
+// Set the pixel format based on the colortype.
+// These degrees of freedom are removed from canvaskit only to keep the interface simpler.
+struct ColorSettings {
+ ColorSettings(sk_sp<SkColorSpace> colorSpace) {
+ if (colorSpace == nullptr || colorSpace->isSRGB()) {
+ colorType = kRGBA_8888_SkColorType;
+ pixFormat = GL_RGBA8;
+ } else {
+ colorType = kRGBA_F16_SkColorType;
+ pixFormat = GL_RGBA16F;
+ }
+ };
+ SkColorType colorType;
+ GrGLenum pixFormat;
+};
+
sk_sp<GrContext> MakeGrContext(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)
{
EMSCRIPTEN_RESULT r = emscripten_webgl_make_context_current(context);
@@ -131,31 +150,31 @@ sk_sp<GrContext> MakeGrContext(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)
return grContext;
}
-sk_sp<SkSurface> MakeOnScreenGLSurface(sk_sp<GrContext> grContext, int width, int height) {
+sk_sp<SkSurface> MakeOnScreenGLSurface(sk_sp<GrContext> grContext, int width, int height,
+ sk_sp<SkColorSpace> colorSpace) {
+ // WebGL should already be clearing the color and stencil buffers, but do it again here to
+ // ensure Skia receives them in the expected state.
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0, 0, 0, 0);
glClearStencil(0);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ grContext->resetContext(kRenderTarget_GrGLBackendState | kMisc_GrGLBackendState);
-
- // Wrap the frame buffer object attached to the screen in a Skia render
- // target so Skia can render to it
- GrGLint buffer;
- glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buffer);
+ // The on-screen canvas is FBO 0. Wrap it in a Skia render target so Skia can render to it.
GrGLFramebufferInfo info;
- info.fFBOID = (GrGLuint) buffer;
- SkColorType colorType;
+ info.fFBOID = 0;
+
+ GrGLint sampleCnt;
+ glGetIntegerv(GL_SAMPLES, &sampleCnt);
GrGLint stencil;
glGetIntegerv(GL_STENCIL_BITS, &stencil);
- info.fFormat = GL_RGBA8;
- colorType = kRGBA_8888_SkColorType;
-
- GrBackendRenderTarget target(width, height, 0, stencil, info);
-
+ const auto colorSettings = ColorSettings(colorSpace);
+ info.fFormat = colorSettings.pixFormat;
+ GrBackendRenderTarget target(width, height, sampleCnt, stencil, info);
sk_sp<SkSurface> surface(SkSurface::MakeFromBackendRenderTarget(grContext.get(), target,
- kBottomLeft_GrSurfaceOrigin,
- colorType, nullptr, nullptr));
+ kBottomLeft_GrSurfaceOrigin, colorSettings.colorType, colorSpace, nullptr));
return surface;
}
@@ -469,6 +488,76 @@ SkPathOrNull MakePathFromCmds(uintptr_t /* float* */ cptr, int numCmds) {
return emscripten::val(path);
}
+void PathAddVerbsPointsWeights(SkPath& path, uintptr_t /* uint8_t* */ verbsPtr, int numVerbs,
+ uintptr_t /* float* */ ptsPtr, int numPts,
+ uintptr_t /* float* */ wtsPtr, int numWts) {
+ const uint8_t* verbs = reinterpret_cast<const uint8_t*>(verbsPtr);
+ const float* pts = reinterpret_cast<const float*>(ptsPtr);
+ const float* weights = reinterpret_cast<const float*>(wtsPtr);
+
+ #define CHECK_NUM_POINTS(n) \
+ if ((ptIdx + n) > numPts) { \
+ SkDebugf("Not enough points to match the verbs. Saw %d points\n", numPts); \
+ return; \
+ }
+ #define CHECK_NUM_WEIGHTS(n) \
+ if ((wtIdx + n) > numWts) { \
+ SkDebugf("Not enough weights to match the verbs. Saw %d weights\n", numWts); \
+ return; \
+ }
+
+ path.incReserve(numPts);
+ int ptIdx = 0;
+ int wtIdx = 0;
+ for (int v = 0; v < numVerbs; ++v) {
+ switch (verbs[v]) {
+ case MOVE:
+ CHECK_NUM_POINTS(2);
+ path.moveTo(pts[ptIdx], pts[ptIdx+1]);
+ ptIdx += 2;
+ break;
+ case LINE:
+ CHECK_NUM_POINTS(2);
+ path.lineTo(pts[ptIdx], pts[ptIdx+1]);
+ ptIdx += 2;
+ break;
+ case QUAD:
+ CHECK_NUM_POINTS(4);
+ path.quadTo(pts[ptIdx], pts[ptIdx+1], pts[ptIdx+2], pts[ptIdx+3]);
+ ptIdx += 4;
+ break;
+ case CONIC:
+ CHECK_NUM_POINTS(4);
+ CHECK_NUM_WEIGHTS(1);
+ path.conicTo(pts[ptIdx], pts[ptIdx+1], pts[ptIdx+2], pts[ptIdx+3],
+ weights[wtIdx]);
+ ptIdx += 4;
+ wtIdx++;
+ break;
+ case CUBIC:
+ CHECK_NUM_POINTS(6);
+ path.cubicTo(pts[ptIdx ], pts[ptIdx+1],
+ pts[ptIdx+2], pts[ptIdx+3],
+ pts[ptIdx+4], pts[ptIdx+5]);
+ ptIdx += 6;
+ break;
+ case CLOSE:
+ path.close();
+ break;
+ }
+ }
+ #undef CHECK_NUM_POINTS
+ #undef CHECK_NUM_WEIGHTS
+}
+
+SkPath MakePathFromVerbsPointsWeights(uintptr_t /* uint8_t* */ verbsPtr, int numVerbs,
+ uintptr_t ptsPtr, int numPts,
+ uintptr_t wtsPtr, int numWts) {
+ SkPath path;
+ PathAddVerbsPointsWeights(path, verbsPtr, numVerbs, ptsPtr, numPts, wtsPtr, numWts);
+ return path;
+}
+
//========================================================================================
// Path Effects
//========================================================================================
@@ -740,7 +829,6 @@ EMSCRIPTEN_BINDINGS(Skia) {
// Adds a little helper because emscripten doesn't expose default params.
return SkMaskFilter::MakeBlur(style, sigma, respectCTM);
}), allow_raw_pointers());
- function("_MakePathFromCmds", &MakePathFromCmds);
#ifdef SK_INCLUDE_PATHOPS
function("MakePathFromOp", &MakePathFromOp);
#endif
@@ -757,18 +845,33 @@ EMSCRIPTEN_BINDINGS(Skia) {
return SkImage::MakeRasterData(info, pixelData, rowBytes);
}), allow_raw_pointers());
+
+ // Here and in other gradient functions, cPtr is a pointer to an array of data
+ // representing colors. whether this is an array of SkColor or SkColor4f is indicated
+ // by the colorType argument. Only RGBA_8888 and RGBA_F32 are accepted.
function("_MakeLinearGradientShader", optional_override([](SkPoint start, SkPoint end,
- uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
+ uintptr_t cPtr, SkColorType colorType,
+ uintptr_t /* SkScalar* */ pPtr,
int count, SkTileMode mode, uint32_t flags,
- uintptr_t /* SkScalar* */ mPtr)->sk_sp<SkShader> {
+ uintptr_t /* SkScalar* */ mPtr,
+ sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
SkPoint points[] = { start, end };
// See comment above for uintptr_t explanation
- const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
OptionalMatrix localMatrix(mPtr);
- // TODO(nifong): do not assume color space. Support and test wide gamut color gradients
- return SkGradientShader::MakeLinear(points, colors, SkColorSpace::MakeSRGB(), positions, count,
+
+ if (colorType == SkColorType::kRGBA_F32_SkColorType) {
+ const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
+ return SkGradientShader::MakeLinear(points, colors, colorSpace, positions, count,
+ mode, flags, &localMatrix);
+ } else if (colorType == SkColorType::kRGBA_8888_SkColorType) {
+ const SkColor* colors = reinterpret_cast<const SkColor*>(cPtr);
+ return SkGradientShader::MakeLinear(points, colors, positions, count,
mode, flags, &localMatrix);
+ } else {
+ SkDebugf("%d is not an accepted colorType\n", colorType);
+ return nullptr;
+ }
}), allow_raw_pointers());
#ifdef SK_SERIALIZE_SKP
function("_MakeSkPicture", optional_override([](uintptr_t /* unint8_t* */ dPtr,
@@ -781,43 +884,79 @@ EMSCRIPTEN_BINDINGS(Skia) {
}), allow_raw_pointers());
#endif
function("_MakeRadialGradientShader", optional_override([](SkPoint center, SkScalar radius,
- uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
+ uintptr_t cPtr, SkColorType colorType,
+ uintptr_t /* SkScalar* */ pPtr,
int count, SkTileMode mode, uint32_t flags,
- uintptr_t /* SkScalar* */ mPtr)->sk_sp<SkShader> {
+ uintptr_t /* SkScalar* */ mPtr,
+ sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
// See comment above for uintptr_t explanation
- const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
OptionalMatrix localMatrix(mPtr);
- return SkGradientShader::MakeRadial(center, radius, colors, SkColorSpace::MakeSRGB(), positions, count,
- mode, flags, &localMatrix);
+ if (colorType == SkColorType::kRGBA_F32_SkColorType) {
+ const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
+ return SkGradientShader::MakeRadial(center, radius, colors, colorSpace, positions, count,
+ mode, flags, &localMatrix);
+ } else if (colorType == SkColorType::kRGBA_8888_SkColorType) {
+ const SkColor* colors = reinterpret_cast<const SkColor*>(cPtr);
+ return SkGradientShader::MakeRadial(center, radius, colors, positions, count,
+ mode, flags, &localMatrix);
+ } else {
+ SkDebugf("%d is not an accepted colorType\n", colorType);
+ return nullptr;
+ }
}), allow_raw_pointers());
function("_MakeSweepGradientShader", optional_override([](SkScalar cx, SkScalar cy,
- uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
+ uintptr_t cPtr, SkColorType colorType,
+ uintptr_t /* SkScalar* */ pPtr,
int count, SkTileMode mode,
SkScalar startAngle, SkScalar endAngle,
uint32_t flags,
- uintptr_t /* SkScalar* */ mPtr)->sk_sp<SkShader> {
+ uintptr_t /* SkScalar* */ mPtr,
+ sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
// See comment above for uintptr_t explanation
- const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
OptionalMatrix localMatrix(mPtr);
- return SkGradientShader::MakeSweep(cx, cy, colors, SkColorSpace::MakeSRGB(), positions, count,
- mode, startAngle, endAngle, flags,
- &localMatrix);
+ if (colorType == SkColorType::kRGBA_F32_SkColorType) {
+ const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
+ return SkGradientShader::MakeSweep(cx, cy, colors, colorSpace, positions, count,
+ mode, startAngle, endAngle, flags,
+ &localMatrix);
+ } else if (colorType == SkColorType::kRGBA_8888_SkColorType) {
+ const SkColor* colors = reinterpret_cast<const SkColor*>(cPtr);
+ return SkGradientShader::MakeSweep(cx, cy, colors, positions, count,
+ mode, startAngle, endAngle, flags,
+ &localMatrix);
+ } else {
+ SkDebugf("%d is not an accepted colorType\n", colorType);
+ return nullptr;
+ }
}), allow_raw_pointers());
function("_MakeTwoPointConicalGradientShader", optional_override([](
SkPoint start, SkScalar startRadius,
SkPoint end, SkScalar endRadius,
- uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
+ uintptr_t cPtr, SkColorType colorType,
+ uintptr_t /* SkScalar* */ pPtr,
int count, SkTileMode mode, uint32_t flags,
- uintptr_t /* SkScalar* */ mPtr)->sk_sp<SkShader> {
+ uintptr_t /* SkScalar* */ mPtr,
+ sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
// See comment above for uintptr_t explanation
- const SkColor4f* colors = reinterpret_cast<const SkColor4f*> (cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
OptionalMatrix localMatrix(mPtr);
- return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius,
- colors, SkColorSpace::MakeSRGB(), positions, count, mode,
- flags, &localMatrix);
+
+ if (colorType == SkColorType::kRGBA_F32_SkColorType) {
+ const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
+ return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius,
+ colors, colorSpace, positions, count, mode,
+ flags, &localMatrix);
+ } else if (colorType == SkColorType::kRGBA_8888_SkColorType) {
+ const SkColor* colors = reinterpret_cast<const SkColor*>(cPtr);
+ return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius,
+ colors, positions, count, mode,
+ flags, &localMatrix);
+ } else {
+ SkDebugf("%d is not an accepted colorType\n", colorType);
+ return nullptr;
+ }
}), allow_raw_pointers());
#ifdef SK_GL
@@ -861,7 +1000,7 @@ EMSCRIPTEN_BINDINGS(Skia) {
class_<SkCanvas>("SkCanvas")
.constructor<>()
.function("_clear", optional_override([](SkCanvas& self, uintptr_t /* float* */ cPtr) {
- self.clear(ptrToSkColor4f(cPtr).toSkColor());
+ self.clear(ptrToSkColor4f(cPtr));
}))
.function("clipPath", select_overload<void (const SkPath&, SkClipOp, bool)>(&SkCanvas::clipPath))
.function("clipRRect", optional_override([](SkCanvas& self, const SimpleRRect& r, SkClipOp op, bool doAntiAlias) {
@@ -876,9 +1015,7 @@ EMSCRIPTEN_BINDINGS(Skia) {
self.concat(m);
}))
.function("drawArc", &SkCanvas::drawArc)
- // _drawAtlas takes an SkColor, unlike most private functions handling color.
- // This is because it takes an array of colors. Converting it on the Javascript side allows
- // an allocation to be avoided here.
+ // _drawAtlas takes an array of SkColor. There is no SkColor4f override.
.function("_drawAtlas", optional_override([](SkCanvas& self,
const sk_sp<SkImage>& atlas, uintptr_t /* SkRSXform* */ xptr,
uintptr_t /* SkRect* */ rptr, uintptr_t /* SkColor* */ cptr, int count,
@@ -894,10 +1031,16 @@ EMSCRIPTEN_BINDINGS(Skia) {
}), allow_raw_pointers())
.function("drawCircle", select_overload<void (SkScalar, SkScalar, SkScalar, const SkPaint& paint)>(&SkCanvas::drawCircle))
.function("_drawColor", optional_override([](SkCanvas& self, uintptr_t /* float* */ cPtr) {
- self.drawColor(ptrToSkColor4f(cPtr).toSkColor());
+ self.drawColor(ptrToSkColor4f(cPtr));
}))
.function("_drawColor", optional_override([](SkCanvas& self, uintptr_t /* float* */ cPtr, SkBlendMode mode) {
- self.drawColor(ptrToSkColor4f(cPtr).toSkColor(), mode);
+ self.drawColor(ptrToSkColor4f(cPtr), mode);
+ }))
+ .function("drawColorInt", optional_override([](SkCanvas& self, SkColor color) {
+ self.drawColor(color);
+ }))
+ .function("drawColorInt", optional_override([](SkCanvas& self, SkColor color, SkBlendMode mode) {
+ self.drawColor(color, mode);
}))
.function("drawDRRect",optional_override([](SkCanvas& self, const SimpleRRect& o, const SimpleRRect& i, const SkPaint& paint) {
self.drawDRRect(toRRect(o), toRRect(i), paint);
@@ -1257,8 +1400,16 @@ EMSCRIPTEN_BINDINGS(Skia) {
.function("setAntiAlias", &SkPaint::setAntiAlias)
.function("setAlphaf", &SkPaint::setAlphaf)
.function("setBlendMode", &SkPaint::setBlendMode)
- .function("_setColor", optional_override([](SkPaint& self, uintptr_t /* float* */ cPtr) {
- self.setColor(ptrToSkColor4f(cPtr));
+ .function("_setColor", optional_override([](SkPaint& self, uintptr_t /* float* */ cPtr,
+ sk_sp<SkColorSpace> colorSpace) {
+ self.setColor(ptrToSkColor4f(cPtr), colorSpace.get());
+ }))
+ .function("setColorInt", optional_override([](SkPaint& self, SkColor color) {
+ self.setColor(SkColor4f::FromColor(color), nullptr);
+ }))
+ .function("setColorInt", optional_override([](SkPaint& self, SkColor color,
+ sk_sp<SkColorSpace> colorSpace) {
+ self.setColor(SkColor4f::FromColor(color), colorSpace.get());
}))
.function("setColorFilter", &SkPaint::setColorFilter)
.function("setFilterQuality", &SkPaint::setFilterQuality)
@@ -1272,6 +1423,21 @@ EMSCRIPTEN_BINDINGS(Skia) {
.function("setStrokeWidth", &SkPaint::setStrokeWidth)
.function("setStyle", &SkPaint::setStyle);
+ class_<SkColorSpace>("SkColorSpace")
+ .smart_ptr<sk_sp<SkColorSpace>>("sk_sp<SkColorSpace>")
+ .class_function("Equals", optional_override([](sk_sp<SkColorSpace> a, sk_sp<SkColorSpace> b)->bool {
+ return SkColorSpace::Equals(a.get(), b.get());
+ }))
+ // These are private because they are to be called once in interface.js to
+ // avoid clients having to delete the returned objects.
+ .class_function("_MakeSRGB", &SkColorSpace::MakeSRGB)
+ .class_function("_MakeDisplayP3", optional_override([]()->sk_sp<SkColorSpace> {
+ return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDisplayP3);
+ }))
+ .class_function("_MakeAdobeRGB", optional_override([]()->sk_sp<SkColorSpace> {
+ return SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, SkNamedGamut::kAdobeRGB);
+ }));
+
class_<SkPathEffect>("SkPathEffect")
.smart_ptr<sk_sp<SkPathEffect>>("sk_sp<SkPathEffect>")
.class_function("MakeCorner", &SkCornerPathEffect::Make)
@@ -1286,6 +1452,8 @@ EMSCRIPTEN_BINDINGS(Skia) {
class_<SkPath>("SkPath")
.constructor<>()
.constructor<const SkPath&>()
+ .class_function("_MakeFromCmds", &MakePathFromCmds)
+ .class_function("_MakeFromVerbsPointsWeights", &MakePathFromVerbsPointsWeights)
.function("_addArc", &ApplyAddArc)
// interface.js has 3 overloads of addPath
.function("_addOval", &ApplyAddOval)
@@ -1301,6 +1469,7 @@ EMSCRIPTEN_BINDINGS(Skia) {
.function("_addRect", &ApplyAddRect)
// interface.js has 4 overloads of addRoundRect
.function("_addRoundRect", &ApplyAddRoundRect)
+ .function("_addVerbsPointsWeights", &PathAddVerbsPointsWeights)
.function("_arcTo", &ApplyArcTo)
.function("_arcTo", &ApplyArcToAngle)
.function("_arcTo", &ApplyArcToArcSize)
@@ -1405,8 +1574,8 @@ EMSCRIPTEN_BINDINGS(Skia) {
.smart_ptr<sk_sp<SkShader>>("sk_sp<SkShader>")
.class_function("Blend", select_overload<sk_sp<SkShader>(SkBlendMode, sk_sp<SkShader>, sk_sp<SkShader>)>(&SkShaders::Blend))
.class_function("_Color",
- optional_override([](uintptr_t /* float* */ cPtr)->sk_sp<SkShader> {
- return SkShaders::Color(ptrToSkColor4f(cPtr), SkColorSpace::MakeSRGB());
+ optional_override([](uintptr_t /* float* */ cPtr, sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
+ return SkShaders::Color(ptrToSkColor4f(cPtr), colorSpace);
})
)
.class_function("Lerp", select_overload<sk_sp<SkShader>(float, sk_sp<SkShader>, sk_sp<SkShader>)>(&SkShaders::Lerp));
@@ -1455,18 +1624,32 @@ EMSCRIPTEN_BINDINGS(Skia) {
class_<SkSurface>("SkSurface")
.smart_ptr<sk_sp<SkSurface>>("sk_sp<SkSurface>")
- .function("_flush", select_overload<void()>(&SkSurface::flush))
+ .function("_flush", select_overload<void()>(&SkSurface::flushAndSubmit))
.function("getCanvas", &SkSurface::getCanvas, allow_raw_pointers())
+ .function("imageInfo", optional_override([](SkSurface& self)->SimpleImageInfo {
+ const auto& ii = self.imageInfo();
+ return {ii.width(), ii.height(), ii.colorType(), ii.alphaType(), ii.refColorSpace()};
+ }))
.function("height", &SkSurface::height)
.function("makeImageSnapshot", select_overload<sk_sp<SkImage>()>(&SkSurface::makeImageSnapshot))
.function("makeImageSnapshot", select_overload<sk_sp<SkImage>(const SkIRect& bounds)>(&SkSurface::makeImageSnapshot))
.function("makeSurface", optional_override([](SkSurface& self, SimpleImageInfo sii)->sk_sp<SkSurface> {
return self.makeSurface(toSkImageInfo(sii));
}), allow_raw_pointers())
- .function("width", &SkSurface::width)
+#ifdef SK_GL
.function("reportBackendType", optional_override([](SkSurface& self)->std::string {
return self.getCanvas()->getGrContext() == nullptr ? "CPU" : "GPU";
- }));
+ }))
+ .function("sampleCnt", optional_override([](SkSurface& self)->int {
+ auto backendRT = self.getBackendRenderTarget(SkSurface::kFlushRead_BackendHandleAccess);
+ return (backendRT.isValid()) ? backendRT.sampleCnt() : 0;
+ }))
+#else
+ .function("reportBackendType", optional_override([](SkSurface& self)->std::string {
+ return "CPU";
+ }))
+#endif
+ .function("width", &SkSurface::width);
#ifndef SK_NO_FONTS
class_<SkTextBlob>("SkTextBlob")
@@ -1654,7 +1837,6 @@ EMSCRIPTEN_BINDINGS(Skia) {
.value("TrianglesStrip", SkVertices::VertexMode::kTriangleStrip_VertexMode)
.value("TriangleFan", SkVertices::VertexMode::kTriangleFan_VertexMode);
-
// A value object is much simpler than a class - it is returned as a JS
// object and does not require delete().
// https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#value-types
@@ -1690,10 +1872,11 @@ EMSCRIPTEN_BINDINGS(Skia) {
.field("fBottom", &SkIRect::fBottom);
value_object<SimpleImageInfo>("SkImageInfo")
- .field("width", &SimpleImageInfo::width)
- .field("height", &SimpleImageInfo::height)
- .field("colorType", &SimpleImageInfo::colorType)
- .field("alphaType", &SimpleImageInfo::alphaType);
+ .field("width", &SimpleImageInfo::width)
+ .field("height", &SimpleImageInfo::height)
+ .field("colorType", &SimpleImageInfo::colorType)
+ .field("alphaType", &SimpleImageInfo::alphaType)
+ .field("colorSpace", &SimpleImageInfo::colorSpace);
// SkPoints can be represented by [x, y]
value_array<SkPoint>("SkPoint")
diff --git a/chromium/third_party/skia/modules/canvaskit/compile.sh b/chromium/third_party/skia/modules/canvaskit/compile.sh
index 93734dc3fc0..bc880df3881 100755
--- a/chromium/third_party/skia/modules/canvaskit/compile.sh
+++ b/chromium/third_party/skia/modules/canvaskit/compile.sh
@@ -72,8 +72,6 @@ SKP_JS="--pre-js $BASE_DIR/skp.js"
GN_SKP_FLAGS=""
WASM_SKP="-DSK_SERIALIZE_SKP"
if [[ $@ == *no_skp* ]]; then
- GN_SKP_FLAGS="\"-DSK_DISABLE_READBUFFER\","
- WASM_SKP="-DSK_DISABLE_READBUFFER"
SKP_JS=""
fi
@@ -90,11 +88,13 @@ if [[ $@ == *no_skottie* ]]; then
SKOTTIE_BINDINGS=""
fi
+GN_VIEWER="skia_use_expat=false skia_enable_ccpr=false"
VIEWER_BINDINGS=""
VIEWER_LIB=""
if [[ $@ == *viewer* ]]; then
echo "Including viewer"
+ GN_VIEWER="skia_use_expat=true skia_enable_ccpr=true"
VIEWER_BINDINGS="$BASE_DIR/viewer_bindings.cpp"
VIEWER_LIB="$BUILD_DIR/libviewer_wasm.a"
IS_OFFICIAL_BUILD="false"
@@ -156,20 +156,18 @@ if [[ $@ == *no_canvas* ]]; then
HTML_CANVAS_API=""
fi
-GN_FONT="skia_enable_fontmgr_empty=false skia_enable_fontmgr_custom_empty=false"
+GN_FONT="skia_enable_fontmgr_custom_directory=false "
FONT_CFLAGS=""
-BUILTIN_FONT="$BASE_DIR/fonts/NotoMono-Regular.ttf.cpp"
+BUILTIN_FONT=""
FONT_JS="--pre-js $BASE_DIR/font.js"
if [[ $@ == *no_font* ]]; then
echo "Omitting the built-in font(s), font manager and all code dealing with fonts"
- BUILTIN_FONT=""
FONT_CFLAGS="-DSK_NO_FONTS"
FONT_JS=""
- GN_FONT="skia_enable_fontmgr_empty=true skia_enable_fontmgr_custom_empty=false"
+ GN_FONT+="skia_enable_fontmgr_custom_embedded=false skia_enable_fontmgr_custom_empty=false"
elif [[ $@ == *no_embedded_font* ]]; then
echo "Omitting the built-in font(s)"
- BUILTIN_FONT=""
- GN_FONT="skia_enable_fontmgr_empty=false skia_enable_fontmgr_custom_empty=true"
+ GN_FONT+="skia_enable_fontmgr_custom_embedded=false skia_enable_fontmgr_custom_empty=true"
else
# Generate the font's binary file (which is covered by .gitignore)
python tools/embed_resources.py \
@@ -177,10 +175,12 @@ else
--input $BASE_DIR/fonts/NotoMono-Regular.ttf \
--output $BASE_DIR/fonts/NotoMono-Regular.ttf.cpp \
--align 4
+ BUILTIN_FONT="$BASE_DIR/fonts/NotoMono-Regular.ttf.cpp"
+ GN_FONT+="skia_enable_fontmgr_custom_embedded=true skia_enable_fontmgr_custom_empty=false"
fi
if [[ $@ == *no_alias_font* ]]; then
-EXTRA_CFLAGS+=" -DCANVASKIT_NO_ALIAS_FONT"
+EXTRA_CFLAGS+=" \"-DCANVASKIT_NO_ALIAS_FONT\""
FONT_CFLAGS+=" -DCANVASKIT_NO_ALIAS_FONT"
fi
@@ -268,7 +268,6 @@ echo "Compiling bitcode"
skia_use_angle=false \
skia_use_dng_sdk=false \
skia_use_egl=true \
- skia_use_expat=false \
skia_use_fontconfig=false \
skia_use_freetype=true \
skia_use_libheif=false \
@@ -293,9 +292,9 @@ echo "Compiling bitcode"
${GN_GPU} \
${GN_FONT} \
${GN_PARTICLES} \
+ ${GN_VIEWER} \
\
skia_enable_skshaper=true \
- skia_enable_ccpr=false \
skia_enable_nvpr=false \
skia_enable_skparagraph=true \
skia_enable_pdf=false"
@@ -331,6 +330,7 @@ ${EMCXX} \
$FONT_CFLAGS \
-std=c++17 \
--bind \
+ --no-entry \
--pre-js $BASE_DIR/preamble.js \
--pre-js $BASE_DIR/helper.js \
--pre-js $BASE_DIR/interface.js \
@@ -343,7 +343,6 @@ ${EMCXX} \
$RT_SHADER_JS \
$HTML_CANVAS_API \
--pre-js $BASE_DIR/postamble.js \
- --post-js $BASE_DIR/ready.js \
$BASE_DIR/canvaskit_bindings.cpp \
$PARTICLES_BINDINGS \
$SKOTTIE_BINDINGS \
@@ -365,7 +364,7 @@ ${EMCXX} \
-s MODULARIZE=1 \
-s NO_EXIT_RUNTIME=1 \
-s STRICT=1 \
- -s TOTAL_MEMORY=128MB \
+ -s INITIAL_MEMORY=128MB \
-s WARN_UNALIGNED=1 \
-s WASM=1 \
-o $BUILD_DIR/canvaskit.js
diff --git a/chromium/third_party/skia/modules/canvaskit/cpu.js b/chromium/third_party/skia/modules/canvaskit/cpu.js
index d2e543cd552..229a6c7355a 100644
--- a/chromium/third_party/skia/modules/canvaskit/cpu.js
+++ b/chromium/third_party/skia/modules/canvaskit/cpu.js
@@ -1,5 +1,7 @@
// Adds compile-time JS functions to augment the CanvasKit interface.
-// Specifically, anything that should only be on the CPU version of canvaskit.
+// Implementations in this file are considerate of GPU builds, i.e. some
+// behavior is predicated on whether or not this is being compiled alongside
+// gpu.js.
(function(CanvasKit){
CanvasKit._extraInitializations = CanvasKit._extraInitializations || [];
CanvasKit._extraInitializations.push(function() {
@@ -7,6 +9,7 @@
CanvasKit.MakeSWCanvasSurface = function(idOrElement) {
var canvas = idOrElement;
if (canvas.tagName !== 'CANVAS') {
+ // TODO(nifong): unit test
canvas = document.getElementById(idOrElement);
if (!canvas) {
throw 'Canvas with id ' + idOrElement + ' was not found';
@@ -26,6 +29,10 @@
CanvasKit.MakeCanvasSurface = CanvasKit.MakeSWCanvasSurface;
}
+ // Note that color spaces are currently not supported in CPU surfaces. due to the limitation
+ // canvas.getContext('2d').putImageData imposes a limitatin of using an RGBA_8888 color type.
+ // TODO(nifong): support WGC color spaces while still using an RGBA_8888 color type when
+ // on a cpu backend.
CanvasKit.MakeSurface = function(width, height) {
/* @dict */
var imageInfo = {
@@ -35,6 +42,7 @@
// Since we are sending these pixels directly into the HTML canvas,
// (and those pixels are un-premultiplied, i.e. straight r,g,b,a)
'alphaType': CanvasKit.AlphaType.Unpremul,
+ 'colorSpace': CanvasKit.SkColorSpace.SRGB,
}
var pixelLen = width * height * 4; // it's 8888, so 4 bytes per pixel
// Allocate the buffer of pixels to be drawn into.
@@ -55,7 +63,9 @@
return surface;
};
- CanvasKit.SkSurface.prototype.flush = function() {
+ // For GPU builds, simply proxies to native code flush. For CPU builds,
+ // also updates the underlying HTML canvas, optionally with dirtyRect.
+ CanvasKit.SkSurface.prototype.flush = function(dirtyRect) {
this._flush();
// Do we have an HTML canvas to write the pixels to?
// We will not if this a GPU build or a raster surface, for example.
@@ -63,7 +73,14 @@
var pixels = new Uint8ClampedArray(CanvasKit.HEAPU8.buffer, this._pixelPtr, this._pixelLen);
var imageData = new ImageData(pixels, this._width, this._height);
- this._canvas.getContext('2d').putImageData(imageData, 0, 0);
+ if (!dirtyRect) {
+ this._canvas.getContext('2d').putImageData(imageData, 0, 0);
+ } else {
+ this._canvas.getContext('2d').putImageData(imageData, 0, 0,
+ dirtyRect.fLeft, dirtyRect.fTop,
+ dirtyRect.fRight - dirtyRect.fLeft,
+ dirtyRect.fBottom - dirtyRect.fTop);
+ }
}
};
diff --git a/chromium/third_party/skia/modules/canvaskit/externs.js b/chromium/third_party/skia/modules/canvaskit/externs.js
index 7b62777927c..81a3778a707 100644
--- a/chromium/third_party/skia/modules/canvaskit/externs.js
+++ b/chromium/third_party/skia/modules/canvaskit/externs.js
@@ -26,6 +26,7 @@ var CanvasKit = {
// public API (i.e. things we declare in the pre-js file or in the cpp bindings)
Color: function() {},
Color4f: function() {},
+ ColorAsInt: function() {},
/** @return {CanvasKit.SkRect} */
LTRBRect: function() {},
/** @return {CanvasKit.SkRect} */
@@ -46,6 +47,7 @@ var CanvasKit = {
MakeImage: function() {},
/** @return {CanvasKit.SkImage} */
MakeImageFromEncoded: function() {},
+ MakeImageFromCanvasImageSource: function() {},
MakeOnScreenGLSurface: function() {},
MakePathFromCmds: function() {},
MakePathFromOp: function() {},
@@ -60,6 +62,7 @@ var CanvasKit = {
MakeWebGLCanvasSurface: function() {},
/** @return {TypedArray} */
Malloc: function() {},
+ Free: function() {},
computeTonalColors: function() {},
currentContext: function() {},
getColorComponents: function() {},
@@ -71,12 +74,14 @@ var CanvasKit = {
setCurrentContext: function() {},
setDecodeCacheLimitBytes: function() {},
+ // Defined by emscripten.
+ createContext:function() {},
+
// private API (i.e. things declared in the bindings that we use
// in the pre-js file)
_computeTonalColors: function() {},
_MakeImage: function() {},
_MakeLinearGradientShader: function() {},
- _MakePathFromCmds: function() {},
_MakeRadialGradientShader: function() {},
_MakeSweepGradientShader: function() {},
_MakeManagedAnimation: function() {},
@@ -181,6 +186,7 @@ var CanvasKit = {
drawAnimatedImage: function() {},
drawArc: function() {},
drawCircle: function() {},
+ drawColorInt: function() {},
drawDRRect: function() {},
drawImage: function() {},
drawImageNine: function() {},
@@ -214,6 +220,7 @@ var CanvasKit = {
prototype: {
clear: function() {},
drawColor: function() {},
+ drawColorComponents: function() {},
drawShadow: function() {},
},
@@ -256,6 +263,17 @@ var CanvasKit = {
scaled: function() {},
},
+ SkColorSpace: {
+ Equals: function() {},
+ SRGB: {},
+ DISPLAY_P3: {},
+ ADOBE_RGB: {},
+ // private API (from C++ bindings)
+ _MakeSRGB: function() {},
+ _MakeDisplayP3: function() {},
+ _MakeAdobeRGB: function() {},
+ },
+
SkContourMeasureIter: {
next: function() {},
},
@@ -360,6 +378,7 @@ var CanvasKit = {
getStrokeWidth: function() {},
setAntiAlias: function() {},
setBlendMode: function() {},
+ setColorInt: function() {},
setFilterQuality: function() {},
setImageFilter: function() {},
setMaskFilter: function() {},
@@ -373,6 +392,8 @@ var CanvasKit = {
prototype: {
setColor: function() {},
+ setColorComponents: function() {},
+ setColorInt: function() {},
},
// Private API
@@ -412,7 +433,9 @@ var CanvasKit = {
},
SkPath: {
- // public API (from C++ bindings)
+ // public API (from C++ and JS bindings)
+ MakeFromCmds: function() {},
+ MakeFromVerbsPointsWeights: function() {},
computeTightBounds: function() {},
contains: function() {},
/** @return {CanvasKit.SkPath} */
@@ -428,15 +451,19 @@ var CanvasKit = {
rewind: function() {},
setFillType: function() {},
setIsVolatile: function() {},
+ toCmds: function() {},
toSVGString: function() {},
// private API
+ _MakeFromCmds: function() {},
+ _MakeFromVerbsPointsWeights: function() {},
_addArc: function() {},
_addOval: function() {},
_addPath: function() {},
_addRect: function() {},
_addPoly: function() {},
_addRoundRect: function() {},
+ _addVerbsPointsWeights: function() {},
_arc: function() {},
_arcTo: function() {},
_close: function() {},
@@ -517,9 +544,11 @@ var CanvasKit = {
// public API (from C++ bindings)
/** @return {CanvasKit.SkCanvas} */
getCanvas: function() {},
+ imageInfo: function() {},
/** @return {CanvasKit.SkImage} */
makeImageSnapshot: function() {},
makeSurface: function() {},
+ sampleCnt: function() {},
reportBackendType: function() {},
grContext: {},
@@ -846,6 +875,7 @@ CanvasKit.SkPath.prototype.addPath = function() {};
CanvasKit.SkPath.prototype.addPoly = function() {};
CanvasKit.SkPath.prototype.addRect = function() {};
CanvasKit.SkPath.prototype.addRoundRect = function() {};
+CanvasKit.SkPath.prototype.addVerbsPointsWeights = function() {};
CanvasKit.SkPath.prototype.arc = function() {};
CanvasKit.SkPath.prototype.arcTo = function() {};
CanvasKit.SkPath.prototype.close = function() {};
@@ -930,6 +960,9 @@ HTMLCanvas.prototype.loadFont = function() {};
HTMLCanvas.prototype.makePath2D = function() {};
HTMLCanvas.prototype.toDataURL = function() {};
+var ImageBitmapRenderingContext = {};
+ImageBitmapRenderingContext.prototype.transferFromImageBitmap = function() {};
+
var CanvasRenderingContext2D = {};
CanvasRenderingContext2D.prototype.addHitRegion = function() {};
CanvasRenderingContext2D.prototype.arc = function() {};
diff --git a/chromium/third_party/skia/modules/canvaskit/font.js b/chromium/third_party/skia/modules/canvaskit/font.js
index eb127bf8c27..845a8c2f032 100644
--- a/chromium/third_party/skia/modules/canvaskit/font.js
+++ b/chromium/third_party/skia/modules/canvaskit/font.js
@@ -65,13 +65,13 @@ CanvasKit._extraInitializations.push(function() {
var sizes = [];
for (var i = 0; i < fonts.length; i++) {
var data = new Uint8Array(fonts[i]);
- var dptr = copy1dArray(data, CanvasKit.HEAPU8);
+ var dptr = copy1dArray(data, "HEAPU8");
dPtrs.push(dptr);
sizes.push(data.byteLength);
}
// Pointers are 32 bit unsigned ints
- var datasPtr = copy1dArray(dPtrs, CanvasKit.HEAPU32);
- var sizesPtr = copy1dArray(sizes, CanvasKit.HEAPU32);
+ var datasPtr = copy1dArray(dPtrs, "HEAPU32");
+ var sizesPtr = copy1dArray(sizes, "HEAPU32");
var fm = CanvasKit.SkFontMgr._fromData(datasPtr, sizesPtr, fonts.length);
// The SkFontMgr has taken ownership of the bytes we allocated in the for loop.
CanvasKit._free(datasPtr);
@@ -83,7 +83,7 @@ CanvasKit._extraInitializations.push(function() {
CanvasKit.SkFontMgr.prototype.MakeTypefaceFromData = function(fontData) {
var data = new Uint8Array(fontData);
- var fptr = copy1dArray(data, CanvasKit.HEAPU8);
+ var fptr = copy1dArray(data, "HEAPU8");
var font = this._makeTypefaceFromData(fptr, data.byteLength);
if (!font) {
SkDebug('Could not decode font data');
diff --git a/chromium/third_party/skia/modules/canvaskit/future_apis/ImageDecoder.md b/chromium/third_party/skia/modules/canvaskit/future_apis/ImageDecoder.md
new file mode 100644
index 00000000000..a8092de5646
--- /dev/null
+++ b/chromium/third_party/skia/modules/canvaskit/future_apis/ImageDecoder.md
@@ -0,0 +1,62 @@
+# ImageDecoder API
+
+Date Updated: June 16, 2020
+
+## Summary and Links
+
+The [ImageDecoder API](https://github.com/dalecurtis/image-decoder-api/blob/master/explainer.md)
+handles decoding of both still and animated images.
+Similar to the larger [web codecs](https://github.com/WICG/web-codecs/blob/master/explainer.md)
+proposal which is focused more on video and audio.
+The ImageDecoder API could be used with `CanvasKit.MakeImageFromCanvasImageSource`
+for creating CanvasKit compatible `SkImage`s.
+For still images, the `createImageBitmap(blob)` API achieves the same result.
+
+- [Explainer](https://github.com/dalecurtis/image-decoder-api/blob/master/explainer.md)
+- [Prototype](https://chromium-review.googlesource.com/c/chromium/src/+/2145133)
+- [Discourse](https://discourse.wicg.io/t/proposal-imagedecoder-api-extension-for-webcodecs/4418)
+
+Currently available as a prototype behind the `--enable-blink-features=WebCodecs` flag
+in Chrome Canary, works in version 85.0.4175.0.
+
+## Running the prototype
+
+1. Download and install [Chrome Canary](https://www.google.com/chrome/canary/). Verify that you
+have version 85.0.4175.0 or later.
+2. Close ALL open instances of chromium browsers, including chrome.
+2. Run Chrome Canary with the `--enable-blink-features=WebCodecs` flag.
+
+**MacOS**: Run `/applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary --enable-blink-features=WebCodecs`
+
+**Windows, Linux**: [https://www.chromium.org/developers/how-tos/run-chromium-with-flags](https://www.chromium.org/developers/how-tos/run-chromium-with-flags)
+
+3. Navigate to: [http://storage.googleapis.com/dalecurtis/test-gif.html?src=giphy.gif](http://storage.googleapis.com/dalecurtis/test-gif.html?src=giphy.gif)
+4. You should see a cute animated cat illustration.
+
+## Example API Usage with CanvasKit
+
+With a still image:
+```jsx
+const response = await fetch(stillImageUrl); // e.g. png or jpeg
+const data = await response.arrayBuffer();
+
+const imageDecoder = new ImageDecoder({ data });
+const imageBitmap = await imageDecoder.decode();
+
+const skImage = CanvasKit.MakeImageFromCanvasImageSource(imageBitmap);
+// do something with skImage, such as drawing it
+```
+
+With an animated image:
+```jsx
+const response = await fetch(animatedImageUrl); // e.g. gif or mjpeg
+const data = await response.arrayBuffer();
+
+const imageDecoder = new ImageDecoder({ data });
+
+for (let frame = 0; frame < imageDecoder.frameCount; frame++) {
+ const imageBitmap = await imageDecoder.decode(frame);
+ const skImage = CanvasKit.MakeImageFromCanvasImageSource(imageBitmap);
+ // do something with skImage, such as drawing it
+}
+```
diff --git a/chromium/third_party/skia/modules/canvaskit/future_apis/WebGPU.md b/chromium/third_party/skia/modules/canvaskit/future_apis/WebGPU.md
new file mode 100644
index 00000000000..f141f05c8a8
--- /dev/null
+++ b/chromium/third_party/skia/modules/canvaskit/future_apis/WebGPU.md
@@ -0,0 +1,17 @@
+# WebGPU API
+
+Date Updated: June 16, 2020
+
+## Summary and Links
+
+WebGPU exposes an API for performing operations, such as rendering and computation,
+on a Graphics Processing Unit. [Dawn](https://dawn.googlesource.com/dawn) is the underlying
+implementation of WebGPU in chromium. In the future, with
+[WebGPU bindings provided by emscripten](https://github.com/emscripten-core/emscripten/pull/10218),
+CanvasKit should be able to use a WebGPU rendering device.
+
+- [W.I.P. Specification](https://gpuweb.github.io/gpuweb/)
+- [WebGPU Samples](https://austineng.github.io/webgpu-samples/)
+- [Implementation Status](https://github.com/gpuweb/gpuweb/wiki/Implementation-Status)
+
+Some features are currently available in Chrome Canary behind the `--enable-unsafe-webgpu` flag.
diff --git a/chromium/third_party/skia/modules/canvaskit/gpu.js b/chromium/third_party/skia/modules/canvaskit/gpu.js
index adfc7a172b2..20b5553fa20 100644
--- a/chromium/third_party/skia/modules/canvaskit/gpu.js
+++ b/chromium/third_party/skia/modules/canvaskit/gpu.js
@@ -1,5 +1,6 @@
// Adds compile-time JS functions to augment the CanvasKit interface.
// Specifically, anything that should only be on the GPU version of canvaskit.
+// Functions in this file are supplemented by cpu.js.
(function(CanvasKit){
CanvasKit._extraInitializations = CanvasKit._extraInitializations || [];
CanvasKit._extraInitializations.push(function() {
@@ -10,89 +11,69 @@
return defaultValue;
}
- function makeWebGLContext(canvas, attrs) {
- var contextAttributes = {
- alpha: get(attrs, 'alpha', 1),
- depth: get(attrs, 'depth', 1),
- stencil: get(attrs, 'stencil', 8),
- antialias: get(attrs, 'antialias', 1),
- premultipliedAlpha: get(attrs, 'premultipliedAlpha', 1),
- preserveDrawingBuffer: get(attrs, 'preserveDrawingBuffer', 0),
- preferLowPowerToHighPerformance: get(attrs, 'preferLowPowerToHighPerformance', 0),
- failIfMajorPerformanceCaveat: get(attrs, 'failIfMajorPerformanceCaveat', 0),
- majorVersion: get(attrs, 'majorVersion', 2),
- minorVersion: get(attrs, 'minorVersion', 0),
- enableExtensionsByDefault: get(attrs, 'enableExtensionsByDefault', 1),
- explicitSwapControl: get(attrs, 'explicitSwapControl', 0),
- renderViaOffscreenBackBuffer: get(attrs, 'renderViaOffscreenBackBuffer', 0),
- };
+ CanvasKit.makeWebGLContextAsCurrent = function(canvas, attrs) {
if (!canvas) {
- SkDebug('null canvas passed into makeWebGLContext');
- return 0;
+ throw 'null canvas passed into makeWebGLContext';
}
+ var contextAttributes = {
+ 'alpha': get(attrs, 'alpha', 1),
+ 'depth': get(attrs, 'depth', 1),
+ 'stencil': get(attrs, 'stencil', 8),
+ 'antialias': get(attrs, 'antialias', 0),
+ 'premultipliedAlpha': get(attrs, 'premultipliedAlpha', 1),
+ 'preserveDrawingBuffer': get(attrs, 'preserveDrawingBuffer', 0),
+ 'preferLowPowerToHighPerformance': get(attrs, 'preferLowPowerToHighPerformance', 0),
+ 'failIfMajorPerformanceCaveat': get(attrs, 'failIfMajorPerformanceCaveat', 0),
+ 'enableExtensionsByDefault': get(attrs, 'enableExtensionsByDefault', 1),
+ 'explicitSwapControl': get(attrs, 'explicitSwapControl', 0),
+ 'renderViaOffscreenBackBuffer': get(attrs, 'renderViaOffscreenBackBuffer', 0),
+ };
+
// This check is from the emscripten version
if (contextAttributes['explicitSwapControl']) {
- SkDebug('explicitSwapControl is not supported');
- return 0;
+ throw 'explicitSwapControl is not supported';
}
- // GL is an enscripten provided helper
- // See https://github.com/emscripten-core/emscripten/blob/incoming/src/library_webgl.js
- return GL.createContext(canvas, contextAttributes);
+ // Creates a WebGL context and sets it to be the current context.
+ this.createContext(canvas, true, true, contextAttributes);
}
CanvasKit.GetWebGLContext = function(canvas, attrs) {
- return makeWebGLContext(canvas, attrs);
+ this.makeWebGLContextAsCurrent(canvas, attrs);
+ return CanvasKit.currentContext() || 0;
};
- // arg can be of types:
+ // idOrElement can be of types:
// - String - in which case it is interpreted as an id of a
// canvas element.
// - HTMLCanvasElement - in which the provided canvas element will
// be used directly.
- // Width and height can be provided to override those on the canvas
- // element, or specify a height for when a context is provided.
- CanvasKit.MakeWebGLCanvasSurface = function(arg, width, height, webGLVersion) {
- var canvas = arg;
+ // colorSpace - sk_sp<SkColorSpace> - one of the supported color spaces:
+ // CanvasKit.SkColorSpace.SRGB
+ // CanvasKit.SkColorSpace.DISPLAY_P3
+ // CanvasKit.SkColorSpace.ADOBE_RGB
+ CanvasKit.MakeWebGLCanvasSurface = function(idOrElement, colorSpace) {
+ colorSpace = colorSpace || null;
+ var canvas = idOrElement;
if (canvas.tagName !== 'CANVAS') {
- canvas = document.getElementById(arg);
+ canvas = document.getElementById(idOrElement);
if (!canvas) {
- throw 'Canvas with id ' + arg + ' was not found';
- }
- }
- if (!webGLVersion) {
- if (!!window['safari']) {
- // Safari, by default, should use WebGL 1. skbug.com/10171
- webGLVersion = 1;
- } else {
- webGLVersion = 2;
+ throw 'Canvas with id ' + idOrElement + ' was not found';
}
}
// we are ok with all the other defaults.
- var ctx = this.GetWebGLContext(canvas, {majorVersion: webGLVersion});
+ var ctx = this.GetWebGLContext(canvas);
if (!ctx || ctx < 0) {
throw 'failed to create webgl context: err ' + ctx;
}
- if (!canvas && (!width || !height)) {
- throw 'height and width must be provided with context';
- }
-
var grcontext = this.MakeGrContext(ctx);
- if (grcontext) {
- // Bump the default resource cache limit.
- var RESOURCE_CACHE_BYTES = 256 * 1024 * 1024;
- grcontext.setResourceCacheLimitBytes(RESOURCE_CACHE_BYTES);
- }
-
-
- // Maybe better to use clientWidth/height. See:
- // https://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html
- var surface = this.MakeOnScreenGLSurface(grcontext,
- width || canvas.width,
- height || canvas.height);
+ // Note that canvas.width/height here is used because it gives the size of the buffer we're
+ // rendering into. This may not be the same size the element is displayed on the page, which
+ // constrolled by css, and available in canvas.clientWidth/height.
+ var surface = this.MakeOnScreenGLSurface(grcontext, canvas.width, canvas.height, colorSpace);
if (!surface) {
SkDebug('falling back from GPU implementation to a SW based one');
// we need to throw away the old canvas (which was locked to
diff --git a/chromium/third_party/skia/modules/canvaskit/helper.js b/chromium/third_party/skia/modules/canvaskit/helper.js
index 78e62f3c30a..230b1a23062 100644
--- a/chromium/third_party/skia/modules/canvaskit/helper.js
+++ b/chromium/third_party/skia/modules/canvaskit/helper.js
@@ -17,6 +17,21 @@ CanvasKit.Color = function(r, g, b, a) {
return CanvasKit.Color4f(clamp(r)/255, clamp(g)/255, clamp(b)/255, a);
}
+// Constructs a Color as a 32 bit unsigned integer, with 8 bits assigned to each channel.
+// Channels are expected to be between 0 and 255 and will be clamped as such.
+CanvasKit.ColorAsInt = function(r, g, b, a) {
+ // default to opaque
+ if (a === undefined) {
+ a = 255;
+ }
+ // This is consistent with how Skia represents colors in C++, as an unsigned int.
+ // This is also consistent with how Flutter represents colors:
+ // https://github.com/flutter/engine/blob/243bb59c7179a7e701ce478080d6ce990710ae73/lib/web_ui/lib/src/ui/painting.dart#L50
+ return (((clamp(a) << 24) | (clamp(r) << 16) | (clamp(g) << 8) | (clamp(b) << 0)
+ & 0xFFFFFFF) // This truncates the unsigned to 32 bits and signals to JS engines they can
+ // represent the number with an int instead of a double.
+ >>> 0); // This makes the value an unsigned int.
+}
// Construct a 4-float color.
// Opaque if opacity is omitted.
CanvasKit.Color4f = function(r, g, b, a) {
@@ -138,6 +153,23 @@ function isCanvasKitColor(ob) {
function toUint32Color(c) {
return ((clamp(c[3]*255) << 24) | (clamp(c[0]*255) << 16) | (clamp(c[1]*255) << 8) | (clamp(c[2]*255) << 0)) >>> 0;
}
+// Accepts various colors representations and converts them to an array of int colors.
+// Does not handle builders.
+function assureIntColors(arr) {
+ if (arr instanceof Float32Array) {
+ var count = Math.floor(arr.length / 4);
+ var result = new Uint32Array(count);
+ for (var i = 0; i < count; i ++) {
+ result[i] = toUint32Color(arr.slice(i*4, (i+1)*4));
+ }
+ return result;
+ } else if (arr instanceof Uint32Array) {
+ return arr;
+ } else if (arr instanceof Array && arr[0] instanceof Float32Array) {
+ return arr.map(toUint32Color);
+ }
+}
+
function uIntColorToCanvasKitColor(c) {
return CanvasKit.Color(
(c >> 16) & 0xFF,
@@ -183,11 +215,11 @@ function almostEqual(floata, floatb) {
return Math.abs(floata - floatb) < 0.00001;
}
-
var nullptr = 0; // emscripten doesn't like to take null as uintptr_t
// arr can be a normal JS array or a TypedArray
-// dest is something like CanvasKit.HEAPF32
+// dest is a string like "HEAPU32" that specifies the type the src array
+// should be copied into.
// ptr can be optionally provided if the memory was already allocated.
function copy1dArray(arr, dest, ptr) {
if (!arr || !arr.length) {
@@ -197,8 +229,9 @@ function copy1dArray(arr, dest, ptr) {
if (arr['_ck']) {
return arr.byteOffset;
}
+ var bytesPerElement = CanvasKit[dest].BYTES_PER_ELEMENT;
if (!ptr) {
- ptr = CanvasKit._malloc(arr.length * dest.BYTES_PER_ELEMENT);
+ ptr = CanvasKit._malloc(arr.length * bytesPerElement);
}
// In c++ terms, the WASM heap is a uint8_t*, a long buffer/array of single
// byte elements. When we run _malloc, we always get an offset/pointer into
@@ -209,7 +242,10 @@ function copy1dArray(arr, dest, ptr) {
// Concretely, we need to convert ptr to go from an index into a 1-byte-wide
// buffer to an index into a 4-byte-wide buffer (in the case of HEAPF32)
// and thus we divide ptr by 4.
- dest.set(arr, ptr / dest.BYTES_PER_ELEMENT);
+ // It is important to make sure we are grabbing the freshest view of the
+ // memory possible because if we call _malloc and the heap needs to grow,
+ // the TypedArrayView will no longer be valid.
+ CanvasKit[dest].set(arr, ptr / bytesPerElement);
return ptr;
}
@@ -217,15 +253,19 @@ function copy1dArray(arr, dest, ptr) {
// inside themselves). A common use case is points.
// dest is something like CanvasKit.HEAPF32
// ptr can be optionally provided if the memory was already allocated.
+// TODO(kjlubick): Remove 2d arrays - everything should be flat.
function copy2dArray(arr, dest, ptr) {
if (!arr || !arr.length) {
return nullptr;
}
+ var bytesPerElement = CanvasKit[dest].BYTES_PER_ELEMENT;
if (!ptr) {
- ptr = CanvasKit._malloc(arr.length * arr[0].length * dest.BYTES_PER_ELEMENT);
+ ptr = CanvasKit._malloc(arr.length * arr[0].length * bytesPerElement);
}
+ // Make sure we have a fresh view of the heap after we malloc.
+ dest = CanvasKit[dest];
var idx = 0;
- var adjustedPtr = ptr / dest.BYTES_PER_ELEMENT;
+ var adjustedPtr = ptr / bytesPerElement;
for (var r = 0; r < arr.length; r++) {
for (var c = 0; c < arr[0].length; c++) {
dest[adjustedPtr + idx] = arr[r][c];
@@ -235,32 +275,41 @@ function copy2dArray(arr, dest, ptr) {
return ptr;
}
-// arr should be a non-jagged 3d JS array (TypedArrays can't be nested
-// inside themselves.)
-// dest is something like CanvasKit.HEAPF32
-// ptr can be optionally provided if the memory was already allocated.
-function copy3dArray(arr, dest, ptr) {
- if (!arr || !arr.length || !arr[0].length) {
- return nullptr;
- }
- if (!ptr) {
- ptr = CanvasKit._malloc(arr.length * arr[0].length * arr[0][0].length * dest.BYTES_PER_ELEMENT);
- }
- var idx = 0;
- var adjustedPtr = ptr / dest.BYTES_PER_ELEMENT;
- for (var x = 0; x < arr.length; x++) {
- for (var y = 0; y < arr[0].length; y++) {
- for (var z = 0; z < arr[0][0].length; z++) {
- dest[adjustedPtr + idx] = arr[x][y][z];
- idx++;
- }
- }
+// Copies an array of colors to wasm, returning an object with the pointer
+// and info necessary to use the copied colors.
+// Accepts either a flat Float32Array, flat Uint32Array or Array of Float32Arrays.
+// If color is an object that was allocated with CanvasKit.Malloc, it's pointer is
+// returned and no extra copy is performed.
+// Array of Float32Arrays is deprecated and planned to be removed, prefer flat
+// Float32Array
+// TODO(nifong): have this accept color builders.
+function copyFlexibleColorArray(colors) {
+ var result = {
+ colorPtr: nullptr,
+ count: colors.length,
+ colorType: CanvasKit.ColorType.RGBA_F32,
+ }
+ if (colors instanceof Float32Array) {
+ result.colorPtr = copy1dArray(colors, "HEAPF32");
+ result.count = colors.length / 4;
+
+ } else if (colors instanceof Uint32Array) {
+ result.colorPtr = copy1dArray(colors, "HEAPU32");
+ result.colorType = CanvasKit.ColorType.RGBA_8888;
+
+ } else if (colors instanceof Array && colors[0] instanceof Float32Array) {
+ result.colorPtr = copy2dArray(colors, "HEAPF32");
+ } else {
+ throw('Invalid argument to copyFlexibleColorArray, Not a color array '+typeof(colors));
}
- return ptr;
+ return result;
}
var defaultPerspective = Float32Array.of(0, 0, 1);
+var _scratch3x3MatrixPtr = nullptr;
+var _scratch3x3Matrix; // the result from CanvasKit.Malloc
+
// Copies the given DOMMatrix/Array/TypedArray to the CanvasKit heap and
// returns a pointer to the memory. This memory is a float* of length 9.
// If the passed in matrix is null/undefined, we return 0 (nullptr). All calls
@@ -271,7 +320,7 @@ function copy3x3MatrixToWasm(matr) {
if (!matr) {
return nullptr;
}
- var mPtr = CanvasKit._malloc(9 * 4); // 9 matrix scalars, each at 4 bytes.
+
if (matr.length) {
// TODO(kjlubick): Downsample a 16 length (4x4 matrix)
if (matr.length !== 6 && matr.length !== 9) {
@@ -279,27 +328,38 @@ function copy3x3MatrixToWasm(matr) {
}
// This should be an array or typed array.
// have to divide the pointer by 4 to "cast" it from bytes to float.
- CanvasKit.HEAPF32.set(matr, mPtr / 4);
+ var mPtr = copy1dArray(matr, "HEAPF32", _scratch3x3MatrixPtr);
if (matr.length === 6) {
- CanvasKit.HEAPF32.set(defaultPerspective, 6 + mPtr / 4);
+ // Overwrite the last 3 floats with the default perspective. The divide
+ // by 4 casts the pointer into a float pointer.
+ CanvasKit.HEAPF32.set(defaultPerspective, 6 + mPtr / 4);
}
- } else {
- // Try as if it's a DOMMatrix. Reminder that DOMMatrix is column-major.
- var floats = Float32Array.of(
- matr.m11, matr.m21, matr.m41,
- matr.m12, matr.m22, matr.m42,
- matr.m14, matr.m24, matr.m44);
- // have to divide the pointer by 4 to "cast" it from bytes to float.
- CanvasKit.HEAPF32.set(floats, mPtr / 4);
+ return mPtr;
}
- return mPtr;
+ var wasm3x3Matrix = _scratch3x3Matrix['toTypedArray']();
+ // Try as if it's a DOMMatrix. Reminder that DOMMatrix is column-major.
+ wasm3x3Matrix[0] = matr.m11;
+ wasm3x3Matrix[1] = matr.m21;
+ wasm3x3Matrix[2] = matr.m41;
+
+ wasm3x3Matrix[3] = matr.m12;
+ wasm3x3Matrix[4] = matr.m22;
+ wasm3x3Matrix[5] = matr.m42;
+
+ wasm3x3Matrix[6] = matr.m14;
+ wasm3x3Matrix[7] = matr.m24;
+ wasm3x3Matrix[8] = matr.m44;
+ return _scratch3x3MatrixPtr;
}
+var _scratch4x4MatrixPtr = nullptr;
+var _scratch4x4Matrix; // the result from CanvasKit.Malloc
+
function copy4x4MatrixToWasm(matr) {
if (!matr) {
return nullptr;
}
- var mPtr = CanvasKit._malloc(16 * 4); // 9 matrix scalars, each at 4 bytes.
+ var wasm4x4Matrix = _scratch4x4Matrix['toTypedArray']();
if (matr.length) {
if (matr.length !== 16 && matr.length !== 6 && matr.length !== 9) {
throw 'invalid matrix size';
@@ -307,39 +367,64 @@ function copy4x4MatrixToWasm(matr) {
if (matr.length === 16) {
// This should be an array or typed array.
// have to divide the pointer by 4 to "cast" it from bytes to float.
- CanvasKit.HEAPF32.set(matr, mPtr / 4);
- } else {
- // Upscale the row-major 3x3 or 3x2 matrix into a 4x4 row-major matrix
- // TODO(skbug.com/10108) This will need to change when we convert our
- // JS 4x4 to be column-major.
- var floats = Float32Array.of(
- matr[0], matr[1], 0, matr[2],
- matr[3], matr[4], 0, matr[5],
- 0, 0, 0, 0,
- matr[6], matr[7], 0, matr[8]);
- if (matr.length === 6) {
- // fix perspective for the 3x2 case (from above, they will be undefined).
- floats[4*3+0]=0;
- floats[4*3+1]=0;
- floats[4*3+3]=1;
- }
- CanvasKit.HEAPF32.set(floats, mPtr / 4);
+ return copy1dArray(matr, "HEAPF32", _scratch4x4MatrixPtr);
}
- } else {
- // Try as if it's a DOMMatrix. Reminder that DOMMatrix is column-major.
- // TODO(skbug.com/10108) use toFloat32Array().
- var floats = Float32Array.of(
- matr.m11, matr.m21, matr.m31, matr.m41,
- matr.m12, matr.m22, matr.m32, matr.m42,
- matr.m13, matr.m23, matr.m33, matr.m43,
- matr.m14, matr.m24, matr.m34, matr.m44);
- // have to divide the pointer by 4 to "cast" it from bytes to float.
- CanvasKit.HEAPF32.set(floats, mPtr / 4);
+ // Upscale the row-major 3x3 or 3x2 matrix into a 4x4 row-major matrix
+ // TODO(skbug.com/10108) This will need to change when we convert our
+ // JS 4x4 to be column-major.
+ // When upscaling, we need to overwrite the 3rd column and the 3rd row with
+ // 0s. It's easiest to just do that with a fill command.
+ wasm4x4Matrix.fill(0);
+ wasm4x4Matrix[0] = matr[0];
+ wasm4x4Matrix[1] = matr[1];
+ // skip col 2
+ wasm4x4Matrix[3] = matr[2];
+
+ wasm4x4Matrix[4] = matr[3];
+ wasm4x4Matrix[5] = matr[4];
+ // skip col 2
+ wasm4x4Matrix[7] = matr[5];
+
+ // skip row 2
+
+ wasm4x4Matrix[12] = matr[6];
+ wasm4x4Matrix[13] = matr[7];
+ // skip col 2
+ wasm4x4Matrix[15] = matr[8];
+
+ if (matr.length === 6) {
+ // fix perspective for the 3x2 case (from above, they will be undefined).
+ wasm4x4Matrix[12]=0;
+ wasm4x4Matrix[13]=0;
+ wasm4x4Matrix[15]=1;
+ }
+ return _scratch4x4MatrixPtr;
}
- return mPtr;
+ // Try as if it's a DOMMatrix. Reminder that DOMMatrix is column-major.
+ wasm4x4Matrix[0] = matr.m11;
+ wasm4x4Matrix[1] = matr.m21;
+ wasm4x4Matrix[2] = matr.m31;
+ wasm4x4Matrix[3] = matr.m41;
+
+ wasm4x4Matrix[4] = matr.m12;
+ wasm4x4Matrix[5] = matr.m22;
+ wasm4x4Matrix[6] = matr.m32;
+ wasm4x4Matrix[7] = matr.m42;
+
+ wasm4x4Matrix[8] = matr.m13;
+ wasm4x4Matrix[9] = matr.m23;
+ wasm4x4Matrix[10] = matr.m33;
+ wasm4x4Matrix[11] = matr.m43;
+
+ wasm4x4Matrix[12] = matr.m14;
+ wasm4x4Matrix[13] = matr.m24;
+ wasm4x4Matrix[14] = matr.m34;
+ wasm4x4Matrix[15] = matr.m44;
+ return _scratch4x4MatrixPtr;
}
-// copies a 4x4 matrix at the given pointer into a JS array.
+// copies a 4x4 matrix at the given pointer into a JS array. It is the caller's
+// responsibility to free the matrPtr if needed.
function copy4x4MatrixFromWasm(matrPtr) {
// read them out into an array. TODO(kjlubick): If we change SkMatrix to be
// typedArrays, then we should return a typed array here too.
@@ -347,19 +432,38 @@ function copy4x4MatrixFromWasm(matrPtr) {
for (var i = 0; i < 16; i++) {
rv[i] = CanvasKit.HEAPF32[matrPtr/4 + i]; // divide by 4 to "cast" to float.
}
- CanvasKit._free(matrPtr);
return rv;
}
+var _scratchColorPtr = nullptr;
+var _scratchColor; // the result from CanvasKit.Malloc
+
+function copyColorToWasm(color4f, ptr) {
+ return copy1dArray(color4f, "HEAPF32", ptr || _scratchColorPtr);
+}
+
+function copyColorComponentsToWasm(r, g, b, a) {
+ var colors = _scratchColor['toTypedArray']();
+ colors[0] = r;
+ colors[1] = g;
+ colors[2] = b;
+ colors[3] = a;
+ return _scratchColorPtr;
+}
+
+function copyColorToWasmNoScratch(color4f) {
+ // TODO(kjlubick): accept 4 floats or int color
+ return copy1dArray(color4f, "HEAPF32");
+}
+
// copies the four floats at the given pointer in a js Float32Array
function copyColorFromWasm(colorPtr) {
var rv = new Float32Array(4);
for (var i = 0; i < 4; i++) {
rv[i] = CanvasKit.HEAPF32[colorPtr/4 + i]; // divide by 4 to "cast" to float.
}
- CanvasKit._free(colorPtr);
return rv;
-}
+}
// Caching the Float32Arrays can save having to reallocate them
// over and over again.
@@ -377,6 +481,7 @@ var Float32ArrayCache = {};
// [CanvasKit.LINE_VERB, 30, 40],
// [CanvasKit.QUAD_VERB, 20, 50, 45, 60],
// ];
+// TODO(kjlubick) remove this and Float32ArrayCache (superceded by Malloc).
function loadCmdsTypedArray(arr) {
var len = 0;
for (var r = 0; r < arr.length; r++) {
@@ -400,7 +505,7 @@ function loadCmdsTypedArray(arr) {
}
}
- var ptr = copy1dArray(ta, CanvasKit.HEAPF32);
+ var ptr = copy1dArray(ta, "HEAPF32");
return [ptr, len];
}
@@ -490,7 +595,7 @@ CanvasKit.FourFloatArrayHelper.prototype.build = function() {
if (this._ptr) {
return this._ptr;
}
- this._ptr = copy1dArray(this._floats, CanvasKit.HEAPF32);
+ this._ptr = copy1dArray(this._floats, "HEAPF32");
return this._ptr;
}
@@ -563,7 +668,7 @@ CanvasKit.OneUIntArrayHelper.prototype.build = function() {
if (this._ptr) {
return this._ptr;
}
- this._ptr = copy1dArray(this._uints, CanvasKit.HEAPU32);
+ this._ptr = copy1dArray(this._uints, "HEAPU32");
return this._ptr;
}
@@ -630,20 +735,64 @@ CanvasKit.SkColorBuilder = CanvasKit.OneUIntArrayHelper;
* can manage memory and initialize values properly. When used
* correctly, it can save copying of data between JS and C++.
* When used incorrectly, it can lead to memory leaks.
+ * Any memory allocated by CanvasKit.Malloc needs to be released with CanvasKit.Free.
*
- * const ta = CanvasKit.Malloc(Float32Array, 20);
+ * const mObj = CanvasKit.Malloc(Float32Array, 20);
+ * Get a TypedArray view around the malloc'd memory (this does not copy anything).
+ * const ta = mObj.toTypedArray();
* // store data into ta
- * const cf = CanvasKit.SkColorFilter.MakeMatrix(ta);
- * // MakeMatrix cleans up the ptr automatically.
+ * const cf = CanvasKit.SkColorFilter.MakeMatrix(ta); // mObj could also be used.
+ *
+ * // eventually...
+ * CanvasKit.Free(mObj);
*
* @param {TypedArray} typedArray - constructor for the typedArray.
- * @param {number} len - number of elements to store.
+ * @param {number} len - number of *elements* to store.
*/
CanvasKit.Malloc = function(typedArray, len) {
var byteLen = len * typedArray.BYTES_PER_ELEMENT;
var ptr = CanvasKit._malloc(byteLen);
- var ta = new typedArray(CanvasKit.HEAPU8.buffer, ptr, len);
- // add a marker that this was allocated in C++ land
- ta['_ck'] = true;
- return ta;
+ return {
+ '_ck': true,
+ 'length': len,
+ 'byteOffset': ptr,
+ typedArray: null,
+ 'subarray': function(start, end) {
+ var sa = this['toTypedArray']().subarray(start, end);
+ sa['_ck'] = true;
+ return sa;
+ },
+ 'toTypedArray': function() {
+ // Check if the previously allocated array is still usable.
+ // If it's falsey, then we haven't created an array yet.
+ // If it's empty, then WASM resized memory and emptied the array.
+ if (this.typedArray && this.typedArray.length) {
+ return this.typedArray;
+ }
+ this.typedArray = new typedArray(CanvasKit.HEAPU8.buffer, ptr, len);
+ // add a marker that this was allocated in C++ land
+ this.typedArray['_ck'] = true;
+ return this.typedArray;
+ },
+ };
+};
+
+/**
+ * Free frees the memory returned by Malloc.
+ * Any memory allocated by CanvasKit.Malloc needs to be released with CanvasKit.Free.
+ */
+CanvasKit.Free = function(mallocObj) {
+ CanvasKit._free(mallocObj['byteOffset']);
+ mallocObj['byteOffset'] = nullptr;
+ // Set these to null to make sure the TypedArrays can be garbage collected.
+ mallocObj['toTypedArray'] = null;
+ mallocObj.typedArray = null;
+};
+
+// This helper will free the given pointer unless the provided array is one
+// that was returned by CanvasKit.Malloc.
+function freeArraysThatAreNotMallocedByUsers(ptr, arr) {
+ if (arr && !arr['_ck']) {
+ CanvasKit._free(ptr);
+ }
}
diff --git a/chromium/third_party/skia/modules/canvaskit/htmlcanvas/_namedcolors.js b/chromium/third_party/skia/modules/canvaskit/htmlcanvas/_namedcolors.js
index 16dec34d66f..69a736b151e 100644
--- a/chromium/third_party/skia/modules/canvaskit/htmlcanvas/_namedcolors.js
+++ b/chromium/third_party/skia/modules/canvaskit/htmlcanvas/_namedcolors.js
@@ -7,7 +7,7 @@ const CanvasKitInit = require('../canvaskit/bin/canvaskit.js');
CanvasKitInit({
locateFile: (file) => __dirname + '/../canvaskit/bin/'+file,
-}).ready().then((CanvasKit) => {
+}).then((CanvasKit) => {
let colorMap = {
// From https://drafts.csswg.org/css-color/#named-colors
'aliceblue': CanvasKit.Color(240, 248, 255),
@@ -162,4 +162,4 @@ CanvasKitInit({
};
console.log(JSON.stringify(colorMap));
-}); \ No newline at end of file
+});
diff --git a/chromium/third_party/skia/modules/canvaskit/htmlcanvas/canvas2dcontext.js b/chromium/third_party/skia/modules/canvaskit/htmlcanvas/canvas2dcontext.js
index f4fc8dd1a20..8ebecceefbe 100644
--- a/chromium/third_party/skia/modules/canvaskit/htmlcanvas/canvas2dcontext.js
+++ b/chromium/third_party/skia/modules/canvaskit/htmlcanvas/canvas2dcontext.js
@@ -848,7 +848,8 @@ function CanvasRenderingContext2D(skcanvas) {
}
var img = CanvasKit.MakeImage(imageData.data, imageData.width, imageData.height,
CanvasKit.AlphaType.Unpremul,
- CanvasKit.ColorType.RGBA_8888);
+ CanvasKit.ColorType.RGBA_8888,
+ CanvasKit.SkColorSpace.SRGB);
var src = CanvasKit.XYWHRect(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
var dst = CanvasKit.XYWHRect(x+dirtyX, y+dirtyY, dirtyWidth, dirtyHeight);
var inverted = CanvasKit.SkMatrix.invert(this._currentTransform);
diff --git a/chromium/third_party/skia/modules/canvaskit/interface.js b/chromium/third_party/skia/modules/canvaskit/interface.js
index 9159f901ac5..0135dbbbaff 100644
--- a/chromium/third_party/skia/modules/canvaskit/interface.js
+++ b/chromium/third_party/skia/modules/canvaskit/interface.js
@@ -8,6 +8,20 @@
CanvasKit.onRuntimeInitialized = function() {
// All calls to 'this' need to go in externs.js so closure doesn't minify them away.
+ _scratchColor = CanvasKit.Malloc(Float32Array, 4); // 4 color scalars.
+ _scratchColorPtr = _scratchColor['byteOffset'];
+
+ _scratch4x4Matrix = CanvasKit.Malloc(Float32Array, 16); // 16 matrix scalars.
+ _scratch4x4MatrixPtr = _scratch4x4Matrix['byteOffset'];
+
+ _scratch3x3Matrix = CanvasKit.Malloc(Float32Array, 9); // 9 matrix scalars.
+ _scratch3x3MatrixPtr = _scratch3x3Matrix['byteOffset'];
+ // Create single copies of all three supported color spaces
+ // These are sk_sp<SkColorSpace>
+ CanvasKit.SkColorSpace.SRGB = CanvasKit.SkColorSpace._MakeSRGB();
+ CanvasKit.SkColorSpace.DISPLAY_P3 = CanvasKit.SkColorSpace._MakeDisplayP3();
+ CanvasKit.SkColorSpace.ADOBE_RGB = CanvasKit.SkColorSpace._MakeAdobeRGB();
+
// Add some helpers for matrices. This is ported from SkMatrix.cpp
// to save complexity and overhead of going back and forth between
// C++ and JS layers.
@@ -260,7 +274,7 @@ CanvasKit.onRuntimeInitialized = function() {
// This rotate can be used when you already have the cosAngle and sinAngle values
// so you don't have to atan(cos/sin) to call roatated() which expects an angle in radians.
// this does no checking! Behavior for invalid sin or cos values or non-normalized axis vectors
- // is incorrect. Prefer rotate().
+ // is incorrect. Prefer rotated().
CanvasKit.SkM44.rotatedUnitSinCos = function(axisVec, sinAngle, cosAngle) {
var x = axisVec[0];
var y = axisVec[1];
@@ -506,7 +520,31 @@ CanvasKit.onRuntimeInitialized = function() {
}
return m;
- }
+ };
+
+ CanvasKit.SkPath.MakeFromCmds = function(cmds) {
+ var ptrLen = loadCmdsTypedArray(cmds);
+ var path = CanvasKit.SkPath._MakeFromCmds(ptrLen[0], ptrLen[1]);
+ CanvasKit._free(ptrLen[0]);
+ return path;
+ };
+
+ // Deprecated
+ CanvasKit.MakePathFromCmds = CanvasKit.SkPath.MakeFromCmds;
+
+ // The weights array is optional (only used for conics).
+ CanvasKit.SkPath.MakeFromVerbsPointsWeights = function(verbs, pts, weights) {
+ var verbsPtr = copy1dArray(verbs, "HEAPU8");
+ var pointsPtr = copy1dArray(pts, "HEAPF32");
+ var weightsPtr = copy1dArray(weights, "HEAPF32");
+ var numWeights = (weights && weights.length) || 0;
+ var path = CanvasKit.SkPath._MakeFromVerbsPointsWeights(
+ verbsPtr, verbs.length, pointsPtr, pts.length, weightsPtr, numWeights);
+ freeArraysThatAreNotMallocedByUsers(verbsPtr, verbs);
+ freeArraysThatAreNotMallocedByUsers(pointsPtr, pts);
+ freeArraysThatAreNotMallocedByUsers(weightsPtr, weights);
+ return path;
+ };
CanvasKit.SkPath.prototype.addArc = function(oval, startAngle, sweepAngle) {
// see arc() for the HTMLCanvas version
@@ -577,11 +615,11 @@ CanvasKit.onRuntimeInitialized = function() {
ptr = points.byteOffset;
n = points.length/2;
} else {
- ptr = copy2dArray(points, CanvasKit.HEAPF32);
+ ptr = copy2dArray(points, "HEAPF32");
n = points.length;
}
this._addPoly(ptr, n, close);
- CanvasKit._free(ptr);
+ freeArraysThatAreNotMallocedByUsers(ptr, points);
return this;
};
@@ -607,14 +645,14 @@ CanvasKit.onRuntimeInitialized = function() {
CanvasKit.SkPath.prototype.addRoundRect = function() {
// Takes 3, 4, 6 or 7 args
- // - SkRect, radii, ccw
+ // - SkRect, radii (an array of 8 numbers), ccw
// - SkRect, rx, ry, ccw
// - left, top, right, bottom, radii, ccw
// - left, top, right, bottom, rx, ry, ccw
var args = arguments;
if (args.length === 3 || args.length === 6) {
var radii = args[args.length-2];
- } else if (args.length === 6 || args.length === 7){
+ } else if (args.length === 4 || args.length === 7){
// duplicate the given (rx, ry) pairs for each corner.
var rx = args[args.length-3];
var ry = args[args.length-2];
@@ -627,7 +665,7 @@ CanvasKit.onRuntimeInitialized = function() {
SkDebug('addRoundRect needs 8 radii provided. Got ' + radii.length);
return null;
}
- var rptr = copy1dArray(radii, CanvasKit.HEAPF32);
+ var rptr = copy1dArray(radii, "HEAPF32");
if (args.length === 3 || args.length === 4) {
var r = args[0];
var ccw = args[args.length - 1];
@@ -636,10 +674,23 @@ CanvasKit.onRuntimeInitialized = function() {
var a = args;
this._addRoundRect(a[0], a[1], a[2], a[3], rptr, ccw);
}
- CanvasKit._free(rptr);
+ freeArraysThatAreNotMallocedByUsers(rptr, radii);
return this;
};
+ // The weights array is optional (only used for conics).
+ CanvasKit.SkPath.prototype.addVerbsPointsWeights = function(verbs, points, weights) {
+ var verbsPtr = copy1dArray(verbs, "HEAPU8");
+ var pointsPtr = copy1dArray(points, "HEAPF32");
+ var weightsPtr = copy1dArray(weights, "HEAPF32");
+ var numWeights = (weights && weights.length) || 0;
+ this._addVerbsPointsWeights(verbsPtr, verbs.length, pointsPtr, points.length,
+ weightsPtr, numWeights);
+ freeArraysThatAreNotMallocedByUsers(verbsPtr, verbs);
+ freeArraysThatAreNotMallocedByUsers(pointsPtr, points);
+ freeArraysThatAreNotMallocedByUsers(weightsPtr, weights);
+ };
+
CanvasKit.SkPath.prototype.arc = function(x, y, radius, startAngle, endAngle, ccw) {
// emulates the HTMLCanvas behavior. See addArc() for the SkPath version.
// Note input angles are radians.
@@ -749,16 +800,12 @@ CanvasKit.onRuntimeInitialized = function() {
CanvasKit.SkPath.prototype.stroke = function(opts) {
// Fill out any missing values with the default values.
- /**
- * See externs.js for this definition
- * @type {StrokeOpts}
- */
opts = opts || {};
- opts.width = opts.width || 1;
- opts.miter_limit = opts.miter_limit || 4;
- opts.cap = opts.cap || CanvasKit.StrokeCap.Butt;
- opts.join = opts.join || CanvasKit.StrokeJoin.Miter;
- opts.precision = opts.precision || 1;
+ opts['width'] = opts['width'] || 1;
+ opts['miter_limit'] = opts['miter_limit'] || 4;
+ opts['cap'] = opts['cap'] || CanvasKit.StrokeCap.Butt;
+ opts['join'] = opts['join'] || CanvasKit.StrokeJoin.Miter;
+ opts['precision'] = opts['precision'] || 1;
if (this._stroke(opts)) {
return this;
}
@@ -807,9 +854,7 @@ CanvasKit.onRuntimeInitialized = function() {
CanvasKit.SkImage.prototype.makeShader = function(xTileMode, yTileMode, localMatrix) {
var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
- var shader = this._makeShader(xTileMode, yTileMode, localMatrixPtr);
- CanvasKit._free(localMatrixPtr);
- return shader;
+ return this._makeShader(xTileMode, yTileMode, localMatrixPtr);
}
CanvasKit.SkImage.prototype.readPixels = function(imageInfo, srcX, srcY) {
@@ -854,9 +899,8 @@ CanvasKit.onRuntimeInitialized = function() {
// Accepts an array of four numbers in the range of 0-1 representing a 4f color
CanvasKit.SkCanvas.prototype.clear = function (color4f) {
- var cPtr = copy1dArray(color4f, CanvasKit.HEAPF32);
+ var cPtr = copyColorToWasm(color4f);
this._clear(cPtr);
- CanvasKit._free(cPtr);
}
// concat takes a 3x2, a 3x3, or a 4x4 matrix and upscales it (if needed) to 4x4. This is because
@@ -864,23 +908,30 @@ CanvasKit.onRuntimeInitialized = function() {
CanvasKit.SkCanvas.prototype.concat = function(matr) {
var matrPtr = copy4x4MatrixToWasm(matr);
this._concat(matrPtr);
- CanvasKit._free(matrPtr);
}
// Deprecated - just use concat
CanvasKit.SkCanvas.prototype.concat44 = CanvasKit.SkCanvas.prototype.concat;
// atlas is an SkImage, e.g. from CanvasKit.MakeImageFromEncoded
- // srcRects and dstXforms should be CanvasKit.SkRectBuilder and CanvasKit.RSXFormBuilder
- // or just arrays of floats in groups of 4.
- // colors, if provided, should be a CanvasKit.SkColorBuilder or array of float colors (arrays of 4 floats)
+ // srcRects, dstXforms, and colors should be CanvasKit.SkRectBuilder, CanvasKit.RSXFormBuilder,
+ // and CanvasKit.SkColorBuilder (fastest)
+ // Or they can be an array of floats of length 4*number of destinations.
+ // colors are optional and used to tint the drawn images using the optional blend mode
+ // Colors may be an SkColorBuilder, a Uint32Array of int colors,
+ // a Flat Float32Array of float colors or a 2d Array of Float32Array(4) (deprecated)
CanvasKit.SkCanvas.prototype.drawAtlas = function(atlas, srcRects, dstXforms, paint,
/*optional*/ blendMode, colors) {
if (!atlas || !paint || !srcRects || !dstXforms) {
SkDebug('Doing nothing since missing a required input');
return;
}
- if (srcRects.length !== dstXforms.length || (colors && colors.length !== dstXforms.length)) {
+
+ // builder arguments report the length as the number of rects, but when passed as arrays
+ // their.length attribute is 4x higher because it's the number of total components of all rects.
+ // colors is always going to report the same length, at least until floats colors are supported
+ // by this function.
+ if (srcRects.length !== dstXforms.length) {
SkDebug('Doing nothing since input arrays length mismatches');
return;
}
@@ -892,14 +943,17 @@ CanvasKit.onRuntimeInitialized = function() {
if (srcRects.build) {
srcRectPtr = srcRects.build();
} else {
- srcRectPtr = copy1dArray(srcRects, CanvasKit.HEAPF32);
+ srcRectPtr = copy1dArray(srcRects, "HEAPF32");
}
+ var count = 1;
var dstXformPtr;
if (dstXforms.build) {
dstXformPtr = dstXforms.build();
+ count = dstXforms.length;
} else {
- dstXformPtr = copy1dArray(dstXforms, CanvasKit.HEAPF32);
+ dstXformPtr = copy1dArray(dstXforms, "HEAPF32");
+ count = dstXforms.length / 4;
}
var colorPtr = nullptr;
@@ -907,40 +961,39 @@ CanvasKit.onRuntimeInitialized = function() {
if (colors.build) {
colorPtr = colors.build();
} else {
- if (!isCanvasKitColor(colors[0])) {
- SkDebug('DrawAtlas color argument expected to be CanvasKit.SkRectBuilder or array of ' +
- 'float arrays, but got '+colors);
- return;
- }
- // convert here
- colors = colors.map(toUint32Color);
- colorPtr = copy1dArray(colors, CanvasKit.HEAPU32);
+ colorPtr = copy1dArray(assureIntColors(colors), "HEAPU32");
}
}
- this._drawAtlas(atlas, dstXformPtr, srcRectPtr, colorPtr, dstXforms.length,
- blendMode, paint);
+ this._drawAtlas(atlas, dstXformPtr, srcRectPtr, colorPtr, count, blendMode, paint);
if (srcRectPtr && !srcRects.build) {
- CanvasKit._free(srcRectPtr);
+ freeArraysThatAreNotMallocedByUsers(srcRectPtr, srcRects);
}
if (dstXformPtr && !dstXforms.build) {
- CanvasKit._free(dstXformPtr);
+ freeArraysThatAreNotMallocedByUsers(dstXformPtr, dstXforms);
}
if (colorPtr && !colors.build) {
- CanvasKit._free(colorPtr);
+ freeArraysThatAreNotMallocedByUsers(colorPtr, colors);
}
-
}
CanvasKit.SkCanvas.prototype.drawColor = function (color4f, mode) {
- var cPtr = copy1dArray(color4f, CanvasKit.HEAPF32);
+ var cPtr = copyColorToWasm(color4f);
+ if (mode !== undefined) {
+ this._drawColor(cPtr, mode);
+ } else {
+ this._drawColor(cPtr);
+ }
+ }
+
+ CanvasKit.SkCanvas.prototype.drawColorComponents = function (r, g, b, a, mode) {
+ var cPtr = copyColorComponentsToWasm(r, g, b, a);
if (mode !== undefined) {
this._drawColor(cPtr, mode);
} else {
this._drawColor(cPtr);
}
- CanvasKit._free(cPtr);
}
// points is either an array of [x, y] where x and y are numbers or
@@ -955,63 +1008,64 @@ CanvasKit.onRuntimeInitialized = function() {
ptr = points.byteOffset;
n = points.length/2;
} else {
- ptr = copy2dArray(points, CanvasKit.HEAPF32);
+ ptr = copy2dArray(points, "HEAPF32");
n = points.length;
}
this._drawPoints(mode, ptr, n, paint);
- CanvasKit._free(ptr);
+ freeArraysThatAreNotMallocedByUsers(ptr, points);
}
CanvasKit.SkCanvas.prototype.drawShadow = function(path, zPlaneParams, lightPos, lightRadius, ambientColor, spotColor, flags) {
- var ambiPtr = copy1dArray(ambientColor, CanvasKit.HEAPF32);
- var spotPtr = copy1dArray(spotColor, CanvasKit.HEAPF32);
+ var ambiPtr = copyColorToWasmNoScratch(ambientColor);
+ var spotPtr = copyColorToWasmNoScratch(spotColor);
this._drawShadow(path, zPlaneParams, lightPos, lightRadius, ambiPtr, spotPtr, flags);
- CanvasKit._free(ambiPtr);
- CanvasKit._free(spotPtr);
+ freeArraysThatAreNotMallocedByUsers(ambiPtr, ambientColor);
+ freeArraysThatAreNotMallocedByUsers(spotPtr, spotColor);
}
// getLocalToDevice returns a 4x4 matrix.
CanvasKit.SkCanvas.prototype.getLocalToDevice = function() {
- var matrPtr = CanvasKit._malloc(16 * 4); // allocate space for the matrix
// _getLocalToDevice will copy the values into the pointer.
- this._getLocalToDevice(matrPtr);
- return copy4x4MatrixFromWasm(matrPtr);
+ this._getLocalToDevice(_scratch4x4MatrixPtr);
+ return copy4x4MatrixFromWasm(_scratch4x4MatrixPtr);
}
// findMarkedCTM returns a 4x4 matrix, or null if a matrix was not found at
// the provided marker.
CanvasKit.SkCanvas.prototype.findMarkedCTM = function(marker) {
- var matrPtr = CanvasKit._malloc(16 * 4); // allocate space for the matrix
// _getLocalToDevice will copy the values into the pointer.
- var found = this._findMarkedCTM(marker, matrPtr);
+ var found = this._findMarkedCTM(marker, _scratch4x4MatrixPtr);
if (!found) {
return null;
}
- return copy4x4MatrixFromWasm(matrPtr);
+ return copy4x4MatrixFromWasm(_scratch4x4MatrixPtr);
}
// getTotalMatrix returns the current matrix as a 3x3 matrix.
CanvasKit.SkCanvas.prototype.getTotalMatrix = function() {
- var matrPtr = CanvasKit._malloc(9 * 4); // allocate space for the matrix
// _getTotalMatrix will copy the values into the pointer.
- this._getTotalMatrix(matrPtr);
+ this._getTotalMatrix(_scratch3x3MatrixPtr);
// read them out into an array. TODO(kjlubick): If we change SkMatrix to be
// typedArrays, then we should return a typed array here too.
var rv = new Array(9);
for (var i = 0; i < 9; i++) {
- rv[i] = CanvasKit.HEAPF32[matrPtr/4 + i]; // divide by 4 to "cast" to float.
+ rv[i] = CanvasKit.HEAPF32[_scratch3x3MatrixPtr/4 + i]; // divide by 4 to "cast" to float.
}
- CanvasKit._free(matrPtr);
return rv;
}
// returns Uint8Array
CanvasKit.SkCanvas.prototype.readPixels = function(x, y, w, h, alphaType,
- colorType, dstRowBytes) {
+ colorType, colorSpace, dstRowBytes) {
// supply defaults (which are compatible with HTMLCanvas's getImageData)
alphaType = alphaType || CanvasKit.AlphaType.Unpremul;
colorType = colorType || CanvasKit.ColorType.RGBA_8888;
- dstRowBytes = dstRowBytes || (4 * w);
+ colorSpace = colorSpace || CanvasKit.SkColorSpace.SRGB;
+ var pixBytes = 4;
+ if (colorType === CanvasKit.ColorType.RGBA_F16) {
+ pixBytes = 8;
+ }
+ dstRowBytes = dstRowBytes || (pixBytes * w);
var len = h * dstRowBytes
var pptr = CanvasKit._malloc(len);
@@ -1020,6 +1074,7 @@ CanvasKit.onRuntimeInitialized = function() {
'height': h,
'colorType': colorType,
'alphaType': alphaType,
+ 'colorSpace': colorSpace,
}, pptr, dstRowBytes, x, y);
if (!ok) {
CanvasKit._free(pptr);
@@ -1033,10 +1088,9 @@ CanvasKit.onRuntimeInitialized = function() {
return pixels;
}
- // pixels is a TypedArray. No matter the input size, it will be treated as
- // a Uint8Array (essentially, a byte array).
+ // pixels should be a Uint8Array or a plain JS array.
CanvasKit.SkCanvas.prototype.writePixels = function(pixels, srcWidth, srcHeight,
- destX, destY, alphaType, colorType) {
+ destX, destY, alphaType, colorType, colorSpace) {
if (pixels.byteLength % (srcWidth * srcHeight)) {
throw 'pixels length must be a multiple of the srcWidth * srcHeight';
}
@@ -1044,26 +1098,25 @@ CanvasKit.onRuntimeInitialized = function() {
// supply defaults (which are compatible with HTMLCanvas's putImageData)
alphaType = alphaType || CanvasKit.AlphaType.Unpremul;
colorType = colorType || CanvasKit.ColorType.RGBA_8888;
+ colorSpace = colorSpace || CanvasKit.SkColorSpace.SRGB;
var srcRowBytes = bytesPerPixel * srcWidth;
- var pptr = CanvasKit._malloc(pixels.byteLength);
- CanvasKit.HEAPU8.set(pixels, pptr);
-
+ var pptr = copy1dArray(pixels, "HEAPU8");
var ok = this._writePixels({
'width': srcWidth,
'height': srcHeight,
'colorType': colorType,
'alphaType': alphaType,
+ 'colorSpace': colorSpace,
}, pptr, srcRowBytes, destX, destY);
- CanvasKit._free(pptr);
+ freeArraysThatAreNotMallocedByUsers(pptr, pixels);
return ok;
}
CanvasKit.SkColorFilter.MakeBlend = function(color4f, mode) {
- var cPtr = copy1dArray(color4f, CanvasKit.HEAPF32);
+ var cPtr = copyColorToWasm(color4f);
var result = CanvasKit.SkColorFilter._MakeBlend(cPtr, mode);
- CanvasKit._free(cPtr);
return result;
}
@@ -1072,31 +1125,38 @@ CanvasKit.onRuntimeInitialized = function() {
if (!colorMatrix || colorMatrix.length !== 20) {
throw 'invalid color matrix';
}
- var fptr = copy1dArray(colorMatrix, CanvasKit.HEAPF32);
+ var fptr = copy1dArray(colorMatrix, "HEAPF32");
// We know skia memcopies the floats, so we can free our memory after the call returns.
var m = CanvasKit.SkColorFilter._makeMatrix(fptr);
- CanvasKit._free(fptr);
+ freeArraysThatAreNotMallocedByUsers(fptr, colorMatrix);
return m;
}
CanvasKit.SkImageFilter.MakeMatrixTransform = function(matr, filterQuality, input) {
var matrPtr = copy3x3MatrixToWasm(matr);
- var imgF = CanvasKit.SkImageFilter._MakeMatrixTransform(matrPtr, filterQuality, input);
-
- CanvasKit._free(matrPtr);
- return imgF;
+ return CanvasKit.SkImageFilter._MakeMatrixTransform(matrPtr, filterQuality, input);
}
CanvasKit.SkPaint.prototype.getColor = function() {
- var cPtr = CanvasKit._malloc(16); // 4 floats, 4 bytes each
- this._getColor(cPtr);
- return copyColorFromWasm(cPtr);
+ this._getColor(_scratchColorPtr);
+ return copyColorFromWasm(_scratchColorPtr);
}
- CanvasKit.SkPaint.prototype.setColor = function(color4f) {
- var cPtr = copy1dArray(color4f, CanvasKit.HEAPF32);
- this._setColor(cPtr);
- CanvasKit._free(cPtr);
+ CanvasKit.SkPaint.prototype.setColor = function(color4f, colorSpace) {
+ colorSpace = colorSpace || null; // null will be replaced with sRGB in the C++ method.
+ // emscripten wouldn't bind undefined to the sk_sp<SkColorSpace> expected here.
+ var cPtr = copyColorToWasm(color4f);
+ this._setColor(cPtr, colorSpace);
+ }
+
+ // The color components here are expected to be floating point values (nominally between
+ // 0.0 and 1.0, but with wider color gamuts, the values could exceed this range). To convert
+ // between standard 8 bit colors and floats, just divide by 255 before passing them in.
+ CanvasKit.SkPaint.prototype.setColorComponents = function(r, g, b, a, colorSpace) {
+ colorSpace = colorSpace || null; // null will be replaced with sRGB in the C++ method.
+ // emscripten wouldn't bind undefined to the sk_sp<SkColorSpace> expected here.
+ var cPtr = copyColorComponentsToWasm(r, g, b, a);
+ this._setColor(cPtr, colorSpace);
}
CanvasKit.SkSurface.prototype.captureFrameAsSkPicture = function(drawFrame) {
@@ -1126,7 +1186,7 @@ CanvasKit.onRuntimeInitialized = function() {
// We do not dispose() of the SkSurface here, as the client will typically
// call requestAnimationFrame again from within the supplied callback.
// For drawing a single frame, prefer drawOnce().
- this.flush();
+ this.flush(dirtyRect);
}.bind(this));
}
@@ -1142,7 +1202,7 @@ CanvasKit.onRuntimeInitialized = function() {
}
callback(this._cached_canvas);
- this.flush();
+ this.flush(dirtyRect);
this.dispose();
}.bind(this));
}
@@ -1154,82 +1214,82 @@ CanvasKit.onRuntimeInitialized = function() {
if (!intervals.length || intervals.length % 2 === 1) {
throw 'Intervals array must have even length';
}
- var ptr = copy1dArray(intervals, CanvasKit.HEAPF32);
+ var ptr = copy1dArray(intervals, "HEAPF32");
var dpe = CanvasKit.SkPathEffect._MakeDash(ptr, intervals.length, phase);
- CanvasKit._free(ptr);
+ freeArraysThatAreNotMallocedByUsers(ptr, intervals);
return dpe;
}
- CanvasKit.SkShader.Color = function(color4f) {
- var cPtr = copy1dArray(color4f, CanvasKit.HEAPF32);
- var result = CanvasKit.SkShader._Color(cPtr);
- CanvasKit._free(cPtr);
+ CanvasKit.SkShader.Color = function(color4f, colorSpace) {
+ colorSpace = colorSpace || null
+ var cPtr = copyColorToWasm(color4f);
+ var result = CanvasKit.SkShader._Color(cPtr, colorSpace);
return result;
}
- CanvasKit.SkShader.MakeLinearGradient = function(start, end, colors, pos, mode, localMatrix, flags) {
- var colorPtr = copy2dArray(colors, CanvasKit.HEAPF32);
- var posPtr = copy1dArray(pos, CanvasKit.HEAPF32);
+ CanvasKit.SkShader.MakeLinearGradient = function(start, end, colors, pos, mode, localMatrix, flags, colorSpace) {
+ colorSpace = colorSpace || null
+ var cPtrInfo = copyFlexibleColorArray(colors);
+ var posPtr = copy1dArray(pos, "HEAPF32");
flags = flags || 0;
var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
- var lgs = CanvasKit._MakeLinearGradientShader(start, end, colorPtr, posPtr,
- colors.length, mode, flags, localMatrixPtr);
+ var lgs = CanvasKit._MakeLinearGradientShader(start, end, cPtrInfo.colorPtr, cPtrInfo.colorType, posPtr,
+ cPtrInfo.count, mode, flags, localMatrixPtr, colorSpace);
- CanvasKit._free(localMatrixPtr);
- CanvasKit._free(colorPtr);
- CanvasKit._free(posPtr);
+ freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors);
+ pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos);
return lgs;
}
- CanvasKit.SkShader.MakeRadialGradient = function(center, radius, colors, pos, mode, localMatrix, flags) {
- var colorPtr = copy2dArray(colors, CanvasKit.HEAPF32);
- var posPtr = copy1dArray(pos, CanvasKit.HEAPF32);
+ CanvasKit.SkShader.MakeRadialGradient = function(center, radius, colors, pos, mode, localMatrix, flags, colorSpace) {
+ colorSpace = colorSpace || null
+ var cPtrInfo = copyFlexibleColorArray(colors);
+ var posPtr = copy1dArray(pos, "HEAPF32");
flags = flags || 0;
var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
- var rgs = CanvasKit._MakeRadialGradientShader(center, radius, colorPtr, posPtr,
- colors.length, mode, flags, localMatrixPtr);
+ var rgs = CanvasKit._MakeRadialGradientShader(center, radius, cPtrInfo.colorPtr, cPtrInfo.colorType, posPtr,
+ cPtrInfo.count, mode, flags, localMatrixPtr, colorSpace);
- CanvasKit._free(localMatrixPtr);
- CanvasKit._free(colorPtr);
- CanvasKit._free(posPtr);
+ freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors);
+ pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos);
return rgs;
}
- CanvasKit.SkShader.MakeSweepGradient = function(cx, cy, colors, pos, mode, localMatrix, flags, startAngle, endAngle) {
- var colorPtr = copy2dArray(colors, CanvasKit.HEAPF32);
- var posPtr = copy1dArray(pos, CanvasKit.HEAPF32);
+ CanvasKit.SkShader.MakeSweepGradient = function(cx, cy, colors, pos, mode, localMatrix, flags, startAngle, endAngle, colorSpace) {
+ colorSpace = colorSpace || null
+ var cPtrInfo = copyFlexibleColorArray(colors);
+ var posPtr = copy1dArray(pos, "HEAPF32");
flags = flags || 0;
startAngle = startAngle || 0;
endAngle = endAngle || 360;
var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
- var sgs = CanvasKit._MakeSweepGradientShader(cx, cy, colorPtr, posPtr,
- colors.length, mode,
+ var sgs = CanvasKit._MakeSweepGradientShader(cx, cy, cPtrInfo.colorPtr, cPtrInfo.colorType, posPtr,
+ cPtrInfo.count, mode,
startAngle, endAngle, flags,
- localMatrixPtr);
+ localMatrixPtr, colorSpace);
- CanvasKit._free(localMatrixPtr);
- CanvasKit._free(colorPtr);
- CanvasKit._free(posPtr);
+ freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors);
+ pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos);
return sgs;
}
CanvasKit.SkShader.MakeTwoPointConicalGradient = function(start, startRadius, end, endRadius,
- colors, pos, mode, localMatrix, flags) {
- var colorPtr = copy2dArray(colors, CanvasKit.HEAPF32);
- var posPtr = copy1dArray(pos, CanvasKit.HEAPF32);
+ colors, pos, mode, localMatrix, flags, colorSpace) {
+ colorSpace = colorSpace || null
+ var cPtrInfo = copyFlexibleColorArray(colors);
+ var posPtr = copy1dArray(pos, "HEAPF32");
flags = flags || 0;
var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
var rgs = CanvasKit._MakeTwoPointConicalGradientShader(
- start, startRadius, end, endRadius,
- colorPtr, posPtr, colors.length, mode, flags, localMatrixPtr);
+ start, startRadius, end, endRadius, cPtrInfo.colorPtr, cPtrInfo.colorType,
+ posPtr, cPtrInfo.count, mode, flags, localMatrixPtr, colorSpace);
- CanvasKit._free(localMatrixPtr);
- CanvasKit._free(colorPtr);
- CanvasKit._free(posPtr);
+ freeArraysThatAreNotMallocedByUsers(cPtrInfo.colorPtr, colors);
+ pos && freeArraysThatAreNotMallocedByUsers(posPtr, pos);
return rgs;
}
@@ -1252,17 +1312,25 @@ CanvasKit.onRuntimeInitialized = function() {
// ambient: {r, g, b, a},
// spot: {r, g, b, a},
// }
-// Returns the same format
+// Returns the same format. Note, if malloced colors are passed in, the memory
+// housing the passed in colors passed in will be overwritten with the computed
+// tonal colors.
CanvasKit.computeTonalColors = function(tonalColors) {
- var cPtrAmbi = copy1dArray(tonalColors['ambient'], CanvasKit.HEAPF32);
- var cPtrSpot = copy1dArray(tonalColors['spot'], CanvasKit.HEAPF32);
+ // copy the colors into WASM
+ var cPtrAmbi = copyColorToWasmNoScratch(tonalColors['ambient']);
+ var cPtrSpot = copyColorToWasmNoScratch(tonalColors['spot']);
+ // The output of this function will be the same pointers we passed in.
this._computeTonalColors(cPtrAmbi, cPtrSpot);
+ // Read the results out.
var result = {
'ambient': copyColorFromWasm(cPtrAmbi),
'spot': copyColorFromWasm(cPtrSpot),
- }
+ };
+ // If the user passed us malloced colors in here, we don't want to clean them up.
+ freeArraysThatAreNotMallocedByUsers(cPtrAmbi, tonalColors['ambient']);
+ freeArraysThatAreNotMallocedByUsers(cPtrSpot, tonalColors['spot']);
return result;
-}
+};
CanvasKit.LTRBRect = function(l, t, r, b) {
return {
@@ -1271,7 +1339,7 @@ CanvasKit.LTRBRect = function(l, t, r, b) {
fRight: r,
fBottom: b,
};
-}
+};
CanvasKit.XYWHRect = function(x, y, w, h) {
return {
@@ -1280,7 +1348,7 @@ CanvasKit.XYWHRect = function(x, y, w, h) {
fRight: x+w,
fBottom: y+h,
};
-}
+};
// RRectXY returns an RRect with the given rect and a radiusX and radiusY for
// all 4 corners.
@@ -1296,14 +1364,7 @@ CanvasKit.RRectXY = function(rect, rx, ry) {
rx4: rx,
ry4: ry,
};
-}
-
-CanvasKit.MakePathFromCmds = function(cmds) {
- var ptrLen = loadCmdsTypedArray(cmds);
- var path = CanvasKit._MakePathFromCmds(ptrLen[0], ptrLen[1]);
- CanvasKit._free(ptrLen[0]);
- return path;
-}
+};
// data is a TypedArray or ArrayBuffer e.g. from fetch().then(resp.arrayBuffer())
CanvasKit.MakeAnimatedImageFromEncoded = function(data) {
@@ -1333,23 +1394,61 @@ CanvasKit.MakeImageFromEncoded = function(data) {
return img;
}
-// pixels must be a Uint8Array with bytes representing the pixel values
+// A variable to hold a canvasElement which can be reused once created the first time.
+var memoizedCanvas2dElement = null;
+
+// Alternative to CanvasKit.MakeImageFromEncoded. Allows for CanvasKit users to take advantage of
+// browser APIs to decode images instead of using codecs included in the CanvasKit wasm binary.
+// Expects that the canvasImageSource has already loaded/decoded.
+// CanvasImageSource reference: https://developer.mozilla.org/en-US/docs/Web/API/CanvasImageSource
+CanvasKit.MakeImageFromCanvasImageSource = function(canvasImageSource) {
+ var width = canvasImageSource.width;
+ var height = canvasImageSource.height;
+
+ if (!memoizedCanvas2dElement) {
+ memoizedCanvas2dElement = document.createElement('canvas');
+ }
+ memoizedCanvas2dElement.width = width;
+ memoizedCanvas2dElement.height = height;
+
+ var ctx2d = memoizedCanvas2dElement.getContext('2d');
+ ctx2d.drawImage(canvasImageSource, 0, 0);
+
+ var imageData = ctx2d.getImageData(0, 0, width, height);
+
+ return CanvasKit.MakeImage(
+ imageData.data,
+ width,
+ height,
+ CanvasKit.AlphaType.Unpremul,
+ CanvasKit.ColorType.RGBA_8888,
+ CanvasKit.SkColorSpace.SRGB
+ );
+}
+
+// pixels may be any Typed Array, but Uint8Array or Uint8ClampedArray is recommended,
+// with bytes representing the pixel values.
// (e.g. each set of 4 bytes could represent RGBA values for a single pixel).
-CanvasKit.MakeImage = function(pixels, width, height, alphaType, colorType) {
+CanvasKit.MakeImage = function(pixels, width, height, alphaType, colorType, colorSpace) {
var bytesPerPixel = pixels.length / (width * height);
var info = {
'width': width,
'height': height,
'alphaType': alphaType,
'colorType': colorType,
+ 'colorSpace': colorSpace,
};
- var pptr = copy1dArray(pixels, CanvasKit.HEAPU8);
+ var pptr = copy1dArray(pixels, "HEAPU8");
// No need to _free pptr, Image takes it with SkData::MakeFromMalloc
return CanvasKit._MakeImage(info, pptr, pixels.length, width * bytesPerPixel);
}
-// colors is an array of float color arrays
+// Colors may be a Uint32Array of int colors, a Flat Float32Array of float colors
+// or a 2d Array of Float32Array(4) (deprecated)
+// the underlying skia function accepts only int colors so it is recommended
+// to pass an array of int colors to avoid an extra conversion.
+// SkColorBuilder is not accepted.
CanvasKit.MakeSkVertices = function(mode, positions, textureCoordinates, colors,
indices, isVolatile) {
// Default isVolitile to true if not set
@@ -1368,21 +1467,23 @@ CanvasKit.MakeSkVertices = function(mode, positions, textureCoordinates, colors,
flags |= (1 << 2);
}
- var builder = new CanvasKit._SkVerticesBuilder(mode, positions.length, idxCount, flags);
+ var builder = new CanvasKit._SkVerticesBuilder(mode, positions.length, idxCount, flags);
- copy2dArray(positions, CanvasKit.HEAPF32, builder.positions());
+ copy2dArray(positions, "HEAPF32", builder.positions());
if (builder.texCoords()) {
- copy2dArray(textureCoordinates, CanvasKit.HEAPF32, builder.texCoords());
+ copy2dArray(textureCoordinates, "HEAPF32", builder.texCoords());
}
if (builder.colors()) {
- // Convert from canvaskit 4f colors to 32 bit uint colors which builder supports.
- copy1dArray(colors.map(toUint32Color), CanvasKit.HEAPU32, builder.colors());
+ if (colors.build) {
+ throw('Color builder not accepted by MakeSkVertices, use array of ints');
+ } else {
+ copy1dArray(assureIntColors(colors), "HEAPU32", builder.colors());
+ }
}
if (builder.indices()) {
- copy1dArray(indices, CanvasKit.HEAPU16, builder.indices());
+ copy1dArray(indices, "HEAPU16", builder.indices());
}
- var idxCount = (indices && indices.length) || 0;
// Create the vertices, which owns the memory that the builder had allocated.
return builder.detach();
};
diff --git a/chromium/third_party/skia/modules/canvaskit/karma.conf.js b/chromium/third_party/skia/modules/canvaskit/karma.conf.js
index dd059443682..962176eefc5 100644
--- a/chromium/third_party/skia/modules/canvaskit/karma.conf.js
+++ b/chromium/third_party/skia/modules/canvaskit/karma.conf.js
@@ -57,7 +57,7 @@ module.exports = function(config) {
concurrency: Infinity,
};
- if (isDocker) {
+ if (isDocker || config.headless) {
// See https://hackernoon.com/running-karma-tests-with-headless-chrome-inside-docker-ae4aceb06ed3
cfg.browsers = ['ChromeHeadlessNoSandbox'],
cfg.customLaunchers = {
@@ -76,6 +76,17 @@ module.exports = function(config) {
],
},
};
+ } else {
+ // Extra options that should only be applied locally
+
+ // Measure test coverage and write output to coverage/ directory
+ cfg.reporters.push('coverage');
+ cfg.preprocessors = {
+ // Measure test coverage of these source files
+ // Since this file is a combination of our code, and emscripten's glue,
+ // we'll never see 100% coverage, but this lets us measure improvements.
+ 'canvaskit/bin/canvaskit.js': ['coverage'],
+ };
}
config.set(cfg);
diff --git a/chromium/third_party/skia/modules/canvaskit/package-lock.json b/chromium/third_party/skia/modules/canvaskit/package-lock.json
new file mode 100644
index 00000000000..5fc95f855b7
--- /dev/null
+++ b/chromium/third_party/skia/modules/canvaskit/package-lock.json
@@ -0,0 +1,3494 @@
+{
+ "name": "canvaskit-local",
+ "version": "0.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
+ "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.8.3"
+ }
+ },
+ "@babel/core": {
+ "version": "7.9.6",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.6.tgz",
+ "integrity": "sha512-nD3deLvbsApbHAHttzIssYqgb883yU/d9roe4RZymBCDaZryMJDbptVpEpeQuRh4BJ+SYI8le9YGxKvFEvl1Wg==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.8.3",
+ "@babel/generator": "^7.9.6",
+ "@babel/helper-module-transforms": "^7.9.0",
+ "@babel/helpers": "^7.9.6",
+ "@babel/parser": "^7.9.6",
+ "@babel/template": "^7.8.6",
+ "@babel/traverse": "^7.9.6",
+ "@babel/types": "^7.9.6",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.1",
+ "json5": "^2.1.2",
+ "lodash": "^4.17.13",
+ "resolve": "^1.3.2",
+ "semver": "^5.4.1",
+ "source-map": "^0.5.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
+ }
+ },
+ "@babel/generator": {
+ "version": "7.9.6",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz",
+ "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.9.6",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.13",
+ "source-map": "^0.5.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
+ "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.8.3",
+ "@babel/template": "^7.8.3",
+ "@babel/types": "^7.9.5"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz",
+ "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz",
+ "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz",
+ "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz",
+ "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.8.3",
+ "@babel/helper-replace-supers": "^7.8.6",
+ "@babel/helper-simple-access": "^7.8.3",
+ "@babel/helper-split-export-declaration": "^7.8.3",
+ "@babel/template": "^7.8.6",
+ "@babel/types": "^7.9.0",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz",
+ "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.9.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.9.6.tgz",
+ "integrity": "sha512-qX+chbxkbArLyCImk3bWV+jB5gTNU/rsze+JlcF6Nf8tVTigPJSI1o1oBow/9Resa1yehUO9lIipsmu9oG4RzA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.8.3",
+ "@babel/helper-optimise-call-expression": "^7.8.3",
+ "@babel/traverse": "^7.9.6",
+ "@babel/types": "^7.9.6"
+ }
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz",
+ "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.8.3",
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz",
+ "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz",
+ "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==",
+ "dev": true
+ },
+ "@babel/helpers": {
+ "version": "7.9.6",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.6.tgz",
+ "integrity": "sha512-tI4bUbldloLcHWoRUMAj4g1bF313M/o6fBKhIsb3QnGVPwRm9JsNf/gqMkQ7zjqReABiffPV6RWj7hEglID5Iw==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.8.3",
+ "@babel/traverse": "^7.9.6",
+ "@babel/types": "^7.9.6"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
+ "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.9.0",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.9.6",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz",
+ "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.8.6",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
+ "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.8.3",
+ "@babel/parser": "^7.8.6",
+ "@babel/types": "^7.8.6"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.9.6",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz",
+ "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.8.3",
+ "@babel/generator": "^7.9.6",
+ "@babel/helper-function-name": "^7.9.5",
+ "@babel/helper-split-export-declaration": "^7.8.3",
+ "@babel/parser": "^7.9.6",
+ "@babel/types": "^7.9.6",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/types": {
+ "version": "7.9.6",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz",
+ "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.9.5",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "@istanbuljs/schema": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz",
+ "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==",
+ "dev": true
+ },
+ "accepts": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "dev": true,
+ "requires": {
+ "mime-types": "~2.1.24",
+ "negotiator": "0.6.2"
+ }
+ },
+ "after": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
+ "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "dev": true,
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ },
+ "dependencies": {
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true,
+ "requires": {
+ "remove-trailing-separator": "^1.0.1"
+ }
+ }
+ }
+ },
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "dev": true
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+ "dev": true
+ },
+ "arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+ "dev": true
+ },
+ "array-slice": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz",
+ "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=",
+ "dev": true
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+ "dev": true
+ },
+ "arraybuffer.slice": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
+ "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==",
+ "dev": true
+ },
+ "assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+ "dev": true
+ },
+ "async-each": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
+ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
+ "dev": true
+ },
+ "async-limiter": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
+ "dev": true
+ },
+ "atob": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+ "dev": true
+ },
+ "backo2": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
+ "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+ "dev": true,
+ "requires": {
+ "cache-base": "^1.0.1",
+ "class-utils": "^0.3.5",
+ "component-emitter": "^1.2.1",
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.1",
+ "mixin-deep": "^1.2.0",
+ "pascalcase": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "base64-arraybuffer": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
+ "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=",
+ "dev": true
+ },
+ "base64id": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
+ "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=",
+ "dev": true
+ },
+ "better-assert": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
+ "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
+ "dev": true,
+ "requires": {
+ "callsite": "1.0.0"
+ }
+ },
+ "binary-extensions": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+ "dev": true
+ },
+ "bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
+ "blob": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
+ "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==",
+ "dev": true
+ },
+ "bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+ "dev": true
+ },
+ "body-parser": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+ "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+ "dev": true,
+ "requires": {
+ "bytes": "3.1.0",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "on-finished": "~2.3.0",
+ "qs": "6.7.0",
+ "raw-body": "2.4.0",
+ "type-is": "~1.6.17"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "buffer-alloc": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
+ "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
+ "dev": true,
+ "requires": {
+ "buffer-alloc-unsafe": "^1.1.0",
+ "buffer-fill": "^1.0.0"
+ }
+ },
+ "buffer-alloc-unsafe": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
+ "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
+ "dev": true
+ },
+ "buffer-fill": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
+ "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=",
+ "dev": true
+ },
+ "bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
+ "dev": true
+ },
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+ "dev": true,
+ "requires": {
+ "collection-visit": "^1.0.0",
+ "component-emitter": "^1.2.1",
+ "get-value": "^2.0.6",
+ "has-value": "^1.0.0",
+ "isobject": "^3.0.1",
+ "set-value": "^2.0.0",
+ "to-object-path": "^0.3.0",
+ "union-value": "^1.0.0",
+ "unset-value": "^1.0.0"
+ }
+ },
+ "callsite": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
+ "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "dev": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ }
+ },
+ "circular-json": {
+ "version": "0.5.9",
+ "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz",
+ "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==",
+ "dev": true
+ },
+ "class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+ "dev": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "define-property": "^0.2.5",
+ "isobject": "^3.0.0",
+ "static-extend": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "dev": true,
+ "requires": {
+ "map-visit": "^1.0.0",
+ "object-visit": "^1.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "colors": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
+ "dev": true
+ },
+ "combine-lists": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz",
+ "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.5.0"
+ }
+ },
+ "component-bind": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
+ "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=",
+ "dev": true
+ },
+ "component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
+ "dev": true
+ },
+ "component-inherit": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
+ "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "connect": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
+ "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "finalhandler": "1.1.2",
+ "parseurl": "~1.3.3",
+ "utils-merge": "1.0.1"
+ }
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
+ "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ },
+ "dependencies": {
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ }
+ }
+ },
+ "cookie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
+ "dev": true
+ },
+ "copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+ "dev": true
+ },
+ "core-js": {
+ "version": "2.6.11",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
+ "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==",
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "custom-event": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz",
+ "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=",
+ "dev": true
+ },
+ "date-format": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz",
+ "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=",
+ "dev": true
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+ "dev": true
+ },
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ },
+ "dependencies": {
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+ "dev": true
+ },
+ "di": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz",
+ "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=",
+ "dev": true
+ },
+ "dom-serialize": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz",
+ "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=",
+ "dev": true,
+ "requires": {
+ "custom-event": "~1.0.0",
+ "ent": "~2.2.0",
+ "extend": "^3.0.0",
+ "void-elements": "^2.0.0"
+ }
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
+ "dev": true
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+ "dev": true
+ },
+ "engine.io": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz",
+ "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.4",
+ "base64id": "1.0.0",
+ "cookie": "0.3.1",
+ "debug": "~3.1.0",
+ "engine.io-parser": "~2.1.0",
+ "ws": "~3.3.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "engine.io-client": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz",
+ "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==",
+ "dev": true,
+ "requires": {
+ "component-emitter": "1.2.1",
+ "component-inherit": "0.0.3",
+ "debug": "~3.1.0",
+ "engine.io-parser": "~2.1.1",
+ "has-cors": "1.1.0",
+ "indexof": "0.0.1",
+ "parseqs": "0.0.5",
+ "parseuri": "0.0.5",
+ "ws": "~3.3.1",
+ "xmlhttprequest-ssl": "~1.5.4",
+ "yeast": "0.1.2"
+ },
+ "dependencies": {
+ "component-emitter": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+ "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+ "dev": true
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "engine.io-parser": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz",
+ "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
+ "dev": true,
+ "requires": {
+ "after": "0.8.2",
+ "arraybuffer.slice": "~0.0.7",
+ "base64-arraybuffer": "0.1.5",
+ "blob": "0.0.5",
+ "has-binary2": "~1.0.2"
+ }
+ },
+ "ent": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz",
+ "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=",
+ "dev": true
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "eventemitter3": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz",
+ "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==",
+ "dev": true
+ },
+ "expand-braces": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz",
+ "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=",
+ "dev": true,
+ "requires": {
+ "array-slice": "^0.2.3",
+ "array-unique": "^0.2.1",
+ "braces": "^0.1.2"
+ },
+ "dependencies": {
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+ "dev": true
+ },
+ "braces": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz",
+ "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=",
+ "dev": true,
+ "requires": {
+ "expand-range": "^0.1.0"
+ }
+ }
+ }
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "dev": true,
+ "requires": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "expand-range": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz",
+ "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=",
+ "dev": true,
+ "requires": {
+ "is-number": "^0.1.1",
+ "repeat-string": "^0.2.2"
+ },
+ "dependencies": {
+ "is-number": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz",
+ "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz",
+ "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=",
+ "dev": true
+ }
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "dev": true,
+ "requires": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "dev": true,
+ "requires": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "dev": true,
+ "optional": true
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "statuses": "~1.5.0",
+ "unpipe": "~1.0.0"
+ }
+ },
+ "follow-redirects": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.11.0.tgz",
+ "integrity": "sha512-KZm0V+ll8PfBrKwMzdo5D13b1bur9Iq9Zd/RMmAoQQcl2PxxFml8cxXPaaPYVbV0RjNjq1CU7zIzAOqtUPudmA==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "dev": true,
+ "requires": {
+ "map-cache": "^0.2.2"
+ }
+ },
+ "fs-access": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz",
+ "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=",
+ "dev": true,
+ "requires": {
+ "null-check": "^1.0.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "fsevents": {
+ "version": "1.2.11",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz",
+ "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1",
+ "node-pre-gyp": "*"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "chownr": {
+ "version": "1.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "debug": {
+ "version": "3.2.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "detect-libc": {
+ "version": "1.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "fs-minipass": {
+ "version": "1.2.7",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.6.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ignore-walk": {
+ "version": "3.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "minipass": {
+ "version": "2.9.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.3.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.9.0"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "needle": {
+ "version": "2.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "debug": "^3.2.6",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.14.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4.4.2"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "npm-normalize-package-bin": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "npm-packlist": {
+ "version": "1.4.7",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "semver": {
+ "version": "5.7.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "4.4.13",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.8.6",
+ "minizlib": "^1.2.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.3"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "wide-align": {
+ "version": "1.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "gensync": {
+ "version": "1.0.0-beta.1",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz",
+ "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==",
+ "dev": true
+ },
+ "get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "dev": true,
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true
+ },
+ "graceful-fs": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
+ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
+ "dev": true
+ },
+ "has-binary2": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
+ "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==",
+ "dev": true,
+ "requires": {
+ "isarray": "2.0.1"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+ "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
+ "dev": true
+ }
+ }
+ },
+ "has-cors": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
+ "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "has-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ }
+ },
+ "has-values": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+ "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+ "dev": true,
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.1",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.0"
+ }
+ },
+ "http-proxy": {
+ "version": "1.18.1",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
+ "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
+ "dev": true,
+ "requires": {
+ "eventemitter3": "^4.0.0",
+ "follow-redirects": "^1.0.0",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "indexof": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^1.0.0"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true
+ }
+ }
+ },
+ "is-docker": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-1.1.0.tgz",
+ "integrity": "sha1-8EN01O7lMQ6ajhE78UlUEeRhdqE=",
+ "dev": true
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "isbinaryfile": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz",
+ "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==",
+ "dev": true,
+ "requires": {
+ "buffer-alloc": "^1.2.0"
+ }
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ },
+ "istanbul-lib-coverage": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz",
+ "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==",
+ "dev": true
+ },
+ "istanbul-lib-instrument": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz",
+ "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==",
+ "dev": true,
+ "requires": {
+ "@babel/core": "^7.7.5",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.0.0",
+ "semver": "^6.3.0"
+ }
+ },
+ "istanbul-lib-report": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
+ "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
+ "dev": true,
+ "requires": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^3.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "dependencies": {
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "istanbul-lib-source-maps": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz",
+ "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "istanbul-reports": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz",
+ "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==",
+ "dev": true,
+ "requires": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ }
+ },
+ "jasmine-core": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.1.0.tgz",
+ "integrity": "sha1-pHheE11d9lAk38kiSVPfWFvSdmw=",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
+ },
+ "json5": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
+ "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "karma": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/karma/-/karma-3.0.0.tgz",
+ "integrity": "sha512-ZTjyuDXVXhXsvJ1E4CnZzbCjSxD6sEdzEsFYogLuZM0yqvg/mgz+O+R1jb0J7uAQeuzdY8kJgx6hSNXLwFuHIQ==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.3.0",
+ "body-parser": "^1.16.1",
+ "chokidar": "^2.0.3",
+ "colors": "^1.1.0",
+ "combine-lists": "^1.0.0",
+ "connect": "^3.6.0",
+ "core-js": "^2.2.0",
+ "di": "^0.0.1",
+ "dom-serialize": "^2.2.0",
+ "expand-braces": "^0.1.1",
+ "glob": "^7.1.1",
+ "graceful-fs": "^4.1.2",
+ "http-proxy": "^1.13.0",
+ "isbinaryfile": "^3.0.0",
+ "lodash": "^4.17.4",
+ "log4js": "^3.0.0",
+ "mime": "^2.3.1",
+ "minimatch": "^3.0.2",
+ "optimist": "^0.6.1",
+ "qjobs": "^1.1.4",
+ "range-parser": "^1.2.0",
+ "rimraf": "^2.6.0",
+ "safe-buffer": "^5.0.1",
+ "socket.io": "2.1.1",
+ "source-map": "^0.6.1",
+ "tmp": "0.0.33",
+ "useragent": "2.2.1"
+ }
+ },
+ "karma-chrome-launcher": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz",
+ "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==",
+ "dev": true,
+ "requires": {
+ "fs-access": "^1.0.0",
+ "which": "^1.2.1"
+ }
+ },
+ "karma-coverage": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.0.2.tgz",
+ "integrity": "sha512-zge5qiGEIKDdzWciQwP4p0LSac4k/L6VfrBsERMUn5mpDvxhv1sPVOrSlpzpi70T7NhuEy4bgnpAKIYuumIMCw==",
+ "dev": true,
+ "requires": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^4.0.1",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.0.0",
+ "minimatch": "^3.0.4"
+ }
+ },
+ "karma-jasmine": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.2.tgz",
+ "integrity": "sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM=",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+ "dev": true
+ },
+ "log4js": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz",
+ "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==",
+ "dev": true,
+ "requires": {
+ "circular-json": "^0.5.5",
+ "date-format": "^1.2.0",
+ "debug": "^3.1.0",
+ "rfdc": "^1.1.2",
+ "streamroller": "0.7.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "lru-cache": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz",
+ "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=",
+ "dev": true
+ },
+ "make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "requires": {
+ "semver": "^6.0.0"
+ }
+ },
+ "map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+ "dev": true
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "dev": true,
+ "requires": {
+ "object-visit": "^1.0.0"
+ }
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "mime": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
+ "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
+ "dev": true
+ },
+ "mime-db": {
+ "version": "1.43.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
+ "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.26",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
+ "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.43.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+ "dev": true
+ },
+ "mixin-deep": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+ "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+ "dev": true,
+ "requires": {
+ "for-in": "^1.0.2",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz",
+ "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "nan": {
+ "version": "2.14.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
+ "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
+ "dev": true,
+ "optional": true
+ },
+ "nanomatch": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "fragment-cache": "^0.2.1",
+ "is-windows": "^1.0.2",
+ "kind-of": "^6.0.2",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ }
+ },
+ "negotiator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
+ "dev": true
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "null-check": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz",
+ "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=",
+ "dev": true
+ },
+ "object-component": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
+ "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=",
+ "dev": true
+ },
+ "object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "dev": true,
+ "requires": {
+ "copy-descriptor": "^0.1.0",
+ "define-property": "^0.2.5",
+ "kind-of": "^3.0.3"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "object-visit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.0"
+ }
+ },
+ "object.pick": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "dev": true,
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "optimist": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
+ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
+ "dev": true,
+ "requires": {
+ "minimist": "~0.0.1",
+ "wordwrap": "~0.0.2"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
+ "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
+ "dev": true
+ }
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+ "dev": true
+ },
+ "parseqs": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
+ "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
+ "dev": true,
+ "requires": {
+ "better-assert": "~1.0.0"
+ }
+ },
+ "parseuri": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
+ "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
+ "dev": true,
+ "requires": {
+ "better-assert": "~1.0.0"
+ }
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "dev": true
+ },
+ "pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+ "dev": true
+ },
+ "path-dirname": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "dev": true
+ },
+ "posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true
+ },
+ "qjobs": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz",
+ "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+ "dev": true
+ },
+ "range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "dev": true
+ },
+ "raw-body": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+ "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+ "dev": true,
+ "requires": {
+ "bytes": "3.1.0",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ },
+ "dependencies": {
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ }
+ }
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+ "dev": true
+ },
+ "repeat-element": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
+ "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "dev": true
+ },
+ "requirejs": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz",
+ "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==",
+ "dev": true
+ },
+ "requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+ "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+ "dev": true
+ },
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "dev": true
+ },
+ "rfdc": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz",
+ "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
+ "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
+ "dev": true
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "dev": true,
+ "requires": {
+ "ret": "~0.1.10"
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ },
+ "set-value": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+ "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "setprototypeof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==",
+ "dev": true
+ },
+ "snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "dev": true,
+ "requires": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "dev": true,
+ "requires": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.2.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "socket.io": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz",
+ "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==",
+ "dev": true,
+ "requires": {
+ "debug": "~3.1.0",
+ "engine.io": "~3.2.0",
+ "has-binary2": "~1.0.2",
+ "socket.io-adapter": "~1.1.0",
+ "socket.io-client": "2.1.1",
+ "socket.io-parser": "~3.2.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "socket.io-adapter": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz",
+ "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==",
+ "dev": true
+ },
+ "socket.io-client": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz",
+ "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==",
+ "dev": true,
+ "requires": {
+ "backo2": "1.0.2",
+ "base64-arraybuffer": "0.1.5",
+ "component-bind": "1.0.0",
+ "component-emitter": "1.2.1",
+ "debug": "~3.1.0",
+ "engine.io-client": "~3.2.0",
+ "has-binary2": "~1.0.2",
+ "has-cors": "1.1.0",
+ "indexof": "0.0.1",
+ "object-component": "0.0.3",
+ "parseqs": "0.0.5",
+ "parseuri": "0.0.5",
+ "socket.io-parser": "~3.2.0",
+ "to-array": "0.1.4"
+ },
+ "dependencies": {
+ "component-emitter": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+ "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+ "dev": true
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "socket.io-parser": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz",
+ "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==",
+ "dev": true,
+ "requires": {
+ "component-emitter": "1.2.1",
+ "debug": "~3.1.0",
+ "isarray": "2.0.1"
+ },
+ "dependencies": {
+ "component-emitter": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+ "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+ "dev": true
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "isarray": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+ "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
+ "dev": true
+ }
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "source-map-resolve": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
+ "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
+ "dev": true,
+ "requires": {
+ "atob": "^2.1.2",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "source-map-url": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+ "dev": true
+ },
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.0"
+ }
+ },
+ "static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "dev": true,
+ "requires": {
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+ "dev": true
+ },
+ "streamroller": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz",
+ "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==",
+ "dev": true,
+ "requires": {
+ "date-format": "^1.2.0",
+ "debug": "^3.1.0",
+ "mkdirp": "^0.5.1",
+ "readable-stream": "^2.3.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ },
+ "dependencies": {
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ }
+ }
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "~1.0.2"
+ }
+ },
+ "to-array": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
+ "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=",
+ "dev": true
+ },
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+ "dev": true
+ },
+ "to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "dev": true,
+ "requires": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "toidentifier": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
+ "dev": true
+ },
+ "type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "dev": true,
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ }
+ },
+ "ultron": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
+ "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==",
+ "dev": true
+ },
+ "union-value": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+ "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+ "dev": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^2.0.1"
+ }
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+ "dev": true
+ },
+ "unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "dev": true,
+ "requires": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "dependencies": {
+ "has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true,
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+ "dev": true
+ }
+ }
+ },
+ "upath": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
+ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
+ "dev": true
+ },
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+ "dev": true
+ },
+ "use": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
+ "dev": true
+ },
+ "useragent": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz",
+ "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "2.2.x",
+ "tmp": "0.0.x"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+ "dev": true
+ },
+ "void-elements": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
+ "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=",
+ "dev": true
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "wordwrap": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
+ "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "ws": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
+ "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
+ "dev": true,
+ "requires": {
+ "async-limiter": "~1.0.0",
+ "safe-buffer": "~5.1.0",
+ "ultron": "~1.1.0"
+ },
+ "dependencies": {
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ }
+ }
+ },
+ "xmlhttprequest-ssl": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
+ "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=",
+ "dev": true
+ },
+ "yeast": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
+ "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=",
+ "dev": true
+ }
+ }
+}
diff --git a/chromium/third_party/skia/modules/canvaskit/package.json b/chromium/third_party/skia/modules/canvaskit/package.json
index 33a4a86cb93..24f520b947d 100644
--- a/chromium/third_party/skia/modules/canvaskit/package.json
+++ b/chromium/third_party/skia/modules/canvaskit/package.json
@@ -10,6 +10,7 @@
"jasmine-core": "~3.1.0",
"karma": "~3.0.0",
"karma-chrome-launcher": "~2.2.0",
+ "karma-coverage": "^2.0.2",
"karma-jasmine": "~1.1.2",
"requirejs": "~2.3.5"
},
diff --git a/chromium/third_party/skia/modules/canvaskit/paragraph.js b/chromium/third_party/skia/modules/canvaskit/paragraph.js
index 381e8cb777d..c171a36721d 100644
--- a/chromium/third_party/skia/modules/canvaskit/paragraph.js
+++ b/chromium/third_party/skia/modules/canvaskit/paragraph.js
@@ -15,7 +15,7 @@
var ret = [];
for (var i = 0; i < floatArray.length; i+=5) {
var r = CanvasKit.LTRBRect(floatArray[i], floatArray[i+1], floatArray[i+2], floatArray[i+3]);
- if (floatArray[i+4] === 1) {
+ if (floatArray[i+4] === 0) {
r['direction'] = CanvasKit.TextDirection.RTL;
} else {
r['direction'] = CanvasKit.TextDirection.LTR;
@@ -34,11 +34,8 @@
s['disableHinting'] = s['disableHinting'] || false;
if (s['ellipsis']) {
var str = s['ellipsis'];
- var strLen = lengthBytesUTF8(str) + 1;
- var strPtr = CanvasKit._malloc(strLen);
- stringToUTF8(str, strPtr, strLen);
- s['_ellipsisPtr'] = strPtr;
- s['_ellipsisLen'] = strLen;
+ s['_ellipsisPtr'] = cacheOrCopyString(str);
+ s['_ellipsisLen'] = lengthBytesUTF8(str) + 1; // add 1 for the null terminator.
} else {
s['_ellipsisPtr'] = nullptr;
s['_ellipsisLen'] = 0;
@@ -50,7 +47,7 @@
s['textDirection'] = s['textDirection'] || CanvasKit.TextDirection.LTR;
s['textStyle'] = CanvasKit.TextStyle(s['textStyle']);
return s;
- }
+ };
function fontStyle(s) {
s = s || {};
@@ -65,27 +62,16 @@
CanvasKit.TextStyle = function(s) {
// Use [''] to tell closure not to minify the names
- if (!isCanvasKitColor(s['color'])) {
+ if (!s['color']) {
s['color'] = CanvasKit.BLACK;
}
- s['foregroundColor'] = s['foregroundColor'] || CanvasKit.TRANSPARENT;
- s['backgroundColor'] = s['backgroundColor'] || CanvasKit.TRANSPARENT;
s['decoration'] = s['decoration'] || 0;
s['decorationThickness'] = s['decorationThickness'] || 0;
s['fontSize'] = s['fontSize'] || 0;
- if (Array.isArray(s['fontFamilies']) && s['fontFamilies'].length) {
- var sPtr = naiveCopyStrArray(s['fontFamilies']);
- s['_fontFamilies'] = sPtr;
- s['_numFontFamilies'] = s['fontFamilies'].length;
- } else {
- s['_fontFamilies'] = nullptr;
- s['_numFontFamilies'] = 0;
- SkDebug("no font families provided, text may draw wrong or not at all")
- }
s['fontStyle'] = fontStyle(s['fontStyle']);
return s;
- }
+ };
// returns a pointer to a place on the heap that has an array
// of char* (effectively a char**). For now, this does the naive thing
@@ -100,50 +86,79 @@
}
var sPtrs = [];
for (var i = 0; i < strings.length; i++) {
- var str = strings[i];
- // Add 1 for null terminator, which we need when copying/converting
- var strLen = lengthBytesUTF8(str) + 1;
- var strPtr = CanvasKit._malloc(strLen);
- stringToUTF8(str, strPtr, strLen);
+ var strPtr = cacheOrCopyString(strings[i]);
sPtrs.push(strPtr);
}
- return copy1dArray(sPtrs, CanvasKit.HEAPU32);
+ return copy1dArray(sPtrs, "HEAPU32");
}
- function copyColors(textStyle) {
- // these two color fields were arrays, but will set to WASM pointers before we pass this
+ // maps string -> malloc'd pointer
+ var stringCache = {};
+
+ // cacheOrCopyString copies a string from JS into WASM on the heap and returns the pointer
+ // to the memory of the string. It is expected that a caller to this helper will *not* free
+ // that memory, so it is cached. Thus, if a future call to this function with the same string
+ // will return the cached pointer, preventing the memory usage from growing unbounded (in
+ // a normal use case).
+ function cacheOrCopyString(str) {
+ if (stringCache[str]) {
+ return stringCache[str];
+ }
+ // Add 1 for null terminator, which we need when copying/converting
+ var strLen = lengthBytesUTF8(str) + 1;
+ var strPtr = CanvasKit._malloc(strLen);
+ stringToUTF8(str, strPtr, strLen);
+ stringCache[str] = strPtr;
+ return strPtr;
+ }
+
+ // These scratch arrays are allocated once to copy the color data into, which saves us
+ // having to free them after every invocation.
+ var scratchForegroundColorPtr = CanvasKit._malloc(4 * 4); // room for 4 32bit floats
+ var scratchBackgroundColorPtr = CanvasKit._malloc(4 * 4); // room for 4 32bit floats
+
+ function copyArrays(textStyle) {
+ // These color fields were arrays, but will set to WASM pointers before we pass this
// object over the WASM interface.
- textStyle['colorPtr'] = copy1dArray(textStyle['color'], CanvasKit.HEAPF32);
- textStyle['foregroundColorPtr'] = nullptr; // nullptr is 0, from helper.js
- textStyle['backgroundColorPtr'] = nullptr;
+ textStyle['_colorPtr'] = copyColorToWasm(textStyle['color']);
+ textStyle['_foregroundColorPtr'] = nullptr; // nullptr is 0, from helper.js
+ textStyle['_backgroundColorPtr'] = nullptr;
- if (isCanvasKitColor(textStyle['foregroundColor']) && textStyle['foregroundColor'][3] > 0) {
- textStyle['foregroundColorPtr'] = copy1dArray(textStyle['foregroundColor'], CanvasKit.HEAPF32);
+ if (textStyle['foregroundColor']) {
+ textStyle['_foregroundColorPtr'] = copyColorToWasm(textStyle['foregroundColor'], scratchForegroundColorPtr);
+ }
+ if (textStyle['backgroundColor']) {
+ textStyle['_backgroundColorPtr'] = copyColorToWasm(textStyle['backgroundColor'], scratchBackgroundColorPtr);
}
- if (isCanvasKitColor(textStyle['backgroundColor']) && textStyle['backgroundColor'][3] > 0) {
- textStyle['backgroundColorPtr'] = copy1dArray(textStyle['backgroundColor'], CanvasKit.HEAPF32);
+
+ if (Array.isArray(textStyle['fontFamilies']) && textStyle['fontFamilies'].length) {
+ textStyle['_fontFamiliesPtr'] = naiveCopyStrArray(textStyle['fontFamilies']);
+ textStyle['_fontFamiliesLen'] = textStyle['fontFamilies'].length;
+ } else {
+ textStyle['_fontFamiliesPtr'] = nullptr;
+ textStyle['_fontFamiliesLen'] = 0;
+ SkDebug('no font families provided, text may draw wrong or not at all');
}
- return textStyle;
}
- function freeColors(textStyle) {
- CanvasKit._free(textStyle['colorPtr']);
- CanvasKit._free(textStyle['foregroundColorPtr']);
- CanvasKit._free(textStyle['backgroundColorPtr']);
+ function freeArrays(textStyle) {
+ // The font family strings will get copied to a vector on the C++ side, which is owned by
+ // the text style.
+ CanvasKit._free(textStyle['_fontFamiliesPtr']);
}
CanvasKit.ParagraphBuilder.Make = function(paragraphStyle, fontManager) {
- paragraphStyle['textStyle'] = copyColors(paragraphStyle['textStyle']);
+ copyArrays(paragraphStyle['textStyle']);
var result = CanvasKit.ParagraphBuilder._Make(paragraphStyle, fontManager);
- freeColors(paragraphStyle['textStyle']);
+ freeArrays(paragraphStyle['textStyle']);
return result;
- }
+ };
CanvasKit.ParagraphBuilder.prototype.pushStyle = function(textStyle) {
- var tmpStyle = copyColors(textStyle);
- this._pushStyle(tmpStyle);
- freeColors(tmpStyle);
+ copyArrays(textStyle);
+ this._pushStyle(textStyle);
+ freeArrays(textStyle);
}
});
-}(Module)); // When this file is loaded in, the high level object is "Module"; \ No newline at end of file
+}(Module)); // When this file is loaded in, the high level object is "Module";
diff --git a/chromium/third_party/skia/modules/canvaskit/paragraph_bindings.cpp b/chromium/third_party/skia/modules/canvaskit/paragraph_bindings.cpp
index 92f7b9ebbdf..93142217470 100644
--- a/chromium/third_party/skia/modules/canvaskit/paragraph_bindings.cpp
+++ b/chromium/third_party/skia/modules/canvaskit/paragraph_bindings.cpp
@@ -48,8 +48,8 @@ struct SimpleTextStyle {
SkScalar fontSize;
SimpleFontStyle fontStyle;
- uintptr_t /* const char** */ fontFamilies;
- int numFontFamilies;
+ uintptr_t /* const char** */ fontFamiliesPtr;
+ int fontFamiliesLen;
};
para::TextStyle toTextStyle(const SimpleTextStyle& s) {
@@ -80,10 +80,10 @@ para::TextStyle toTextStyle(const SimpleTextStyle& s) {
ts.setDecorationThicknessMultiplier(s.decorationThickness);
}
- const char** fontFamilies = reinterpret_cast<const char**>(s.fontFamilies);
- if (s.numFontFamilies > 0 && fontFamilies != nullptr) {
+ const char** fontFamilies = reinterpret_cast<const char**>(s.fontFamiliesPtr);
+ if (s.fontFamiliesLen > 0 && fontFamilies != nullptr) {
std::vector<SkString> ff;
- for (int i = 0; i< s.numFontFamilies; i++) {
+ for (int i = 0; i < s.fontFamiliesLen; i++) {
ff.emplace_back(fontFamilies[i]);
}
ts.setFontFamilies(ff);
@@ -279,15 +279,15 @@ EMSCRIPTEN_BINDINGS(Paragraph) {
.field("textStyle", &SimpleParagraphStyle::textStyle);
value_object<SimpleTextStyle>("TextStyle")
- .field("colorPtr", &SimpleTextStyle::colorPtr)
- .field("foregroundColorPtr", &SimpleTextStyle::foregroundColorPtr)
- .field("backgroundColorPtr", &SimpleTextStyle::backgroundColorPtr)
+ .field("_colorPtr", &SimpleTextStyle::colorPtr)
+ .field("_foregroundColorPtr", &SimpleTextStyle::foregroundColorPtr)
+ .field("_backgroundColorPtr", &SimpleTextStyle::backgroundColorPtr)
.field("decoration", &SimpleTextStyle::decoration)
.field("decorationThickness", &SimpleTextStyle::decorationThickness)
- .field("_fontFamilies", &SimpleTextStyle::fontFamilies)
+ .field("_fontFamiliesPtr", &SimpleTextStyle::fontFamiliesPtr)
+ .field("_fontFamiliesLen", &SimpleTextStyle::fontFamiliesLen)
.field("fontSize", &SimpleTextStyle::fontSize)
- .field("fontStyle", &SimpleTextStyle::fontStyle)
- .field("_numFontFamilies", &SimpleTextStyle::numFontFamilies);
+ .field("fontStyle", &SimpleTextStyle::fontStyle);
// The U stands for unsigned - we can't bind a generic/template object, so we have to specify it
// with the type we are using.
diff --git a/chromium/third_party/skia/modules/canvaskit/particles.js b/chromium/third_party/skia/modules/canvaskit/particles.js
index 830a164ce84..24ce748c348 100644
--- a/chromium/third_party/skia/modules/canvaskit/particles.js
+++ b/chromium/third_party/skia/modules/canvaskit/particles.js
@@ -38,9 +38,9 @@ CanvasKit.MakeParticles = function(json, assets) {
// Not entirely sure if it matters, but the uintptr_t are 32 bits
// we want to copy our array of uintptr_t into the right size memory.
- var namesPtr = copy1dArray(assetNamePtrs, CanvasKit.HEAPU32);
- var assetsPtr = copy1dArray(assetDataPtrs, CanvasKit.HEAPU32);
- var assetSizesPtr = copy1dArray(assetSizes, CanvasKit.HEAPU32);
+ var namesPtr = copy1dArray(assetNamePtrs, "HEAPU32");
+ var assetsPtr = copy1dArray(assetDataPtrs, "HEAPU32");
+ var assetSizesPtr = copy1dArray(assetSizes, "HEAPU32");
var particles = CanvasKit._MakeParticles(json, assetKeys.length,
namesPtr, assetsPtr, assetSizesPtr);
@@ -73,4 +73,4 @@ CanvasKit._extraInitializations.push(function() {
}
return new Float32Array(CanvasKit.HEAPU8.buffer, fptr, numFloats);
}
-}); \ No newline at end of file
+});
diff --git a/chromium/third_party/skia/modules/canvaskit/perf/assets/test_1500x959.jpg b/chromium/third_party/skia/modules/canvaskit/perf/assets/test_1500x959.jpg
new file mode 100644
index 00000000000..d27ee59c4aa
--- /dev/null
+++ b/chromium/third_party/skia/modules/canvaskit/perf/assets/test_1500x959.jpg
Binary files differ
diff --git a/chromium/third_party/skia/modules/canvaskit/perf/assets/test_512x512.png b/chromium/third_party/skia/modules/canvaskit/perf/assets/test_512x512.png
new file mode 100644
index 00000000000..c2efb8108df
--- /dev/null
+++ b/chromium/third_party/skia/modules/canvaskit/perf/assets/test_512x512.png
Binary files differ
diff --git a/chromium/third_party/skia/modules/canvaskit/perf/assets/test_64x64.png b/chromium/third_party/skia/modules/canvaskit/perf/assets/test_64x64.png
new file mode 100644
index 00000000000..a3bb32e9f22
--- /dev/null
+++ b/chromium/third_party/skia/modules/canvaskit/perf/assets/test_64x64.png
Binary files differ
diff --git a/chromium/third_party/skia/modules/canvaskit/perf/canvas.bench.js b/chromium/third_party/skia/modules/canvaskit/perf/canvas.bench.js
index 3e822a623c6..1117ad64f1c 100644
--- a/chromium/third_party/skia/modules/canvaskit/perf/canvas.bench.js
+++ b/chromium/third_party/skia/modules/canvaskit/perf/canvas.bench.js
@@ -38,6 +38,77 @@ describe('Basic Canvas ops', () => {
benchmarkAndReport('canvas_drawColor', setup, test, teardown);
});
+ it('can compute tonal colors', () => {
+ function setup(ctx) {};
+
+ function test(ctx) {
+ for (let i = 0; i < 10; i++) {
+ const input = {
+ ambient: randomColor(),
+ spot: randomColor(),
+ };
+ const out = CanvasKit.computeTonalColors(input);
+ if (out.spot[2] > 10 || out.ambient[3] > 10) {
+ // Something to make sure v8 can't optimize away the return value
+ throw 'not possible';
+ }
+ }
+ };
+
+ function teardown(ctx) {};
+
+ benchmarkAndReport('computeTonalColors', setup, test, teardown);
+ });
+
+ function randomColor() {
+ return CanvasKit.Color4f(Math.random(), Math.random(), Math.random(), Math.random());
+ }
+
+ it('can get and set the color to a paint', () => {
+ function setup(ctx) {
+ ctx.paint = new CanvasKit.SkPaint();
+ };
+
+ function test(ctx) {
+ for (let i = 0; i < 10; i++) {
+ ctx.paint.setColor(randomColor());
+ const color = ctx.paint.getColor();
+ if (color[3] > 4) {
+ // Something to make sure v8 can't optimize away the return value
+ throw 'not possible';
+ }
+ }
+ };
+
+ function teardown(ctx) {
+ ctx.paint.delete();
+ };
+
+ benchmarkAndReport('paint_setColor_getColor', setup, test, teardown);
+ });
+
+ it('can set the color to a paint by components', () => {
+ function setup(ctx) {
+ ctx.paint = new CanvasKit.SkPaint();
+ };
+
+ function test(ctx) {
+ const r = Math.random();
+ const g = Math.random();
+ const b = Math.random();
+ const a = Math.random();
+ for (let i = 0; i < 10000; i++) {
+ ctx.paint.setColorComponents(r, g, b, a);
+ }
+ };
+
+ function teardown(ctx) {
+ ctx.paint.delete();
+ };
+
+ benchmarkAndReport('paint_setColorComponents', setup, test, teardown);
+ });
+
it('can draw a shadow with tonal colors', () => {
function setup(ctx) {
ctx.surface = CanvasKit.MakeCanvasSurface('test');
@@ -50,7 +121,7 @@ describe('Basic Canvas ops', () => {
};
const lightRadius = 30;
const flags = 0;
- const lightPos = [250,150,300];
+ const lightPos = [250,150,300];
const zPlaneParams = [0,0,1];
const path = starPath(CanvasKit);
@@ -67,4 +138,100 @@ describe('Basic Canvas ops', () => {
benchmarkAndReport('canvas_drawShadow', setup, test, teardown);
});
+
+ it('can draw a gradient with an array of 1M colors', () => {
+ function setup(ctx) {
+ ctx.surface = CanvasKit.MakeCanvasSurface('test');
+ ctx.canvas = ctx.surface.getCanvas();
+ };
+
+ function test(ctx) {
+ ctx.canvas.clear(CanvasKit.WHITE);
+
+ const num = 1000000;
+ colors = Array(num);
+ positions = Array(num);
+ for (let i=0; i<num; i++) {
+ colors[i] = CanvasKit.Color((i*37)%255, 255, (1-i/num)*255);
+ positions[i] = i/num;
+ }
+
+ const shader = CanvasKit.SkShader.MakeRadialGradient(
+ [300, 300], 50, // center, radius
+ colors, positions,
+ CanvasKit.TileMode.Mirror,
+ );
+ const paint = new CanvasKit.SkPaint();
+ paint.setStyle(CanvasKit.PaintStyle.Fill);
+ paint.setShader(shader);
+ ctx.canvas.drawPaint(paint);
+ ctx.surface.flush();
+ paint.delete();
+ };
+
+ function teardown(ctx) {
+ ctx.surface.delete();
+ };
+
+ benchmarkAndReport('canvas_drawHugeGradient', setup, test, teardown);
+ });
+
+ function NO_OP() {}
+
+ function htmlImageElementToDataURL(htmlImageElement) {
+ const canvas = document.createElement('canvas');
+ canvas.height = htmlImageElement.height;
+ canvas.width = htmlImageElement.width;
+ const ctx = canvas.getContext('2d')
+ ctx.drawImage(htmlImageElement, 0, 0);
+ return canvas.toDataURL();
+ }
+
+ const TEST_IMAGE_FILENAMES = [ 'test_64x64.png', 'test_512x512.png', 'test_1500x959.jpg'];
+ // This for loop generates two perf cases for each test image. One uses browser APIs
+ // to decode an image, and the other uses codecs included in the CanvasKit wasm to decode an
+ // image. wasm codec Image decoding is faster (50 microseconds vs 20000 microseconds), but
+ // including codecs in wasm increases the size of the CanvasKit wasm binary.
+ for (const testImageFilename of TEST_IMAGE_FILENAMES) {
+ const imageResponsePromise = fetch(`/assets/${testImageFilename}`);
+ const imageArrayBufferPromise = imageResponsePromise.then((imageResponse) => imageResponse.arrayBuffer());
+
+ const htmlImageElement = new Image();
+ htmlImageElementLoadPromise = new Promise((resolve) => htmlImageElement.addEventListener('load', resolve));
+ // Create a data url of the image so that load and decode time can be measured
+ // while hopefully ignoring the time of getting the image from disk / the network.
+ imageDataURLPromise = htmlImageElementLoadPromise.then(() => htmlImageElementToDataURL(htmlImageElement));
+ htmlImageElement.src = `/assets/${testImageFilename}`;
+
+ it('can decode an image using HTMLImageElement and Canvas2D', async () => {
+ const imageDataURL = await imageDataURLPromise;
+
+ async function test(ctx) {
+ const image = new Image();
+ // Testing showed that waiting for the load event is faster than waiting for
+ // image.decode().
+ // HTMLImageElement.decode() reference: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decode
+ const promise = new Promise((resolve) => image.addEventListener('load', resolve));
+ image.src = imageDataURL;
+
+ await promise;
+
+ const img = await CanvasKit.MakeImageFromCanvasImageSource(image);
+ img.delete();
+ }
+
+ await asyncBenchmarkAndReport(`canvas_${testImageFilename}_HTMLImageElementDecoding`, NO_OP, test, NO_OP);
+ });
+
+ it('can decode an image using codecs in wasm', async () => {
+ const encodedArrayBuffer = await imageArrayBufferPromise;
+
+ function test(ctx) {
+ const img = CanvasKit.MakeImageFromEncoded(encodedArrayBuffer);
+ img.delete();
+ }
+
+ benchmarkAndReport(`canvas_${testImageFilename}_wasmImageDecoding`, NO_OP, test, NO_OP);
+ });
+ }
});
diff --git a/chromium/third_party/skia/modules/canvaskit/ready.js b/chromium/third_party/skia/modules/canvaskit/ready.js
deleted file mode 100644
index 60f24862d9e..00000000000
--- a/chromium/third_party/skia/modules/canvaskit/ready.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// See https://github.com/kripken/emscripten/issues/5820#issuecomment-385722568
-// for context on why the .then() that comes with Module breaks things (e.g. infinite loops)
-// and why the below fixes it.
-Module['ready'] = function() {
- return new Promise(function (resolve, reject) {
- Module['onAbort'] = reject;
- if (runtimeInitialized) {
- resolve(Module);
- } else {
- addOnPostRun(function() {
- resolve(Module);
- });
- }
- });
-}
-delete Module['then']; \ No newline at end of file
diff --git a/chromium/third_party/skia/modules/canvaskit/rt_shader.js b/chromium/third_party/skia/modules/canvaskit/rt_shader.js
index c3771693d1a..6dc21f06963 100644
--- a/chromium/third_party/skia/modules/canvaskit/rt_shader.js
+++ b/chromium/third_party/skia/modules/canvaskit/rt_shader.js
@@ -2,19 +2,17 @@ CanvasKit._extraInitializations = CanvasKit._extraInitializations || [];
CanvasKit._extraInitializations.push(function() {
CanvasKit.SkRuntimeEffect.prototype.makeShader = function(floats, isOpaque, localMatrix) {
// We don't need to free these floats because they will become owned by the shader.
- var fptr = copy1dArray(floats, CanvasKit.HEAPF32);
+ var fptr = copy1dArray(floats, "HEAPF32");
var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
// Our array has 4 bytes per float, so be sure to account for that before
// sending it over the wire.
- var rts = this._makeShader(fptr, floats.length * 4, !!isOpaque, localMatrixPtr);
- CanvasKit._free(localMatrixPtr);
- return rts;
+ return this._makeShader(fptr, floats.length * 4, !!isOpaque, localMatrixPtr);
}
// childrenWithShaders is an array of other shaders (e.g. SkImage.makeShader())
CanvasKit.SkRuntimeEffect.prototype.makeShaderWithChildren = function(floats, isOpaque, childrenShaders, localMatrix) {
// We don't need to free these floats because they will become owned by the shader.
- var fptr = copy1dArray(floats, CanvasKit.HEAPF32);
+ var fptr = copy1dArray(floats, "HEAPF32");
var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
var barePointers = [];
for (var i = 0; i < childrenShaders.length; i++) {
@@ -22,12 +20,10 @@ CanvasKit._extraInitializations.push(function() {
// and send that over the wire, so it can be re-wrapped as an sk_sp.
barePointers.push(childrenShaders[i].$$.ptr);
}
- var childrenPointers = copy1dArray(barePointers, CanvasKit.HEAPU32);
+ var childrenPointers = copy1dArray(barePointers, "HEAPU32");
// Our array has 4 bytes per float, so be sure to account for that before
// sending it over the wire.
- var rts = this._makeShaderWithChildren(fptr, floats.length * 4, !!isOpaque, childrenPointers,
- barePointers.length, localMatrixPtr);
- CanvasKit._free(localMatrixPtr);
- return rts;
+ return this._makeShaderWithChildren(fptr, floats.length * 4, !!isOpaque, childrenPointers,
+ barePointers.length, localMatrixPtr);
}
-}); \ No newline at end of file
+});
diff --git a/chromium/third_party/skia/modules/canvaskit/skottie.js b/chromium/third_party/skia/modules/canvaskit/skottie.js
index a52470658b7..f07eea51b30 100644
--- a/chromium/third_party/skia/modules/canvaskit/skottie.js
+++ b/chromium/third_party/skia/modules/canvaskit/skottie.js
@@ -38,9 +38,9 @@ CanvasKit.MakeManagedAnimation = function(json, assets) {
// Not entirely sure if it matters, but the uintptr_t are 32 bits
// we want to copy our array of uintptr_t into the right size memory.
- var namesPtr = copy1dArray(assetNamePtrs, CanvasKit.HEAPU32);
- var assetsPtr = copy1dArray(assetDataPtrs, CanvasKit.HEAPU32);
- var assetSizesPtr = copy1dArray(assetSizes, CanvasKit.HEAPU32);
+ var namesPtr = copy1dArray(assetNamePtrs, "HEAPU32");
+ var assetsPtr = copy1dArray(assetDataPtrs, "HEAPU32");
+ var assetSizesPtr = copy1dArray(assetSizes, "HEAPU32");
var anim = CanvasKit._MakeManagedAnimation(json, assetKeys.length, namesPtr,
assetsPtr, assetSizesPtr);
@@ -58,10 +58,9 @@ CanvasKit.MakeManagedAnimation = function(json, assets) {
CanvasKit._extraInitializations.push(function() {
CanvasKit.ManagedAnimation.prototype.setColor = function(key, color) {
- var cPtr = copy1dArray(color, CanvasKit.HEAPF32);
+ var cPtr = copyColorToWasm(color);
this._setColor(key, cPtr);
- CanvasKit._free(cPtr);
}
});
-}(Module)); // When this file is loaded in, the high level object is "Module"; \ No newline at end of file
+}(Module)); // When this file is loaded in, the high level object is "Module";
diff --git a/chromium/third_party/skia/modules/canvaskit/viewer_bindings.cpp b/chromium/third_party/skia/modules/canvaskit/viewer_bindings.cpp
index 66466ef5883..c73408e47f5 100644
--- a/chromium/third_party/skia/modules/canvaskit/viewer_bindings.cpp
+++ b/chromium/third_party/skia/modules/canvaskit/viewer_bindings.cpp
@@ -8,24 +8,66 @@
#include <emscripten.h>
#include <emscripten/bind.h>
#include "include/core/SkCanvas.h"
+#include "include/core/SkSurface.h"
+#include "include/gpu/GrContext.h"
+#include "tools/skui/InputState.h"
+#include "tools/skui/ModifierKey.h"
+#include "tools/viewer/SKPSlide.h"
#include "tools/viewer/SampleSlide.h"
+#include "tools/viewer/SvgSlide.h"
+#include <GLES3/gl3.h>
#include <string>
using namespace emscripten;
+static sk_sp<Slide> MakeSlide(std::string name) {
+ if (name == "PathText") {
+ extern Sample* MakePathTextSample();
+ return sk_make_sp<SampleSlide>(MakePathTextSample);
+ }
+ if (name == "TessellatedWedge") {
+ extern Sample* MakeTessellatedWedgeSample();
+ return sk_make_sp<SampleSlide>(MakeTessellatedWedgeSample);
+ }
+ return nullptr;
+}
+
+static sk_sp<Slide> MakeSkpSlide(std::string name, std::string skpData) {
+ auto stream = std::make_unique<SkMemoryStream>(skpData.data(), skpData.size(),
+ /*copyData=*/true);
+ return sk_make_sp<SKPSlide>(SkString(name.c_str()), std::move(stream));
+}
+
+static sk_sp<Slide> MakeSvgSlide(std::string name, std::string svgText) {
+ auto stream = std::make_unique<SkMemoryStream>(svgText.data(), svgText.size(),
+ /*copyData=*/true);
+ return sk_make_sp<SvgSlide>(SkString(name.c_str()), std::move(stream));
+}
+
EMSCRIPTEN_BINDINGS(Viewer) {
- function("MakeSlide", optional_override([](std::string name)->sk_sp<Slide> {
- if (name == "WavyPathText") {
- extern Sample* MakeWavyPathTextSample();
- return sk_make_sp<SampleSlide>(MakeWavyPathTextSample);
- }
- return nullptr;
- }));
+ function("MakeSlide", &MakeSlide);
+ function("MakeSkpSlide", &MakeSkpSlide);
+ function("MakeSvgSlide", &MakeSvgSlide);
class_<Slide>("Slide")
.smart_ptr<sk_sp<Slide>>("sk_sp<Slide>")
.function("load", &Slide::load)
.function("animate", &Slide::animate)
.function("draw", optional_override([](Slide& self, SkCanvas& canvas) {
self.draw(&canvas);
- }));
+ }))
+ .function("onChar", &Slide::onChar)
+ .function("onMouse", &Slide::onMouse);
+ enum_<skui::InputState>("InputState")
+ .value("Down", skui::InputState::kDown)
+ .value("Up", skui::InputState::kUp)
+ .value("Move", skui::InputState::kMove)
+ .value("Right", skui::InputState::kRight)
+ .value("Left", skui::InputState::kLeft);
+ enum_<skui::ModifierKey>("ModifierKey")
+ .value("None", skui::ModifierKey::kNone)
+ .value("Shift", skui::ModifierKey::kShift)
+ .value("Control", skui::ModifierKey::kControl)
+ .value("Option", skui::ModifierKey::kOption)
+ .value("Command", skui::ModifierKey::kCommand)
+ .value("FirstPress", skui::ModifierKey::kFirstPress);
}
diff --git a/chromium/third_party/skia/modules/particles/src/SkParticleEffect.cpp b/chromium/third_party/skia/modules/particles/src/SkParticleEffect.cpp
index 1cca0608bfc..55c1bba74dc 100644
--- a/chromium/third_party/skia/modules/particles/src/SkParticleEffect.cpp
+++ b/chromium/third_party/skia/modules/particles/src/SkParticleEffect.cpp
@@ -121,6 +121,7 @@ void SkParticleEffectParams::prepare(const skresources::ResourceProvider* resour
auto buildProgram = [this](const SkSL::String& code, Program* p) {
SkSL::Compiler compiler;
SkSL::Program::Settings settings;
+ settings.fRemoveDeadFunctions = false;
SkTArray<std::unique_ptr<SkParticleExternalValue>> externalValues;
diff --git a/chromium/third_party/skia/modules/pathkit/CHANGELOG.md b/chromium/third_party/skia/modules/pathkit/CHANGELOG.md
index dc0b62811cb..9b968bd55cc 100644
--- a/chromium/third_party/skia/modules/pathkit/CHANGELOG.md
+++ b/chromium/third_party/skia/modules/pathkit/CHANGELOG.md
@@ -7,7 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Changed
- - Updated to emscripten 1.39.6
+ - Updated to emscripten 1.39.16
+
+### Breaking
+ - `PathKitInit(...)` now directly returns a Promise. As such, `PathKitInit(...).ready()`
+ has been removed.
## [0.6.0] 2019-02-25
diff --git a/chromium/third_party/skia/modules/pathkit/compile.sh b/chromium/third_party/skia/modules/pathkit/compile.sh
index 7d4660d321c..32cd53c0afc 100755
--- a/chromium/third_party/skia/modules/pathkit/compile.sh
+++ b/chromium/third_party/skia/modules/pathkit/compile.sh
@@ -93,7 +93,7 @@ echo "Compiling bitcode"
--args="cc=\"${EMCC}\" \
cxx=\"${EMCXX}\" \
ar=\"${EMAR}\" \
- extra_cflags=[\"-DSK_DISABLE_READBUFFER=1\",\"-s\", \"WARN_UNALIGNED=1\",
+ extra_cflags=[\"-s\", \"WARN_UNALIGNED=1\",
\"-s\", \"MAIN_MODULE=1\",
${EXTRA_CFLAGS}
] \
@@ -110,10 +110,9 @@ echo "Generating WASM"
${EMCXX} $RELEASE_CONF -std=c++17 \
-I. \
--bind \
+--no-entry \
--pre-js $BASE_DIR/helper.js \
--pre-js $BASE_DIR/chaining.js \
---post-js $BASE_DIR/ready.js \
--DSK_DISABLE_READBUFFER=1 \
-fno-rtti -fno-exceptions -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 \
$WASM_CONF \
-s ERROR_ON_UNDEFINED_SYMBOLS=1 \
diff --git a/chromium/third_party/skia/modules/pathkit/npm-asmjs/README.md b/chromium/third_party/skia/modules/pathkit/npm-asmjs/README.md
index ff71af1b764..ac05297a4aa 100644
--- a/chromium/third_party/skia/modules/pathkit/npm-asmjs/README.md
+++ b/chromium/third_party/skia/modules/pathkit/npm-asmjs/README.md
@@ -5,7 +5,7 @@ To use the library, run `npm install pathkit-asmjs` and then simply include it:
<script src="/node_modules/pathkit-asmjs/bin/pathkit.js"></script>
PathKitInit({
locateFile: (file) => '/node_modules/pathkit-asmjs/bin/'+file,
- }).ready().then((PathKit) => {
+ }).then((PathKit) => {
// Code goes here using PathKit
});
@@ -14,7 +14,7 @@ a global `PathKitInit` that can be called to load the WASM code. The `locateFile
is used to tell the JS loader where to find the .js.mem file. By default, it will
look for /pathkit.js.mem, so if this is not the case, use `locateFile` to configure
this properly.
-The `PathKit` object returned upon resolution of the .ready() Promise is fully loaded and ready to use.
+The `PathKit` object returned upon resolution of the PathKitInit Promise is fully loaded and ready to use.
See the [API page](https://skia.org/user/modules/pathkit) and
[example.html](https://github.com/google/skia/blob/master/modules/pathkit/npm-asmjs/example.html)
@@ -29,7 +29,7 @@ used with just a few configuration changes.
In the JS code, use require():
const PathKitInit = require('pathkit-asmjs/bin/pathkit.js')
- PathKitInit().ready().then((PathKit) => {
+ PathKitInit().then((PathKit) => {
// Code goes here using PathKit
})
diff --git a/chromium/third_party/skia/modules/pathkit/npm-asmjs/example.html b/chromium/third_party/skia/modules/pathkit/npm-asmjs/example.html
index a2fc4c18902..c50c453e1af 100644
--- a/chromium/third_party/skia/modules/pathkit/npm-asmjs/example.html
+++ b/chromium/third_party/skia/modules/pathkit/npm-asmjs/example.html
@@ -53,7 +53,7 @@
PathKitInit({
locateFile: (file) => '/node_modules/pathkit-asmjs/bin/'+file,
- }).ready().then((PathKit) => {
+ }).then((PathKit) => {
window.PathKit = PathKit;
OutputsExample(PathKit);
Path2DExample(PathKit);
diff --git a/chromium/third_party/skia/modules/pathkit/npm-wasm/README.md b/chromium/third_party/skia/modules/pathkit/npm-wasm/README.md
index 815e417d8f5..2e7a6d74b83 100644
--- a/chromium/third_party/skia/modules/pathkit/npm-wasm/README.md
+++ b/chromium/third_party/skia/modules/pathkit/npm-wasm/README.md
@@ -5,7 +5,7 @@ To use the library, run `npm install pathkit-wasm` and then simply include it:
<script src="/node_modules/pathkit-wasm/bin/pathkit.js"></script>
PathKitInit({
locateFile: (file) => '/node_modules/pathkit-wasm/bin/'+file,
- }).ready().then((PathKit) => {
+ }).then((PathKit) => {
// Code goes here using PathKit
});
@@ -14,7 +14,7 @@ a global `PathKitInit` that can be called to load the WASM code. The `locateFile
is used to tell the JS loader where to find the .wasm file. By default, it will
look for /pathkit.wasm, so if this is not the case, use `locateFile` to configure
this properly.
-The `PathKit` object returned upon resolution of the .ready() Promise is fully loaded and ready to use.
+The `PathKit` object returned upon resolution of the PathKitInit Promise is fully loaded and ready to use.
See the [API page](https://skia.org/user/modules/pathkit) and
[example.html](https://github.com/google/skia/blob/master/modules/pathkit/npm-wasm/example.html)
@@ -29,7 +29,7 @@ used with a few configuration changes.
In the JS code, use require():
const PathKitInit = require('pathkit-wasm/bin/pathkit.js')
- PathKitInit().ready().then((PathKit) => {
+ PathKitInit().then((PathKit) => {
// Code goes here using PathKit
})
diff --git a/chromium/third_party/skia/modules/pathkit/npm-wasm/example.html b/chromium/third_party/skia/modules/pathkit/npm-wasm/example.html
index d7c2469a992..488f6ecbed8 100644
--- a/chromium/third_party/skia/modules/pathkit/npm-wasm/example.html
+++ b/chromium/third_party/skia/modules/pathkit/npm-wasm/example.html
@@ -53,7 +53,7 @@
PathKitInit({
locateFile: (file) => '/node_modules/pathkit-wasm/bin/'+file,
- }).ready().then((PathKit) => {
+ }).then((PathKit) => {
window.PathKit = PathKit;
OutputsExample(PathKit);
Path2DExample(PathKit);
diff --git a/chromium/third_party/skia/modules/pathkit/pathkit_wasm_bindings.cpp b/chromium/third_party/skia/modules/pathkit/pathkit_wasm_bindings.cpp
index 56db3e186dc..30ecd21ffd5 100644
--- a/chromium/third_party/skia/modules/pathkit/pathkit_wasm_bindings.cpp
+++ b/chromium/third_party/skia/modules/pathkit/pathkit_wasm_bindings.cpp
@@ -259,31 +259,36 @@ SkPathOrNull EMSCRIPTEN_KEEPALIVE ResolveBuilder(SkOpBuilder& builder) {
//========================================================================================
void EMSCRIPTEN_KEEPALIVE ToCanvas(const SkPath& path, emscripten::val /* Path2D or Canvas*/ ctx) {
- for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
+ SkPath::Iter iter(path, false);
+ SkPoint pts[4];
+ SkPath::Verb verb;
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
switch (verb) {
- case SkPathVerb::kMove:
+ case SkPath::kMove_Verb:
ctx.call<void>("moveTo", pts[0].x(), pts[0].y());
break;
- case SkPathVerb::kLine:
+ case SkPath::kLine_Verb:
ctx.call<void>("lineTo", pts[1].x(), pts[1].y());
break;
- case SkPathVerb::kQuad:
+ case SkPath::kQuad_Verb:
ctx.call<void>("quadraticCurveTo", pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y());
break;
- case SkPathVerb::kConic:
+ case SkPath::kConic_Verb:
SkPoint quads[5];
// approximate with 2^1=2 quads.
- SkPath::ConvertConicToQuads(pts[0], pts[1], pts[2], *w, quads, 1);
+ SkPath::ConvertConicToQuads(pts[0], pts[1], pts[2], iter.conicWeight(), quads, 1);
ctx.call<void>("quadraticCurveTo", quads[1].x(), quads[1].y(), quads[2].x(), quads[2].y());
ctx.call<void>("quadraticCurveTo", quads[3].x(), quads[3].y(), quads[4].x(), quads[4].y());
break;
- case SkPathVerb::kCubic:
+ case SkPath::kCubic_Verb:
ctx.call<void>("bezierCurveTo", pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y(),
pts[3].x(), pts[3].y());
break;
- case SkPathVerb::kClose:
+ case SkPath::kClose_Verb:
ctx.call<void>("closePath");
break;
+ case SkPath::kDone_Verb:
+ break;
}
}
}
diff --git a/chromium/third_party/skia/modules/pathkit/perf/perfReporter.js b/chromium/third_party/skia/modules/pathkit/perf/perfReporter.js
index 35fd3590bc5..d2211d231cb 100644
--- a/chromium/third_party/skia/modules/pathkit/perf/perfReporter.js
+++ b/chromium/third_party/skia/modules/pathkit/perf/perfReporter.js
@@ -51,6 +51,55 @@ function benchmarkAndReport(benchName, setupFn, testFn, teardownFn) {
}
}
+// The same as benchmarkAndReport, except expects the third parameter, testFn, to return a promise
+async function asyncBenchmarkAndReport(benchName, setupFn, testFn, teardownFn) {
+ try {
+ let ctx = {};
+ // warmup 3 times (arbitrary choice)
+ setupFn(ctx);
+ await testFn(ctx);
+ await testFn(ctx);
+ await testFn(ctx);
+ teardownFn(ctx);
+
+ ctx = {};
+ setupFn(ctx);
+ let start = Date.now();
+ let now = start;
+ times = 0;
+ // See how many times we can do it in 100ms (arbitrary choice)
+ while (now - start < 100) {
+ await testFn(ctx);
+ now = Date.now();
+ times++;
+ }
+
+ teardownFn(ctx);
+
+ // Try to make it go for 2 seconds (arbitrarily chosen)
+ // Since the pre-try took 100ms, multiply by 20 to get
+ // approximate tries in 2s (unless now - start >> 100 ms)
+ let goalTimes = times * 20;
+ ctx = {};
+ setupFn(ctx);
+ times = 0;
+ start = Date.now();
+ while (times < goalTimes) {
+ await testFn(ctx);
+ times++;
+ }
+ const end = Date.now();
+ teardownFn(ctx);
+
+ const us = (end - start) * 1000 / times;
+ console.log(benchName, `${us} microseconds`)
+ return _report(us, benchName);
+ } catch(e) {
+ console.error('caught error', e);
+ return Promise.reject(e);
+ }
+}
+
function _report(microseconds, benchName) {
return fetch(REPORT_URL, {
diff --git a/chromium/third_party/skia/modules/pathkit/ready.js b/chromium/third_party/skia/modules/pathkit/ready.js
deleted file mode 100644
index 60f24862d9e..00000000000
--- a/chromium/third_party/skia/modules/pathkit/ready.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// See https://github.com/kripken/emscripten/issues/5820#issuecomment-385722568
-// for context on why the .then() that comes with Module breaks things (e.g. infinite loops)
-// and why the below fixes it.
-Module['ready'] = function() {
- return new Promise(function (resolve, reject) {
- Module['onAbort'] = reject;
- if (runtimeInitialized) {
- resolve(Module);
- } else {
- addOnPostRun(function() {
- resolve(Module);
- });
- }
- });
-}
-delete Module['then']; \ No newline at end of file
diff --git a/chromium/third_party/skia/modules/skottie/gm/ExternalProperties.cpp b/chromium/third_party/skia/modules/skottie/gm/ExternalProperties.cpp
index 786a95d0d7e..0b82ba5654e 100644
--- a/chromium/third_party/skia/modules/skottie/gm/ExternalProperties.cpp
+++ b/chromium/third_party/skia/modules/skottie/gm/ExternalProperties.cpp
@@ -25,14 +25,15 @@ static constexpr char kSkottieResource[] = "skottie/skottie_sample_webfont.json"
// Dummy web font loader which serves a single local font (checked in under resources/).
class FakeWebFontProvider final : public skresources::ResourceProvider {
public:
- FakeWebFontProvider() : fFontData(GetResourceAsData(kWebFontResource)) {}
+ FakeWebFontProvider()
+ : fTypeface(SkTypeface::MakeFromData(GetResourceAsData(kWebFontResource))) {}
- sk_sp<SkData> loadFont(const char[], const char[]) const override {
- return fFontData;
+ sk_sp<SkTypeface> loadTypeface(const char[], const char[]) const override {
+ return fTypeface;
}
private:
- sk_sp<SkData> fFontData;
+ sk_sp<SkTypeface> fTypeface;
using INHERITED = skresources::ResourceProvider;
};
diff --git a/chromium/third_party/skia/modules/skottie/gm/SkottieGM.cpp b/chromium/third_party/skia/modules/skottie/gm/SkottieGM.cpp
index 03b0b757841..6365d179b31 100644
--- a/chromium/third_party/skia/modules/skottie/gm/SkottieGM.cpp
+++ b/chromium/third_party/skia/modules/skottie/gm/SkottieGM.cpp
@@ -25,14 +25,15 @@ static constexpr char kSkottieResource[] = "skottie/skottie_sample_webfont.json"
// Dummy web font loader which serves a single local font (checked in under resources/).
class FakeWebFontProvider final : public skresources::ResourceProvider {
public:
- FakeWebFontProvider() : fFontData(GetResourceAsData(kWebFontResource)) {}
+ FakeWebFontProvider()
+ : fTypeface(SkTypeface::MakeFromData(GetResourceAsData(kWebFontResource))) {}
- sk_sp<SkData> loadFont(const char[], const char[]) const override {
- return fFontData;
+ sk_sp<SkTypeface> loadTypeface(const char[], const char[]) const override {
+ return fTypeface;
}
private:
- sk_sp<SkData> fFontData;
+ sk_sp<SkTypeface> fTypeface;
using INHERITED = skresources::ResourceProvider;
};
diff --git a/chromium/third_party/skia/modules/skottie/include/Skottie.h b/chromium/third_party/skia/modules/skottie/include/Skottie.h
index 6e7d643b806..c519068b430 100644
--- a/chromium/third_party/skia/modules/skottie/include/Skottie.h
+++ b/chromium/third_party/skia/modules/skottie/include/Skottie.h
@@ -14,6 +14,7 @@
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "modules/skottie/include/ExternalLayer.h"
+#include "modules/skottie/include/SkottieProperty.h"
#include "modules/skresources/include/SkResources.h"
#include <memory>
@@ -39,8 +40,6 @@ namespace internal { class Animator; }
using ImageAsset = skresources::ImageAsset;
using ResourceProvider = skresources::ResourceProvider;
-class PropertyObserver;
-
/**
* A Logger subclass can be used to receive Animation::Builder parsing errors and warnings.
*/
@@ -68,9 +67,11 @@ public:
class Builder final {
public:
enum Flags : uint32_t {
- kDeferImageLoading = 0x01, // Normally, all static image frames are resolved at
- // load time via ImageAsset::getFrame(0). With this flag,
- // frames are only resolved when needed, at seek() time.
+ kDeferImageLoading = 0x01, // Normally, all static image frames are resolved at
+ // load time via ImageAsset::getFrame(0). With this flag,
+ // frames are only resolved when needed, at seek() time.
+ kPreferEmbeddedFonts = 0x02, // Attempt to use the embedded fonts (glyph paths,
+ // normally used as fallback) over native Skia typefaces.
};
explicit Builder(uint32_t flags = 0);
diff --git a/chromium/third_party/skia/modules/skottie/src/Layer.cpp b/chromium/third_party/skia/modules/skottie/src/Layer.cpp
index 3a7e1630173..575e0b2d5c9 100644
--- a/chromium/third_party/skia/modules/skottie/src/Layer.cpp
+++ b/chromium/third_party/skia/modules/skottie/src/Layer.cpp
@@ -275,9 +275,10 @@ private:
LayerBuilder::LayerBuilder(const skjson::ObjectValue& jlayer)
: fJlayer(jlayer)
- , fIndex(ParseDefault<int>(jlayer["ind"], -1))
+ , fIndex (ParseDefault<int>(jlayer["ind" ], -1))
, fParentIndex(ParseDefault<int>(jlayer["parent"], -1))
- , fType(ParseDefault<int>(jlayer["ty"], -1)) {
+ , fType (ParseDefault<int>(jlayer["ty" ], -1))
+ , fAutoOrient (ParseDefault<int>(jlayer["ao" ], 0)) {
if (this->isCamera() || ParseDefault<int>(jlayer["ddd"], 0)) {
fFlags |= Flags::kIs3D;
@@ -363,8 +364,8 @@ sk_sp<sksg::Transform> LayerBuilder::doAttachTransform(const AnimationBuilder& a
}
return this->is3D()
- ? abuilder.attachMatrix3D(*jtransform, std::move(parent_transform))
- : abuilder.attachMatrix2D(*jtransform, std::move(parent_transform));
+ ? abuilder.attachMatrix3D(*jtransform, std::move(parent_transform), fAutoOrient)
+ : abuilder.attachMatrix2D(*jtransform, std::move(parent_transform), fAutoOrient);
}
bool LayerBuilder::hasMotionBlur(const CompositionBuilder* cbuilder) const {
diff --git a/chromium/third_party/skia/modules/skottie/src/Layer.h b/chromium/third_party/skia/modules/skottie/src/Layer.h
index 3a1f6f2bf6f..5d29b203287 100644
--- a/chromium/third_party/skia/modules/skottie/src/Layer.h
+++ b/chromium/third_party/skia/modules/skottie/src/Layer.h
@@ -63,6 +63,7 @@ private:
const int fIndex;
const int fParentIndex;
const int fType;
+ const bool fAutoOrient;
sk_sp<sksg::Transform> fLayerTransform; // this layer's transform node.
sk_sp<sksg::Transform> fTransformCache[2]; // cached 2D/3D chain for the local node
diff --git a/chromium/third_party/skia/modules/skottie/src/SkottiePriv.h b/chromium/third_party/skia/modules/skottie/src/SkottiePriv.h
index b12b8e4c67d..398ecd795ae 100644
--- a/chromium/third_party/skia/modules/skottie/src/SkottiePriv.h
+++ b/chromium/third_party/skia/modules/skottie/src/SkottiePriv.h
@@ -14,6 +14,7 @@
#include "include/core/SkString.h"
#include "include/core/SkTypeface.h"
#include "include/private/SkTHash.h"
+#include "include/utils/SkCustomTypeface.h"
#include "modules/skottie/include/SkottieProperty.h"
#include "modules/skottie/src/animator/Animator.h"
#include "modules/sksg/include/SkSGScene.h"
@@ -63,10 +64,12 @@ public:
AnimationInfo parse(const skjson::ObjectValue&);
struct FontInfo {
- SkString fFamily,
- fStyle;
- SkScalar fAscentPct;
- sk_sp<SkTypeface> fTypeface;
+ SkString fFamily,
+ fStyle,
+ fPath;
+ SkScalar fAscentPct;
+ sk_sp<SkTypeface> fTypeface;
+ SkCustomTypefaceBuilder fCustomBuilder;
bool matches(const char family[], const char style[]) const;
};
@@ -74,8 +77,10 @@ public:
void log(Logger::Level, const skjson::Value*, const char fmt[], ...) const;
- sk_sp<sksg::Transform> attachMatrix2D(const skjson::ObjectValue&, sk_sp<sksg::Transform>) const;
- sk_sp<sksg::Transform> attachMatrix3D(const skjson::ObjectValue&, sk_sp<sksg::Transform>) const;
+ sk_sp<sksg::Transform> attachMatrix2D(const skjson::ObjectValue&, sk_sp<sksg::Transform>,
+ bool auto_orient = false) const;
+ sk_sp<sksg::Transform> attachMatrix3D(const skjson::ObjectValue&, sk_sp<sksg::Transform>,
+ bool auto_orient = false) const;
sk_sp<sksg::Transform> attachCamera(const skjson::ObjectValue& jlayer,
const skjson::ObjectValue& jtransform,
@@ -182,6 +187,10 @@ private:
void parseFonts (const skjson::ObjectValue* jfonts,
const skjson::ArrayValue* jchars);
+ // Return true iff all fonts were resolved.
+ bool resolveNativeTypefaces();
+ bool resolveEmbeddedTypefaces(const skjson::ArrayValue& jchars);
+
void dispatchMarkers(const skjson::ArrayValue*) const;
sk_sp<sksg::RenderNode> attachBlendMode(const skjson::ObjectValue&,
diff --git a/chromium/third_party/skia/modules/skottie/src/SkottieTool.cpp b/chromium/third_party/skia/modules/skottie/src/SkottieTool.cpp
index e546c593b89..9ce6288e4c9 100644
--- a/chromium/third_party/skia/modules/skottie/src/SkottieTool.cpp
+++ b/chromium/third_party/skia/modules/skottie/src/SkottieTool.cpp
@@ -12,6 +12,7 @@
#include "include/core/SkSurface.h"
#include "include/encode/SkPngEncoder.h"
#include "modules/skottie/include/Skottie.h"
+#include "modules/skottie/utils/SkottieUtils.h"
#include "modules/skresources/include/SkResources.h"
#include "src/core/SkOSFile.h"
#include "src/core/SkTaskGroup.h"
@@ -45,6 +46,8 @@ static DEFINE_int(threads, 0, "Number of worker threads (0 -> cores count).");
namespace {
+static constexpr SkColor kClearColor = SK_ColorWHITE;
+
std::unique_ptr<SkFILEWStream> MakeFrameStream(size_t idx, const char* ext) {
const auto frame_file = SkStringPrintf("0%06zu.%s", idx, ext);
auto stream = std::make_unique<SkFILEWStream>(SkOSPath::Join(FLAGS_writePath[0],
@@ -87,7 +90,7 @@ private:
SkCanvas* beginFrame(size_t) override {
auto* canvas = fSurface->getCanvas();
- canvas->clear(SK_ColorTRANSPARENT);
+ canvas->clear(kClearColor);
return canvas;
}
@@ -161,7 +164,7 @@ private:
SkCanvas* beginFrame(size_t) override {
auto* canvas = fSurface->getCanvas();
- canvas->clear(SK_ColorTRANSPARENT);
+ canvas->clear(kClearColor);
return canvas;
}
@@ -182,7 +185,7 @@ struct MP4Sink final : public Sink {
SkCanvas* beginFrame(size_t) override {
SkCanvas* canvas = fSurface->getCanvas();
- canvas->clear(SK_ColorTRANSPARENT);
+ canvas->clear(kClearColor);
return canvas;
}
@@ -265,6 +268,8 @@ int main(int argc, char** argv) {
/*predecode=*/true),
/*predecode=*/true));
auto data = SkData::MakeFromFileName(FLAGS_input[0]);
+ auto precomp_interceptor =
+ sk_make_sp<skottie_utils::ExternalAnimationPrecompInterceptor>(rp, "__");
if (!data) {
SkDebugf("Could not load %s.\n", FLAGS_input[0]);
@@ -334,12 +339,14 @@ int main(int argc, char** argv) {
// iOS doesn't support thread_local on versions less than 9.0.
auto anim = skottie::Animation::Builder()
.setResourceProvider(rp)
+ .setPrecompInterceptor(precomp_interceptor)
.make(static_cast<const char*>(data->data()), data->size());
auto sink = MakeSink(FLAGS_format[0], scale_matrix);
#else
thread_local static auto* anim =
skottie::Animation::Builder()
.setResourceProvider(rp)
+ .setPrecompInterceptor(precomp_interceptor)
.make(static_cast<const char*>(data->data()), data->size())
.release();
thread_local static auto* sink = MakeSink(FLAGS_format[0], scale_matrix).release();
diff --git a/chromium/third_party/skia/modules/skottie/src/Transform.cpp b/chromium/third_party/skia/modules/skottie/src/Transform.cpp
index ff8b45c6188..7548233bf54 100644
--- a/chromium/third_party/skia/modules/skottie/src/Transform.cpp
+++ b/chromium/third_party/skia/modules/skottie/src/Transform.cpp
@@ -20,15 +20,18 @@ TransformAdapter2D::TransformAdapter2D(const AnimationBuilder& abuilder,
const skjson::ObjectValue* jscale,
const skjson::ObjectValue* jrotation,
const skjson::ObjectValue* jskew,
- const skjson::ObjectValue* jskew_axis)
+ const skjson::ObjectValue* jskew_axis,
+ bool auto_orient)
: INHERITED(sksg::Matrix<SkMatrix>::Make(SkMatrix::I())) {
this->bind(abuilder, janchor_point, fAnchorPoint);
- this->bind(abuilder, jposition , fPosition);
this->bind(abuilder, jscale , fScale);
this->bind(abuilder, jrotation , fRotation);
this->bind(abuilder, jskew , fSkew);
this->bind(abuilder, jskew_axis , fSkewAxis);
+
+ this->bindAutoOrientable(abuilder, jposition, &fPosition, auto_orient ? &fOrientation
+ : nullptr);
}
TransformAdapter2D::~TransformAdapter2D() {}
@@ -38,14 +41,11 @@ void TransformAdapter2D::onSync() {
}
SkMatrix TransformAdapter2D::totalMatrix() const {
- SkMatrix t = SkMatrix::MakeTrans(-fAnchorPoint.x, -fAnchorPoint.y);
-
- t.postScale(fScale.x / 100, fScale.y / 100); // 100% based
- t.postRotate(fRotation);
- t.postTranslate(fPosition.x, fPosition.y);
// TODO: skew
-
- return t;
+ return SkMatrix::Translate(fPosition.x, fPosition.y)
+ * SkMatrix::RotateDeg(fRotation + fOrientation)
+ * SkMatrix::Scale (fScale.x / 100, fScale.y / 100) // 100% based
+ * SkMatrix::Translate(-fAnchorPoint.x, -fAnchorPoint.y);
}
SkPoint TransformAdapter2D::getAnchorPoint() const {
@@ -91,7 +91,8 @@ void TransformAdapter2D::setSkewAxis(float sa) {
}
sk_sp<sksg::Transform> AnimationBuilder::attachMatrix2D(const skjson::ObjectValue& jtransform,
- sk_sp<sksg::Transform> parent) const {
+ sk_sp<sksg::Transform> parent,
+ bool auto_orient) const {
const auto* jrotation = &jtransform["r"];
if (jrotation->is<skjson::NullValue>()) {
// Some 2D rotations are disguised as 3D...
@@ -104,7 +105,8 @@ sk_sp<sksg::Transform> AnimationBuilder::attachMatrix2D(const skjson::ObjectValu
jtransform["s"],
*jrotation,
jtransform["sk"],
- jtransform["sa"]);
+ jtransform["sa"],
+ auto_orient);
SkASSERT(adapter);
const auto dispatched = this->dispatchTransformProperty(adapter);
@@ -172,7 +174,8 @@ SkM44 TransformAdapter3D::totalMatrix() const {
}
sk_sp<sksg::Transform> AnimationBuilder::attachMatrix3D(const skjson::ObjectValue& jtransform,
- sk_sp<sksg::Transform> parent) const {
+ sk_sp<sksg::Transform> parent,
+ bool /*TODO: auto_orient*/) const {
auto adapter = TransformAdapter3D::Make(jtransform, *this);
SkASSERT(adapter);
diff --git a/chromium/third_party/skia/modules/skottie/src/Transform.h b/chromium/third_party/skia/modules/skottie/src/Transform.h
index bf688e34c9d..16a6ebee9a0 100644
--- a/chromium/third_party/skia/modules/skottie/src/Transform.h
+++ b/chromium/third_party/skia/modules/skottie/src/Transform.h
@@ -33,7 +33,8 @@ public:
const skjson::ObjectValue* jscale,
const skjson::ObjectValue* jrotation,
const skjson::ObjectValue* jskew,
- const skjson::ObjectValue* jskew_axis);
+ const skjson::ObjectValue* jskew_axis,
+ bool auto_orient = false);
~TransformAdapter2D() override;
// Accessors needed for public property APIs.
@@ -66,7 +67,8 @@ private:
fScale = { 100, 100 };
ScalarValue fRotation = 0,
fSkew = 0,
- fSkewAxis = 0;
+ fSkewAxis = 0,
+ fOrientation = 0; // additional rotation component controlled by auto-orient
using INHERITED = DiscardableAdapterBase<TransformAdapter2D, sksg::Matrix<SkMatrix>>;
};
diff --git a/chromium/third_party/skia/modules/skottie/src/animator/Animator.cpp b/chromium/third_party/skia/modules/skottie/src/animator/Animator.cpp
index 231ff514022..3e891476f8b 100644
--- a/chromium/third_party/skia/modules/skottie/src/animator/Animator.cpp
+++ b/chromium/third_party/skia/modules/skottie/src/animator/Animator.cpp
@@ -49,8 +49,7 @@ void AnimatablePropertyContainer::shrink_to_fit() {
bool AnimatablePropertyContainer::bindImpl(const AnimationBuilder& abuilder,
const skjson::ObjectValue* jprop,
- KeyframeAnimatorBuilder& builder,
- void* target_value) {
+ KeyframeAnimatorBuilder& builder) {
if (!jprop) {
return false;
}
@@ -65,7 +64,7 @@ bool AnimatablePropertyContainer::bindImpl(const AnimationBuilder& abuilder,
// Older Json versions don't have an "a" animation marker.
// For those, we attempt to parse both ways.
if (!ParseDefault<bool>(jpropA, false)) {
- if (builder.parseValue(abuilder, jpropK, target_value)) {
+ if (builder.parseValue(abuilder, jpropK)) {
// Static property.
return true;
}
@@ -81,7 +80,7 @@ bool AnimatablePropertyContainer::bindImpl(const AnimationBuilder& abuilder,
sk_sp<KeyframeAnimator> animator;
const skjson::ArrayValue* jkfs = jpropK;
if (jkfs && jkfs->size() > 0) {
- animator = builder.make(abuilder, *jkfs, target_value);
+ animator = builder.make(abuilder, *jkfs);
}
if (!animator) {
diff --git a/chromium/third_party/skia/modules/skottie/src/animator/Animator.h b/chromium/third_party/skia/modules/skottie/src/animator/Animator.h
index 2c1918b89f9..399d98c5caa 100644
--- a/chromium/third_party/skia/modules/skottie/src/animator/Animator.h
+++ b/chromium/third_party/skia/modules/skottie/src/animator/Animator.h
@@ -12,6 +12,8 @@
#include <vector>
+struct SkV2;
+
namespace skjson {
class ObjectValue;
@@ -54,6 +56,12 @@ public:
return this->bind<T>(abuilder, jobject, &v);
}
+ // A flavor of bind<Vec2Value> which drives an additional/optional orientation target
+ // (rotation in degrees), when bound to a motion path property.
+ bool bindAutoOrientable(const AnimationBuilder& abuilder,
+ const skjson::ObjectValue* jobject,
+ SkV2* v, float* orientation);
+
bool isStatic() const { return fAnimators.empty(); }
protected:
@@ -66,10 +74,7 @@ protected:
private:
StateChanged onSeek(float) final;
- bool bindImpl(const AnimationBuilder&,
- const skjson::ObjectValue*,
- KeyframeAnimatorBuilder&,
- void*);
+ bool bindImpl(const AnimationBuilder&, const skjson::ObjectValue*, KeyframeAnimatorBuilder&);
std::vector<sk_sp<Animator>> fAnimators;
bool fHasSynced = false;
diff --git a/chromium/third_party/skia/modules/skottie/src/animator/KeyframeAnimator.h b/chromium/third_party/skia/modules/skottie/src/animator/KeyframeAnimator.h
index 35eee98b595..d9955e4376b 100644
--- a/chromium/third_party/skia/modules/skottie/src/animator/KeyframeAnimator.h
+++ b/chromium/third_party/skia/modules/skottie/src/animator/KeyframeAnimator.h
@@ -108,11 +108,9 @@ class KeyframeAnimatorBuilder : public SkNoncopyable {
public:
virtual ~KeyframeAnimatorBuilder();
- virtual sk_sp<KeyframeAnimator> make(const AnimationBuilder&,
- const skjson::ArrayValue&,
- void* target_value) = 0;
+ virtual sk_sp<KeyframeAnimator> make(const AnimationBuilder&, const skjson::ArrayValue&) = 0;
- virtual bool parseValue(const AnimationBuilder&, const skjson::Value&, void*) const = 0;
+ virtual bool parseValue(const AnimationBuilder&, const skjson::Value&) const = 0;
protected:
virtual bool parseKFValue(const AnimationBuilder&,
diff --git a/chromium/third_party/skia/modules/skottie/src/animator/ScalarKeyframeAnimator.cpp b/chromium/third_party/skia/modules/skottie/src/animator/ScalarKeyframeAnimator.cpp
index e9e6bd52039..d0babc50779 100644
--- a/chromium/third_party/skia/modules/skottie/src/animator/ScalarKeyframeAnimator.cpp
+++ b/chromium/third_party/skia/modules/skottie/src/animator/ScalarKeyframeAnimator.cpp
@@ -19,22 +19,21 @@ class ScalarKeyframeAnimator final : public KeyframeAnimator {
public:
class Builder final : public KeyframeAnimatorBuilder {
public:
+ explicit Builder(ScalarValue* target) : fTarget(target) {}
+
sk_sp<KeyframeAnimator> make(const AnimationBuilder& abuilder,
- const skjson::ArrayValue& jkfs,
- void* target_value) override {
+ const skjson::ArrayValue& jkfs) override {
SkASSERT(jkfs.size() > 0);
if (!this->parseKeyframes(abuilder, jkfs)) {
return nullptr;
}
return sk_sp<ScalarKeyframeAnimator>(
- new ScalarKeyframeAnimator(std::move(fKFs),
- std::move(fCMs),
- static_cast<ScalarValue*>(target_value)));
+ new ScalarKeyframeAnimator(std::move(fKFs), std::move(fCMs), fTarget));
}
- bool parseValue(const AnimationBuilder&, const skjson::Value& jv, void* v) const override {
- return Parse(jv, static_cast<float*>(v));
+ bool parseValue(const AnimationBuilder&, const skjson::Value& jv) const override {
+ return Parse(jv, fTarget);
}
private:
@@ -44,6 +43,8 @@ public:
Keyframe::Value* v) override {
return Parse(jv, &v->flt);
}
+
+ ScalarValue* fTarget;
};
private:
@@ -73,9 +74,9 @@ template <>
bool AnimatablePropertyContainer::bind<ScalarValue>(const AnimationBuilder& abuilder,
const skjson::ObjectValue* jprop,
ScalarValue* v) {
- ScalarKeyframeAnimator::Builder builder;
+ ScalarKeyframeAnimator::Builder builder(v);
- return this->bindImpl(abuilder, jprop, builder, v);
+ return this->bindImpl(abuilder, jprop, builder);
}
} // namespace skottie::internal
diff --git a/chromium/third_party/skia/modules/skottie/src/animator/ShapeKeyframeAnimator.cpp b/chromium/third_party/skia/modules/skottie/src/animator/ShapeKeyframeAnimator.cpp
index b5f6fee532c..b53dc1ba859 100644
--- a/chromium/third_party/skia/modules/skottie/src/animator/ShapeKeyframeAnimator.cpp
+++ b/chromium/third_party/skia/modules/skottie/src/animator/ShapeKeyframeAnimator.cpp
@@ -169,9 +169,9 @@ template <>
bool AnimatablePropertyContainer::bind<ShapeValue>(const AnimationBuilder& abuilder,
const skjson::ObjectValue* jprop,
ShapeValue* v) {
- VectorKeyframeAnimatorBuilder builder(parse_encoding_len, parse_encoding_data);
+ VectorKeyframeAnimatorBuilder builder(v, parse_encoding_len, parse_encoding_data);
- return this->bindImpl(abuilder, jprop, builder, v);
+ return this->bindImpl(abuilder, jprop, builder);
}
} // namespace internal
diff --git a/chromium/third_party/skia/modules/skottie/src/animator/TextKeyframeAnimator.cpp b/chromium/third_party/skia/modules/skottie/src/animator/TextKeyframeAnimator.cpp
index e1f8d14256c..8fb1ad1fe87 100644
--- a/chromium/third_party/skia/modules/skottie/src/animator/TextKeyframeAnimator.cpp
+++ b/chromium/third_party/skia/modules/skottie/src/animator/TextKeyframeAnimator.cpp
@@ -18,9 +18,10 @@ class TextKeyframeAnimator final : public KeyframeAnimator {
public:
class Builder final : public KeyframeAnimatorBuilder {
public:
+ explicit Builder(TextValue* target) : fTarget(target) {}
+
sk_sp<KeyframeAnimator> make(const AnimationBuilder& abuilder,
- const skjson::ArrayValue& jkfs,
- void* target_value) override {
+ const skjson::ArrayValue& jkfs) override {
SkASSERT(jkfs.size() > 0);
fValues.reserve(jkfs.size());
@@ -33,12 +34,11 @@ public:
new TextKeyframeAnimator(std::move(fKFs),
std::move(fCMs),
std::move(fValues),
- static_cast<TextValue*>(target_value)));
+ fTarget));
}
- bool parseValue(const AnimationBuilder& abuilder,
- const skjson::Value& jv, void* v) const override {
- return Parse(jv, abuilder, static_cast<TextValue*>(v));
+ bool parseValue(const AnimationBuilder& abuilder, const skjson::Value& jv) const override {
+ return Parse(jv, abuilder, fTarget);
}
private:
@@ -62,6 +62,7 @@ public:
}
std::vector<TextValue> fValues;
+ TextValue* fTarget;
};
private:
@@ -95,8 +96,8 @@ template <>
bool AnimatablePropertyContainer::bind<TextValue>(const AnimationBuilder& abuilder,
const skjson::ObjectValue* jprop,
TextValue* v) {
- TextKeyframeAnimator::Builder builder;
- return this->bindImpl(abuilder, jprop, builder, v);
+ TextKeyframeAnimator::Builder builder(v);
+ return this->bindImpl(abuilder, jprop, builder);
}
} // namespace skottie::internal
diff --git a/chromium/third_party/skia/modules/skottie/src/animator/Vec2KeyframeAnimator.cpp b/chromium/third_party/skia/modules/skottie/src/animator/Vec2KeyframeAnimator.cpp
index 6e531cd45f5..7907203156f 100644
--- a/chromium/third_party/skia/modules/skottie/src/animator/Vec2KeyframeAnimator.cpp
+++ b/chromium/third_party/skia/modules/skottie/src/animator/Vec2KeyframeAnimator.cpp
@@ -11,6 +11,8 @@
#include "modules/skottie/src/animator/Animator.h"
#include "modules/skottie/src/animator/KeyframeAnimator.h"
+#include <cmath>
+
namespace skottie::internal {
namespace {
@@ -25,9 +27,12 @@ class Vec2KeyframeAnimator final : public KeyframeAnimator {
public:
class Builder final : public KeyframeAnimatorBuilder {
public:
+ Builder(Vec2Value* vec_target, float* rot_target)
+ : fVecTarget(vec_target)
+ , fRotTarget(rot_target) {}
+
sk_sp<KeyframeAnimator> make(const AnimationBuilder& abuilder,
- const skjson::ArrayValue& jkfs,
- void* target_value) override {
+ const skjson::ArrayValue& jkfs) override {
SkASSERT(jkfs.size() > 0);
fValues.reserve(jkfs.size());
@@ -40,11 +45,12 @@ public:
new Vec2KeyframeAnimator(std::move(fKFs),
std::move(fCMs),
std::move(fValues),
- static_cast<Vec2Value*>(target_value)));
+ fVecTarget,
+ fRotTarget));
}
- bool parseValue(const AnimationBuilder&, const skjson::Value& jv, void* v) const override {
- return Parse(jv, static_cast<Vec2Value*>(v));
+ bool parseValue(const AnimationBuilder&, const skjson::Value& jv) const override {
+ return Parse(jv, fVecTarget);
}
private:
@@ -120,20 +126,30 @@ public:
}
std::vector<SpatialValue> fValues;
+ Vec2Value* fVecTarget; // required
+ float* fRotTarget; // optional
SkV2 fTi{0,0},
fTo{0,0};
};
private:
Vec2KeyframeAnimator(std::vector<Keyframe> kfs, std::vector<SkCubicMap> cms,
- std::vector<SpatialValue> vs, Vec2Value* target_value)
+ std::vector<SpatialValue> vs, Vec2Value* vec_target, float* rot_target)
: INHERITED(std::move(kfs), std::move(cms))
, fValues(std::move(vs))
- , fTarget(target_value) {}
-
- StateChanged update(const Vec2Value& new_value) {
- const auto changed = (new_value != *fTarget);
- *fTarget = new_value;
+ , fVecTarget(vec_target)
+ , fRotTarget(rot_target) {}
+
+ StateChanged update(const Vec2Value& new_vec_value, const Vec2Value& new_tan_value) {
+ auto changed = (new_vec_value != *fVecTarget);
+ *fVecTarget = new_vec_value;
+
+ if (fRotTarget) {
+ const auto new_rot_value = SkRadiansToDegrees(std::atan2(new_tan_value.y,
+ new_tan_value.x));
+ changed |= new_rot_value != *fRotTarget;
+ *fRotTarget = new_rot_value;
+ }
return changed;
}
@@ -145,36 +161,39 @@ private:
if (v0.cmeasure) {
// Spatial keyframe: the computed weight is relative to the interpolation path
// arc length.
- SkPoint pos;
- if (v0.cmeasure->getPosTan(lerp_info.weight * v0.cmeasure->length(), &pos, nullptr)) {
- return this->update({ pos.fX, pos.fY });
+ SkPoint pos;
+ SkVector tan;
+ if (v0.cmeasure->getPosTan(lerp_info.weight * v0.cmeasure->length(), &pos, &tan)) {
+ return this->update({ pos.fX, pos.fY }, {tan.fX, tan.fY});
}
}
const auto& v1 = fValues[lerp_info.vrec1.idx];
- return this->update(Lerp(v0.v2, v1.v2, lerp_info.weight));
+ const auto tan = v1.v2 - v0.v2;
+
+ return this->update(Lerp(v0.v2, v1.v2, lerp_info.weight), tan);
}
const std::vector<SpatialValue> fValues;
- Vec2Value* fTarget;
+ Vec2Value* fVecTarget;
+ float* fRotTarget;
using INHERITED = KeyframeAnimator;
};
} // namespace
-template <>
-bool AnimatablePropertyContainer::bind<Vec2Value>(const AnimationBuilder& abuilder,
- const skjson::ObjectValue* jprop,
- Vec2Value* v) {
+bool AnimatablePropertyContainer::bindAutoOrientable(const AnimationBuilder& abuilder,
+ const skjson::ObjectValue* jprop,
+ Vec2Value* v, float* orientation) {
if (!jprop) {
return false;
}
if (!ParseDefault<bool>((*jprop)["s"], false)) {
// Regular (static or keyframed) 2D value.
- Vec2KeyframeAnimator::Builder builder;
- return this->bindImpl(abuilder, jprop, builder, v);
+ Vec2KeyframeAnimator::Builder builder(v, orientation);
+ return this->bindImpl(abuilder, jprop, builder);
}
// Separate-dimensions vector value: each component is animated independently.
@@ -182,4 +201,11 @@ bool AnimatablePropertyContainer::bind<Vec2Value>(const AnimationBuilder& abuild
| this->bind(abuilder, (*jprop)["y"], &v->y);
}
+template <>
+bool AnimatablePropertyContainer::bind<Vec2Value>(const AnimationBuilder& abuilder,
+ const skjson::ObjectValue* jprop,
+ Vec2Value* v) {
+ return this->bindAutoOrientable(abuilder, jprop, v, nullptr);
+}
+
} // namespace skottie::internal
diff --git a/chromium/third_party/skia/modules/skottie/src/animator/VectorKeyframeAnimator.cpp b/chromium/third_party/skia/modules/skottie/src/animator/VectorKeyframeAnimator.cpp
index 23a482688d5..008b751efc2 100644
--- a/chromium/third_party/skia/modules/skottie/src/animator/VectorKeyframeAnimator.cpp
+++ b/chromium/third_party/skia/modules/skottie/src/animator/VectorKeyframeAnimator.cpp
@@ -44,16 +44,7 @@ VectorValue::operator SkV3() const {
}
VectorValue::operator SkColor() const {
- // best effort to turn this into a color
- const auto r = this->size() > 0 ? (*this)[0] : 0,
- g = this->size() > 1 ? (*this)[1] : 0,
- b = this->size() > 2 ? (*this)[2] : 0,
- a = this->size() > 3 ? (*this)[3] : 1;
-
- return SkColorSetARGB(SkScalarRoundToInt(SkTPin(a, 0.0f, 1.0f) * 255),
- SkScalarRoundToInt(SkTPin(r, 0.0f, 1.0f) * 255),
- SkScalarRoundToInt(SkTPin(g, 0.0f, 1.0f) * 255),
- SkScalarRoundToInt(SkTPin(b, 0.0f, 1.0f) * 255));
+ return static_cast<SkColor4f>(*this).toSkColor();
}
VectorValue::operator SkColor4f() const {
@@ -84,7 +75,7 @@ public:
std::vector<SkCubicMap> cms,
std::vector<float> storage,
size_t vec_len,
- VectorValue* target_value)
+ std::vector<float>* target_value)
: INHERITED(std::move(kfs), std::move(cms))
, fStorage(std::move(storage))
, fVecLen(vec_len)
@@ -143,21 +134,22 @@ private:
const std::vector<float> fStorage;
const size_t fVecLen;
- VectorValue* fTarget;
+ std::vector<float>* fTarget;
using INHERITED = KeyframeAnimator;
};
} // namespace
-VectorKeyframeAnimatorBuilder::VectorKeyframeAnimatorBuilder(VectorLenParser parse_len,
+VectorKeyframeAnimatorBuilder::VectorKeyframeAnimatorBuilder(std::vector<float>* target,
+ VectorLenParser parse_len,
VectorDataParser parse_data)
: fParseLen(parse_len)
- , fParseData(parse_data) {}
+ , fParseData(parse_data)
+ , fTarget(target) {}
sk_sp<KeyframeAnimator> VectorKeyframeAnimatorBuilder::make(const AnimationBuilder& abuilder,
- const skjson::ArrayValue& jkfs,
- void* target_value) {
+ const skjson::ArrayValue& jkfs) {
SkASSERT(jkfs.size() > 0);
// peek at the first keyframe value to find our vector length
@@ -190,20 +182,18 @@ sk_sp<KeyframeAnimator> VectorKeyframeAnimatorBuilder::make(const AnimationBuild
std::move(fCMs),
std::move(fStorage),
fVecLen,
- static_cast<VectorValue*>(target_value)));
+ fTarget));
}
bool VectorKeyframeAnimatorBuilder::parseValue(const AnimationBuilder&,
- const skjson::Value& jv,
- void* raw_v) const {
+ const skjson::Value& jv) const {
size_t vec_len;
if (!this->fParseLen(jv, &vec_len)) {
return false;
}
- auto* v = static_cast<VectorValue*>(raw_v);
- v->resize(vec_len);
- return fParseData(jv, vec_len, v->data());
+ fTarget->resize(vec_len);
+ return fParseData(jv, vec_len, fTarget->data());
}
bool VectorKeyframeAnimatorBuilder::parseKFValue(const AnimationBuilder&,
@@ -246,6 +236,7 @@ bool AnimatablePropertyContainer::bind<VectorValue>(const AnimationBuilder& abui
if (!ParseDefault<bool>((*jprop)["s"], false)) {
// Regular (static or keyframed) vector value.
VectorKeyframeAnimatorBuilder builder(
+ v,
// Len parser.
[](const skjson::Value& jv, size_t* len) -> bool {
if (const skjson::ArrayValue* ja = jv) {
@@ -259,7 +250,7 @@ bool AnimatablePropertyContainer::bind<VectorValue>(const AnimationBuilder& abui
return parse_array(jv, data, len);
});
- return this->bindImpl(abuilder, jprop, builder, v);
+ return this->bindImpl(abuilder, jprop, builder);
}
// Separate-dimensions vector value: each component is animated independently.
diff --git a/chromium/third_party/skia/modules/skottie/src/animator/VectorKeyframeAnimator.h b/chromium/third_party/skia/modules/skottie/src/animator/VectorKeyframeAnimator.h
index b23ac4690d9..5b8c209e6fc 100644
--- a/chromium/third_party/skia/modules/skottie/src/animator/VectorKeyframeAnimator.h
+++ b/chromium/third_party/skia/modules/skottie/src/animator/VectorKeyframeAnimator.h
@@ -19,16 +19,12 @@ public:
using VectorLenParser = bool(*)(const skjson::Value&, size_t*);
using VectorDataParser = bool(*)(const skjson::Value&, size_t, float*);
- VectorKeyframeAnimatorBuilder(VectorLenParser, VectorDataParser);
+ VectorKeyframeAnimatorBuilder(std::vector<float>*, VectorLenParser, VectorDataParser);
- sk_sp<KeyframeAnimator> make(const AnimationBuilder&,
- const skjson::ArrayValue&,
- void*) override;
+ sk_sp<KeyframeAnimator> make(const AnimationBuilder&, const skjson::ArrayValue&) override;
private:
- bool parseValue(const AnimationBuilder&,
- const skjson::Value&,
- void*) const override;
+ bool parseValue(const AnimationBuilder&, const skjson::Value&) const override;
bool parseKFValue(const AnimationBuilder&,
const skjson::ObjectValue&,
@@ -42,6 +38,7 @@ private:
size_t fVecLen, // size of individual vector values we store
fCurrentVec = 0; // vector value index being parsed (corresponding
// storage offset is fCurrentVec * fVecLen)
+ std::vector<float>* fTarget;
};
} // namespace skottie::internal
diff --git a/chromium/third_party/skia/modules/skottie/src/effects/MotionTileEffect.cpp b/chromium/third_party/skia/modules/skottie/src/effects/MotionTileEffect.cpp
index bc2c31f7f88..71be1636beb 100644
--- a/chromium/third_party/skia/modules/skottie/src/effects/MotionTileEffect.cpp
+++ b/chromium/third_party/skia/modules/skottie/src/effects/MotionTileEffect.cpp
@@ -95,7 +95,7 @@ protected:
const auto phase_shift = SkVector::Make(phase_vec.fX / layerShaderMatrix.getScaleX(),
phase_vec.fY / layerShaderMatrix.getScaleY())
* std::fmod(fPhase * (1/360.0f), 1);
- const auto phase_shader_matrix = SkMatrix::MakeTrans(phase_shift.x(), phase_shift.y());
+ const auto phase_shader_matrix = SkMatrix::Translate(phase_shift.x(), phase_shift.y());
// The mask is generated using a step gradient shader, spanning 2 x tile width/height,
// and perpendicular to the phase vector.
diff --git a/chromium/third_party/skia/modules/skottie/src/layers/TextLayer.cpp b/chromium/third_party/skia/modules/skottie/src/layers/TextLayer.cpp
index 39b9e3d0890..35e9dfe9ca0 100644
--- a/chromium/third_party/skia/modules/skottie/src/layers/TextLayer.cpp
+++ b/chromium/third_party/skia/modules/skottie/src/layers/TextLayer.cpp
@@ -17,6 +17,7 @@
#include "modules/sksg/include/SkSGDraw.h"
#include "modules/sksg/include/SkSGGroup.h"
#include "modules/sksg/include/SkSGPaint.h"
+#include "modules/sksg/include/SkSGPath.h"
#include "modules/sksg/include/SkSGText.h"
#include <string.h>
@@ -93,6 +94,70 @@ SkFontStyle FontStyle(const AnimationBuilder* abuilder, const char* style) {
return SkFontStyle(weight, SkFontStyle::kNormal_Width, slant);
}
+bool parse_glyph_path(const skjson::ObjectValue* jdata,
+ const AnimationBuilder* abuilder,
+ SkPath* path) {
+ // Glyph path encoding:
+ //
+ // "data": {
+ // "shapes": [ // follows the shape layer format
+ // {
+ // "ty": "gr", // group shape type
+ // "it": [ // group items
+ // {
+ // "ty": "sh", // actual shape
+ // "ks": <path data> // animatable path format, but always static
+ // },
+ // ...
+ // ]
+ // },
+ // ...
+ // ]
+ // }
+
+ if (!jdata) {
+ return false;
+ }
+
+ const skjson::ArrayValue* jshapes = (*jdata)["shapes"];
+ if (!jshapes) {
+ // Space/empty glyph.
+ return true;
+ }
+
+ for (const skjson::ObjectValue* jgrp : *jshapes) {
+ if (!jgrp) {
+ return false;
+ }
+
+ const skjson::ArrayValue* jit = (*jgrp)["it"];
+ if (!jit) {
+ return false;
+ }
+
+ for (const skjson::ObjectValue* jshape : *jit) {
+ if (!jshape) {
+ return false;
+ }
+
+ // Glyph paths should never be animated. But they are encoded as
+ // animatable properties, so we use the appropriate helpers.
+ AnimationBuilder::AutoScope ascope(abuilder);
+ auto path_node = abuilder->attachPath((*jshape)["ks"]);
+ auto animators = ascope.release();
+
+ if (!path_node || !animators.empty()) {
+ return false;
+ }
+
+ // Successfully parsed a static path. Whew.
+ path->addPath(path_node->getPath());
+ }
+ }
+
+ return true;
+}
+
} // namespace
bool AnimationBuilder::FontInfo::matches(const char family[], const char style[]) const {
@@ -127,129 +192,204 @@ void AnimationBuilder::parseFonts(const skjson::ObjectValue* jfonts,
// }
// ]
// },
- if (jfonts) {
- if (const skjson::ArrayValue* jlist = (*jfonts)["list"]) {
- for (const skjson::ObjectValue* jfont : *jlist) {
- if (!jfont) {
- continue;
- }
+ const skjson::ArrayValue* jlist = jfonts
+ ? static_cast<const skjson::ArrayValue*>((*jfonts)["list"])
+ : nullptr;
+ if (!jlist) {
+ return;
+ }
+
+ // First pass: collect font info.
+ for (const skjson::ObjectValue* jfont : *jlist) {
+ if (!jfont) {
+ continue;
+ }
- const skjson::StringValue* jname = (*jfont)["fName"];
- const skjson::StringValue* jfamily = (*jfont)["fFamily"];
- const skjson::StringValue* jstyle = (*jfont)["fStyle"];
- const skjson::StringValue* jpath = (*jfont)["fPath"];
+ const skjson::StringValue* jname = (*jfont)["fName"];
+ const skjson::StringValue* jfamily = (*jfont)["fFamily"];
+ const skjson::StringValue* jstyle = (*jfont)["fStyle"];
+ const skjson::StringValue* jpath = (*jfont)["fPath"];
- if (!jname || !jname->size() ||
- !jfamily || !jfamily->size() ||
- !jstyle || !jstyle->size()) {
- this->log(Logger::Level::kError, jfont, "Invalid font.");
- continue;
- }
+ if (!jname || !jname->size() ||
+ !jfamily || !jfamily->size() ||
+ !jstyle || !jstyle->size()) {
+ this->log(Logger::Level::kError, jfont, "Invalid font.");
+ continue;
+ }
+
+ fFonts.set(SkString(jname->begin(), jname->size()),
+ {
+ SkString(jfamily->begin(), jfamily->size()),
+ SkString( jstyle->begin(), jstyle->size()),
+ jpath ? SkString( jpath->begin(), jpath->size()) : SkString(),
+ ParseDefault((*jfont)["ascent"] , 0.0f),
+ nullptr, // placeholder
+ SkCustomTypefaceBuilder()
+ });
+ }
+
+ // Optional pass.
+ if (jchars && (fFlags & Animation::Builder::kPreferEmbeddedFonts) &&
+ this->resolveEmbeddedTypefaces(*jchars)) {
+ return;
+ }
- const auto& fmgr = fLazyFontMgr.get();
+ // Native typeface resolution.
+ if (this->resolveNativeTypefaces()) {
+ return;
+ }
- // Typeface fallback order:
- // 1) externally-loaded font (provided by the embedder)
- // 2) system font (family/style)
- // 3) system default
+ // Embedded typeface fallback.
+ if (jchars && !(fFlags & Animation::Builder::kPreferEmbeddedFonts) &&
+ this->resolveEmbeddedTypefaces(*jchars)) {
+ }
+}
- sk_sp<SkTypeface> tf =
- fmgr->makeFromData(fResourceProvider->loadFont(jname->begin(),
- jpath ? jpath->begin()
- : nullptr));
+bool AnimationBuilder::resolveNativeTypefaces() {
+ bool has_unresolved = false;
- if (!tf) {
- tf.reset(fmgr->matchFamilyStyle(jfamily->begin(),
- FontStyle(this, jstyle->begin())));
- }
+ fFonts.foreach([&](const SkString& name, FontInfo* finfo) {
+ SkASSERT(finfo);
- if (!tf) {
- this->log(Logger::Level::kError, nullptr,
- "Could not create typeface for %s|%s.",
- jfamily->begin(), jstyle->begin());
- // Last resort.
- tf = fmgr->legacyMakeTypeface(nullptr, FontStyle(this, jstyle->begin()));
- if (!tf) {
- continue;
- }
- }
+ if (finfo->fTypeface) {
+ // Already resolved from glyph paths.
+ return;
+ }
+
+ const auto& fmgr = fLazyFontMgr.get();
+
+ // Typeface fallback order:
+ // 1) externally-loaded font (provided by the embedder)
+ // 2) system font (family/style)
+ // 3) system default
- fFonts.set(SkString(jname->begin(), jname->size()),
- {
- SkString(jfamily->begin(), jfamily->size()),
- SkString(jstyle->begin(), jstyle->size()),
- ParseDefault((*jfont)["ascent"] , 0.0f),
- std::move(tf)
- });
+ finfo->fTypeface = fResourceProvider->loadTypeface(name.c_str(), finfo->fPath.c_str());
+
+ // legacy API fallback
+ // TODO: remove after client migration
+ if (!finfo->fTypeface) {
+ finfo->fTypeface = fmgr->makeFromData(
+ fResourceProvider->loadFont(name.c_str(), finfo->fPath.c_str()));
+ }
+
+ if (!finfo->fTypeface) {
+ finfo->fTypeface.reset(fmgr->matchFamilyStyle(finfo->fFamily.c_str(),
+ FontStyle(this, finfo->fStyle.c_str())));
+
+ if (!finfo->fTypeface) {
+ this->log(Logger::Level::kError, nullptr, "Could not create typeface for %s|%s.",
+ finfo->fFamily.c_str(), finfo->fStyle.c_str());
+ // Last resort.
+ finfo->fTypeface = fmgr->legacyMakeTypeface(nullptr,
+ FontStyle(this, finfo->fStyle.c_str()));
+
+ has_unresolved |= !finfo->fTypeface;
}
}
- }
+ });
+ return !has_unresolved;
+}
+
+bool AnimationBuilder::resolveEmbeddedTypefaces(const skjson::ArrayValue& jchars) {
// Optional array of glyphs, to be associated with one of the declared fonts. E.g.
// "chars": [
// {
// "ch": "t",
// "data": {
- // "shapes": [...]
+ // "shapes": [...] // shape-layer-like geometry
// },
- // "fFamily": "Roboto",
- // "size": 50,
- // "style": "Regular",
- // "w": 32.67
+ // "fFamily": "Roboto", // part of the font key
+ // "size": 50, // apparently ignored
+ // "style": "Regular", // part of the font key
+ // "w": 32.67 // width/advance (1/100 units)
// }
// ]
- if (jchars) {
- FontInfo* current_font = nullptr;
+ FontInfo* current_font = nullptr;
- for (const skjson::ObjectValue* jchar : *jchars) {
- if (!jchar) {
- continue;
- }
+ for (const skjson::ObjectValue* jchar : jchars) {
+ if (!jchar) {
+ continue;
+ }
- const skjson::StringValue* jch = (*jchar)["ch"];
- if (!jch) {
- continue;
- }
+ const skjson::StringValue* jch = (*jchar)["ch"];
+ if (!jch) {
+ continue;
+ }
- const skjson::StringValue* jfamily = (*jchar)["fFamily"];
- const skjson::StringValue* jstyle = (*jchar)["style"]; // "style", not "fStyle"...
+ const skjson::StringValue* jfamily = (*jchar)["fFamily"];
+ const skjson::StringValue* jstyle = (*jchar)["style"]; // "style", not "fStyle"...
- const auto* ch_ptr = jch->begin();
- const auto ch_len = jch->size();
+ const auto* ch_ptr = jch->begin();
+ const auto ch_len = jch->size();
- if (!jfamily || !jstyle || (SkUTF::CountUTF8(ch_ptr, ch_len) != 1)) {
- this->log(Logger::Level::kError, jchar, "Invalid glyph.");
- continue;
- }
+ if (!jfamily || !jstyle || (SkUTF::CountUTF8(ch_ptr, ch_len) != 1)) {
+ this->log(Logger::Level::kError, jchar, "Invalid glyph.");
+ continue;
+ }
- const auto uni = SkUTF::NextUTF8(&ch_ptr, ch_ptr + ch_len);
- SkASSERT(uni != -1);
-
- const auto* family = jfamily->begin();
- const auto* style = jstyle->begin();
-
- // Locate (and cache) the font info. Unlike text nodes, glyphs reference the font by
- // (family, style) -- not by name :( For now this performs a linear search over *all*
- // fonts: generally there are few of them, and glyph definitions are font-clustered.
- // If problematic, we can refactor as a two-level hashmap.
- if (!current_font || !current_font->matches(family, style)) {
- current_font = nullptr;
- fFonts.foreach([&](const SkString& name, FontInfo* finfo) {
- if (finfo->matches(family, style)) {
- current_font = finfo;
- // TODO: would be nice to break early here...
- }
- });
- if (!current_font) {
- this->log(Logger::Level::kError, nullptr,
- "Font not found for codepoint (%d, %s, %s).", uni, family, style);
- continue;
+ const auto uni = SkUTF::NextUTF8(&ch_ptr, ch_ptr + ch_len);
+ SkASSERT(uni != -1);
+ if (!SkTFitsIn<SkGlyphID>(uni)) {
+ // Custom font keys are SkGlyphIDs. We could implement a remapping scheme if needed,
+ // but for now direct mapping seems to work well enough.
+ this->log(Logger::Level::kError, jchar, "Unsupported glyph ID.");
+ continue;
+ }
+ const auto glyph_id = SkTo<SkGlyphID>(uni);
+
+ const auto* family = jfamily->begin();
+ const auto* style = jstyle->begin();
+
+ // Locate (and cache) the font info. Unlike text nodes, glyphs reference the font by
+ // (family, style) -- not by name :( For now this performs a linear search over *all*
+ // fonts: generally there are few of them, and glyph definitions are font-clustered.
+ // If problematic, we can refactor as a two-level hashmap.
+ if (!current_font || !current_font->matches(family, style)) {
+ current_font = nullptr;
+ fFonts.foreach([&](const SkString& name, FontInfo* finfo) {
+ if (finfo->matches(family, style)) {
+ current_font = finfo;
+ // TODO: would be nice to break early here...
}
+ });
+ if (!current_font) {
+ this->log(Logger::Level::kError, nullptr,
+ "Font not found for codepoint (%d, %s, %s).", uni, family, style);
+ continue;
}
+ }
- // TODO: parse glyphs
+ SkPath path;
+ if (!parse_glyph_path((*jchar)["data"], this, &path)) {
+ continue;
}
+
+ const auto advance = ParseDefault((*jchar)["w"], 0.0f);
+
+ // Interestingly, glyph paths are defined in a percentage-based space,
+ // regardless of declared glyph size...
+ static constexpr float kPtScale = 0.01f;
+
+ // Normalize the path and advance for 1pt.
+ path.transform(SkMatrix::Scale(kPtScale, kPtScale));
+
+ current_font->fCustomBuilder.setGlyph(glyph_id, advance * kPtScale, path);
}
+
+ // Final pass to commit custom typefaces.
+ auto has_unresolved = false;
+ fFonts.foreach([&has_unresolved](const SkString&, FontInfo* finfo) {
+ if (finfo->fTypeface) {
+ return; // already resolved
+ }
+
+ finfo->fTypeface = finfo->fCustomBuilder.detach();
+
+ has_unresolved |= !finfo->fTypeface;
+ });
+
+ return !has_unresolved;
}
sk_sp<sksg::RenderNode> AnimationBuilder::attachTextLayer(const skjson::ObjectValue& jlayer,
@@ -265,6 +405,5 @@ const AnimationBuilder::FontInfo* AnimationBuilder::findFont(const SkString& fon
return fFonts.find(font_name);
}
-
} // namespace internal
} // namespace skottie
diff --git a/chromium/third_party/skia/modules/skottie/src/layers/shapelayer/Repeater.cpp b/chromium/third_party/skia/modules/skottie/src/layers/shapelayer/Repeater.cpp
index 3a80af05827..1d26b08f32e 100644
--- a/chromium/third_party/skia/modules/skottie/src/layers/shapelayer/Repeater.cpp
+++ b/chromium/third_party/skia/modules/skottie/src/layers/shapelayer/Repeater.cpp
@@ -49,7 +49,7 @@ private:
const auto t = fOffset + index;
// Position, scale & rotation are "scaled" by index/offset.
- SkMatrix m = SkMatrix::MakeTrans(-fAnchorPoint.x,
+ SkMatrix m = SkMatrix::Translate(-fAnchorPoint.x,
-fAnchorPoint.y);
m.postScale(std::pow(fScale.x * .01f, fOffset),
std::pow(fScale.y * .01f, fOffset));
diff --git a/chromium/third_party/skia/modules/skottie/src/text/TextValue.cpp b/chromium/third_party/skia/modules/skottie/src/text/TextValue.cpp
index f87158d159d..08741f1b62f 100644
--- a/chromium/third_party/skia/modules/skottie/src/text/TextValue.cpp
+++ b/chromium/third_party/skia/modules/skottie/src/text/TextValue.cpp
@@ -63,33 +63,34 @@ bool Parse(const skjson::Value& jv, const internal::AnimationBuilder& abuilder,
}
}
- // Skia resizing extension "sk_rs":
static constexpr Shaper::ResizePolicy gResizeMap[] = {
- Shaper::ResizePolicy::kNone, // 'sk_rs': 0
- Shaper::ResizePolicy::kScaleToFit, // 'sk_rs': 1
- Shaper::ResizePolicy::kDownscaleToFit, // 'sk_rs': 2
+ Shaper::ResizePolicy::kNone, // 'rs': 0
+ Shaper::ResizePolicy::kScaleToFit, // 'rs': 1
+ Shaper::ResizePolicy::kDownscaleToFit, // 'rs': 2
};
- v->fResize = gResizeMap[std::min<size_t>(ParseDefault<size_t>((*jtxt)["sk_rs"], 0),
- SK_ARRAY_COUNT(gResizeMap))];
+ // TODO: remove "sk_rs" support after migrating clients.
+ v->fResize = gResizeMap[std::min(std::max(ParseDefault<size_t>((*jtxt)[ "rs"], 0),
+ ParseDefault<size_t>((*jtxt)["sk_rs"], 0)),
+ SK_ARRAY_COUNT(gResizeMap))];
// In point mode, the text is baseline-aligned.
v->fVAlign = v->fBox.isEmpty() ? Shaper::VAlign::kTopBaseline
: Shaper::VAlign::kTop;
- // Skia vertical alignment extension "sk_vj":
static constexpr Shaper::VAlign gVAlignMap[] = {
- Shaper::VAlign::kVisualTop, // 'sk_vj': 0
- Shaper::VAlign::kVisualCenter, // 'sk_vj': 1
- Shaper::VAlign::kVisualBottom, // 'sk_vj': 2
+ Shaper::VAlign::kVisualTop, // 'vj': 0
+ Shaper::VAlign::kVisualCenter, // 'vj': 1
+ Shaper::VAlign::kVisualBottom, // 'vj': 2
};
- size_t sk_vj;
- if (skottie::Parse((*jtxt)["sk_vj"], &sk_vj)) {
- if (sk_vj < SK_ARRAY_COUNT(gVAlignMap)) {
- v->fVAlign = gVAlignMap[sk_vj];
+ size_t vj;
+ if (skottie::Parse((*jtxt)[ "vj"], &vj) ||
+ skottie::Parse((*jtxt)["sk_vj"], &vj)) { // TODO: remove after migrating clients.
+ if (vj < SK_ARRAY_COUNT(gVAlignMap)) {
+ v->fVAlign = gVAlignMap[vj];
} else {
// Legacy sk_vj values.
// TODO: remove after clients update.
- switch (sk_vj) {
+ switch (vj) {
case 3:
// 'sk_vj': 3 -> kVisualCenter/kScaleToFit
v->fVAlign = Shaper::VAlign::kVisualCenter;
@@ -102,7 +103,7 @@ bool Parse(const skjson::Value& jv, const internal::AnimationBuilder& abuilder,
break;
default:
abuilder.log(Logger::Level::kWarning, nullptr,
- "Ignoring unknown 'sk_vj' value: %zu", sk_vj);
+ "Ignoring unknown 'vj' value: %zu", vj);
break;
}
}
diff --git a/chromium/third_party/skia/modules/skparagraph/BUILD.gn b/chromium/third_party/skia/modules/skparagraph/BUILD.gn
index aa90c30dd39..48e09296c88 100644
--- a/chromium/third_party/skia/modules/skparagraph/BUILD.gn
+++ b/chromium/third_party/skia/modules/skparagraph/BUILD.gn
@@ -4,6 +4,7 @@ import("../../gn/skia.gni")
declare_args() {
skia_enable_skparagraph = true
+ paragraph_gms_enabled = true
paragraph_tests_enabled = true
paragraph_bench_enabled = false
}
@@ -22,6 +23,7 @@ if (skia_enable_skparagraph) {
public = skparagraph_public
if (skia_use_icu && skia_use_harfbuzz) {
sources = skparagraph_sources
+ configs += [ "../../third_party/icu/config:no_cxx" ]
} else {
sources = []
}
@@ -43,6 +45,7 @@ if (skia_enable_skparagraph) {
configs += [ "../../:skia_private" ]
if (skia_use_icu && skia_use_harfbuzz) {
sources = skparagraph_utils
+ configs += [ "../../third_party/icu/config:no_cxx" ]
} else {
sources = []
}
@@ -53,10 +56,25 @@ if (skia_enable_skparagraph) {
]
}
+ source_set("gm") {
+ if (skia_use_icu && skia_use_harfbuzz && paragraph_gms_enabled) {
+ testonly = true
+ sources = [ "gm/simple_gm.cpp" ]
+ deps = [
+ ":skparagraph",
+ "../..:gpu_tool_utils",
+ "../..:skia",
+ "../skshaper",
+ "//third_party/icu",
+ ]
+ }
+ }
+
source_set("tests") {
if (skia_use_icu && skia_use_harfbuzz && paragraph_tests_enabled) {
testonly = true
- sources = [ "//tests/SkParagraphTest.cpp" ]
+ sources = [ "tests/SkParagraphTest.cpp" ]
+ configs += [ "../../third_party/icu/config:no_cxx" ]
deps = [
":skparagraph",
"../..:gpu_tool_utils",
@@ -70,7 +88,8 @@ if (skia_enable_skparagraph) {
source_set("bench") {
if (skia_use_icu && skia_use_harfbuzz && paragraph_bench_enabled) {
testonly = true
- sources = [ "//bench/ParagraphBench.cpp" ]
+ sources = [ "bench/ParagraphBench.cpp" ]
+ configs += [ "../../third_party/icu/config:no_cxx" ]
deps = [
":skparagraph",
"../..:skia",
@@ -83,7 +102,8 @@ if (skia_enable_skparagraph) {
source_set("samples") {
if (skia_use_icu && skia_use_harfbuzz) {
testonly = true
- sources = [ "//samplecode/SampleParagraph.cpp" ]
+ sources = [ "samples/SampleParagraph.cpp" ]
+ configs += [ "../../third_party/icu/config:no_cxx" ]
deps = [
":skparagraph",
":utils",
diff --git a/chromium/third_party/skia/bench/ParagraphBench.cpp b/chromium/third_party/skia/modules/skparagraph/bench/ParagraphBench.cpp
index 35e4300f90f..35e4300f90f 100644
--- a/chromium/third_party/skia/bench/ParagraphBench.cpp
+++ b/chromium/third_party/skia/modules/skparagraph/bench/ParagraphBench.cpp
diff --git a/chromium/third_party/skia/modules/skparagraph/gm/simple_gm.cpp b/chromium/third_party/skia/modules/skparagraph/gm/simple_gm.cpp
new file mode 100644
index 00000000000..3b365bcc881
--- /dev/null
+++ b/chromium/third_party/skia/modules/skparagraph/gm/simple_gm.cpp
@@ -0,0 +1,120 @@
+/*
+ * 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 "gm/gm.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkColor.h"
+#include "include/core/SkFont.h"
+#include "include/core/SkFontTypes.h"
+#include "include/core/SkPaint.h"
+#include "include/core/SkPoint.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkShader.h"
+#include "include/core/SkSize.h"
+#include "include/core/SkString.h"
+#include "include/core/SkTypeface.h"
+#include "tools/ToolUtils.h"
+
+#include "modules/skparagraph/include/Paragraph.h"
+#include "modules/skparagraph/include/ParagraphBuilder.h"
+
+static const char* gSpeach = "Five score years ago, a great American, in whose symbolic shadow we stand today, signed the Emancipation Proclamation. This momentous decree came as a great beacon light of hope to millions of Negro slaves who had been seared in the flames of withering injustice. It came as a joyous daybreak to end the long night of their captivity.";
+
+namespace {
+enum ParaFlags {
+ kTimeLayout = 1 << 0,
+ kUseUnderline = 1 << 1,
+};
+}
+
+class ParagraphGM : public skiagm::GM {
+ std::unique_ptr<skia::textlayout::Paragraph> fPara;
+ const unsigned fFlags;
+
+public:
+ ParagraphGM(unsigned flags) : fFlags(flags) {}
+
+ void buildParagraph() {
+ skia::textlayout::TextStyle style;
+ style.setForegroundColor(SkPaint());
+ style.setFontFamilies({SkString("sans-serif")});
+ style.setFontSize(30);
+
+ if (fFlags & kUseUnderline) {
+ style.setDecoration(skia::textlayout::TextDecoration::kUnderline);
+ style.setDecorationMode(skia::textlayout::TextDecorationMode::kThrough);
+ style.setDecorationColor(SK_ColorBLACK);
+ style.setDecorationThicknessMultiplier(2);
+ }
+
+ skia::textlayout::ParagraphStyle paraStyle;
+ paraStyle.setTextStyle(style);
+
+ auto collection = sk_make_sp<skia::textlayout::FontCollection>();
+ collection->setDefaultFontManager(SkFontMgr::RefDefault());
+ auto builder = skia::textlayout::ParagraphBuilder::make(paraStyle, collection);
+
+ builder->addText(gSpeach, strlen(gSpeach));
+
+ fPara = builder->Build();
+ fPara->layout(400);
+ }
+
+protected:
+ void onOnceBeforeDraw() override {
+ this->buildParagraph();
+ }
+
+ SkString onShortName() override {
+ SkString name;
+ name.printf("paragraph%s_%s",
+ fFlags & kTimeLayout ? "_layout" : "",
+ fFlags & kUseUnderline ? "_underline" : "");
+ return name;
+ }
+
+ SkISize onISize() override { return SkISize::Make(412, 420); }
+
+ DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
+ const int loop = (this->getMode() == kGM_Mode) ? 1 : 50;
+
+ int parity = 0;
+ for (int i = 0; i < loop; ++i) {
+ SkAutoCanvasRestore acr(canvas, true);
+
+ if (fFlags & kTimeLayout) {
+ fPara->layout(400 + parity);
+ parity = (parity + 1) & 1;
+ }
+ fPara->paint(canvas, 10, 10);
+ }
+ // clean up if we've been looping
+ if (loop > 1) {
+ canvas->clear(SK_ColorWHITE);
+ fPara->layout(400);
+ fPara->paint(canvas, 10, 10);
+ }
+
+ if ((this->getMode() == kGM_Mode) && (fFlags & kTimeLayout)) {
+ return DrawResult::kSkip;
+ }
+ return DrawResult::kOk;
+ }
+
+ bool runAsBench() const override { return true; }
+
+ bool onAnimate(double /*nanos*/) override {
+ return true;
+ }
+
+private:
+ typedef skiagm::GM INHERITED;
+};
+DEF_GM(return new ParagraphGM(0);)
+DEF_GM(return new ParagraphGM(kTimeLayout);)
+DEF_GM(return new ParagraphGM(kUseUnderline);)
diff --git a/chromium/third_party/skia/modules/skparagraph/include/DartTypes.h b/chromium/third_party/skia/modules/skparagraph/include/DartTypes.h
index 162fe104453..415d5dfa722 100644
--- a/chromium/third_party/skia/modules/skparagraph/include/DartTypes.h
+++ b/chromium/third_party/skia/modules/skparagraph/include/DartTypes.h
@@ -4,6 +4,10 @@
#define DartTypes_DEFINED
#include "include/core/SkRect.h"
+#include "include/core/SkTypes.h"
+
+#include <iterator>
+#include <limits>
namespace skia {
namespace textlayout {
diff --git a/chromium/third_party/skia/modules/skparagraph/include/Paragraph.h b/chromium/third_party/skia/modules/skparagraph/include/Paragraph.h
index d262aae9a6b..4e999318302 100644
--- a/chromium/third_party/skia/modules/skparagraph/include/Paragraph.h
+++ b/chromium/third_party/skia/modules/skparagraph/include/Paragraph.h
@@ -15,8 +15,7 @@ namespace textlayout {
class Paragraph {
public:
- Paragraph(ParagraphStyle style, sk_sp<FontCollection> fonts)
- : fFontCollection(std::move(fonts)), fParagraphStyle(std::move(style)) {}
+ Paragraph(ParagraphStyle style, sk_sp<FontCollection> fonts);
virtual ~Paragraph() = default;
diff --git a/chromium/third_party/skia/modules/skparagraph/include/ParagraphCache.h b/chromium/third_party/skia/modules/skparagraph/include/ParagraphCache.h
index bd89c274a93..1d477a1b130 100644
--- a/chromium/third_party/skia/modules/skparagraph/include/ParagraphCache.h
+++ b/chromium/third_party/skia/modules/skparagraph/include/ParagraphCache.h
@@ -13,12 +13,12 @@ namespace textlayout {
enum InternalState {
kUnknown = 0,
- kShaped = 1,
- kClusterized = 2,
- kMarked = 3,
- kLineBroken = 4,
- kFormatted = 5,
- kDrawn = 6
+ kShaped = 2,
+ kClusterized = 3,
+ kMarked = 4,
+ kLineBroken = 5,
+ kFormatted = 6,
+ kDrawn = 7
};
class ParagraphImpl;
diff --git a/chromium/third_party/skia/modules/skparagraph/include/ParagraphStyle.h b/chromium/third_party/skia/modules/skparagraph/include/ParagraphStyle.h
index 2fcb8591ae8..682bae07d0c 100644
--- a/chromium/third_party/skia/modules/skparagraph/include/ParagraphStyle.h
+++ b/chromium/third_party/skia/modules/skparagraph/include/ParagraphStyle.h
@@ -3,9 +3,17 @@
#define ParagraphStyle_DEFINED
#include "include/core/SkFontStyle.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkString.h"
#include "modules/skparagraph/include/DartTypes.h"
#include "modules/skparagraph/include/TextStyle.h"
-#include <string> // std::u16string
+
+#include <stddef.h>
+#include <algorithm>
+#include <limits>
+#include <string>
+#include <utility>
+#include <vector>
namespace skia {
namespace textlayout {
diff --git a/chromium/third_party/skia/modules/skparagraph/include/TypefaceFontProvider.h b/chromium/third_party/skia/modules/skparagraph/include/TypefaceFontProvider.h
index 2e83912c6da..727659d85d8 100644
--- a/chromium/third_party/skia/modules/skparagraph/include/TypefaceFontProvider.h
+++ b/chromium/third_party/skia/modules/skparagraph/include/TypefaceFontProvider.h
@@ -67,9 +67,7 @@ public:
const SkFontArguments&) const override {
return nullptr;
}
- sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData>) const override {
- return nullptr;
- }
+ sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData>) const override;
sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override {
return nullptr;
}
diff --git a/chromium/third_party/skia/samplecode/SampleParagraph.cpp b/chromium/third_party/skia/modules/skparagraph/samples/SampleParagraph.cpp
index c4fd8c86833..28f3207743f 100644
--- a/chromium/third_party/skia/samplecode/SampleParagraph.cpp
+++ b/chromium/third_party/skia/modules/skparagraph/samples/SampleParagraph.cpp
@@ -17,6 +17,8 @@
#include "modules/skparagraph/include/TypefaceFontProvider.h"
#include "modules/skparagraph/src/ParagraphBuilderImpl.h"
#include "modules/skparagraph/src/ParagraphImpl.h"
+#include "modules/skparagraph/src/ParagraphUtil.h"
+#include "modules/skparagraph/src/TextLine.h"
#include "modules/skparagraph/utils/TestFontCollection.h"
#include "samplecode/Sample.h"
#include "src/core/SkOSFile.h"
@@ -745,9 +747,7 @@ protected:
builder.pop();
} else {
if (this->isVerbose()) {
- icu::UnicodeString unicode((UChar*) text.data(), SkToS32(text.size()));
- std::string str;
- unicode.toUTF8String(str);
+ SkString str = SkStringFromU16String(text);
SkDebugf("Text: %s\n", str.c_str());
}
builder.addText(text + expected);
@@ -1356,7 +1356,9 @@ protected:
paint.setStyle(SkPaint::kStroke_Style);
paint.setAntiAlias(true);
paint.setStrokeWidth(1);
- canvas->drawRect(result.front().rect, paint);
+ if (!result.empty()) {
+ canvas->drawRect(result.front().rect, paint);
+ }
}
private:
@@ -1494,8 +1496,8 @@ protected:
auto ltgray = SkColorSetRGB(211, 211, 211);
auto multiplier = 5.67;
- const char* text = ">Sͬ͑̀͐̈͒̈́̋̎ͮͩ̽̓ͬ̂̆̔͗́̓ͣͧ͊ͫ͛̉͌̐̑ͪ͗̚͝҉̴͉͢k̡̊̓ͫͭͩ͂͊ͨͪͬ̑ͫ̍̌̄͛̌̂̑̂̋̊̔ͫ͛̽̑ͨ̍ͭ̓̀ͪͪ̉͐͗̌̓̃̚͟͝҉̢͏̫̞̙͇͖̮͕̗̟͕͇͚̻͈̣̻̪͉̰̲̣̫ͅͅP̴̅̍͒̿͗͗̇ͩ̃͆͌̀̽͏̧̡͕͖̝̖̼̺̰̣̬͔͖͔̼͙̞̦̫͓̘͜a̸̴̸̴̢̢̨̨̫͍͓̥̼̭̼̻̤̯̙̤̻̠͚̍̌͋̂ͦͨ̽̇͌͌͆̀̽̎͒̄ͪ̐ͦ̈ͫ͐͗̓̚̚͜ͅr͐͐ͤͫ̐ͥ͂̈́̿́ͮ̃͗̓̏ͫ̀̿͏̸̵̧́͘̕͟͝͠͞͠҉̷̧͚͢͟a̓̽̎̄͗̔͛̄̐͊͛ͫ͂͌̂̂̈̈̓̔̅̅̄͊̉́ͪ̑̄͆ͬ̍͆ͭ͋̐ͬ͏̷̵̨̢̩̹̖͓̥̳̰͔̱̬͖̙͓̙͇̀̀̕͜͟͟͢͟͜͠͡g̨̅̇ͦ͋̂ͦͨͭ̓͐͆̏̂͛̉ͧ̑ͫ̐̒͛ͫ̍̒͛́̚҉̷̨̛̛̀͜͢͞҉̩̘̲͍͎̯̹̝̭̗̱͇͉̲̱͔̯̠̹̥̻͉̲̜̤̰̪̗̺̖̺r̷͌̓̇̅ͭ̀̐̃̃ͭ͑͗̉̈̇̈́ͥ̓ͣ́ͤ͂ͤ͂̏͌̆̚҉̴̸̧̢̢̛̫͉̦̥̤̙͈͉͈͉͓̙̗̟̳̜͈̗̺̟̠̠͖͓̖̪͕̠̕̕͝ͅả̸̴̡̡̧͠͞͡͞҉̛̕͟͏̷̘̪̱͈̲͉̞̠̞̪̫͎̲̬̖̀̀͟͝͞͞͠p̛͂̈͐̚͠҉̵̸̡̢̢̩̹͙̯͖̙̙̮̥̙͚̠͔̥̭̮̞̣̪̬̥̠̖̝̥̪͎́̀̕͜͡͡ͅͅh̵̷̵̡̛ͤ̂͌̐̓̐̋̋͊̒̆̽́̀̀̀͢͠͞͞҉̷̸̢̕҉͚̯͖̫̜̞̟̠̱͉̝̲̹̼͉̟͉̩̮͔̤͖̞̭̙̹̬ͅ<";
-
+ //const char* text = ">Sͬ͑̀͐̈͒̈́̋̎ͮͩ̽̓ͬ̂̆̔͗́̓ͣͧ͊ͫ͛̉͌̐̑ͪ͗̚͝҉̴͉͢k̡̊̓ͫͭͩ͂͊ͨͪͬ̑ͫ̍̌̄͛̌̂̑̂̋̊̔ͫ͛̽̑ͨ̍ͭ̓̀ͪͪ̉͐͗̌̓̃̚͟͝҉̢͏̫̞̙͇͖̮͕̗̟͕͇͚̻͈̣̻̪͉̰̲̣̫ͅͅP̴̅̍͒̿͗͗̇ͩ̃͆͌̀̽͏̧̡͕͖̝̖̼̺̰̣̬͔͖͔̼͙̞̦̫͓̘͜a̸̴̸̴̢̢̨̨̫͍͓̥̼̭̼̻̤̯̙̤̻̠͚̍̌͋̂ͦͨ̽̇͌͌͆̀̽̎͒̄ͪ̐ͦ̈ͫ͐͗̓̚̚͜ͅr͐͐ͤͫ̐ͥ͂̈́̿́ͮ̃͗̓̏ͫ̀̿͏̸̵̧́͘̕͟͝͠͞͠҉̷̧͚͢͟a̓̽̎̄͗̔͛̄̐͊͛ͫ͂͌̂̂̈̈̓̔̅̅̄͊̉́ͪ̑̄͆ͬ̍͆ͭ͋̐ͬ͏̷̵̨̢̩̹̖͓̥̳̰͔̱̬͖̙͓̙͇̀̀̕͜͟͟͢͟͜͠͡g̨̅̇ͦ͋̂ͦͨͭ̓͐͆̏̂͛̉ͧ̑ͫ̐̒͛ͫ̍̒͛́̚҉̷̨̛̛̀͜͢͞҉̩̘̲͍͎̯̹̝̭̗̱͇͉̲̱͔̯̠̹̥̻͉̲̜̤̰̪̗̺̖̺r̷͌̓̇̅ͭ̀̐̃̃ͭ͑͗̉̈̇̈́ͥ̓ͣ́ͤ͂ͤ͂̏͌̆̚҉̴̸̧̢̢̛̫͉̦̥̤̙͈͉͈͉͓̙̗̟̳̜͈̗̺̟̠̠͖͓̖̪͕̠̕̕͝ͅả̸̴̡̡̧͠͞͡͞҉̛̕͟͏̷̘̪̱͈̲͉̞̠̞̪̫͎̲̬̖̀̀͟͝͞͞͠p̛͂̈͐̚͠҉̵̸̡̢̢̩̹͙̯͖̙̙̮̥̙͚̠͔̥̭̮̞̣̪̬̥̠̖̝̥̪͎́̀̕͜͡͡ͅͅh̵̷̵̡̛ͤ̂͌̐̓̐̋̋͊̒̆̽́̀̀̀͢͠͞͞҉̷̸̢̕҉͚̯͖̫̜̞̟̠̱͉̝̲̹̼͉̟͉̩̮͔̤͖̞̭̙̹̬ͅ<";
+ const char* text = ">S͛ͭ̋͆̈̔̇͗̍͑̎ͪͮͧͣ̽ͫͣ́ͬ̀͌͑͂͗͒̍̔̄ͧ̏̉̌̊̊̿̀̌̃̄͐̓̓̚̚҉̵̡͜͟͝͠͏̸̵̡̧͜҉̷̡͇̜̘̻̺̘̟̝͙̬̘̩͇̭̼̥̖̤̦͎k͉̩̘͚̜̹̗̗͍̤̥̱͉̳͕͖̤̲̣͚̮̞̬̲͍͔̯̻̮̞̭͈̗̫͓̂ͨ̉ͪ̒͋͛̀̍͊ͧ̿̅͆̓̔̔ͬ̇̑̿ͩ͗ͮ̎͌̿̄ͅP̴̵̡̡̛̪͙̼̣̟̩̭̫̱͙̬͔͉͍̘̠͉̦̝̘̥̟̗͖̫̤͕̙̬̦͍̱̖̮̱͑͐̎̃̒͐͋̚͘͞a̶̶̵̵̵̶̶̡̧̢̢̺͔̣͖̭̺͍̤͚̱̜̰̥͕̬̥̲̞̥̘͇͚̺̰͚̪̺͔̤͍̓̿͆̎͋̓ͦ̈́ͦ̌́̄͗̌̓͌̕͜͜͟͢͝͡ŕ͎̝͕͉̻͎̤̭͚̗̳̖̙̘͚̫͖͓͚͉͔͈̟̰̟̬̗͓̟͚̱̕͡ͅͅͅa̸̶̢̛̛̽ͮͩ̅͒ͫ͗͂̎ͦ̈́̓̚͘͜͢͡҉̷̵̶̢̡̜̮̦̜̥̜̯̙͓͔̼̗̻͜͜ͅḡ̢̛͕̗͖̖̤̦̘͔ͨͨ̊͒ͩͭͤ̍̅̃ͪ̋̏̓̍̋͗̋ͨ̏̽̈́̔̀̋̉ͫ̅̂ͭͫ̏͒͋ͥ̚͜r̶̢̧̧̥̤̼̀̂̒ͪ͌̿͌̅͛ͨͪ͒̍ͥ̉ͤ̌̿̆́ͭ͆̃̒ͤ͛̊ͧ̽͘͝͠a̧̢̧̢͑͑̓͑ͮ̃͂̄͛́̈́͋̂͌̽̄͒̔́̇ͨͧͭ͐ͦ̋ͨ̍ͦ̍̋͆̔ͧ͑͋͌̈̓͛͛̚͢͜͜͏̴̢̧̛̳͍̹͚̰̹̻͔p̨̡͆ͦͣ͊̽̔͂̉ͣ̔ͣ̌̌̉̃̋̂͒ͫ̄̎̐͗̉̌̃̽̽́̀̚͘͜͟҉̱͉h̭̮̘̗͔̜̯͔͈̯̺͔̗̣̭͚̱̰̙̼̹͚̣̻̥̲̮͍̤͜͝<";
ParagraphStyle paragraph_style;
ParagraphBuilderImpl builder(paragraph_style, fontCollection);
SkPaint paint;
@@ -1606,11 +1608,9 @@ protected:
ParagraphBuilderImpl builder(paragraph_style, fontCollection);
builder.pushStyle(text_style);
auto utf16text = zalgo.zalgo("SkParagraph");
- icu::UnicodeString unicode((UChar*)utf16text.data(), SkToS32(utf16text.size()));
- std::string str;
- unicode.toUTF8String(str);
if (this->isVerbose()) {
- SkDebugf("Text:>%s<\n", str.data());
+ SkString str = SkStringFromU16String(utf16text);
+ SkDebugf("Text:>%s<\n", str.c_str());
}
builder.addText(utf16text);
fParagraph = builder.Build();
@@ -1630,13 +1630,11 @@ protected:
for (size_t i = 0; i < run.size(); ++i) {
auto glyph = run.glyphs().begin() + i;
if (*glyph == 0) {
- SkDebugf("Run[%d] @pos=%d\n", run.index(), i);
- SkASSERT(false);
+ //SkDebugf("Run[%d] @pos=%d\n", run.index(), i);
}
}
} else {
- SkDebugf("Run[%d]: %s\n", run.index(), fontFamily.c_str());
- SkASSERT(false);
+ //SkDebugf("Run[%d]: %s\n", run.index(), fontFamily.c_str());
}
}
fRedraw = false;
@@ -2192,16 +2190,32 @@ protected:
f2.position, f2.affinity == Affinity::kUpstream ? "up" : "down",
i.position, i.affinity == Affinity::kUpstream ? "up" : "down");
- auto rf1 = paragraph->getRectsForRange(0, 1, RectHeightStyle::kTight, RectWidthStyle::kTight)[0];
- auto rf2 = paragraph->getRectsForRange(1, 2, RectHeightStyle::kTight, RectWidthStyle::kTight)[0];
- auto rfi = paragraph->getRectsForRange(2, 3, RectHeightStyle::kTight, RectWidthStyle::kTight)[0];
+ auto f1 = paragraph->getRectsForRange(0, 1, RectHeightStyle::kTight, RectWidthStyle::kTight);
+ if (f1.empty()) {
+ SkDebugf("F1 is empty\n");
+ } else {
+ auto rf1 = f1[0];
+ SkDebugf("f1: [%f:%f] %s\n",
+ rf1.rect.fLeft, rf1.rect.fRight, rf1.direction == TextDirection::kRtl ? "rtl" : "ltr");
+ }
- SkDebugf("f1: [%f:%f] %s\n",
- rf1.rect.fLeft, rf1.rect.fRight, rf1.direction == TextDirection::kRtl ? "rtl" : "ltr");
- SkDebugf("f2: [%f:%f] %s\n",
- rf2.rect.fLeft, rf2.rect.fRight, rf2.direction == TextDirection::kRtl ? "rtl" : "ltr");
- SkDebugf("i: [%f:%f] %s\n",
- rfi.rect.fLeft, rfi.rect.fRight, rfi.direction == TextDirection::kRtl ? "rtl" : "ltr");
+ auto f2 = paragraph->getRectsForRange(1, 2, RectHeightStyle::kTight, RectWidthStyle::kTight);
+ if (f2.empty()) {
+ SkDebugf("F2 is empty\n");
+ } else {
+ auto rf2 = f2[0];
+ SkDebugf("f2: [%f:%f] %s\n",
+ rf2.rect.fLeft, rf2.rect.fRight, rf2.direction == TextDirection::kRtl ? "rtl" : "ltr");
+ }
+
+ auto fi = paragraph->getRectsForRange(2, 3, RectHeightStyle::kTight, RectWidthStyle::kTight);
+ if (fi.empty()) {
+ SkDebugf("FI is empty\n");
+ } else {
+ auto rfi = fi[0];
+ SkDebugf("i: [%f:%f] %s\n",
+ rfi.rect.fLeft, rfi.rect.fRight, rfi.direction == TextDirection::kRtl ? "rtl" : "ltr");
+ }
}
}
@@ -2795,6 +2809,95 @@ private:
typedef Sample INHERITED;
};
+class ParagraphView44 : public ParagraphView_Base {
+protected:
+ SkString name() override { return SkString("Paragraph44"); }
+
+ void onDrawContent(SkCanvas* canvas) override {
+
+ const std::u16string text = u"The quick brown fox \U0001f98a ate a zesty ham burger fons \U0001f354."
+ "The \U0001f469\u200D\U0001f469\u200D\U0001f467\u200D\U0001f467 laughed.";
+ canvas->drawColor(SK_ColorWHITE);
+
+ auto fontCollection = sk_make_sp<FontCollection>();
+ fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());
+ fontCollection->enableFontFallback();
+
+ ParagraphStyle paragraph_style;
+ paragraph_style.setMaxLines(7);
+ paragraph_style.setEllipsis(u"\u2026");
+ ParagraphBuilderImpl builder(paragraph_style, fontCollection);
+ TextStyle text_style;
+ text_style.setColor(SK_ColorBLACK);
+ text_style.setFontFamilies({SkString("Roboto"), SkString("Noto Color Emoji")});
+ text_style.setFontSize(60);
+ builder.pushStyle(text_style);
+ builder.addText(text);
+ auto paragraph = builder.Build();
+ paragraph->layout(305);//width());
+ paragraph->paint(canvas, 0, 0);
+ }
+
+private:
+ typedef Sample INHERITED;
+};
+
+class ParagraphView45 : public ParagraphView_Base {
+protected:
+ SkString name() override { return SkString("Paragraph45"); }
+
+ void onDrawContent(SkCanvas* canvas) override {
+
+ // This test crashed when resources/fonts directory had only 5 fonts listed below
+ std::string fonts = GetResourcePath("fonts/").c_str();
+ std::set<std::pair<std::string, std::string>> font_paths = {
+ {"Roboto", "Roboto-Regular.ttf"},
+ {"Roboto", "Roboto-Bold.ttf"},
+ {"Noto","NotoSansCJK-Regular.ttc"},
+ {"Noto", "NotoSansCJK-Bold.ttc"},
+ {"Emoji","NotoColorEmoji.ttf"}};
+
+ sk_sp<TypefaceFontProvider> font_provider = sk_make_sp<TypefaceFontProvider>();
+
+ for (auto& pair : font_paths) {
+ SkString family_name = SkString(pair.first.c_str());
+ std::string path = fonts;
+ path += pair.second;
+
+ auto data = SkData::MakeFromFileName(path.c_str());
+ font_provider->registerTypeface(SkTypeface::MakeFromData(std::move(data)), family_name);
+ }
+
+ sk_sp<FontCollection> font_collection = sk_make_sp<FontCollection>();
+ font_collection->setAssetFontManager(std::move(font_provider));
+ font_collection->getParagraphCache()->turnOn(false);
+
+ const std::u16string text = u"❤️🕵🏾‍♀️ 🕵🏾 👩🏾‍⚕️ 👨🏾‍⚕️ 👩🏾‍🌾 👨🏾‍🌾 👩🏾‍🍳 👨🏾‍🍳 👩🏾‍🎓 👨🏾‍🎓 👩🏾‍🎤 👨🏾‍🎤 👩🏾‍🏫 👨🏾‍🏫 👩🏾‍🏭 👨🏾‍🏭 👩🏾‍💻 👨🏾‍💻 👩🏾‍💼 👨🏾‍💼 👩🏾‍🔧 👨🏾‍🔧 👩🏾‍🔬 👨🏾‍🔬 👩🏾‍🎨 👨🏾‍🎨 👩🏾‍🚒 👨🏾‍🚒 👩🏾‍✈️ 👨🏾‍✈️ 👩🏾‍🚀 👨🏾‍🚀 👩🏾‍⚖️ 👨🏾‍⚖️ 🤶🏾 🎅🏾";
+ //u"\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC66\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC67\uD83C\uDDFA\uD83C\uDDF8";
+
+ canvas->drawColor(SK_ColorWHITE);
+
+ ParagraphStyle paragraph_style;
+ paragraph_style.setMaxLines(1);
+ paragraph_style.setHeight(0);
+ paragraph_style.setEllipsis(u"\u2026");
+ ParagraphBuilderImpl builder(paragraph_style, font_collection);
+ TextStyle text_style;
+ text_style.setColor(SK_ColorBLACK);
+ text_style.setFontFamilies({SkString("Roboto"), SkString("Noto"), SkString("Emoji")});
+ text_style.setFontSize(20);
+ text_style.setFontStyle(SkFontStyle::Bold());
+ builder.pushStyle(text_style);
+ builder.addText(text);
+ auto paragraph = builder.Build();
+ paragraph->layout(width());
+ paragraph->paint(canvas, 0, 0);
+ }
+
+private:
+ typedef Sample INHERITED;
+};
+
} // namespace
//////////////////////////////////////////////////////////////////////////////
@@ -2815,7 +2918,7 @@ DEF_SAMPLE(return new ParagraphView15();)
DEF_SAMPLE(return new ParagraphView16();)
DEF_SAMPLE(return new ParagraphView17();)
DEF_SAMPLE(return new ParagraphView18();)
-//DEF_SAMPLE(return new ParagraphView19();)
+DEF_SAMPLE(return new ParagraphView19();)
DEF_SAMPLE(return new ParagraphView20();)
DEF_SAMPLE(return new ParagraphView21();)
DEF_SAMPLE(return new ParagraphView22();)
@@ -2839,3 +2942,5 @@ DEF_SAMPLE(return new ParagraphView39();)
DEF_SAMPLE(return new ParagraphView41();)
DEF_SAMPLE(return new ParagraphView42();)
DEF_SAMPLE(return new ParagraphView43();)
+DEF_SAMPLE(return new ParagraphView44();)
+DEF_SAMPLE(return new ParagraphView45();)
diff --git a/chromium/third_party/skia/modules/skparagraph/skparagraph.gni b/chromium/third_party/skia/modules/skparagraph/skparagraph.gni
index df0091cc8f5..0221d786800 100644
--- a/chromium/third_party/skia/modules/skparagraph/skparagraph.gni
+++ b/chromium/third_party/skia/modules/skparagraph/skparagraph.gni
@@ -31,6 +31,8 @@ skparagraph_sources = [
"$_src/ParagraphImpl.cpp",
"$_src/ParagraphImpl.h",
"$_src/ParagraphStyle.cpp",
+ "$_src/ParagraphUtil.cpp",
+ "$_src/ParagraphUtil.h",
"$_src/Run.cpp",
"$_src/Run.h",
"$_src/TextLine.cpp",
diff --git a/chromium/third_party/skia/modules/skparagraph/src/Decorations.cpp b/chromium/third_party/skia/modules/skparagraph/src/Decorations.cpp
index 175fcce2645..18a56f0cd9d 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/Decorations.cpp
+++ b/chromium/third_party/skia/modules/skparagraph/src/Decorations.cpp
@@ -3,11 +3,23 @@
#include "include/effects/SkDiscretePathEffect.h"
#include "modules/skparagraph/src/Decorations.h"
+static void draw_line_as_rect(SkCanvas* canvas, SkScalar x, SkScalar y, SkScalar width,
+ const SkPaint& paint) {
+ SkASSERT(paint.getPathEffect() == nullptr);
+ SkASSERT(paint.getStrokeCap() == SkPaint::kButt_Cap);
+ SkASSERT(paint.getStrokeWidth() > 0); // this trick won't work for hairlines
+
+ SkPaint p(paint);
+ p.setStroke(false);
+ float radius = paint.getStrokeWidth() * 0.5f;
+ canvas->drawRect({x, y - radius, x + width, y + radius}, p);
+}
+
namespace skia {
namespace textlayout {
static const float kDoubleDecorationSpacing = 3.0f;
-void Decorations::paint(SkCanvas* canvas, const TextStyle& textStyle, const TextLine::ClipContext& context, SkScalar baseline, SkScalar shift) {
+void Decorations::paint(SkCanvas* canvas, const TextStyle& textStyle, const TextLine::ClipContext& context, SkScalar baseline, SkPoint offset) {
if (textStyle.getDecorationType() == TextDecoration::kNoDecoration) {
return;
}
@@ -43,13 +55,13 @@ void Decorations::paint(SkCanvas* canvas, const TextStyle& textStyle, const Text
if (drawGaps) {
SkScalar left = x - context.fTextShift;
canvas->translate(context.fTextShift, 0);
- calculateGaps(context, left, left + width, y, y + fThickness, baseline, fThickness);
+ calculateGaps(context, SkRect::MakeXYWH(left, y, width, fThickness), baseline, fThickness);
canvas->drawPath(fPath, fPaint);
- calculateGaps(context, left, left + width, bottom, bottom + fThickness, baseline, fThickness);
+ calculateGaps(context, SkRect::MakeXYWH(left, bottom, width, fThickness), baseline, fThickness);
canvas->drawPath(fPath, fPaint);
} else {
- canvas->drawLine(x, y, x + width, y, fPaint);
- canvas->drawLine(x, bottom, x + width, bottom, fPaint);
+ draw_line_as_rect(canvas, x, y, width, fPaint);
+ draw_line_as_rect(canvas, x, bottom, width, fPaint);
}
break;
}
@@ -58,7 +70,7 @@ void Decorations::paint(SkCanvas* canvas, const TextStyle& textStyle, const Text
if (drawGaps) {
SkScalar left = x - context.fTextShift;
canvas->translate(context.fTextShift, 0);
- calculateGaps(context, left, left + width, y, y + fThickness, baseline, 0);
+ calculateGaps(context, SkRect::MakeXYWH(left, y, width, fThickness), baseline, 0);
canvas->drawPath(fPath, fPaint);
} else {
canvas->drawLine(x, y, x + width, y, fPaint);
@@ -68,21 +80,18 @@ void Decorations::paint(SkCanvas* canvas, const TextStyle& textStyle, const Text
if (drawGaps) {
SkScalar left = x - context.fTextShift;
canvas->translate(context.fTextShift, 0);
- calculateGaps(context, left, left + width, y, y + fThickness, baseline, fThickness);
+ calculateGaps(context, SkRect::MakeXYWH(left, y, width, fThickness), baseline, fThickness);
canvas->drawPath(fPath, fPaint);
} else {
- canvas->drawLine(x, y, x + width, y, fPaint);
+ draw_line_as_rect(canvas, x, y, width, fPaint);
}
break;
default:break;
}
-
- canvas->save();
- canvas->restore();
}
}
-void Decorations::calculateGaps(const TextLine::ClipContext& context, SkScalar x0, SkScalar x1, SkScalar y0, SkScalar y1, SkScalar baseline, SkScalar halo) {
+void Decorations::calculateGaps(const TextLine::ClipContext& context, const SkRect& rect, SkScalar baseline, SkScalar halo) {
fPath.reset();
@@ -90,27 +99,30 @@ void Decorations::calculateGaps(const TextLine::ClipContext& context, SkScalar x
SkTextBlobBuilder builder;
context.run->copyTo(builder,
SkToU32(context.pos),
- context.size,
- SkVector::Make(0, baseline));
+ context.size);
auto blob = builder.make();
- const SkScalar bounds[2] = {y0, y1};
+ // Since we do not shift down the text by {baseline}
+ // (it now happens on drawTextBlob but we do not draw text here)
+ // we have to shift up the bounds to compensate
+ // This baseline thing ends with getIntercepts
+ const SkScalar bounds[2] = {rect.fTop - baseline, rect.fBottom - baseline};
auto count = blob->getIntercepts(bounds, nullptr, &fPaint);
SkTArray<SkScalar> intersections(count);
intersections.resize(count);
blob->getIntercepts(bounds, intersections.data(), &fPaint);
- auto start = x0;
- fPath.moveTo({x0, y0});
+ auto start = rect.fLeft;
+ fPath.moveTo(rect.fLeft, rect.fTop);
for (int i = 0; i < intersections.count(); i += 2) {
auto end = intersections[i] - halo;
if (end - start >= halo) {
start = intersections[i + 1] + halo;
- fPath.lineTo(end, y0).moveTo(start, y0);
+ fPath.lineTo(end, rect.fTop).moveTo(start, rect.fTop);
}
}
- if (!intersections.empty() && (x1 - start > halo)) {
- fPath.lineTo(x1, y0);
+ if (!intersections.empty() && (rect.fRight - start > halo)) {
+ fPath.lineTo(rect.fRight, rect.fTop);
}
}
diff --git a/chromium/third_party/skia/modules/skparagraph/src/Decorations.h b/chromium/third_party/skia/modules/skparagraph/src/Decorations.h
index f2c61abd8a1..959c4098224 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/Decorations.h
+++ b/chromium/third_party/skia/modules/skparagraph/src/Decorations.h
@@ -12,7 +12,7 @@ namespace textlayout {
class Decorations {
public:
- void paint(SkCanvas* canvas, const TextStyle& textStyle, const TextLine::ClipContext& context, SkScalar baseline, SkScalar shift);
+ void paint(SkCanvas* canvas, const TextStyle& textStyle, const TextLine::ClipContext& context, SkScalar baseline, SkPoint offset);
private:
@@ -20,7 +20,7 @@ class Decorations {
void calculatePosition(TextDecoration decoration, SkScalar ascent);
void calculatePaint(const TextStyle& textStyle);
void calculateWaves(const TextStyle& textStyle, SkRect clip);
- void calculateGaps(const TextLine::ClipContext& context, SkScalar x0, SkScalar x1, SkScalar y0, SkScalar y1, SkScalar baseline, SkScalar halo);
+ void calculateGaps(const TextLine::ClipContext& context, const SkRect& rect, SkScalar baseline, SkScalar halo);
SkScalar fThickness;
SkScalar fPosition;
diff --git a/chromium/third_party/skia/modules/skparagraph/src/FontCollection.cpp b/chromium/third_party/skia/modules/skparagraph/src/FontCollection.cpp
index f26ec578013..f5802dfaf15 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/FontCollection.cpp
+++ b/chromium/third_party/skia/modules/skparagraph/src/FontCollection.cpp
@@ -131,8 +131,8 @@ sk_sp<SkTypeface> FontCollection::defaultFallback() {
if (fDefaultFontManager == nullptr) {
return nullptr;
}
- auto result = fDefaultFontManager->matchFamilyStyle(fDefaultFamilyName.c_str(), SkFontStyle());
- return sk_ref_sp<SkTypeface>(result);
+ return sk_sp<SkTypeface>(fDefaultFontManager->matchFamilyStyle(fDefaultFamilyName.c_str(),
+ SkFontStyle()));
}
diff --git a/chromium/third_party/skia/modules/skparagraph/src/Iterators.h b/chromium/third_party/skia/modules/skparagraph/src/Iterators.h
index 8e4bc2f2986..f418b3ba784 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/Iterators.h
+++ b/chromium/third_party/skia/modules/skparagraph/src/Iterators.h
@@ -2,15 +2,11 @@
#ifndef FontIterator_DEFINED
#define FontIterator_DEFINED
-#include <unicode/brkiter.h>
-#include <unicode/ubidi.h>
-#include "include/core/SkBlurTypes.h"
-#include "include/core/SkCanvas.h"
-#include "include/core/SkFontMgr.h"
-#include "include/core/SkPictureRecorder.h"
-#include "modules/skparagraph/src/ParagraphImpl.h"
+#include "include/core/SkString.h"
+#include "include/core/SkTypes.h"
+#include "modules/skparagraph/include/TextStyle.h"
+#include "modules/skshaper/include/SkShaper.h"
#include "src/core/SkSpan.h"
-#include "src/utils/SkUTF.h"
namespace skia {
namespace textlayout {
diff --git a/chromium/third_party/skia/modules/skparagraph/src/OneLineShaper.cpp b/chromium/third_party/skia/modules/skparagraph/src/OneLineShaper.cpp
index e9691eb26b5..eaa4d0b63be 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/OneLineShaper.cpp
+++ b/chromium/third_party/skia/modules/skparagraph/src/OneLineShaper.cpp
@@ -26,33 +26,32 @@ void OneLineShaper::commitRunBuffer(const RunInfo&) {
auto oldUnresolvedCount = fUnresolvedBlocks.size();
// Find all unresolved blocks
- bool nothingWasUnresolved = true;
sortOutGlyphs([&](GlyphRange block){
if (block.width() == 0) {
return;
}
- nothingWasUnresolved = false;
addUnresolvedWithRun(block);
});
// Fill all the gaps between unresolved blocks with resolved ones
- if (nothingWasUnresolved) {
+ if (oldUnresolvedCount == fUnresolvedBlocks.size()) {
// No unresolved blocks added - we resolved the block with one run entirely
addFullyResolved();
return;
- }
-
- auto& front = fUnresolvedBlocks.front(); // The one we need to resolve
- auto& back = fUnresolvedBlocks.back(); // The one we have from shaper
- if (fUnresolvedBlocks.size() == oldUnresolvedCount + 1 &&
- front.fText == back.fText) {
- // The entire block remains unresolved!
- if (front.fRun != nullptr) {
- back.fRun = front.fRun;
+ } else if (oldUnresolvedCount == fUnresolvedBlocks.size() - 1) {
+ auto& unresolved = fUnresolvedBlocks.back();
+ if (fCurrentRun->textRange() == unresolved.fText) {
+ // Nothing was resolved; preserve the initial run if it makes sense
+ auto& front = fUnresolvedBlocks.front();
+ if (front.fRun != nullptr) {
+ unresolved.fRun = front.fRun;
+ unresolved.fGlyphs = front.fGlyphs;
+ }
+ return;
}
- } else {
- fillGaps(oldUnresolvedCount);
}
+
+ fillGaps(oldUnresolvedCount);
}
#ifdef SK_DEBUG
@@ -76,20 +75,12 @@ void OneLineShaper::printState() {
auto size = fUnresolvedBlocks.size();
SkDebugf("Unresolved: %d\n", size);
- for (size_t i = 0; i < size; ++i) {
- auto unresolved = fUnresolvedBlocks.front();
- fUnresolvedBlocks.pop();
+ for (const auto& unresolved : fUnresolvedBlocks) {
SkDebugf("[%d:%d)\n", unresolved.fText.start, unresolved.fText.end);
- fUnresolvedBlocks.emplace(unresolved);
}
}
#endif
-void OneLineShaper::dropUnresolved() {
- SkASSERT(!fUnresolvedBlocks.empty());
- fUnresolvedBlocks.pop();
-}
-
void OneLineShaper::fillGaps(size_t startingCount) {
// Fill out gaps between all unresolved blocks
TextRange resolvedTextLimits = fCurrentRun->fTextRange;
@@ -99,17 +90,21 @@ void OneLineShaper::fillGaps(size_t startingCount) {
TextIndex resolvedTextStart = resolvedTextLimits.start;
GlyphIndex resolvedGlyphsStart = 0;
- auto count = fUnresolvedBlocks.size();
- for (size_t i = 0; i < count; ++i) {
- auto front = fUnresolvedBlocks.front();
- fUnresolvedBlocks.pop();
- fUnresolvedBlocks.push(front);
- if (i < startingCount) {
- // Skip the first ones
+ auto begin = fUnresolvedBlocks.begin();
+ auto end = fUnresolvedBlocks.end();
+ begin += startingCount; // Skip the old ones, do the new ones
+ TextRange prevText = EMPTY_TEXT;
+ for (; begin != end; ++begin) {
+ auto& unresolved = *begin;
+
+ if (unresolved.fText == prevText) {
+ // Clean up repetitive blocks that appear inside the same grapheme block
+ unresolved.fText = EMPTY_TEXT;
continue;
+ } else {
+ prevText = unresolved.fText;
}
- auto& unresolved = fUnresolvedBlocks.back();
TextRange resolvedText(resolvedTextStart, fCurrentRun->leftToRight() ? unresolved.fText.start : unresolved.fText.end);
if (resolvedText.width() > 0) {
if (!fCurrentRun->leftToRight()) {
@@ -154,7 +149,7 @@ void OneLineShaper::finish(TextRange blockText, SkScalar height, SkScalar& advan
// Add all unresolved blocks to resolved blocks
while (!fUnresolvedBlocks.empty()) {
auto unresolved = fUnresolvedBlocks.front();
- fUnresolvedBlocks.pop();
+ fUnresolvedBlocks.pop_front();
if (unresolved.fText.width() == 0) {
continue;
}
@@ -227,7 +222,6 @@ void OneLineShaper::finish(TextRange blockText, SkScalar height, SkScalar& advan
piece->fBounds[index] = run->fBounds[i];
}
piece->fClusterIndexes[index] = run->fClusterIndexes[i];
- piece->fOffsets[index] = run->fOffsets[i];
piece->fPositions[index] = run->fPositions[i] - zero;
piece->addX(index, advanceX);
}
@@ -244,16 +238,6 @@ void OneLineShaper::finish(TextRange blockText, SkScalar height, SkScalar& advan
}
}
-void OneLineShaper::increment(TextIndex& index) {
- auto text = fCurrentRun->fMaster->text();
- auto cluster = text.begin() + index;
-
- if (cluster < text.end()) {
- utf8_next(&cluster, text.end());
- index = cluster - text.begin();
- }
-}
-
// Make it [left:right) regardless of a text direction
TextRange OneLineShaper::normalizeTextRange(GlyphRange glyphRange) {
@@ -307,7 +291,7 @@ void OneLineShaper::addUnresolvedWithRun(GlyphRange glyphRange) {
}
}
}
- fUnresolvedBlocks.emplace(unresolved);
+ fUnresolvedBlocks.emplace_back(unresolved);
}
void OneLineShaper::sortOutGlyphs(std::function<void(GlyphRange)>&& sortOutUnresolvedBLock) {
@@ -488,8 +472,7 @@ void OneLineShaper::matchResolvedFonts(const TextStyle& textStyle,
bool OneLineShaper::iterateThroughShapingRegions(const ShapeVisitor& shape) {
- SkTArray<BidiRegion> bidiRegions;
- if (!fParagraph->calculateBidiRegions(&bidiRegions)) {
+ if (!fParagraph->getBidiRegions()) {
return false;
}
@@ -500,8 +483,8 @@ bool OneLineShaper::iterateThroughShapingRegions(const ShapeVisitor& shape) {
if (placeholder.fTextBefore.width() > 0) {
// Shape the text by bidi regions
- while (bidiIndex < bidiRegions.size()) {
- BidiRegion& bidiRegion = bidiRegions[bidiIndex];
+ while (bidiIndex < fParagraph->fBidiRegions.size()) {
+ BidiRegion& bidiRegion = fParagraph->fBidiRegions[bidiIndex];
auto start = std::max(bidiRegion.text.start, placeholder.fTextBefore.start);
auto end = std::min(bidiRegion.text.end, placeholder.fTextBefore.end);
@@ -550,7 +533,6 @@ bool OneLineShaper::iterateThroughShapingRegions(const ShapeVisitor& shape) {
advanceX);
run.fPositions[0] = { advanceX, 0 };
- run.fOffsets[0] = {0, 0};
run.fClusterIndexes[0] = 0;
run.fPlaceholderIndex = &placeholder - fParagraph->fPlaceholders.begin();
advanceX += placeholder.fStyle.fWidth;
@@ -584,7 +566,7 @@ bool OneLineShaper::shape() {
fHeight = block.fStyle.getHeightOverride() ? block.fStyle.getHeight() : 0;
fAdvance = SkVector::Make(advanceX, 0);
fCurrentText = block.fRange;
- fUnresolvedBlocks.emplace(RunBlock(block.fRange));
+ fUnresolvedBlocks.emplace_back(RunBlock(block.fRange));
matchResolvedFonts(block.fStyle, [&](sk_sp<SkTypeface> typeface) {
@@ -612,6 +594,11 @@ bool OneLineShaper::shape() {
auto unresolvedCount = fUnresolvedBlocks.size();
while (unresolvedCount-- > 0) {
auto unresolvedRange = fUnresolvedBlocks.front().fText;
+ if (unresolvedRange == EMPTY_TEXT) {
+ // Duplicate blocks should be ignored
+ fUnresolvedBlocks.pop_front();
+ continue;
+ }
auto unresolvedText = fParagraph->text(unresolvedRange);
SkShaper::TrivialFontRunIterator fontIter(font, unresolvedText.size());
@@ -628,7 +615,7 @@ bool OneLineShaper::shape() {
// Take off the queue the block we tried to resolved -
// whatever happened, we have now smaller pieces of it to deal with
- this->dropUnresolved();
+ fUnresolvedBlocks.pop_front();
}
if (fUnresolvedBlocks.empty()) {
@@ -660,15 +647,17 @@ TextRange OneLineShaper::clusteredText(GlyphRange& glyphs) {
if (dir == Dir::right) {
while (index < fCurrentRun->fTextRange.end) {
- if (this->fParagraph->fGraphemes.contains(index)) {
+ if (this->fParagraph->codeUnitHasProperty(index,
+ CodeUnitFlags::kGraphemeStart)) {
return index;
}
++index;
}
return fCurrentRun->fTextRange.end;
} else {
- while (index >= fCurrentRun->fTextRange.start) {
- if (this->fParagraph->fGraphemes.contains(index)) {
+ while (index > fCurrentRun->fTextRange.start) {
+ if (this->fParagraph->codeUnitHasProperty(index,
+ CodeUnitFlags::kGraphemeStart)) {
return index;
}
--index;
diff --git a/chromium/third_party/skia/modules/skparagraph/src/OneLineShaper.h b/chromium/third_party/skia/modules/skparagraph/src/OneLineShaper.h
index 456855f8382..569fadb804f 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/OneLineShaper.h
+++ b/chromium/third_party/skia/modules/skparagraph/src/OneLineShaper.h
@@ -42,8 +42,8 @@ private:
// Entire run comes as one block fully resolved
explicit RunBlock(std::shared_ptr<Run> run)
: fRun(std::move(run))
- , fText(run->fTextRange)
- , fGlyphs(GlyphRange(0, run->size())) { }
+ , fText(fRun->fTextRange)
+ , fGlyphs(GlyphRange(0, fRun->size())) { }
std::shared_ptr<Run> fRun;
TextRange fText;
@@ -69,7 +69,6 @@ private:
#ifdef SK_DEBUG
void printState();
#endif
- void dropUnresolved();
void finish(TextRange text, SkScalar height, SkScalar& advanceX);
void beginLine() override {}
@@ -97,7 +96,6 @@ private:
void addUnresolvedWithRun(GlyphRange glyphRange);
void sortOutGlyphs(std::function<void(GlyphRange)>&& sortOutUnresolvedBLock);
ClusterRange normalizeTextRange(GlyphRange glyphRange);
- void increment(TextIndex& index);
void fillGaps(size_t);
ParagraphImpl* fParagraph;
@@ -109,7 +107,7 @@ private:
// TODO: Something that is not thead-safe since we don't need it
std::shared_ptr<Run> fCurrentRun;
- std::queue<RunBlock> fUnresolvedBlocks;
+ std::deque<RunBlock> fUnresolvedBlocks;
std::vector<RunBlock> fResolvedBlocks;
// Keeping all resolved typefaces
diff --git a/chromium/third_party/skia/modules/skparagraph/src/ParagraphBuilderImpl.cpp b/chromium/third_party/skia/modules/skparagraph/src/ParagraphBuilderImpl.cpp
index 64b6fce4245..5f904e94892 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/ParagraphBuilderImpl.cpp
+++ b/chromium/third_party/skia/modules/skparagraph/src/ParagraphBuilderImpl.cpp
@@ -1,10 +1,17 @@
// Copyright 2019 Google LLC.
-#include "include/core/SkPaint.h"
+
+#include "include/core/SkTypes.h"
+#include "modules/skparagraph/include/FontCollection.h"
+#include "modules/skparagraph/include/Paragraph.h"
+#include "modules/skparagraph/include/ParagraphBuilder.h"
#include "modules/skparagraph/include/ParagraphStyle.h"
+#include "modules/skparagraph/include/TextStyle.h"
#include "modules/skparagraph/src/ParagraphBuilderImpl.h"
#include "modules/skparagraph/src/ParagraphImpl.h"
-#include "src/core/SkSpan.h"
-#include "unicode/unistr.h"
+#include "modules/skparagraph/src/ParagraphUtil.h"
+
+#include <algorithm>
+#include <utility>
namespace skia {
namespace textlayout {
@@ -67,19 +74,15 @@ TextStyle ParagraphBuilderImpl::peekStyle() {
}
void ParagraphBuilderImpl::addText(const std::u16string& text) {
- icu::UnicodeString unicode;
- unicode.setTo((UChar*)text.data());
- std::string str;
- unicode.toUTF8String(str);
- fUtf8.insert(fUtf8.size(), str.c_str());
+ fUtf8.append(SkStringFromU16String(text));
}
void ParagraphBuilderImpl::addText(const char* text) {
- fUtf8.insert(fUtf8.size(), text);
+ fUtf8.append(text);
}
void ParagraphBuilderImpl::addText(const char* text, size_t len) {
- fUtf8.insert(fUtf8.size(), text, len);
+ fUtf8.append(text, len);
}
void ParagraphBuilderImpl::addPlaceholder(const PlaceholderStyle& placeholderStyle) {
diff --git a/chromium/third_party/skia/modules/skparagraph/src/ParagraphCache.cpp b/chromium/third_party/skia/modules/skparagraph/src/ParagraphCache.cpp
index ca47776ceae..2464acaee69 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/ParagraphCache.cpp
+++ b/chromium/third_party/skia/modules/skparagraph/src/ParagraphCache.cpp
@@ -35,13 +35,24 @@ class ParagraphCacheValue {
public:
ParagraphCacheValue(const ParagraphImpl* paragraph)
: fKey(ParagraphCacheKey(paragraph))
- , fRuns(paragraph->fRuns) { }
+ , fRuns(paragraph->fRuns)
+ , fCodeUnitProperties(paragraph->fCodeUnitProperties)
+ , fWords(paragraph->fWords)
+ , fBidiRegions(paragraph->fBidiRegions)
+ , fUTF8IndexForUTF16Index(paragraph->fUTF8IndexForUTF16Index)
+ , fUTF16IndexForUTF8Index(paragraph->fUTF16IndexForUTF8Index) { }
// Input == key
ParagraphCacheKey fKey;
// Shaped results
SkTArray<Run, false> fRuns;
+ // ICU results
+ SkTArray<CodeUnitFlags> fCodeUnitProperties;
+ std::vector<size_t> fWords;
+ SkTArray<BidiRegion> fBidiRegions;
+ SkTArray<TextIndex, true> fUTF8IndexForUTF16Index;
+ SkTArray<size_t, true> fUTF16IndexForUTF8Index;
};
uint32_t ParagraphCache::KeyHash::mix(uint32_t hash, uint32_t data) const {
@@ -193,6 +204,11 @@ void ParagraphCache::updateTo(ParagraphImpl* paragraph, const Entry* entry) {
paragraph->fRuns.reset();
paragraph->fRuns = entry->fValue->fRuns;
+ paragraph->fCodeUnitProperties = entry->fValue->fCodeUnitProperties;
+ paragraph->fWords = entry->fValue->fWords;
+ paragraph->fBidiRegions = entry->fValue->fBidiRegions;
+ paragraph->fUTF8IndexForUTF16Index = entry->fValue->fUTF8IndexForUTF16Index;
+ paragraph->fUTF16IndexForUTF8Index = entry->fValue->fUTF16IndexForUTF8Index;
for (auto& run : paragraph->fRuns) {
run.setMaster(paragraph);
}
diff --git a/chromium/third_party/skia/modules/skparagraph/src/ParagraphImpl.cpp b/chromium/third_party/skia/modules/skparagraph/src/ParagraphImpl.cpp
index 285ceaadcc7..7389ef37d69 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/ParagraphImpl.cpp
+++ b/chromium/third_party/skia/modules/skparagraph/src/ParagraphImpl.cpp
@@ -1,18 +1,39 @@
// Copyright 2019 Google LLC.
-#include "include/core/SkBlurTypes.h"
+
#include "include/core/SkCanvas.h"
-#include "include/core/SkFontMgr.h"
+#include "include/core/SkFontMetrics.h"
+#include "include/core/SkMatrix.h"
#include "include/core/SkPictureRecorder.h"
+#include "include/core/SkTypeface.h"
+#include "include/private/SkTFitsIn.h"
+#include "include/private/SkTo.h"
+#include "modules/skparagraph/include/Metrics.h"
+#include "modules/skparagraph/include/Paragraph.h"
+#include "modules/skparagraph/include/ParagraphStyle.h"
+#include "modules/skparagraph/include/TextStyle.h"
#include "modules/skparagraph/src/OneLineShaper.h"
#include "modules/skparagraph/src/ParagraphImpl.h"
+#include "modules/skparagraph/src/ParagraphUtil.h"
#include "modules/skparagraph/src/Run.h"
+#include "modules/skparagraph/src/TextLine.h"
#include "modules/skparagraph/src/TextWrapper.h"
#include "src/core/SkSpan.h"
#include "src/utils/SkUTF.h"
+
+#if defined(SK_USING_THIRD_PARTY_ICU)
+#include "third_party/icu/SkLoadICU.h"
+#endif
+
+#include <math.h>
+#include <unicode/ubidi.h>
+#include <unicode/uloc.h>
+#include <unicode/umachine.h>
#include <unicode/ustring.h>
+#include <unicode/utext.h>
+#include <unicode/utypes.h>
#include <algorithm>
-#include <chrono>
-#include <queue>
+#include <utility>
+
namespace skia {
namespace textlayout {
@@ -49,34 +70,18 @@ TextRange operator*(const TextRange& a, const TextRange& b) {
return end > begin ? TextRange(begin, end) : EMPTY_TEXT;
}
-bool TextBreaker::initialize(SkSpan<const char> text, UBreakIteratorType type) {
-
- UErrorCode status = U_ZERO_ERROR;
- fIterator = nullptr;
- fSize = text.size();
- UText sUtf8UText = UTEXT_INITIALIZER;
- std::unique_ptr<UText, SkFunctionWrapper<decltype(utext_close), utext_close>> utf8UText(
- utext_openUTF8(&sUtf8UText, text.begin(), text.size(), &status));
- if (U_FAILURE(status)) {
- SkDEBUGF("Could not create utf8UText: %s", u_errorName(status));
- return false;
- }
- fIterator.reset(ubrk_open(type, "en", nullptr, 0, &status));
- if (U_FAILURE(status)) {
- SkDEBUGF("Could not create line break iterator: %s", u_errorName(status));
- SK_ABORT("");
- }
-
- ubrk_setUText(fIterator.get(), utf8UText.get(), &status);
- if (U_FAILURE(status)) {
- SkDEBUGF("Could not setText on break iterator: %s", u_errorName(status));
- return false;
- }
-
- fInitialized = true;
- fPos = 0;
- return true;
-}
+Paragraph::Paragraph(ParagraphStyle style, sk_sp<FontCollection> fonts)
+ : fFontCollection(std::move(fonts))
+ , fParagraphStyle(std::move(style))
+ , fAlphabeticBaseline(0)
+ , fIdeographicBaseline(0)
+ , fHeight(0)
+ , fWidth(0)
+ , fMaxIntrinsicWidth(0)
+ , fMinIntrinsicWidth(0)
+ , fLongestLine(0)
+ , fExceededMaxLines(0)
+{ }
ParagraphImpl::ParagraphImpl(const SkString& text,
ParagraphStyle style,
@@ -94,7 +99,6 @@ ParagraphImpl::ParagraphImpl(const SkString& text,
, fOldWidth(0)
, fOldHeight(0)
, fOrigin(SkRect::MakeEmpty()) {
- // TODO: extractStyles();
}
ParagraphImpl::ParagraphImpl(const std::u16string& utf16text,
@@ -102,22 +106,12 @@ ParagraphImpl::ParagraphImpl(const std::u16string& utf16text,
SkTArray<Block, true> blocks,
SkTArray<Placeholder, true> placeholders,
sk_sp<FontCollection> fonts)
- : Paragraph(std::move(style), std::move(fonts))
- , fTextStyles(std::move(blocks))
- , fPlaceholders(std::move(placeholders))
- , fState(kUnknown)
- , fUnresolvedGlyphs(0)
- , fPicture(nullptr)
- , fStrutMetrics(false)
- , fOldWidth(0)
- , fOldHeight(0)
- , fOrigin(SkRect::MakeEmpty()) {
- icu::UnicodeString unicode((UChar*)utf16text.data(), SkToS32(utf16text.size()));
- std::string str;
- unicode.toUTF8String(str);
- fText = SkString(str.data(), str.size());
- // TODO: extractStyles();
-}
+ : ParagraphImpl(SkStringFromU16String(utf16text),
+ std::move(style),
+ std::move(blocks),
+ std::move(placeholders),
+ std::move(fonts))
+{ }
ParagraphImpl::~ParagraphImpl() = default;
@@ -133,22 +127,28 @@ void ParagraphImpl::layout(SkScalar rawWidth) {
// TODO: This rounding is done to match Flutter tests. Must be removed...
auto floorWidth = SkScalarFloorToScalar(rawWidth);
- if (fState < kShaped) {
- // Layout marked as dirty for performance/testing reasons
- this->fRuns.reset();
- this->fClusters.reset();
- this->resetShifts();
- } else if (fState >= kLineBroken && (fOldWidth != floorWidth || fOldHeight != fHeight)) {
+
+ if ((!SkScalarIsFinite(rawWidth) || fLongestLine <= floorWidth) &&
+ fState >= kLineBroken &&
+ fLines.size() == 1 && fLines.front().ellipsis() == nullptr) {
+ // Most common case: one line of text (and one line is never justified, so no cluster shifts)
+ fWidth = floorWidth;
+ fState = kLineBroken;
+ } else if (fState >= kLineBroken && fOldWidth != floorWidth) {
// We can use the results from SkShaper but have to do EVERYTHING ELSE again
- this->fClusters.reset();
- this->resetShifts();
fState = kShaped;
+ } else {
+ // Nothing changed case: we can reuse the data from the last layout
}
if (fState < kShaped) {
- fGraphemes.reset();
- this->markGraphemes();
-
+ this->fCodeUnitProperties.reset();
+ this->fCodeUnitProperties.push_back_n(fText.size() + 1, CodeUnitFlags::kNoCodeUnitFlag);
+ this->fWords.clear();
+ this->fBidiRegions.reset();
+ this->fUTF8IndexForUTF16Index.reset();
+ this->fUTF16IndexForUTF8Index.reset();
+ this->fRuns.reset();
if (!this->shapeTextIntoEndlessLine()) {
this->resetContext();
// TODO: merge the two next calls - they always come together
@@ -165,6 +165,7 @@ void ParagraphImpl::layout(SkScalar rawWidth) {
}
fAlphabeticBaseline = fEmptyMetrics.alphabeticBaseline();
fIdeographicBaseline = fEmptyMetrics.ideographicBaseline();
+ fLongestLine = FLT_MIN - FLT_MAX; // That is what flutter has
fMinIntrinsicWidth = 0;
fMaxIntrinsicWidth = 0;
this->fOldWidth = floorWidth;
@@ -172,27 +173,20 @@ void ParagraphImpl::layout(SkScalar rawWidth) {
return;
}
-
- this->fClusters.reset();
- this->resetShifts();
fState = kShaped;
}
if (fState < kMarked) {
+ this->fClusters.reset();
+ this->resetShifts();
+ this->fClustersIndexFromCodeUnit.reset();
+ this->fClustersIndexFromCodeUnit.push_back_n(fText.size() + 1, EMPTY_INDEX);
this->buildClusterTable();
fState = kClusterized;
-
- this->markLineBreaks();
this->spaceGlyphs();
fState = kMarked;
}
- if (fState >= kLineBroken) {
- if (fOldWidth != floorWidth || fOldHeight != fHeight) {
- fState = kMarked;
- }
- }
-
if (fState < kLineBroken) {
this->resetContext();
this->resolveStrut();
@@ -234,7 +228,7 @@ void ParagraphImpl::paint(SkCanvas* canvas, SkScalar x, SkScalar y) {
fState = kDrawn;
}
- SkMatrix matrix = SkMatrix::MakeTrans(x + fOrigin.fLeft, y + fOrigin.fTop);
+ SkMatrix matrix = SkMatrix::Translate(x + fOrigin.fLeft, y + fOrigin.fTop);
canvas->drawPicture(fPicture, &matrix, nullptr);
}
@@ -250,6 +244,246 @@ void ParagraphImpl::resetContext() {
fExceededMaxLines = false;
}
+class TextBreaker {
+public:
+ TextBreaker() : fInitialized(false), fPos(-1) {}
+
+ bool initialize(SkSpan<const char> text, UBreakIteratorType type) {
+
+ UErrorCode status = U_ZERO_ERROR;
+ fIterator = nullptr;
+ fSize = text.size();
+ UText sUtf8UText = UTEXT_INITIALIZER;
+ std::unique_ptr<UText, SkFunctionWrapper<decltype(utext_close), utext_close>> utf8UText(
+ utext_openUTF8(&sUtf8UText, text.begin(), text.size(), &status));
+ if (U_FAILURE(status)) {
+ SkDEBUGF("Could not create utf8UText: %s", u_errorName(status));
+ return false;
+ }
+ fIterator.reset(ubrk_open(type, "en", nullptr, 0, &status));
+ if (U_FAILURE(status)) {
+ SkDEBUGF("Could not create line break iterator: %s", u_errorName(status));
+ SK_ABORT("");
+ }
+
+ ubrk_setUText(fIterator.get(), utf8UText.get(), &status);
+ if (U_FAILURE(status)) {
+ SkDEBUGF("Could not setText on break iterator: %s", u_errorName(status));
+ return false;
+ }
+
+ fInitialized = true;
+ fPos = 0;
+ return true;
+ }
+
+ bool initialized() const { return fInitialized; }
+
+ size_t first() {
+ fPos = ubrk_first(fIterator.get());
+ return eof() ? fSize : fPos;
+ }
+
+ size_t next() {
+ fPos = ubrk_next(fIterator.get());
+ return eof() ? fSize : fPos;
+ }
+
+ size_t preceding(size_t offset) {
+ auto pos = ubrk_preceding(fIterator.get(), offset);
+ return pos == UBRK_DONE ? 0 : pos;
+ }
+
+ size_t following(size_t offset) {
+ auto pos = ubrk_following(fIterator.get(), offset);
+ return pos == UBRK_DONE ? fSize : pos;
+ }
+
+ int32_t status() { return ubrk_getRuleStatus(fIterator.get()); }
+
+ bool eof() { return fPos == UBRK_DONE; }
+
+private:
+ std::unique_ptr<UBreakIterator, SkFunctionWrapper<decltype(ubrk_close), ubrk_close>> fIterator;
+ bool fInitialized;
+ int32_t fPos;
+ size_t fSize;
+};
+
+// shapeTextIntoEndlessLine is the thing that calls this method
+// (that contains all ICU dependencies except for words)
+bool ParagraphImpl::computeCodeUnitProperties() {
+
+ #if defined(SK_USING_THIRD_PARTY_ICU)
+ if (!SkLoadICU()) {
+ return false;
+ }
+ #endif
+
+ {
+ const char* start = fText.c_str();
+ const char* end = start + fText.size();
+ const char* ch = start;
+ while (ch < end) {
+ auto index = ch - start;
+ auto unichar = utf8_next(&ch, end);
+ if (u_isWhitespace(unichar)) {
+ auto ending = ch - start;
+ for (auto k = index; k < ending; ++k) {
+ fCodeUnitProperties[k] |= CodeUnitFlags::kPartOfWhiteSpace;
+ }
+ }
+ }
+ }
+ {
+ TextBreaker breaker;
+ if (!breaker.initialize(this->text(), UBRK_LINE)) {
+ return false;
+ }
+ while (!breaker.eof()) {
+ size_t currentPos = breaker.next();
+ fCodeUnitProperties[currentPos] |=
+ breaker.status() == UBRK_LINE_HARD ? CodeUnitFlags::kHardLineBreakBefore : CodeUnitFlags::kSoftLineBreakBefore;
+ }
+ }
+ {
+ TextBreaker breaker;
+ if (!breaker.initialize(this->text(), UBRK_CHARACTER)) {
+ return false;
+ }
+
+ while (!breaker.eof()) {
+ auto currentPos = breaker.next();
+ fCodeUnitProperties[currentPos] |= CodeUnitFlags::kGraphemeStart;
+ }
+ }
+
+ return true;
+}
+
+// getWordBoundary is the thing that calls this method lazily
+bool ParagraphImpl::computeWords() {
+
+ if (!fWords.empty()) {
+ return true;
+ }
+
+ UErrorCode errorCode = U_ZERO_ERROR;
+
+ auto iter = ubrk_open(UBRK_WORD, uloc_getDefault(), nullptr, 0, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ SkDEBUGF("Could not create line break iterator: %s", u_errorName(errorCode));
+ return false;
+ }
+
+ // Getting the length like this seems to always set U_BUFFER_OVERFLOW_ERROR
+ int32_t utf16Units;
+ u_strFromUTF8(nullptr, 0, &utf16Units, fText.c_str(), fText.size(), &errorCode);
+ errorCode = U_ZERO_ERROR;
+ std::unique_ptr<UChar[]> utf16(new UChar[utf16Units]);
+ u_strFromUTF8(utf16.get(), utf16Units, nullptr, fText.c_str(), fText.size(), &errorCode);
+ if (U_FAILURE(errorCode)) {
+ SkDEBUGF("Invalid utf8 input: %s", u_errorName(errorCode));
+ return false;
+ }
+
+ UText sUtf16UText = UTEXT_INITIALIZER;
+ ICUUText utf8UText(utext_openUChars(&sUtf16UText, utf16.get(), utf16Units, &errorCode));
+ if (U_FAILURE(errorCode)) {
+ SkDEBUGF("Could not create utf8UText: %s", u_errorName(errorCode));
+ return false;
+ }
+
+ ubrk_setUText(iter, utf8UText.get(), &errorCode);
+ if (U_FAILURE(errorCode)) {
+ SkDEBUGF("Could not setText on break iterator: %s", u_errorName(errorCode));
+ return false;
+ }
+
+ int32_t pos = ubrk_first(iter);
+ while (pos != UBRK_DONE) {
+ fWords.emplace_back(pos);
+ pos = ubrk_next(iter);
+ }
+
+ return true;
+}
+
+bool ParagraphImpl::getBidiRegions() {
+
+ if (!fBidiRegions.empty()) {
+ return true;
+ }
+
+ // ubidi only accepts utf16 (though internally it basically works on utf32 chars).
+ // We want an ubidi_setPara(UBiDi*, UText*, UBiDiLevel, UBiDiLevel*, UErrorCode*);
+ size_t utf8Bytes = fText.size();
+ const char* utf8 = fText.c_str();
+ uint8_t bidiLevel = fParagraphStyle.getTextDirection() == TextDirection::kLtr
+ ? UBIDI_LTR
+ : UBIDI_RTL;
+ if (!SkTFitsIn<int32_t>(utf8Bytes)) {
+ SkDEBUGF("Bidi error: text too long");
+ return false;
+ }
+
+ // Getting the length like this seems to always set U_BUFFER_OVERFLOW_ERROR
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t utf16Units;
+ u_strFromUTF8(nullptr, 0, &utf16Units, utf8, utf8Bytes, &status);
+ status = U_ZERO_ERROR;
+ std::unique_ptr<UChar[]> utf16(new UChar[utf16Units]);
+ u_strFromUTF8(utf16.get(), utf16Units, nullptr, utf8, utf8Bytes, &status);
+ if (U_FAILURE(status)) {
+ SkDEBUGF("Invalid utf8 input: %s", u_errorName(status));
+ return false;
+ }
+
+ ICUBiDi bidi(ubidi_openSized(utf16Units, 0, &status));
+ if (U_FAILURE(status)) {
+ SkDEBUGF("Bidi error: %s", u_errorName(status));
+ return false;
+ }
+ SkASSERT(bidi);
+
+ // The required lifetime of utf16 isn't well documented.
+ // It appears it isn't used after ubidi_setPara except through ubidi_getText.
+ ubidi_setPara(bidi.get(), utf16.get(), utf16Units, bidiLevel, nullptr, &status);
+ if (U_FAILURE(status)) {
+ SkDEBUGF("Bidi error: %s", u_errorName(status));
+ return false;
+ }
+
+ SkTArray<BidiRegion> bidiRegions;
+ const char* start8 = utf8;
+ const char* end8 = utf8 + utf8Bytes;
+ TextRange textRange(0, 0);
+ UBiDiLevel currentLevel = 0;
+
+ int32_t pos16 = 0;
+ int32_t end16 = ubidi_getLength(bidi.get());
+ while (pos16 < end16) {
+ auto level = ubidi_getLevelAt(bidi.get(), pos16);
+ if (pos16 == 0) {
+ currentLevel = level;
+ } else if (level != currentLevel) {
+ textRange.end = start8 - utf8;
+ fBidiRegions.emplace_back(textRange.start, textRange.end, currentLevel);
+ currentLevel = level;
+ textRange = TextRange(textRange.end, textRange.end);
+ }
+ SkUnichar u = utf8_next(&start8, end8);
+ pos16 += SkUTF::ToUTF16(u);
+ }
+
+ textRange.end = start8 - utf8;
+ if (!textRange.empty()) {
+ fBidiRegions.emplace_back(textRange.start, textRange.end, currentLevel);
+ }
+
+ return true;
+}
+
// Clusters in the order of the input text
void ParagraphImpl::buildClusterTable() {
@@ -258,14 +492,14 @@ void ParagraphImpl::buildClusterTable() {
auto runIndex = run.index();
auto runStart = fClusters.size();
if (run.isPlaceholder()) {
- // There are no glyphs but we want to have one cluster
- SkSpan<const char> text = this->text(run.textRange());
- if (!fClusters.empty()) {
- fClusters.back().setBreakType(Cluster::SoftLineBreak);
+ // Add info to cluster indexes table (text -> cluster)
+ for (auto i = run.textRange().start; i < run.textRange().end; ++i) {
+ fClustersIndexFromCodeUnit[i] = fClusters.size();
}
- auto& cluster = fClusters.emplace_back(this, runIndex, 0ul, 1ul, text, run.advance().fX,
- run.advance().fY);
- cluster.setBreakType(Cluster::SoftLineBreak);
+ // There are no glyphs but we want to have one cluster
+ fClusters.emplace_back(this, runIndex, 0ul, 1ul, this->text(run.textRange()), run.advance().fX, run.advance().fY);
+ fCodeUnitProperties[run.textRange().start] |= CodeUnitFlags::kSoftLineBreakBefore;
+ fCodeUnitProperties[run.textRange().end] |= CodeUnitFlags::kSoftLineBreakBefore;
} else {
fClusters.reserve(fClusters.size() + run.size());
// Walk through the glyph in the direction of input text
@@ -276,20 +510,20 @@ void ParagraphImpl::buildClusterTable() {
SkScalar width,
SkScalar height) {
SkASSERT(charEnd >= charStart);
- SkSpan<const char> text(fText.c_str() + charStart, charEnd - charStart);
- auto& cluster = fClusters.emplace_back(this, runIndex, glyphStart, glyphEnd, text,
- width, height);
- cluster.setIsWhiteSpaces();
- if (fGraphemes.find(cluster.fTextRange.end) != nullptr) {
- cluster.setBreakType(Cluster::BreakType::GraphemeBreak);
+ // Add info to cluster indexes table (text -> cluster)
+ for (auto i = charStart; i < charEnd; ++i) {
+ fClustersIndexFromCodeUnit[i] = fClusters.size();
}
+ SkSpan<const char> text(fText.c_str() + charStart, charEnd - charStart);
+ fClusters.emplace_back(this, runIndex, glyphStart, glyphEnd, text, width, height);
});
}
run.setClusterRange(runStart, fClusters.size());
fMaxIntrinsicWidth += run.advance().fX;
}
- fClusters.emplace_back(this, EMPTY_RUN, 0, 0, SkSpan<const char>(), 0, 0);
+ fClustersIndexFromCodeUnit[fText.size()] = fClusters.size();
+ fClusters.emplace_back(this, EMPTY_RUN, 0, 0, this->text({fText.size(), fText.size()}), 0, 0);
}
void ParagraphImpl::spaceGlyphs() {
@@ -338,41 +572,6 @@ void ParagraphImpl::spaceGlyphs() {
}
}
-void ParagraphImpl::markLineBreaks() {
-
- // Find all possible (soft) line breaks
- // This iterator is used only once for a paragraph so we don't have to keep it
- TextBreaker breaker;
- if (!breaker.initialize(this->text(), UBRK_LINE)) {
- return;
- }
-
- // Mark all soft line breaks
- // Remove soft line breaks that are not on grapheme cluster edge
- Cluster* current = fClusters.begin();
- while (!breaker.eof() && current < fClusters.end()) {
- size_t currentPos = breaker.next();
- while (current < fClusters.end()) {
- if (current->textRange().end > currentPos) {
- break;
- } else if (current->textRange().end == currentPos) {
- if (breaker.status() == UBRK_LINE_HARD) {
- // Hard line break stronger than anything
- current->setBreakType(Cluster::BreakType::HardLineBreak);
- } else if (current->isGraphemeBreak()) {
- // Only allow soft line break if it's grapheme break
- current->setBreakType(Cluster::BreakType::SoftLineBreak);
- } else {
- // Leave it as is (either it's no break or a placeholder)
- }
- ++current;
- break;
- }
- ++current;
- }
- }
-}
-
bool ParagraphImpl::shapeTextIntoEndlessLine() {
if (fText.size() == 0) {
@@ -384,6 +583,10 @@ bool ParagraphImpl::shapeTextIntoEndlessLine() {
return true;
}
+ if (!computeCodeUnitProperties()) {
+ return false;
+ }
+
fFontSwitches.reset();
OneLineShaper oneLineShaper(this);
@@ -560,76 +763,6 @@ TextLine& ParagraphImpl::addLine(SkVector offset,
return fLines.emplace_back(this, offset, advance, blocks, text, textWithSpaces, clusters, clustersWithGhosts, widthWithSpaces, sizes);
}
-void ParagraphImpl::markGraphemes16() {
-
- if (!fGraphemes16.empty()) {
- return;
- }
-
- // This breaker gets called only once for a paragraph so we don't have to keep it
- TextBreaker breaker;
- if (!breaker.initialize(this->text(), UBRK_CHARACTER)) {
- return;
- }
-
- auto ptr = fText.c_str();
- auto end = fText.c_str() + fText.size();
- while (ptr < end) {
-
- size_t index = ptr - fText.c_str();
- SkUnichar u = SkUTF::NextUTF8(&ptr, end);
- uint16_t buffer[2];
- size_t count = SkUTF::ToUTF16(u, buffer);
- fCodePoints.emplace_back(EMPTY_INDEX, index, count > 1 ? 2 : 1);
- if (count > 1) {
- fCodePoints.emplace_back(EMPTY_INDEX, index, 1);
- }
- }
-
- CodepointRange codepoints(0ul, 0ul);
-
- size_t endPos = 0;
- while (!breaker.eof()) {
- auto startPos = endPos;
- endPos = breaker.next();
-
- // Collect all the codepoints that belong to the grapheme
- while (codepoints.end < fCodePoints.size() && fCodePoints[codepoints.end].fTextIndex < endPos) {
- ++codepoints.end;
- }
-
- if (startPos == endPos) {
- continue;
- }
-
- //SkDebugf("Grapheme #%d [%d:%d)\n", fGraphemes16.size(), startPos, endPos);
-
- // Update all the codepoints that belong to this grapheme
- for (auto i = codepoints.start; i < codepoints.end; ++i) {
- //SkDebugf(" [%d] = %d + %d\n", i, fCodePoints[i].fTextIndex, fCodePoints[i].fIndex);
- fCodePoints[i].fGrapheme = fGraphemes16.size();
- }
-
- fGraphemes16.emplace_back(codepoints, TextRange(startPos, endPos));
- codepoints.start = codepoints.end;
- }
-}
-
-void ParagraphImpl::markGraphemes() {
-
- // This breaker gets called only once for a paragraph so we don't have to keep it
- TextBreaker breaker;
- if (!breaker.initialize(this->text(), UBRK_CHARACTER)) {
- return;
- }
-
- auto endPos = breaker.first();
- while (!breaker.eof()) {
- fGraphemes.add(endPos);
- endPos = breaker.next();
- }
-}
-
// Returns a vector of bounding boxes that enclose all text between
// start and end glyph indexes, including start and excluding end
std::vector<TextBox> ParagraphImpl::getRectsForRange(unsigned start,
@@ -646,9 +779,9 @@ std::vector<TextBox> ParagraphImpl::getRectsForRange(unsigned start,
return results;
}
- markGraphemes16();
+ ensureUTF16Mapping();
- if (start >= end || start > fCodePoints.size() || end == 0) {
+ if (start >= end || start > fUTF8IndexForUTF16Index.size() || end == 0) {
return results;
}
@@ -661,16 +794,11 @@ std::vector<TextBox> ParagraphImpl::getRectsForRange(unsigned start,
// One flutter test fails because of it but the editing experience is correct
// (although you have to press the cursor many times before it moves to the next grapheme).
TextRange text(fText.size(), fText.size());
- if (start < fCodePoints.size()) {
- auto codepoint = fCodePoints[start];
- auto grapheme = fGraphemes16[codepoint.fGrapheme];
- text.start = grapheme.fTextRange.start;
+ if (start < fUTF8IndexForUTF16Index.size()) {
+ text.start = findGraphemeStart(fUTF8IndexForUTF16Index[start]);
}
-
- if (end < fCodePoints.size()) {
- auto codepoint = fCodePoints[end];
- auto grapheme = fGraphemes16[codepoint.fGrapheme];
- text.end = grapheme.fTextRange.start;
+ if (end < fUTF8IndexForUTF16Index.size()) {
+ text.end = findGraphemeStart(fUTF8IndexForUTF16Index[end]);
}
for (auto& line : fLines) {
@@ -728,7 +856,8 @@ PositionWithAffinity ParagraphImpl::getGlyphPositionAtCoordinate(SkScalar dx, Sk
return {0, Affinity::kDownstream};
}
- markGraphemes16();
+ ensureUTF16Mapping();
+
for (auto& line : fLines) {
// Let's figure out if we can stop looking
auto offsetY = line.offset().fY;
@@ -753,35 +882,9 @@ PositionWithAffinity ParagraphImpl::getGlyphPositionAtCoordinate(SkScalar dx, Sk
// the glyph at index offset.
// By "glyph" they mean a character index - indicated by Minikin's code
SkRange<size_t> ParagraphImpl::getWordBoundary(unsigned offset) {
- if (fWords.empty()) {
- auto unicode = icu::UnicodeString::fromUTF8(fText.c_str());
-
- UErrorCode errorCode = U_ZERO_ERROR;
- auto iter = ubrk_open(UBRK_WORD, icu::Locale().getName(), nullptr, 0, &errorCode);
- if (U_FAILURE(errorCode)) {
- SkDEBUGF("Could not create line break iterator: %s", u_errorName(errorCode));
- return {0, 0};
- }
-
- UText sUtf16UText = UTEXT_INITIALIZER;
- ICUUText utf16UText(utext_openUnicodeString(&sUtf16UText, &unicode, &errorCode));
- if (U_FAILURE(errorCode)) {
- SkDEBUGF("Could not create utf8UText: %s", u_errorName(errorCode));
- return {0, 0};
- }
-
- ubrk_setUText(iter, utf16UText.get(), &errorCode);
- if (U_FAILURE(errorCode)) {
- SkDEBUGF("Could not setText on break iterator: %s", u_errorName(errorCode));
- return {0, 0};
- }
-
- int32_t pos = ubrk_first(iter);
- while (pos != icu::BreakIterator::DONE) {
- fWords.emplace_back(pos);
- pos = ubrk_next(iter);
- }
+ if (!computeWords()) {
+ return {0, 0 };
}
int32_t start = 0;
@@ -796,10 +899,36 @@ SkRange<size_t> ParagraphImpl::getWordBoundary(unsigned offset) {
break;
}
}
+
//SkDebugf("getWordBoundary(%d): %d - %d\n", offset, start, end);
return { SkToU32(start), SkToU32(end) };
}
+void ParagraphImpl::forEachCodeUnitPropertyRange(CodeUnitFlags property, CodeUnitRangeVisitor visitor) {
+
+ size_t first = 0;
+ for (size_t i = 1; i < fText.size(); ++i) {
+ auto properties = fCodeUnitProperties[i];
+ if (properties & property) {
+ visitor({first, i});
+ first = i;
+ }
+
+ }
+ visitor({first, fText.size()});
+}
+
+size_t ParagraphImpl::getWhitespacesLength(TextRange textRange) {
+ size_t len = 0;
+ for (auto i = textRange.start; i < textRange.end; ++i) {
+ auto properties = fCodeUnitProperties[i];
+ if (properties & CodeUnitFlags::kPartOfWhiteSpace) {
+ ++len;
+ }
+ }
+ return len;
+}
+
void ParagraphImpl::getLineMetrics(std::vector<LineMetrics>& metrics) {
metrics.clear();
for (auto& line : fLines) {
@@ -823,11 +952,6 @@ Cluster& ParagraphImpl::cluster(ClusterIndex clusterIndex) {
return fClusters[clusterIndex];
}
-Run& ParagraphImpl::run(RunIndex runIndex) {
- SkASSERT(runIndex < fRuns.size());
- return fRuns[runIndex];
-}
-
Run& ParagraphImpl::runByCluster(ClusterIndex clusterIndex) {
auto start = cluster(clusterIndex);
return this->run(start.fRunIndex);
@@ -853,8 +977,18 @@ void ParagraphImpl::setState(InternalState state) {
switch (fState) {
case kUnknown:
fRuns.reset();
+ fCodeUnitProperties.reset();
+ fCodeUnitProperties.push_back_n(fText.size() + 1, kNoCodeUnitFlag);
+ fWords.clear();
+ fBidiRegions.reset();
+ fUTF8IndexForUTF16Index.reset();
+ fUTF16IndexForUTF8Index.reset();
+ [[fallthrough]];
+
case kShaped:
fClusters.reset();
+ [[fallthrough]];
+
case kClusterized:
case kMarked:
case kLineBroken:
@@ -863,12 +997,15 @@ void ParagraphImpl::setState(InternalState state) {
this->computeEmptyMetrics();
this->resetShifts();
fLines.reset();
+ [[fallthrough]];
+
case kFormatted:
fPicture = nullptr;
+ [[fallthrough]];
+
case kDrawn:
+ default:
break;
- default:
- break;
}
}
@@ -950,77 +1087,46 @@ void ParagraphImpl::updateBackgroundPaint(size_t from, size_t to, SkPaint paint)
}
}
-bool ParagraphImpl::calculateBidiRegions(SkTArray<BidiRegion>* regions) {
-
- regions->reset();
-
- // ubidi only accepts utf16 (though internally it basically works on utf32 chars).
- // We want an ubidi_setPara(UBiDi*, UText*, UBiDiLevel, UBiDiLevel*, UErrorCode*);
- size_t utf8Bytes = fText.size();
- const char* utf8 = fText.c_str();
- uint8_t bidiLevel = fParagraphStyle.getTextDirection() == TextDirection::kLtr
- ? UBIDI_LTR
- : UBIDI_RTL;
- if (!SkTFitsIn<int32_t>(utf8Bytes)) {
- SkDEBUGF("Bidi error: text too long");
- return false;
- }
-
- // Getting the length like this seems to always set U_BUFFER_OVERFLOW_ERROR
- UErrorCode status = U_ZERO_ERROR;
- int32_t utf16Units;
- u_strFromUTF8(nullptr, 0, &utf16Units, utf8, utf8Bytes, &status);
- status = U_ZERO_ERROR;
- std::unique_ptr<UChar[]> utf16(new UChar[utf16Units]);
- u_strFromUTF8(utf16.get(), utf16Units, nullptr, utf8, utf8Bytes, &status);
- if (U_FAILURE(status)) {
- SkDEBUGF("Invalid utf8 input: %s", u_errorName(status));
- return false;
+TextIndex ParagraphImpl::findGraphemeStart(TextIndex index) {
+ if (index == fText.size()) {
+ return index;
}
-
- ICUBiDi bidi(ubidi_openSized(utf16Units, 0, &status));
- if (U_FAILURE(status)) {
- SkDEBUGF("Bidi error: %s", u_errorName(status));
- return false;
+ while (index > 0 &&
+ (fCodeUnitProperties[index] & CodeUnitFlags::kGraphemeStart) == 0) {
+ --index;
}
- SkASSERT(bidi);
+ return index;
+}
- // The required lifetime of utf16 isn't well documented.
- // It appears it isn't used after ubidi_setPara except through ubidi_getText.
- ubidi_setPara(bidi.get(), utf16.get(), utf16Units, bidiLevel, nullptr, &status);
- if (U_FAILURE(status)) {
- SkDEBUGF("Bidi error: %s", u_errorName(status));
- return false;
+void ParagraphImpl::ensureUTF16Mapping() {
+ if (!fUTF16IndexForUTF8Index.empty()) {
+ return;
}
+ // Fill out code points 16
+ auto ptr = fText.c_str();
+ auto end = fText.c_str() + fText.size();
+ while (ptr < end) {
- SkTArray<BidiRegion> bidiRegions;
- const char* start8 = utf8;
- const char* end8 = utf8 + utf8Bytes;
- TextRange textRange(0, 0);
- UBiDiLevel currentLevel = 0;
+ size_t index = ptr - fText.c_str();
+ SkUnichar u = SkUTF::NextUTF8(&ptr, end);
- int32_t pos16 = 0;
- int32_t end16 = ubidi_getLength(bidi.get());
- while (pos16 < end16) {
- auto level = ubidi_getLevelAt(bidi.get(), pos16);
- if (pos16 == 0) {
- currentLevel = level;
- } else if (level != currentLevel) {
- textRange.end = start8 - utf8;
- regions->emplace_back(textRange.start, textRange.end, currentLevel);
- currentLevel = level;
- textRange = TextRange(textRange.end, textRange.end);
+ // All utf8 units refer to the same codepoint
+ size_t next = ptr - fText.c_str();
+ for (auto i = index; i < next; ++i) {
+ fUTF16IndexForUTF8Index.emplace_back(fUTF8IndexForUTF16Index.size());
}
- SkUnichar u = utf8_next(&start8, end8);
- pos16 += SkUTF::ToUTF16(u);
- }
+ SkASSERT(fUTF16IndexForUTF8Index.size() == next);
- textRange.end = start8 - utf8;
- if (!textRange.empty()) {
- regions->emplace_back(textRange.start, textRange.end, currentLevel);
+ // One or two codepoints refer to the same text index
+ uint16_t buffer[2];
+ size_t count = SkUTF::ToUTF16(u, buffer);
+ fUTF8IndexForUTF16Index.emplace_back(index);
+ if (count > 1) {
+ fUTF8IndexForUTF16Index.emplace_back(index);
+ }
}
-
- return true;
+ fUTF16IndexForUTF8Index.emplace_back(fUTF8IndexForUTF16Index.size());
+ fUTF8IndexForUTF16Index.emplace_back(fText.size());
}
} // namespace textlayout
diff --git a/chromium/third_party/skia/modules/skparagraph/src/ParagraphImpl.h b/chromium/third_party/skia/modules/skparagraph/src/ParagraphImpl.h
index 36b8abf53ad..bda3d1fed3b 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/ParagraphImpl.h
+++ b/chromium/third_party/skia/modules/skparagraph/src/ParagraphImpl.h
@@ -2,24 +2,59 @@
#ifndef ParagraphImpl_DEFINED
#define ParagraphImpl_DEFINED
-#include <unicode/brkiter.h>
-#include <unicode/ubidi.h>
-#include <unicode/unistr.h>
-#include <unicode/urename.h>
+#include "include/core/SkFont.h"
+#include "include/core/SkPaint.h"
#include "include/core/SkPicture.h"
-#include "include/private/SkMutex.h"
+#include "include/core/SkPoint.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkString.h"
+#include "include/core/SkTypes.h"
+#include "include/private/SkBitmaskEnum.h"
+#include "include/private/SkTArray.h"
#include "include/private/SkTHash.h"
+#include "include/private/SkTemplates.h"
+#include "modules/skparagraph/include/DartTypes.h"
+#include "modules/skparagraph/include/FontCollection.h"
#include "modules/skparagraph/include/Paragraph.h"
+#include "modules/skparagraph/include/ParagraphCache.h"
#include "modules/skparagraph/include/ParagraphStyle.h"
+#include "modules/skparagraph/include/TextShadow.h"
#include "modules/skparagraph/include/TextStyle.h"
#include "modules/skparagraph/src/Run.h"
-#include "modules/skparagraph/src/TextLine.h"
+#include "src/core/SkSpan.h"
+
+#include <unicode/ubrk.h>
+#include <memory>
+#include <string>
+#include <vector>
class SkCanvas;
namespace skia {
namespace textlayout {
+enum CodeUnitFlags {
+ kNoCodeUnitFlag = 0x0,
+ kPartOfWhiteSpace = 0x1,
+ kGraphemeStart = 0x2,
+ kSoftLineBreakBefore = 0x4,
+ kHardLineBreakBefore = 0x8,
+};
+}
+}
+
+namespace sknonstd {
+template <> struct is_bitmask_enum<skia::textlayout::CodeUnitFlags> : std::true_type {};
+}
+
+namespace skia {
+namespace textlayout {
+
+class LineMetrics;
+class TextLine;
+
template <typename T> bool operator==(const SkSpan<T>& a, const SkSpan<T>& b) {
return a.size() == b.size() && a.begin() == b.begin();
}
@@ -56,45 +91,6 @@ struct BidiRegion {
uint8_t direction;
};
-class TextBreaker {
-public:
- TextBreaker() : fInitialized(false), fPos(-1) {}
-
- bool initialize(SkSpan<const char> text, UBreakIteratorType type);
-
- bool initialized() const { return fInitialized; }
-
- size_t first() {
- fPos = ubrk_first(fIterator.get());
- return eof() ? fSize : fPos;
- }
-
- size_t next() {
- fPos = ubrk_next(fIterator.get());
- return eof() ? fSize : fPos;
- }
-
- size_t preceding(size_t offset) {
- auto pos = ubrk_preceding(fIterator.get(), offset);
- return pos == icu::BreakIterator::DONE ? 0 : pos;
- }
-
- size_t following(size_t offset) {
- auto pos = ubrk_following(fIterator.get(), offset);
- return pos == icu::BreakIterator::DONE ? fSize : pos;
- }
-
- int32_t status() { return ubrk_getRuleStatus(fIterator.get()); }
-
- bool eof() { return fPos == icu::BreakIterator::DONE; }
-
-private:
- std::unique_ptr<UBreakIterator, SkFunctionWrapper<decltype(ubrk_close), ubrk_close>> fIterator;
- bool fInitialized;
- int32_t fPos;
- size_t fSize;
-};
-
class ParagraphImpl final : public Paragraph {
public:
@@ -142,9 +138,12 @@ public:
const ParagraphStyle& paragraphStyle() const { return fParagraphStyle; }
SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); }
sk_sp<FontCollection> fontCollection() const { return fFontCollection; }
- const SkTHashSet<size_t>& graphemes() const { return fGraphemes; }
- SkSpan<Codepoint> codepoints(){ return SkSpan<Codepoint>(fCodePoints.begin(), fCodePoints.size()); }
void formatLines(SkScalar maxWidth);
+ void ensureUTF16Mapping();
+ TextIndex findGraphemeStart(TextIndex index);
+ size_t getUTF16Index(TextIndex index) {
+ return fUTF16IndexForUTF8Index[index];
+ }
bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); }
bool strutForceHeight() const {
@@ -158,7 +157,16 @@ public:
SkSpan<const char> text(TextRange textRange);
SkSpan<Cluster> clusters(ClusterRange clusterRange);
Cluster& cluster(ClusterIndex clusterIndex);
- Run& run(RunIndex runIndex);
+ ClusterIndex clusterIndex(TextIndex textIndex) {
+ auto clusterIndex = this->fClustersIndexFromCodeUnit[textIndex];
+ SkASSERT(clusterIndex != EMPTY_INDEX);
+ return clusterIndex;
+ }
+ Run& run(RunIndex runIndex) {
+ SkASSERT(runIndex < fRuns.size());
+ return fRuns[runIndex];
+ }
+
Run& runByCluster(ClusterIndex clusterIndex);
SkSpan<Block> blocks(BlockRange blockRange);
Block& block(BlockIndex blockIndex);
@@ -176,8 +184,12 @@ public:
void resetContext();
void resolveStrut();
+
+ bool computeCodeUnitProperties();
+ bool computeWords();
+ bool getBidiRegions();
+
void buildClusterTable();
- void markLineBreaks();
void spaceGlyphs();
bool shapeTextIntoEndlessLine();
void breakShapedTextIntoLines(SkScalar maxWidth);
@@ -201,6 +213,12 @@ public:
}
}
+ using CodeUnitRangeVisitor = std::function<bool(TextRange textRange)>;
+ void forEachCodeUnitPropertyRange(CodeUnitFlags property, CodeUnitRangeVisitor visitor);
+ size_t getWhitespacesLength(TextRange textRange);
+
+ bool codeUnitHasProperty(size_t index, CodeUnitFlags property) const { return (fCodeUnitProperties[index] & property) == property; }
+
private:
friend class ParagraphBuilder;
friend class ParagraphCacheKey;
@@ -212,13 +230,8 @@ private:
void calculateBoundaries();
- void markGraphemes16();
- void markGraphemes();
-
void computeEmptyMetrics();
- bool calculateBidiRegions(SkTArray<BidiRegion>* regions);
-
// Input
SkTArray<StyleBlock<SkScalar>> fLetterSpaceStyles;
SkTArray<StyleBlock<SkScalar>> fWordSpaceStyles;
@@ -234,12 +247,17 @@ private:
InternalState fState;
SkTArray<Run, false> fRuns; // kShaped
SkTArray<Cluster, true> fClusters; // kClusterized (cached: text, word spacing, letter spacing, resolved fonts)
- SkTArray<Grapheme, true> fGraphemes16;
- SkTArray<Codepoint, true> fCodePoints;
- SkTHashSet<size_t> fGraphemes;
+ SkTArray<CodeUnitFlags> fCodeUnitProperties;
+ SkTArray<size_t> fClustersIndexFromCodeUnit;
+ std::vector<size_t> fWords;
+ SkTArray<BidiRegion> fBidiRegions;
+ // These two arrays are used in measuring methods (getRectsForRange, getGlyphPositionAtCoordinate)
+ // They are filled lazily whenever they need and cached
+ SkTArray<TextIndex, true> fUTF8IndexForUTF16Index;
+ SkTArray<size_t, true> fUTF16IndexForUTF8Index;
size_t fUnresolvedGlyphs;
- SkTArray<TextLine, true> fLines; // kFormatted (cached: width, max lines, ellipsis, text align)
+ SkTArray<TextLine, false> fLines; // kFormatted (cached: width, max lines, ellipsis, text align)
sk_sp<SkPicture> fPicture; // kRecorded (cached: text styles)
SkTArray<ResolvedFontDescriptor> fFontSwitches;
@@ -251,9 +269,9 @@ private:
SkScalar fOldHeight;
SkScalar fMaxWidthWithTrailingSpaces;
SkRect fOrigin;
- std::vector<size_t> fWords;
};
} // namespace textlayout
} // namespace skia
+
#endif // ParagraphImpl_DEFINED
diff --git a/chromium/third_party/skia/modules/skparagraph/src/ParagraphStyle.cpp b/chromium/third_party/skia/modules/skparagraph/src/ParagraphStyle.cpp
index 8327790a854..c40372dce02 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/ParagraphStyle.cpp
+++ b/chromium/third_party/skia/modules/skparagraph/src/ParagraphStyle.cpp
@@ -1,7 +1,8 @@
// Copyright 2019 Google LLC.
-#include <string>
+
+#include "modules/skparagraph/include/DartTypes.h"
#include "modules/skparagraph/include/ParagraphStyle.h"
-#include "unicode/unistr.h"
+#include "modules/skparagraph/src/ParagraphUtil.h"
namespace skia {
namespace textlayout {
@@ -36,11 +37,7 @@ TextAlign ParagraphStyle::effective_align() const {
}
void ParagraphStyle::setEllipsis(const std::u16string& ellipsis) {
- icu::UnicodeString unicode;
- unicode.setTo((UChar*)ellipsis.data());
- std::string str;
- unicode.toUTF8String(str);
- fEllipsis = SkString(str.c_str());
+ fEllipsis = SkStringFromU16String(ellipsis);
}
} // namespace textlayout
} // namespace skia
diff --git a/chromium/third_party/skia/modules/skparagraph/src/ParagraphUtil.cpp b/chromium/third_party/skia/modules/skparagraph/src/ParagraphUtil.cpp
new file mode 100644
index 00000000000..d78ad656878
--- /dev/null
+++ b/chromium/third_party/skia/modules/skparagraph/src/ParagraphUtil.cpp
@@ -0,0 +1,34 @@
+// Copyright 2019 Google LLC.
+
+#include "include/core/SkString.h"
+#include "include/core/SkTypes.h"
+#include "include/private/SkTo.h"
+#include "modules/skparagraph/src/ParagraphUtil.h"
+
+#include <unicode/umachine.h>
+#include <unicode/ustring.h>
+#include <unicode/utypes.h>
+#include <string>
+
+namespace skia {
+namespace textlayout {
+
+SkString SkStringFromU16String(const std::u16string& utf16text) {
+ SkString dst;
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t dstSize;
+ // Getting the length like this seems to always set U_BUFFER_OVERFLOW_ERROR
+ u_strToUTF8(nullptr, 0, &dstSize, (UChar*)utf16text.data(), SkToS32(utf16text.size()), &status);
+ dst.resize(dstSize);
+ status = U_ZERO_ERROR;
+ u_strToUTF8(dst.writable_str(), dst.size(), nullptr,
+ (UChar*)utf16text.data(), SkToS32(utf16text.size()), &status);
+ if (U_FAILURE(status)) {
+ SkDEBUGF("Invalid UTF-16 input: %s", u_errorName(status));
+ return dst;
+ }
+ return dst;
+}
+
+}
+}
diff --git a/chromium/third_party/skia/modules/skparagraph/src/ParagraphUtil.h b/chromium/third_party/skia/modules/skparagraph/src/ParagraphUtil.h
new file mode 100644
index 00000000000..a32025ab805
--- /dev/null
+++ b/chromium/third_party/skia/modules/skparagraph/src/ParagraphUtil.h
@@ -0,0 +1,14 @@
+// Copyright 2020 Google LLC.
+#ifndef ParagraphUtil_DEFINED
+#define ParagraphUtil_DEFINED
+
+#include "include/core/SkString.h"
+#include <string>
+
+namespace skia {
+namespace textlayout {
+SkString SkStringFromU16String(const std::u16string& utf16text);
+}
+}
+
+#endif
diff --git a/chromium/third_party/skia/modules/skparagraph/src/Run.cpp b/chromium/third_party/skia/modules/skparagraph/src/Run.cpp
index e679be8648c..80c5222f05d 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/Run.cpp
+++ b/chromium/third_party/skia/modules/skparagraph/src/Run.cpp
@@ -1,35 +1,32 @@
// Copyright 2019 Google LLC.
-#include "modules/skparagraph/src/Run.h"
-#include <unicode/brkiter.h>
#include "include/core/SkFontMetrics.h"
+#include "include/core/SkTextBlob.h"
+#include "include/private/SkFloatingPoint.h"
+#include "include/private/SkMalloc.h"
+#include "include/private/SkTo.h"
+#include "modules/skparagraph/include/DartTypes.h"
+#include "modules/skparagraph/include/TextStyle.h"
#include "modules/skparagraph/src/ParagraphImpl.h"
-#include <algorithm>
+#include "modules/skparagraph/src/Run.h"
+#include "modules/skshaper/include/SkShaper.h"
#include "src/utils/SkUTF.h"
-namespace {
-
-SkUnichar utf8_next(const char** ptr, const char* end) {
- SkUnichar val = SkUTF::NextUTF8(ptr, end);
- return val < 0 ? 0xFFFD : val;
-}
-
-}
-
namespace skia {
namespace textlayout {
Run::Run(ParagraphImpl* master,
const SkShaper::RunHandler::RunInfo& info,
size_t firstChar,
- SkScalar lineHeight,
+ SkScalar heightMultiplier,
size_t index,
SkScalar offsetX)
- : fMaster(master)
- , fTextRange(firstChar + info.utf8Range.begin(), firstChar + info.utf8Range.end())
- , fClusterRange(EMPTY_CLUSTERS)
- , fClusterStart(firstChar) {
- fFont = info.fFont;
- fHeightMultiplier = lineHeight;
+ : fMaster(master)
+ , fTextRange(firstChar + info.utf8Range.begin(), firstChar + info.utf8Range.end())
+ , fClusterRange(EMPTY_CLUSTERS)
+ , fFont(info.fFont)
+ , fClusterStart(firstChar)
+ , fHeightMultiplier(heightMultiplier)
+{
fBidiLevel = info.fBidiLevel;
fAdvance = info.fAdvance;
fIndex = index;
@@ -38,21 +35,34 @@ Run::Run(ParagraphImpl* master,
fGlyphs.push_back_n(info.glyphCount);
fBounds.push_back_n(info.glyphCount);
fPositions.push_back_n(info.glyphCount + 1);
- fOffsets.push_back_n(info.glyphCount + 1);
fClusterIndexes.push_back_n(info.glyphCount + 1);
fShifts.push_back_n(info.glyphCount + 1, 0.0);
info.fFont.getMetrics(&fFontMetrics);
+
+ this->calculateMetrics();
+
fSpaced = false;
// To make edge cases easier:
fPositions[info.glyphCount] = fOffset + fAdvance;
- fOffsets[info.glyphCount] = { 0, 0};
fClusterIndexes[info.glyphCount] = this->leftToRight() ? info.utf8Range.end() : info.utf8Range.begin();
fEllipsis = false;
fPlaceholderIndex = std::numeric_limits<size_t>::max();
}
+void Run::calculateMetrics() {
+ fCorrectAscent = fFontMetrics.fAscent - fFontMetrics.fLeading * 0.5;
+ fCorrectDescent = fFontMetrics.fDescent + fFontMetrics.fLeading * 0.5;
+ fCorrectLeading = 0;
+ if (!SkScalarNearlyZero(fHeightMultiplier)) {
+ auto multiplier = fHeightMultiplier * fFont.getSize() /
+ (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading);
+ fCorrectAscent *= multiplier;
+ fCorrectDescent *= multiplier;
+ }
+}
+
SkShaper::RunHandler::Buffer Run::newRunBuffer() {
- return {fGlyphs.data(), fPositions.data(), fOffsets.data(), fClusterIndexes.data(), fOffset};
+ return {fGlyphs.data(), fPositions.data(), nullptr, fClusterIndexes.data(), fOffset};
}
void Run::commit() {
@@ -74,81 +84,46 @@ SkScalar Run::calculateWidth(size_t start, size_t end, bool clip) const {
return posX(end) - posX(start) + shift + correction;
}
-void Run::copyTo(SkTextBlobBuilder& builder, size_t pos, size_t size, SkVector runOffset) const {
+void Run::copyTo(SkTextBlobBuilder& builder, size_t pos, size_t size) const {
SkASSERT(pos + size <= this->size());
const auto& blobBuffer = builder.allocRunPos(fFont, SkToInt(size));
sk_careful_memcpy(blobBuffer.glyphs, fGlyphs.data() + pos, size * sizeof(SkGlyphID));
- for (size_t i = 0; i < size; ++i) {
- auto point = fPositions[i + pos];
- auto offset = fOffsets[i + pos];
- point.offset(offset.fX, offset.fY);
- if (fSpaced) {
- point.fX += fShifts[i + pos];
- }
- if (!fJustificationShifts.empty()) {
- point.fX += fJustificationShifts[i + pos].fX;
- }
- blobBuffer.points()[i] = point + runOffset;
- }
-}
-
-std::tuple<bool, ClusterIndex, ClusterIndex> Run::findLimitingClusters(TextRange text, bool extendToClusters) const {
-
- if (text.width() == 0) {
- for (auto i = fClusterRange.start; i != fClusterRange.end; ++i) {
- auto& cluster = fMaster->cluster(i);
- if (cluster.textRange().end >= text.end && cluster.textRange().start <= text.start) {
- return std::make_tuple(true, i, i);
- }
- }
- return std::make_tuple(false, 0, 0);
- }
- Cluster* start = nullptr;
- Cluster* end = nullptr;
- if (extendToClusters) {
- for (auto i = fClusterRange.start; i != fClusterRange.end; ++i) {
- auto& cluster = fMaster->cluster(i);
- auto clusterRange = cluster.textRange();
- if (clusterRange.end <= text.start) {
- continue;
- } else if (clusterRange.start >= text.end) {
- break;
- }
- TextRange s = TextRange(std::max(clusterRange.start, text.start),
- std::min(clusterRange.end, text.end));
- if (s.width() > 0) {
- if (start == nullptr) {
- start = &cluster;
- }
- end = &cluster;
- }
- }
+ if (!fSpaced && fJustificationShifts.empty()) {
+ sk_careful_memcpy(blobBuffer.points(), fPositions.data() + pos, size * sizeof(SkPoint));
} else {
- // We need this branch when we draw styles for the part of a cluster
- for (auto i = fClusterRange.start; i != fClusterRange.end; ++i) {
- auto& cluster = fMaster->cluster(i);
- if (cluster.textRange().end > text.start && start == nullptr) {
- start = &cluster;
+ for (size_t i = 0; i < size; ++i) {
+ auto point = fPositions[i + pos];
+ if (fSpaced) {
+ point.fX += fShifts[i + pos];
}
- if (cluster.textRange().start < text.end) {
- end = &cluster;
- } else {
- break;
+ if (!fJustificationShifts.empty()) {
+ point.fX += fJustificationShifts[i + pos].fX;
}
+ blobBuffer.points()[i] = point;
}
}
+}
- if (start == nullptr || end == nullptr) {
- return std::make_tuple(false, 0, 0);
+// Find a cluster range from text range (within one run)
+// Cluster range is normalized ([start:end) start < end regardless of TextDirection
+// Boolean value in triple indicates whether the cluster range was found or not
+std::tuple<bool, ClusterIndex, ClusterIndex> Run::findLimitingClusters(TextRange text) const {
+ if (text.width() == 0) {
+ // Special Flutter case for "\n" and "...\n"
+ if (text.end > this->fTextRange.start) {
+ ClusterIndex index = fMaster->clusterIndex(text.end - 1);
+ return std::make_tuple(true, index, index);
+ } else {
+ return std::make_tuple(false, 0, 0);
+ }
}
+ ClusterIndex startIndex = fMaster->clusterIndex(text.start);
+ ClusterIndex endIndex = fMaster->clusterIndex(text.end - 1);
if (!leftToRight()) {
- std::swap(start, end);
+ std::swap(startIndex, endIndex);
}
-
- size_t startIndex = start - fMaster->clusters().begin();
- size_t endIndex = end - fMaster->clusters().begin();
return std::make_tuple(startIndex != fClusterRange.end && endIndex != fClusterRange.end, startIndex, endIndex);
}
@@ -307,25 +282,12 @@ void Run::updateMetrics(InternalLineMetrics* endlineMetrics) {
break;
}
+ this->calculateMetrics();
+
// Make sure the placeholder can fit the line
endlineMetrics->add(this);
}
-void Cluster::setIsWhiteSpaces() {
-
- fWhiteSpaces = false;
-
- auto span = fMaster->text(fTextRange);
- const char* ch = span.begin();
- while (ch < span.end()) {
- auto unichar = utf8_next(&ch, span.end());
- if (!u_isWhitespace(unichar)) {
- return;
- }
- }
- fWhiteSpaces = true;
-}
-
SkScalar Cluster::sizeToChar(TextIndex ch) const {
if (ch < fTextRange.start || ch >= fTextRange.end) {
return 0;
@@ -382,6 +344,18 @@ SkFont Cluster::font() const {
return fMaster->run(fRunIndex).font();
}
+bool Cluster::isHardBreak() const {
+ return fMaster->codeUnitHasProperty(fTextRange.end,CodeUnitFlags::kHardLineBreakBefore);
+}
+
+bool Cluster::isSoftBreak() const {
+ return fMaster->codeUnitHasProperty(fTextRange.end,CodeUnitFlags::kSoftLineBreakBefore);
+}
+
+bool Cluster::isGraphemeBreak() const {
+ return fMaster->codeUnitHasProperty(fTextRange.end,CodeUnitFlags::kGraphemeStart);
+}
+
Cluster::Cluster(ParagraphImpl* master,
RunIndex runIndex,
size_t start,
@@ -398,9 +372,9 @@ Cluster::Cluster(ParagraphImpl* master,
, fWidth(width)
, fSpacing(0)
, fHeight(height)
- , fHalfLetterSpacing(0.0)
- , fWhiteSpaces(false)
- , fBreakType(None) {
+ , fHalfLetterSpacing(0.0) {
+ size_t len = fMaster->getWhitespacesLength(fTextRange);
+ fIsWhiteSpaces = (len == this->fTextRange.width());
}
} // namespace textlayout
diff --git a/chromium/third_party/skia/modules/skparagraph/src/Run.h b/chromium/third_party/skia/modules/skparagraph/src/Run.h
index df61276e3ee..c50be46df55 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/Run.h
+++ b/chromium/third_party/skia/modules/skparagraph/src/Run.h
@@ -2,21 +2,32 @@
#ifndef Run_DEFINED
#define Run_DEFINED
+#include "include/core/SkFont.h"
#include "include/core/SkFontMetrics.h"
#include "include/core/SkPoint.h"
-#include "include/core/SkTextBlob.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkTypes.h"
+#include "include/private/SkTArray.h"
#include "modules/skparagraph/include/DartTypes.h"
#include "modules/skparagraph/include/TextStyle.h"
#include "modules/skshaper/include/SkShaper.h"
#include "src/core/SkSpan.h"
-#include <functional> // std::function
+
+#include <math.h>
+#include <algorithm>
+#include <functional>
+#include <limits>
+#include <tuple>
+
+class SkTextBlobBuilder;
namespace skia {
namespace textlayout {
-class ParagraphImpl;
class Cluster;
-class Run;
+class InternalLineMetrics;
+class ParagraphImpl;
typedef size_t RunIndex;
const size_t EMPTY_RUN = EMPTY_INDEX;
@@ -29,9 +40,6 @@ const SkRange<size_t> EMPTY_CLUSTERS = EMPTY_RANGE;
typedef size_t GraphemeIndex;
typedef SkRange<GraphemeIndex> GraphemeRange;
-typedef size_t CodepointIndex;
-typedef SkRange<CodepointIndex> CodepointRange;
-
typedef size_t GlyphIndex;
typedef SkRange<GlyphIndex> GlyphRange;
@@ -44,31 +52,27 @@ class DirText {
size_t end;
};
-class InternalLineMetrics;
class Run {
public:
- Run() = default;
Run(ParagraphImpl* master,
const SkShaper::RunHandler::RunInfo& info,
size_t firstChar,
- SkScalar lineHeight,
+ SkScalar heightMultiplier,
size_t index,
SkScalar shiftX);
- ~Run() {}
+ Run(const Run&) = default;
+ Run& operator=(const Run&) = delete;
+ Run(Run&&) = default;
+ Run& operator=(Run&&) = delete;
+ ~Run() = default;
void setMaster(ParagraphImpl* master) { fMaster = master; }
SkShaper::RunHandler::Buffer newRunBuffer();
- SkScalar posX(size_t index) const {
- return fPositions[index].fX + fOffsets[index].fX;
- }
- void addX(size_t index, SkScalar shift) {
- fPositions[index].fX += shift;
- }
- SkScalar posY(size_t index) const {
- return fPositions[index].fY + fOffsets[index].fY;
- }
+ SkScalar posX(size_t index) const { return fPositions[index].fX; }
+ void addX(size_t index, SkScalar shift) { fPositions[index].fX += shift; }
+ SkScalar posY(size_t index) const { return fPositions[index].fY; }
size_t size() const { return fGlyphs.size(); }
void setWidth(SkScalar width) { fAdvance.fX = width; }
void setHeight(SkScalar height) { fAdvance.fY = height; }
@@ -77,36 +81,15 @@ public:
fOffset.fY += shiftY;
}
SkVector advance() const {
- return SkVector::Make(fAdvance.fX, fFontMetrics.fDescent - fFontMetrics.fAscent);
+ return SkVector::Make(fAdvance.fX, fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading);
}
SkVector offset() const { return fOffset; }
SkScalar ascent() const { return fFontMetrics.fAscent; }
SkScalar descent() const { return fFontMetrics.fDescent; }
SkScalar leading() const { return fFontMetrics.fLeading; }
- SkScalar correctAscent() const {
-
- if (fHeightMultiplier == 0) {
- return fFontMetrics.fAscent - fFontMetrics.fLeading / 2;
- }
- return fFontMetrics.fAscent * fHeightMultiplier * fFont.getSize() /
- (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading / 2);
- }
- SkScalar correctDescent() const {
-
- if (fHeightMultiplier == 0) {
- return fFontMetrics.fDescent + fFontMetrics.fLeading / 2;
- }
- return fFontMetrics.fDescent * fHeightMultiplier * fFont.getSize() /
- (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading / 2);
- }
- SkScalar correctLeading() const {
-
- if (fHeightMultiplier == 0) {
- return fFontMetrics.fAscent;
- }
- return fFontMetrics.fLeading * fHeightMultiplier * fFont.getSize() /
- (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading);
- }
+ SkScalar correctAscent() const { return fCorrectAscent; }
+ SkScalar correctDescent() const { return fCorrectDescent; }
+ SkScalar correctLeading() const { return fCorrectLeading; }
const SkFont& font() const { return fFont; }
bool leftToRight() const { return fBidiLevel % 2 == 0; }
TextDirection getTextDirection() const { return leftToRight() ? TextDirection::kLtr : TextDirection::kRtl; }
@@ -125,6 +108,7 @@ public:
bool isEllipsis() const { return fEllipsis; }
+ void calculateMetrics();
void updateMetrics(InternalLineMetrics* endlineMetrics);
void setClusterRange(size_t from, size_t to) { fClusterRange = ClusterRange(from, to); }
@@ -145,7 +129,7 @@ public:
}
SkScalar calculateWidth(size_t start, size_t end, bool clip) const;
- void copyTo(SkTextBlobBuilder& builder, size_t pos, size_t size, SkVector offset) const;
+ void copyTo(SkTextBlobBuilder& builder, size_t pos, size_t size) const;
using ClusterTextVisitor = std::function<void(size_t glyphStart,
size_t glyphEnd,
@@ -158,16 +142,13 @@ public:
using ClusterVisitor = std::function<void(Cluster* cluster)>;
void iterateThroughClusters(const ClusterVisitor& visitor);
- std::tuple<bool, ClusterIndex, ClusterIndex> findLimitingClusters(TextRange text, bool onlyInnerClusters) const;
+ std::tuple<bool, ClusterIndex, ClusterIndex> findLimitingClusters(TextRange text) const;
SkSpan<const SkGlyphID> glyphs() const {
return SkSpan<const SkGlyphID>(fGlyphs.begin(), fGlyphs.size());
}
SkSpan<const SkPoint> positions() const {
return SkSpan<const SkPoint>(fPositions.begin(), fPositions.size());
}
- SkSpan<const SkPoint> offsets() const {
- return SkSpan<const SkPoint>(fOffsets.begin(), fOffsets.size());
- }
SkSpan<const uint32_t> clusterIndexes() const {
return SkSpan<const uint32_t>(fClusterIndexes.begin(), fClusterIndexes.size());
}
@@ -197,12 +178,8 @@ private:
ClusterRange fClusterRange;
SkFont fFont;
- SkFontMetrics fFontMetrics;
- SkScalar fHeightMultiplier;
size_t fPlaceholderIndex;
- bool fEllipsis;
size_t fIndex;
- uint8_t fBidiLevel;
SkVector fAdvance;
SkVector fOffset;
TextIndex fClusterStart;
@@ -210,29 +187,20 @@ private:
SkSTArray<128, SkGlyphID, true> fGlyphs;
SkSTArray<128, SkPoint, true> fPositions;
SkSTArray<128, SkPoint, true> fJustificationShifts; // For justification (current and prev shifts)
- SkSTArray<128, SkPoint, true> fOffsets;
SkSTArray<128, uint32_t, true> fClusterIndexes;
SkSTArray<128, SkRect, true> fBounds;
SkSTArray<128, SkScalar, true> fShifts; // For formatting (letter/word spacing)
- bool fSpaced;
-};
-
-struct Codepoint {
- Codepoint(GraphemeIndex graphemeIndex, TextIndex textIndex, size_t index)
- : fGrapheme(graphemeIndex), fTextIndex(textIndex), fIndex(index) { }
-
- GraphemeIndex fGrapheme;
- TextIndex fTextIndex; // Used for getGlyphPositionAtCoordinate
- size_t fIndex;
-};
+ SkFontMetrics fFontMetrics;
+ const SkScalar fHeightMultiplier;
+ SkScalar fCorrectAscent;
+ SkScalar fCorrectDescent;
+ SkScalar fCorrectLeading;
-struct Grapheme {
- Grapheme(CodepointRange codepoints, TextRange textRange)
- : fCodepointRange(codepoints), fTextRange(textRange) { }
- CodepointRange fCodepointRange;
- TextRange fTextRange; // Used for getRectsForRange
+ bool fSpaced;
+ bool fEllipsis;
+ uint8_t fBidiLevel;
};
class Cluster {
@@ -254,9 +222,7 @@ public:
, fWidth()
, fSpacing(0)
, fHeight()
- , fHalfLetterSpacing(0.0)
- , fWhiteSpaces(false)
- , fBreakType(None) {}
+ , fHalfLetterSpacing(0.0) {}
Cluster(ParagraphImpl* master,
RunIndex runIndex,
@@ -281,14 +247,11 @@ public:
fWidth += shift;
}
- void setBreakType(BreakType type) { fBreakType = type; }
- bool isWhitespaces() const { return fWhiteSpaces; }
- bool canBreakLineAfter() const {
- return fBreakType == SoftLineBreak || fBreakType == HardLineBreak;
- }
- bool isHardBreak() const { return fBreakType == HardLineBreak; }
- bool isSoftBreak() const { return fBreakType == SoftLineBreak; }
- bool isGraphemeBreak() const { return fBreakType == GraphemeBreak; }
+ bool isWhitespaces() const { return fIsWhiteSpaces; }
+ bool isHardBreak() const;
+ bool isSoftBreak() const;
+ bool isGraphemeBreak() const;
+ bool canBreakLineAfter() const { return isHardBreak() || isSoftBreak(); }
size_t startPos() const { return fStart; }
size_t endPos() const { return fEnd; }
SkScalar width() const { return fWidth; }
@@ -308,8 +271,6 @@ public:
SkScalar trimmedWidth(size_t pos) const;
- void setIsWhiteSpaces();
-
bool contains(TextIndex ch) const { return ch >= fTextRange.start && ch < fTextRange.end; }
bool belongs(TextRange text) const {
@@ -335,8 +296,7 @@ private:
SkScalar fSpacing;
SkScalar fHeight;
SkScalar fHalfLetterSpacing;
- bool fWhiteSpaces;
- BreakType fBreakType;
+ bool fIsWhiteSpaces;
};
class InternalLineMetrics {
diff --git a/chromium/third_party/skia/modules/skparagraph/src/TextLine.cpp b/chromium/third_party/skia/modules/skparagraph/src/TextLine.cpp
index ce9b1a97955..128310366c3 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/TextLine.cpp
+++ b/chromium/third_party/skia/modules/skparagraph/src/TextLine.cpp
@@ -1,13 +1,34 @@
// Copyright 2019 Google LLC.
-#include "modules/skparagraph/src/TextLine.h"
-#include <unicode/brkiter.h>
-#include <unicode/ubidi.h>
+#include "include/core/SkBlurTypes.h"
+#include "include/core/SkCanvas.h"
+#include "include/core/SkFont.h"
+#include "include/core/SkFontMetrics.h"
+#include "include/core/SkMaskFilter.h"
+#include "include/core/SkPaint.h"
+#include "include/core/SkString.h"
+#include "include/core/SkTextBlob.h"
+#include "include/core/SkTypes.h"
+#include "include/private/SkTemplates.h"
+#include "include/private/SkTo.h"
+#include "modules/skparagraph/include/DartTypes.h"
+#include "modules/skparagraph/include/Metrics.h"
+#include "modules/skparagraph/include/ParagraphStyle.h"
+#include "modules/skparagraph/include/TextShadow.h"
+#include "modules/skparagraph/include/TextStyle.h"
#include "modules/skparagraph/src/Decorations.h"
#include "modules/skparagraph/src/ParagraphImpl.h"
+#include "modules/skparagraph/src/TextLine.h"
+#include "modules/skshaper/include/SkShaper.h"
+#include "src/core/SkSpan.h"
-#include "include/core/SkMaskFilter.h"
-#include "include/effects/SkDashPathEffect.h"
-#include "include/effects/SkDiscretePathEffect.h"
+#include <unicode/ubidi.h>
+#include <algorithm>
+#include <iterator>
+#include <limits>
+#include <map>
+#include <tuple>
+#include <type_traits>
+#include <utility>
namespace skia {
namespace textlayout {
@@ -107,16 +128,24 @@ TextLine::TextLine(ParagraphImpl* master,
}
// Get the logical order
- std::vector<UBiDiLevel> runLevels;
+
+ // This is just chosen to catch the common/fast cases. Feel free to tweak.
+ constexpr int kPreallocCount = 4;
+
+ SkAutoSTArray<kPreallocCount, UBiDiLevel> runLevels(numRuns);
+
+ size_t runLevelsIndex = 0;
for (auto runIndex = start.runIndex(); runIndex <= end.runIndex(); ++runIndex) {
auto& run = fMaster->run(runIndex);
- runLevels.emplace_back(run.fBidiLevel);
- fMaxRunMetrics.add(InternalLineMetrics(run.fFontMetrics.fAscent, run.fFontMetrics.fDescent, run.fFontMetrics.fLeading));
+ runLevels[runLevelsIndex++] = run.fBidiLevel;
+ fMaxRunMetrics.add(InternalLineMetrics(run.fFontMetrics.fAscent, run.fFontMetrics.fDescent,
+ run.fFontMetrics.fLeading));
}
+ SkASSERT(runLevelsIndex == numRuns);
- std::vector<int32_t> logicalOrder(numRuns);
- ubidi_reorderVisual(runLevels.data(), SkToU32(numRuns), logicalOrder.data());
+ SkAutoSTArray<kPreallocCount, int32_t> logicalOrder(numRuns);
+ ubidi_reorderVisual(runLevels.data(), SkToU32(numRuns), logicalOrder.data());
auto firstRunIndex = start.runIndex();
for (auto index : logicalOrder) {
fRunsInVisualOrder.push_back(firstRunIndex + index);
@@ -189,8 +218,7 @@ SkRect TextLine::calculateBoundaries() {
boundaries.fBottom += shadowRect.fBottom;
}
- boundaries.offset(this->fOffset); // Line offset from the beginning of the para
- boundaries.offset(this->fShift, 0); // Shift produced by formatting
+ boundaries.offset(this->offset()); // Line offset from the beginning of the para
boundaries.offset(0, this->baseline()); // Down by baseline
return boundaries;
@@ -201,9 +229,6 @@ void TextLine::paint(SkCanvas* textCanvas) {
return;
}
- textCanvas->save();
- textCanvas->translate(this->offset().fX, this->offset().fY);
-
if (fHasBackground) {
this->iterateThroughVisualRuns(false,
[textCanvas, this]
@@ -257,8 +282,6 @@ void TextLine::paint(SkCanvas* textCanvas) {
return true;
});
}
-
- textCanvas->restore();
}
void TextLine::format(TextAlign align, SkScalar maxWidth) {
@@ -345,22 +368,25 @@ void TextLine::paintText(SkCanvas* canvas, TextRange textRange, const TextStyle&
}
// TODO: This is the change for flutter, must be removed later
- SkScalar correctedBaseline = SkScalarFloorToScalar(this->baseline() + 0.5);
SkTextBlobBuilder builder;
- context.run->copyTo(builder, SkToU32(context.pos), context.size, SkVector::Make(0, correctedBaseline));
- canvas->save();
+ context.run->copyTo(builder, SkToU32(context.pos), context.size);
if (context.clippingNeeded) {
- canvas->clipRect(extendHeight(context));
+ canvas->save();
+ canvas->clipRect(extendHeight(context).makeOffset(this->offset()));
}
- canvas->translate(context.fTextShift, 0);
- canvas->drawTextBlob(builder.make(), 0, 0, paint);
- canvas->restore();
+ SkScalar correctedBaseline = SkScalarFloorToScalar(this->baseline() + 0.5);
+ canvas->drawTextBlob(builder.make(),
+ this->offset().fX + context.fTextShift, this->offset().fY + correctedBaseline, paint);
+
+ if (context.clippingNeeded) {
+ canvas->restore();
+ }
}
void TextLine::paintBackground(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const {
if (style.hasBackground()) {
- canvas->drawRect(context.clip, style.getBackground());
+ canvas->drawRect(context.clip.makeOffset(this->offset()), style.getBackground());
}
}
@@ -378,25 +404,32 @@ void TextLine::paintShadow(SkCanvas* canvas, TextRange textRange, const TextStyl
}
SkTextBlobBuilder builder;
- context.run->copyTo(builder, context.pos, context.size, SkVector::Make(0, shiftDown));
- canvas->save();
- SkRect clip = context.clip;
- clip.offset(shadow.fOffset);
+ context.run->copyTo(builder, context.pos, context.size);
+
if (context.clippingNeeded) {
- canvas->clipRect(extendHeight(context));
+ canvas->save();
+ SkRect clip = extendHeight(context);
+ clip.offset(this->offset());
+ canvas->clipRect(clip);
+ }
+ canvas->drawTextBlob(builder.make(),
+ this->offset().fX + shadow.fOffset.x() + context.fTextShift,
+ this->offset().fY + shadow.fOffset.y() + shiftDown,
+ paint);
+
+ if (context.clippingNeeded) {
+ canvas->restore();
}
- canvas->translate(context.fTextShift, 0);
- canvas->drawTextBlob(builder.make(), shadow.fOffset.x(), shadow.fOffset.y(), paint);
- canvas->restore();
}
}
void TextLine::paintDecorations(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->translate(this->offset().fX, this->offset().fY);
Decorations decorations;
SkScalar correctedBaseline = SkScalarFloorToScalar(this->baseline() + 0.5);
- decorations.paint(canvas, style, context, correctedBaseline, this->fShift);
-
+ decorations.paint(canvas, style, context, correctedBaseline, this->offset());
}
void TextLine::justify(SkScalar maxWidth) {
@@ -489,7 +522,7 @@ void TextLine::createEllipsis(SkScalar maxWidth, const SkString& ellipsis, bool)
auto attachEllipsis = [&](const Cluster* cluster){
// Shape the ellipsis
- Run* run = shapeEllipsis(ellipsis, cluster->run());
+ std::unique_ptr<Run> run = shapeEllipsis(ellipsis, cluster->run());
run->fClusterStart = cluster->textRange().start;
run->setMaster(fMaster);
@@ -500,7 +533,7 @@ void TextLine::createEllipsis(SkScalar maxWidth, const SkString& ellipsis, bool)
return false;
}
- fEllipsis = std::make_shared<Run>(*run);
+ fEllipsis = std::move(run);
fEllipsis->shift(width, 0);
fAdvance.fX = width;
return true;
@@ -517,13 +550,14 @@ void TextLine::createEllipsis(SkScalar maxWidth, const SkString& ellipsis, bool)
}
}
-Run* TextLine::shapeEllipsis(const SkString& ellipsis, Run* run) {
+std::unique_ptr<Run> TextLine::shapeEllipsis(const SkString& ellipsis, Run* run) {
class ShapeHandler final : public SkShaper::RunHandler {
public:
ShapeHandler(SkScalar lineHeight, const SkString& ellipsis)
: fRun(nullptr), fLineHeight(lineHeight), fEllipsis(ellipsis) {}
- Run* run() { return fRun; }
+ Run* run() & { return fRun.get(); }
+ std::unique_ptr<Run> run() && { return std::move(fRun); }
private:
void beginLine() override {}
@@ -533,7 +567,8 @@ Run* TextLine::shapeEllipsis(const SkString& ellipsis, Run* run) {
void commitRunInfo() override {}
Buffer runBuffer(const RunInfo& info) override {
- fRun = new Run(nullptr, info, 0, fLineHeight, 0, 0);
+ SkASSERT(!fRun);
+ fRun = std::unique_ptr<Run>(new Run(nullptr, info, 0, fLineHeight, 0, 0));
return fRun->newRunBuffer();
}
@@ -546,7 +581,7 @@ Run* TextLine::shapeEllipsis(const SkString& ellipsis, Run* run) {
void commitLine() override {}
- Run* fRun;
+ std::unique_ptr<Run> fRun;
SkScalar fLineHeight;
SkString fEllipsis;
};
@@ -558,7 +593,7 @@ Run* TextLine::shapeEllipsis(const SkString& ellipsis, Run* run) {
std::numeric_limits<SkScalar>::max(), &handler);
handler.run()->fTextRange = TextRange(0, ellipsis.size());
handler.run()->fMaster = fMaster;
- return handler.run();
+ return std::move(handler).run();
}
TextLine::ClipContext TextLine::measureTextInsideOneRun(TextRange textRange,
@@ -593,7 +628,7 @@ TextLine::ClipContext TextLine::measureTextInsideOneRun(TextRange textRange,
bool found;
ClusterIndex startIndex;
ClusterIndex endIndex;
- std::tie(found, startIndex, endIndex) = run->findLimitingClusters(textRange, limitToClusters);
+ std::tie(found, startIndex, endIndex) = run->findLimitingClusters(textRange);
if (!found) {
SkASSERT(textRange.empty() || limitToClusters);
return result;
@@ -647,6 +682,12 @@ TextLine::ClipContext TextLine::measureTextInsideOneRun(TextRange textRange,
result.clip.fRight = fAdvance.fX;
}
+ if (result.clip.width() < 0) {
+ // Weird situation when glyph offsets move the glyph to the left
+ // (happens with zalgo texts, for instance)
+ result.clip.fRight = result.clip.fLeft;
+ }
+
// The text must be aligned with the lineOffset
result.fTextShift = textStartInLine - textStartInRun;
@@ -658,7 +699,9 @@ void TextLine::iterateThroughClustersInGlyphsOrder(bool reversed,
const ClustersVisitor& visitor) const {
// Walk through the clusters in the logical order (or reverse)
SkSpan<const size_t> runs(fRunsInVisualOrder.data(), fRunsInVisualOrder.size());
- directional_for_each(runs, reversed, [&](decltype(runs[0]) r) {
+ bool ignore = false;
+ directional_for_each(runs, !reversed, [&](decltype(runs[0]) r) {
+ if (ignore) return;
auto run = this->fMaster->run(r);
auto trimmedRange = fClusterRange.intersection(run.clusterRange());
auto trailedRange = fGhostClusterRange.intersection(run.clusterRange());
@@ -666,12 +709,10 @@ void TextLine::iterateThroughClustersInGlyphsOrder(bool reversed,
auto trailed = fMaster->clusters(trailedRange);
auto trimmed = fMaster->clusters(trimmedRange);
- bool ignore = false;
directional_for_each(trailed, reversed != run.leftToRight(), [&](Cluster& cluster) {
if (ignore) return;
bool ghost = &cluster >= trimmed.end();
if (!includeGhosts && ghost) {
- ignore = true;
return;
}
if (!visitor(&cluster, ghost)) {
@@ -690,7 +731,8 @@ SkScalar TextLine::iterateThroughSingleRunByStyles(const Run* run,
if (run->fEllipsis) {
// Extra efforts to get the ellipsis text style
- ClipContext clipContext = this->measureTextInsideOneRun(run->textRange(), run, runOffset, 0, false, false);
+ ClipContext clipContext = this->measureTextInsideOneRun(run->textRange(), run, runOffset,
+ 0, false, false);
TextRange testRange(run->fClusterStart, run->fClusterStart + 1);
for (BlockIndex index = fBlockRange.start; index < fBlockRange.end; ++index) {
auto block = fMaster->styles().begin() + index;
@@ -704,7 +746,8 @@ SkScalar TextLine::iterateThroughSingleRunByStyles(const Run* run,
}
if (styleType == StyleType::kNone) {
- ClipContext clipContext = this->measureTextInsideOneRun(textRange, run, runOffset, 0, false, false);
+ ClipContext clipContext = this->measureTextInsideOneRun(textRange, run, runOffset,
+ 0, false, false);
if (clipContext.clip.height() > 0) {
visitor(textRange, TextStyle(), clipContext);
return clipContext.clip.width();
@@ -757,13 +800,14 @@ SkScalar TextLine::iterateThroughSingleRunByStyles(const Run* run,
}
// We have the style and the text
- auto textRange = TextRange(start, start + size);
+ auto runStyleTextRange = TextRange(start, start + size);
// Measure the text
- ClipContext clipContext = this->measureTextInsideOneRun(textRange, run, runOffset, textOffsetInRun, false, false);
+ ClipContext clipContext = this->measureTextInsideOneRun(runStyleTextRange, run, runOffset,
+ textOffsetInRun, false, false);
if (clipContext.clip.height() == 0) {
continue;
}
- visitor(textRange, *prevStyle, clipContext);
+ visitor(runStyleTextRange, *prevStyle, clipContext);
textOffsetInRun += clipContext.clip.width();
// Start all over again
@@ -843,7 +887,8 @@ LineMetrics TextLine::getMetrics() const {
result.fHeight = littleRound(fAdvance.fY);
result.fWidth = littleRound(fAdvance.fX);
result.fLeft = fOffset.fX;
- result.fBaseline = fMaxRunMetrics.baseline() + (this - fMaster->lines().begin()) * result.fHeight;
+ // This is Flutter definition of a baseline
+ result.fBaseline = this->offset().fY + this->height() - this->sizes().descent();
result.fLineNumber = this - fMaster->lines().begin();
// Fill out the style parts
@@ -1086,29 +1131,19 @@ PositionWithAffinity TextLine::getGlyphPositionAtCoordinate(SkScalar dx) {
[this, dx, &result, &lookingForHit]
(TextRange textRange, const TextStyle& style, const TextLine::ClipContext& context) {
- auto findCodepointByTextIndex = [this](ClusterIndex clusterIndex8) {
- auto codepoints = fMaster->codepoints();
- auto codepoint = std::lower_bound(
- codepoints.begin(), codepoints.end(),
- clusterIndex8,
- [](const Codepoint& lhs,size_t rhs) -> bool { return lhs.fTextIndex < rhs; });
-
- return codepoint - codepoints.begin();
- };
-
auto offsetX = this->offset().fX;
if (dx < context.clip.fLeft + offsetX) {
// All the other runs are placed right of this one
- auto codepointIndex = findCodepointByTextIndex(context.run->globalClusterIndex(context.pos));
- result = { SkToS32(codepointIndex), kDownstream };
+ auto utf16Index = fMaster->getUTF16Index(context.run->globalClusterIndex(context.pos));
+ result = { SkToS32(utf16Index), kDownstream };
lookingForHit = false;
return false;
}
if (dx >= context.clip.fRight + offsetX) {
// We have to keep looking ; just in case keep the last one as the closest
- auto codepointIndex = findCodepointByTextIndex(context.run->globalClusterIndex(context.pos + context.size));
- result = { SkToS32(codepointIndex), kUpstream };
+ auto utf16Index = fMaster->getUTF16Index(context.run->globalClusterIndex(context.pos + context.size));
+ result = { SkToS32(utf16Index), kUpstream };
return true;
}
@@ -1125,53 +1160,34 @@ PositionWithAffinity TextLine::getGlyphPositionAtCoordinate(SkScalar dx) {
found = index;
}
- auto glyphStart = context.run->positionX(found) + context.fTextShift + offsetX;
- auto glyphWidth = context.run->positionX(found + 1) - context.run->positionX(found);
+ auto glyphemeStart = context.run->positionX(found) + context.fTextShift + offsetX;
+ auto glyphemeWidth = context.run->positionX(found + 1) - context.run->positionX(found);
+
+ // Find the grapheme range that contains the point
auto clusterIndex8 = context.run->globalClusterIndex(found);
auto clusterEnd8 = context.run->globalClusterIndex(found + 1);
-
- // Find the grapheme positions in codepoints that contains the point
- auto codepointIndex = findCodepointByTextIndex(clusterIndex8);
- CodepointRange codepoints(codepointIndex, codepointIndex);
- auto masterCodepoints = fMaster->codepoints();
- if (context.run->leftToRight()) {
- for (codepoints.end = codepointIndex;
- codepoints.end < masterCodepoints.size(); ++codepoints.end) {
- auto& cp = masterCodepoints[codepoints.end];
- if (cp.fTextIndex >= clusterEnd8) {
- break;
- }
- }
- } else {
- for (codepoints.end = codepointIndex;
- codepoints.end > 0; --codepoints.end) {
- auto& cp = masterCodepoints[codepoints.end];
- if (cp.fTextIndex <= clusterEnd8) {
- break;
- }
- }
- std::swap(codepoints.start, codepoints.end);
- }
-
- auto graphemeSize = codepoints.width();
+ auto graphemeStart = fMaster->findGraphemeStart(clusterIndex8);
+ auto graphemeWidth =
+ fMaster->findGraphemeStart(clusterEnd8) - graphemeStart;
+ auto utf16Index = fMaster->getUTF16Index(clusterIndex8);
// We only need to inspect one glyph (maybe not even the entire glyph)
SkScalar center;
bool insideGlyph = false;
- if (graphemeSize > 1) {
- auto averageCodepointWidth = glyphWidth / graphemeSize;
- auto delta = dx - glyphStart;
- auto insideIndex = SkScalarFloorToInt(delta / averageCodepointWidth);
- insideGlyph = delta > averageCodepointWidth;
- center = glyphStart + averageCodepointWidth * insideIndex + averageCodepointWidth / 2;
- codepointIndex += insideIndex;
+ if (graphemeWidth > 1) {
+ auto averageGlyphWidth = glyphemeWidth / graphemeWidth;
+ auto delta = dx - glyphemeStart;
+ auto insideIndex = SkScalarFloorToInt(delta / averageGlyphWidth);
+ insideGlyph = delta > averageGlyphWidth;
+ center = glyphemeStart + averageGlyphWidth * insideIndex + averageGlyphWidth / 2;
+ utf16Index += insideIndex;
} else {
- center = glyphStart + glyphWidth / 2;
+ center = glyphemeStart + glyphemeWidth / 2;
}
if ((dx < center) == context.run->leftToRight() || insideGlyph) {
- result = { SkToS32(codepointIndex), kDownstream };
+ result = { SkToS32(utf16Index), kDownstream };
} else {
- result = { SkToS32(codepointIndex + 1), kUpstream };
+ result = { SkToS32(utf16Index + 1), kUpstream };
}
// No need to continue
lookingForHit = false;
diff --git a/chromium/third_party/skia/modules/skparagraph/src/TextLine.h b/chromium/third_party/skia/modules/skparagraph/src/TextLine.h
index da54147e60a..73033f130f8 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/TextLine.h
+++ b/chromium/third_party/skia/modules/skparagraph/src/TextLine.h
@@ -2,18 +2,28 @@
#ifndef TextLine_DEFINED
#define TextLine_DEFINED
-#include "include/core/SkCanvas.h"
+#include "include/core/SkPoint.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkScalar.h"
#include "include/private/SkTArray.h"
-#include "include/private/SkTHash.h"
#include "modules/skparagraph/include/DartTypes.h"
#include "modules/skparagraph/include/Metrics.h"
#include "modules/skparagraph/include/TextStyle.h"
#include "modules/skparagraph/src/Run.h"
-#include "src/core/SkSpan.h"
+
+#include <stddef.h>
+#include <functional>
+#include <memory>
+#include <vector>
+
+class SkCanvas;
+class SkString;
namespace skia {
namespace textlayout {
+class ParagraphImpl;
+
class TextLine {
public:
@@ -27,6 +37,10 @@ public:
};
TextLine() = default;
+ TextLine(const TextLine&) = delete;
+ TextLine& operator=(const TextLine&) = delete;
+ TextLine(TextLine&&) = default;
+ TextLine& operator=(TextLine&&) = default;
~TextLine() = default;
TextLine(ParagraphImpl* master,
@@ -108,7 +122,7 @@ public:
private:
- Run* shapeEllipsis(const SkString& ellipsis, Run* run);
+ std::unique_ptr<Run> shapeEllipsis(const SkString& ellipsis, Run* run);
void justify(SkScalar maxWidth);
void paintText(SkCanvas* canvas, TextRange textRange, const TextStyle& style, const ClipContext& context) const;
@@ -124,13 +138,13 @@ private:
TextRange fTextWithWhitespacesRange;
ClusterRange fClusterRange;
ClusterRange fGhostClusterRange;
-
- SkTArray<size_t, true> fRunsInVisualOrder;
+ // Avoid the malloc/free in the common case of one run per line
+ SkSTArray<1, size_t, true> fRunsInVisualOrder;
SkVector fAdvance; // Text size
SkVector fOffset; // Text position
SkScalar fShift; // Let right
SkScalar fWidthWithSpaces;
- std::shared_ptr<Run> fEllipsis; // In case the line ends with the ellipsis
+ std::unique_ptr<Run> fEllipsis; // In case the line ends with the ellipsis
InternalLineMetrics fSizes; // Line metrics as a max of all run metrics and struts
InternalLineMetrics fMaxRunMetrics; // No struts - need it for GetRectForRange(max height)
bool fHasBackground;
diff --git a/chromium/third_party/skia/modules/skparagraph/src/TextStyle.cpp b/chromium/third_party/skia/modules/skparagraph/src/TextStyle.cpp
index 4dfa070b365..9445f7920ed 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/TextStyle.cpp
+++ b/chromium/third_party/skia/modules/skparagraph/src/TextStyle.cpp
@@ -15,7 +15,8 @@ TextStyle::TextStyle() : fFontStyle() {
// value to indicate no decoration color was set.
fDecoration.fColor = SK_ColorTRANSPARENT;
fDecoration.fStyle = TextDecorationStyle::kSolid;
- fDecoration.fMode = TextDecorationMode::kGaps;
+ // TODO: switch back to kGaps when (if) switching flutter to skparagraph
+ fDecoration.fMode = TextDecorationMode::kThrough;
// Thickness is applied as a multiplier to the default thickness of the font.
fDecoration.fThicknessMultiplier = 1.0;
fFontSize = 14.0;
diff --git a/chromium/third_party/skia/modules/skparagraph/src/TextWrapper.cpp b/chromium/third_party/skia/modules/skparagraph/src/TextWrapper.cpp
index 7c1fcf32595..bfee1b8d743 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/TextWrapper.cpp
+++ b/chromium/third_party/skia/modules/skparagraph/src/TextWrapper.cpp
@@ -10,9 +10,9 @@ SkScalar littleRound(SkScalar a) {
// This rounding is done to match Flutter tests. Must be removed..
auto val = std::fabs(a);
if (val < 10000) {
- return SkScalarRoundToScalar(a * 100.0)/100.0;
+ return SkScalarRoundToScalar(a * 100) * (1.0f/100);
} else if (val < 100000) {
- return SkScalarRoundToScalar(a * 10.0)/10.0;
+ return SkScalarRoundToScalar(a * 10) * (1.0f/10);
} else {
return SkScalarFloorToScalar(a);
}
diff --git a/chromium/third_party/skia/modules/skparagraph/src/TextWrapper.h b/chromium/third_party/skia/modules/skparagraph/src/TextWrapper.h
index 7dfd1051863..95f4b004bfc 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/TextWrapper.h
+++ b/chromium/third_party/skia/modules/skparagraph/src/TextWrapper.h
@@ -75,6 +75,7 @@ class TextWrapper {
fStart = ClusterPos(cluster, cluster->startPos());
}
fEnd = ClusterPos(cluster, cluster->endPos());
+ // TODO: Make sure all the checks are correct and there are no unnecessary checks
if (!cluster->run()->isPlaceholder()) {
fMetrics.add(cluster->run());
}
diff --git a/chromium/third_party/skia/modules/skparagraph/src/TypefaceFontProvider.cpp b/chromium/third_party/skia/modules/skparagraph/src/TypefaceFontProvider.cpp
index cb5c262da48..cd30a67d967 100644
--- a/chromium/third_party/skia/modules/skparagraph/src/TypefaceFontProvider.cpp
+++ b/chromium/third_party/skia/modules/skparagraph/src/TypefaceFontProvider.cpp
@@ -24,6 +24,10 @@ SkFontStyleSet* TypefaceFontProvider::onMatchFamily(const char familyName[]) con
return nullptr;
}
+sk_sp<SkTypeface> TypefaceFontProvider::onMakeFromFontData(std::unique_ptr<SkFontData>) const {
+ return nullptr;
+}
+
size_t TypefaceFontProvider::registerTypeface(sk_sp<SkTypeface> typeface) {
if (typeface == nullptr) {
return 0;
@@ -76,7 +80,9 @@ SkTypeface* TypefaceFontStyleSet::matchStyle(const SkFontStyle& pattern) {
}
void TypefaceFontStyleSet::appendTypeface(sk_sp<SkTypeface> typeface) {
- fStyles.emplace_back(std::move(typeface));
+ if (typeface.get() != nullptr) {
+ fStyles.emplace_back(std::move(typeface));
+ }
}
} // namespace textlayout
diff --git a/chromium/third_party/skia/modules/skplaintexteditor/BUILD.gn b/chromium/third_party/skia/modules/skplaintexteditor/BUILD.gn
index abf7d2aa68e..0b72bec1ecb 100644
--- a/chromium/third_party/skia/modules/skplaintexteditor/BUILD.gn
+++ b/chromium/third_party/skia/modules/skplaintexteditor/BUILD.gn
@@ -35,7 +35,8 @@ if (skia_use_icu && skia_use_harfbuzz) {
include_dirs = [ "../.." ]
public = [ "src/word_boundaries.h" ]
sources = [ "src/word_boundaries.cpp" ]
- deps = [ "../../third_party/icu" ]
+ configs += [ "../../third_party/icu/config:no_cxx" ]
+ deps = [ "//third_party/icu" ]
}
source_set("editor_app") {
diff --git a/chromium/third_party/skia/modules/skplaintexteditor/src/word_boundaries.cpp b/chromium/third_party/skia/modules/skplaintexteditor/src/word_boundaries.cpp
index 17c8cd35b2b..3b08f634a2f 100644
--- a/chromium/third_party/skia/modules/skplaintexteditor/src/word_boundaries.cpp
+++ b/chromium/third_party/skia/modules/skplaintexteditor/src/word_boundaries.cpp
@@ -1,50 +1,55 @@
// Copyright 2019 Google LLC.
// 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"
+#include "include/private/SkTemplates.h"
#include "modules/skplaintexteditor/src/word_boundaries.h"
-#include <unicode/brkiter.h>
-#include <unicode/unistr.h>
-
+#include <unicode/ubrk.h>
+#include <unicode/utext.h>
+#include <unicode/utypes.h>
#include <memory>
-std::vector<bool> GetUtf8WordBoundaries(const char* begin, size_t byteCount, const char* locale) {
- static constexpr UBreakIteratorType kIteratorType = UBRK_WORD;
- struct UTextCloser {
- void operator()(UText* p) { (void)utext_close(p); }
- };
- struct UBreakCloser {
- void operator()(UBreakIterator* p) { (void)ubrk_close(p); }
- };
+namespace {
+template <typename T,typename P,P* p> using resource = std::unique_ptr<T, SkFunctionWrapper<P, p>>;
+using ICUBrk = resource<UBreakIterator, decltype(ubrk_close) , ubrk_close >;
+using ICUUText = resource<UText , decltype(utext_close) , utext_close >;
+}
+
+std::vector<bool> GetUtf8WordBoundaries(const char* begin, size_t byteCount, const char* locale) {
std::vector<bool> result;
if (0 == byteCount) {
return result;
}
result.resize(byteCount);
- UText utf8UText = UTEXT_INITIALIZER;
- UErrorCode errorCode = U_ZERO_ERROR;
- (void)utext_openUTF8(&utf8UText, begin, byteCount, &errorCode);
- std::unique_ptr<UText, UTextCloser> autoclose1(&utf8UText);
- if (U_FAILURE(errorCode)) {
+ UErrorCode status = U_ZERO_ERROR;
+ UText sUtf8UText = UTEXT_INITIALIZER;
+ ICUUText utf8UText(utext_openUTF8(&sUtf8UText, begin, byteCount, &status));
+ if (U_FAILURE(status)) {
+ SkDebugf("Could not create utf8UText: %s", u_errorName(status));
return result;
}
- UBreakIterator* iter = ubrk_open(kIteratorType, locale, nullptr, 0, &errorCode);
- std::unique_ptr<UBreakIterator, UBreakCloser> autoclose2(iter);
- if (U_FAILURE(errorCode)) {
+
+ ICUBrk wordBreakIterator(ubrk_open(UBRK_WORD, locale, nullptr, 0, &status));
+ if (!wordBreakIterator || U_FAILURE(status)) {
+ SkDEBUGF("Could not create line break iterator: %s", u_errorName(status));
return result;
}
- ubrk_setUText(iter, &utf8UText, &errorCode);
- if (U_FAILURE(errorCode)) {
+
+ ubrk_setUText(&*wordBreakIterator, utf8UText.get(), &status);
+ if (U_FAILURE(status)) {
+ SkDebugf("Could not setText on break iterator: %s", u_errorName(status));
return result;
}
- int pos = ubrk_first(iter);
- while (pos != icu::BreakIterator::DONE) {
- if ((unsigned)pos < (unsigned)byteCount) {
+
+ int32_t pos = ubrk_first(&*wordBreakIterator);
+ while (pos != UBRK_DONE) {
+ if ((size_t)pos < byteCount) {
result[pos] = true;
}
- pos = ubrk_next(iter);
+ pos = ubrk_next(&*wordBreakIterator);
}
return result;
}
diff --git a/chromium/third_party/skia/modules/skresources/include/SkResources.h b/chromium/third_party/skia/modules/skresources/include/SkResources.h
index 3a5769d900f..c5bdb81dfa7 100644
--- a/chromium/third_party/skia/modules/skresources/include/SkResources.h
+++ b/chromium/third_party/skia/modules/skresources/include/SkResources.h
@@ -11,6 +11,7 @@
#include "include/core/SkData.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkString.h"
+#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/private/SkMutex.h"
#include "include/private/SkTHash.h"
@@ -96,6 +97,8 @@ public:
}
/**
+ * DEPRECATED: implement loadTypeface() instead.
+ *
* Load an external font and return as SkData.
*
* @param name font name ("fName" Lottie property)
@@ -112,6 +115,17 @@ public:
const char[] /* url */) const {
return nullptr;
}
+
+ /**
+ * Load an external font and return as SkTypeface.
+ *
+ * @param name font name
+ * @param url web font URL
+ */
+ virtual sk_sp<SkTypeface> loadTypeface(const char[] /* name */,
+ const char[] /* url */) const {
+ return nullptr;
+ }
};
class FileResourceProvider final : public ResourceProvider {
@@ -137,7 +151,7 @@ protected:
sk_sp<SkData> load(const char[], const char[]) const override;
sk_sp<ImageAsset> loadImageAsset(const char[], const char[], const char[]) const override;
- sk_sp<SkData> loadFont(const char[], const char[]) const override;
+ sk_sp<SkTypeface> loadTypeface(const char[], const char[]) const override;
private:
const sk_sp<ResourceProvider> fProxy;
diff --git a/chromium/third_party/skia/modules/skresources/src/SkResources.cpp b/chromium/third_party/skia/modules/skresources/src/SkResources.cpp
index 1d3e710c3f9..8934fd40e25 100644
--- a/chromium/third_party/skia/modules/skresources/src/SkResources.cpp
+++ b/chromium/third_party/skia/modules/skresources/src/SkResources.cpp
@@ -196,8 +196,9 @@ sk_sp<ImageAsset> ResourceProviderProxyBase::loadImageAsset(const char rpath[],
: nullptr;
}
-sk_sp<SkData> ResourceProviderProxyBase::loadFont(const char name[], const char url[]) const {
- return fProxy ? fProxy->loadFont(name, url)
+sk_sp<SkTypeface> ResourceProviderProxyBase::loadTypeface(const char name[],
+ const char url[]) const {
+ return fProxy ? fProxy->loadTypeface(name, url)
: nullptr;
}
diff --git a/chromium/third_party/skia/modules/sksg/include/SkSGGroup.h b/chromium/third_party/skia/modules/sksg/include/SkSGGroup.h
index 81dd797af5c..085f7a66abd 100644
--- a/chromium/third_party/skia/modules/sksg/include/SkSGGroup.h
+++ b/chromium/third_party/skia/modules/sksg/include/SkSGGroup.h
@@ -35,6 +35,7 @@ public:
void clear();
protected:
+ Group();
explicit Group(std::vector<sk_sp<RenderNode>>);
~Group() override;
diff --git a/chromium/third_party/skia/modules/sksg/include/SkSGTransform.h b/chromium/third_party/skia/modules/sksg/include/SkSGTransform.h
index 1c7c17ca8ef..3c1c013086f 100644
--- a/chromium/third_party/skia/modules/sksg/include/SkSGTransform.h
+++ b/chromium/third_party/skia/modules/sksg/include/SkSGTransform.h
@@ -49,7 +49,7 @@ private:
*
* auto m33 = Matrix<SkMatrix>::Make(SkMatrix::I());
* ...
- * m33->setMatrix(SkMatrix::MakeTrans(10, 10));
+ * m33->setMatrix(SkMatrix::Translate(10, 10));
*
*/
template <typename T>
diff --git a/chromium/third_party/skia/modules/sksg/src/SkSGGroup.cpp b/chromium/third_party/skia/modules/sksg/src/SkSGGroup.cpp
index 829c5ae50fc..f60c6ffbca9 100644
--- a/chromium/third_party/skia/modules/sksg/src/SkSGGroup.cpp
+++ b/chromium/third_party/skia/modules/sksg/src/SkSGGroup.cpp
@@ -13,6 +13,8 @@
namespace sksg {
+Group::Group() = default;
+
Group::Group(std::vector<sk_sp<RenderNode>> children)
: fChildren(std::move(children)) {
for (const auto& child : fChildren) {
diff --git a/chromium/third_party/skia/modules/skshaper/BUILD.gn b/chromium/third_party/skia/modules/skshaper/BUILD.gn
index 9673c374d1d..e595d859492 100644
--- a/chromium/third_party/skia/modules/skshaper/BUILD.gn
+++ b/chromium/third_party/skia/modules/skshaper/BUILD.gn
@@ -16,7 +16,10 @@ if (skia_enable_skshaper) {
if (is_component_build) {
defines += [ "SKSHAPER_DLL" ]
}
- if (skia_use_icu) {
+ if (skia_use_fonthost_mac) {
+ defines += [ "SK_SHAPER_CORETEXT_AVAILABLE" ]
+ }
+ if (skia_use_icu && skia_use_harfbuzz) {
defines += [ "SK_SHAPER_HARFBUZZ_AVAILABLE" ]
}
}
@@ -29,6 +32,9 @@ if (skia_enable_skshaper) {
deps = [ "../..:skia" ]
defines = [ "SKSHAPER_IMPLEMENTATION=1" ]
sources = skia_shaper_primitive_sources
+ if (skia_use_fonthost_mac) {
+ sources += skia_shaper_coretext_sources
+ }
if (skia_use_icu && skia_use_harfbuzz) {
sources += skia_shaper_harfbuzz_sources
deps += [
@@ -36,7 +42,10 @@ if (skia_enable_skshaper) {
"//third_party/icu",
]
}
- configs += [ "../../:skia_private" ]
+ configs += [
+ "../../:skia_private",
+ "../../third_party/icu/config:no_cxx",
+ ]
}
} else {
group("skshaper") {
diff --git a/chromium/third_party/skia/modules/skshaper/include/SkShaper.h b/chromium/third_party/skia/modules/skshaper/include/SkShaper.h
index 104872cd21c..c0864af5ab4 100644
--- a/chromium/third_party/skia/modules/skshaper/include/SkShaper.h
+++ b/chromium/third_party/skia/modules/skshaper/include/SkShaper.h
@@ -54,8 +54,9 @@ public:
static std::unique_ptr<SkShaper> MakeShapeThenWrap(sk_sp<SkFontMgr> = nullptr);
static std::unique_ptr<SkShaper> MakeShapeDontWrapOrReorder(sk_sp<SkFontMgr> = nullptr);
#endif
- // Returns nullptr if not supported
+ #ifdef SK_SHAPER_CORETEXT_AVAILABLE
static std::unique_ptr<SkShaper> MakeCoreText();
+ #endif
static std::unique_ptr<SkShaper> Make(sk_sp<SkFontMgr> = nullptr);
diff --git a/chromium/third_party/skia/modules/skshaper/skshaper.gni b/chromium/third_party/skia/modules/skshaper/skshaper.gni
index ba3f09dd36f..425cf3f4b96 100644
--- a/chromium/third_party/skia/modules/skshaper/skshaper.gni
+++ b/chromium/third_party/skia/modules/skshaper/skshaper.gni
@@ -11,7 +11,7 @@ skia_shaper_public = [ "$_include/SkShaper.h" ]
skia_shaper_primitive_sources = [
"$_src/SkShaper.cpp",
- "$_src/SkShaper_coretext.cpp",
"$_src/SkShaper_primitive.cpp",
]
skia_shaper_harfbuzz_sources = [ "$_src/SkShaper_harfbuzz.cpp" ]
+skia_shaper_coretext_sources = [ "$_src/SkShaper_coretext.cpp" ]
diff --git a/chromium/third_party/skia/modules/skshaper/src/SkShaper_coretext.cpp b/chromium/third_party/skia/modules/skshaper/src/SkShaper_coretext.cpp
index 6252795952f..50689ccc349 100644
--- a/chromium/third_party/skia/modules/skshaper/src/SkShaper_coretext.cpp
+++ b/chromium/third_party/skia/modules/skshaper/src/SkShaper_coretext.cpp
@@ -7,8 +7,6 @@
#include "modules/skshaper/include/SkShaper.h"
-#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
-
#ifdef SK_BUILD_FOR_MAC
#import <ApplicationServices/ApplicationServices.h>
#endif
@@ -22,6 +20,8 @@
#include "include/ports/SkTypeface_mac.h"
#include "src/core/SkArenaAlloc.h"
+#include "src/utils/mac/SkCGBase.h"
+#include "src/utils/mac/SkUniqueCFRef.h"
#include <vector>
@@ -96,15 +96,6 @@ void SkShaper_CoreText::shape(const char* utf8, size_t utf8Bytes,
width, handler);
}
-template <typename T> class AutoCF {
- T fObj;
-public:
- AutoCF(T obj) : fObj(obj) {}
- ~AutoCF() { CFRelease(fObj); }
-
- T get() const { return fObj; }
-};
-
// CTFramesetter/CTFrame can do this, but require version 10.14
class LineBreakIter {
CTTypesetterRef fTypesetter;
@@ -128,28 +119,16 @@ public:
};
static void dict_add_double(CFMutableDictionaryRef d, const void* name, double value) {
- AutoCF<CFNumberRef> number = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value);
+ SkUniqueCFRef<CFNumberRef> number(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
CFDictionaryAddValue(d, name, number.get());
}
-static void dump(CFDictionaryRef d) {
- CFIndex count = CFDictionaryGetCount(d);
- std::vector<const void*> keys(count);
- std::vector<const void*> vals(count);
-
- CFDictionaryGetKeysAndValues(d, keys.data(), vals.data());
-
- for (CFIndex i = 0; i < count; ++i) {
- CFStringRef kstr = (CFStringRef)keys[i];
- const char* ckstr = CFStringGetCStringPtr(kstr, kCFStringEncodingUTF8);
- SkDebugf("dict[%d] %s %p\n", i, ckstr, vals[i]);
- }
-}
-
-static CTFontRef create_ctfont_from_font(const SkFont& font) {
+static SkUniqueCFRef<CTFontRef> create_ctfont_from_font(const SkFont& font) {
auto typeface = font.getTypefaceOrDefault();
auto ctfont = SkTypeface_GetCTFontRef(typeface);
- return CTFontCreateCopyWithAttributes(ctfont, font.getSize(), nullptr, nullptr);
+ return SkUniqueCFRef<CTFontRef>(
+ CTFontCreateCopyWithAttributes(ctfont, font.getSize(), nullptr, nullptr));
}
static SkFont run_to_font(CTRunRef run, const SkFont& orig) {
@@ -157,7 +136,7 @@ static SkFont run_to_font(CTRunRef run, const SkFont& orig) {
CTFontRef ct = (CTFontRef)CFDictionaryGetValue(attr, kCTFontAttributeName);
if (!ct) {
SkDebugf("no ctfont in Run Attributes\n");
- dump(attr);
+ CFShow(attr);
return orig;
}
// Do I need to add a local cache, or allow the caller to manage this lookup?
@@ -174,25 +153,16 @@ void SkShaper_CoreText::shape(const char* utf8, size_t utf8Bytes,
bool /* leftToRight */,
SkScalar width,
RunHandler* handler) const {
- auto cgfloat_to_scalar = [](CGFloat x) {
- SkScalar s;
- if (sizeof(CGFloat) == sizeof(double)) {
- s = SkDoubleToScalar(x);
- } else {
- s = x;
- }
- return s;
- };
-
- AutoCF<CFStringRef> textString = CFStringCreateWithBytes(nullptr, (const uint8_t*)utf8, utf8Bytes,
- kCFStringEncodingUTF8, false);
+ SkUniqueCFRef<CFStringRef> textString(
+ CFStringCreateWithBytes(kCFAllocatorDefault, (const uint8_t*)utf8, utf8Bytes,
+ kCFStringEncodingUTF8, false));
- AutoCF<CTFontRef> ctfont = create_ctfont_from_font(font);
+ SkUniqueCFRef<CTFontRef> ctfont = create_ctfont_from_font(font);
- AutoCF<CFMutableDictionaryRef> attr =
+ SkUniqueCFRef<CFMutableDictionaryRef> attr(
CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
+ &kCFTypeDictionaryValueCallBacks));
CFDictionaryAddValue(attr.get(), kCTFontAttributeName, ctfont.get());
if (false) {
// trying to see what these affect
@@ -200,11 +170,11 @@ void SkShaper_CoreText::shape(const char* utf8, size_t utf8Bytes,
dict_add_double(attr.get(), kCTKernAttributeName, 0.0);
}
- AutoCF<CFAttributedStringRef> attrString =
- CFAttributedStringCreate(nullptr, textString.get(), attr.get());
+ SkUniqueCFRef<CFAttributedStringRef> attrString(
+ CFAttributedStringCreate(kCFAllocatorDefault, textString.get(), attr.get()));
- AutoCF<CTTypesetterRef> typesetter =
- CTTypesetterCreateWithAttributedStringAndOptions(attrString.get(), nullptr);
+ SkUniqueCFRef<CTTypesetterRef> typesetter(
+ CTTypesetterCreateWithAttributedString(attrString.get()));
SkSTArenaAlloc<4096> arena;
@@ -272,7 +242,7 @@ void SkShaper_CoreText::shape(const char* utf8, size_t utf8Bytes,
for (CFIndex k = 0; k < runGlyphs; ++k) {
buffer.positions[k] = {
- buffer.point.fX + cgfloat_to_scalar(positions[k].x),
+ buffer.point.fX + SkScalarFromCGFloat(positions[k].x),
buffer.point.fY,
};
if (buffer.offsets) {
@@ -288,9 +258,3 @@ void SkShaper_CoreText::shape(const char* utf8, size_t utf8Bytes,
handler->commitLine();
}
}
-
-#else
-std::unique_ptr<SkShaper> SkShaper::MakeCoreText() {
- return nullptr;
-}
-#endif
diff --git a/chromium/third_party/skia/modules/skshaper/src/SkShaper_harfbuzz.cpp b/chromium/third_party/skia/modules/skshaper/src/SkShaper_harfbuzz.cpp
index 29d9fe92974..c42575d6356 100644
--- a/chromium/third_party/skia/modules/skshaper/src/SkShaper_harfbuzz.cpp
+++ b/chromium/third_party/skia/modules/skshaper/src/SkShaper_harfbuzz.cpp
@@ -20,11 +20,13 @@
#include "include/core/SkTypes.h"
#include "include/private/SkBitmaskEnum.h"
#include "include/private/SkMalloc.h"
+#include "include/private/SkMutex.h"
#include "include/private/SkTArray.h"
#include "include/private/SkTFitsIn.h"
#include "include/private/SkTemplates.h"
#include "include/private/SkTo.h"
#include "modules/skshaper/include/SkShaper.h"
+#include "src/core/SkLRUCache.h"
#include "src/core/SkSpan.h"
#include "src/core/SkTDPQueue.h"
#include "src/utils/SkUTF.h"
@@ -73,25 +75,6 @@ using ICUBiDi = resource<UBiDi , decltype(ubidi_close) , ubidi_clo
using ICUBrk = resource<UBreakIterator, decltype(ubrk_close) , ubrk_close >;
using ICUUText = resource<UText , decltype(utext_close) , utext_close >;
-HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
- size_t size = asset->getLength();
- HBBlob blob;
- if (const void* base = asset->getMemoryBase()) {
- blob.reset(hb_blob_create((char*)base, SkToUInt(size),
- HB_MEMORY_MODE_READONLY, asset.release(),
- [](void* p) { delete (SkStreamAsset*)p; }));
- } else {
- // SkDebugf("Extra SkStreamAsset copy\n");
- void* ptr = size ? sk_malloc_throw(size) : nullptr;
- asset->read(ptr, size);
- blob.reset(hb_blob_create((char*)ptr, SkToUInt(size),
- HB_MEMORY_MODE_READONLY, ptr, sk_free));
- }
- SkASSERT(blob);
- hb_blob_make_immutable(blob.get());
- return blob;
-}
-
hb_position_t skhb_position(SkScalar value) {
// Treat HarfBuzz hb_position_t as 16.16 fixed-point.
constexpr int kHbPosition1 = 1 << 16;
@@ -266,31 +249,65 @@ hb_blob_t* skhb_get_table(hb_face_t* face, hb_tag_t tag, void* user_data) {
}
SkData* rawData = data.release();
return hb_blob_create(reinterpret_cast<char*>(rawData->writable_data()), rawData->size(),
- HB_MEMORY_MODE_WRITABLE, rawData, [](void* ctx) {
+ HB_MEMORY_MODE_READONLY, rawData, [](void* ctx) {
SkSafeUnref(((SkData*)ctx));
});
}
-HBFont create_hb_font(const SkFont& font) {
- SkASSERT(font.getTypeface());
+HBBlob stream_to_blob(std::unique_ptr<SkStreamAsset> asset) {
+ size_t size = asset->getLength();
+ HBBlob blob;
+ if (const void* base = asset->getMemoryBase()) {
+ blob.reset(hb_blob_create((char*)base, SkToUInt(size),
+ HB_MEMORY_MODE_READONLY, asset.release(),
+ [](void* p) { delete (SkStreamAsset*)p; }));
+ } else {
+ // SkDebugf("Extra SkStreamAsset copy\n");
+ void* ptr = size ? sk_malloc_throw(size) : nullptr;
+ asset->read(ptr, size);
+ blob.reset(hb_blob_create((char*)ptr, SkToUInt(size),
+ HB_MEMORY_MODE_READONLY, ptr, sk_free));
+ }
+ SkASSERT(blob);
+ hb_blob_make_immutable(blob.get());
+ return blob;
+}
+
+SkDEBUGCODE(static hb_user_data_key_t gDataIdKey;)
+
+HBFace create_hb_face(const SkTypeface& typeface) {
int index;
- std::unique_ptr<SkStreamAsset> typefaceAsset = font.getTypeface()->openStream(&index);
+ std::unique_ptr<SkStreamAsset> typefaceAsset = typeface.openStream(&index);
HBFace face;
- if (!typefaceAsset) {
+ if (typefaceAsset && typefaceAsset->getMemoryBase()) {
+ HBBlob blob(stream_to_blob(std::move(typefaceAsset)));
+ face.reset(hb_face_create(blob.get(), (unsigned)index));
+ } else {
face.reset(hb_face_create_for_tables(
skhb_get_table,
- reinterpret_cast<void *>(font.refTypeface().release()),
+ const_cast<SkTypeface*>(SkRef(&typeface)),
[](void* user_data){ SkSafeUnref(reinterpret_cast<SkTypeface*>(user_data)); }));
- } else {
- HBBlob blob(stream_to_blob(std::move(typefaceAsset)));
- face.reset(hb_face_create(blob.get(), (unsigned)index));
}
SkASSERT(face);
if (!face) {
return nullptr;
}
hb_face_set_index(face.get(), (unsigned)index);
- hb_face_set_upem(face.get(), font.getTypeface()->getUnitsPerEm());
+ hb_face_set_upem(face.get(), typeface.getUnitsPerEm());
+
+ SkDEBUGCODE(
+ hb_face_set_user_data(face.get(), &gDataIdKey, const_cast<SkTypeface*>(&typeface),
+ nullptr, false);
+ )
+
+ return face;
+}
+
+HBFont create_hb_font(const SkFont& font, const HBFace& face) {
+ SkDEBUGCODE(
+ void* dataId = hb_face_get_user_data(face.get(), &gDataIdKey);
+ SkASSERT(dataId == font.getTypeface());
+ )
HBFont otFont(hb_font_create(face.get()));
SkASSERT(otFont);
@@ -652,6 +669,7 @@ protected:
private:
const sk_sp<SkFontMgr> fFontMgr;
HBBuffer fBuffer;
+ hb_language_t fUndefinedLanguage;
void shape(const char* utf8, size_t utf8Bytes,
const SkFont&,
@@ -777,6 +795,7 @@ ShaperHarfBuzz::ShaperHarfBuzz(HBBuffer buffer, ICUBrk line, ICUBrk grapheme,
, fGraphemeBreakIterator(std::move(grapheme))
, fFontMgr(std::move(fontmgr))
, fBuffer(std::move(buffer))
+ , fUndefinedLanguage(hb_language_from_string("und", -1))
{}
void ShaperHarfBuzz::shape(const char* utf8, size_t utf8Bytes,
@@ -1315,11 +1334,34 @@ ShapedRun ShaperHarfBuzz::shape(char const * const utf8,
hb_direction_t direction = is_LTR(bidi.currentLevel()) ? HB_DIRECTION_LTR:HB_DIRECTION_RTL;
hb_buffer_set_direction(buffer, direction);
hb_buffer_set_script(buffer, hb_script_from_iso15924_tag((hb_tag_t)script.currentScript()));
- hb_buffer_set_language(buffer, hb_language_from_string(language.currentLanguage(), -1));
+ // Buffers with HB_LANGUAGE_INVALID race since hb_language_get_default is not thread safe.
+ // The user must provide a language, but may provide data hb_language_from_string cannot use.
+ // Use "und" for the undefined language in this case (RFC5646 4.1 5).
+ hb_language_t hbLanguage = hb_language_from_string(language.currentLanguage(), -1);
+ if (hbLanguage == HB_LANGUAGE_INVALID) {
+ hbLanguage = fUndefinedLanguage;
+ }
+ hb_buffer_set_language(buffer, hbLanguage);
hb_buffer_guess_segment_properties(buffer);
- // TODO: how to cache hbface (typeface) / hbfont (font)
- HBFont hbFont(create_hb_font(font.currentFont()));
+ // TODO: better cache HBFace (data) / hbfont (typeface)
+ // An HBFace is expensive (it sanitizes the bits).
+ // An HBFont is fairly inexpensive.
+ // An HBFace is actually tied to the data, not the typeface.
+ // The size of 100 here is completely arbitrary and used to match libtxt.
+ static SkLRUCache<SkFontID, HBFace> gHBFaceCache(100);
+ static SkMutex gHBFaceCacheMutex;
+ HBFont hbFont;
+ {
+ SkAutoMutexExclusive lock(gHBFaceCacheMutex);
+ SkFontID dataId = font.currentFont().getTypeface()->uniqueID();
+ HBFace* hbFaceCached = gHBFaceCache.find(dataId);
+ if (!hbFaceCached) {
+ HBFace hbFace(create_hb_face(*font.currentFont().getTypeface()));
+ hbFaceCached = gHBFaceCache.insert(dataId, std::move(hbFace));
+ }
+ hbFont = create_hb_font(font.currentFont(), *hbFaceCached);
+ }
if (!hbFont) {
return run;
}
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/CMakeLists.txt b/chromium/third_party/skia/platform_tools/android/apps/arcore/CMakeLists.txt
deleted file mode 100644
index 6bfe1b7bef6..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/CMakeLists.txt
+++ /dev/null
@@ -1,76 +0,0 @@
-# Copyright (C) 2018 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-# Sets the minimum version of CMake required to build the native library.
-cmake_minimum_required(VERSION 3.4.1)
-
-# Import the ARCore library.
-add_library(arcore SHARED IMPORTED)
-set_target_properties(arcore PROPERTIES IMPORTED_LOCATION
- "${ARCORE_LIBPATH}/${ANDROID_ABI}/libarcore_sdk_c.so")
-
-add_library(sk_skia SHARED IMPORTED)
-set_target_properties(sk_skia PROPERTIES IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}/libarcore.so")
-
-# This is the main app library.
-add_library(hello_ar_native SHARED
- "src/main/cpp/hello_ar_application.cc"
- "src/main/cpp/background_renderer.cc"
- "src/main/cpp/jni_interface.cc"
- "src/main/cpp/plane_renderer.cc"
- "src/main/cpp/point_cloud_renderer.cc"
- "src/main/cpp/util.cc"
- "src/main/cpp/pending_anchor.cc"
- "src/main/cpp/anchor_wrapper.cc"
-
- "src/main/cpp/SkArCamera.cpp")
-
-target_include_directories(hello_ar_native PRIVATE
- #BASIC AR NATIVE CODE
- "src/main/cpp"
-
- #ARCORE LIBRARY
- "${ARCORE_INCLUDE}"
-
- #GLM
- "${ANDROID_NDK}/sources/third_party/vulkan/src/libs/glm"
-
- #SKIA INCLUDE DIRECTORIES
- "${SKIA_INCLUDE_PATH}/../modules/skshaper/include"
- "${SKIA_INCLUDE_PATH}/../modules/skottie/include"
- "${SKIA_INCLUDE_PATH}/../tools"
- "${SKIA_INCLUDE_PATH}/../gm"
- "${SKIA_INCLUDE_PATH}/core"
- "${SKIA_INCLUDE_PATH}/config"
- "${SKIA_INCLUDE_PATH}/gpu"
- "${SKIA_INCLUDE_PATH}/android"
- "${SKIA_INCLUDE_PATH}/atlastext"
- "${SKIA_INCLUDE_PATH}/c"
- "${SKIA_INCLUDE_PATH}/codec"
- "${SKIA_INCLUDE_PATH}/effects"
- "${SKIA_INCLUDE_PATH}/encode"
- "${SKIA_INCLUDE_PATH}/pathops"
- "${SKIA_INCLUDE_PATH}/ports"
- "${SKIA_INCLUDE_PATH}/private"
- "${SKIA_INCLUDE_PATH}/svg"
- "${SKIA_INCLUDE_PATH}/utils"
- "${SKIA_INCLUDE_PATH}/views")
-
-target_link_libraries(hello_ar_native
- android
- log
- GLESv2
- arcore
- sk_skia)
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/build.gradle b/chromium/third_party/skia/platform_tools/android/apps/arcore/build.gradle
deleted file mode 100644
index 0e82ab88312..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/build.gradle
+++ /dev/null
@@ -1,92 +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.
- */
-apply plugin: 'com.android.application'
-
-/*
-The arcore aar library contains the native shared libraries. These are
-extracted before building to a temporary directory.
- */
-def arcore_libpath = "${buildDir}/arcore-native"
-
-// Create a configuration to mark which aars to extract .so files from
-configurations { natives }
-
-android {
- sourceSets.main.jni.srcDirs = [] //disable automatic ndk-build call
- sourceSets.main.jniLibs.srcDir "src/main/libs"
- productFlavors { arm64 {} }
-
- setupSkiaLibraryBuild(project, applicationVariants, "libarcore")
-
- compileSdkVersion 27
- defaultConfig {
- applicationId "org.skia.viewer"
- // 24 is the minimum since ARCore only works with 24 and higher.
- minSdkVersion 24
- targetSdkVersion 27
- versionCode 1
- versionName "1.0"
-
- externalNativeBuild {
- cmake {
- cppFlags "-std=c++11", "-Wall"
- arguments "-DANDROID_STL=c++_static",
- "-DARCORE_LIBPATH=${arcore_libpath}/jni",
- "-DARCORE_INCLUDE=${project.rootDir}/../../libraries/include",
- "-DSKIA_INCLUDE_PATH=${project.rootDir}/../../../include"
- }
- }
- ndk {
- abiFilters "arm64-v8a"
- }
- }
- flavorDimensions "base"
- externalNativeBuild {
- cmake {
- path "CMakeLists.txt"
- }
- }
-
-}
-
-dependencies {
- // ARCore library
- implementation 'com.google.ar:core:1.2.0'
- natives 'com.google.ar:core:1.2.0'
-
- implementation 'com.android.support:appcompat-v7:27.0.2'
- implementation 'com.android.support:design:27.0.2'
-}
-
-// Extracts the shared libraries from aars in the natives configuration.
-// This is done so that NDK builds can access these libraries.
-task extractNativeLibraries() {
- doFirst {
- configurations.natives.files.each { f ->
- copy {
- from zipTree(f)
- into arcore_libpath
- include "jni/**/*"
- }
- }
- }
-}
-
-
-tasks.whenTaskAdded {
- task-> if (task.name.contains("external") && !task.name.contains("Clean")) {
- task.dependsOn(extractNativeLibraries)
-
- //make sure skia lib is built and copied in the correct directory before building arcore
- tasks.whenTaskAdded {
- t-> if (t.name.contains("CopySkiaLib")) {
- task.dependsOn(t)
- }
- }
- }
-}
-
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/AndroidManifest.xml b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/AndroidManifest.xml
deleted file mode 100644
index 975dc2592db..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.skia.arcore">
-
- <uses-permission android:name="android.permission.CAMERA"/>
- <!-- This tag indicates that this application requires ARCore. This results in the application
- only being visible in the Google Play Store on devices that support ARCore. -->
- <uses-feature android:name="android.hardware.camera.ar" android:required="true"/>
- <uses-feature android:glEsVersion="0x00020000" android:required="true" />
-
- <application
- android:allowBackup="true"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/Theme.AppCompat.Light.NoActionBar"
- android:usesCleartextTraffic="false">
- <!-- This tag indicates that this application requires ARCore. This results in the Google Play
- Store downloading and installing ARCore along with the application. -->
- <meta-data android:name="com.google.ar.core" android:value="required" />
-
- <activity
- android:name=".HelloArActivity"
- android:label="@string/app_name"
- android:configChanges="orientation|screenSize"
- android:exported="true"
- android:theme="@style/Theme.AppCompat.DayNight.NoActionBar"
-
- android:screenOrientation="locked">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- </application>
-</manifest>
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/assets/models/trigrid.png b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/assets/models/trigrid.png
deleted file mode 100644
index d85eedf72cb..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/assets/models/trigrid.png
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/SkArCamera.cpp b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/SkArCamera.cpp
deleted file mode 100644
index f773582aada..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/SkArCamera.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2018 Google LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <arcore_c_api.h>
-#include "platform_tools/android/apps/arcore/src/main/cpp/SkArCamera.h"
-#include "SkArUtil.h"
-
-std::unique_ptr<SkArCamera> SkArCamera::Make(SkArSession* session, SkArFrame* frame) {
- return std::unique_ptr<SkArCamera>(new SkArCamera(session, frame));
-}
-
-SkArCamera::~SkArCamera() {
- ArCamera_release(fArCamera);
-}
-
-SkArCamera::SkArCamera(SkArSession* session, SkArFrame* frame) : fArCamera(nullptr) {
- ArFrame_acquireCamera(session->getArSession(), frame->getArFrame(), &fArCamera);
-}
-
-void SkArCamera::getViewMatrix(const SkArSession* session, float outColMajor[16]) {
- ArCamera_getViewMatrix(session->getArSession(), fArCamera, outColMajor);
-}
-
-void SkArCamera::getProjectionMatrix(const SkArSession* session, float nearClip,
- float farClip, float outColMajor[16]) {
- ArCamera_getProjectionMatrix(session->getArSession(), fArCamera, nearClip, farClip,
- outColMajor);
-}
-
-SkArTrackingState SkArCamera::getTrackingState(const SkArSession* session) {
- ArTrackingState arTrackingState;
- ArCamera_getTrackingState(session->getArSession(), fArCamera, &arTrackingState);
- return SkArUtil::MakeSkArTrackingState(arTrackingState);
-}
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/SkArCamera.h b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/SkArCamera.h
deleted file mode 100644
index 0cf8f3c449e..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/SkArCamera.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2018 Google LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkArCamera_DEFINED
-#define SkArCamera_DEFINED
-
-#include <memory>
-#include "SkArTrackingState.h"
-
-class ArCamera;
-class SkArFrame;
-class SkArSession;
-
-/**
- * Provides information about the camera that is used to capture images. Such information
- * includes projection matrices, pose of camera...
- */
-
-class SkArCamera {
-
-public:
- /**
- * Factory method used to construct an SkArCamera from the current frame, using the current
- * session
- * @param session raw pointer to the current SkArSession
- * @param frame raw pointer to the current SkArFrame
- * @return unique pointer to an SkArCamera. Never nullptr
- */
- static std::unique_ptr<SkArCamera> Make(SkArSession* session, SkArFrame* frame);
-
- ~SkArCamera();
-
- /**
- * Fills outColMajor with the values of the camera's current View matrix in column-major order
- * @param session current SkArSession
- * @param outColMajor 16-float array that will contain the View matrix content
- */
- void getViewMatrix(const SkArSession* session, float outColMajor[16]);
-
- /**
- * Fills outColMajor with the values of the camera's current Projection matrix in
- * column-major order
- * @param session current SkArSession
- * @param nearClip wanted near clip value for the camera
- * @param farClip wanted far clip value for the camera
- * @param outColMajor 16-float array that will contain the Projection matrix content
- */
- void getProjectionMatrix(const SkArSession* session, float nearClip, float farClip,
- float outColMajor[16]);
-
- /**
- * Used to check the current SkArTrackingState of the camera
- * @param session current SkArSession
- * @return tracking state of the SkArCamera described by the SkArTrackingState enum
- */
- SkArTrackingState getTrackingState(const SkArSession* session);
-
-private:
- SkArCamera(SkArSession* session, SkArFrame* frame);
-
- // This is a raw pointer. Its lifetime matches that of this class (SkArCamera)
- ArCamera* fArCamera;
-};
-#endif // SkArCamera_DEFINED
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/anchor_wrapper.cc b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/anchor_wrapper.cc
deleted file mode 100644
index 1ef6fb8dbd0..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/anchor_wrapper.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2018 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "platform_tools/android/apps/arcore/src/main/cpp/hello_ar_application.h"
-#include "arcore_c_api.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/anchor_wrapper.h"
-
-namespace hello_ar {
-
- AnchorWrapper::AnchorWrapper(ArAnchor *anchor) : anchor(anchor) {}
-
- const ArAnchor* AnchorWrapper::GetArAnchor() {
- return anchor;
- }
- DrawableType AnchorWrapper::GetDrawableType() {
- return drawableType;
- }
-
- void AnchorWrapper::SetArAnchor(ArAnchor* anchor) {
- this->anchor = anchor;
- }
- void AnchorWrapper::SetDrawableType(DrawableType drawableType) {
- this->drawableType = drawableType;
- }
-
-
-
-} // namespace hello_ar
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/anchor_wrapper.h b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/anchor_wrapper.h
deleted file mode 100644
index ff05e57010d..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/anchor_wrapper.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2018 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef C_ARCORE_HELLO_AR_ANCHOR_WRAPPER_H_
-#define C_ARCORE_HELLO_AR_ANCHOR_WRAPPER_H_
-#include "arcore_c_api.h"
-
-namespace hello_ar {
- enum DrawableType {
- TEXT = 0, CIRCLE = 1, RECT = 2
- };
-
- class AnchorWrapper {
- public:
- AnchorWrapper(ArAnchor* anchor);
-
- const ArAnchor* GetArAnchor();
- DrawableType GetDrawableType();
- bool GetInEditMode();
-
- void SetArAnchor(ArAnchor* anchor);
- void SetDrawableType(DrawableType drawableType);
- void SetInEditMode(bool inEditMode);
-
- private:
- ArAnchor* anchor;
- DrawableType drawableType;
- bool inEditMode = false;
- };
-} // namespace hello_ar
-
-#endif
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/background_renderer.cc b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/background_renderer.cc
deleted file mode 100644
index c701dbd9010..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/background_renderer.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This modules handles drawing the passthrough camera image into the OpenGL
-// scene.
-
-#include <type_traits>
-
-#include "platform_tools/android/apps/arcore/src/main/cpp/background_renderer.h"
-
-namespace hello_ar {
- namespace {
-// Positions of the quad vertices in clip space (X, Y, Z).
- const GLfloat kVertices[] = {
- -1.0f, -1.0f, 0.0f, +1.0f, -1.0f, 0.0f,
- -1.0f, +1.0f, 0.0f, +1.0f, +1.0f, 0.0f,
- };
-
-// UVs of the quad vertices (S, T)
- const GLfloat kUvs[] = {
- 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
- };
-
- constexpr char kVertexShader[] = R"(
- attribute vec4 vertex;
- attribute vec2 textureCoords;
- varying vec2 v_textureCoords;
- void main() {
- v_textureCoords = textureCoords;
- gl_Position = vertex;
- })";
-
- constexpr char kFragmentShader[] = R"(
- #extension GL_OES_EGL_image_external : require
- precision mediump float;
- uniform samplerExternalOES texture;
- varying vec2 v_textureCoords;
- void main() {
- gl_FragColor = texture2D(texture, v_textureCoords);
- })";
-
- } // namespace
-
- void BackgroundRenderer::InitializeGlContent() {
- shader_program_ = util::CreateProgram(kVertexShader, kFragmentShader);
-
- if (!shader_program_) {
- LOGE("Could not create program.");
- }
-
- glGenTextures(1, &texture_id_);
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id_);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- uniform_texture_ = glGetUniformLocation(shader_program_, "texture");
- attribute_vertices_ = glGetAttribLocation(shader_program_, "vertex");
- attribute_uvs_ = glGetAttribLocation(shader_program_, "textureCoords");
- }
-
- void BackgroundRenderer::Draw(const ArSession *session, const ArFrame *frame) {
- static_assert(std::extent<decltype(kUvs)>::value == kNumVertices * 2,
- "Incorrect kUvs length");
- static_assert(std::extent<decltype(kVertices)>::value == kNumVertices * 3,
- "Incorrect kVertices length");
-
- // If display rotation changed (also includes view size change), we need to
- // re-query the uv coordinates for the on-screen portion of the camera image.
- int32_t geometry_changed = 0;
- ArFrame_getDisplayGeometryChanged(session, frame, &geometry_changed);
- if (geometry_changed != 0 || !uvs_initialized_) {
- ArFrame_transformDisplayUvCoords(session, frame, kNumVertices * 2, kUvs,
- transformed_uvs_);
- uvs_initialized_ = true;
- }
- glUseProgram(shader_program_);
- glDepthMask(GL_FALSE);
-
- glUniform1i(uniform_texture_, 1);
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id_);
-
- glEnableVertexAttribArray(attribute_vertices_);
- glVertexAttribPointer(attribute_vertices_, 3, GL_FLOAT, GL_FALSE, 0,
- kVertices);
-
- glEnableVertexAttribArray(attribute_uvs_);
- glVertexAttribPointer(attribute_uvs_, 2, GL_FLOAT, GL_FALSE, 0,
- transformed_uvs_);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
- glUseProgram(0);
- glDepthMask(GL_TRUE);
- util::CheckGlError("BackgroundRenderer::Draw() error");
- }
-
- GLuint BackgroundRenderer::GetTextureId() const { return texture_id_; }
-
-} // namespace hello_ar
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/background_renderer.h b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/background_renderer.h
deleted file mode 100644
index e0624f5cc4a..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/background_renderer.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef C_ARCORE_HELLO_AR_BACKGROUND_RENDERER_H_
-#define C_ARCORE_HELLO_AR_BACKGROUND_RENDERER_H_
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <cstdlib>
-
-#include "arcore_c_api.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/util.h"
-
-namespace hello_ar {
-
-// This class renders the passthrough camera image into the OpenGL frame.
- class BackgroundRenderer {
- public:
- BackgroundRenderer() = default;
-
- ~BackgroundRenderer() = default;
-
- // Sets up OpenGL state. Must be called on the OpenGL thread and before any
- // other methods below.
- void InitializeGlContent();
-
- // Draws the background image. This methods must be called for every ArFrame
- // returned by ArSession_update() to catch display geometry change events.
- void Draw(const ArSession *session, const ArFrame *frame);
-
- // Returns the generated texture name for the GL_TEXTURE_EXTERNAL_OES target.
- GLuint GetTextureId() const;
-
- private:
- static constexpr int kNumVertices = 4;
-
- GLuint shader_program_;
- GLuint texture_id_;
-
- GLuint attribute_vertices_;
- GLuint attribute_uvs_;
- GLuint uniform_texture_;
-
- float transformed_uvs_[kNumVertices * 2];
- bool uvs_initialized_ = false;
- };
-} // namespace hello_ar
-#endif // C_ARCORE_HELLO_AR_BACKGROUND_RENDERER_H_
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/glm.h b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/glm.h
deleted file mode 100644
index cf2a8440b88..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/glm.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef C_ARCORE_HELLOE_AR_GLM_H_
-#define C_ARCORE_HELLOE_AR_GLM_H_
-
-#define GLM_FORCE_RADIANS 1
-#include "glm.hpp"
-#include "gtc/matrix_transform.hpp"
-#include "gtc/type_ptr.hpp"
-#include "gtx/quaternion.hpp"
-
-#endif
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/hello_ar_application.cc b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/hello_ar_application.cc
deleted file mode 100644
index fffa5d71131..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/hello_ar_application.cc
+++ /dev/null
@@ -1,986 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "platform_tools/android/apps/arcore/src/main/cpp/hello_ar_application.h"
-#include <gtx/string_cast.hpp>
-
-#include <math.h> /* acos */
-#include "include/core/SkCanvas.h"
-#include "include/core/SkFontStyle.h"
-#include "include/core/SkMatrix.h"
-#include "include/core/SkMatrix44.h"
-#include "include/core/SkPoint3.h"
-#include "include/core/SkStream.h"
-#include "include/core/SkSurface.h"
-#include "include/core/SkTextBlob.h"
-#include "include/core/SkTypeface.h"
-#include "include/gpu/GrBackendSurface.h"
-#include "include/gpu/GrContext.h"
-#include "include/gpu/gl/GrGLTypes.h"
-#include "include/utils/Sk3D.h"
-#include "modules/skottie/include/Skottie.h"
-#include "modules/skshaper/include/SkShaper.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/anchor_wrapper.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/glm.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/pending_anchor.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/plane_renderer.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/util.h"
-#include "tools/Resources.h"
-
-namespace hello_ar {
- namespace {
- constexpr size_t kMaxNumberOfAndroidsToRender = 1;
- constexpr int32_t kPlaneColorRgbaSize = 16;
-
- const glm::vec3 kWhite = {255, 255, 255};
-
- constexpr std::array<uint32_t, kPlaneColorRgbaSize> kPlaneColorRgba = {
- {0xFFFFFFFF, 0xF44336FF, 0xE91E63FF, 0x9C27B0FF, 0x673AB7FF, 0x3F51B5FF,
- 0x2196F3FF, 0x03A9F4FF, 0x00BCD4FF, 0x009688FF, 0x4CAF50FF, 0x8BC34AFF,
- 0xCDDC39FF, 0xFFEB3BFF, 0xFFC107FF, 0xFF9800FF}};
-
- inline glm::vec3 GetRandomPlaneColor() {
- const int32_t colorRgba = kPlaneColorRgba[std::rand() % kPlaneColorRgbaSize];
- return glm::vec3(((colorRgba >> 24) & 0xff) / 255.0f,
- ((colorRgba >> 16) & 0xff) / 255.0f,
- ((colorRgba >> 8) & 0xff) / 255.0f);
- }
- } // namespace
-
- HelloArApplication::HelloArApplication(AAssetManager *asset_manager)
- : asset_manager_(asset_manager) {
- LOGI("OnCreate()");
- }
-
- HelloArApplication::~HelloArApplication() {
- if (ar_session_ != nullptr) {
- ArSession_destroy(ar_session_);
- ArFrame_destroy(ar_frame_);
- }
- }
-
- void HelloArApplication::OnPause() {
- LOGI("OnPause()");
- if (ar_session_ != nullptr) {
- ArSession_pause(ar_session_);
- }
- }
-
- void HelloArApplication::OnResume(void *env, void *context, void *activity) {
- LOGI("OnResume()");
-
- if (ar_session_ == nullptr) {
- ArInstallStatus install_status;
- // If install was not yet requested, that means that we are resuming the
- // activity first time because of explicit user interaction (such as
- // launching the application)
- bool user_requested_install = !install_requested_;
-
- // === ATTENTION! ATTENTION! ATTENTION! ===
- // This method can and will fail in user-facing situations. Your
- // application must handle these cases at least somewhat gracefully. See
- // HelloAR Java sample code for reasonable behavior.
- CHECK(ArCoreApk_requestInstall(env, activity, user_requested_install,
- &install_status) == AR_SUCCESS);
-
- switch (install_status) {
- case AR_INSTALL_STATUS_INSTALLED:
- break;
- case AR_INSTALL_STATUS_INSTALL_REQUESTED:
- install_requested_ = true;
- return;
- }
-
- // === ATTENTION! ATTENTION! ATTENTION! ===
- // This method can and will fail in user-facing situations. Your
- // application must handle these cases at least somewhat gracefully. See
- // HelloAR Java sample code for reasonable behavior.
- CHECK(ArSession_create(env, context, &ar_session_) == AR_SUCCESS);
- CHECK(ar_session_);
-
- ArFrame_create(ar_session_, &ar_frame_);
- CHECK(ar_frame_);
-
- ArSession_setDisplayGeometry(ar_session_, display_rotation_, width_,
- height_);
- }
-
- const ArStatus status = ArSession_resume(ar_session_);
- CHECK(status == AR_SUCCESS);
- }
-
- void HelloArApplication::OnSurfaceCreated() {
- LOGI("OnSurfaceCreated()");
-
- background_renderer_.InitializeGlContent();
- point_cloud_renderer_.InitializeGlContent();
- plane_renderer_.InitializeGlContent(asset_manager_);
- }
-
- void HelloArApplication::OnDisplayGeometryChanged(int display_rotation,
- int width, int height) {
- LOGI("OnSurfaceChanged(%d, %d)", width, height);
- glViewport(0, 0, width, height);
- display_rotation_ = display_rotation;
- width_ = width;
- height_ = height;
-
- if (ar_session_ != nullptr) {
- ArSession_setDisplayGeometry(ar_session_, display_rotation, width, height);
- }
- }
-
- void HelloArApplication::OnObjectRotationChanged(int rotation) {
- LOGI("OnObjectRotationChanged(%d)", rotation);
- currentObjectRotation = rotation;
- }
-
- void HelloArApplication::OnAction(float value) {
- LOGI("OnAction(%.6f)", value);
- currentValue = value;
- }
-
- void DrawText(SkCanvas *canvas, SkPaint *paint, const char text[]) {
- float spacing = 0.05;
- for (int i = 0; i < sizeof(text) / sizeof(text[0]); i++) {
- const char letter[] = {text[i]};
- size_t byteLength = strlen(static_cast<const char *>(letter));
- canvas->drawText(letter, byteLength, spacing * i, 0, *paint);
- }
- }
-
- void DrawAxes(SkCanvas *canvas, SkMatrix44 m) {
- SkPaint p;
- p.setStrokeWidth(10);
- SkPoint3 src[4] = {
- {0, 0, 0},
- {0.2, 0, 0},
- {0, 0.2, 0},
- {0, 0, 0.2},
- };
- SkPoint dst[4];
- Sk3MapPts(dst, m, src, 4);
-
- const char str[] = "XYZ";
- p.setColor(SK_ColorRED);
- canvas->drawLine(dst[0], dst[1], p);
-
- p.setColor(SK_ColorGREEN);
- canvas->drawLine(dst[0], dst[2], p);
-
- p.setColor(SK_ColorBLUE);
- canvas->drawLine(dst[0], dst[3], p);
- }
-
- void DrawVector(SkCanvas *canvas, SkMatrix44 m, glm::vec3 begin, glm::vec3 end, SkColor c) {
- SkPaint p;
- p.setStrokeWidth(15);
- SkPoint3 src[2] = {
- {begin.x, begin.y, begin.z},
- {end.x, end.y, end.z}
- };
- SkPoint dst[2];
- Sk3MapPts(dst, m, src, 2);
-
- const char str[] = "XYZ";
- p.setColor(c);
- canvas->drawLine(dst[0], dst[1], p);
- }
-
- void DrawBoundingBox(SkCanvas* canvas) {
- SkPaint paint;
- paint.setColor(SK_ColorYELLOW);
- SkIRect bounds = canvas->getDeviceClipBounds();
- SkRect b = SkRect::Make(bounds);
-
- canvas->drawRect(b, paint);
- }
-
- void HelloArApplication::OnDrawFrame() {
- grContext = GrContext::MakeGL();
-
- GrBackendRenderTarget target;
- sk_sp<SkSurface> surface = nullptr;
- GrGLFramebufferInfo framebuffer_info;
- framebuffer_info.fFBOID = 0;
- framebuffer_info.fFormat = 0x8058;
-
-
- glClearColor(0.9f, 0.9f, 0.9f, 1.0f);
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-
- glEnable(GL_CULL_FACE);
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- if (ar_session_ == nullptr) return;
-
- ArSession_setCameraTextureName(ar_session_,
- background_renderer_.GetTextureId());
-
- // Update session to get current frame and render camera background.
- if (ArSession_update(ar_session_, ar_frame_) != AR_SUCCESS) {
- LOGE("HelloArApplication::OnDrawFrame ArSession_update error");
- }
-
- // GET CAMERA INFO
- ArCamera *ar_camera;
- ArFrame_acquireCamera(ar_session_, ar_frame_, &ar_camera);
-
- glm::mat4 view_mat;
- glm::mat4 projection_mat;
- ArCamera_getViewMatrix(ar_session_, ar_camera, glm::value_ptr(view_mat));
- ArCamera_getProjectionMatrix(ar_session_, ar_camera,
- /*near=*/0.1f, /*far=*/100.f,
- glm::value_ptr(projection_mat));
-
- ArTrackingState camera_tracking_state;
- ArCamera_getTrackingState(ar_session_, ar_camera, &camera_tracking_state);
- ArCamera_release(ar_camera);
-
- background_renderer_.Draw(ar_session_, ar_frame_);
-
- // If the camera isn't tracking don't bother rendering other objects.
- if (camera_tracking_state != AR_TRACKING_STATE_TRACKING) {
- return;
- }
-
- // Get light estimation value.
- ArLightEstimate *ar_light_estimate;
- ArLightEstimateState ar_light_estimate_state;
- ArLightEstimate_create(ar_session_, &ar_light_estimate);
-
- ArFrame_getLightEstimate(ar_session_, ar_frame_, ar_light_estimate);
- ArLightEstimate_getState(ar_session_, ar_light_estimate,
- &ar_light_estimate_state);
-
- // Set light intensity to default. Intensity value ranges from 0.0f to 1.0f.
- // The first three components are color scaling factors.
- // The last one is the average pixel intensity in gamma space.
- float color_correction[4] = {1.f, 1.f, 1.f, 1.f};
- if (ar_light_estimate_state == AR_LIGHT_ESTIMATE_STATE_VALID) {
- ArLightEstimate_getColorCorrection(ar_session_, ar_light_estimate,
- color_correction);
- }
-
- ArLightEstimate_destroy(ar_light_estimate);
- ar_light_estimate = nullptr;
- SkMatrix44 skProj;
- SkMatrix44 skView;
- SkMatrix skViewport;
-
- skProj = util::GlmMatToSkMat(projection_mat);
- skView = util::GlmMatToSkMat(view_mat);
- skViewport.setScale(width_ / 2, -height_ / 2);
- skViewport.postTranslate(width_ / 2, height_ / 2);
- target = GrBackendRenderTarget(width_, height_, 0, 0, framebuffer_info);
- surface = SkSurface::MakeFromBackendRenderTarget(grContext.get(),
- target,
- kBottomLeft_GrSurfaceOrigin,
- kRGBA_8888_SkColorType,
- nullptr, nullptr);
-
- // Render Andy objects.
- std::vector<SkMatrix44> models;
- //glm::mat4 model_mat(1.0f);
- for (const auto &obj_iter : tracked_obj_set_) {
- ArTrackingState tracking_state = AR_TRACKING_STATE_STOPPED;
- ArAnchor_getTrackingState(ar_session_, obj_iter, &tracking_state);
- if (tracking_state == AR_TRACKING_STATE_TRACKING) {
- // Render object only if the tracking state is AR_TRACKING_STATE_TRACKING.
- //util::GetTransformMatrixFromAnchor(ar_session_, obj_iter, &model_mat);
- //DRAW ANDY
- //andy_renderer_.Draw(glm::mat4(1), glm::mat4(1), model_mat, color_correction);
-
- //PREPARE SKIA MATS
-
- SkMatrix44 skModel;
-
- switch (currentObjectRotation) {
- case 0: {
- auto iter = anchor_skmat4_axis_aligned_map_.find(obj_iter);
- if (iter != anchor_skmat4_axis_aligned_map_.end()) {
- skModel = iter->second;
- models.push_back(skModel);
- }
- }
- break;
- case 1: {
- auto iter = anchor_skmat4_camera_aligned_map_.find(obj_iter);
- if (iter != anchor_skmat4_camera_aligned_map_.end()) {
- skModel = iter->second;
- models.push_back(skModel);
- }
- }
- break;
- case 2: {
- auto iter = anchor_skmat4_snap_aligned_map_.find(obj_iter);
- if (iter != anchor_skmat4_snap_aligned_map_.end()) {
- skModel = iter->second;
- models.push_back(skModel);
- }
- }
- break;
- default: {
- auto iter = anchor_skmat4_axis_aligned_map_.find(obj_iter);
- if (iter != anchor_skmat4_axis_aligned_map_.end()) {
- skModel = iter->second;
- models.push_back(skModel);
- }
- }
- break;
- }
-
- }
- }
-
- // Update and render planes.
- ArTrackableList *plane_list = nullptr;
- ArTrackableList_create(ar_session_, &plane_list);
- CHECK(plane_list != nullptr);
-
- ArTrackableType plane_tracked_type = AR_TRACKABLE_PLANE;
- ArSession_getAllTrackables(ar_session_, plane_tracked_type, plane_list);
-
- int32_t plane_list_size = 0;
- ArTrackableList_getSize(ar_session_, plane_list, &plane_list_size);
- plane_count_ = plane_list_size;
-
- for (int i = 0; i < plane_list_size; ++i) {
- ArTrackable *ar_trackable = nullptr;
- ArTrackableList_acquireItem(ar_session_, plane_list, i, &ar_trackable);
- ArPlane *ar_plane = ArAsPlane(ar_trackable);
- ArTrackingState out_tracking_state;
- ArTrackable_getTrackingState(ar_session_, ar_trackable,
- &out_tracking_state);
-
- ArPlane *subsume_plane;
- ArPlane_acquireSubsumedBy(ar_session_, ar_plane, &subsume_plane);
- if (subsume_plane != nullptr) {
- ArTrackable_release(ArAsTrackable(subsume_plane));
- continue;
- }
-
- if (ArTrackingState::AR_TRACKING_STATE_TRACKING != out_tracking_state) {
- continue;
- }
-
- ArTrackingState plane_tracking_state;
- ArTrackable_getTrackingState(ar_session_, ArAsTrackable(ar_plane),
- &plane_tracking_state);
- if (plane_tracking_state == AR_TRACKING_STATE_TRACKING) {
- const auto iter = plane_color_map_.find(ar_plane);
- glm::vec3 color;
- if (iter != plane_color_map_.end()) {
- color = iter->second;
-
- // If this is an already observed trackable release it so it doesn't
- // leave aof placing objects on surfaces (n additional reference dangling.
- ArTrackable_release(ar_trackable);
- } else {
- // The first plane is always white.
- if (!first_plane_has_been_found_) {
- first_plane_has_been_found_ = true;
- color = kWhite;
- } else {
- color = GetRandomPlaneColor();
- }
- plane_color_map_.insert({ar_plane, color});
- }
-
- plane_renderer_.Draw(projection_mat, view_mat, ar_session_, ar_plane,
- color);
- }
- }
-
- ArTrackableList_destroy(plane_list);
- plane_list = nullptr;
-
- // Update and render point cloud.
- ArPointCloud *ar_point_cloud = nullptr;
- ArStatus point_cloud_status =
- ArFrame_acquirePointCloud(ar_session_, ar_frame_, &ar_point_cloud);
- if (point_cloud_status == AR_SUCCESS) {
- point_cloud_renderer_.Draw(projection_mat * view_mat, ar_session_,
- ar_point_cloud);
- ArPointCloud_release(ar_point_cloud);
- }
- SkMatrix44 i = SkMatrix44::kIdentity_Constructor;
-
- if (surface != nullptr) {
- SkCanvas *canvas = surface->getCanvas();
- SkAutoCanvasRestore acr(canvas, true);
- SkMatrix44 vpv = skViewport * skProj * skView;
- for(SkMatrix44 skModel: models) {
- SkMatrix44 i = SkMatrix44::kIdentity_Constructor;
- canvas->setMatrix(i);
- SkMatrix44 mvpv = skViewport * skProj * skView * skModel;
-
- //Draw XYZ axes
- DrawAxes(canvas, mvpv);
- //Drawing camera orientation
- /* DrawVector(canvas, vpv, begins[0], ends[0], SK_ColorMAGENTA);
- DrawVector(canvas, vpv, begins[0], ends[1], SK_ColorYELLOW);
- DrawVector(canvas, vpv, begins[0], ends[2], SK_ColorCYAN);*/
-
- canvas->concat(mvpv);
- SkPaint paint;
-
- //Draw Circle
- paint.setColor(0x80700000);
- canvas->drawCircle(0, 0, 0.1, paint);
-
- //Draw Text
- paint.setColor(SK_ColorBLUE);
- if (currentValue != 0) {
- paint.setTextSize(currentValue);
- } else {
- paint.setTextSize(0.1);
- }
-
- paint.setAntiAlias(true);
- const char text[] = "SkAR";
- size_t byteLength = strlen(static_cast<const char *>(text));
- SkShaper shaper(nullptr);
- SkTextBlobBuilder builder;
- SkPoint p = SkPoint::Make(0, 0);
- shaper.shape(&builder, paint, text, byteLength, true, p, 10);
- canvas->drawTextBlob(builder.make(), 0, 0, paint);
-
- //DrawBoundingBox(canvas);
- }
- canvas->flush();
- }
- }
-
-
- bool HelloArApplication::OnTouchedFirst(float x, float y, int drawMode) {
- LOGI("Entered OnTouchedFirst");
- if (pendingAnchor != nullptr) {
- delete pendingAnchor;
- }
- SkPoint p = SkPoint::Make(x,y);
- pendingAnchor = new PendingAnchor(p);
- bool editAnchor = false;
-
- if (ar_frame_ != nullptr && ar_session_ != nullptr) {
- ArHitResultList *hit_result_list = nullptr;
- ArHitResultList_create(ar_session_, &hit_result_list);
- CHECK(hit_result_list);
- ArFrame_hitTest(ar_session_, ar_frame_, x, y, hit_result_list);
-
- int32_t hit_result_list_size = 0;
- ArHitResultList_getSize(ar_session_, hit_result_list, &hit_result_list_size);
- ArHitResult *ar_hit_result = nullptr;
- ArPose *out_pose = nullptr;
- ArPlane* hitPlane = nullptr;
- for (int32_t i = 0; i < hit_result_list_size; ++i) {
- ArHitResult *ar_hit = nullptr;
- ArPose *created_out_pose = nullptr;
- ArHitResult_create(ar_session_, &ar_hit);
- ArHitResultList_getItem(ar_session_, hit_result_list, i, ar_hit);
-
- if (ar_hit == nullptr) {
- LOGE("HelloArApplication::OnTouched ArHitResultList_getItem error");
- return editAnchor;
- }
-
- ArTrackable *ar_trackable = nullptr;
- ArHitResult_acquireTrackable(ar_session_, ar_hit, &ar_trackable);
- ArTrackableType ar_trackable_type = AR_TRACKABLE_NOT_VALID;
- ArTrackable_getType(ar_session_, ar_trackable, &ar_trackable_type);
- // Creates an anchor if a plane or an oriented point was hit.
- if (AR_TRACKABLE_PLANE == ar_trackable_type) {
- ArPose *hit_pose = nullptr;
- ArPose_create(ar_session_, nullptr, &hit_pose);
- ArHitResult_getHitPose(ar_session_, ar_hit, hit_pose);
- int32_t in_polygon = 0;
- ArPlane *ar_plane = ArAsPlane(ar_trackable);
- ArPlane_isPoseInPolygon(ar_session_, ar_plane, hit_pose, &in_polygon);
-
- {
- // Use hit pose and camera pose to check if hittest is from the
- // back of the plane, if it is, no need to create the anchor.
- ArPose *camera_pose = nullptr;
- ArPose_create(ar_session_, nullptr, &camera_pose);
- ArCamera *ar_camera;
- ArFrame_acquireCamera(ar_session_, ar_frame_, &ar_camera);
- ArCamera_getPose(ar_session_, ar_camera, camera_pose);
- float normal_distance_to_plane = util::CalculateDistanceToPlane(
- ar_session_, *hit_pose, *camera_pose);
-
- if (!in_polygon || normal_distance_to_plane < 0) {
- ArPose_destroy(camera_pose);
- continue;
- }
- ArPose_destroy(camera_pose);
- ArCamera_release(ar_camera);
- }
-
- //Raw pose of hit location
- float out_hit_raw[] = {0, 0, 0, 0, 0, 0, 0};
- ArPose_getPoseRaw(ar_session_, hit_pose, out_hit_raw);
- ArPose_destroy(hit_pose);
-
- //Position of anchor
- glm::vec4 pendingAnchorPos(out_hit_raw[4], out_hit_raw[5], out_hit_raw[6], 1);
- pendingAnchor->SetContainingPlane(ar_plane);
-
- //Check if plane contains approx the same anchor
- auto planeAnchors = plane_anchors_map_.find(ar_plane);
- if (planeAnchors != plane_anchors_map_.end()) {
- //other anchors existed on this plane
- std::vector<ArAnchor*> anchors = planeAnchors->second;
- int i = 0;
- LOGI("Size of anchor list: %d", (int) anchors.size());
- for(ArAnchor* const& anchor: anchors) {
- //Get anchor's pose
- i++;
- LOGI("CHECKING: Anchor #%d", i);
- ArPose *anchor_pose = nullptr;
- ArPose_create(ar_session_, nullptr, &anchor_pose);
- ArAnchor_getPose(ar_session_, anchor, anchor_pose);
- float out_anchor_raw[] = {0, 0, 0, 0, 0, 0, 0};
- ArPose_getPoseRaw(ar_session_, anchor_pose, out_anchor_raw);
- ArPose_destroy(anchor_pose);
- glm::vec4 oldAnchorPos(out_anchor_raw[4], out_anchor_raw[5], out_anchor_raw[6], 1);
- oldAnchorPos = oldAnchorPos - pendingAnchorPos;
- float distance = util::Magnitude(glm::vec3(oldAnchorPos));
- if (distance < 0.1f) {
- LOGI("TouchFirst: Editing old anchor!");
- editAnchor = true;
- pendingAnchor->SetArAnchor(anchor);
- pendingAnchor->SetEditMode(true);
-
- ArHitResult_destroy(ar_hit);
- ArHitResultList_destroy(hit_result_list);
- LOGI("TouchFirst: Edit %d", editAnchor);
- return editAnchor;
- }
- }
- }
-
- //actual hit result, and containing plane
- ar_hit_result = ar_hit;
- hitPlane = ar_plane;
-
- //new anchor pos
- float wanted_raw_pose[] = {0, 0, 0, 0, out_hit_raw[4], out_hit_raw[5], out_hit_raw[6]};
- ArPose_create(ar_session_, wanted_raw_pose, &created_out_pose);
- out_pose = created_out_pose;
- break;
- }
- }
-
-
- if (ar_hit_result) {
- LOGI("TouchFirst: Adding new anchor!");
- ArAnchor *anchor = nullptr;
- pendingAnchor->SetEditMode(false);
-
- if (ArSession_acquireNewAnchor(ar_session_, out_pose, &anchor) != AR_SUCCESS) {
- LOGE("HelloArApplication::OnTouched ArHitResult_acquireNewAnchor error");
- LOGI("TouchFirst: Failed to acquire new anchor");
- delete hitPlane;
- delete pendingAnchor;
- pendingAnchor = nullptr;
- LOGI("TouchFirst: Edit %d", editAnchor);
- return editAnchor;
- }
- pendingAnchor->SetArAnchor(anchor);
-
- ArHitResult_destroy(ar_hit_result);
- ArHitResultList_destroy(hit_result_list);
- ArPose_destroy(out_pose);
- hit_result_list = nullptr;
- LOGI("TouchFirst: Edit %d", editAnchor);
- return editAnchor;
- }
-
- LOGI("TouchFirst: didn't hit anything");
- delete hitPlane;
- delete pendingAnchor;
- pendingAnchor = nullptr;
- LOGI("TouchFirst: Edit %d", editAnchor);
- return editAnchor;
- }
- }
-
- void HelloArApplication::AddAnchor(ArAnchor* anchor, ArPlane* containingPlane) {
- //delete anchor from matrices maps
- //releasing the anchor if it is not tracking anymore
- ArTrackingState tracking_state = AR_TRACKING_STATE_STOPPED;
- ArAnchor_getTrackingState(ar_session_, anchor, &tracking_state);
- if (tracking_state != AR_TRACKING_STATE_TRACKING) {
- RemoveAnchor(anchor);
- return;
- }
-
- //releasing the first anchor if we exceeded maximum number of objects to be rendered
- if (tracked_obj_set_.size() >= kMaxNumberOfAndroidsToRender) {
- RemoveAnchor(tracked_obj_set_[0]);
- }
-
- //updating the containing plane with a new anchor
- auto planeAnchors = plane_anchors_map_.find(containingPlane);
- if (planeAnchors != plane_anchors_map_.end()) {
- //other anchors existed on this plane
- LOGI("TouchFinal: ADDING TO OLD ANCHORS");
- std::vector<ArAnchor*> anchors = planeAnchors->second;
- anchors.push_back(anchor);
- plane_anchors_map_[containingPlane] = anchors;
- anchor_plane_map_.insert({anchor, containingPlane});
- } else {
- LOGI("TouchFinal: NEW SET OF ANCHORS");
- std::vector<ArAnchor*> anchors;
- anchors.push_back(anchor);
- plane_anchors_map_.insert({containingPlane, anchors});
- anchor_plane_map_.insert({anchor, containingPlane});
- }
-
- tracked_obj_set_.push_back(anchor);
- }
-
- void HelloArApplication::OnTouchTranslate(float x, float y) {
- LOGI("Entered On Edit Touched");
- ArAnchor *anchor = pendingAnchor->GetArAnchor();
- glm::mat4 matrix = util::SkMatToGlmMat(
- anchor_skmat4_axis_aligned_map_.find(anchor)->second);
-
- if (ar_frame_ != nullptr && ar_session_ != nullptr) {
- ArHitResultList *hit_result_list = nullptr;
- ArHitResultList_create(ar_session_, &hit_result_list);
- CHECK(hit_result_list);
- ArFrame_hitTest(ar_session_, ar_frame_, x, y, hit_result_list);
-
- int32_t hit_result_list_size = 0;
- ArHitResultList_getSize(ar_session_, hit_result_list, &hit_result_list_size);
- ArHitResult *ar_hit_result = nullptr;
- ArPose *out_pose = nullptr;
- ArPlane *hitPlane = nullptr;
- for (int32_t i = 0; i < hit_result_list_size; ++i) {
- ArHitResult *ar_hit = nullptr;
- ArPose *created_out_pose = nullptr;
- ArHitResult_create(ar_session_, &ar_hit);
- ArHitResultList_getItem(ar_session_, hit_result_list, i, ar_hit);
-
- if (ar_hit == nullptr) {
- LOGE("HelloArApplication::OnTouched ArHitResultList_getItem error");
- return;
- }
-
- ArTrackable *ar_trackable = nullptr;
- ArHitResult_acquireTrackable(ar_session_, ar_hit, &ar_trackable);
- ArTrackableType ar_trackable_type = AR_TRACKABLE_NOT_VALID;
- ArTrackable_getType(ar_session_, ar_trackable, &ar_trackable_type);
- // Creates an anchor if a plane or an oriented point was hit.
- if (AR_TRACKABLE_PLANE == ar_trackable_type) {
- ArPose *hit_pose = nullptr;
- ArPose_create(ar_session_, nullptr, &hit_pose);
- ArHitResult_getHitPose(ar_session_, ar_hit, hit_pose);
- int32_t in_polygon = 0;
- ArPlane *ar_plane = ArAsPlane(ar_trackable);
- ArPlane_isPoseInPolygon(ar_session_, ar_plane, hit_pose, &in_polygon);
-
- {
- // Use hit pose and camera pose to check if hittest is from the
- // back of the plane, if it is, no need to create the anchor.
- ArPose *camera_pose = nullptr;
- ArPose_create(ar_session_, nullptr, &camera_pose);
- ArCamera *ar_camera;
- ArFrame_acquireCamera(ar_session_, ar_frame_, &ar_camera);
- ArCamera_getPose(ar_session_, ar_camera, camera_pose);
- float normal_distance_to_plane = util::CalculateDistanceToPlane(
- ar_session_, *hit_pose, *camera_pose);
-
- if (!in_polygon || normal_distance_to_plane < 0) {
- ArPose_destroy(camera_pose);
- continue;
- }
- ArPose_destroy(camera_pose);
- ArCamera_release(ar_camera);
- }
-
- //Raw pose of hit location
- float out_hit_raw[] = {0, 0, 0, 0, 0, 0, 0};
- ArPose_getPoseRaw(ar_session_, hit_pose, out_hit_raw);
- ArPose_destroy(hit_pose);
-
- //Translate by new amount
- glm::vec4 newPos(out_hit_raw[4], out_hit_raw[5], out_hit_raw[6], 1);
- glm::vec4 oldPos = pendingAnchor->GetAnchorPos(ar_session_);
- glm::vec3 movement = glm::vec3(newPos - oldPos);
-
-
- //CAMERA SETTINGS
- glm::mat4 backToOrigin(1);
- backToOrigin = glm::translate(backToOrigin, -glm::vec3(oldPos));
- glm::mat4 backToPlane(1);
- backToPlane = glm::translate(backToPlane, glm::vec3(oldPos));
-
- //Axes of Skia object: start with XYZ, totate to get X(-Z)Y, paste on plane, go back to origin --> plane orientation but on origin
- glm::vec3 objX = glm::normalize(glm::vec3(
- backToOrigin * matrix *
- glm::vec4(1, 0, 0, 1))); //X still X
- glm::vec3 objY = glm::normalize(glm::vec3(
- backToOrigin * matrix *
- glm::vec4(0, 1, 0, 1))); //Y is now Z
- glm::vec3 objZ = glm::normalize(glm::vec3(
- backToOrigin * matrix *
- glm::vec4(0, 0, 1, 1))); //Z is now Y
-
-
- glm::mat4 translate(1);
- translate = glm::translate(translate, movement);
- matrix = translate * matrix;
- RemoveAnchor(anchor);
-
-
-
- //new anchor pos
- float wanted_raw_pose[] = {0, 0, 0, 0, out_hit_raw[4], out_hit_raw[5],
- out_hit_raw[6]};
- ArPose_create(ar_session_, wanted_raw_pose, &created_out_pose);
- out_pose = created_out_pose;
- ar_hit_result = ar_hit;
- break;
- }
- }
-
- if (ar_hit_result) {
- LOGI("TouchFirst: Adding new anchor!");
- ArAnchor *anchor = nullptr;
- pendingAnchor->SetEditMode(false);
-
- if (ArSession_acquireNewAnchor(ar_session_, out_pose, &anchor) != AR_SUCCESS) {
- LOGE("HelloArApplication::OnTouched ArHitResult_acquireNewAnchor error");
- LOGI("TouchFirst: Failed to acquire new anchor");
- delete hitPlane;
- delete pendingAnchor;
- pendingAnchor = nullptr;
- return;
- }
- pendingAnchor->SetArAnchor(anchor);
- anchor_skmat4_axis_aligned_map_[anchor] = util::GlmMatToSkMat(matrix);
-
- //Add anchor
- AddAnchor(anchor, pendingAnchor->GetContainingPlane());
-
-
- ArHitResult_destroy(ar_hit_result);
- ArHitResultList_destroy(hit_result_list);
- ArPose_destroy(out_pose);
- hit_result_list = nullptr;
- return;
- }
- }
- }
-
- void HelloArApplication::RemoveAnchor(ArAnchor* anchor) {
- //delete anchor from matrices maps
- anchor_skmat4_axis_aligned_map_.erase(anchor);
- anchor_skmat4_camera_aligned_map_.erase(anchor);
- anchor_skmat4_snap_aligned_map_.erase(anchor);
-
- auto containingPlaneIter = anchor_plane_map_.find(anchor);
- if (containingPlaneIter != anchor_plane_map_.end()) {
- ArPlane* containingPlane = containingPlaneIter->second;
- auto planeAnchors = plane_anchors_map_.find(containingPlane);
- if (planeAnchors != plane_anchors_map_.end()) {
- //delete this anchor from the list of anchors associated with its plane
- std::vector<ArAnchor*> anchors = planeAnchors->second;
- anchors.erase(std::remove(anchors.begin(), anchors.end(), anchor), anchors.end());
- plane_anchors_map_[planeAnchors->first] = anchors;
-
- //delete anchor from map of anchor to plane
- anchor_plane_map_.erase(anchor);
- }
- }
- //delete anchor from list of tracked objects
- tracked_obj_set_.erase(std::remove(tracked_obj_set_.begin(), tracked_obj_set_.end(), anchor), tracked_obj_set_.end());
- ArAnchor_release(anchor);
- }
-
- void HelloArApplication::UpdateMatrixMaps(ArAnchor* anchorKey, glm::mat4 aaMat, glm::mat4 caMat, glm::mat4 snapMat) {
- anchor_skmat4_axis_aligned_map_.insert({anchorKey, util::GlmMatToSkMat(aaMat)});
- anchor_skmat4_camera_aligned_map_.insert({anchorKey, util::GlmMatToSkMat(caMat)});
- anchor_skmat4_snap_aligned_map_.insert({anchorKey, util::GlmMatToSkMat(snapMat)});
- }
-
- void SetSkiaInitialRotation(glm::mat4& initRotation) {
- initRotation = glm::rotate(initRotation, SK_ScalarPI / 2, glm::vec3(1, 0, 0));
- }
-
- void SetSkiaObjectAxes(glm::vec3& x, glm::vec3& y, glm::vec3& z, glm::mat4 transform) {
- x = glm::normalize(glm::vec3(transform * glm::vec4(1, 0, 0, 1))); //X still X
- y = glm::normalize(glm::vec3(transform * glm::vec4(0, 1, 0, 1))); //Y is now Z
- z = glm::normalize(glm::vec3(transform * glm::vec4(0, 0, 1, 1))); //Z is now Y
- }
-
- void SetCameraAlignedRotation(glm::mat4& rotateTowardsCamera, float& rotationDirection, const glm::vec3& toProject, const glm::vec3& skiaY, const glm::vec3& skiaZ) {
- glm::vec3 hitLookProj = -util::ProjectOntoPlane(toProject, skiaZ);
- float angleRad = util::AngleRad(skiaY, hitLookProj);
- glm::vec3 cross = glm::normalize(glm::cross(skiaY, hitLookProj));
-
- //outs
- rotationDirection = util::Dot(cross, skiaZ);
- rotateTowardsCamera = glm::rotate(rotateTowardsCamera, angleRad, rotationDirection * skiaZ);
- }
-
- struct CameraAlignmentInfo {
- glm::vec3& skiaY, skiaZ;
- glm::mat4& preRot, postRot;
-
- CameraAlignmentInfo(glm::vec3& skiaY, glm::vec3& skiaZ, glm::mat4 preRot, glm::mat4 postRot)
- : skiaY(skiaY), skiaZ(skiaZ), preRot(preRot), postRot(postRot) {}
- };
-
- void SetCameraAlignedVertical(glm::mat4& caMat, const glm::mat4& camRot, const CameraAlignmentInfo& camAlignInfo) {
- //Camera axes
- glm::vec3 xCamera = glm::vec3(glm::vec4(1, 0, 0, 1) * camRot);
- glm::vec3 yCamera = glm::vec3(glm::vec4(0, 1, 0, 1) * camRot);
- glm::vec3 zCamera = glm::vec3(glm::vec4(0, 0, -1, 1) * camRot);
-
- //Get matrix that rotates object from plane towards the wanted angle
- glm::mat4 rotateTowardsCamera(1);
- float rotationDirection = 1;
- SetCameraAlignedRotation(rotateTowardsCamera, rotationDirection, yCamera, camAlignInfo.skiaY, camAlignInfo.skiaZ);
-
- //LogOrientation(dot, angleRad, "Vertical/Wall");
- glm::mat4 flip(1);
- flip = glm::rotate(flip, SK_ScalarPI, rotationDirection * camAlignInfo.skiaZ);
- caMat = camAlignInfo.postRot * flip * rotateTowardsCamera * camAlignInfo.preRot;
- }
-
- void SetCameraAlignedHorizontal(glm::mat4& caMat, ArPlaneType planeType, const glm::vec3 hitLook, const CameraAlignmentInfo& camAlignInfo) {
- //Ceiling or Floor: follow hit location
- //Get matrix that rotates object from plane towards the wanted angle
- glm::mat4 rotateTowardsCamera(1);
- float rotationDirection = 1;
- SetCameraAlignedRotation(rotateTowardsCamera, rotationDirection, hitLook, camAlignInfo.skiaY, camAlignInfo.skiaZ);
-
- if (planeType == ArPlaneType::AR_PLANE_HORIZONTAL_DOWNWARD_FACING) {
- //ceiling
- //LogOrientation(dot, angleRad, "Ceiling");
- glm::mat4 flip(1);
- flip = glm::rotate(flip, SK_ScalarPI, rotationDirection * camAlignInfo.skiaZ);
- caMat = camAlignInfo.postRot * flip * rotateTowardsCamera * camAlignInfo.preRot;
- } else {
- //floor or tabletop
- //LogOrientation(dot, angleRad, "Floor");
- caMat = camAlignInfo.postRot * rotateTowardsCamera * camAlignInfo.preRot;
- }
- }
-
-
-
- void HelloArApplication::SetCameraAlignedMatrix(glm::mat4& caMat, glm::vec3 hitPos, glm::mat4& planeModel, const glm::mat4& initRotation) {
- //Translation matrices: from plane to origin, and from origin to plane
- glm::mat4 backToOrigin(1);
- backToOrigin = glm::translate(backToOrigin, -hitPos);
- glm::mat4 backToPlane(1);
- backToPlane = glm::translate(backToPlane, hitPos);
-
- //Axes of Skia object: start with XYZ, totate to get X(-Z)Y, paste on plane, go back to origin --> plane orientation but on origin
- glm::vec3 skiaX, skiaY, skiaZ;
- SetSkiaObjectAxes(skiaX, skiaY, skiaZ, backToOrigin * planeModel * initRotation);
-
- //Get camera position & rotation
- glm::vec3 cameraPos;
- glm::mat4 cameraRotationMatrix;
- util::GetCameraInfo(ar_session_, ar_frame_, cameraPos, cameraRotationMatrix);
-
- //Set matrix depending on type of surface
- ArPlaneType planeType = AR_PLANE_VERTICAL;
- ArPlane_getType(ar_session_, pendingAnchor->GetContainingPlane(), &planeType);
-
- //Set CamerAlignmentInfo
- CameraAlignmentInfo camAlignInfo(skiaY, skiaZ, backToOrigin * planeModel * initRotation, backToPlane);
-
- if (planeType == ArPlaneType::AR_PLANE_VERTICAL) {
- //Wall: follow phone orientation
- SetCameraAlignedVertical(caMat, cameraRotationMatrix, camAlignInfo);
- } else {
- //Ceiling or Floor: follow hit location
- glm::vec3 hitLook(hitPos - cameraPos);
- SetCameraAlignedHorizontal(caMat, planeType, hitLook, camAlignInfo);
- }
- }
-
-
- void HelloArApplication::SetModelMatrices(glm::mat4& aaMat, glm::mat4& caMat, glm::mat4& snapMat, const glm::mat4& planeModel) {
- //Brings Skia world to ARCore world
- glm::mat4 initRotation(1);
- SetSkiaInitialRotation(initRotation);
-
- //Copy plane model for editing
- glm::mat4 copyPlaneModel(planeModel);
-
- //Set snap matrix
- //snapMat = copyPlaneModel * initRotation;
-
- //Set axis-aligned matrix
- glm::vec4 anchorPos = pendingAnchor->GetAnchorPos(ar_session_);
- copyPlaneModel[3] = anchorPos;
- aaMat = planeModel * initRotation;
-
- //Set camera-aligned matrix
- //SetCameraAlignedMatrix(caMat, glm::vec3(anchorPos), copyPlaneModel, initRotation);
- }
-
- void GetPlaneModelMatrix(glm::mat4& planeModel, ArSession* arSession, ArPlane* arPlane) {
- ArPose *plane_pose = nullptr;
- ArPose_create(arSession, nullptr, &plane_pose);
- ArPlane_getCenterPose(arSession, arPlane, plane_pose);
- util::GetTransformMatrixFromPose(arSession, plane_pose, &planeModel);
- ArPose_destroy(plane_pose);
- }
-
- void HelloArApplication::OnTouchedFinal(int type) {
- LOGI("Entered OnTouchedFinal");
- if (pendingAnchor == nullptr) {
- LOGI("WARNING: Entered OnTouchedFinal but no pending anchor..");
- return;
- }
-
- if (pendingAnchor->GetEditMode()) {
- LOGI("WARNING: Editing old anchor in OnTouchedFinal!");
- }
-
- //Get necessary pending anchor info
- ArPlane* containingPlane = pendingAnchor->GetContainingPlane();
- glm::vec4 pendingAnchorPos = pendingAnchor->GetAnchorPos(ar_session_);
- ArAnchor* actualAnchor = pendingAnchor->GetArAnchor();
-
- //Plane model matrix
- glm::mat4 planeModel(1);
- GetPlaneModelMatrix(planeModel, ar_session_, containingPlane);
-
- //Setup skia object model matrices
- glm::mat4 matrixAxisAligned(1);
- glm::mat4 matrixCameraAligned(1);
- glm::mat4 matrixSnapAligned(1);
- SetModelMatrices(matrixAxisAligned, matrixCameraAligned, matrixSnapAligned, planeModel);
-
- //Update anchor -> model matrix datastructures
- UpdateMatrixMaps(actualAnchor, matrixAxisAligned, matrixCameraAligned, matrixSnapAligned);
-
- //Add anchor to aux datastructures
- AddAnchor(actualAnchor, containingPlane);
- }
-
-} // namespace hello_ar
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/hello_ar_application.h b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/hello_ar_application.h
deleted file mode 100644
index 323ec59ee7c..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/hello_ar_application.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef C_ARCORE_HELLOE_AR_HELLO_AR_APPLICATION_H_
-#define C_ARCORE_HELLOE_AR_HELLO_AR_APPLICATION_H_
-
-#include "include/core/SkSurface.h"
-#include "include/gpu/GrBackendSurface.h"
-#include "include/gpu/GrContext.h"
-#include "include/gpu/gl/GrGLTypes.h"
-#include "modules/skottie/include/Skottie.h"
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <android/asset_manager.h>
-#include <jni.h>
-#include <memory>
-#include <set>
-#include <string>
-#include <unordered_map>
-
-#include "arcore_c_api.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/background_renderer.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/glm.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/pending_anchor.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/plane_renderer.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/point_cloud_renderer.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/util.h"
-
-namespace hello_ar {
-
-// HelloArApplication handles all application logics.
- class HelloArApplication {
- public:
- // Constructor and deconstructor.
- HelloArApplication() = default;
-
- HelloArApplication(AAssetManager *asset_manager);
-
- ~HelloArApplication();
-
- SkMatrix SkiaRenderer(const glm::mat4 &proj, const glm::mat4 &view, const glm::mat4 &model);
-
- // OnPause is called on the UI thread from the Activity's onPause method.
- void OnPause();
-
- // OnResume is called on the UI thread from the Activity's onResume method.
- void OnResume(void *env, void *context, void *activity);
-
- // OnSurfaceCreated is called on the OpenGL thread when GLSurfaceView
- // is created.
- void OnSurfaceCreated();
-
- // OnDisplayGeometryChanged is called on the OpenGL thread when the
- // render surface size or display rotation changes.
- //
- // @param display_rotation: current display rotation.
- // @param width: width of the changed surface view.
- // @param height: height of the changed surface view.
- void OnDisplayGeometryChanged(int display_rotation, int width, int height);
-
- void OnObjectRotationChanged(int rotation);
-
- void OnAction(float value);
-
- // OnDrawFrame is called on the OpenGL thread to render the next frame.
- void OnDrawFrame();
-
- bool OnTouchedFirst(float x, float y, int drawMode);
-
- void OnTouchTranslate(float x, float y);
-
- void OnEditTouched(float x, float y);
-
- void OnTouchedFinal(int type);
-
- void RemoveAnchor(ArAnchor* anchor);
-
- void AddAnchor(ArAnchor* anchor, ArPlane* containingPlane);
-
- void UpdateMatrixMaps(ArAnchor* anchorKey, glm::mat4 aaMat, glm::mat4 caMat, glm::mat4 snapMat);
-
- void SetModelMatrices(glm::mat4& aaMat, glm::mat4& caMat, glm::mat4& snapMat, const glm::mat4& planeModel);
-
- void SetCameraAlignedMatrix(glm::mat4& caMat, glm::vec3 hitPos, glm::mat4& planeModel, const glm::mat4& initRotation);
-
- // Returns true if any planes have been detected. Used for hiding the
- // "searching for planes" snackbar.
- bool HasDetectedPlanes() const { return plane_count_ > 0; }
-
- glm::mat4
- ComputeCameraAlignedMatrix(ArPlane *arPlane, glm::mat4 planeModel, glm::mat4 initRotation,
- glm::vec4 anchorPos,
- glm::vec3 cameraPos, glm::vec3 hitPos,
- float cameraDisplayOutRaw[]);
-
- private:
- ArSession *ar_session_ = nullptr;
- ArFrame *ar_frame_ = nullptr;
-
- PendingAnchor* pendingAnchor = nullptr;
-
- //SKIA VARS
- sk_sp<GrContext> grContext;
- sk_sp<skottie::Animation> fAnim;
- SkScalar fAnimT = 0;
-
- bool install_requested_ = false;
- int width_ = 1;
- int height_ = 1;
- int display_rotation_ = 0;
-
- int currentObjectRotation = 0;
- float currentValue = 0;
-
- std::vector<glm::vec3> begins;
- std::vector<glm::vec3> ends;
-
- AAssetManager *const asset_manager_;
-
- // The anchors at which we are drawing android models
- std::vector<ArAnchor *> tracked_obj_set_;
-
- // Stores the randomly-selected color each plane is drawn with
- std::unordered_map<ArPlane *, glm::vec3> plane_color_map_;
-
- std::unordered_map<ArAnchor *, SkMatrix44> anchor_skmat4_axis_aligned_map_;
- std::unordered_map<ArAnchor *, SkMatrix44> anchor_skmat4_camera_aligned_map_;
- std::unordered_map<ArAnchor *, SkMatrix44> anchor_skmat4_snap_aligned_map_;
-
- std::unordered_map<ArPlane *, std::vector<ArAnchor*>> plane_anchors_map_;
- std::unordered_map<ArAnchor *, ArPlane*> anchor_plane_map_;
-
- // The first plane is always rendered in white, if this is true then a plane
- // at some point has been found.
- bool first_plane_has_been_found_ = false;
-
- PointCloudRenderer point_cloud_renderer_;
- BackgroundRenderer background_renderer_;
- PlaneRenderer plane_renderer_;
-
- int32_t plane_count_ = 0;
- };
-} // namespace hello_ar
-
-#endif // C_ARCORE_HELLOE_AR_HELLO_AR_APPLICATION_H_
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/jni_interface.cc b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/jni_interface.cc
deleted file mode 100644
index 898c20d956b..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/jni_interface.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/asset_manager.h>
-#include <android/asset_manager_jni.h>
-#include <jni.h>
-
-#include "platform_tools/android/apps/arcore/src/main/cpp/hello_ar_application.h"
-
-#define JNI_METHOD(return_type, method_name) \
- JNIEXPORT return_type JNICALL \
- Java_org_skia_arcore_JniInterface_##method_name
-
-extern "C" {
-
-namespace {
-// maintain a reference to the JVM so we can use it later.
- static JavaVM *g_vm = nullptr;
-
- inline jlong jptr(hello_ar::HelloArApplication *native_hello_ar_application) {
- return reinterpret_cast<intptr_t>(native_hello_ar_application);
- }
-
- inline hello_ar::HelloArApplication *native(jlong ptr) {
- return reinterpret_cast<hello_ar::HelloArApplication *>(ptr);
- }
-
-} // namespace
-
-jint JNI_OnLoad(JavaVM *vm, void *) {
- g_vm = vm;
- return JNI_VERSION_1_6;
-}
-
-JNI_METHOD(jlong, createNativeApplication)
-(JNIEnv *env, jclass, jobject j_asset_manager) {
- AAssetManager *asset_manager = AAssetManager_fromJava(env, j_asset_manager);
- return jptr(new hello_ar::HelloArApplication(asset_manager));
-}
-
-JNI_METHOD(void, destroyNativeApplication)
-(JNIEnv *, jclass, jlong native_application) {
- delete native(native_application);
-}
-
-JNI_METHOD(void, onPause)
-(JNIEnv *, jclass, jlong native_application) {
- native(native_application)->OnPause();
-}
-
-JNI_METHOD(void, onResume)
-(JNIEnv *env, jclass, jlong native_application, jobject context,
- jobject activity) {
- native(native_application)->OnResume(env, context, activity);
-}
-
-JNI_METHOD(void, onGlSurfaceCreated)
-(JNIEnv *, jclass, jlong native_application) {
- native(native_application)->OnSurfaceCreated();
-}
-
-JNI_METHOD(void, onDisplayGeometryChanged)
-(JNIEnv *, jobject, jlong native_application, int display_rotation, int width,
- int height) {
- native(native_application)
- ->OnDisplayGeometryChanged(display_rotation, width, height);
-}
-
-JNI_METHOD(void, onObjectRotationChanged)
-(JNIEnv *, jobject, jlong native_application, int rotation) {
- native(native_application)
- ->OnObjectRotationChanged(rotation);
-}
-
-JNI_METHOD(void, onAction)
-(JNIEnv *, jobject, jlong native_application, jfloat value) {
- native(native_application)->OnAction(value);
-}
-
-JNI_METHOD(void, onGlSurfaceDrawFrame)
-(JNIEnv *, jclass, jlong native_application) {
- native(native_application)->OnDrawFrame();
-}
-
-JNI_METHOD(void, onTouchTranslate)
-(JNIEnv *, jclass, jlong native_application, jfloat x, jfloat y) {
- return native(native_application)->OnTouchTranslate(x, y);
-}
-
-JNI_METHOD(bool, onTouchedFirst)
-(JNIEnv *, jclass, jlong native_application, jfloat x, jfloat y, int drawMode) {
- return native(native_application)->OnTouchedFirst(x, y, drawMode);
-}
-
-JNI_METHOD(void, onTouchedFinal)
-(JNIEnv *, jclass, jlong native_application, int type) {
- native(native_application)->OnTouchedFinal(type);
-}
-
-JNI_METHOD(jboolean, hasDetectedPlanes)
-(JNIEnv *, jclass, jlong native_application) {
- return static_cast<jboolean>(
- native(native_application)->HasDetectedPlanes() ? JNI_TRUE : JNI_FALSE);
-}
-
-JNIEnv *GetJniEnv() {
- JNIEnv *env;
- jint result = g_vm->AttachCurrentThread(&env, nullptr);
- return result == JNI_OK ? env : nullptr;
-}
-
-jclass FindClass(const char *classname) {
- JNIEnv *env = GetJniEnv();
- return env->FindClass(classname);
-}
-
-} // extern "C"
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/jni_interface.h b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/jni_interface.h
deleted file mode 100644
index fe19cfcb858..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/jni_interface.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef C_ARCORE_HELLOE_AR_JNI_INTERFACE_H_
-#define C_ARCORE_HELLOE_AR_JNI_INTERFACE_H_
-
-#include <jni.h>
-/**
- * Helper functions to provide access to Java from C via JNI.
- */
-extern "C" {
-
-// Helper function used to access the jni environment on the current thread.
-// In this sample, no consideration is made for detaching the thread when the
-// thread exits. This can cause memory leaks, so production applications should
-// detach when the thread no longer needs access to the JVM.
-JNIEnv *GetJniEnv();
-
-jclass FindClass(const char *classname);
-} // extern "C"
-#endif
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/pending_anchor.cc b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/pending_anchor.cc
deleted file mode 100644
index 3ff5e609a69..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/pending_anchor.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2018 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "include/core/SkCanvas.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/hello_ar_application.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/plane_renderer.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/util.h"
-
-namespace hello_ar {
- PendingAnchor::PendingAnchor(SkPoint touchLocation) : touchLocation(touchLocation) {}
-
- PendingAnchor::~PendingAnchor() {}
-
- SkPoint PendingAnchor::GetTouchLocation() {
- return touchLocation;
- }
-
- bool PendingAnchor::GetEditMode() {
- return editMode;
- }
-
- ArPlane* PendingAnchor::GetContainingPlane() {
- return containingPlane;
- }
-
- glm::vec4 PendingAnchor::GetAnchorPos(ArSession* arSession) {
- float poseRaw[] = {0, 0, 0, 0, 0, 0, 0};
- ArPose* anchorPose = nullptr;
- ArPose_create(arSession, poseRaw, &anchorPose);
- ArAnchor_getPose(arSession, this->anchor, anchorPose);
- ArPose_getPoseRaw(arSession, anchorPose, poseRaw);
- ArPose_destroy(anchorPose);
- glm::vec4 anchorPos = glm::vec4(poseRaw[4], poseRaw[5], poseRaw[6], 1);
- return anchorPos;
- }
-
- ArAnchor* PendingAnchor::GetArAnchor() {
- return anchor;
- }
-
- void PendingAnchor::SetArAnchor(ArAnchor* anchor) {
- this->anchor = anchor;
- }
-
- void PendingAnchor::SetEditMode(bool editMode) {
- this->editMode = editMode;
- }
-
- void PendingAnchor::SetContainingPlane(ArPlane* plane) {
- this->containingPlane = plane;
- }
-
-
-
-} // namespace hello_ar
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/pending_anchor.h b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/pending_anchor.h
deleted file mode 100644
index c301e1a727c..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/pending_anchor.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2018 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef C_ARCORE_HELLO_AR_PENDING_ANCHOR_H_
-#define C_ARCORE_HELLO_AR_PENDING_ANCHOR_H_
-
-#include "include/gpu/GrBackendSurface.h"
-#include "include/gpu/gl/GrGLTypes.h"
-
-#include "arcore_c_api.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/glm.h"
-
-namespace hello_ar {
- class PendingAnchor {
- public:
- PendingAnchor(SkPoint touchLocation);
- ~PendingAnchor();
-
- SkPoint GetTouchLocation();
- bool GetEditMode();
- ArPlane* GetContainingPlane();
- glm::vec4 GetAnchorPos(ArSession* arSession);
- ArAnchor* GetArAnchor();
-
- void SetArAnchor(ArAnchor* anchor);
- void SetEditMode(bool editMode);
- void SetContainingPlane(ArPlane* plane);
-
- private:
- SkPoint touchLocation;
- bool editMode = false;
- ArAnchor* anchor;
- ArPlane* containingPlane;
- };
-} // namespace hello_ar
-
-#endif
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/plane_renderer.cc b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/plane_renderer.cc
deleted file mode 100644
index b62652db375..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/plane_renderer.cc
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "platform_tools/android/apps/arcore/src/main/cpp/plane_renderer.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/util.h"
-
-namespace hello_ar {
- namespace {
- constexpr char kVertexShader[] = R"(
- precision highp float;
- precision highp int;
- attribute vec3 vertex;
- varying vec2 v_textureCoords;
- varying float v_alpha;
-
- uniform mat4 mvp;
- uniform mat4 model_mat;
- uniform vec3 normal;
-
- void main() {
- // Vertex Z value is used as the alpha in this shader.
- v_alpha = vertex.z;
-
- vec4 local_pos = vec4(vertex.x, 0.0, vertex.y, 1.0);
- gl_Position = mvp * local_pos;
- vec4 world_pos = model_mat * local_pos;
-
- // Construct two vectors that are orthogonal to the normal.
- // This arbitrary choice is not co-linear with either horizontal
- // or vertical plane normals.
- const vec3 arbitrary = vec3(1.0, 1.0, 0.0);
- vec3 vec_u = normalize(cross(normal, arbitrary));
- vec3 vec_v = normalize(cross(normal, vec_u));
-
- // Project vertices in world frame onto vec_u and vec_v.
- v_textureCoords = vec2(
- dot(world_pos.xyz, vec_u), dot(world_pos.xyz, vec_v));
- })";
-
- constexpr char kFragmentShader[] = R"(
- precision highp float;
- precision highp int;
- uniform sampler2D texture;
- uniform vec3 color;
- varying vec2 v_textureCoords;
- varying float v_alpha;
- void main() {
- float r = texture2D(texture, v_textureCoords).r;
- gl_FragColor = vec4(color.xyz, r * v_alpha);
- })";
- } // namespace
-
- void PlaneRenderer::InitializeGlContent(AAssetManager *asset_manager) {
- shader_program_ = util::CreateProgram(kVertexShader, kFragmentShader);
-
- if (!shader_program_) {
- LOGE("Could not create program.");
- }
-
- uniform_mvp_mat_ = glGetUniformLocation(shader_program_, "mvp");
- uniform_texture_ = glGetUniformLocation(shader_program_, "texture");
- uniform_model_mat_ = glGetUniformLocation(shader_program_, "model_mat");
- uniform_normal_vec_ = glGetUniformLocation(shader_program_, "normal");
- uniform_color_ = glGetUniformLocation(shader_program_, "color");
- attri_vertices_ = glGetAttribLocation(shader_program_, "vertex");
-
- glGenTextures(1, &texture_id_);
- glBindTexture(GL_TEXTURE_2D, texture_id_);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- if (!util::LoadPngFromAssetManager(GL_TEXTURE_2D, "models/trigrid.png")) {
- LOGE("Could not load png texture for planes.");
- }
-
- glGenerateMipmap(GL_TEXTURE_2D);
-
- glBindTexture(GL_TEXTURE_2D, 0);
-
- util::CheckGlError("plane_renderer::InitializeGlContent()");
- }
-
- void PlaneRenderer::Draw(const glm::mat4 &projection_mat,
- const glm::mat4 &view_mat, const ArSession *ar_session,
- const ArPlane *ar_plane, const glm::vec3 &color) {
- if (!shader_program_) {
- LOGE("shader_program is null.");
- return;
- }
-
- UpdateForPlane(ar_session, ar_plane);
-
- glUseProgram(shader_program_);
- glDepthMask(GL_FALSE);
-
- glActiveTexture(GL_TEXTURE0);
- glUniform1i(uniform_texture_, 0);
- glBindTexture(GL_TEXTURE_2D, texture_id_);
-
- // Compose final mvp matrix for this plane renderer.
- glUniformMatrix4fv(uniform_mvp_mat_, 1, GL_FALSE,
- glm::value_ptr(projection_mat * view_mat * model_mat_));
-
- glUniformMatrix4fv(uniform_model_mat_, 1, GL_FALSE,
- glm::value_ptr(model_mat_));
- glUniform3f(uniform_normal_vec_, normal_vec_.x, normal_vec_.y, normal_vec_.z);
- glUniform3f(uniform_color_, color.x, color.y, color.z);
-
- glEnableVertexAttribArray(attri_vertices_);
- glVertexAttribPointer(attri_vertices_, 3, GL_FLOAT, GL_FALSE, 0,
- vertices_.data());
-
- glDrawElements(GL_TRIANGLES, triangles_.size(), GL_UNSIGNED_SHORT,
- triangles_.data());
-
- glUseProgram(0);
- glDepthMask(GL_TRUE);
- util::CheckGlError("plane_renderer::Draw()");
- }
-
- void PlaneRenderer::UpdateForPlane(const ArSession *ar_session,
- const ArPlane *ar_plane) {
- // The following code generates a triangle mesh filling a convex polygon,
- // including a feathered edge for blending.
- //
- // The indices shown in the diagram are used in comments below.
- // _______________ 0_______________1
- // | | |4___________5|
- // | | | | | |
- // | | => | | | |
- // | | | | | |
- // | | |7-----------6|
- // --------------- 3---------------2
-
- vertices_.clear();
- triangles_.clear();
-
- int32_t polygon_length;
- ArPlane_getPolygonSize(ar_session, ar_plane, &polygon_length);
-
- if (polygon_length == 0) {
- LOGE("PlaneRenderer::UpdatePlane, no valid plane polygon is found");
- return;
- }
-
- const int32_t vertices_size = polygon_length / 2;
- std::vector<glm::vec2> raw_vertices(vertices_size);
- ArPlane_getPolygon(ar_session, ar_plane,
- glm::value_ptr(raw_vertices.front()));
-
- // Fill vertex 0 to 3. Note that the vertex.xy are used for x and z
- // position. vertex.z is used for alpha. The outter polygon's alpha
- // is 0.
- for (int32_t i = 0; i < vertices_size; ++i) {
- vertices_.push_back(glm::vec3(raw_vertices[i].x, raw_vertices[i].y, 0.0f));
- }
-
- util::ScopedArPose scopedArPose(ar_session);
- ArPlane_getCenterPose(ar_session, ar_plane, scopedArPose.GetArPose());
- ArPose_getMatrix(ar_session, scopedArPose.GetArPose(),
- glm::value_ptr(model_mat_));
- normal_vec_ = util::GetPlaneNormal(ar_session, *scopedArPose.GetArPose());
-
- // Feather distance 0.2 meters.
- const float kFeatherLength = 0.2f;
- // Feather scale over the distance between plane center and vertices.
- const float kFeatherScale = 0.2f;
-
- // Fill vertex 4 to 7, with alpha set to 1.
- for (int32_t i = 0; i < vertices_size; ++i) {
- // Vector from plane center to current point.
- glm::vec2 v = raw_vertices[i];
- const float scale =
- 1.0f - std::min((kFeatherLength / glm::length(v)), kFeatherScale);
- const glm::vec2 result_v = scale * v;
-
- vertices_.push_back(glm::vec3(result_v.x, result_v.y, 1.0f));
- }
-
- const int32_t vertices_length = vertices_.size();
- const int32_t half_vertices_length = vertices_length / 2;
-
- // Generate triangle (4, 5, 6) and (4, 6, 7).
- for (int i = half_vertices_length + 1; i < vertices_length - 1; ++i) {
- triangles_.push_back(half_vertices_length);
- triangles_.push_back(i);
- triangles_.push_back(i + 1);
- }
-
- // Generate triangle (0, 1, 4), (4, 1, 5), (5, 1, 2), (5, 2, 6),
- // (6, 2, 3), (6, 3, 7), (7, 3, 0), (7, 0, 4)
- for (int i = 0; i < half_vertices_length; ++i) {
- triangles_.push_back(i);
- triangles_.push_back((i + 1) % half_vertices_length);
- triangles_.push_back(i + half_vertices_length);
-
- triangles_.push_back(i + half_vertices_length);
- triangles_.push_back((i + 1) % half_vertices_length);
- triangles_.push_back((i + half_vertices_length + 1) % half_vertices_length +
- half_vertices_length);
- }
- }
-
-} // namespace hello_ar
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/plane_renderer.h b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/plane_renderer.h
deleted file mode 100644
index b8fd415f4af..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/plane_renderer.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef C_ARCORE_HELLOE_AR_PLANE_RENDERER_H_
-#define C_ARCORE_HELLOE_AR_PLANE_RENDERER_H_
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <android/asset_manager.h>
-#include <array>
-#include <cstdint>
-#include <cstdlib>
-#include <string>
-#include <vector>
-
-#include "arcore_c_api.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/glm.h"
-
-namespace hello_ar {
-
-// PlaneRenderer renders ARCore plane type.
- class PlaneRenderer {
- public:
- PlaneRenderer() = default;
-
- ~PlaneRenderer() = default;
-
- // Sets up OpenGL state used by the plane renderer. Must be called on the
- // OpenGL thread.
- void InitializeGlContent(AAssetManager *asset_manager);
-
- // Draws the provided plane.
- void Draw(const glm::mat4 &projection_mat, const glm::mat4 &view_mat,
- const ArSession *ar_session, const ArPlane *ar_plane,
- const glm::vec3 &color);
-
- private:
- void UpdateForPlane(const ArSession *ar_session, const ArPlane *ar_plane);
-
- std::vector<glm::vec3> vertices_;
- std::vector<GLushort> triangles_;
- glm::mat4 model_mat_ = glm::mat4(1.0f);
- glm::vec3 normal_vec_ = glm::vec3(0.0f);
-
- GLuint texture_id_;
-
- GLuint shader_program_;
- GLint attri_vertices_;
- GLint uniform_mvp_mat_;
- GLint uniform_texture_;
- GLint uniform_model_mat_;
- GLint uniform_normal_vec_;
- GLint uniform_color_;
- };
-} // namespace hello_ar
-
-#endif // C_ARCORE_HELLOE_AR_PLANE_RENDERER_H_
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/point_cloud_renderer.cc b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/point_cloud_renderer.cc
deleted file mode 100644
index 111e716460f..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/point_cloud_renderer.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "platform_tools/android/apps/arcore/src/main/cpp/point_cloud_renderer.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/util.h"
-
-namespace hello_ar {
- namespace {
- constexpr char kVertexShader[] = R"(
- attribute vec4 vertex;
- uniform mat4 mvp;
- void main() {
- gl_PointSize = 5.0;
- // Pointcloud vertex's w component is confidence value.
- // Not used in renderer.
- gl_Position = mvp * vec4(vertex.xyz, 1.0);
- })";
-
- constexpr char kFragmentShader[] = R"(
- precision lowp float;
- void main() {
- gl_FragColor = vec4(0.1215, 0.7372, 0.8235, 1.0);
- })";
- } // namespace
-
- void PointCloudRenderer::InitializeGlContent() {
- shader_program_ = util::CreateProgram(kVertexShader, kFragmentShader);
-
- CHECK(shader_program_);
-
- attribute_vertices_ = glGetAttribLocation(shader_program_, "vertex");
- uniform_mvp_mat_ = glGetUniformLocation(shader_program_, "mvp");
-
- util::CheckGlError("point_cloud_renderer::InitializeGlContent()");
- }
-
- void PointCloudRenderer::Draw(glm::mat4 mvp_matrix, ArSession *ar_session,
- ArPointCloud *ar_point_cloud) const {
- CHECK(shader_program_);
-
- glUseProgram(shader_program_);
-
- int32_t number_of_points = 0;
- ArPointCloud_getNumberOfPoints(ar_session, ar_point_cloud, &number_of_points);
- if (number_of_points <= 0) {
- return;
- }
-
- const float *point_cloud_data;
- ArPointCloud_getData(ar_session, ar_point_cloud, &point_cloud_data);
-
- glUniformMatrix4fv(uniform_mvp_mat_, 1, GL_FALSE, glm::value_ptr(mvp_matrix));
-
- glEnableVertexAttribArray(attribute_vertices_);
- glVertexAttribPointer(attribute_vertices_, 4, GL_FLOAT, GL_FALSE, 0,
- point_cloud_data);
-
- glDrawArrays(GL_POINTS, 0, number_of_points);
-
- glUseProgram(0);
- util::CheckGlError("PointCloudRenderer::Draw");
- }
-
-} // namespace hello_ar
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/point_cloud_renderer.h b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/point_cloud_renderer.h
deleted file mode 100644
index faba4d3b93f..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/point_cloud_renderer.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef C_ARCORE_HELLOE_AR_POINT_CLOUD_RENDERER_H_
-#define C_ARCORE_HELLOE_AR_POINT_CLOUD_RENDERER_H_
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <cstdlib>
-#include <vector>
-
-#include "arcore_c_api.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/glm.h"
-
-namespace hello_ar {
-
- class PointCloudRenderer {
- public:
- // Default constructor of PointCloudRenderer.
- PointCloudRenderer() = default;
-
- // Default deconstructor of PointCloudRenderer.
- ~PointCloudRenderer() = default;
-
- // Initialize the GL content, needs to be called on GL thread.
- void InitializeGlContent();
-
- // Render the AR point cloud.
- //
- // @param mvp_matrix, the model view projection matrix of point cloud.
- // @param ar_session, the session that is used to query point cloud points
- // from ar_point_cloud.
- // @param ar_point_cloud, point cloud data to for rendering.
- void Draw(glm::mat4 mvp_matrix, ArSession *ar_session,
- ArPointCloud *ar_point_cloud) const;
-
- private:
- GLuint shader_program_;
- GLint attribute_vertices_;
- GLint uniform_mvp_mat_;
- };
-} // namespace hello_ar
-
-#endif // C_ARCORE_HELLOE_AR_POINT_CLOUD_RENDERER_H_
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/util.cc b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/util.cc
deleted file mode 100644
index 945d3da1a42..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/util.cc
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "platform_tools/android/apps/arcore/src/main/cpp/util.h"
-
-#include "include/core/SkMatrix44.h"
-#include <gtx/string_cast.inl>
-#include <sstream>
-#include <string>
-#include <unistd.h>
-
-#include "platform_tools/android/apps/arcore/src/main/cpp/jni_interface.h"
-
-namespace hello_ar {
- namespace util {
-
- void CheckGlError(const char *operation) {
- bool anyError = false;
- for (GLint error = glGetError(); error; error = glGetError()) {
- LOGE("after %s() glError (0x%x)\n", operation, error);
- anyError = true;
- }
- if (anyError) {
- abort();
- }
- }
-
- // Convenience function used in CreateProgram below.
- static GLuint LoadShader(GLenum shader_type, const char *shader_source) {
- GLuint shader = glCreateShader(shader_type);
- if (!shader) {
- return shader;
- }
-
- glShaderSource(shader, 1, &shader_source, nullptr);
- glCompileShader(shader);
- GLint compiled = 0;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
-
- if (!compiled) {
- GLint info_len = 0;
-
- glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
- if (!info_len) {
- return shader;
- }
-
- char *buf = reinterpret_cast<char *>(malloc(info_len));
- if (!buf) {
- return shader;
- }
-
- glGetShaderInfoLog(shader, info_len, nullptr, buf);
- LOGE("hello_ar::util::Could not compile shader %d:\n%s\n", shader_type,
- buf);
- free(buf);
- glDeleteShader(shader);
- shader = 0;
- }
-
- return shader;
- }
-
- GLuint CreateProgram(const char *vertex_source, const char *fragment_source) {
- GLuint vertexShader = LoadShader(GL_VERTEX_SHADER, vertex_source);
- if (!vertexShader) {
- return 0;
- }
-
- GLuint fragment_shader = LoadShader(GL_FRAGMENT_SHADER, fragment_source);
- if (!fragment_shader) {
- return 0;
- }
-
- GLuint program = glCreateProgram();
- if (program) {
- glAttachShader(program, vertexShader);
- CheckGlError("hello_ar::util::glAttachShader");
- glAttachShader(program, fragment_shader);
- CheckGlError("hello_ar::util::glAttachShader");
- glLinkProgram(program);
- GLint link_status = GL_FALSE;
- glGetProgramiv(program, GL_LINK_STATUS, &link_status);
- if (link_status != GL_TRUE) {
- GLint buf_length = 0;
- glGetProgramiv(program, GL_INFO_LOG_LENGTH, &buf_length);
- if (buf_length) {
- char *buf = reinterpret_cast<char *>(malloc(buf_length));
- if (buf) {
- glGetProgramInfoLog(program, buf_length, nullptr, buf);
- LOGE("hello_ar::util::Could not link program:\n%s\n", buf);
- free(buf);
- }
- }
- glDeleteProgram(program);
- program = 0;
- }
- }
- return program;
- }
-
- bool LoadPngFromAssetManager(int target, const std::string &path) {
- JNIEnv *env = GetJniEnv();
-
- // Put all the JNI values in a structure that is statically initalized on the
- // first call to this method. This makes it thread safe in the unlikely case
- // of multiple threads calling this method.
- static struct JNIData {
- jclass helper_class;
- jmethodID load_image_method;
- jmethodID load_texture_method;
- } jniIds = [env]() -> JNIData {
- constexpr char kHelperClassName[] =
- "org/skia/arcore/JniInterface";
- constexpr char kLoadImageMethodName[] = "loadImage";
- constexpr char kLoadImageMethodSignature[] =
- "(Ljava/lang/String;)Landroid/graphics/Bitmap;";
- constexpr char kLoadTextureMethodName[] = "loadTexture";
- constexpr char kLoadTextureMethodSignature[] =
- "(ILandroid/graphics/Bitmap;)V";
- jclass helper_class = FindClass(kHelperClassName);
- if (helper_class) {
- helper_class = static_cast<jclass>(env->NewGlobalRef(helper_class));
- jmethodID load_image_method = env->GetStaticMethodID(
- helper_class, kLoadImageMethodName, kLoadImageMethodSignature);
- jmethodID load_texture_method = env->GetStaticMethodID(
- helper_class, kLoadTextureMethodName, kLoadTextureMethodSignature);
- return {helper_class, load_image_method, load_texture_method};
- }
- LOGE("hello_ar::util::Could not find Java helper class %s",
- kHelperClassName);
- return {};
- }();
-
- if (!jniIds.helper_class) {
- return false;
- }
-
- jstring j_path = env->NewStringUTF(path.c_str());
-
- jobject image_obj = env->CallStaticObjectMethod(
- jniIds.helper_class, jniIds.load_image_method, j_path);
-
- if (j_path) {
- env->DeleteLocalRef(j_path);
- }
-
- env->CallStaticVoidMethod(jniIds.helper_class, jniIds.load_texture_method,
- target, image_obj);
- return true;
- }
-
- void GetTransformMatrixFromPose(ArSession *ar_session,
- const ArPose *ar_pose,
- glm::mat4 *out_model_mat) {
- if (out_model_mat == nullptr) {
- LOGE("util::GetTransformMatrixFromPose model_mat is null.");
- return;
- }
- ArPose_getMatrix(ar_session, ar_pose,
- glm::value_ptr(*out_model_mat));
- }
-
- glm::vec3 GetPlaneNormal(const ArSession *ar_session,
- const ArPose &plane_pose) {
- float plane_pose_raw[7] = {0.f};
- ArPose_getPoseRaw(ar_session, &plane_pose, plane_pose_raw);
- glm::quat plane_quaternion(plane_pose_raw[3], plane_pose_raw[0],
- plane_pose_raw[1], plane_pose_raw[2]);
- // Get normal vector, normal is defined to be positive Y-position in local
- // frame.
- return glm::rotate(plane_quaternion, glm::vec3(0., 1.f, 0.));
- }
-
- float CalculateDistanceToPlane(const ArSession *ar_session,
- const ArPose &plane_pose,
- const ArPose &camera_pose) {
- float plane_pose_raw[7] = {0.f};
- ArPose_getPoseRaw(ar_session, &plane_pose, plane_pose_raw);
- glm::vec3 plane_position(plane_pose_raw[4], plane_pose_raw[5],
- plane_pose_raw[6]);
- glm::vec3 normal = GetPlaneNormal(ar_session, plane_pose);
-
- float camera_pose_raw[7] = {0.f};
- ArPose_getPoseRaw(ar_session, &camera_pose, camera_pose_raw);
- glm::vec3 camera_P_plane(camera_pose_raw[4] - plane_position.x,
- camera_pose_raw[5] - plane_position.y,
- camera_pose_raw[6] - plane_position.z);
- return glm::dot(normal, camera_P_plane);
- }
-
- glm::mat4 GetCameraRotationMatrix(float cameraOutRaw[]) {
- glm::mat4 cameraRotation(1);
- glm::quat cameraQuat = glm::quat(cameraOutRaw[0], cameraOutRaw[1], cameraOutRaw[2],
- cameraOutRaw[3]);
- cameraRotation = glm::toMat4(cameraQuat);
- glm::vec4 temp = cameraRotation[0];
- cameraRotation[0] = cameraRotation[2];
- cameraRotation[2] = temp;
- return cameraRotation;
- }
-
- void GetCameraInfo(ArSession* arSession, ArFrame* arFrame, glm::vec3& cameraPos, glm::mat4& cameraRotation) {
- //Acquire camera
- ArCamera *ar_camera;
- ArFrame_acquireCamera(arSession, arFrame, &ar_camera);
-
- //Get camera pose
- ArPose *camera_pose = nullptr;
- ArPose_create(arSession, nullptr, &camera_pose);
- ArCamera_getDisplayOrientedPose(arSession, ar_camera, camera_pose);
-
- //Get camera raw info
- float outCameraRaw[] = {0, 0, 0, 0, 0, 0, 0};
- ArPose_getPoseRaw(arSession, camera_pose, outCameraRaw);
- ArPose_destroy(camera_pose);
-
- //Write to out variables
- cameraPos = glm::vec3(outCameraRaw[4], outCameraRaw[5], outCameraRaw[6]);
- cameraRotation = util::GetCameraRotationMatrix(outCameraRaw);
-
- //Release camera
- ArCamera_release(ar_camera);
- }
-
- SkMatrix44 GlmMatToSkMat(const glm::mat4 m) {
- SkMatrix44 skMat = SkMatrix44::kIdentity_Constructor;
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- skMat.set(j, i, m[i][j]);
- }
- }
- return skMat;
- }
-
- glm::mat4 SkMatToGlmMat(const SkMatrix44 m) {
- glm::mat4 glmMat(1);
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- glmMat[i][j] = m.get(j, i);
- }
- }
- return glmMat;
- }
-
- void Log4x4Matrix(float raw_matrix[16]) {
- LOGI(
- "%f, %f, %f, %f\n"
- "%f, %f, %f, %f\n"
- "%f, %f, %f, %f\n"
- "%f, %f, %f, %f\n",
- raw_matrix[0], raw_matrix[1], raw_matrix[2], raw_matrix[3], raw_matrix[4],
- raw_matrix[5], raw_matrix[6], raw_matrix[7], raw_matrix[8], raw_matrix[9],
- raw_matrix[10], raw_matrix[11], raw_matrix[12], raw_matrix[13],
- raw_matrix[14], raw_matrix[15]);
- }
-
- void LogGlmMat(glm::mat4 m, char *type) {
- std::string str = glm::to_string(m);
- LOGE("glm Matrix - %s: %s\n", type, str.c_str());
- }
-
- void LogSkMat44(SkMatrix44 m, char *type) {
- LOGE("SkMatrix - %s: [%g, %g, %g, %g] || [%g, %g, %g, %g] || [%g, %g, %g, %g] || [%g, %g, %g, %g] \n",
- type,
- m.get(0, 0), m.get(1, 0), m.get(2, 0), m.get(3, 0),
- m.get(0, 1), m.get(1, 1), m.get(2, 1), m.get(3, 1),
- m.get(0, 2), m.get(1, 2), m.get(2, 2), m.get(3, 2),
- m.get(0, 3), m.get(1, 3), m.get(2, 3), m.get(3, 3)
- );
- }
-
- void LogSkMat(SkMatrix m, char *type) {
- LOGE("SkMatrix - %s: [%g, %g, %g] || [%g, %g, %g] || [%g, %g, %g] \n", type,
- m.get(0), m.get(3), m.get(6),
- m.get(1), m.get(4), m.get(7),
- m.get(2), m.get(5), m.get(8)
- );
- }
-
- void LogOrientation(float rotationDirection, float angleRad, char *type) {
- LOGI("Plane orientation: %s", type);
- LOGI("Cross dotted with zDir:", rotationDirection);
- if (rotationDirection == -1) {
- LOGI("Counter Clockwise %.6f degrees rotation: ", glm::degrees(angleRad));
- } else {
- LOGI("Clockwise %.6f degrees rotation: ", glm::degrees(angleRad));
- }
- }
-
- float Dot(glm::vec3 u, glm::vec3 v) {
- float result = u.x * v.x + u.y * v.y + u.z * v.z;
- return result;
- }
-
- float Magnitude(glm::vec3 u) {
- float result = u.x * u.x + u.y * u.y + u.z * u.z;
- return sqrt(result);
- }
-
- float AngleRad(glm::vec3 u, glm::vec3 v) {
- float dot = util::Dot(u, v);
- float scale = (util::Magnitude(u) * util::Magnitude(v));
- float cosine = dot / scale;
- float acosine = acos(cosine);
- return acosine;
- }
-
- glm::vec3 ProjectOntoPlane(glm::vec3 in, glm::vec3 normal) {
- float dot = util::Dot(in, normal);
- float multiplier = dot / (util::Magnitude(normal) * util::Magnitude(normal));
- glm::vec3 out = in - multiplier * normal;
- return out;
- }
-
- } // namespace util
-} // namespace hello_ar
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/util.h b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/util.h
deleted file mode 100644
index fbd664dbfab..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/cpp/util.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef C_ARCORE_HELLOE_AR_UTIL_H_
-#define C_ARCORE_HELLOE_AR_UTIL_H_
-
-#include "include/core/SkMatrix44.h"
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <android/asset_manager.h>
-#include <android/log.h>
-#include <cstdint>
-#include <cstdlib>
-#include <errno.h>
-#include <jni.h>
-#include <vector>
-
-#include "arcore_c_api.h"
-#include "platform_tools/android/apps/arcore/src/main/cpp/glm.h"
-
-#ifndef LOGI
-#define LOGI(...) \
- __android_log_print(ANDROID_LOG_INFO, "hello_ar_example_c", __VA_ARGS__)
-#endif // LOGI
-
-#ifndef LOGE
-#define LOGE(...) \
- __android_log_print(ANDROID_LOG_ERROR, "hello_ar_example_c", __VA_ARGS__)
-#endif // LOGE
-
-#ifndef CHECK
-#define CHECK(condition) \
- if (!(condition)) { \
- LOGE("*** CHECK FAILED at %s:%d: %s", __FILE__, __LINE__, #condition); \
- abort(); \
- }
-#endif // CHECK
-
-namespace hello_ar {
- // Utilities
- namespace util {
-
- // Provides a scoped allocated instance of Anchor.
- // Can be treated as an ArAnchor*.
- class ScopedArPose {
- public:
- explicit ScopedArPose(const ArSession *session) {
- ArPose_create(session, nullptr, &pose_);
- }
-
- ~ScopedArPose() { ArPose_destroy(pose_); }
-
- ArPose *GetArPose() { return pose_; }
-
- // Delete copy constructors.
- ScopedArPose(const ScopedArPose &) = delete;
-
- void operator=(const ScopedArPose &) = delete;
-
- private:
- ArPose *pose_;
- };
-
- /* GL Utils */
- // Check GL error, and abort if an error is encountered.
- //
- // @param operation, the name of the GL function call.
- void CheckGlError(const char *operation);
-
- // Create a shader program ID.
- //
- // @param vertex_source, the vertex shader source.
- // @param fragment_source, the fragment shader source.
- // @return
- GLuint CreateProgram(const char *vertex_source, const char *fragment_source);
-
- // Load png file from assets folder and then assign it to the OpenGL target.
- // This method must be called from the renderer thread since it will result in
- // OpenGL calls to assign the image to the texture target.
- //
- // @param target, openGL texture target to load the image into.
- // @param path, path to the file, relative to the assets folder.
- // @return true if png is loaded correctly, otherwise false.
- bool LoadPngFromAssetManager(int target, const std::string &path);
-
-
- /* ARCore utils */
- void GetTransformMatrixFromPose(ArSession *ar_session, const ArPose *ar_pose, glm::mat4 *out_model_mat);
-
- // Get the plane's normal from center pose.
- glm::vec3 GetPlaneNormal(const ArSession *ar_session, const ArPose &plane_pose);
-
- // Calculate the normal distance to plane from cameraPose, the given planePose
- // should have y axis parallel to plane's normal, for example plane's center
- // pose or hit test pose.
- float CalculateDistanceToPlane(const ArSession *ar_session, const ArPose &plane_pose, const ArPose &camera_pose);
-
- // Outputs the camera rotation using display orientation
- glm::mat4 GetCameraRotationMatrix(float cameraOutRaw[]);
-
- // Computes camera position and orientation (using GetCameraRotationMatrix)
- void GetCameraInfo(ArSession* arSession, ArFrame* arFrame, glm::vec3& cameraPos, glm::mat4& cameraRotation);
-
- /* Matrix conversion */
- SkMatrix44 GlmMatToSkMat(const glm::mat4 m);
- glm::mat4 SkMatToGlmMat(const SkMatrix44 m);
-
- /* Logging utils */
- //Row major output
- void Log4x4Matrix(float raw_matrix[16]);
-
- //Column major output
- void LogGlmMat(glm::mat4 m, char *type);
- void LogSkMat44(SkMatrix44 m, char *type);
- void LogSkMat(SkMatrix m, char *type);
- void LogOrientation(float rotationDirection, float angleRad, char *type);
-
- /* Vector ops */
- float Dot(glm::vec3 u, glm::vec3 v);
- float Magnitude(glm::vec3 u);
- float AngleRad(glm::vec3 u, glm::vec3 v);
- glm::vec3 ProjectOntoPlane(glm::vec3 in, glm::vec3 normal);
- } // namespace util
-} // namespace hello_ar
-
-#endif // C_ARCORE_HELLOE_AR_UTIL_H_
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/java/org/skia/arcore/CameraPermissionHelper.java b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/java/org/skia/arcore/CameraPermissionHelper.java
deleted file mode 100644
index 3499ec00f30..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/java/org/skia/arcore/CameraPermissionHelper.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.skia.arcore;
-
-import android.Manifest;
-import android.app.Activity;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.net.Uri;
-import android.provider.Settings;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.content.ContextCompat;
-
-/**
- * Helper to ask camera permission.
- */
-public class CameraPermissionHelper {
- private static final String CAMERA_PERMISSION = Manifest.permission.CAMERA;
- private static final int CAMERA_PERMISSION_CODE = 0;
-
- /**
- * Check to see we have the necessary permissions for this app.
- */
- public static boolean hasCameraPermission(Activity activity) {
- return ContextCompat.checkSelfPermission(activity, CAMERA_PERMISSION)
- == PackageManager.PERMISSION_GRANTED;
- }
-
- /**
- * Check to see we have the necessary permissions for this app, and ask for them if we don't.
- */
- public static void requestCameraPermission(Activity activity) {
- ActivityCompat.requestPermissions(
- activity, new String[]{CAMERA_PERMISSION}, CAMERA_PERMISSION_CODE);
- }
-
- /**
- * Check to see if we need to show the rationale for this permission.
- */
- public static boolean shouldShowRequestPermissionRationale(Activity activity) {
- return ActivityCompat.shouldShowRequestPermissionRationale(activity, CAMERA_PERMISSION);
- }
-
- /**
- * Launch Application Setting to grant permission.
- */
- public static void launchPermissionSettings(Activity activity) {
- Intent intent = new Intent();
- intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
- intent.setData(Uri.fromParts("package", activity.getPackageName(), null));
- activity.startActivity(intent);
- }
-}
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/java/org/skia/arcore/HelloArActivity.java b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/java/org/skia/arcore/HelloArActivity.java
deleted file mode 100644
index 73651f51c6e..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/java/org/skia/arcore/HelloArActivity.java
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.skia.arcore;
-
-import android.app.Activity;
-import android.content.Context;
-import android.hardware.display.DisplayManager;
-import android.opengl.GLES20;
-import android.opengl.GLSurfaceView;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.design.widget.Snackbar;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.util.Log;
-import android.view.ActionMode;
-import android.view.ContextMenu;
-import android.view.GestureDetector;
-import android.view.Gravity;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.WindowManager;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.AdapterView;
-import android.widget.EditText;
-import android.widget.PopupMenu;
-import android.widget.Toast;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-/**
- * This is a simple example that shows how to create an augmented reality (AR) application using the
- * ARCore C API.
- */
-public class HelloArActivity extends AppCompatActivity
- implements GLSurfaceView.Renderer, DisplayManager.DisplayListener {
- private static final String TAG = HelloArActivity.class.getSimpleName();
- private static final int SNACKBAR_UPDATE_INTERVAL_MILLIS = 1000; // In milliseconds.
-
- private GLSurfaceView mSurfaceView;
- private Activity activity = null;
- private boolean mViewportChanged = false;
- private int mViewportWidth;
- private int mViewportHeight;
- private View contextView = null;
- private int mCurrentObjectRotation = 0;
- private float mCurrentValue = 0;
- private float X = 0;
- private float Y = 0;
-
- private boolean toEdit = false;
-
- // Opaque native pointer to the native application instance.
- private long mNativeApplication;
- private GestureDetector mGestureDetector;
-
- private Snackbar mLoadingMessageSnackbar;
- private Handler mPlaneStatusCheckingHandler;
- private final Runnable mPlaneStatusCheckingRunnable =
- new Runnable() {
- @Override
- public void run() {
- // The runnable is executed on main UI thread.
- try {
- if (JniInterface.hasDetectedPlanes(mNativeApplication)) {
- if (mLoadingMessageSnackbar != null) {
- mLoadingMessageSnackbar.dismiss();
- }
- mLoadingMessageSnackbar = null;
- } else {
- mPlaneStatusCheckingHandler.postDelayed(
- mPlaneStatusCheckingRunnable, SNACKBAR_UPDATE_INTERVAL_MILLIS);
- }
- } catch (Exception e) {
- Log.e(TAG, e.getMessage());
- }
- }
- };
- private int mDrawMode = -1;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
- setSupportActionBar(myToolbar);
-
- activity = this;
-
- //hide notifications bar
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
-
- mSurfaceView = (GLSurfaceView) findViewById(R.id.surfaceview);
-
- mGestureDetector =
- new GestureDetector(
- this,
- new GestureDetector.SimpleOnGestureListener() {
- @Override
- public boolean onSingleTapUp(final MotionEvent e) {
- toEdit = JniInterface.onTouchedFirst(mNativeApplication, e.getX(), e.getY(), mDrawMode);
-
- Log.i(TAG, "toEdit: " + toEdit);
- X = e.getX();
- Y = e.getY();
- contextView.showContextMenu(e.getX(), e.getY());
- return true;
- }
-
- @Override
- public boolean onScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- Log.i(TAG, "Scrolling!");
- JniInterface.onTouchTranslate(mNativeApplication, e2.getX(), e2.getY());
- return true;
- }
-
- @Override
- public boolean onDown(MotionEvent e) {
- return true;
- }
- });
-
- mSurfaceView.setOnTouchListener(
- new View.OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- return mGestureDetector.onTouchEvent(event);
- }
- });
-
- // Set up renderer.
- mSurfaceView.setPreserveEGLContextOnPause(true);
- mSurfaceView.setEGLContextClientVersion(2);
- mSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0); // Alpha used for plane blending.
- mSurfaceView.setRenderer(this);
- mSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
-
- JniInterface.assetManager = getAssets();
- mNativeApplication = JniInterface.createNativeApplication(getAssets());
-
- mPlaneStatusCheckingHandler = new Handler();
-
- //Floating context menu
- contextView = findViewById(R.id.menuView);
- this.registerForContextMenu(contextView);
- View.OnLongClickListener listener = new View.OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- activity.closeContextMenu();
- return false;
- }
- };
- contextView.setOnLongClickListener(listener);
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
- {
- super.onCreateContextMenu(menu, v, menuInfo);
-
- if (!toEdit) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.draw_menu, menu);
- menu.setHeaderTitle("Draw Options");
- }
-
- v.setClickable(false);
- v.setFocusable(false);
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
- switch (item.getItemId()) {
- case R.id.draw_text:
- JniInterface.onTouchedFinal(mNativeApplication, 0);
- return true;
- case R.id.draw_circle:
- JniInterface.onTouchedFinal(mNativeApplication, 1);
- return true;
- case R.id.draw_rect:
- JniInterface.onTouchedFinal(mNativeApplication, 2);
- return true;
- case R.id.edit_size:
- return true;
- case R.id.edit_text:
- return true;
- default:
- return super.onContextItemSelected(item);
- }
- }
-
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.rotation_mode, menu);
- return true;
- }
-
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.rotation_axis_aligned:
- mCurrentObjectRotation = 0;
- break;
- case R.id.rotation_camera_aligned:
- mCurrentObjectRotation = 1;
- break;
- case R.id.rotation_snap_aligned:
- mCurrentObjectRotation = 2;
- break;
- case R.id.action:
- mCurrentValue = 180;
- JniInterface.onAction(mNativeApplication, mCurrentValue);
- return true;
- default:
- return true;
- }
- JniInterface.onObjectRotationChanged(mNativeApplication, mCurrentObjectRotation);
- return true;
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- // ARCore requires camera permissions to operate. If we did not yet obtain runtime
- // permission on Android M and above, now is a good time to ask the user for it.
- if (!CameraPermissionHelper.hasCameraPermission(this)) {
- CameraPermissionHelper.requestCameraPermission(this);
- return;
- }
-
- JniInterface.onResume(mNativeApplication, getApplicationContext(), this);
- mSurfaceView.onResume();
-
- mLoadingMessageSnackbar =
- Snackbar.make(
- HelloArActivity.this.findViewById(android.R.id.content),
- "Searching for surfaces...",
- Snackbar.LENGTH_INDEFINITE);
- // Set the snackbar background to light transparent black color.
- mLoadingMessageSnackbar.getView().setBackgroundColor(0xbf323232);
- mLoadingMessageSnackbar.show();
- mPlaneStatusCheckingHandler.postDelayed(
- mPlaneStatusCheckingRunnable, SNACKBAR_UPDATE_INTERVAL_MILLIS);
-
- // Listen to display changed events to detect 180° rotation, which does not cause a config
- // change or view resize.
- getSystemService(DisplayManager.class).registerDisplayListener(this, null);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mSurfaceView.onPause();
- JniInterface.onPause(mNativeApplication);
-
- mPlaneStatusCheckingHandler.removeCallbacks(mPlaneStatusCheckingRunnable);
-
- getSystemService(DisplayManager.class).unregisterDisplayListener(this);
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
-
- // Synchronized to avoid racing onDrawFrame.
- synchronized (this) {
- JniInterface.destroyNativeApplication(mNativeApplication);
- mNativeApplication = 0;
- }
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasFocus) {
- super.onWindowFocusChanged(hasFocus);
- if (hasFocus) {
- // Standard Android full-screen functionality.
- getWindow()
- .getDecorView()
- .setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_FULLSCREEN
- | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- }
- }
-
- @Override
- public void onSurfaceCreated(GL10 gl, EGLConfig config) {
- GLES20.glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
- JniInterface.onGlSurfaceCreated(mNativeApplication);
- }
-
- @Override
- public void onSurfaceChanged(GL10 gl, int width, int height) {
- mViewportWidth = width;
- mViewportHeight = height;
- mViewportChanged = true;
- }
-
- @Override
- public void onDrawFrame(GL10 gl) {
- // Synchronized to avoid racing onDestroy.
- synchronized (this) {
- if (mNativeApplication == 0) {
- return;
- }
- if (mViewportChanged) {
- int displayRotation = getWindowManager().getDefaultDisplay().getRotation();
- JniInterface.onDisplayGeometryChanged(
- mNativeApplication, displayRotation, mViewportWidth, mViewportHeight);
- mViewportChanged = false;
- }
- JniInterface.onGlSurfaceDrawFrame(mNativeApplication);
- }
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] results) {
- if (!CameraPermissionHelper.hasCameraPermission(this)) {
- Toast.makeText(this, "Camera permission is needed to run this application", Toast.LENGTH_LONG)
- .show();
- if (!CameraPermissionHelper.shouldShowRequestPermissionRationale(this)) {
- // Permission denied with checking "Do not ask again".
- CameraPermissionHelper.launchPermissionSettings(this);
- }
- finish();
- }
- }
-
- // DisplayListener methods
- @Override
- public void onDisplayAdded(int displayId) {
- }
-
- @Override
- public void onDisplayRemoved(int displayId) {
- }
-
- @Override
- public void onDisplayChanged(int displayId) {
- mViewportChanged = true;
- }
-}
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/java/org/skia/arcore/JniInterface.java b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/java/org/skia/arcore/JniInterface.java
deleted file mode 100644
index 1592bb2a4e4..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/java/org/skia/arcore/JniInterface.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.skia.arcore;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.AssetManager;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.opengl.GLUtils;
-import android.util.Log;
-
-import java.io.IOException;
-
-/**
- * JNI interface to native layer.
- */
-public class JniInterface {
- static {
- System.loadLibrary("hello_ar_native");
- }
-
- private static final String TAG = "JniInterface";
- static AssetManager assetManager;
-
- public static native long createNativeApplication(AssetManager assetManager);
-
- public static native void destroyNativeApplication(long nativeApplication);
-
- public static native void onPause(long nativeApplication);
-
- public static native void onResume(long nativeApplication, Context context, Activity activity);
-
- /**
- * Allocate OpenGL resources for rendering.
- */
- public static native void onGlSurfaceCreated(long nativeApplication);
-
- /**
- * Called on the OpenGL thread before onGlSurfaceDrawFrame when the view port width, height, or
- * display rotation may have changed.
- */
- public static native void onDisplayGeometryChanged(
- long nativeApplication, int displayRotation, int width, int height);
-
- public static native void onObjectRotationChanged(long nativeApplication, int rotation);
-
- public static native void onAction(long nativeApplication, float value);
-
- /**
- * Main render loop, called on the OpenGL thread.
- */
- public static native void onGlSurfaceDrawFrame(long nativeApplication);
-
- /**
- * OnTouch event, called on the OpenGL thread.
- */
-
- public static native void onTouchTranslate(long nativeApplication, float x, float y);
-
- public static native boolean onTouchedFirst(long nativeApplication, float x, float y, int drawMode);
-
- public static native void onTouchedFinal(long nativeApplication, int type);
-
-
- /**
- * Get plane count in current session. Used to disable the "searching for surfaces" snackbar.
- */
- public static native boolean hasDetectedPlanes(long nativeApplication);
-
- public static Bitmap loadImage(String imageName) {
-
- try {
- return BitmapFactory.decodeStream(assetManager.open(imageName));
- } catch (IOException e) {
- Log.e(TAG, "Cannot open image " + imageName);
- return null;
- }
- }
-
- public static void loadTexture(int target, Bitmap bitmap) {
- GLUtils.texImage2D(target, 0, bitmap, 0);
- }
-}
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/drawable-xxhdpi/ic_launcher.png b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/drawable-xxhdpi/ic_launcher.png
deleted file mode 100644
index 3f691da0397..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/drawable-xxhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/layout-xlarge-land/activity_main.xml b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/layout-xlarge-land/activity_main.xml
deleted file mode 100644
index 49457c98028..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/layout-xlarge-land/activity_main.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:background="@android:color/darker_gray"
- android:layout_height="match_parent">
-
- <!-- The navigation drawer that's always open -->
- <ListView android:id="@+id/leftDrawer"
- android:layout_width="240dp"
- android:layout_height="match_parent"
- android:layout_gravity="start"
- android:choiceMode="singleChoice"
- android:divider="@android:color/transparent"
- android:dividerHeight="0dp"
- android:layout_marginRight="5dp"
- android:background="@android:color/background_light"/>
-
- <!-- The main content view -->
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <!-- We use mainLayout for recreating SurfaceView -->
- <LinearLayout
- android:id="@+id/mainLayout"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <SurfaceView
- android:id="@+id/surfaceView"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_centerVertical="true"
- android:layout_centerHorizontal="true" />
- </LinearLayout>
- </RelativeLayout>
-
-</LinearLayout>
-
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/layout/activity_main.xml b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/layout/activity_main.xml
deleted file mode 100644
index c3f1e2a3a22..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/drawerLayout"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <!-- The main content view -->
-
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <View
- android:layout_gravity="center"
- android:id="@+id/menuView"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
- <android.support.v7.widget.Toolbar
- android:id="@+id/my_toolbar"
- android:layout_width="match_parent"
- android:layout_height="?attr/actionBarSize"
- android:background="?attr/colorPrimary"
- android:elevation="4dp"
- android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
- app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
- <EditText
- android:id="@+id/text_box"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:focusable="false"
- android:clickable="false"
- android:visibility="gone"/>
- <android.opengl.GLSurfaceView
- android:id="@+id/surfaceview"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="bottom" />
-
- </LinearLayout>
-
-
-
- </FrameLayout>
-
-</android.support.v4.widget.DrawerLayout>
-
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/layout/state_item.xml b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/layout/state_item.xml
deleted file mode 100644
index 7a7d539d43c..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/layout/state_item.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical" android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:weightSum="1">
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="10dp"
- android:layout_marginLeft="10dp"
- android:layout_marginBottom="0dp"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:text="Name:"
- android:id="@+id/nameText" />
-
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="10dp"
- android:layout_marginLeft="10dp"
- android:layout_marginTop="0dp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:text="Value"
- android:id="@+id/valueText" />
-
- <Spinner
- android:id="@+id/optionSpinner"
- android:paddingTop="0dp"
- android:paddingBottom="0dp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- </Spinner>
-
-</LinearLayout>
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/draw_menu.xml b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/draw_menu.xml
deleted file mode 100644
index 92851804bdd..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/draw_menu.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/draw_text"
- android:title="Draw Text" />
- <item
- android:id="@+id/draw_shape"
- android:title="Draw Shape" >
- <menu>
- <item android:id="@+id/draw_circle"
- android:title="Circle" />
- <item android:id="@+id/draw_rect"
- android:title="Rectangle" />
- </menu>
- </item>
-</menu> \ No newline at end of file
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/edit_menu.xml b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/edit_menu.xml
deleted file mode 100644
index 25f6a1dc02a..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/edit_menu.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/edit_size"
- android:title="Size" />
- <item
- android:id="@+id/edit_text"
- android:title="Text" />
-</menu> \ No newline at end of file
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/rotation_mode.xml b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/rotation_mode.xml
deleted file mode 100644
index bcee4f0fb92..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/rotation_mode.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@+id/rotation_axis_aligned"
- android:title="Plane Axis-Aligned"/>
- <item android:id="@+id/rotation_camera_aligned"
- android:title="Camera-Aligned"/>
- <item android:id="@+id/rotation_snap_aligned"
- android:title="Snap-Aligned"/>
-
- <item android:id="@+id/action"
- android:title="Do Action"/>
-</menu> \ No newline at end of file
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/title.xml b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/title.xml
deleted file mode 100644
index 57d04ef143a..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/menu/title.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-
- <item
- android:id="@+id/action_left"
- android:icon="@android:drawable/ic_media_previous"
- android:showAsAction="always"/>
-
- <item android:id="@+id/action_right"
- android:icon="@android:drawable/ic_media_next"
- android:showAsAction="always"/>
-
-</menu>
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/values/integers.xml b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/values/integers.xml
deleted file mode 100644
index d3da8e7ca5d..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/values/integers.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <integer name="value_tag_key">1</integer>
-</resources> \ No newline at end of file
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/values/strings.xml b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/values/strings.xml
deleted file mode 100644
index 8b7a8ad7403..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright 2017 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources>
- <string name="app_name">HelloAR C</string>
-</resources>
diff --git a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/values/styles.xml b/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/values/styles.xml
deleted file mode 100644
index 3a71bd32b5f..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/arcore/src/main/res/values/styles.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<!--
- Copyright 2017 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources>
-
- <!--
- Base application theme, dependent on API level. This theme is replaced
- by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
- -->
- <style name="AppBaseTheme" parent="android:Theme.Light">
- <!--
- Theme customizations available in newer API levels can go in
- res/values-vXX/styles.xml, while customizations related to
- backward-compatibility can go here.
- -->
- </style>
-
- <!-- Application theme. -->
- <style name="AppTheme" parent="AppBaseTheme">
- <!-- All customizations that are NOT specific to a particular API-level can go here. -->
- </style>
-
-</resources>
diff --git a/chromium/third_party/skia/platform_tools/android/apps/gradle/wrapper/gradle-wrapper.properties b/chromium/third_party/skia/platform_tools/android/apps/gradle/wrapper/gradle-wrapper.properties
index 9a8e388de9d..8d6ab56fd31 100644
--- a/chromium/third_party/skia/platform_tools/android/apps/gradle/wrapper/gradle-wrapper.properties
+++ b/chromium/third_party/skia/platform_tools/android/apps/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Thu Oct 04 10:41:31 EDT 2018
+#Wed Jun 24 16:43:49 UTC 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
diff --git a/chromium/third_party/skia/platform_tools/android/apps/settings.gradle b/chromium/third_party/skia/platform_tools/android/apps/settings.gradle
index e42c0d4163b..29732f3ec39 100644
--- a/chromium/third_party/skia/platform_tools/android/apps/settings.gradle
+++ b/chromium/third_party/skia/platform_tools/android/apps/settings.gradle
@@ -1,5 +1,5 @@
include ':viewer'
include ':skqp'
-include ':arcore' //must build out directory first: bin/gn gen out/arm64 --args='ndk="NDKPATH" target_cpu="ABI" is_component_build=true'
include ':skar_java'
-include ':skottie' \ No newline at end of file
+include ':skottie'
+include ':skottie:skottielib'
diff --git a/chromium/third_party/skia/platform_tools/android/apps/skottie/build.gradle b/chromium/third_party/skia/platform_tools/android/apps/skottie/build.gradle
index 1346a2f9afe..c7a4ad4604e 100644
--- a/chromium/third_party/skia/platform_tools/android/apps/skottie/build.gradle
+++ b/chromium/third_party/skia/platform_tools/android/apps/skottie/build.gradle
@@ -7,21 +7,20 @@
apply plugin: 'com.android.application'
dependencies {
- implementation 'com.android.support:support-v13:23.3.0'
- implementation 'com.android.support:appcompat-v7:23.3.0'
+ implementation project("skottielib")
+ implementation 'androidx.appcompat:appcompat:1.1.0'
}
android {
- compileSdkVersion 23
+ compileSdkVersion 28
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
flavorDimensions "tier"
defaultConfig {
- applicationId "org.skia.skottie"
- minSdkVersion 23
- targetSdkVersion 23
+ minSdkVersion 19
+ targetSdkVersion 28
versionCode 1
versionName "1.0"
signingConfig signingConfigs.debug
@@ -29,7 +28,15 @@ android {
flavorDimensions "base"
sourceSets.main.jni.srcDirs = [] //disable automatic ndk-build call
sourceSets.main.jniLibs.srcDir "src/main/libs"
- productFlavors { universal{}; arm {}; arm64 {}; x86 {}; x64 {}; arm64vulkan{}; }
- setupSkiaLibraryBuild(project, applicationVariants, "libskottie_android")
+ // When building from Android Studio, ensure that local variables are set:
+ // sdk.dir=[sdk file path]
+ // depot_tools.dir=[depot tools file path]
+ // x86.out.dir=[out file for x86]
+ // x64.out.dir=[out file for x64]
+ // arm64.out.dir=[out file for xarm64]
+ // arm.out.dir=[out file for arm]
+
+ productFlavors { arm {}; arm64 {}; x86 {}; x64 {}; arm64vulkan{}; }
+
}
diff --git a/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/build.gradle b/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/build.gradle
new file mode 100644
index 00000000000..29eab4816d3
--- /dev/null
+++ b/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/build.gradle
@@ -0,0 +1,36 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 29
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ buildToolsVersion "29.0.3"
+
+ defaultConfig {
+ minSdkVersion 19
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+ }
+
+ // When building from Android Studio, ensure that local variables are set:
+ // sdk.dir=[sdk file path]
+ // depot_tools.dir=[depot tools file path]
+ // x86.out.dir=[out file for x86]
+ // x64.out.dir=[out file for x64]
+ // arm64.out.dir=[out file for xarm64]
+ // arm.out.dir=[out file for arm]
+
+ sourceSets.main.jniLibs.srcDir "src/main/libs"
+ flavorDimensions "base"
+ productFlavors { arm {}; arm64 {}; x86 {}; x64 {}; arm64vulkan{}; }
+ setupSkiaLibraryBuild(project, libraryVariants, "libskottie_android")
+
+}
+
+dependencies {
+ implementation 'androidx.appcompat:appcompat:1.1.0'
+
+}
diff --git a/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/AndroidManifest.xml b/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/AndroidManifest.xml
new file mode 100644
index 00000000000..135d0d8be0f
--- /dev/null
+++ b/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.skia.skottielib" />
diff --git a/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/cpp/native-lib.cpp b/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/cpp/native-lib.cpp
index 5dd7f61a759..5e384c72b42 100644
--- a/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/cpp/native-lib.cpp
+++ b/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/cpp/native-lib.cpp
@@ -29,7 +29,6 @@
#include <GLES3/gl3.h>
#include <android/trace.h>
-#include "platform_tools/android/apps/skottie/src/main/cpp/JavaInputStreamAdaptor.h"
#define STENCIL_BUFFER_SIZE 8
@@ -59,6 +58,17 @@ struct SkottieRunner {
sk_sp<GrContext> mGrContext;
};
+static JavaVM* sJVM = nullptr;
+
+static void release_global_jni_ref(const void* /*data*/, void* context) {
+ JNIEnv* env;
+ if (sJVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+ SK_ABORT("Attempting to release a JNI ref on a thread without a JVM attached.");
+ }
+ jobject obj = reinterpret_cast<jobject>(context);
+ env->DeleteGlobalRef(obj);
+}
+
extern "C" JNIEXPORT jlong
JNICALL
Java_org_skia_skottie_SkottieRunner_nCreateProxy(JNIEnv *env, jclass clazz) {
@@ -104,15 +114,31 @@ struct SkottieAnimation {
extern "C" JNIEXPORT jlong
JNICALL
-Java_org_skia_skottie_SkottieRunner_00024SkottieAnimationImpl_nCreateProxy(JNIEnv *env, jobject clazz,
- jlong runner, jobject is,
- jbyteArray storage) {
+Java_org_skia_skottie_SkottieRunner_00024SkottieAnimationImpl_nCreateProxy(JNIEnv *env,
+ jobject clazz,
+ jlong runner,
+ jobject bufferObj) {
if (!runner) {
return 0;
}
SkottieRunner *skottieRunner = reinterpret_cast<SkottieRunner*>(runner);
- std::unique_ptr<SkStream> stream(CopyJavaInputStream(env, is, storage));
+
+ const void* buffer = env->GetDirectBufferAddress(bufferObj);
+ jlong bufferSize = env->GetDirectBufferCapacity(bufferObj);
+ if (buffer == nullptr || bufferSize <= 0) {
+ return 0;
+ }
+
+ env->GetJavaVM(&sJVM);
+ jobject bufferRef = env->NewGlobalRef(bufferObj);
+ if (bufferRef == nullptr) {
+ return 0;
+ }
+
+ sk_sp<SkData> data(SkData::MakeWithProc(buffer, bufferSize, release_global_jni_ref,
+ reinterpret_cast<void*>(bufferRef)));
+ std::unique_ptr<SkStream> stream = SkMemoryStream::Make(data);
if (!stream.get()) {
// Cannot create a stream
return 0;
diff --git a/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/java/org/skia/skottie/SkottieAnimation.java b/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/java/org/skia/skottie/SkottieAnimation.java
index 4280e69d004..0c4e8d0be11 100644
--- a/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/java/org/skia/skottie/SkottieAnimation.java
+++ b/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/java/org/skia/skottie/SkottieAnimation.java
@@ -1,7 +1,7 @@
package org.skia.skottie;
import android.graphics.drawable.Animatable;
-import android.support.annotation.FloatRange;
+import androidx.annotation.FloatRange;
public interface SkottieAnimation extends Animatable {
/**
diff --git a/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/java/org/skia/skottie/SkottieApplication.java b/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/java/org/skia/skottie/SkottieApplication.java
index cd3418081f2..cd3418081f2 100644
--- a/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/java/org/skia/skottie/SkottieApplication.java
+++ b/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/java/org/skia/skottie/SkottieApplication.java
diff --git a/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/java/org/skia/skottie/SkottieRunner.java b/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/java/org/skia/skottie/SkottieRunner.java
index ebcd748aa9f..416650beb05 100644
--- a/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/java/org/skia/skottie/SkottieRunner.java
+++ b/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/java/org/skia/skottie/SkottieRunner.java
@@ -16,7 +16,13 @@ import android.util.Log;
import android.view.Choreographer;
import android.view.TextureView;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -262,8 +268,6 @@ public class SkottieRunner {
private int mSurfaceWidth = 0;
private int mSurfaceHeight = 0;
private long mNativeProxy;
- private InputStream mInputStream;
- private byte[] mTempStorage;
private long mDuration; // duration in ms of the animation
private float mProgress; // animation progress in the range of 0.0f to 1.0f
private long mAnimationStartTime; // time in System.nanoTime units, when started
@@ -277,11 +281,41 @@ public class SkottieRunner {
view.setSurfaceTextureListener(this);
}
+ private ByteBuffer convertToByteBuffer(InputStream is) throws IOException {
+ if (is instanceof FileInputStream) {
+ FileChannel fileChannel = ((FileInputStream)is).getChannel();
+ return fileChannel.map(FileChannel.MapMode.READ_ONLY,
+ fileChannel.position(), fileChannel.size());
+ }
+
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ byte[] tmpStorage = new byte[4096];
+ int bytesRead;
+ while ((bytesRead = is.read(tmpStorage, 0, tmpStorage.length)) != -1) {
+ byteStream.write(tmpStorage, 0, bytesRead);
+ }
+
+ byteStream.flush();
+ tmpStorage = byteStream.toByteArray();
+
+ ByteBuffer buffer = ByteBuffer.allocateDirect(tmpStorage.length);
+ buffer.order(ByteOrder.nativeOrder());
+ buffer.put(tmpStorage, 0, tmpStorage.length);
+ return buffer.asReadOnlyBuffer();
+ }
+
private void init(SurfaceTexture surfaceTexture, InputStream is) {
- mTempStorage = new byte[16 * 1024];
- mInputStream = is;
+
+ ByteBuffer byteBuffer;
+ try {
+ byteBuffer = convertToByteBuffer(is);
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "failed to read input stream", e);
+ return;
+ }
+
long proxy = SkottieRunner.getInstance().getNativeProxy();
- mNativeProxy = nCreateProxy(proxy, mInputStream, mTempStorage);
+ mNativeProxy = nCreateProxy(proxy, byteBuffer);
mSurfaceTexture = surfaceTexture;
mDuration = nGetDuration(mNativeProxy);
mProgress = 0f;
@@ -499,7 +533,7 @@ public class SkottieRunner {
}
- private native long nCreateProxy(long runner, InputStream is, byte[] storage);
+ private native long nCreateProxy(long runner, ByteBuffer data);
private native void nDeleteProxy(long nativeProxy);
private native void nDrawFrame(long nativeProxy, int width, int height,
boolean wideColorGamut, float progress);
diff --git a/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/java/org/skia/skottie/SkottieView.java b/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/java/org/skia/skottie/SkottieView.java
index 30602ea76bc..30602ea76bc 100644
--- a/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/java/org/skia/skottie/SkottieView.java
+++ b/chromium/third_party/skia/platform_tools/android/apps/skottie/skottielib/src/main/java/org/skia/skottie/SkottieView.java
diff --git a/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/cpp/JavaInputStreamAdaptor.cpp b/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/cpp/JavaInputStreamAdaptor.cpp
deleted file mode 100644
index caeb85917c1..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/cpp/JavaInputStreamAdaptor.cpp
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include "include/core/SkTypes.h"
-#include "platform_tools/android/apps/skottie/src/main/cpp/JavaInputStreamAdaptor.h"
-
-static jclass findClassCheck(JNIEnv* env, const char classname[]) {
- jclass clazz = env->FindClass(classname);
- SkASSERT(!env->ExceptionCheck());
- return clazz;
-}
-
-static jmethodID getMethodIDCheck(JNIEnv* env, jclass clazz,
- const char methodname[], const char type[]) {
- jmethodID id = env->GetMethodID(clazz, methodname, type);
- SkASSERT(!env->ExceptionCheck());
- return id;
-}
-
-static jmethodID gInputStream_readMethodID;
-static jmethodID gInputStream_skipMethodID;
-
-static JNIEnv* get_env_or_die(JavaVM* jvm) {
- JNIEnv* env;
- if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- char errorMessage[256];
- sprintf(errorMessage, "Failed to get JNIEnv for JavaVM: %p", jvm);
- SK_ABORT(errorMessage);
- }
- return env;
-}
-
-/**
- * Wrapper for a Java InputStream.
- */
-class JavaInputStreamAdaptor : public SkStream {
- JavaInputStreamAdaptor(JavaVM* jvm, jobject js, jbyteArray ar, jint capacity,
- bool swallowExceptions)
- : fJvm(jvm)
- , fJavaInputStream(js)
- , fJavaByteArray(ar)
- , fCapacity(capacity)
- , fBytesRead(0)
- , fIsAtEnd(false)
- , fSwallowExceptions(swallowExceptions) {}
-
-public:
- static JavaInputStreamAdaptor* Create(JNIEnv* env, jobject js, jbyteArray ar,
- bool swallowExceptions) {
- JavaVM* jvm;
- if (env->GetJavaVM(&jvm) != JNI_OK) {
- SK_ABORT("Failed to get JavaVM");
- }
-
- js = env->NewGlobalRef(js);
- if (!js) {
- return nullptr;
- }
-
- ar = (jbyteArray) env->NewGlobalRef(ar);
- if (!ar) {
- env->DeleteGlobalRef(js);
- return nullptr;
- }
-
- jint capacity = env->GetArrayLength(ar);
- return new JavaInputStreamAdaptor(jvm, js, ar, capacity, swallowExceptions);
- }
-
- ~JavaInputStreamAdaptor() override {
- auto* env = get_env_or_die(fJvm);
- env->DeleteGlobalRef(fJavaInputStream);
- env->DeleteGlobalRef(fJavaByteArray);
- }
-
- size_t read(void* buffer, size_t size) override {
- auto* env = get_env_or_die(fJvm);
- if (!fSwallowExceptions && checkException(env)) {
- // Just in case the caller did not clear from a previous exception.
- return 0;
- }
- if (NULL == buffer) {
- if (0 == size) {
- return 0;
- } else {
- /* InputStream.skip(n) can return <=0 but still not be at EOF
- If we see that value, we need to call read(), which will
- block if waiting for more data, or return -1 at EOF
- */
- size_t amountSkipped = 0;
- do {
- size_t amount = this->doSkip(size - amountSkipped, env);
- if (0 == amount) {
- char tmp;
- amount = this->doRead(&tmp, 1, env);
- if (0 == amount) {
- // if read returned 0, we're at EOF
- fIsAtEnd = true;
- break;
- }
- }
- amountSkipped += amount;
- } while (amountSkipped < size);
- return amountSkipped;
- }
- }
- return this->doRead(buffer, size, env);
- }
-
- bool isAtEnd() const override { return fIsAtEnd; }
-
-private:
- size_t doRead(void* buffer, size_t size, JNIEnv* env) {
- size_t bytesRead = 0;
- // read the bytes
- do {
- jint requested = 0;
- if (size > static_cast<size_t>(fCapacity)) {
- requested = fCapacity;
- } else {
- // This is safe because requested is clamped to (jint)
- // fCapacity.
- requested = static_cast<jint>(size);
- }
-
- jint n = env->CallIntMethod(fJavaInputStream,
- gInputStream_readMethodID, fJavaByteArray, 0, requested);
- if (checkException(env)) {
- SkDebugf("---- read threw an exception\n");
- return bytesRead;
- }
-
- if (n < 0) { // n == 0 should not be possible, see InputStream read() specifications.
- fIsAtEnd = true;
- break; // eof
- }
-
- env->GetByteArrayRegion(fJavaByteArray, 0, n,
- reinterpret_cast<jbyte*>(buffer));
- if (checkException(env)) {
- SkDebugf("---- read:GetByteArrayRegion threw an exception\n");
- return bytesRead;
- }
-
- buffer = (void*)((char*)buffer + n);
- bytesRead += n;
- size -= n;
- fBytesRead += n;
- } while (size != 0);
-
- return bytesRead;
- }
-
- size_t doSkip(size_t size, JNIEnv* env) {
- jlong skipped = env->CallLongMethod(fJavaInputStream,
- gInputStream_skipMethodID, (jlong)size);
- if (checkException(env)) {
- SkDebugf("------- skip threw an exception\n");
- return 0;
- }
- if (skipped < 0) {
- skipped = 0;
- }
-
- return (size_t)skipped;
- }
-
- bool checkException(JNIEnv* env) {
- if (!env->ExceptionCheck()) {
- return false;
- }
-
- env->ExceptionDescribe();
- if (fSwallowExceptions) {
- env->ExceptionClear();
- }
-
- // There is no way to recover from the error, so consider the stream
- // to be at the end.
- fIsAtEnd = true;
-
- return true;
- }
-
- JavaVM* fJvm;
- jobject fJavaInputStream;
- jbyteArray fJavaByteArray;
- const jint fCapacity;
- size_t fBytesRead;
- bool fIsAtEnd;
- const bool fSwallowExceptions;
-};
-
-static SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream, jbyteArray storage,
- bool swallowExceptions = true) {
- return JavaInputStreamAdaptor::Create(env, stream, storage, swallowExceptions);
-}
-
-static SkMemoryStream* adaptor_to_mem_stream(SkStream* stream) {
- SkASSERT(stream != NULL);
- size_t bufferSize = 4096;
- size_t streamLen = 0;
- size_t len;
- char* data = (char*)sk_malloc_throw(bufferSize);
-
- while ((len = stream->read(data + streamLen,
- bufferSize - streamLen)) != 0) {
- streamLen += len;
- if (streamLen == bufferSize) {
- bufferSize *= 2;
- data = (char*)sk_realloc_throw(data, bufferSize);
- }
- }
- data = (char*)sk_realloc_throw(data, streamLen);
-
- SkMemoryStream* streamMem = new SkMemoryStream();
- streamMem->setMemoryOwned(data, streamLen);
- return streamMem;
-}
-
-SkStreamRewindable* CopyJavaInputStream(JNIEnv* env, jobject stream,
- jbyteArray storage) {
- std::unique_ptr<SkStream> adaptor(CreateJavaInputStreamAdaptor(env, stream, storage));
- if (NULL == adaptor.get()) {
- return NULL;
- }
- return adaptor_to_mem_stream(adaptor.get());
-}
-
-
-extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
- JNIEnv* env;
- if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- return -1;
- }
-
- jclass inputStream_Clazz = findClassCheck(env, "java/io/InputStream");
- gInputStream_readMethodID = getMethodIDCheck(env, inputStream_Clazz, "read", "([BII)I");
- gInputStream_skipMethodID = getMethodIDCheck(env, inputStream_Clazz, "skip", "(J)J");
-
- return JNI_VERSION_1_6;
-}
diff --git a/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/cpp/JavaInputStreamAdaptor.h b/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/cpp/JavaInputStreamAdaptor.h
deleted file mode 100644
index 8cfc2a4ef77..00000000000
--- a/chromium/third_party/skia/platform_tools/android/apps/skottie/src/main/cpp/JavaInputStreamAdaptor.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "include/core/SkStream.h"
-#include "include/private/SkMalloc.h"
-#include <jni.h>
-
-SkStreamRewindable* CopyJavaInputStream(JNIEnv* env, jobject stream,
- jbyteArray storage);
diff --git a/chromium/third_party/skia/public.bzl b/chromium/third_party/skia/public.bzl
index 95fee11b93e..539de115762 100644
--- a/chromium/third_party/skia/public.bzl
+++ b/chromium/third_party/skia/public.bzl
@@ -2,39 +2,27 @@
# Skylark macros
################################################################################
-is_bazel = not hasattr(native, "genmpm")
+def skia_select(conditions, results):
+ """select() for conditions provided externally.
-def portable_select(select_dict, bazel_condition, default_condition):
- """Replaces select() with a Bazel-friendly wrapper.
+ Instead of {"conditionA": resultA, "conditionB": resultB},
+ this takes two arrays, ["conditionA", "conditionB"] and [resultA, resultB].
- Args:
- select_dict: Dictionary in the same format as select().
- Returns:
- If Blaze platform, returns select() using select_dict.
- If Bazel platform, returns dependencies for condition
- bazel_condition, or empty list if none specified.
- """
- if is_bazel:
- return select_dict.get(bazel_condition, select_dict[default_condition])
- else:
- return select(select_dict)
+ This allows the exact targets of the conditions to be provided externally while
+ the results can live here, hiding the structure of those conditions in Google3.
-def skia_select(conditions, results):
- """Replaces select() for conditions [UNIX, ANDROID, IOS, WASM]
+ Maybe this is too much paranoia?
Args:
- conditions: [CONDITION_UNIX, CONDITION_ANDROID, CONDITION_IOS, CONDITION_WASM]
- results: [RESULT_UNIX, RESULT_ANDROID, RESULT_IOS, RESULT_WASM]
+ conditions: [CONDITION_UNIX, CONDITION_ANDROID, CONDITION_IOS, CONDITION_WASM, ...]
+ results: [RESULT_UNIX, RESULT_ANDROID, RESULT_IOS, RESULT_WASM, ....]
Returns:
- The result matching the platform condition.
+ The result matching the active condition.
"""
- if len(conditions) != 4 or len(results) != 4:
- fail("Must provide exactly 4 conditions and 4 results")
-
selector = {}
- for i in range(4):
+ for i in range(len(conditions)):
selector[conditions[i]] = results[i]
- return portable_select(selector, conditions[2], conditions[0])
+ return select(selector)
def skia_glob(srcs):
"""Replaces glob() with a version that accepts a struct.
@@ -261,9 +249,6 @@ BASE_SRCS_ALL = struct(
# Only used to regenerate the lexer
"src/sksl/lex/*",
-
- # Atlas text
- "src/atlastext/*",
],
)
@@ -416,6 +401,44 @@ PORTS_SRCS_WASM = struct(
],
)
+GL_SRCS_FUCHSIA = struct(
+ include = [
+ "src/gpu/gl/GrGLMakeNativeInterface_none.cpp",
+ ],
+ exclude = [],
+)
+PORTS_SRCS_FUCHSIA = struct(
+ include = [
+ "src/ports/**/*.cpp",
+ "src/ports/**/*.h",
+ ],
+ exclude = [
+ "src/ports/*FontConfig*",
+ #"src/ports/*FreeType*",
+ "src/ports/*WIC*",
+ "src/ports/*CG*",
+ "src/ports/*android*",
+ "src/ports/*chromium*",
+ "src/ports/*fontconfig*",
+ "src/ports/*mac*",
+ "src/ports/*mozalloc*",
+ "src/ports/*nacl*",
+ "src/ports/*win*",
+ #"src/ports/SkDebug_stdio.cpp",
+ #"src/ports/SkFontMgr_custom.cpp",
+ "src/ports/SkFontMgr_custom_directory.cpp",
+ "src/ports/SkFontMgr_custom_directory_factory.cpp",
+ "src/ports/SkFontMgr_custom_embedded.cpp",
+ "src/ports/SkFontMgr_custom_embedded_factory.cpp",
+ "src/ports/SkFontMgr_custom_empty.cpp",
+ "src/ports/SkFontMgr_custom_empty_factory.cpp",
+ #"src/ports/SkFontMgr_empty_factory.cpp",
+ "src/ports/SkFontMgr_fontconfig_factory.cpp",
+ #"src/ports/SkFontMgr_fuchsia.cpp",
+ "src/ports/SkImageGenerator_none.cpp",
+ ],
+)
+
def base_srcs():
return skia_glob(BASE_SRCS_ALL)
@@ -427,6 +450,7 @@ def ports_srcs(os_conditions):
skia_glob(PORTS_SRCS_ANDROID),
skia_glob(PORTS_SRCS_IOS),
skia_glob(PORTS_SRCS_WASM),
+ skia_glob(PORTS_SRCS_FUCHSIA),
],
)
@@ -438,6 +462,7 @@ def gl_srcs(os_conditions):
skia_glob(GL_SRCS_ANDROID),
skia_glob(GL_SRCS_IOS),
skia_glob(GL_SRCS_WASM),
+ skia_glob(GL_SRCS_FUCHSIA),
],
)
@@ -576,7 +601,6 @@ DM_SRCS_ALL = struct(
"tests/FontMgrFontConfigTest.cpp", # FontConfig-only.
"tests/SkParagraphTest.cpp", # Skipping tests for now.
"tests/skia_test.cpp", # Old main.
- "tools/gpu/atlastext/*",
"tools/gpu/d3d/*",
"tools/gpu/dawn/*",
"tools/gpu/gl/angle/*",
@@ -601,8 +625,9 @@ def dm_srcs(os_conditions):
[
["tests/FontMgrFontConfigTest.cpp"],
["tests/FontMgrAndroidParserTest.cpp"],
- [],
- [],
+ [], # iOS
+ [], # WASM
+ [], # Fuchsia
],
)
@@ -624,12 +649,11 @@ def DM_ARGS(asan):
################################################################################
def base_copts(os_conditions):
- return skia_select(
+ return ["-Wno-implicit-fallthrough"] + skia_select(
os_conditions,
[
# UNIX
[
- "-Wno-implicit-fallthrough", # Some intentional fallthrough.
# Internal use of deprecated methods. :(
"-Wno-deprecated-declarations",
# TODO(kjlubick)
@@ -637,19 +661,13 @@ def base_copts(os_conditions):
],
# ANDROID
[
- "-Wno-implicit-fallthrough", # Some intentional fallthrough.
# 'GrResourceCache' declared with greater visibility than the
# type of its field 'GrResourceCache::fPurgeableQueue'... bogus.
"-Wno-error=attributes",
],
- # IOS
- [
- "-Wno-implicit-fallthrough", # Some intentional fallthrough.
- ],
- # WASM
- [
- "-Wno-implicit-fallthrough", # Some intentional fallthrough.
- ],
+ [], # iOS
+ [], # wasm
+ [], # Fuchsia
],
)
@@ -716,6 +734,15 @@ def base_defines(os_conditions):
"SK_FORCE_8_BYTE_ALIGNMENT",
"SKNX_NO_SIMD",
],
+ # FUCHSIA
+ [
+ "SK_BUILD_FOR_UNIX",
+ "SK_CODEC_DECODES_PNG",
+ "SK_CODEC_DECODES_WEBP",
+ "SK_ENCODE_PNG",
+ "SK_ENCODE_WEBP",
+ "SK_R32_SHIFT=16",
+ ],
],
)
@@ -729,8 +756,7 @@ def base_linkopts(os_conditions):
] + skia_select(
os_conditions,
[
- # UNIX
- [],
+ [], # Unix
# ANDROID
[
"-lEGL",
@@ -744,8 +770,8 @@ def base_linkopts(os_conditions):
"-framework ImageIO",
"-framework MobileCoreServices",
],
- # WASM
- [],
+ [], # wasm
+ [], # Fuchsia
],
)
@@ -822,6 +848,18 @@ def skottie_lib_srcs():
)
################################################################################
+## skottie_utils
+################################################################################
+
+SKOTTIE_UTILS_HDRS = [
+ "modules/skottie/utils/SkottieUtils.h",
+]
+
+SKOTTIE_UTILS_SRCS = [
+ "modules/skottie/utils/SkottieUtils.cpp",
+]
+
+################################################################################
## skottie_shaper
################################################################################
diff --git a/chromium/third_party/skia/resources/images/lut_identity.png b/chromium/third_party/skia/resources/images/lut_identity.png
new file mode 100644
index 00000000000..00985acb442
--- /dev/null
+++ b/chromium/third_party/skia/resources/images/lut_identity.png
Binary files differ
diff --git a/chromium/third_party/skia/resources/images/lut_sepia.png b/chromium/third_party/skia/resources/images/lut_sepia.png
new file mode 100644
index 00000000000..364fe8d5415
--- /dev/null
+++ b/chromium/third_party/skia/resources/images/lut_sepia.png
Binary files differ
diff --git a/chromium/third_party/skia/resources/images/mandrill_sepia.png b/chromium/third_party/skia/resources/images/mandrill_sepia.png
new file mode 100644
index 00000000000..a345f448414
--- /dev/null
+++ b/chromium/third_party/skia/resources/images/mandrill_sepia.png
Binary files differ
diff --git a/chromium/third_party/skia/resources/skottie/skottie-auto-orient.json b/chromium/third_party/skia/resources/skottie/skottie-auto-orient.json
new file mode 100644
index 00000000000..0583f17b98c
--- /dev/null
+++ b/chromium/third_party/skia/resources/skottie/skottie-auto-orient.json
@@ -0,0 +1 @@
+{"v":"5.6.10","fr":60,"ip":0,"op":601,"w":500,"h":500,"nm":"auto orient","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sr","sy":1,"d":1,"pt":{"a":0,"k":3,"ix":3},"p":{"a":0,"k":[0,0],"ix":4},"r":{"a":0,"k":-30,"ix":5},"ir":{"a":0,"k":5,"ix":6},"is":{"a":0,"k":0,"ix":8},"or":{"a":0,"k":10,"ix":7},"os":{"a":0,"k":0,"ix":9},"ix":1,"nm":"Polystar Path 1","mn":"ADBE Vector Shape - Star","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"sr","sy":1,"d":1,"pt":{"a":0,"k":3,"ix":3},"p":{"a":0,"k":[-10,0],"ix":4},"r":{"a":0,"k":-30,"ix":5},"ir":{"a":0,"k":10,"ix":6},"is":{"a":0,"k":0,"ix":8},"or":{"a":0,"k":20,"ix":7},"os":{"a":0,"k":0,"ix":9},"ix":1,"nm":"Polystar Path 1","mn":"ADBE Vector Shape - Star","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.98059129715,0.110340073705,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":601,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[125,125,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":601,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"precomp","parent":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[0,-50,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":150,"s":[100,0.001,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":300,"s":[0,50,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":450,"s":[-100,0.001,0],"to":[0,0,0],"ti":[0,0,0]},{"t":600,"s":[0,-50,0]}],"ix":2},"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":500,"h":500,"ip":0,"op":601,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"shape 1","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,-50],[-100,0],[0,50],[100,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":601,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":3,"nm":"Null 2","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[375,125,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":601,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":0,"nm":"precomp","parent":4,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[0,-50,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":150,"s":[100,0.001,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":300,"s":[0,50,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":450,"s":[-100,0.001,0],"to":[0,0,0],"ti":[0,0,0]},{"t":600,"s":[0,-50,0]}],"ix":2},"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":1,"w":500,"h":500,"ip":0,"op":601,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"shape 2","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0,-50],[-100,0],[0,50],[100,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":601,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null 3","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,375,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":601,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":0,"nm":"precomp","parent":7,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[0,-50,0],"to":[81.667,2.333,0],"ti":[0,-16.667,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":150,"s":[100,0.001,0],"to":[0,16.667,0],"ti":[73.339,-0.448,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":300,"s":[0,50,0],"to":[-74.33,0.455,0],"ti":[0,16.667,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":450,"s":[-100,0.001,0],"to":[0,-16.667,0],"ti":[-84.667,4.333,0]},{"t":600,"s":[0,-50,0]}],"ix":2},"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":1,"w":500,"h":500,"ip":0,"op":601,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"shape 3","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[37.268,0],[0,-37.268],[-37.268,0],[0,37.268]],"o":[[-37.268,0],[0,37.268],[37.268,0],[0,-37.268]],"v":[[0,-50],[-100,0],[0,50],[100,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":601,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":1,"nm":"White Solid 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"sw":500,"sh":500,"sc":"#ffffff","ip":0,"op":601,"st":0,"bm":0}],"markers":[]} \ No newline at end of file
diff --git a/chromium/third_party/skia/samplecode/Sample.cpp b/chromium/third_party/skia/samplecode/Sample.cpp
index 9fa836be1bb..10fac8203d9 100644
--- a/chromium/third_party/skia/samplecode/Sample.cpp
+++ b/chromium/third_party/skia/samplecode/Sample.cpp
@@ -51,7 +51,7 @@ void Sample::draw(SkCanvas* canvas) {
#if SK_SUPPORT_GPU
// Ensure the GrContext doesn't combine GrDrawOps across draw loops.
if (GrContext* context = canvas->getGrContext()) {
- context->flush();
+ context->flushAndSubmit();
}
#endif
diff --git a/chromium/third_party/skia/samplecode/Sample3D.cpp b/chromium/third_party/skia/samplecode/Sample3D.cpp
index 51e3baeb4dc..0ee2c4cb5bd 100644
--- a/chromium/third_party/skia/samplecode/Sample3D.cpp
+++ b/chromium/third_party/skia/samplecode/Sample3D.cpp
@@ -356,20 +356,20 @@ class SampleBump3D : public SampleCubeBase {
SkRRect fRR;
public:
- SampleBump3D() : SampleCubeBase(kShowLightDome) {}
+ SampleBump3D() : SampleCubeBase(Flags(kCanRunOnCPU | kShowLightDome)) {}
SkString name() override { return SkString("bump3d"); }
void onOnceBeforeDraw() override {
fRR = SkRRect::MakeRectXY({20, 20, 380, 380}, 50, 50);
auto img = GetResourceAsImage("images/brickwork-texture.jpg");
- fImgShader = img->makeShader(SkMatrix::MakeScale(2, 2));
+ fImgShader = img->makeShader(SkMatrix::Scale(2, 2));
img = GetResourceAsImage("images/brickwork_normal-map.jpg");
- fBmpShader = img->makeShader(SkMatrix::MakeScale(2, 2));
+ fBmpShader = img->makeShader(SkMatrix::Scale(2, 2));
const char code[] = R"(
- in fragmentProcessor color_map;
- in fragmentProcessor normal_map;
+ in shader color_map;
+ in shader normal_map;
layout (marker=local_to_world) uniform float4x4 localToWorld;
layout (marker=normals(local_to_world)) uniform float4x4 localToWorldAdjInv;
diff --git a/chromium/third_party/skia/samplecode/SampleAAGeometry.cpp b/chromium/third_party/skia/samplecode/SampleAAGeometry.cpp
index bc708ea8be0..07e7285d468 100644
--- a/chromium/third_party/skia/samplecode/SampleAAGeometry.cpp
+++ b/chromium/third_party/skia/samplecode/SampleAAGeometry.cpp
@@ -278,6 +278,7 @@ static void set_path_verb(int index, SkPath::Verb v, SkPath* path, SkScalar w) {
switch (v) {
case SkPath::kConic_Verb:
weight = w;
+ [[fallthrough]];
case SkPath::kQuad_Verb:
pts[2] = pts[1];
pts[1].fX = (pts[0].fX + pts[2].fX) / 2;
@@ -303,6 +304,7 @@ static void set_path_verb(int index, SkPath::Verb v, SkPath* path, SkScalar w) {
break;
case SkPath::kConic_Verb:
weight = w;
+ [[fallthrough]];
case SkPath::kQuad_Verb:
break;
case SkPath::kCubic_Verb: {
@@ -325,6 +327,7 @@ static void set_path_verb(int index, SkPath::Verb v, SkPath* path, SkScalar w) {
break;
case SkPath::kConic_Verb:
weight = w;
+ [[fallthrough]];
case SkPath::kQuad_Verb: {
SkDCubic dCubic;
dCubic.set(pts);
diff --git a/chromium/third_party/skia/samplecode/SampleAnimatedImage.cpp b/chromium/third_party/skia/samplecode/SampleAnimatedImage.cpp
index da6ac28caa9..1ca7ac1ef3e 100644
--- a/chromium/third_party/skia/samplecode/SampleAnimatedImage.cpp
+++ b/chromium/third_party/skia/samplecode/SampleAnimatedImage.cpp
@@ -104,11 +104,10 @@ class SampleAnimatedImage : public Sample {
switch (uni) {
case kPauseKey:
fRunning = !fRunning;
- if (fImage->isFinished()) {
- // fall through
- } else {
+ if (!fImage->isFinished()) {
return true;
}
+ [[fallthrough]];
case kResetKey:
fImage->reset();
fCurrentTime = fLastWallTime;
diff --git a/chromium/third_party/skia/samplecode/SampleBackdropBounds.cpp b/chromium/third_party/skia/samplecode/SampleBackdropBounds.cpp
index d16d0b9911f..67ac714fc7c 100644
--- a/chromium/third_party/skia/samplecode/SampleBackdropBounds.cpp
+++ b/chromium/third_party/skia/samplecode/SampleBackdropBounds.cpp
@@ -76,7 +76,7 @@ public:
toGlobal = SkMatrix::I();
layerMatrix = ctm;
} else if (ctm.decomposeScale(&scale, &toGlobal)) {
- layerMatrix = SkMatrix::MakeScale(scale.fWidth, scale.fHeight);
+ layerMatrix = SkMatrix::Scale(scale.fWidth, scale.fHeight);
} else {
toGlobal = ctm;
layerMatrix = SkMatrix::I();
diff --git a/chromium/third_party/skia/samplecode/SampleCCPRGeometry.cpp b/chromium/third_party/skia/samplecode/SampleCCPRGeometry.cpp
index f70039a1d44..23061f6df4c 100644
--- a/chromium/third_party/skia/samplecode/SampleCCPRGeometry.cpp
+++ b/chromium/third_party/skia/samplecode/SampleCCPRGeometry.cpp
@@ -14,7 +14,6 @@
#include "include/core/SkPath.h"
#include "samplecode/Sample.h"
#include "src/core/SkRectPriv.h"
-#include "src/gpu/GrClip.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrMemoryPool.h"
@@ -198,8 +197,7 @@ void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
auto ccbuff = GrRenderTargetContext::Make(
ctx, GrColorType::kAlpha_F16, nullptr, SkBackingFit::kApprox, {width, height});
SkASSERT(ccbuff);
- ccbuff->clear(nullptr, SK_PMColor4fTRANSPARENT,
- GrRenderTargetContext::CanClearFullscreen::kYes);
+ ccbuff->clear(SK_PMColor4fTRANSPARENT);
ccbuff->priv().testingOnly_addDrawOp(pool->allocate<DrawCoverageCountOp>(this));
// Visualize coverage count in main canvas.
@@ -209,7 +207,7 @@ void CCPRGeometryView::onDrawContent(SkCanvas* canvas) {
paint.addColorFragmentProcessor(
std::make_unique<VisualizeCoverageCountFP>());
paint.setPorterDuffXPFactory(SkBlendMode::kSrcOver);
- rtc->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
+ rtc->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(),
SkRect::MakeIWH(this->width(), this->height()));
// Add label.
diff --git a/chromium/third_party/skia/samplecode/SampleClip.cpp b/chromium/third_party/skia/samplecode/SampleClip.cpp
index 74af4ae49d5..014d03453c0 100644
--- a/chromium/third_party/skia/samplecode/SampleClip.cpp
+++ b/chromium/third_party/skia/samplecode/SampleClip.cpp
@@ -505,7 +505,7 @@ class HalfPlaneView3 : public SampleCameraView {
void onOnceBeforeDraw() override {
fPath = make_path();
fShader = GetResourceAsImage("images/mandrill_128.png")
- ->makeShader(SkMatrix::MakeScale(3, 3));
+ ->makeShader(SkMatrix::Scale(3, 3));
}
bool onChar(SkUnichar uni) override {
diff --git a/chromium/third_party/skia/samplecode/SampleCowboy.cpp b/chromium/third_party/skia/samplecode/SampleCowboy.cpp
index 6ba3177f8c3..492550891ac 100644
--- a/chromium/third_party/skia/samplecode/SampleCowboy.cpp
+++ b/chromium/third_party/skia/samplecode/SampleCowboy.cpp
@@ -61,12 +61,12 @@ private:
void onDrawContent(SkCanvas* canvas) override {
if (fDom) {
- canvas->setMatrix(SkMatrix::MakeScale(3));
+ canvas->setMatrix(SkMatrix::Scale(3, 3));
canvas->clipRect(SkRect::MakeLTRB(0, 0, 400, 400));
switch (fState) {
case kZoomIn:
fDelta += 0.2f;
- canvas->concat(SkMatrix::MakeScale(fDelta));
+ canvas->scale(fDelta, fDelta);
break;
case kScroll:
if (fAnimationLoop > kAnimationIterations/2) {
@@ -74,12 +74,12 @@ private:
} else {
fDelta -= 80.f;
}
- canvas->concat(SkMatrix::MakeScale(fDelta));
+ canvas->scale(fDelta, fDelta);
canvas->translate(fDelta, 0);
break;
case kZoomOut:
fDelta += 0.2f;
- canvas->concat(SkMatrix::MakeScale(fDelta));
+ canvas->scale(fDelta, fDelta);
break;
}
diff --git a/chromium/third_party/skia/samplecode/SampleFatBits.cpp b/chromium/third_party/skia/samplecode/SampleFatBits.cpp
index f1dcd295b47..7f1ef613222 100644
--- a/chromium/third_party/skia/samplecode/SampleFatBits.cpp
+++ b/chromium/third_party/skia/samplecode/SampleFatBits.cpp
@@ -382,7 +382,7 @@ public:
fPts[0].set(1, 1);
fPts[1].set(5, 4);
fPts[2].set(2, 6);
- SkMatrix::MakeScale(SkIntToScalar(fZoom)).mapPoints(fPts, 3);
+ SkMatrix::Scale(fZoom, fZoom).mapPoints(fPts, 3);
fIsRect = false;
}
diff --git a/chromium/third_party/skia/samplecode/SampleFitCubicToCircle.cpp b/chromium/third_party/skia/samplecode/SampleFitCubicToCircle.cpp
new file mode 100644
index 00000000000..84042e56899
--- /dev/null
+++ b/chromium/third_party/skia/samplecode/SampleFitCubicToCircle.cpp
@@ -0,0 +1,257 @@
+/*
+ * 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 "samplecode/Sample.h"
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkFont.h"
+#include "include/core/SkPaint.h"
+#include "include/core/SkPath.h"
+#include <tuple>
+
+// Math constants are not always defined.
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338327950288
+#endif
+
+#ifndef M_SQRT2
+#define M_SQRT2 1.41421356237309504880168872420969808
+#endif
+
+constexpr static int kCenterX = 300;
+constexpr static int kCenterY = 325;
+constexpr static int kRadius = 250;
+
+// This sample fits a cubic to the arc between two interactive points on a circle. It also finds the
+// T-coordinate of max error, and outputs it and its value in pixels. (It turns out that max error
+// always occurs at T=0.21132486540519.)
+//
+// Press 'E' to iteratively cut the arc in half and report the improvement in max error after each
+// halving. (It turns out that max error improves by exactly 64x on every halving.)
+class SampleFitCubicToCircle : public Sample {
+ SkString name() override { return SkString("FitCubicToCircle"); }
+ void onOnceBeforeDraw() override { this->fitCubic(); }
+ void fitCubic();
+ void onDrawContent(SkCanvas*) override;
+ Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) override;
+ bool onClick(Sample::Click*) override;
+ bool onChar(SkUnichar) override;
+
+ // Coordinates of two points on the unit circle. These are the two endpoints of the arc we fit.
+ double fEndptsX[2] = {0, 1};
+ double fEndptsY[2] = {-1, 0};
+
+ // Fitted cubic and info, set by fitCubic().
+ double fControlLength; // Length of (p1 - p0) and/or (p3 - p2) in unit circle space.
+ double fMaxErrorT; // T value where the cubic diverges most from the true arc.
+ std::array<double, 4> fCubicX; // Screen space cubic control points.
+ std::array<double, 4> fCubicY;
+ double fMaxError; // Max error (in pixels) between the cubic and the screen-space arc.
+ double fTheta; // Angle of the arc. This is only used for informational purposes.
+ SkTArray<SkString> fInfoStrings;
+
+ class Click;
+};
+
+// Fits a cubic to an arc on the unit circle with endpoints (x0, y0) and (x1, y1). Using the
+// following 3 constraints, we arrive at the formula used in the method:
+//
+// 1) The endpoints and tangent directions at the endpoints must match the arc.
+// 2) The cubic must be symmetric (i.e., length(p1 - p0) == length(p3 - p2)).
+// 3) The height of the cubic must match the height of the arc.
+//
+// Returns the "control length", or length of (p1 - p0) and/or (p3 - p2).
+static float fit_cubic_to_unit_circle(double x0, double y0, double x1, double y1,
+ std::array<double, 4>* X, std::array<double, 4>* Y) {
+ constexpr static double kM = -4.0/3;
+ constexpr static double kA = 4*M_SQRT2/3;
+ double d = x0*x1 + y0*y1;
+ double c = (std::sqrt(1 + d) * kM + kA) / std::sqrt(1 - d);
+ *X = {x0, x0 - y0*c, x1 + y1*c, x1};
+ *Y = {y0, y0 + x0*c, y1 - x1*c, y1};
+ return c;
+}
+
+static double lerp(double x, double y, double T) {
+ return x + T*(y - x);
+}
+
+// Evaluates the cubic and 1st and 2nd derivatives at T.
+static std::tuple<double, double, double> eval_cubic(double x[], double T) {
+ // Use De Casteljau's algorithm for better accuracy and stability.
+ double ab = lerp(x[0], x[1], T);
+ double bc = lerp(x[1], x[2], T);
+ double cd = lerp(x[2], x[3], T);
+ double abc = lerp(ab, bc, T);
+ double bcd = lerp(bc, cd, T);
+ double abcd = lerp(abc, bcd, T);
+ return {abcd, 3 * (bcd - abc) /*1st derivative.*/, 6 * (cd - 2*bc + ab) /*2nd derivative.*/};
+}
+
+// Uses newton-raphson convergence to find the point where the provided cubic diverges most from the
+// unit circle. i.e., the point where the derivative of error == 0. For error we use:
+//
+// error = x^2 + y^2 - 1
+// error' = 2xx' + 2yy'
+// error'' = 2xx'' + 2yy'' + 2x'^2 + 2y'^2
+//
+double find_max_error_T(double cubicX[4], double cubicY[4]) {
+ constexpr static double kInitialT = .25;
+ double T = kInitialT;
+ for (int i = 0; i < 64; ++i) {
+ auto [x, dx, ddx] = eval_cubic(cubicX, T);
+ auto [y, dy, ddy] = eval_cubic(cubicY, T);
+ double dError = 2*(x*dx + y*dy);
+ double ddError = 2*(x*ddx + y*ddy + dx*dx + dy*dy);
+ T -= dError / ddError;
+ }
+ return T;
+}
+
+void SampleFitCubicToCircle::fitCubic() {
+ fInfoStrings.reset();
+
+ std::array<double, 4> X, Y;
+ // "Control length" is the length of (p1 - p0) and/or (p3 - p2) in unit circle space.
+ fControlLength = fit_cubic_to_unit_circle(fEndptsX[0], fEndptsY[0], fEndptsX[1], fEndptsY[1],
+ &X, &Y);
+ fInfoStrings.push_back().printf("control length=%0.14f", fControlLength);
+
+ fMaxErrorT = find_max_error_T(X.data(), Y.data());
+ fInfoStrings.push_back().printf("max error T=%0.14f", fMaxErrorT);
+
+ for (int i = 0; i < 4; ++i) {
+ fCubicX[i] = X[i] * kRadius + kCenterX;
+ fCubicY[i] = Y[i] * kRadius + kCenterY;
+ }
+ double errX = std::get<0>(eval_cubic(fCubicX.data(), fMaxErrorT)) - kCenterX;
+ double errY = std::get<0>(eval_cubic(fCubicY.data(), fMaxErrorT)) - kCenterY;
+ fMaxError = std::sqrt(errX*errX + errY*errY) - kRadius;
+ fInfoStrings.push_back().printf("max error=%.5gpx", fMaxError);
+
+ fTheta = std::atan2(fEndptsY[1], fEndptsX[1]) - std::atan2(fEndptsY[0], fEndptsX[0]);
+ fTheta = std::abs(fTheta * 180/M_PI);
+ if (fTheta > 180) {
+ fTheta = 360 - fTheta;
+ }
+ fInfoStrings.push_back().printf("(theta=%.2f)", fTheta);
+
+ SkDebugf("\n");
+ for (const SkString& infoString : fInfoStrings) {
+ SkDebugf("%s\n", infoString.c_str());
+ }
+}
+
+void SampleFitCubicToCircle::onDrawContent(SkCanvas* canvas) {
+ canvas->clear(SK_ColorBLACK);
+
+ SkPaint circlePaint;
+ circlePaint.setColor(0x80ffffff);
+ circlePaint.setStyle(SkPaint::kStroke_Style);
+ circlePaint.setStrokeWidth(0);
+ circlePaint.setAntiAlias(true);
+ canvas->drawArc(SkRect::MakeXYWH(kCenterX - kRadius, kCenterY - kRadius, kRadius * 2,
+ kRadius * 2), 0, 360, false, circlePaint);
+
+ SkPaint cubicPaint;
+ cubicPaint.setColor(SK_ColorGREEN);
+ cubicPaint.setStyle(SkPaint::kStroke_Style);
+ cubicPaint.setStrokeWidth(10);
+ cubicPaint.setAntiAlias(true);
+ SkPath cubicPath;
+ cubicPath.moveTo(fCubicX[0], fCubicY[0]);
+ cubicPath.cubicTo(fCubicX[1], fCubicY[1], fCubicX[2], fCubicY[2], fCubicX[3], fCubicY[3]);
+ canvas->drawPath(cubicPath, cubicPaint);
+
+ SkPaint endpointsPaint;
+ endpointsPaint.setColor(SK_ColorBLUE);
+ endpointsPaint.setStrokeWidth(8);
+ endpointsPaint.setAntiAlias(true);
+ SkPoint points[2] = {{(float)fCubicX[0], (float)fCubicY[0]},
+ {(float)fCubicX[3], (float)fCubicY[3]}};
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, points, endpointsPaint);
+
+ SkPaint textPaint;
+ textPaint.setColor(SK_ColorWHITE);
+ constexpr static float kInfoTextSize = 16;
+ SkFont font(nullptr, kInfoTextSize);
+ int infoY = 10 + kInfoTextSize;
+ for (const SkString& infoString : fInfoStrings) {
+ canvas->drawString(infoString.c_str(), 10, infoY, font, textPaint);
+ infoY += kInfoTextSize * 3/2;
+ }
+}
+
+class SampleFitCubicToCircle::Click : public Sample::Click {
+public:
+ Click(int ptIdx) : fPtIdx(ptIdx) {}
+
+ void doClick(SampleFitCubicToCircle* that) {
+ double dx = fCurr.fX - kCenterX;
+ double dy = fCurr.fY - kCenterY;
+ double l = std::sqrt(dx*dx + dy*dy);
+ that->fEndptsX[fPtIdx] = dx/l;
+ that->fEndptsY[fPtIdx] = dy/l;
+ if (that->fEndptsX[0] * that->fEndptsY[1] - that->fEndptsY[0] * that->fEndptsX[1] < 0) {
+ std::swap(that->fEndptsX[0], that->fEndptsX[1]);
+ std::swap(that->fEndptsY[0], that->fEndptsY[1]);
+ fPtIdx = 1 - fPtIdx;
+ }
+ that->fitCubic();
+ }
+
+private:
+ int fPtIdx;
+};
+
+Sample::Click* SampleFitCubicToCircle::onFindClickHandler(SkScalar x, SkScalar y,
+ skui::ModifierKey) {
+ double dx0 = x - fCubicX[0];
+ double dy0 = y - fCubicY[0];
+ double dx3 = x - fCubicX[3];
+ double dy3 = y - fCubicY[3];
+ if (dx0*dx0 + dy0*dy0 < dx3*dx3 + dy3*dy3) {
+ return new Click(0);
+ } else {
+ return new Click(1);
+ }
+}
+
+bool SampleFitCubicToCircle::onClick(Sample::Click* click) {
+ Click* myClick = (Click*)click;
+ myClick->doClick(this);
+ return true;
+}
+
+bool SampleFitCubicToCircle::onChar(SkUnichar unichar) {
+ if (unichar == 'E') {
+ constexpr static double kMaxErrorT = 0.21132486540519; // Always the same.
+ // Split the arc in half until error =~0, and report the improvement after each halving.
+ double lastError = -1;
+ for (double theta = fTheta; lastError != 0; theta /= 2) {
+ double rads = theta * M_PI/180;
+ std::array<double, 4> X, Y;
+ fit_cubic_to_unit_circle(1, 0, std::cos(rads), std::sin(rads), &X, &Y);
+ auto [x, dx, ddx] = eval_cubic(X.data(), kMaxErrorT);
+ auto [y, dy, ddy] = eval_cubic(Y.data(), kMaxErrorT);
+ double error = std::sqrt(x*x + y*y) * kRadius - kRadius;
+ if ((float)error <= 0) {
+ error = 0;
+ }
+ SkDebugf("%6.2f degrees: error= %10.5gpx", theta, error);
+ if (lastError > 0) {
+ SkDebugf(" (%17.14fx improvement)", lastError / error);
+ }
+ SkDebugf("\n");
+ lastError = error;
+ }
+ return true;
+ }
+ return false;
+}
+
+DEF_SAMPLE(return new SampleFitCubicToCircle;)
diff --git a/chromium/third_party/skia/samplecode/SampleLayers.cpp b/chromium/third_party/skia/samplecode/SampleLayers.cpp
index 74de654c429..420caadbf05 100644
--- a/chromium/third_party/skia/samplecode/SampleLayers.cpp
+++ b/chromium/third_party/skia/samplecode/SampleLayers.cpp
@@ -206,7 +206,7 @@ protected:
SkPaint paint;
paint.setAlpha(0xCC);
- canvas->saveLayer({ &bounds, &paint, fFilter.get(), nullptr, nullptr, 0 });
+ canvas->saveLayer(SkCanvas::SaveLayerRec(&bounds, &paint, fFilter.get(), 0));
canvas->restore();
}
diff --git a/chromium/third_party/skia/samplecode/SamplePathText.cpp b/chromium/third_party/skia/samplecode/SamplePathText.cpp
index a8b65e34da7..b8927b9df23 100644
--- a/chromium/third_party/skia/samplecode/SamplePathText.cpp
+++ b/chromium/third_party/skia/samplecode/SamplePathText.cpp
@@ -30,6 +30,7 @@ public:
for (Glyph& glyph : fGlyphs) {
glyph.reset(fRand, this->width(), this->height());
}
+ fGlyphAnimator->reset(&fRand, this->width(), this->height());
}
void onOnceBeforeDraw() final {
@@ -49,43 +50,30 @@ public:
fGlyphs[i].init(fRand, p);
}
- this->INHERITED::onOnceBeforeDraw();
+ this->Sample::onOnceBeforeDraw();
this->reset();
}
- void onSizeChange() final { this->INHERITED::onSizeChange(); this->reset(); }
+ void onSizeChange() final { this->Sample::onSizeChange(); this->reset(); }
SkString name() override { return SkString(this->getName()); }
- bool onChar(SkUnichar unichar) override {
- if (unichar == 'X') {
- fDoClip = !fDoClip;
- return true;
- }
- return false;
+ bool onChar(SkUnichar) override;
+
+ bool onAnimate(double nanos) final {
+ return fGlyphAnimator->animate(nanos, this->width(), this->height());
}
void onDrawContent(SkCanvas* canvas) override {
if (fDoClip) {
SkPath deviceSpaceClipPath = fClipPath;
- deviceSpaceClipPath.transform(SkMatrix::MakeScale(this->width(), this->height()));
+ deviceSpaceClipPath.transform(SkMatrix::Scale(this->width(), this->height()));
canvas->save();
canvas->clipPath(deviceSpaceClipPath, SkClipOp::kDifference, true);
canvas->clear(SK_ColorBLACK);
canvas->restore();
canvas->clipPath(deviceSpaceClipPath, SkClipOp::kIntersect, true);
}
- this->drawGlyphs(canvas);
- }
-
- virtual void drawGlyphs(SkCanvas* canvas) {
- for (Glyph& glyph : fGlyphs) {
- SkAutoCanvasRestore acr(canvas, true);
- canvas->translate(glyph.fPosition.x(), glyph.fPosition.y());
- canvas->scale(glyph.fZoom, glyph.fZoom);
- canvas->rotate(glyph.fSpin);
- canvas->translate(-glyph.fMidpt.x(), -glyph.fMidpt.y());
- canvas->drawPath(glyph.fPath, glyph.fPaint);
- }
+ fGlyphAnimator->draw(canvas);
}
protected:
@@ -101,12 +89,36 @@ protected:
SkPoint fMidpt;
};
- Glyph fGlyphs[kNumPaths];
- SkRandom fRand{25};
- SkPath fClipPath = ToolUtils::make_star(SkRect{0, 0, 1, 1}, 11, 3);
- bool fDoClip = false;
+ class GlyphAnimator {
+ public:
+ GlyphAnimator(Glyph* glyphs) : fGlyphs(glyphs) {}
+ virtual void reset(SkRandom*, int screenWidth, int screenHeight) {}
+ virtual bool animate(double nanos, int screenWidth, int screenHeight) { return false; }
+ virtual void draw(SkCanvas* canvas) {
+ for (int i = 0; i < kNumPaths; ++i) {
+ Glyph& glyph = fGlyphs[i];
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->translate(glyph.fPosition.x(), glyph.fPosition.y());
+ canvas->scale(glyph.fZoom, glyph.fZoom);
+ canvas->rotate(glyph.fSpin);
+ canvas->translate(-glyph.fMidpt.x(), -glyph.fMidpt.y());
+ canvas->drawPath(glyph.fPath, glyph.fPaint);
+ }
+ }
+ virtual ~GlyphAnimator() {}
+
+ protected:
+ Glyph* const fGlyphs;
+ };
+
+ class MovingGlyphAnimator;
+ class WavyGlyphAnimator;
- typedef Sample INHERITED;
+ Glyph fGlyphs[kNumPaths];
+ SkRandom fRand{25};
+ SkPath fClipPath = ToolUtils::make_star(SkRect{0, 0, 1, 1}, 11, 3);
+ bool fDoClip = false;
+ std::unique_ptr<GlyphAnimator> fGlyphAnimator = std::make_unique<GlyphAnimator>(fGlyphs);
};
void PathText::Glyph::init(SkRandom& rand, const SkPath& path) {
@@ -130,48 +142,46 @@ void PathText::Glyph::reset(SkRandom& rand, int w, int h) {
////////////////////////////////////////////////////////////////////////////////////////////////////
// Text from paths with animated transformation matrices.
-class MovingPathText : public PathText {
+class PathText::MovingGlyphAnimator : public PathText::GlyphAnimator {
public:
- const char* getName() const override { return "MovingPathText"; }
-
- MovingPathText()
- : fFrontMatrices(kNumPaths)
- , fBackMatrices(kNumPaths) {
+ MovingGlyphAnimator(Glyph* glyphs)
+ : GlyphAnimator(glyphs)
+ , fFrontMatrices(kNumPaths)
+ , fBackMatrices(kNumPaths) {
}
- ~MovingPathText() override {
+ ~MovingGlyphAnimator() override {
fBackgroundAnimationTask.wait();
}
- void reset() override {
- const SkScalar screensize = static_cast<SkScalar>(std::max(this->width(), this->height()));
- this->INHERITED::reset();
+ void reset(SkRandom* rand, int screenWidth, int screenHeight) override {
+ const SkScalar screensize = static_cast<SkScalar>(std::max(screenWidth, screenHeight));
for (auto& v : fVelocities) {
for (SkScalar* d : {&v.fDx, &v.fDy}) {
- SkScalar t = pow(fRand.nextF(), 3);
- *d = ((1 - t) / 60 + t / 10) * (fRand.nextBool() ? screensize : -screensize);
+ SkScalar t = pow(rand->nextF(), 3);
+ *d = ((1 - t) / 60 + t / 10) * (rand->nextBool() ? screensize : -screensize);
}
- SkScalar t = pow(fRand.nextF(), 25);
- v.fDSpin = ((1 - t) * 360 / 7.5 + t * 360 / 1.5) * (fRand.nextBool() ? 1 : -1);
+ SkScalar t = pow(rand->nextF(), 25);
+ v.fDSpin = ((1 - t) * 360 / 7.5 + t * 360 / 1.5) * (rand->nextBool() ? 1 : -1);
}
// Get valid front data.
fBackgroundAnimationTask.wait();
- this->runAnimationTask(0, 0, this->width(), this->height());
+ this->runAnimationTask(0, 0, screenWidth, screenHeight);
memcpy(fFrontMatrices, fBackMatrices, kNumPaths * sizeof(SkMatrix));
fLastTick = 0;
}
- bool onAnimate(double nanos) final {
+ bool animate(double nanos, int screenWidth, int screenHeight) final {
fBackgroundAnimationTask.wait();
this->swapAnimationBuffers();
const double tsec = 1e-9 * nanos;
const double dt = fLastTick ? (1e-9 * nanos - fLastTick) : 0;
- fBackgroundAnimationTask.add(std::bind(&MovingPathText::runAnimationTask, this, tsec,
- dt, this->width(), this->height()));
+ fBackgroundAnimationTask.add(std::bind(&MovingGlyphAnimator::runAnimationTask, this, tsec,
+ dt, screenWidth, screenHeight));
fLastTick = 1e-9 * nanos;
return true;
}
@@ -216,7 +226,7 @@ public:
std::swap(fFrontMatrices, fBackMatrices);
}
- void drawGlyphs(SkCanvas* canvas) override {
+ void draw(SkCanvas* canvas) override {
for (int i = 0; i < kNumPaths; ++i) {
SkAutoCanvasRestore acr(canvas, true);
canvas->concat(fFrontMatrices[i]);
@@ -230,33 +240,31 @@ protected:
SkScalar fDSpin;
};
- Velocity fVelocities[kNumPaths];
- SkAutoTMalloc<SkMatrix> fFrontMatrices;
- SkAutoTMalloc<SkMatrix> fBackMatrices;
- SkTaskGroup fBackgroundAnimationTask;
- double fLastTick;
-
- typedef PathText INHERITED;
+ Velocity fVelocities[kNumPaths];
+ SkAutoTMalloc<SkMatrix> fFrontMatrices;
+ SkAutoTMalloc<SkMatrix> fBackMatrices;
+ SkTaskGroup fBackgroundAnimationTask;
+ double fLastTick;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// Text from paths with animated control points.
-class WavyPathText : public MovingPathText {
+class PathText::WavyGlyphAnimator : public PathText::MovingGlyphAnimator {
public:
- const char* getName() const override { return "WavyPathText"; }
-
- WavyPathText()
- : fFrontPaths(kNumPaths)
- , fBackPaths(kNumPaths) {}
+ WavyGlyphAnimator(Glyph* glyphs)
+ : MovingGlyphAnimator(glyphs)
+ , fFrontPaths(kNumPaths)
+ , fBackPaths(kNumPaths) {
+ }
- ~WavyPathText() override {
+ ~WavyGlyphAnimator() override {
fBackgroundAnimationTask.wait();
}
- void reset() override {
- fWaves.reset(fRand, this->width(), this->height());
- this->INHERITED::reset();
+ void reset(SkRandom* rand, int screenWidth, int screenHeight) override {
+ fWaves.reset(*rand, screenWidth, screenHeight);
+ this->MovingGlyphAnimator::reset(rand, screenWidth, screenHeight);
std::copy(fBackPaths.get(), fBackPaths.get() + kNumPaths, fFrontPaths.get());
}
@@ -265,7 +273,7 @@ public:
*/
void runAnimationTask(double t, double dt, int w, int h) override {
const float tsec = static_cast<float>(t);
- this->INHERITED::runAnimationTask(t, 0.5 * dt, w, h);
+ this->MovingGlyphAnimator::runAnimationTask(t, 0.5 * dt, w, h);
for (int i = 0; i < kNumPaths; ++i) {
const Glyph& glyph = fGlyphs[i];
@@ -313,11 +321,11 @@ public:
}
void swapAnimationBuffers() override {
- this->INHERITED::swapAnimationBuffers();
+ this->MovingGlyphAnimator::swapAnimationBuffers();
std::swap(fFrontPaths, fBackPaths);
}
- void drawGlyphs(SkCanvas* canvas) override {
+ void draw(SkCanvas* canvas) override {
for (int i = 0; i < kNumPaths; ++i) {
canvas->drawPath(fFrontPaths[i], fGlyphs[i].fPaint);
}
@@ -344,14 +352,12 @@ private:
float fOffsets[4];
};
- SkAutoTArray<SkPath> fFrontPaths;
- SkAutoTArray<SkPath> fBackPaths;
- Waves fWaves;
-
- typedef MovingPathText INHERITED;
+ SkAutoTArray<SkPath> fFrontPaths;
+ SkAutoTArray<SkPath> fBackPaths;
+ Waves fWaves;
};
-void WavyPathText::Waves::reset(SkRandom& rand, int w, int h) {
+void PathText::WavyGlyphAnimator::Waves::reset(SkRandom& rand, int w, int h) {
const double pixelsPerMeter = 0.06 * std::max(w, h);
const double medianWavelength = 8 * pixelsPerMeter;
const double medianWaveAmplitude = 0.05 * 4 * pixelsPerMeter;
@@ -371,7 +377,8 @@ void WavyPathText::Waves::reset(SkRandom& rand, int w, int h) {
}
}
-SkPoint WavyPathText::Waves::apply(float tsec, const Sk2f matrix[3], const SkPoint& pt) const {
+SkPoint PathText::WavyGlyphAnimator::Waves::apply(float tsec, const Sk2f matrix[3],
+ const SkPoint& pt) const {
constexpr static int kTablePeriod = 1 << 12;
static float sin2table[kTablePeriod + 1];
static SkOnce initTable;
@@ -418,10 +425,28 @@ SkPoint WavyPathText::Waves::apply(float tsec, const Sk2f matrix[3], const SkPoi
return {devicePt[0] + offsetY[0] + offsetY[1], devicePt[1] - offsetX[0] - offsetX[1]};
}
-////////////////////////////////////////////////////////////////////////////////////////////////////
+bool PathText::onChar(SkUnichar unichar) {
+ switch (unichar) {
+ case 'X':
+ fDoClip = !fDoClip;
+ return true;
+ case 'S':
+ fGlyphAnimator = std::make_unique<GlyphAnimator>(fGlyphs);
+ fGlyphAnimator->reset(&fRand, this->width(), this->height());
+ return true;
+ case 'M':
+ fGlyphAnimator = std::make_unique<MovingGlyphAnimator>(fGlyphs);
+ fGlyphAnimator->reset(&fRand, this->width(), this->height());
+ return true;
+ case 'W':
+ fGlyphAnimator = std::make_unique<WavyGlyphAnimator>(fGlyphs);
+ fGlyphAnimator->reset(&fRand, this->width(), this->height());
+ return true;
+ }
+ return false;
+}
-DEF_SAMPLE( return new PathText; )
-DEF_SAMPLE( return new MovingPathText; )
+////////////////////////////////////////////////////////////////////////////////////////////////////
-Sample* MakeWavyPathTextSample() { return new WavyPathText; }
-static SampleRegistry WavyPathText(MakeWavyPathTextSample);
+Sample* MakePathTextSample() { return new PathText; }
+static SampleRegistry gPathTextSample(MakePathTextSample);
diff --git a/chromium/third_party/skia/samplecode/SampleRectanizer.cpp b/chromium/third_party/skia/samplecode/SampleRectanizer.cpp
index 41420a9f08a..67f36f9a18d 100644
--- a/chromium/third_party/skia/samplecode/SampleRectanizer.cpp
+++ b/chromium/third_party/skia/samplecode/SampleRectanizer.cpp
@@ -10,20 +10,21 @@
#include "include/core/SkPaint.h"
#include "include/utils/SkRandom.h"
#include "samplecode/Sample.h"
-#include "src/core/SkMathPriv.h"
#include "src/utils/SkUTF.h"
#if SK_SUPPORT_GPU
+#include "src/gpu/GrRectanizerPow2.h"
#include "src/gpu/GrRectanizerSkyline.h"
// This slide visualizes the various GrRectanizer-derived classes behavior
// for various input sets
+// 'j' will cycle through the various rectanizers
+// Pow2 -> GrRectanizerPow2
+// Skyline -> GrRectanizerSkyline
// 'h' will cycle through the various rect sets
// Rand -> random rects from 2-256
// Pow2Rand -> random power of 2 sized rects from 2-256
// SmallPow2 -> 128x128 rects
class RectanizerView : public Sample {
- static constexpr int kWidth = 1024;
- static constexpr int kHeight = 1024;
public:
RectanizerView()
: fCurRandRect(0)
@@ -46,7 +47,10 @@ public:
fCurRects = &fRects[0];
- fRectanizers.emplace_back(kWidth, kHeight);
+ fRectanizers.push_back(
+ std::unique_ptr<GrRectanizer>(new GrRectanizerPow2(kWidth, kHeight)));
+ fRectanizers.push_back(
+ std::unique_ptr<GrRectanizer>(new GrRectanizerSkyline(kWidth, kHeight)));
}
protected:
@@ -58,6 +62,9 @@ protected:
// Only consider events for single char keys
if (1 == size) {
switch (utf8[0]) {
+ case kCycleRectanizerKey:
+ this->cycleRectanizer();
+ return true;
case kCycleRectsKey:
this->cycleRects();
return true;
@@ -70,9 +77,9 @@ protected:
void onDrawContent(SkCanvas* canvas) override {
if (fCurRandRect < kNumRandRects) {
- if (fRectanizers[fCurRectanizer].addRect((*fCurRects)[fCurRandRect].fWidth,
- (*fCurRects)[fCurRandRect].fHeight,
- &fRectLocations[fCurRandRect])) {
+ if (fRectanizers[fCurRectanizer]->addRect((*fCurRects)[fCurRandRect].fWidth,
+ (*fCurRects)[fCurRandRect].fHeight,
+ &fRectLocations[fCurRandRect])) {
++fCurRandRect;
}
}
@@ -102,34 +109,52 @@ protected:
SkString str;
- str.printf("%s-%s: tot Area: %ld (%.2f) numTextures: %d/%d",
+ str.printf("%s-%s: tot Area: %ld %%full: %.2f (%.2f) numTextures: %d/%d",
this->getRectanizerName(),
this->getRectsName(),
totArea,
+ 100.0f * fRectanizers[fCurRectanizer]->percentFull(),
100.0f * totArea / ((float)kWidth*kHeight),
fCurRandRect,
kNumRandRects);
canvas->drawString(str, 50, kHeight + 50, blackBigFont, SkPaint());
+ str.printf("Press \'j\' to toggle rectanizer");
+ canvas->drawString(str, 50, kHeight + 100, blackBigFont, SkPaint());
+
str.printf("Press \'h\' to toggle rects");
canvas->drawString(str, 50, kHeight + 150, blackBigFont, SkPaint());
}
private:
+ static const int kWidth = 1024;
+ static const int kHeight = 1024;
static const int kNumRandRects = 200;
+ static const char kCycleRectanizerKey = 'j';
static const char kCycleRectsKey = 'h';
static const int kMinRectSize = 2;
static const int kMaxRectSize = 256;
- int fCurRandRect;
- SkTDArray<SkISize> fRects[3];
- SkTDArray<SkISize>* fCurRects;
- SkTDArray<SkIPoint16> fRectLocations;
- SkTArray<GrRectanizerSkyline> fRectanizers;
- int fCurRectanizer;
+ int fCurRandRect;
+ SkTDArray<SkISize> fRects[3];
+ SkTDArray<SkISize>* fCurRects;
+ SkTDArray<SkIPoint16> fRectLocations;
+ SkTArray<std::unique_ptr<GrRectanizer>> fRectanizers;
+ int fCurRectanizer;
const char* getRectanizerName() const {
- return "Skyline";
+ if (!fCurRectanizer) {
+ return "Pow2";
+ } else {
+ return "Skyline";
+ }
+ }
+
+ void cycleRectanizer() {
+ fCurRectanizer = (fCurRectanizer + 1) % fRectanizers.count();
+
+ fRectanizers[fCurRectanizer]->reset();
+ fCurRandRect = 0;
}
const char* getRectsName() const {
@@ -151,7 +176,7 @@ private:
fCurRects = &fRects[0];
}
- fRectanizers[fCurRectanizer].reset();
+ fRectanizers[fCurRectanizer]->reset();
fCurRandRect = 0;
}
diff --git a/chromium/third_party/skia/samplecode/SampleTessellatedWedge.cpp b/chromium/third_party/skia/samplecode/SampleTessellatedWedge.cpp
index 66b73ba37c1..0598b1f026c 100644
--- a/chromium/third_party/skia/samplecode/SampleTessellatedWedge.cpp
+++ b/chromium/third_party/skia/samplecode/SampleTessellatedWedge.cpp
@@ -22,9 +22,9 @@
// This sample enables wireframe and visualizes the triangulation generated by
// GrTessellateWedgeShader.
-class TessellatedWedgeView : public Sample {
+class TessellatedWedge : public Sample {
public:
- TessellatedWedgeView() {
+ TessellatedWedge() {
#if 0
fPath.moveTo(1, 0);
int numSides = 32 * 3;
@@ -32,8 +32,8 @@ public:
float theta = 2*3.1415926535897932384626433832785 * i / numSides;
fPath.lineTo(std::cos(theta), std::sin(theta));
}
- fPath.transform(SkMatrix::MakeScale(200, 200));
- fPath.transform(SkMatrix::MakeTrans(300, 300));
+ fPath.transform(SkMatrix::Scale(200, 200));
+ fPath.transform(SkMatrix::Translate(300, 300));
#else
fPath.moveTo(100, 200);
fPath.cubicTo(100, 100, 400, 100, 400, 200);
@@ -51,12 +51,12 @@ private:
SkMatrix fLastViewMatrix = SkMatrix::I();
SkPath fPath;
- GrTessellatePathOp::Flags fFlags = GrTessellatePathOp::Flags::kWireframe;
+ GrTessellationPathRenderer::OpFlags fOpFlags = GrTessellationPathRenderer::OpFlags::kWireframe;
class Click;
};
-void TessellatedWedgeView::onDrawContent(SkCanvas* canvas) {
+void TessellatedWedge::onDrawContent(SkCanvas* canvas) {
canvas->clear(SK_ColorBLACK);
GrContext* ctx = canvas->getGrContext();
@@ -65,8 +65,8 @@ void TessellatedWedgeView::onDrawContent(SkCanvas* canvas) {
SkString error;
if (!rtc || !ctx) {
error = "GPU Only.";
- } else if (!ctx->priv().caps()->shaderCaps()->tessellationSupport()) {
- error = "GPU tessellation not supported.";
+ } else if (!ctx->priv().caps()->drawInstancedSupport()) {
+ error = "Instanced rendering not supported.";
} else if (1 == rtc->numSamples() && !ctx->priv().caps()->mixedSamplesSupport()) {
error = "MSAA/mixed samples only.";
}
@@ -92,7 +92,7 @@ void TessellatedWedgeView::onDrawContent(SkCanvas* canvas) {
GrOpMemoryPool* pool = ctx->priv().opMemoryPool();
rtc->priv().testingOnly_addDrawOp(pool->allocate<GrTessellatePathOp>(
- canvas->getTotalMatrix(), fPath, std::move(paint), aa, fFlags));
+ canvas->getTotalMatrix(), fPath, std::move(paint), aa, fOpFlags));
// Draw the path points.
SkPaint pointsPaint;
@@ -110,7 +110,7 @@ void TessellatedWedgeView::onDrawContent(SkCanvas* canvas) {
fLastViewMatrix = canvas->getTotalMatrix();
}
-class TessellatedWedgeView::Click : public Sample::Click {
+class TessellatedWedge::Click : public Sample::Click {
public:
Click(int ptIdx) : fPtIdx(ptIdx) {}
@@ -120,7 +120,7 @@ public:
SkPathPriv::UpdatePathPoint(path, fPtIdx, pt + fCurr - fPrev);
} else {
path->transform(
- SkMatrix::MakeTrans(fCurr.x() - fPrev.x(), fCurr.y() - fPrev.y()), path);
+ SkMatrix::Translate(fCurr.x() - fPrev.x(), fCurr.y() - fPrev.y()), path);
}
}
@@ -128,7 +128,7 @@ private:
int fPtIdx;
};
-Sample::Click* TessellatedWedgeView::onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) {
+Sample::Click* TessellatedWedge::onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) {
const SkPoint* pts = SkPathPriv::PointData(fPath);
float fuzz = 20 / fLastViewMatrix.getMaxScale();
for (int i = 0; i < fPath.countPoints(); ++i) {
@@ -140,17 +140,17 @@ Sample::Click* TessellatedWedgeView::onFindClickHandler(SkScalar x, SkScalar y,
return new Click(-1);
}
-bool TessellatedWedgeView::onClick(Sample::Click* click) {
+bool TessellatedWedge::onClick(Sample::Click* click) {
Click* myClick = (Click*)click;
myClick->doClick(&fPath);
return true;
}
-bool TessellatedWedgeView::onChar(SkUnichar unichar) {
+bool TessellatedWedge::onChar(SkUnichar unichar) {
switch (unichar) {
case 'w':
- fFlags = (GrTessellatePathOp::Flags)(
- (int)fFlags ^ (int)GrTessellatePathOp::Flags::kWireframe);
+ fOpFlags = (GrTessellationPathRenderer::OpFlags)(
+ (int)fOpFlags ^ (int)GrTessellationPathRenderer::OpFlags::kWireframe);
return true;
case 'D': {
fPath.dump();
@@ -160,6 +160,7 @@ bool TessellatedWedgeView::onChar(SkUnichar unichar) {
return false;
}
-DEF_SAMPLE(return new TessellatedWedgeView;)
+Sample* MakeTessellatedWedgeSample() { return new TessellatedWedge; }
+static SampleRegistry gTessellatedWedgeSample(MakeTessellatedWedgeSample);
#endif // SK_SUPPORT_GPU
diff --git a/chromium/third_party/skia/samplecode/SampleTextBox.cpp b/chromium/third_party/skia/samplecode/SampleTextBox.cpp
index c13b98118f6..72bc2726c5d 100644
--- a/chromium/third_party/skia/samplecode/SampleTextBox.cpp
+++ b/chromium/third_party/skia/samplecode/SampleTextBox.cpp
@@ -114,7 +114,7 @@ private:
};
DEF_SAMPLE( return new TextBoxView([](){ return SkShaper::Make(); }, "default"); );
-#ifdef SK_BUILD_FOR_MAC
+#ifdef SK_SHAPER_CORETEXT_AVAILABLE
DEF_SAMPLE( return new TextBoxView(SkShaper::MakeCoreText, "coretext"); );
#endif
@@ -176,7 +176,9 @@ protected:
for (SkScalar size = 30; size <= 30; size += 10) {
this->drawTest(canvas, text, size, SkShaper::Make());
canvas->translate(0, size + 5);
+ #ifdef SK_SHAPER_CORETEXT_AVAILABLE
this->drawTest(canvas, text, size, SkShaper::MakeCoreText());
+ #endif
canvas->translate(0, size*2);
}
}
diff --git a/chromium/third_party/skia/site/dev/chrome/blink.md b/chromium/third_party/skia/site/dev/chrome/blink.md
index 283e8625394..92d88e671db 100644
--- a/chromium/third_party/skia/site/dev/chrome/blink.md
+++ b/chromium/third_party/skia/site/dev/chrome/blink.md
@@ -13,7 +13,7 @@ special coordination with the Blink gardener using these steps:
detail on running the Blink layout tests\).
2. Check in your code to the Skia repo.
3. Ahead of the Skia auto roll including your change, manually push a change to the
- Blink LayoutTests/TestExpectations [file](https://chromium.googlesource.com/chromium/src/+/master/third_party/WebKit/LayoutTests/TestExpectations), flagging tests expected to fail as a result of your change as follows:
+ Blink LayoutTests/TestExpectations [file](https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/web_tests/TestExpectations), flagging tests expected to fail as a result of your change as follows:
foo/bar/test-name.html [ Failure Pass ] # Needs rebaseline
4. Wait for the Skia roll to land successfully.
@@ -65,7 +65,7 @@ See https://chromium.googlesource.com/chromium/src/+log/master/DEPS and search f
know that they are not expected to fix it.
2. Create a CL removing the code suppression from Chromium's
skia/chromium\_skia\_defines\.gypi while simultaneously adding [ NeedsRebaseline ]
- lines to Blink's LayoutTests/TestExpectations [file](https://chromium.googlesource.com/chromium/src/+/master/third_party/WebKit/LayoutTests/TestExpectations).
+ lines to Blink's LayoutTests/TestExpectations [file](https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/web_tests/TestExpectations).
Then the auto rebaseline bot will take care of the work of actually checking in the
new images. This is generally acceptable for up to 600 or so rebaselined images.
Above that you might still use [ NeedsRebaseline ], but it's best to coordinate with
diff --git a/chromium/third_party/skia/site/dev/contrib/style.md b/chromium/third_party/skia/site/dev/contrib/style.md
index 9edf83dcdbe..2a695c049df 100644
--- a/chromium/third_party/skia/site/dev/contrib/style.md
+++ b/chromium/third_party/skia/site/dev/contrib/style.md
@@ -55,8 +55,8 @@ public:
};
~~~~
-Data fields in structs, classes, unions begin with lowercase f and are then
-camel capped.
+Data fields in structs, classes, unions begin with lower-case f and are then
+camel-capped.
<!--?prettify?-->
~~~~
@@ -67,13 +67,17 @@ struct GrCar {
};
~~~~
-Globals variables are similar but prefixed with g and camel-capped
+Global variables are similar but prefixed with g and camel-capped.
<!--?prettify?-->
~~~~
bool gLoggingEnabled
-Local variables begin lowercases and are camel-capped.
+~~~~
+
+Local variables and arguments are camel-capped with no initial cap.
+<!--?prettify?-->
+~~~~
int herdCats(const Array& cats) {
int numCats = cats.count();
}
@@ -137,7 +141,7 @@ enum { kFavoriteNumber = 7 };
Macros are all caps with underscores between words. Macros that have greater
than file scope should be prefixed SK or GR.
-Static non-class functions in implementation files are lower case with
+Static non-class functions in implementation files are lower-case with
underscores separating words:
<!--?prettify?-->
@@ -156,6 +160,9 @@ bool SkIsOdd(int n);
class SkFoo {
public:
static int FooInstanceCount();
+
+ // Not static.
+ int barBaz();
};
~~~~
diff --git a/chromium/third_party/skia/site/dev/testing/fuzz.md b/chromium/third_party/skia/site/dev/testing/fuzz.md
index 8bb37441647..6b4d338cef0 100644
--- a/chromium/third_party/skia/site/dev/testing/fuzz.md
+++ b/chromium/third_party/skia/site/dev/testing/fuzz.md
@@ -12,7 +12,8 @@ less machine- and platform- dependent:
skia_use_system_freetype2=false
skia_use_wuffs=true
skia_enable_skottie=true
- skia_enable_fontmgr_custom=false
+ skia_enable_fontmgr_custom_directory=false
+ skia_enable_fontmgr_custom_embedded=false
skia_enable_fontmgr_custom_empty=true
All that is needed to reproduce a fuzz downloaded from ClusterFuzz, oss-fuzz or
diff --git a/chromium/third_party/skia/site/user/api/catalog.htm b/chromium/third_party/skia/site/user/api/catalog.htm
index a45522fb96f..a9a981f3054 100644
--- a/chromium/third_party/skia/site/user/api/catalog.htm
+++ b/chromium/third_party/skia/site/user/api/catalog.htm
@@ -9120,14 +9120,6 @@
"file": "SkSurface_Reference",
"name": "SkSurface::MakeFromBackendTexture"
},
- "SkSurface_MakeFromBackendTextureAsRenderTarget": {
- "code": "void draw(SkCanvas* canvas) {\n SkPaint paint;\n paint.setTextSize(32);\n GrContext* context = canvas->getGrContext();\n if (!context) {\n canvas->drawString(\"GPU only!\", 20, 40, paint);\n return;\n }\n sk_sp<SkSurface> gpuSurface = SkSurface::MakeFromBackendTextureAsRenderTarget(\n context, backEndTexture, kTopLeft_GrSurfaceOrigin, 0,\n kRGBA_8888_SkColorType, nullptr, nullptr);\n auto surfaceCanvas = gpuSurface->getCanvas();\n surfaceCanvas->drawString(\"GPU rocks!\", 20, 40, paint);\n sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());\n canvas->drawImage(image, 0, 0);\n}",
- "width": 256,
- "height": 256,
- "hash": "5e87093b9cbe95124ae14cbe77091eb7",
- "file": "SkSurface_Reference",
- "name": "SkSurface::MakeFromBackendTextureAsRenderTarget"
-},
"SkSurface_MakeRenderTarget": {
"code": "void draw(SkCanvas* canvas) {\n SkPaint paint;\n paint.setTextSize(32);\n GrContext* context = canvas->getGrContext();\n if (!context) {\n canvas->drawString(\"GPU only!\", 20, 40, paint);\n return;\n }\n SkImageInfo info = SkImageInfo::MakeN32(256, 64, kOpaque_SkAlphaType);\n for (auto surfaceOrigin : { kTopLeft_GrSurfaceOrigin, kBottomLeft_GrSurfaceOrigin } ) {\n auto gpuSurface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, 0,\n surfaceOrigin, nullptr));\n auto surfaceCanvas = gpuSurface->getCanvas();\n surfaceCanvas->clear(SK_ColorWHITE);\n surfaceCanvas->drawString(\"GPU rocks!\", 20, 40, paint);\n sk_sp<SkImage> image(gpuSurface->makeImageSnapshot());\n canvas->drawImage(image, 0, 0);\n canvas->translate(0, 128);\n }\n}",
"width": 256,
diff --git a/chromium/third_party/skia/site/user/modules/canvaskit.md b/chromium/third_party/skia/site/user/modules/canvaskit.md
index 7142dc97497..962fa0c3942 100644
--- a/chromium/third_party/skia/site/user/modules/canvaskit.md
+++ b/chromium/third_party/skia/site/user/modules/canvaskit.md
@@ -29,12 +29,12 @@ Samples
margin: 2px;
}
- #patheffect, #ink, #shaping {
+ #patheffect, #ink, #shaping, #shader1, #camera3d {
width: 400px;
height: 400px;
}
- #sk_legos, #sk_drinks, #sk_party, #sk_onboarding, #shader1 {
+ #sk_legos, #sk_drinks, #sk_party, #sk_onboarding {
width: 300px;
height: 300px;
}
@@ -51,25 +51,33 @@ Samples
</style>
<div id=demo>
- <h3>Go beyond the HTML Canvas2D</h3>
+ <h3>Paragraph shaping, custom shaders, and perspective transformation</h3>
<figure>
- <canvas id=patheffect width=400 height=400></canvas>
+ <canvas id=shaping width=500 height=500></canvas>
<figcaption>
- <a href="https://jsfiddle.skia.org/canvaskit/43b38b83ca77dabe47f18f31cafe83f3018b3a24e569db27fe711c70bc3f7d62"
+ <a href="https://jsfiddle.skia.org/canvaskit/56cb197c724dfdfad0c3d8133d4fcab587e4c4e7f31576e62c17251637d3745c"
target=_blank rel=noopener>
- Star JSFiddle</a>
+ SkParagraph JSFiddle</a>
</figcaption>
</figure>
<figure>
- <canvas id=ink width=400 height=400></canvas>
+ <canvas id=shader1 width=512 height=512></canvas>
<figcaption>
- <a href="https://jsfiddle.skia.org/canvaskit/ad0a5454db3ac757684ed2fa8ce9f1f0175f1c043d2cbe33597d81481cdb4baa"
+ <a href="https://jsfiddle.skia.org/canvaskit/33ff9bed883cd5742b4770169da0b36fb0cbc18fd395ddd9563213e178362d30"
target=_blank rel=noopener>
- Ink JSFiddle</a>
+ Shader JSFiddle</a>
+ </figcaption>
+ </figure>
+ <figure>
+ <canvas id=camera3d width=400 height=400></canvas>
+ <figcaption>
+ <a href="https://jsfiddle.skia.org/canvaskit/4b7f2cb6683ad3254ac46e3bab62da9a09e994044b2e7512c93d166abeaa2549"
+ target=_blank rel=noopener>
+ 3D Cube JSFiddle</a>
</figcaption>
</figure>
- <h3>Skottie (click for fiddles)</h3>
+ <h3>Play back bodymovin lottie files with skottie (click for fiddles)</h3>
<a href="https://jsfiddle.skia.org/canvaskit/092690b273b41076d2f00f0d43d004893d6bb9992c387c0385efa8e6f6bc83d7"
target=_blank rel=noopener>
<canvas id=sk_legos width=300 height=300></canvas>
@@ -87,21 +95,23 @@ Samples
<canvas id=sk_onboarding width=500 height=500></canvas>
</a>
- <h3>SkParagraph (using ICU and Harfbuzz)</h3>
+ <h3>Go beyond the HTML Canvas2D</h3>
<figure>
- <canvas id=shaping width=500 height=500></canvas>
+ <canvas id=patheffect width=400 height=400></canvas>
<figcaption>
- <a href="https://jsfiddle.skia.org/canvaskit/56cb197c724dfdfad0c3d8133d4fcab587e4c4e7f31576e62c17251637d3745c"
+ <a href="https://jsfiddle.skia.org/canvaskit/43b38b83ca77dabe47f18f31cafe83f3018b3a24e569db27fe711c70bc3f7d62"
target=_blank rel=noopener>
- SkParagraph JSFiddle</a>
+ Star JSFiddle</a>
+ </figcaption>
+ </figure>
+ <figure>
+ <canvas id=ink width=400 height=400></canvas>
+ <figcaption>
+ <a href="https://jsfiddle.skia.org/canvaskit/ad0a5454db3ac757684ed2fa8ce9f1f0175f1c043d2cbe33597d81481cdb4baa"
+ target=_blank rel=noopener>
+ Ink JSFiddle</a>
</figcaption>
</figure>
-
- <h3>SKSL for writing custom shaders</h3>
- <a href="https://jsfiddle.skia.org/canvaskit/33ff9bed883cd5742b4770169da0b36fb0cbc18fd395ddd9563213e178362d30"
- target=_blank rel=noopener>
- <canvas id=shader1 width=512 height=512></canvas>
- </a>
</div>
@@ -129,9 +139,11 @@ Samples
let confettiJSON = null;
let onboardingJSON = null;
let fullBounds = {fLeft: 0, fTop: 0, fRight: 500, fBottom: 500};
- CanvasKitInit({
+ const ckLoaded = CanvasKitInit({
locateFile: (file) => locate_file + file,
- }).ready().then((CK) => {
+ });
+
+ ckLoaded.then((CK) => {
CanvasKit = CK;
DrawingExample(CanvasKit);
InkExample(CanvasKit);
@@ -173,6 +185,10 @@ Samples
});
});
+ const loadBrickTex = fetch('https://storage.googleapis.com/skia-cdn/misc/brickwork-texture.jpg').then((response) => response.arrayBuffer());
+ const loadBrickBump = fetch('https://storage.googleapis.com/skia-cdn/misc/brickwork_normal-map.jpg').then((response) => response.arrayBuffer());
+ Promise.all([ckLoaded, loadBrickTex, loadBrickBump]).then((results) => {Camera3D(...results)});
+
function preventScrolling(canvas) {
canvas.addEventListener('touchmove', (e) => {
// Prevents touch events in the canvas from scrolling the canvas.
@@ -508,6 +524,330 @@ void main(float2 p, inout half4 color) {
requestAnimationFrame(drawFrame);
}
+ function Camera3D(canvas, textureImgData, normalImgData) {
+ const surface = CanvasKit.MakeCanvasSurface('camera3d');
+ if (!surface) {
+ console.error('Could not make surface');
+ return;
+ }
+
+ const sizeX = document.getElementById('camera3d').width;
+ const sizeY = document.getElementById('camera3d').height;
+
+ let clickToWorld = CanvasKit.SkM44.identity();
+ let worldToClick = CanvasKit.SkM44.identity();
+ // rotation of the cube shown in the demo
+ let rotation = CanvasKit.SkM44.identity();
+ // temporary during a click and drag
+ let clickRotation = CanvasKit.SkM44.identity();
+
+ // A virtual sphere used for tumbling the object on screen.
+ const vSphereCenter = [sizeX/2, sizeY/2];
+ const vSphereRadius = Math.min(...vSphereCenter);
+
+ // The rounded rect used for each face
+ const margin = vSphereRadius / 20;
+ const rr = CanvasKit.RRectXY(CanvasKit.LTRBRect(margin, margin,
+ vSphereRadius - margin, vSphereRadius - margin), margin*2.5, margin*2.5);
+
+ const camNear = 0.05;
+ const camFar = 4;
+ const camAngle = Math.PI / 12;
+
+ const camEye = [0, 0, 1 / Math.tan(camAngle/2) - 1];
+ const camCOA = [0, 0, 0];
+ const camUp = [0, 1, 0];
+
+ let mouseDown = false;
+ let clickDown = [0, 0]; // location of click down
+ let lastMouse = [0, 0]; // last mouse location
+
+ // keep spinning after mouse up. Also start spinning on load
+ let axis = [0.4, 1, 1];
+ let totalSpin = 0;
+ let spinRate = 0.1;
+ let lastRadians = 0;
+ let spinning = setInterval(keepSpinning, 30);
+
+ const imgscale = CanvasKit.SkMatrix.scaled(2, 2);
+ const textureShader = CanvasKit.MakeImageFromEncoded(textureImgData).makeShader(
+ CanvasKit.TileMode.Clamp, CanvasKit.TileMode.Clamp, imgscale);
+ const normalShader = CanvasKit.MakeImageFromEncoded(normalImgData).makeShader(
+ CanvasKit.TileMode.Clamp, CanvasKit.TileMode.Clamp, imgscale);
+ const children = [textureShader, normalShader];
+
+ const prog = `
+ in shader color_map;
+ in shader normal_map;
+
+ uniform float3 lightPos;
+ layout (marker=local_to_world) uniform float4x4 localToWorld;
+ layout (marker=normals(local_to_world)) uniform float4x4 localToWorldAdjInv;
+
+ float3 convert_normal_sample(half4 c) {
+ float3 n = 2 * c.rgb - 1;
+ n.y = -n.y;
+ return n;
+ }
+
+ void main(float2 p, inout half4 color) {
+ float3 norm = convert_normal_sample(sample(normal_map, p));
+ float3 plane_norm = normalize(localToWorldAdjInv * float4(norm, 0)).xyz;
+
+ float3 plane_pos = (localToWorld * float4(p, 0, 1)).xyz;
+ float3 light_dir = normalize(lightPos - plane_pos);
+
+ float ambient = 0.2;
+ float dp = dot(plane_norm, light_dir);
+ float scale = min(ambient + max(dp, 0), 1);
+
+ color = sample(color_map, p) * half4(float4(scale, scale, scale, 1));
+ }
+`;
+
+ const fact = CanvasKit.SkRuntimeEffect.Make(prog);
+
+ // properties of light
+ let lightLocation = [...vSphereCenter];
+ let lightDistance = vSphereRadius;
+ let lightIconRadius = 12;
+ let draggingLight = false;
+
+ function computeLightWorldPos() {
+ return CanvasKit.SkVector.add(CanvasKit.SkVector.mulScalar([...vSphereCenter, 0], 0.5),
+ CanvasKit.SkVector.mulScalar(vSphereUnitV3(lightLocation), lightDistance));
+ }
+
+ let lightWorldPos = computeLightWorldPos();
+
+ function drawLight(canvas) {
+ const paint = new CanvasKit.SkPaint();
+ paint.setAntiAlias(true);
+ paint.setColor(CanvasKit.WHITE);
+ canvas.drawCircle(...lightLocation, lightIconRadius + 2, paint);
+ paint.setColor(CanvasKit.BLACK);
+ canvas.drawCircle(...lightLocation, lightIconRadius, paint);
+ }
+
+ // Takes an x and y rotation in radians and a scale and returns a 4x4 matrix used to draw a
+ // face of the cube in that orientation.
+ function faceM44(rx, ry, scale) {
+ return CanvasKit.SkM44.multiply(
+ CanvasKit.SkM44.rotated([0,1,0], ry),
+ CanvasKit.SkM44.rotated([1,0,0], rx),
+ CanvasKit.SkM44.translated([0, 0, scale]));
+ }
+
+ const faceScale = vSphereRadius/2
+ const faces = [
+ {matrix: faceM44( 0, 0, faceScale ), color:CanvasKit.RED}, // front
+ {matrix: faceM44( 0, Math.PI, faceScale ), color:CanvasKit.GREEN}, // back
+
+ {matrix: faceM44( Math.PI/2, 0, faceScale ), color:CanvasKit.BLUE}, // top
+ {matrix: faceM44(-Math.PI/2, 0, faceScale ), color:CanvasKit.CYAN}, // bottom
+
+ {matrix: faceM44( 0, Math.PI/2, faceScale ), color:CanvasKit.MAGENTA}, // left
+ {matrix: faceM44( 0,-Math.PI/2, faceScale ), color:CanvasKit.YELLOW}, // right
+ ];
+
+ // Returns a component of the matrix m indicating whether it faces the camera.
+ // If it's positive for one of the matrices representing the face of the cube,
+ // that face is currently in front.
+ function front(m) {
+ // Is this invertible?
+ var m2 = CanvasKit.SkM44.invert(m);
+ if (m2 === null) {
+ m2 = CanvasKit.SkM44.identity();
+ }
+ // look at the sign of the z-scale of the inverse of m.
+ // that's the number in row 2, col 2.
+ return m2[10]
+ }
+
+ // Return the inverse of an SkM44. throw an error if it's not invertible
+ function mustInvert(m) {
+ var m2 = CanvasKit.SkM44.invert(m);
+ if (m2 === null) {
+ throw "Matrix not invertible";
+ }
+ return m2;
+ }
+
+ function saveCamera(canvas, /* rect */ area, /* scalar */ zscale) {
+ const camera = CanvasKit.SkM44.lookat(camEye, camCOA, camUp);
+ const perspective = CanvasKit.SkM44.perspective(camNear, camFar, camAngle);
+ // Calculate viewport scale. Even through we know these values are all constants in this
+ // example it might be handy to change the size later.
+ const center = [(area.fLeft + area.fRight)/2, (area.fTop + area.fBottom)/2, 0];
+ const viewScale = [(area.fRight - area.fLeft)/2, (area.fBottom - area.fTop)/2, zscale];
+ const viewport = CanvasKit.SkM44.multiply(
+ CanvasKit.SkM44.translated(center),
+ CanvasKit.SkM44.scaled(viewScale));
+
+ // want "world" to be in our big coordinates (e.g. area), so apply this inverse
+ // as part of our "camera".
+ canvas.concat(CanvasKit.SkM44.multiply(viewport, perspective));
+ canvas.concat(CanvasKit.SkM44.multiply(camera, mustInvert(viewport)));
+ // Mark the matrix to make it available to the shader by this name.
+ canvas.markCTM('local_to_world');
+ }
+
+ function setClickToWorld(canvas, matrix) {
+ const l2d = canvas.getLocalToDevice();
+ worldToClick = CanvasKit.SkM44.multiply(mustInvert(matrix), l2d);
+ clickToWorld = mustInvert(worldToClick);
+ }
+
+ function drawCubeFace(canvas, m, color) {
+ const trans = new CanvasKit.SkM44.translated([vSphereRadius/2, vSphereRadius/2, 0]);
+ canvas.concat(CanvasKit.SkM44.multiply(trans, m, mustInvert(trans)));
+ const znormal = front(canvas.getLocalToDevice());
+ if (znormal < 0) {
+ return; // skip faces facing backwards
+ }
+ // Pad with space for two 4x4 matrices. Even though the shader uses a layout()
+ // statement to populate them, we still have to reserve space for them.
+ const uniforms = [...lightWorldPos, ...Array(32).fill(0)];
+ const paint = new CanvasKit.SkPaint();
+ paint.setAntiAlias(true);
+ const shader = fact.makeShaderWithChildren(uniforms, true /*=opaque*/, children);
+ paint.setShader(shader);
+ canvas.drawRRect(rr, paint);
+ }
+
+ function drawFrame(canvas) {
+ const clickM = canvas.getLocalToDevice();
+ canvas.save();
+ canvas.translate(vSphereCenter[0] - vSphereRadius/2, vSphereCenter[1] - vSphereRadius/2);
+ // pass surface dimensions as viewport size.
+ saveCamera(canvas, CanvasKit.LTRBRect(0, 0, vSphereRadius, vSphereRadius), vSphereRadius/2);
+ setClickToWorld(canvas, clickM);
+ for (let f of faces) {
+ const saveCount = canvas.getSaveCount();
+ canvas.save();
+ drawCubeFace(canvas, CanvasKit.SkM44.multiply(clickRotation, rotation, f.matrix), f.color);
+ canvas.restoreToCount(saveCount);
+ }
+ canvas.restore(); // camera
+ canvas.restore(); // center the following content in the window
+
+ // draw virtual sphere outline.
+ const paint = new CanvasKit.SkPaint();
+ paint.setAntiAlias(true);
+ paint.setStyle(CanvasKit.PaintStyle.Stroke);
+ paint.setColor(CanvasKit.Color(64, 255, 0, 1.0));
+ canvas.drawCircle(vSphereCenter[0], vSphereCenter[1], vSphereRadius, paint);
+ canvas.drawLine(vSphereCenter[0], vSphereCenter[1] - vSphereRadius,
+ vSphereCenter[0], vSphereCenter[1] + vSphereRadius, paint);
+ canvas.drawLine(vSphereCenter[0] - vSphereRadius, vSphereCenter[1],
+ vSphereCenter[0] + vSphereRadius, vSphereCenter[1], paint);
+
+ drawLight(canvas);
+ }
+
+ // convert a 2D point in the circle displayed on screen to a 3D unit vector.
+ // the virtual sphere is a technique selecting a 3D direction by clicking on a the projection
+ // of a hemisphere.
+ function vSphereUnitV3(p) {
+ // v = (v - fCenter) * (1 / fRadius);
+ let v = CanvasKit.SkVector.mulScalar(CanvasKit.SkVector.sub(p, vSphereCenter), 1/vSphereRadius);
+
+ // constrain the clicked point within the circle.
+ let len2 = CanvasKit.SkVector.lengthSquared(v);
+ if (len2 > 1) {
+ v = CanvasKit.SkVector.normalize(v);
+ len2 = 1;
+ }
+ // the closer to the edge of the circle you are, the closer z is to zero.
+ const z = Math.sqrt(1 - len2);
+ v.push(z);
+ return v;
+ }
+
+ function computeVSphereRotation(start, end) {
+ const u = vSphereUnitV3(start);
+ const v = vSphereUnitV3(end);
+ // Axis is in the scope of the Camera3D function so it can be used in keepSpinning.
+ axis = CanvasKit.SkVector.cross(u, v);
+ const sinValue = CanvasKit.SkVector.length(axis);
+ const cosValue = CanvasKit.SkVector.dot(u, v);
+
+ let m = new CanvasKit.SkM44.identity();
+ if (Math.abs(sinValue) > 0.000000001) {
+ m = CanvasKit.SkM44.rotatedUnitSinCos(
+ CanvasKit.SkVector.mulScalar(axis, 1/sinValue), sinValue, cosValue);
+ const radians = Math.atan(cosValue / sinValue);
+ spinRate = lastRadians - radians;
+ lastRadians = radians;
+ }
+ return m;
+ }
+
+ function keepSpinning() {
+ totalSpin += spinRate;
+ clickRotation = CanvasKit.SkM44.rotated(axis, totalSpin);
+ spinRate *= .998;
+ if (spinRate < 0.01) {
+ stopSpinning();
+ }
+ surface.requestAnimationFrame(drawFrame);
+ }
+
+ function stopSpinning() {
+ clearInterval(spinning);
+ rotation = CanvasKit.SkM44.multiply(clickRotation, rotation);
+ clickRotation = CanvasKit.SkM44.identity();
+ }
+
+ function interact(e) {
+ const type = e.type;
+ let eventPos = [e.offsetX, e.offsetY];
+ if (type === 'lostpointercapture' || type === 'pointerup' || type == 'pointerleave') {
+ if (draggingLight) {
+ draggingLight = false;
+ } else if (mouseDown) {
+ mouseDown = false;
+ if (spinRate > 0.02) {
+ stopSpinning();
+ spinning = setInterval(keepSpinning, 30);
+ }
+ } else {
+ return;
+ }
+ return;
+ } else if (type === 'pointermove') {
+ if (draggingLight) {
+ lightLocation = eventPos;
+ lightWorldPos = computeLightWorldPos();
+ } else if (mouseDown) {
+ lastMouse = eventPos;
+ clickRotation = computeVSphereRotation(clickDown, lastMouse);
+ } else {
+ return;
+ }
+ } else if (type === 'pointerdown') {
+ // Are we repositioning the light?
+ if (CanvasKit.SkVector.dist(eventPos, lightLocation) < lightIconRadius) {
+ draggingLight = true;
+ return;
+ }
+ stopSpinning();
+ mouseDown = true;
+ clickDown = eventPos;
+ lastMouse = eventPos;
+ }
+ surface.requestAnimationFrame(drawFrame);
+ };
+
+ document.getElementById('camera3d').addEventListener('pointermove', interact);
+ document.getElementById('camera3d').addEventListener('pointerdown', interact);
+ document.getElementById('camera3d').addEventListener('lostpointercapture', interact);
+ document.getElementById('camera3d').addEventListener('pointerleave', interact);
+ document.getElementById('camera3d').addEventListener('pointerup', interact);
+
+ surface.requestAnimationFrame(drawFrame);
+ }
+
}
document.head.appendChild(s);
})();
diff --git a/chromium/third_party/skia/site/user/modules/particles.md b/chromium/third_party/skia/site/user/modules/particles.md
index e5e40c98d28..2d11f53578b 100644
--- a/chromium/third_party/skia/site/user/modules/particles.md
+++ b/chromium/third_party/skia/site/user/modules/particles.md
@@ -97,7 +97,7 @@ Samples
var CanvasKit = null;
CanvasKitInit({
locateFile: (file) => locate_file + file,
- }).ready().then((CK) => {
+ }).then((CK) => {
CanvasKit = CK;
TrailExample(CanvasKit, 'trail', trail);
ParticleExample(CanvasKit, 'confetti', confetti, 200, 200);
diff --git a/chromium/third_party/skia/site/user/modules/pathkit.md b/chromium/third_party/skia/site/user/modules/pathkit.md
index 5e597b9dac5..9cf609f8dec 100644
--- a/chromium/third_party/skia/site/user/modules/pathkit.md
+++ b/chromium/third_party/skia/site/user/modules/pathkit.md
@@ -47,6 +47,7 @@ The primary features are:
}
s.src = window.__pathkit_locate_file+'pathkit.js';
s.onload = () => {
+ // TODO(kjlubick) remove .ready() when we update the version served here.
try {
PathKitInit({
locateFile: (file) => window.__pathkit_locate_file+file,
diff --git a/chromium/third_party/skia/site/user/release/release_notes.md b/chromium/third_party/skia/site/user/release/release_notes.md
index b2e06bb17f8..89d12bd2a59 100644
--- a/chromium/third_party/skia/site/user/release/release_notes.md
+++ b/chromium/third_party/skia/site/user/release/release_notes.md
@@ -5,6 +5,69 @@ This page includes a list of high level updates for each milestone release.
* * *
+Milestone 84
+------------
+
+ * Add api on GrContext, updateBackendTexture that will upload new data to a
+ GrBackendTexture.
+ https://review.skia.org/288909
+
+ * Add GrContext getter to SkSurface.
+ https://review.skia.org/289479
+
+ * Deprecate GrContext and SkSurface flush() call and replace ith with flushAndSubmit().
+ This only effects the default flush call that takes no parameters.
+ https://review.skia.org/289478
+
+ * GrContext::createBackendTexture functions that initialize the texture no longer
+ guarantee that all the data has been uploaded and the gpu is done with the texture.
+ Instead the client can assume the upload work has been submitted to the gpu and they
+ must wait for that work to finish before deleting the texture. This can be done via
+ their own synchronization or by passing in a finish proc into the create calls which
+ will be called when it is safe to delete the texture (at least in terms of work
+ done during the create).
+ https://review.skia.org/286517
+
+ * Remove unused SkMaskFilter helpers: compbine, compose
+ Note: shadermaskfilter will likely be removed next (clipShader should serve)
+
+ * Add back SkCanvas::kPreserveLCDText_SaveLayerFlag to indicate that saveLayer()
+ will preserve LCD-text. All text in the layer must be drawn on opaque background
+ to ensure correct rendering.
+
+ * Add the new directory client_utils/ for code that is specific to a single client and
+ should be considered separate from Skia proper. Move SkFrontBufferedStream into the
+ subdir android/.
+
+ * SkBitmap and SkPixmap's erase() methods now treat their color parameters
+ consistently with the rest of Skia, with all SkColors and any untagged
+ SkColor4fs interpreted as sRGB, not as a color in the bitmap's color space.
+ SkPixmap::erase(SkColor4f) now takes an SkColorSpace, so you can pass
+ pixmap.colorSpace() if you want the old behavior.
+
+ * SkCamera.h and SkMatrix44.h are DEPRECATED.
+ Use SkM44 if you want to have 3d transformations.
+
+ * Changed Dilate and Erode image filters to take SkScalar for radius instead of int. While
+ the image filters themselves are defined in terms of discrete pixels, the radii provided by
+ the user are mapped through the CTM so taking ints forced over discretization. After mapping
+ through the CTM the radii are now rounded to pixels.
+ https://review.skia.org/281731
+ https://review.skia.org/282636
+
+ * Updated the contract of GrContext and SkSurface flush calls in regards to semaphores. Made it
+ clear that the caller is responsible for deleting any initialized semaphores after the flush
+ call regardless if we were able to submit them or not. Also, allows skia to only submit a
+ subset of the requested semaphores if we failed to create some.
+ https://review.skia.org/282265
+
+
+ * SkCanvas::drawVertices will now always fill the triangles specified by the vertices. Previously,
+ vertices with no colors and no (texture coordinates or shader) would be drawn in wireframe.
+ https://review.skia.org/282043
+
+* * *
+
Milestone 83
------------
diff --git a/chromium/third_party/skia/specs/web-img-decode/proposed/impl/impl.js b/chromium/third_party/skia/specs/web-img-decode/proposed/impl/impl.js
index bf2c342cb2f..a75a69a8ba8 100644
--- a/chromium/third_party/skia/specs/web-img-decode/proposed/impl/impl.js
+++ b/chromium/third_party/skia/specs/web-img-decode/proposed/impl/impl.js
@@ -3,6 +3,9 @@
let CanvasKit = null;
window.loadPolyfill = () => {
+ // TODO(kjlubick): change ready().then() to just then() when using a newer version
+ // from npm (see
+ // https://skia.googlesource.com/skia/+/d1285b131bcf9c10fe1ad16fd2830c556715ed9e)
return CanvasKitInit({
locateFile: (file) => 'https://unpkg.com/canvaskit-wasm@0.6.0/bin/'+file,
}).ready().then((CK) => {
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.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/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.
diff --git a/chromium/third_party/skia/third_party/angle2/BUILD.gn b/chromium/third_party/skia/third_party/angle2/BUILD.gn
index e860f08bf07..46c980470e6 100644
--- a/chromium/third_party/skia/third_party/angle2/BUILD.gn
+++ b/chromium/third_party/skia/third_party/angle2/BUILD.gn
@@ -93,16 +93,20 @@ shared_library("libGLESv2") {
"LIBANGLE_IMPLEMENTATION",
"LIBGLESV2_IMPLEMENTATION",
]
- deps = [ ":commit_id" ]
+ deps = [
+ ":commit_id",
+ "../zlib:compression_utils_portable",
+ ]
libs = []
sources =
rebase_path(
angle_preprocessor_sources + angle_translator_sources +
angle_translator_essl_sources + angle_translator_glsl_sources +
angle_translator_hlsl_sources + libangle_sources +
- libangle_headers + libangle_common_sources +
- libangle_image_util_sources + libglesv2_sources +
- libangle_gl_sources + angle_system_utils_sources + xxhash_sources,
+ libangle_gpu_info_util_sources + libangle_headers +
+ libangle_common_sources + libangle_image_util_sources +
+ libglesv2_sources + libangle_gl_sources +
+ angle_system_utils_sources + xxhash_sources,
".",
angle_root) + [ "$angle_root/src/libANGLE/FrameCapture_mock.cpp" ]
if (is_win) {
@@ -114,9 +118,14 @@ shared_library("libGLESv2") {
"Xi",
"Xext",
]
- sources += rebase_path(libangle_gl_glx_sources + libangle_gl_egl_sources +
- libangle_gl_egl_dl_sources, ".", angle_root) +
- [ "$angle_root/src/third_party/libXNVCtrl/NVCtrl.c" ]
+ defines += [ "GPU_INFO_USE_X11" ]
+ sources +=
+ rebase_path(
+ libangle_gl_glx_sources + libangle_gl_egl_sources +
+ libangle_gpu_info_util_linux_sources +
+ libangle_gpu_info_util_x11_sources + libangle_gl_egl_dl_sources,
+ ".",
+ angle_root) + [ "$angle_root/src/third_party/libXNVCtrl/NVCtrl.c" ]
} else if (is_win) {
defines += [
# TODO: ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
@@ -124,7 +133,8 @@ shared_library("libGLESv2") {
sources +=
rebase_path(libangle_gl_wgl_sources + libangle_d3d_shared_sources +
libangle_d3d9_sources + libangle_d3d11_sources +
- libangle_d3d11_win32_sources,
+ libangle_d3d11_win32_sources +
+ libangle_gpu_info_util_win_sources,
".",
angle_root)
libs += [
diff --git a/chromium/third_party/skia/third_party/glslang/BUILD.gn b/chromium/third_party/skia/third_party/glslang/BUILD.gn
index e159c4a51ee..3ecb6260cd7 100644
--- a/chromium/third_party/skia/third_party/glslang/BUILD.gn
+++ b/chromium/third_party/skia/third_party/glslang/BUILD.gn
@@ -46,6 +46,21 @@ third_party("glslang_sources") {
"SPIRV/spvIR.h",
"glslang/GenericCodeGen/CodeGen.cpp",
"glslang/GenericCodeGen/Link.cpp",
+ "glslang/HLSL/hlslAttributes.cpp",
+ "glslang/HLSL/hlslAttributes.h",
+ "glslang/HLSL/hlslGrammar.cpp",
+ "glslang/HLSL/hlslGrammar.h",
+ "glslang/HLSL/hlslOpMap.cpp",
+ "glslang/HLSL/hlslOpMap.h",
+ "glslang/HLSL/hlslParseHelper.cpp",
+ "glslang/HLSL/hlslParseHelper.h",
+ "glslang/HLSL/hlslParseables.cpp",
+ "glslang/HLSL/hlslParseables.h",
+ "glslang/HLSL/hlslScanContext.cpp",
+ "glslang/HLSL/hlslScanContext.h",
+ "glslang/HLSL/hlslTokenStream.cpp",
+ "glslang/HLSL/hlslTokenStream.h",
+ "glslang/HLSL/hlslTokens.h",
"glslang/Include/BaseTypes.h",
"glslang/Include/Common.h",
"glslang/Include/ConstantUnion.h",
@@ -105,21 +120,6 @@ third_party("glslang_sources") {
"glslang/MachineIndependent/reflection.h",
"glslang/OSDependent/osinclude.h",
"glslang/Public/ShaderLang.h",
- "hlsl/hlslAttributes.cpp",
- "hlsl/hlslAttributes.h",
- "hlsl/hlslGrammar.cpp",
- "hlsl/hlslGrammar.h",
- "hlsl/hlslOpMap.cpp",
- "hlsl/hlslOpMap.h",
- "hlsl/hlslParseHelper.cpp",
- "hlsl/hlslParseHelper.h",
- "hlsl/hlslParseables.cpp",
- "hlsl/hlslParseables.h",
- "hlsl/hlslScanContext.cpp",
- "hlsl/hlslScanContext.h",
- "hlsl/hlslTokenStream.cpp",
- "hlsl/hlslTokenStream.h",
- "hlsl/hlslTokens.h",
],
".",
"$glslang_root")
diff --git a/chromium/third_party/skia/third_party/icu/BUILD.gn b/chromium/third_party/skia/third_party/icu/BUILD.gn
index 8c224ccfb52..0984c1891bb 100644
--- a/chromium/third_party/skia/third_party/icu/BUILD.gn
+++ b/chromium/third_party/skia/third_party/icu/BUILD.gn
@@ -68,6 +68,7 @@ if (skia_use_system_icu) {
]
public_defines = [
"U_USING_ICU_NAMESPACE=0",
+ "U_DISABLE_RENAMING",
"SK_USING_THIRD_PARTY_ICU",
]
configs -= [ "//gn:no_rtti" ]
diff --git a/chromium/third_party/skia/third_party/icu/config/BUILD.gn b/chromium/third_party/skia/third_party/icu/config/BUILD.gn
new file mode 100644
index 00000000000..dbccf48b368
--- /dev/null
+++ b/chromium/third_party/skia/third_party/icu/config/BUILD.gn
@@ -0,0 +1,12 @@
+# Copyright 2020 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Skia avoids the ICU C++ API, but third_party may use it.
+# Use this config to hide the C++ API.
+# This cannot go in ../BUILD.gn because it cannot be used in a flutter build.
+# This cannot go in a .gni file because gn doesn't like configs in .gni files.
+config("no_cxx") {
+ defines = [ "U_SHOW_CPLUSPLUS_API=0" ]
+}
diff --git a/chromium/third_party/skia/third_party/skcms/skcms.cc b/chromium/third_party/skia/third_party/skcms/skcms.cc
index ae5ba4ffe39..92af9634e6b 100644
--- a/chromium/third_party/skia/third_party/skcms/skcms.cc
+++ b/chromium/third_party/skia/third_party/skcms/skcms.cc
@@ -32,6 +32,11 @@
#endif
#endif
+static bool runtime_cpu_detection = true;
+void skcms_DisableRuntimeCPUDetection() {
+ runtime_cpu_detection = false;
+}
+
// sizeof(x) will return size_t, which is 32-bit on some machines and 64-bit on others.
// We have better testing on 64-bit machines, so force 32-bit machines to behave like 64-bit.
//
@@ -84,11 +89,12 @@ static float exp2f_(float x) {
// Before we cast fbits to int32_t, check for out of range values to pacify UBSAN.
// INT_MAX is not exactly representable as a float, so exclude it as effectively infinite.
- // INT_MIN is a power of 2 and exactly representable as a float, so it's fine.
+ // Negative values are effectively underflow - we'll end up returning a (different) negative
+ // value, which makes no sense. So clamp to zero.
if (fbits >= (float)INT_MAX) {
return INFINITY_;
- } else if (fbits < (float)INT_MIN) {
- return -INFINITY_;
+ } else if (fbits < 0) {
+ return 0;
}
int32_t bits = (int32_t)fbits;
@@ -2142,6 +2148,9 @@ namespace baseline {
enum class CpuType { None, HSW, SKX };
static CpuType cpu_type() {
static const CpuType type = []{
+ if (!runtime_cpu_detection) {
+ return CpuType::None;
+ }
// See http://www.sandpile.org/x86/cpuid.htm
// First, a basic cpuid(1) lets us check prerequisites for HSW, SKX.
diff --git a/chromium/third_party/skia/third_party/skcms/src/Transform_inl.h b/chromium/third_party/skia/third_party/skcms/src/Transform_inl.h
index c4b312286a2..2dcf717f3b7 100644
--- a/chromium/third_party/skia/third_party/skcms/src/Transform_inl.h
+++ b/chromium/third_party/skia/third_party/skcms/src/Transform_inl.h
@@ -287,9 +287,11 @@ SI F approx_exp2(F x) {
#else
F fract = x - floor_(x);
- I32 bits = cast<I32>((1.0f * (1<<23)) * (x + 121.274057500f
- - 1.490129070f*fract
- + 27.728023300f/(4.84252568f - fract)));
+ F fbits = (1.0f * (1<<23)) * (x + 121.274057500f
+ - 1.490129070f*fract
+ + 27.728023300f/(4.84252568f - fract));
+ I32 bits = cast<I32>(max_(fbits, F0));
+
return bit_pun<F>(bits);
#endif
}
diff --git a/chromium/third_party/skia/third_party/skcms/version.sha1 b/chromium/third_party/skia/third_party/skcms/version.sha1
index 1d419756fee..9f4fba2a1c3 100755
--- a/chromium/third_party/skia/third_party/skcms/version.sha1
+++ b/chromium/third_party/skia/third_party/skcms/version.sha1
@@ -1 +1 @@
-60d5d65325e6dfe54622937c300d9bd0d92b0a16 \ No newline at end of file
+403d32176ebc0f057e3ee7cb05c16fe209f61b7e
diff --git a/chromium/third_party/skia/third_party/third_party.gni b/chromium/third_party/skia/third_party/third_party.gni
index b0d106718d2..9b5e8b1a390 100644
--- a/chromium/third_party/skia/third_party/third_party.gni
+++ b/chromium/third_party/skia/third_party/third_party.gni
@@ -3,6 +3,10 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+declare_args() {
+ third_party_isystem = true
+}
+
template("third_party_config") {
enabled = !defined(invoker.enabled) || invoker.enabled
config(target_name) {
@@ -21,7 +25,7 @@ template("third_party_config") {
}
} else {
foreach(dir, invoker.include_dirs) {
- if (werror) {
+ if (third_party_isystem) {
cflags += [
"-isystem",
rebase_path(dir),
diff --git a/chromium/third_party/skia/third_party/zlib/BUILD.gn b/chromium/third_party/skia/third_party/zlib/BUILD.gn
index 40d00e916f2..d733c3c9a4f 100644
--- a/chromium/third_party/skia/third_party/zlib/BUILD.gn
+++ b/chromium/third_party/skia/third_party/zlib/BUILD.gn
@@ -14,13 +14,152 @@ if (skia_use_system_zlib) {
libs = [ "z" ]
}
} else {
+ # ARM optimizations disabled for Windows on Arm MSVC builds, see http://crbug.com/v8/10012.
+ use_arm_neon_optimizations =
+ (current_cpu == "arm" || current_cpu == "arm64") && !(is_win && !is_clang)
+ use_x86_x64_optimizations =
+ (current_cpu == "x86" || current_cpu == "x64") && !is_ios
+
+ config("zlib_simd_config") {
+ defines = []
+ if (use_x86_x64_optimizations) {
+ if (is_win) {
+ defines += [ "X86_WINDOWS" ]
+ } else {
+ defines += [ "X86_NOT_WINDOWS" ]
+ }
+ defines += [ "ADLER32_SIMD_SSSE3" ] # Strangely this is needed for
+ # cpu_features.c
+ }
+ if (use_arm_neon_optimizations) {
+ if (is_android) {
+ defines += [ "ARMV8_OS_ANDROID" ] # also compatible with v7
+ } else if (is_linux || is_chromeos) {
+ defines += [ "ARMV8_OS_LINUX" ]
+ } else if (is_fuchsia) {
+ defines += [ "ARMV8_OS_FUCHSIA" ]
+ } else if (is_win) {
+ defines += [ "ARMV8_OS_WINDOWS" ]
+ } else if (is_ios) {
+ # iOS@ARM is a special case where we always have NEON but don't check
+ # for crypto extensions.
+ defines += [ "ARM_OS_IOS" ]
+ } else {
+ assert(false, "Unsupported ARM OS")
+ }
+ }
+
+ # Warnings are just noise if we're not maintaining the code.
+ if (is_win) {
+ cflags = [ "/w" ]
+ } else {
+ cflags = [ "-w" ]
+ }
+ }
+
+ source_set("zlib_adler32_simd") {
+ visibility = [ ":*" ]
+ configs += [ ":zlib_simd_config" ]
+ if (use_x86_x64_optimizations) {
+ defines = [ "ADLER32_SIMD_SSSE3" ]
+ if (!is_win || is_clang) {
+ cflags = [ "-mssse3" ]
+ }
+ }
+ if (use_arm_neon_optimizations) {
+ defines = [ "ADLER32_SIMD_NEON" ]
+ }
+ sources = [ "../externals/zlib/adler32_simd.c" ]
+ }
+
+ source_set("zlib_crc32_simd") {
+ visibility = [ ":*" ]
+ configs += [ ":zlib_simd_config" ]
+
+ # Disabled for iPhone, as described in DDI0487C_a_armv8_arm:
+ # "All implementations of the ARMv8.1 architecture are required to
+ # implement the CRC32* instructions. These are optional in ARMv8.0."
+ if (!is_ios && use_arm_neon_optimizations) {
+ defines = [ "CRC32_ARMV8_CRC32" ]
+
+ # An ARMv7 GCC build will fail to compile without building this target
+ # for ARMv8-a+crc and letting runtime cpu detection select the correct
+ # function.
+ if (!is_win && !is_clang) {
+ cflags_c = [ "-march=armv8-a+crc" ]
+ }
+ }
+
+ if (use_x86_x64_optimizations) {
+ defines = [ "CRC32_SIMD_SSE42_PCLMUL" ]
+ if (!is_win || is_clang) {
+ cflags = [
+ "-msse4.2",
+ "-mpclmul",
+ ]
+ }
+ }
+
+ sources = [ "../externals/zlib/crc32_simd.c" ]
+ }
+
+ source_set("zlib_inflate_chunk_simd") {
+ visibility = [ ":*" ]
+ configs += [ ":zlib_simd_config" ]
+ if (use_x86_x64_optimizations) {
+ defines = [ "INFLATE_CHUNK_SIMD_SSE2" ]
+ if (current_cpu == "x64") {
+ defines += [ "INFLATE_CHUNK_READ_64LE" ]
+ }
+ }
+ if (use_arm_neon_optimizations) {
+ defines = [ "INFLATE_CHUNK_SIMD_NEON" ]
+ if (current_cpu == "arm64") {
+ defines += [ "INFLATE_CHUNK_READ_64LE" ]
+ }
+ }
+ if (use_x86_x64_optimizations || use_arm_neon_optimizations) {
+ include_dirs = [
+ "../externals/zlib/",
+ "../externals/zlib/contrib/optimizations/",
+ ]
+ sources = [
+ "../externals/zlib/contrib/optimizations/inffast_chunk.c",
+ "../externals/zlib/contrib/optimizations/inflate.c",
+ ]
+ }
+ }
+
+ source_set("zlib_x86_x64_simd") {
+ visibility = [ ":*" ]
+ configs += [ ":zlib_simd_config" ]
+ if (use_x86_x64_optimizations) {
+ defines = [
+ "CRC32_SIMD_SSE42_PCLMUL",
+ "DEFLATE_FILL_WINDOW_SSE2",
+ ]
+ if (!is_win || is_clang) {
+ cflags = [
+ "-msse4.2",
+ "-mpclmul",
+ ]
+ }
+ sources = [
+ "../externals/zlib/crc_folding.c",
+ "../externals/zlib/fill_window_sse.c",
+ ]
+ }
+ }
+
third_party("zlib") {
public_include_dirs = [ "../externals/zlib" ]
+ defines = [ "ZLIB_IMPLEMENTATION" ]
+ deps = []
- deps = [ ":zlib_x86" ]
sources = [
"../externals/zlib/adler32.c",
"../externals/zlib/compress.c",
+ "../externals/zlib/cpu_features.c",
"../externals/zlib/crc32.c",
"../externals/zlib/deflate.c",
"../externals/zlib/gzclose.c",
@@ -29,30 +168,37 @@ if (skia_use_system_zlib) {
"../externals/zlib/gzwrite.c",
"../externals/zlib/infback.c",
"../externals/zlib/inffast.c",
- "../externals/zlib/inflate.c",
"../externals/zlib/inftrees.c",
"../externals/zlib/trees.c",
"../externals/zlib/uncompr.c",
"../externals/zlib/zutil.c",
]
- }
-}
-third_party("zlib_x86") {
- public_include_dirs = []
- if (target_cpu == "x86" || target_cpu == "x64") {
- sources = [
- "../externals/zlib/crc_folding.c",
- "../externals/zlib/fill_window_sse.c",
- "../externals/zlib/x86.c",
- ]
- if (!is_win || is_clang) {
- cflags_c = [
- "-msse4.2",
- "-mpclmul",
+ if (is_android) {
+ deps += [ "//third_party/cpu-features" ]
+ }
+
+ if (!use_x86_x64_optimizations && !use_arm_neon_optimizations) {
+ defines += [ "CPU_NO_SIMD" ]
+ sources += [ "../externals/zlib/inflate.c" ]
+ } else {
+ configs += [ ":zlib_simd_config" ]
+ deps += [
+ ":zlib_adler32_simd",
+ ":zlib_crc32_simd",
+ ":zlib_inflate_chunk_simd",
+ ":zlib_x86_x64_simd",
]
}
- } else {
- sources = [ "../externals/zlib/simd_stub.c" ]
}
}
+
+third_party("compression_utils_portable") {
+ visibility = [ "//third_party/angle2:*" ]
+ public_include_dirs = [ "../externals/zlib/google" ]
+ sources = [
+ "../externals/zlib/google/compression_utils_portable.cc",
+ "../externals/zlib/google/compression_utils_portable.h",
+ ]
+ public_deps = [ ":zlib" ] # either system or from source
+}
diff --git a/chromium/third_party/skia/tools/DDLPromiseImageHelper.cpp b/chromium/third_party/skia/tools/DDLPromiseImageHelper.cpp
index 89dca3c80f7..2dba0b9f8cb 100644
--- a/chromium/third_party/skia/tools/DDLPromiseImageHelper.cpp
+++ b/chromium/third_party/skia/tools/DDLPromiseImageHelper.cpp
@@ -128,6 +128,7 @@ static GrBackendTexture create_yuva_texture(GrContext* context, const SkPixmap&
auto beTex = context->createBackendTexture(&pm, 1, GrRenderable::kNo, GrProtected::kNo,
markFinished, &finishedBECreate);
if (beTex.isValid()) {
+ context->submit();
while (!finishedBECreate) {
context->checkAsyncWorkCompletion();
}
@@ -175,6 +176,7 @@ void DDLPromiseImageHelper::CreateBETexturesForPromiseImage(GrContext* context,
GrRenderable::kNo, GrProtected::kNo,
markFinished, &finishedBECreate);
SkASSERT(backendTex.isValid());
+ context->submit();
while (!finishedBECreate) {
context->checkAsyncWorkCompletion();
}
diff --git a/chromium/third_party/skia/tools/DDLTileHelper.cpp b/chromium/third_party/skia/tools/DDLTileHelper.cpp
index 7771a6ec961..6333ded6219 100644
--- a/chromium/third_party/skia/tools/DDLTileHelper.cpp
+++ b/chromium/third_party/skia/tools/DDLTileHelper.cpp
@@ -109,6 +109,7 @@ void DDLTileHelper::createComposeDDL() {
}
fComposeDDL = recorder.detach();
+ SkASSERT(fComposeDDL);
}
void DDLTileHelper::TileData::precompile(GrContext* context) {
@@ -287,6 +288,11 @@ static void do_gpu_stuff(GrContext* context, DDLTileHelper::TileData* tile) {
tile->precompile(context);
tile->draw(context);
+
+ // TODO: remove this flush once DDLs are reffed by the drawing manager
+ context->flushAndSubmit();
+
+ tile->dropDDL();
}
// We expect to have more than one recording thread but just one gpu thread
@@ -315,6 +321,7 @@ void DDLTileHelper::kickOffThreadedWork(SkTaskGroup* recordingTaskGroup,
recordingTaskGroup->add([this] { this->createComposeDDL(); });
}
+// Only called from ViaDDL
void DDLTileHelper::precompileAndDrawAllTiles(GrContext* context) {
for (int i = 0; i < this->numTiles(); ++i) {
fTiles[i].precompile(context);
@@ -322,6 +329,7 @@ void DDLTileHelper::precompileAndDrawAllTiles(GrContext* context) {
}
}
+// Only called from skpbench
void DDLTileHelper::interleaveDDLCreationAndDraw(GrContext* context) {
for (int i = 0; i < this->numTiles(); ++i) {
fTiles[i].createDDL();
@@ -329,6 +337,7 @@ void DDLTileHelper::interleaveDDLCreationAndDraw(GrContext* context) {
}
}
+// Only called from skpbench
void DDLTileHelper::drawAllTilesDirectly(GrContext* context) {
for (int i = 0; i < this->numTiles(); ++i) {
fTiles[i].drawSKPDirectly(context);
diff --git a/chromium/third_party/skia/tools/DDLTileHelper.h b/chromium/third_party/skia/tools/DDLTileHelper.h
index 4430b52ee6f..bd9112acef3 100644
--- a/chromium/third_party/skia/tools/DDLTileHelper.h
+++ b/chromium/third_party/skia/tools/DDLTileHelper.h
@@ -44,6 +44,8 @@ public:
// Create the DDL for this tile (i.e., fill in 'fDisplayList').
void createDDL();
+ void dropDDL() { fDisplayList.reset(); }
+
// Precompile all the programs required to draw this tile's DDL
void precompile(GrContext*);
@@ -98,11 +100,11 @@ public:
const SkIRect& viewport,
int numDivisions);
- void createSKPPerTile(SkData* compressedPictureData, const DDLPromiseImageHelper& helper);
+ void createSKPPerTile(SkData* compressedPictureData, const DDLPromiseImageHelper&);
void kickOffThreadedWork(SkTaskGroup* recordingTaskGroup,
SkTaskGroup* gpuTaskGroup,
- GrContext* gpuThreadContext);
+ GrContext*);
void createDDLsInParallel();
diff --git a/chromium/third_party/skia/tools/convert-to-nia.cpp b/chromium/third_party/skia/tools/convert-to-nia.cpp
new file mode 100644
index 00000000000..58f9a67360f
--- /dev/null
+++ b/chromium/third_party/skia/tools/convert-to-nia.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// This program converts an image from stdin (e.g. a JPEG, PNG, etc.) to stdout
+// (in the NIA/NIE format, a trivial image file format).
+//
+// The NIA/NIE file format specification is at:
+// https://github.com/google/wuffs/blob/master/doc/spec/nie-spec.md
+//
+// Pass "-1" or "-first-frame-only" as a command line flag to output NIE (a
+// still image) instead of NIA (an animated image). The output format (NIA or
+// NIE) depends only on this flag's absence or presence, not on the stdin
+// image's format.
+//
+// There are multiple codec implementations of any given image format. For
+// example, as of May 2020, Chromium, Skia and Wuffs each have their own BMP
+// decoder implementation. There is no standard "libbmp" that they all share.
+// Comparing this program's output (or hashed output) to similar programs in
+// other repositories can identify image inputs for which these decoders (or
+// different versions of the same decoder) produce different output (pixels).
+//
+// An equivalent program (using the Chromium image codecs) is at:
+// https://crrev.com/c/2210331
+//
+// An equivalent program (using the Wuffs image codecs) is at:
+// https://github.com/google/wuffs/blob/master/example/convert-to-nia/convert-to-nia.c
+
+#include <stdio.h>
+#include <string.h>
+
+#include "include/codec/SkCodec.h"
+#include "include/core/SkBitmap.h"
+#include "include/core/SkData.h"
+#include "src/core/SkAutoMalloc.h"
+
+static inline void set_u32le(uint8_t* ptr, uint32_t val) {
+ ptr[0] = val >> 0;
+ ptr[1] = val >> 8;
+ ptr[2] = val >> 16;
+ ptr[3] = val >> 24;
+}
+
+static inline void set_u64le(uint8_t* ptr, uint64_t val) {
+ ptr[0] = val >> 0;
+ ptr[1] = val >> 8;
+ ptr[2] = val >> 16;
+ ptr[3] = val >> 24;
+ ptr[4] = val >> 32;
+ ptr[5] = val >> 40;
+ ptr[6] = val >> 48;
+ ptr[7] = val >> 56;
+}
+
+static void write_nix_header(uint32_t magicU32le, uint32_t width, uint32_t height) {
+ uint8_t data[16];
+ set_u32le(data + 0, magicU32le);
+ set_u32le(data + 4, 0x346E62FF); // 4 bytes per pixel non-premul BGRA.
+ set_u32le(data + 8, width);
+ set_u32le(data + 12, height);
+ fwrite(data, 1, 16, stdout);
+}
+
+static bool write_nia_duration(uint64_t totalDurationMillis) {
+ // Flicks are NIA's unit of time. One flick (frame-tick) is 1 / 705_600_000
+ // of a second. See https://github.com/OculusVR/Flicks
+ static constexpr uint64_t flicksPerMilli = 705600;
+ if (totalDurationMillis > (INT64_MAX / flicksPerMilli)) {
+ // Converting from millis to flicks would overflow.
+ return false;
+ }
+
+ uint8_t data[8];
+ set_u64le(data + 0, totalDurationMillis * flicksPerMilli);
+ fwrite(data, 1, 8, stdout);
+ return true;
+}
+
+static void write_nie_pixels(uint32_t width, uint32_t height, const SkBitmap& bm) {
+ static constexpr size_t kBufferSize = 4096;
+ uint8_t buf[kBufferSize];
+ size_t n = 0;
+ for (uint32_t y = 0; y < height; y++) {
+ for (uint32_t x = 0; x < width; x++) {
+ SkColor c = bm.getColor(x, y);
+ buf[n++] = SkColorGetB(c);
+ buf[n++] = SkColorGetG(c);
+ buf[n++] = SkColorGetR(c);
+ buf[n++] = SkColorGetA(c);
+ if (n == kBufferSize) {
+ fwrite(buf, 1, n, stdout);
+ n = 0;
+ }
+ }
+ }
+ if (n > 0) {
+ fwrite(buf, 1, n, stdout);
+ }
+}
+
+static void write_nia_padding(uint32_t width, uint32_t height) {
+ // 4 bytes of padding when the width and height are both odd.
+ if (width & height & 1) {
+ uint8_t data[4];
+ set_u32le(data + 0, 0);
+ fwrite(data, 1, 4, stdout);
+ }
+}
+
+static void write_nia_footer(int repetitionCount, bool stillImage) {
+ uint8_t data[8];
+ if (stillImage || (repetitionCount == SkCodec::kRepetitionCountInfinite)) {
+ set_u32le(data + 0, 0);
+ } else {
+ // NIA's loop count and Skia's repetition count differ by one. See
+ // https://github.com/google/wuffs/blob/master/doc/spec/nie-spec.md#nii-footer
+ set_u32le(data + 0, 1 + repetitionCount);
+ }
+ set_u32le(data + 4, 0x80000000);
+ fwrite(data, 1, 8, stdout);
+}
+
+int main(int argc, char** argv) {
+ bool firstFrameOnly = false;
+ for (int a = 1; a < argc; a++) {
+ if ((strcmp(argv[a], "-1") == 0) || (strcmp(argv[a], "-first-frame-only") == 0)) {
+ firstFrameOnly = true;
+ break;
+ }
+ }
+
+ std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(SkData::MakeFromFILE(stdin)));
+ if (!codec) {
+ SkDebugf("Decode failed.\n");
+ return 1;
+ }
+ codec->getInfo().makeColorSpace(nullptr);
+ SkBitmap bm;
+ bm.allocPixels(codec->getInfo());
+ size_t bmByteSize = bm.computeByteSize();
+
+ // Cache a frame that future frames may depend on.
+ int cachedFrame = SkCodec::kNoFrame;
+ SkAutoMalloc cachedFramePixels;
+
+ uint64_t totalDurationMillis = 0;
+ const int frameCount = codec->getFrameCount();
+ if (frameCount == 0) {
+ SkDebugf("No frames.\n");
+ return 1;
+ }
+ // The SkCodec::getFrameInfo comment says that this vector will be empty
+ // for still (not animated) images, even though frameCount should be 1.
+ std::vector<SkCodec::FrameInfo> frameInfos = codec->getFrameInfo();
+ bool stillImage = frameInfos.empty();
+
+ for (int i = 0; i < frameCount; i++) {
+ SkCodec::Options opts;
+ opts.fFrameIndex = i;
+
+ if (!stillImage) {
+ int durationMillis = frameInfos[i].fDuration;
+ if (durationMillis < 0) {
+ SkDebugf("Negative animation duration.\n");
+ return 1;
+ }
+ totalDurationMillis += static_cast<uint64_t>(durationMillis);
+ if (totalDurationMillis > INT64_MAX) {
+ SkDebugf("Unsupported animation duration.\n");
+ return 1;
+ }
+
+ if ((cachedFrame != SkCodec::kNoFrame) &&
+ (cachedFrame == frameInfos[i].fRequiredFrame) && cachedFramePixels.get()) {
+ opts.fPriorFrame = cachedFrame;
+ memcpy(bm.getPixels(), cachedFramePixels.get(), bmByteSize);
+ }
+ }
+
+ if (!firstFrameOnly) {
+ if (i == 0) {
+ write_nix_header(0x41AFC36E, // "nïA" magic string as a u32le.
+ bm.width(), bm.height());
+ }
+
+ if (!write_nia_duration(totalDurationMillis)) {
+ SkDebugf("Unsupported animation duration.\n");
+ return 1;
+ }
+ }
+
+ const SkCodec::Result result =
+ codec->getPixels(codec->getInfo(), bm.getPixels(), bm.rowBytes(), &opts);
+ if ((result != SkCodec::kSuccess) && (result != SkCodec::kIncompleteInput)) {
+ SkDebugf("Decode frame pixels #%d failed.\n", i);
+ return 1;
+ }
+
+ // If the next frame depends on this one, store it in cachedFrame. It
+ // is possible that we may discard a frame that future frames depend
+ // on, but the codec will simply redecode the discarded frame.
+ if ((static_cast<size_t>(i + 1) < frameInfos.size()) &&
+ (frameInfos[i + 1].fRequiredFrame == i)) {
+ cachedFrame = i;
+ memcpy(cachedFramePixels.reset(bmByteSize), bm.getPixels(), bmByteSize);
+ }
+
+ int width = bm.width();
+ int height = bm.height();
+ write_nix_header(0x45AFC36E, // "nïE" magic string as a u32le.
+ width, height);
+ write_nie_pixels(width, height, bm);
+ if (result == SkCodec::kIncompleteInput) {
+ SkDebugf("Incomplete input.\n");
+ return 1;
+ }
+ if (firstFrameOnly) {
+ return 0;
+ }
+ write_nia_padding(width, height);
+ }
+ write_nia_footer(codec->getRepetitionCount(), stillImage);
+ return 0;
+}
diff --git a/chromium/third_party/skia/tools/debugger/DebugCanvas.cpp b/chromium/third_party/skia/tools/debugger/DebugCanvas.cpp
index 11b76085241..95d2e06e0cf 100644
--- a/chromium/third_party/skia/tools/debugger/DebugCanvas.cpp
+++ b/chromium/third_party/skia/tools/debugger/DebugCanvas.cpp
@@ -328,11 +328,11 @@ void DebugCanvas::didConcat44(const SkM44& m) {
}
void DebugCanvas::didScale(SkScalar x, SkScalar y) {
- this->didConcat(SkMatrix::MakeScale(x, y));
+ this->didConcat(SkMatrix::Scale(x, y));
}
void DebugCanvas::didTranslate(SkScalar x, SkScalar y) {
- this->didConcat(SkMatrix::MakeTrans(x, y));
+ this->didConcat(SkMatrix::Translate(x, y));
}
void DebugCanvas::didConcat(const SkMatrix& matrix) {
diff --git a/chromium/third_party/skia/tools/fiddle/all_examples.cpp b/chromium/third_party/skia/tools/fiddle/all_examples.cpp
index 9046fee7f6c..3850ee0a22c 100644
--- a/chromium/third_party/skia/tools/fiddle/all_examples.cpp
+++ b/chromium/third_party/skia/tools/fiddle/all_examples.cpp
@@ -261,7 +261,6 @@
#include "../../docs/examples/Difference.cpp"
#include "../../docs/examples/Dither_a.cpp"
#include "../../docs/examples/Dither_b.cpp"
-#include "../../docs/examples/Draw_Looper_Methods.cpp"
#include "../../docs/examples/Dst.cpp"
#include "../../docs/examples/Dst_Atop.cpp"
#include "../../docs/examples/Dst_In.cpp"
@@ -538,7 +537,6 @@
#include "../../docs/examples/Paint_getColor.cpp"
#include "../../docs/examples/Paint_getColor4f.cpp"
#include "../../docs/examples/Paint_getColorFilter.cpp"
-#include "../../docs/examples/Paint_getDrawLooper.cpp"
#include "../../docs/examples/Paint_getFillPath.cpp"
#include "../../docs/examples/Paint_getFillPath_2.cpp"
#include "../../docs/examples/Paint_getFilterQuality.cpp"
@@ -579,7 +577,6 @@
#include "../../docs/examples/Paint_notequal_operator.cpp"
#include "../../docs/examples/Paint_nothingToDraw.cpp"
#include "../../docs/examples/Paint_refColorFilter.cpp"
-#include "../../docs/examples/Paint_refDrawLooper.cpp"
#include "../../docs/examples/Paint_refImageFilter.cpp"
#include "../../docs/examples/Paint_refMaskFilter.cpp"
#include "../../docs/examples/Paint_refPathEffect.cpp"
@@ -595,7 +592,6 @@
#include "../../docs/examples/Paint_setColor4f.cpp"
#include "../../docs/examples/Paint_setColorFilter.cpp"
#include "../../docs/examples/Paint_setDither.cpp"
-#include "../../docs/examples/Paint_setDrawLooper.cpp"
#include "../../docs/examples/Paint_setEmbeddedBitmapText.cpp"
#include "../../docs/examples/Paint_setFakeBoldText.cpp"
#include "../../docs/examples/Paint_setFilterQuality.cpp"
@@ -1043,7 +1039,6 @@
#include "../../docs/examples/State_Stack_b.cpp"
#include "../../docs/examples/Stroke_Width.cpp"
#include "../../docs/examples/Surface_MakeFromBackendTexture.cpp"
-#include "../../docs/examples/Surface_MakeFromBackendTextureAsRenderTarget.cpp"
#include "../../docs/examples/Surface_MakeNull.cpp"
#include "../../docs/examples/Surface_MakeRaster.cpp"
#include "../../docs/examples/Surface_MakeRasterDirect.cpp"
diff --git a/chromium/third_party/skia/tools/fiddle/disabled_examples.txt b/chromium/third_party/skia/tools/fiddle/disabled_examples.txt
index 3970425b03e..1c568526b76 100644
--- a/chromium/third_party/skia/tools/fiddle/disabled_examples.txt
+++ b/chromium/third_party/skia/tools/fiddle/disabled_examples.txt
@@ -174,7 +174,6 @@ docs/examples/Region_op_6.cpp
docs/examples/Region_setPath.cpp
docs/examples/Region_writeToMemory.cpp
docs/examples/Surface_MakeFromBackendTexture.cpp
-docs/examples/Surface_MakeFromBackendTextureAsRenderTarget.cpp
docs/examples/Surface_MakeRenderTarget.cpp
docs/examples/Surface_MakeRenderTarget_2.cpp
docs/examples/Surface_MakeRenderTarget_3.cpp
diff --git a/chromium/third_party/skia/tools/fiddle/documumentation_examples_map.txt b/chromium/third_party/skia/tools/fiddle/documumentation_examples_map.txt
index 2a98cc07111..46ef1c5b400 100644
--- a/chromium/third_party/skia/tools/fiddle/documumentation_examples_map.txt
+++ b/chromium/third_party/skia/tools/fiddle/documumentation_examples_map.txt
@@ -2022,10 +2022,6 @@ SkColor4f getColor4f() const;
SkPaint
SkColorFilter* getColorFilter() const;
-[Paint_getDrawLooper]
-SkPaint
-SkDrawLooper* getDrawLooper() const;
-
[Paint_getFillPath_2]
[Shader_Methods_a]
[Shader_Methods_b]
@@ -2196,10 +2192,6 @@ bool operator==(const SkPaint& a, const SkPaint& b);
SkPaint
sk_sp<SkColorFilter> refColorFilter() const;
-[Paint_refDrawLooper]
-SkPaint
-sk_sp<SkDrawLooper> refDrawLooper() const;
-
[Paint_refImageFilter]
SkPaint
sk_sp<SkImageFilter> refImageFilter() const;
@@ -2266,11 +2258,6 @@ void setColorFilter(sk_sp<SkColorFilter> colorFilter);
SkPaint
void setDither(bool dither);
-[Paint_setDrawLooper]
-[Text_Size]
-SkPaint
-void setDrawLooper(sk_sp<SkDrawLooper> drawLooper);
-
[Paint_setEmbeddedBitmapText]
SkPaint
void setEmbeddedBitmapText(bool useEmbeddedBitmapText);
@@ -2294,11 +2281,6 @@ void setFlags(uint32_t flags);
SkPaint
void setHinting(SkFontHinting hintingLevel);
-[Draw_Looper_Methods]
-[Paint_setImageFilter]
-SkPaint
-void setImageFilter(sk_sp<SkImageFilter> imageFilter);
-
[Paint_setLCDRenderText]
SkPaint
void setLCDRenderText(bool lcdText);
@@ -3924,10 +3906,6 @@ SkRegion
SkSurface
static sk_sp<SkSurface> MakeFromBackendTexture(GrContext* context, const GrBackendTexture& backendTexture, GrSurfaceOrigin origin, int sampleCnt, SkColorType colorType, sk_sp<SkColorSpace> colorSpace, const SkSurfaceProps* surfaceProps);
-[Surface_MakeFromBackendTextureAsRenderTarget]
-SkSurface
-static sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(GrContext* context, const GrBackendTexture& backendTexture, GrSurfaceOrigin origin, int sampleCnt, SkColorType colorType, sk_sp<SkColorSpace> colorSpace, const SkSurfaceProps* surfaceProps);
-
[Surface_MakeNull]
SkSurface
static sk_sp<SkSurface> MakeNull(int width, int height);
diff --git a/chromium/third_party/skia/tools/flags/CommonFlagsConfig.cpp b/chromium/third_party/skia/tools/flags/CommonFlagsConfig.cpp
index fa0c414363e..0dc0a52d470 100644
--- a/chromium/third_party/skia/tools/flags/CommonFlagsConfig.cpp
+++ b/chromium/third_party/skia/tools/flags/CommonFlagsConfig.cpp
@@ -72,6 +72,7 @@ static const struct {
{ "gltestprecompile", "gpu", "api=gl,testPrecompile=true" },
{ "glestestprecompile", "gpu", "api=gles,testPrecompile=true" },
{ "glddl", "gpu", "api=gl,useDDLSink=true" },
+ { "glooprddl", "gpu", "api=gl,OOPRish=true" },
{ "angle_d3d11_es2", "gpu", "api=angle_d3d11_es2" },
{ "angle_d3d11_es3", "gpu", "api=angle_d3d11_es3" },
{ "angle_d3d9_es2", "gpu", "api=angle_d3d9_es2" },
@@ -103,6 +104,7 @@ static const struct {
{ "vkbert", "gpu", "api=vulkan,surf=bert" },
{ "vktestpersistentcache", "gpu", "api=vulkan,testPersistentCache=1" },
{ "vkddl", "gpu", "api=vulkan,useDDLSink=true" },
+ { "vkooprddl", "gpu", "api=vulkan,OOPRish=true" },
#endif
#ifdef SK_METAL
{ "mtl", "gpu", "api=metal" },
@@ -110,6 +112,7 @@ static const struct {
{ "mtlmsaa4", "gpu", "api=metal,samples=4" },
{ "mtlmsaa8", "gpu", "api=metal,samples=8" },
{ "mtlddl", "gpu", "api=metal,useDDLSink=true" },
+ { "mtlooprddl", "gpu", "api=metal,OOPRish=true" },
#endif
#ifdef SK_DIRECT3D
{ "d3d", "gpu", "api=direct3d" },
@@ -459,6 +462,7 @@ SkCommandLineConfigGpu::SkCommandLineConfigGpu(const SkString& tag,
int testPersistentCache,
bool testPrecompile,
bool useDDLSink,
+ bool OOPRish,
SurfType surfType)
: SkCommandLineConfig(tag, SkString("gpu"), viaParts)
, fContextType(contextType)
@@ -472,6 +476,7 @@ SkCommandLineConfigGpu::SkCommandLineConfigGpu(const SkString& tag,
, fTestPersistentCache(testPersistentCache)
, fTestPrecompile(testPrecompile)
, fUseDDLSink(useDDLSink)
+ , fOOPRish(OOPRish)
, fSurfType(surfType) {
if (!useStencilBuffers) {
fContextOverrides |= ContextOverrides::kAvoidStencilBuffers;
@@ -493,6 +498,7 @@ SkCommandLineConfigGpu* parse_command_line_config_gpu(const SkString&
int testPersistentCache = 0;
bool testPrecompile = false;
bool useDDLs = false;
+ bool ooprish = false;
SkCommandLineConfigGpu::SurfType surfType = SkCommandLineConfigGpu::SurfType::kDefault;
bool parseSucceeded = false;
@@ -511,6 +517,7 @@ SkCommandLineConfigGpu* parse_command_line_config_gpu(const SkString&
extendedOptions.get_option_int("testPersistentCache", &testPersistentCache) &&
extendedOptions.get_option_bool("testPrecompile", &testPrecompile) &&
extendedOptions.get_option_bool("useDDLSink", &useDDLs) &&
+ extendedOptions.get_option_bool("OOPRish", &ooprish) &&
extendedOptions.get_option_gpu_surf_type("surf", &surfType);
// testing threading and the persistent cache are mutually exclusive.
@@ -531,6 +538,7 @@ SkCommandLineConfigGpu* parse_command_line_config_gpu(const SkString&
testPersistentCache,
testPrecompile,
useDDLs,
+ ooprish,
surfType);
}
diff --git a/chromium/third_party/skia/tools/flags/CommonFlagsConfig.h b/chromium/third_party/skia/tools/flags/CommonFlagsConfig.h
index f4ae2949ea1..02bd8569a41 100644
--- a/chromium/third_party/skia/tools/flags/CommonFlagsConfig.h
+++ b/chromium/third_party/skia/tools/flags/CommonFlagsConfig.h
@@ -64,6 +64,7 @@ public:
int testPersistentCache,
bool testPrecompile,
bool useDDLSink,
+ bool OOPRish,
SurfType);
const SkCommandLineConfigGpu* asConfigGpu() const override { return this; }
@@ -78,6 +79,7 @@ public:
int getTestPersistentCache() const { return fTestPersistentCache; }
bool getTestPrecompile() const { return fTestPrecompile; }
bool getUseDDLSink() const { return fUseDDLSink; }
+ bool getOOPRish() const { return fOOPRish; }
SurfType getSurfType() const { return fSurfType; }
private:
@@ -92,6 +94,7 @@ private:
int fTestPersistentCache;
bool fTestPrecompile;
bool fUseDDLSink;
+ bool fOOPRish;
SurfType fSurfType;
};
diff --git a/chromium/third_party/skia/tools/flags/CommonFlagsGpu.cpp b/chromium/third_party/skia/tools/flags/CommonFlagsGpu.cpp
index b00bf8892d8..4f15944e750 100644
--- a/chromium/third_party/skia/tools/flags/CommonFlagsGpu.cpp
+++ b/chromium/third_party/skia/tools/flags/CommonFlagsGpu.cpp
@@ -60,7 +60,7 @@ static GpuPathRenderers get_named_pathrenderers_flags(const char* name) {
} else if (!strcmp(name, "default")) {
return GpuPathRenderers::kDefault;
}
- SK_ABORT(SkStringPrintf("error: unknown named path renderer \"%s\"\n", name).c_str());
+ SK_ABORT("error: unknown named path renderer \"%s\"\n", name);
}
static GpuPathRenderers collect_gpu_path_renderers_from_flags() {
diff --git a/chromium/third_party/skia/tools/fm/fm.cpp b/chromium/third_party/skia/tools/fm/fm.cpp
index 75f1389eaa8..b9909133140 100644
--- a/chromium/third_party/skia/tools/fm/fm.cpp
+++ b/chromium/third_party/skia/tools/fm/fm.cpp
@@ -132,6 +132,12 @@ static void init(Source* source, std::shared_ptr<skiagm::GM> gm) {
source->tweak = [gm](GrContextOptions* options) { gm->modifyGrContextOptions(options); };
source->draw = [gm](SkCanvas* canvas) {
SkString err;
+ switch (gm->gpuSetup(canvas->getGrContext(), &err)) {
+ case skiagm::DrawResult::kOk : break;
+ case skiagm::DrawResult::kSkip: return skip;
+ case skiagm::DrawResult::kFail: return fail(err.c_str());
+ }
+
switch (gm->draw(canvas, &err)) {
case skiagm::DrawResult::kOk: break;
case skiagm::DrawResult::kSkip: return skip;
@@ -573,7 +579,7 @@ int main(int argc, char** argv) {
case Result::Ok: break;
case Result::Skip: return false;
case Result::Fail:
- SK_ABORT(result.failure.c_str());
+ SK_ABORT("%s", result.failure.c_str());
}
return true;
};
diff --git a/chromium/third_party/skia/tools/fonts/TestSVGTypeface.cpp b/chromium/third_party/skia/tools/fonts/TestSVGTypeface.cpp
index 1bba3a608e0..c10bb2185d7 100644
--- a/chromium/third_party/skia/tools/fonts/TestSVGTypeface.cpp
+++ b/chromium/third_party/skia/tools/fonts/TestSVGTypeface.cpp
@@ -772,7 +772,7 @@ void TestSVGTypeface::exportTtxCbdt(SkWStream* out, SkSpan<unsigned> strikeSizes
-bounds.fTop,
font,
paint);
- surface->flush();
+ surface->flushAndSubmit();
sk_sp<SkImage> image = surface->makeImageSnapshot();
sk_sp<SkData> data = image->encodeToData(SkEncodedImageFormat::kPNG, 100);
@@ -994,7 +994,7 @@ void TestSVGTypeface::exportTtxSbix(SkWStream* out, SkSpan<unsigned> strikeSizes
-bounds.fTop,
font,
paint);
- surface->flush();
+ surface->flushAndSubmit();
sk_sp<SkImage> image = surface->makeImageSnapshot();
sk_sp<SkData> data = image->encodeToData(SkEncodedImageFormat::kPNG, 100);
diff --git a/chromium/third_party/skia/tools/fonts/TestTypeface.cpp b/chromium/third_party/skia/tools/fonts/TestTypeface.cpp
index 7f30f01c1d2..f32f77aa03f 100644
--- a/chromium/third_party/skia/tools/fonts/TestTypeface.cpp
+++ b/chromium/third_party/skia/tools/fonts/TestTypeface.cpp
@@ -132,7 +132,7 @@ void TestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) co
*isLocal = false;
}
-void TestTypeface::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
+void TestTypeface::onCharsToGlyphs(const SkUnichar* uni, int count, SkGlyphID glyphs[]) const {
for (int i = 0; i < count; ++i) {
glyphs[i] = fTestFont->glyphForUnichar(uni[i]);
}
diff --git a/chromium/third_party/skia/tools/gpu/GrContextFactory.cpp b/chromium/third_party/skia/tools/gpu/GrContextFactory.cpp
index 13cc9792050..f7356f57fb8 100644
--- a/chromium/third_party/skia/tools/gpu/GrContextFactory.cpp
+++ b/chromium/third_party/skia/tools/gpu/GrContextFactory.cpp
@@ -90,7 +90,8 @@ void GrContextFactory::abandonContexts() {
auto restore = context.fTestContext->makeCurrentAndAutoRestore();
context.fTestContext->testAbandon();
}
- bool requiresEarlyAbandon = (context.fGrContext->backend() == GrBackendApi::kVulkan);
+ GrBackendApi api = context.fGrContext->backend();
+ bool requiresEarlyAbandon = api == GrBackendApi::kVulkan || api == GrBackendApi::kDawn;
if (requiresEarlyAbandon) {
context.fGrContext->abandonContext();
}
diff --git a/chromium/third_party/skia/tools/gpu/GrTest.cpp b/chromium/third_party/skia/tools/gpu/GrTest.cpp
index 2a030d43eb0..d6286674e72 100644
--- a/chromium/third_party/skia/tools/gpu/GrTest.cpp
+++ b/chromium/third_party/skia/tools/gpu/GrTest.cpp
@@ -54,20 +54,18 @@ int GrResourceCache::countUniqueKeysWithTag(const char* tag) const {
///////////////////////////////////////////////////////////////////////////////
-#define ASSERT_SINGLE_OWNER \
- SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());)
-
+#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fRenderTargetContext->singleOwner())
uint32_t GrRenderTargetContextPriv::testingOnly_getOpsTaskID() {
return fRenderTargetContext->getOpsTask()->uniqueID();
}
void GrRenderTargetContextPriv::testingOnly_addDrawOp(std::unique_ptr<GrDrawOp> op) {
- this->testingOnly_addDrawOp(GrNoClip(), std::move(op));
+ this->testingOnly_addDrawOp(nullptr, std::move(op), {});
}
void GrRenderTargetContextPriv::testingOnly_addDrawOp(
- const GrClip& clip,
+ const GrClip* clip,
std::unique_ptr<GrDrawOp> op,
const std::function<GrRenderTargetContext::WillAddOpFn>& willAddFn) {
ASSERT_SINGLE_OWNER
diff --git a/chromium/third_party/skia/tools/gpu/MemoryCache.cpp b/chromium/third_party/skia/tools/gpu/MemoryCache.cpp
index d8fdaf71578..93ef2b14a47 100644
--- a/chromium/third_party/skia/tools/gpu/MemoryCache.cpp
+++ b/chromium/third_party/skia/tools/gpu/MemoryCache.cpp
@@ -57,6 +57,7 @@ void MemoryCache::store(const SkData& key, const SkData& data) {
SkDebugf("Store Key: %s\n\tData: %s\n\n", data_to_str(key).c_str(),
data_to_str(data).c_str());
}
+ ++fCacheStoreCnt;
fMap[Key(key)] = Value(data);
}
@@ -96,7 +97,7 @@ void MemoryCache::writeShadersToDisk(const char* path, GrBackendApi api) {
// Even with the SPIR-V switches, it seems like we must use .spv, or malisc tries to
// run glslang on the input.
const char* ext = GrBackendApi::kOpenGL == api ? "frag" : "spv";
- SkReader32 reader(data->data(), data->size());
+ SkReadBuffer reader(data->data(), data->size());
GrPersistentCacheUtils::GetType(&reader); // Shader type tag
GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders,
inputsIgnored, kGrShaderTypeCount);
diff --git a/chromium/third_party/skia/tools/gpu/MemoryCache.h b/chromium/third_party/skia/tools/gpu/MemoryCache.h
index 22911a5413b..f70cf1388e8 100644
--- a/chromium/third_party/skia/tools/gpu/MemoryCache.h
+++ b/chromium/third_party/skia/tools/gpu/MemoryCache.h
@@ -28,14 +28,18 @@ public:
MemoryCache(const MemoryCache&) = delete;
MemoryCache& operator=(const MemoryCache&) = delete;
void reset() {
- fCacheMissCnt = 0;
+ this->resetCacheStats();
fMap.clear();
}
sk_sp<SkData> load(const SkData& key) override;
void store(const SkData& key, const SkData& data) override;
int numCacheMisses() const { return fCacheMissCnt; }
- void resetNumCacheMisses() { fCacheMissCnt = 0; }
+ int numCacheStores() const { return fCacheStoreCnt; }
+ void resetCacheStats() {
+ fCacheMissCnt = 0;
+ fCacheStoreCnt = 0;
+ }
void writeShadersToDisk(const char* path, GrBackendApi backend);
@@ -80,6 +84,7 @@ private:
};
int fCacheMissCnt = 0;
+ int fCacheStoreCnt = 0;
std::unordered_map<Key, Value, Hash> fMap;
};
diff --git a/chromium/third_party/skia/tools/gpu/TestContext.cpp b/chromium/third_party/skia/tools/gpu/TestContext.cpp
index cdd86c4fc4b..9b9e5dcbb9d 100644
--- a/chromium/third_party/skia/tools/gpu/TestContext.cpp
+++ b/chromium/third_party/skia/tools/gpu/TestContext.cpp
@@ -54,6 +54,7 @@ void TestContext::flushAndWaitOnSync(GrContext* context) {
flushInfo.fFinishedContext = fFinishTrackers[fCurrentFlushIdx].get();
context->flush(flushInfo);
+ context->submit();
fCurrentFlushIdx = (fCurrentFlushIdx + 1) % SK_ARRAY_COUNT(fFinishTrackers);
}
diff --git a/chromium/third_party/skia/tools/gpu/TestOps.cpp b/chromium/third_party/skia/tools/gpu/TestOps.cpp
index ff5201a2c98..1ef7420d74c 100644
--- a/chromium/third_party/skia/tools/gpu/TestOps.cpp
+++ b/chromium/third_party/skia/tools/gpu/TestOps.cpp
@@ -32,26 +32,29 @@ public:
const char* name() const override { return "TestRectOp::GP"; }
- GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps& caps) const override;
+ GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps& caps) const override {
+ return new GLSLGP();
+ }
- void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
+ void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
+ GLSLGP::GenKey(*this, b);
+ }
bool wideColor() const { return fInColor.cpuType() != kUByte4_norm_GrVertexAttribType; }
private:
- Attribute fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
- Attribute fInLocalCoords = {"inLocalCoords", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
- Attribute fInColor;
- SkMatrix fLocalMatrix;
-};
-
-GrGLSLPrimitiveProcessor* GP::createGLSLInstance(const GrShaderCaps& caps) const {
class GLSLGP : public GrGLSLGeometryProcessor {
+ public:
void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& pp,
const CoordTransformRange& transformRange) override {
const auto& gp = pp.cast<GP>();
- this->setTransformDataHelper(gp.fLocalMatrix, pdman, transformRange);
+ this->setTransformDataHelper(pdman, transformRange);
+ this->setTransform(pdman, fLocalMatrixUni, gp.fLocalMatrix);
+ }
+
+ static void GenKey(const GP& gp, GrProcessorKeyBuilder* b) {
+ b->add32(ComputeMatrixKey(gp.fLocalMatrix));
}
private:
@@ -65,13 +68,19 @@ GrGLSLPrimitiveProcessor* GP::createGLSLInstance(const GrShaderCaps& caps) const
args.fFragBuilder->codeAppendf("%s = %s;", args.fOutputColor, colorVarying.fsIn());
args.fFragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
this->writeOutputPosition(args.fVertBuilder, gpArgs, gp.fInPosition.name());
- this->emitTransforms(args.fVertBuilder, args.fVaryingHandler, args.fUniformHandler,
- gp.fInLocalCoords.asShaderVar(), gp.fLocalMatrix,
- args.fFPCoordTransformHandler);
+ this->writeLocalCoord(args.fVertBuilder, args.fUniformHandler, gpArgs,
+ gp.fInLocalCoords.asShaderVar(), gp.fLocalMatrix,
+ &fLocalMatrixUni);
}
+
+ UniformHandle fLocalMatrixUni;
};
- return new GLSLGP();
-}
+
+ Attribute fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
+ Attribute fInLocalCoords = {"inLocalCoords", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
+ Attribute fInColor;
+ SkMatrix fLocalMatrix;
+};
class TestRectOp final : public GrMeshDrawOp {
public:
diff --git a/chromium/third_party/skia/tools/gpu/YUVUtils.cpp b/chromium/third_party/skia/tools/gpu/YUVUtils.cpp
index eb4ca2c3d12..5b941358e3f 100644
--- a/chromium/third_party/skia/tools/gpu/YUVUtils.cpp
+++ b/chromium/third_party/skia/tools/gpu/YUVUtils.cpp
@@ -85,4 +85,29 @@ bool LazyYUVImage::ensureYUVImage(GrContext* context) {
return fYUVImage != nullptr;
}
+///////////////////////////////////////////////////////////////////////////////////////////////////
+void YUVABackendReleaseContext::Unwind(GrContext* context, YUVABackendReleaseContext* beContext) {
+ // Some backends (e.g., Vulkan) require that all work associated w/ texture
+ // creation be completed before deleting the textures.
+ GrFlushInfo flushInfoSyncCpu;
+ flushInfoSyncCpu.fFlags = kSyncCpu_GrFlushFlag;
+ context->flush(flushInfoSyncCpu);
+ context->submit(true);
+
+ delete beContext;
+}
+
+YUVABackendReleaseContext::YUVABackendReleaseContext(GrContext* context) : fContext(context) {
+ SkASSERT(context->priv().getGpu());
+ SkASSERT(context->priv().asDirectContext());
+}
+
+YUVABackendReleaseContext::~YUVABackendReleaseContext() {
+ for (int i = 0; i < 4; ++i) {
+ if (fBETextures[i].isValid()) {
+ fContext->deleteBackendTexture(fBETextures[i]);
+ }
+ }
+}
+
} // namespace sk_gpu_test
diff --git a/chromium/third_party/skia/tools/gpu/YUVUtils.h b/chromium/third_party/skia/tools/gpu/YUVUtils.h
index f6097b9476d..bfca6f41fe3 100644
--- a/chromium/third_party/skia/tools/gpu/YUVUtils.h
+++ b/chromium/third_party/skia/tools/gpu/YUVUtils.h
@@ -11,6 +11,7 @@
#include "include/core/SkImage.h"
#include "include/core/SkYUVAIndex.h"
#include "include/core/SkYUVASizeInfo.h"
+#include "include/gpu/GrBackendSurface.h"
#include "src/core/SkAutoMalloc.h"
class SkData;
@@ -49,6 +50,45 @@ private:
bool ensureYUVImage(GrContext* context);
};
+// A helper for managing the lifetime of backend textures for YUVA images.
+class YUVABackendReleaseContext {
+public:
+ // A stock 'TextureReleaseProc' to use with this class
+ static void Release(void* releaseContext) {
+ auto beContext = reinterpret_cast<YUVABackendReleaseContext*>(releaseContext);
+
+ delete beContext;
+ }
+
+ // Given how and when backend textures are created, just deleting this object often
+ // isn't enough. This helper encapsulates the extra work needed.
+ static void Unwind(GrContext* context, YUVABackendReleaseContext* beContext);
+
+ YUVABackendReleaseContext(GrContext* context);
+ ~YUVABackendReleaseContext();
+
+ void set(int index, const GrBackendTexture& beTex) {
+ SkASSERT(index >= 0 && index < 4);
+ SkASSERT(!fBETextures[index].isValid());
+ SkASSERT(beTex.isValid());
+
+ fBETextures[index] = beTex;
+ }
+
+ const GrBackendTexture* beTextures() const { return fBETextures; }
+
+ const GrBackendTexture& beTexture(int index) {
+ SkASSERT(index >= 0 && index < 4);
+ SkASSERT(fBETextures[index].isValid());
+ return fBETextures[index];
+ }
+
+private:
+ GrContext* fContext;
+ GrBackendTexture fBETextures[4];
+};
+
+
} // namespace sk_gpu_test
#endif // YUVUtils_DEFINED
diff --git a/chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.cpp b/chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.cpp
deleted file mode 100644
index c8dc0540fce..00000000000
--- a/chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.cpp
+++ /dev/null
@@ -1,483 +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/core/SkBitmap.h"
-#include "src/gpu/gl/GrGLDefines.h"
-#include "src/gpu/gl/GrGLUtil.h"
-#include "tools/gpu/atlastext/GLTestAtlasTextRenderer.h"
-#include "tools/gpu/atlastext/TestAtlasTextRenderer.h"
-#include "tools/gpu/gl/GLTestContext.h"
-
-using sk_gpu_test::GLTestContext;
-
-namespace {
-
-class GLTestAtlasTextRenderer : public sk_gpu_test::TestAtlasTextRenderer {
-public:
- GLTestAtlasTextRenderer(std::unique_ptr<GLTestContext>);
-
- void* createTexture(AtlasFormat, int width, int height) override;
-
- void deleteTexture(void* textureHandle) override;
-
- void setTextureData(void* textureHandle, const void* data, int x, int y, int width, int height,
- size_t rowBytes) override;
-
- void drawSDFGlyphs(void* targetHandle, void* textureHandle, const SDFVertex vertices[],
- int quadCnt) override;
-
- void* makeTargetHandle(int width, int height) override;
-
- void targetDeleted(void* targetHandle) override;
-
- SkBitmap readTargetHandle(void* targetHandle) override;
-
- void clearTarget(void* targetHandle, uint32_t color) override;
-
- bool initialized() const { return 0 != fProgram; }
-
-private:
- struct AtlasTexture {
- GrGLuint fID;
- AtlasFormat fFormat;
- int fWidth;
- int fHeight;
- };
-
- struct Target {
- GrGLuint fFBOID;
- GrGLuint fRBID;
- int fWidth;
- int fHeight;
- };
-
- std::unique_ptr<GLTestContext> fContext;
- GrGLuint fProgram = 0;
- GrGLint fDstScaleAndTranslateLocation = 0;
- GrGLint fAtlasInvSizeLocation = 0;
- GrGLint fSamplerLocation = 0;
-};
-
-#define callgl(NAME, ...) fContext->gl()->fFunctions.f##NAME(__VA_ARGS__)
-#define checkgl() \
- do { \
- static constexpr auto line = __LINE__; \
- auto error = fContext->gl()->fFunctions.fGetError(); \
- if (error != GR_GL_NO_ERROR) { \
- SkDebugf("GL ERROR: 0x%x, line %d\n", error, line); \
- } \
- } while (false)
-
-GLTestAtlasTextRenderer::GLTestAtlasTextRenderer(std::unique_ptr<GLTestContext> context)
- : fContext(std::move(context)) {
- auto restore = fContext->makeCurrentAndAutoRestore();
-
- // First check whether the GL is supported so we can avoid spammy failures on systems
- // where the GL simply doesn't work with this class.
- const char* versionStr = reinterpret_cast<const char*>(callgl(GetString, GR_GL_VERSION));
- auto version = GrGLGetVersionFromString(versionStr);
- auto standard = GrGLGetStandardInUseFromString(versionStr);
- switch (standard) {
- case kWebGL_GrGLStandard:
- case kNone_GrGLStandard:
- return;
- case kGLES_GrGLStandard:
- if (version < GR_GL_VER(3, 0)) {
- return;
- }
- break;
- case kGL_GrGLStandard: {
- if (version < GR_GL_VER(4, 3)) {
- return;
- }
- GrGLint profileMask;
- callgl(GetIntegerv, GR_GL_CONTEXT_PROFILE_MASK, &profileMask);
- if (profileMask & GR_GL_CONTEXT_CORE_PROFILE_BIT) {
- return;
- }
- }
- }
-
- auto vs = callgl(CreateShader, GR_GL_VERTEX_SHADER);
- static constexpr char kGLVersionString[] = "#version 430 compatibility";
- static constexpr char kGLESVersionString[] = "#version 300 es";
- GrGLint lengths[2];
- const GrGLchar* strings[2];
- switch (fContext->gl()->fStandard) {
- case kGL_GrGLStandard:
- strings[0] = kGLVersionString;
- lengths[0] = static_cast<GrGLint>(SK_ARRAY_COUNT(kGLVersionString)) - 1;
- break;
- case kGLES_GrGLStandard:
- strings[0] = kGLESVersionString;
- lengths[0] = static_cast<GrGLint>(SK_ARRAY_COUNT(kGLESVersionString)) - 1;
- break;
- default:
- strings[0] = nullptr;
- lengths[0] = 0;
- break;
- }
-
- static constexpr const char kVS[] = R"(
- uniform vec4 uDstScaleAndTranslate;
- uniform vec2 uAtlasInvSize;
-
- layout (location = 0) in vec3 inPosition;
- layout (location = 1) in vec4 inColor;
- layout (location = 2) in uvec2 inTextureCoords;
-
- out vec2 vTexCoord;
- out vec4 vColor;
- out vec2 vIntTexCoord;
-
- void main() {
- vec2 intCoords;
- // floor(vec2) doesn't seem to work on some ES devices.
- intCoords.x = floor(float(inTextureCoords.x));
- intCoords.y = floor(float(inTextureCoords.y));
- vTexCoord = intCoords * uAtlasInvSize;
- vIntTexCoord = intCoords;
- vColor = inColor;
- gl_Position = vec4(inPosition.x * uDstScaleAndTranslate.x + uDstScaleAndTranslate.y,
- inPosition.y * uDstScaleAndTranslate.z + uDstScaleAndTranslate.w,
- 0.0, inPosition.z);
- }
- )";
- strings[1] = kVS;
- lengths[1] = SK_ARRAY_COUNT(kVS) - 1;
- callgl(ShaderSource, vs, 2, strings, lengths);
- callgl(CompileShader, vs);
- GrGLint compileStatus;
- callgl(GetShaderiv, vs, GR_GL_COMPILE_STATUS, &compileStatus);
- if (compileStatus == GR_GL_FALSE) {
- GrGLint logLength;
- callgl(GetShaderiv, vs, GR_GL_INFO_LOG_LENGTH, &logLength);
- std::unique_ptr<GrGLchar[]> log(new GrGLchar[logLength + 1]);
- log[logLength] = '\0';
- callgl(GetShaderInfoLog, vs, logLength, &logLength, log.get());
- SkDebugf("Vertex Shader failed to compile\n%s", log.get());
- callgl(DeleteShader, vs);
- return;
- }
-
- auto fs = callgl(CreateShader, GR_GL_FRAGMENT_SHADER);
- static constexpr const char kFS[] = R"(
- uniform sampler2D uSampler;
-
- in vec2 vTexCoord;
- in vec4 vColor;
- in vec2 vIntTexCoord;
-
- layout (location = 0) out vec4 outColor;
-
- void main() {
- float sdfValue = texture(uSampler, vTexCoord).r;
- float distance = 7.96875 * (sdfValue - 0.50196078431000002);
- vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));
- vec2 Jdx = dFdx(vIntTexCoord);
- vec2 Jdy = dFdy(vIntTexCoord);
- float dg_len2 = dot(dist_grad, dist_grad);
- if (dg_len2 < 0.0001) {
- dist_grad = vec2(0.7071, 0.7071);
- } else {
- dist_grad = dist_grad * inversesqrt(dg_len2);
- }
- vec2 grad = vec2(dist_grad.x * Jdx.x + dist_grad.y * Jdy.x,
- dist_grad.x * Jdx.y + dist_grad.y * Jdy.y);
- float afwidth = abs(0.65000000000000002 * length(grad));
- float value = smoothstep(-afwidth, afwidth, distance);
- outColor = value * vec4(vColor.rgb * vColor.a, vColor.a);
- }
- )";
- strings[1] = kFS;
- lengths[1] = SK_ARRAY_COUNT(kFS) - 1;
- callgl(ShaderSource, fs, 2, strings, lengths);
- callgl(CompileShader, fs);
- callgl(GetShaderiv, fs, GR_GL_COMPILE_STATUS, &compileStatus);
- if (compileStatus == GR_GL_FALSE) {
- GrGLint logLength;
- callgl(GetShaderiv, fs, GR_GL_INFO_LOG_LENGTH, &logLength);
- std::unique_ptr<GrGLchar[]> log(new GrGLchar[logLength + 1]);
- log[logLength] = '\0';
- callgl(GetShaderInfoLog, fs, logLength, &logLength, log.get());
- SkDebugf("Fragment Shader failed to compile\n%s", log.get());
- callgl(DeleteShader, vs);
- callgl(DeleteShader, fs);
- return;
- }
-
- fProgram = callgl(CreateProgram);
- if (!fProgram) {
- callgl(DeleteShader, vs);
- callgl(DeleteShader, fs);
- return;
- }
-
- callgl(AttachShader, fProgram, vs);
- callgl(AttachShader, fProgram, fs);
- callgl(LinkProgram, fProgram);
- GrGLint linkStatus;
- callgl(GetProgramiv, fProgram, GR_GL_LINK_STATUS, &linkStatus);
- if (linkStatus == GR_GL_FALSE) {
- GrGLint logLength = 0;
- callgl(GetProgramiv, vs, GR_GL_INFO_LOG_LENGTH, &logLength);
- std::unique_ptr<GrGLchar[]> log(new GrGLchar[logLength + 1]);
- log[logLength] = '\0';
- callgl(GetProgramInfoLog, vs, logLength, &logLength, log.get());
- SkDebugf("Program failed to link\n%s", log.get());
- callgl(DeleteShader, vs);
- callgl(DeleteShader, fs);
- callgl(DeleteProgram, fProgram);
- fProgram = 0;
- return;
- }
- fDstScaleAndTranslateLocation = callgl(GetUniformLocation, fProgram, "uDstScaleAndTranslate");
- fAtlasInvSizeLocation = callgl(GetUniformLocation, fProgram, "uAtlasInvSize");
- fSamplerLocation = callgl(GetUniformLocation, fProgram, "uSampler");
- if (fDstScaleAndTranslateLocation < 0 || fAtlasInvSizeLocation < 0 || fSamplerLocation < 0) {
- callgl(DeleteShader, vs);
- callgl(DeleteShader, fs);
- callgl(DeleteProgram, fProgram);
- fProgram = 0;
- }
-
- checkgl();
-}
-
-inline bool atlas_format_to_gl_types(SkAtlasTextRenderer::AtlasFormat format,
- GrGLenum* internalFormat, GrGLenum* externalFormat,
- GrGLenum* type) {
- switch (format) {
- case SkAtlasTextRenderer::AtlasFormat::kA8:
- *internalFormat = GR_GL_R8;
- *externalFormat = GR_GL_RED;
- *type = GR_GL_UNSIGNED_BYTE;
- return true;
- }
- return false;
-}
-
-inline int atlas_format_bytes_per_pixel(SkAtlasTextRenderer::AtlasFormat format) {
- switch (format) {
- case SkAtlasTextRenderer::AtlasFormat::kA8:
- return 1;
- }
- return 0;
-}
-
-void* GLTestAtlasTextRenderer::createTexture(AtlasFormat format, int width, int height) {
- GrGLenum internalFormat;
- GrGLenum externalFormat;
- GrGLenum type;
- if (!atlas_format_to_gl_types(format, &internalFormat, &externalFormat, &type)) {
- return nullptr;
- }
- auto restore = fContext->makeCurrentAndAutoRestore();
-
- GrGLuint id;
- callgl(GenTextures, 1, &id);
- if (!id) {
- return nullptr;
- }
-
- callgl(BindTexture, GR_GL_TEXTURE_2D, id);
- callgl(TexImage2D, GR_GL_TEXTURE_2D, 0, internalFormat, width, height, 0, externalFormat, type,
- nullptr);
- checkgl();
-
- AtlasTexture* atlas = new AtlasTexture;
- atlas->fID = id;
- atlas->fFormat = format;
- atlas->fWidth = width;
- atlas->fHeight = height;
- return atlas;
-}
-
-void GLTestAtlasTextRenderer::deleteTexture(void* textureHandle) {
- auto restore = fContext->makeCurrentAndAutoRestore();
-
- auto* atlasTexture = reinterpret_cast<const AtlasTexture*>(textureHandle);
-
- callgl(DeleteTextures, 1, &atlasTexture->fID);
- checkgl();
-
- delete atlasTexture;
-}
-
-void GLTestAtlasTextRenderer::setTextureData(void* textureHandle, const void* data, int x, int y,
- int width, int height, size_t rowBytes) {
- auto restore = fContext->makeCurrentAndAutoRestore();
-
- auto atlasTexture = reinterpret_cast<const AtlasTexture*>(textureHandle);
-
- GrGLenum internalFormat;
- GrGLenum externalFormat;
- GrGLenum type;
- if (!atlas_format_to_gl_types(atlasTexture->fFormat, &internalFormat, &externalFormat, &type)) {
- return;
- }
- int bpp = atlas_format_bytes_per_pixel(atlasTexture->fFormat);
- GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp);
- if (static_cast<size_t>(rowLength * bpp) != rowBytes) {
- return;
- }
- callgl(PixelStorei, GR_GL_UNPACK_ALIGNMENT, 1);
- callgl(PixelStorei, GR_GL_UNPACK_ROW_LENGTH, rowLength);
- callgl(BindTexture, GR_GL_TEXTURE_2D, atlasTexture->fID);
- callgl(TexSubImage2D, GR_GL_TEXTURE_2D, 0, x, y, width, height, externalFormat, type, data);
- checkgl();
-}
-
-void GLTestAtlasTextRenderer::drawSDFGlyphs(void* targetHandle, void* textureHandle,
- const SDFVertex vertices[], int quadCnt) {
- auto restore = fContext->makeCurrentAndAutoRestore();
-
- auto target = reinterpret_cast<const Target*>(targetHandle);
- auto atlas = reinterpret_cast<const AtlasTexture*>(textureHandle);
-
- callgl(UseProgram, fProgram);
-
- callgl(ActiveTexture, GR_GL_TEXTURE0);
- callgl(BindTexture, GR_GL_TEXTURE_2D, atlas->fID);
- callgl(TexParameteri, GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAG_FILTER, GR_GL_LINEAR);
- callgl(TexParameteri, GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_GL_LINEAR);
-
- float uniformScaleAndTranslate[4] = {2.f / target->fWidth, -1.f, 2.f / target->fHeight, -1.f};
- callgl(Uniform4fv, fDstScaleAndTranslateLocation, 1, uniformScaleAndTranslate);
- callgl(Uniform2f, fAtlasInvSizeLocation, 1.f / atlas->fWidth, 1.f / atlas->fHeight);
- callgl(Uniform1i, fSamplerLocation, 0);
-
- callgl(BindFramebuffer, GR_GL_FRAMEBUFFER, target->fFBOID);
- callgl(Viewport, 0, 0, target->fWidth, target->fHeight);
-
- callgl(Enable, GR_GL_BLEND);
- callgl(BlendFunc, GR_GL_ONE, GR_GL_ONE_MINUS_SRC_ALPHA);
- callgl(Disable, GR_GL_DEPTH_TEST);
-
- callgl(BindVertexArray, 0);
- callgl(BindBuffer, GR_GL_ARRAY_BUFFER, 0);
- callgl(BindBuffer, GR_GL_ELEMENT_ARRAY_BUFFER, 0);
- callgl(VertexAttribPointer, 0, 3, GR_GL_FLOAT, GR_GL_FALSE, sizeof(SDFVertex), vertices);
- size_t colorOffset = 3 * sizeof(float);
- callgl(VertexAttribPointer, 1, 4, GR_GL_UNSIGNED_BYTE, GR_GL_TRUE, sizeof(SDFVertex),
- reinterpret_cast<const char*>(vertices) + colorOffset);
- size_t texOffset = colorOffset + sizeof(uint32_t);
- callgl(VertexAttribIPointer, 2, 2, GR_GL_UNSIGNED_SHORT, sizeof(SDFVertex),
- reinterpret_cast<const char*>(vertices) + texOffset);
- callgl(EnableVertexAttribArray, 0);
- callgl(EnableVertexAttribArray, 1);
- callgl(EnableVertexAttribArray, 2);
-
- std::unique_ptr<uint16_t[]> indices(new uint16_t[quadCnt * 6]);
- for (int q = 0; q < quadCnt; ++q) {
- indices[q * 6 + 0] = 0 + 4 * q;
- indices[q * 6 + 1] = 1 + 4 * q;
- indices[q * 6 + 2] = 2 + 4 * q;
- indices[q * 6 + 3] = 2 + 4 * q;
- indices[q * 6 + 4] = 1 + 4 * q;
- indices[q * 6 + 5] = 3 + 4 * q;
- }
- callgl(DrawElements, GR_GL_TRIANGLES, 6 * quadCnt, GR_GL_UNSIGNED_SHORT, indices.get());
- checkgl();
-}
-
-void* GLTestAtlasTextRenderer::makeTargetHandle(int width, int height) {
- auto restore = fContext->makeCurrentAndAutoRestore();
-
- GrGLuint fbo;
- callgl(GenFramebuffers, 1, &fbo);
- if (!fbo) {
- return nullptr;
- }
- GrGLuint rb;
- callgl(GenRenderbuffers, 1, &rb);
- if (!rb) {
- callgl(DeleteFramebuffers, 1, &fbo);
- return nullptr;
- }
- callgl(BindFramebuffer, GR_GL_FRAMEBUFFER, fbo);
- callgl(BindRenderbuffer, GR_GL_RENDERBUFFER, rb);
- callgl(RenderbufferStorage, GR_GL_RENDERBUFFER, GR_GL_RGBA8, width, height);
- callgl(FramebufferRenderbuffer, GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, GR_GL_RENDERBUFFER,
- rb);
- GrGLenum status = callgl(CheckFramebufferStatus, GR_GL_FRAMEBUFFER);
- if (GR_GL_FRAMEBUFFER_COMPLETE != status) {
- callgl(DeleteFramebuffers, 1, &fbo);
- callgl(DeleteRenderbuffers, 1, &rb);
- return nullptr;
- }
- callgl(Disable, GR_GL_SCISSOR_TEST);
- callgl(ClearColor, 0, 0, 0, 0.0);
- callgl(Clear, GR_GL_COLOR_BUFFER_BIT);
- checkgl();
- Target* target = new Target;
- target->fFBOID = fbo;
- target->fRBID = rb;
- target->fWidth = width;
- target->fHeight = height;
- return target;
-}
-
-void GLTestAtlasTextRenderer::targetDeleted(void* targetHandle) {
- auto restore = fContext->makeCurrentAndAutoRestore();
-
- Target* target = reinterpret_cast<Target*>(targetHandle);
- callgl(DeleteFramebuffers, 1, &target->fFBOID);
- callgl(DeleteRenderbuffers, 1, &target->fRBID);
- delete target;
-}
-
-SkBitmap GLTestAtlasTextRenderer::readTargetHandle(void* targetHandle) {
- auto restore = fContext->makeCurrentAndAutoRestore();
-
- Target* target = reinterpret_cast<Target*>(targetHandle);
-
- auto info =
- SkImageInfo::Make(target->fWidth, target->fHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
- SkBitmap bmp;
- bmp.setInfo(info, sizeof(uint32_t) * target->fWidth);
- bmp.allocPixels();
-
- callgl(BindFramebuffer, GR_GL_FRAMEBUFFER, target->fFBOID);
- callgl(ReadPixels, 0, 0, target->fWidth, target->fHeight, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE,
- bmp.getPixels());
- checkgl();
- return bmp;
-}
-
-void GLTestAtlasTextRenderer::clearTarget(void* targetHandle, uint32_t color) {
- auto restore = fContext->makeCurrentAndAutoRestore();
-
- Target* target = reinterpret_cast<Target*>(targetHandle);
- callgl(BindFramebuffer, GR_GL_FRAMEBUFFER, target->fFBOID);
- callgl(Disable, GR_GL_SCISSOR_TEST);
- float r = ((color >> 0) & 0xff) / 255.f;
- float g = ((color >> 8) & 0xff) / 255.f;
- float b = ((color >> 16) & 0xff) / 255.f;
- float a = ((color >> 24) & 0xff) / 255.f;
- callgl(ClearColor, r, g, b, a);
- callgl(Clear, GR_GL_COLOR_BUFFER_BIT);
-}
-
-} // anonymous namespace
-
-namespace sk_gpu_test {
-
-sk_sp<TestAtlasTextRenderer> MakeGLTestAtlasTextRenderer() {
- std::unique_ptr<GLTestContext> context(CreatePlatformGLTestContext(kGL_GrGLStandard));
- if (!context) {
- context.reset(CreatePlatformGLTestContext(kGLES_GrGLStandard));
- }
- if (!context) {
- return nullptr;
- }
- auto restorer = context->makeCurrentAndAutoRestore();
- auto renderer = sk_make_sp<GLTestAtlasTextRenderer>(std::move(context));
- return renderer->initialized() ? std::move(renderer) : nullptr;
-}
-
-} // namespace sk_gpu_test
diff --git a/chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.h b/chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.h
deleted file mode 100644
index d1536d303c6..00000000000
--- a/chromium/third_party/skia/tools/gpu/atlastext/GLTestAtlasTextRenderer.h
+++ /dev/null
@@ -1,25 +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 GLTestAtlasTextRenderer_DEFINED
-#define GLTestAtlasTextRenderer_DEFINED
-
-#include "include/core/SkRefCnt.h"
-
-namespace sk_gpu_test {
-
-class TestAtlasTextRenderer;
-
-/**
- * Creates a TestAtlasTextRenderer that uses its own OpenGL context to implement
- * SkAtlasTextRenderer.
- */
-sk_sp<TestAtlasTextRenderer> MakeGLTestAtlasTextRenderer();
-
-} // namespace sk_gpu_test
-
-#endif
diff --git a/chromium/third_party/skia/tools/gpu/atlastext/TestAtlasTextRenderer.h b/chromium/third_party/skia/tools/gpu/atlastext/TestAtlasTextRenderer.h
deleted file mode 100644
index e928e76402b..00000000000
--- a/chromium/third_party/skia/tools/gpu/atlastext/TestAtlasTextRenderer.h
+++ /dev/null
@@ -1,37 +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 TestAtlasTextRenderer_DEFINED
-#define TestAtlasTextRenderer_DEFINED
-
-#include "include/atlastext/SkAtlasTextRenderer.h"
-#include "include/core/SkBitmap.h"
-
-namespace sk_gpu_test {
-
-class TestContext;
-
-/**
- * Base class for implementations of SkAtlasTextRenderer in order to test the SkAtlasText APIs.
- * Adds a helper for creating SkAtlasTextTargets and to read back the contents of a target as a
- * bitmap.
- */
-class TestAtlasTextRenderer : public SkAtlasTextRenderer {
-public:
- /** Returns a handle that can be used to construct a SkAtlasTextTarget instance. */
- virtual void* makeTargetHandle(int width, int height) = 0;
-
- /** Makes a SkBitmap of the target handle's contents. */
- virtual SkBitmap readTargetHandle(void* targetHandle) = 0;
-
- /** Clears the target to the specified color, encoded as RGBA (low to high byte order) */
- virtual void clearTarget(void* targetHandle, uint32_t color) = 0;
-};
-
-} // namespace sk_gpu_test
-
-#endif
diff --git a/chromium/third_party/skia/tools/gpu/d3d/D3DTestContext.cpp b/chromium/third_party/skia/tools/gpu/d3d/D3DTestContext.cpp
index ba00a36cd5c..fff7ca127ff 100644
--- a/chromium/third_party/skia/tools/gpu/d3d/D3DTestContext.cpp
+++ b/chromium/third_party/skia/tools/gpu/d3d/D3DTestContext.cpp
@@ -55,6 +55,7 @@ protected:
private:
D3DTestContextImpl(const GrD3DBackendContext& backendContext, bool ownsContext)
: D3DTestContext(backendContext, ownsContext) {
+ fFenceSupport = true;
}
void onPlatformMakeNotCurrent() const override {}
diff --git a/chromium/third_party/skia/tools/gpu/dawn/DawnTestContext.cpp b/chromium/third_party/skia/tools/gpu/dawn/DawnTestContext.cpp
index c23669709f7..58d755ea5c1 100644
--- a/chromium/third_party/skia/tools/gpu/dawn/DawnTestContext.cpp
+++ b/chromium/third_party/skia/tools/gpu/dawn/DawnTestContext.cpp
@@ -6,7 +6,6 @@
*/
#include "dawn/webgpu_cpp.h"
-#include "dawn_native/DawnNative.h"
#include "tools/gpu/dawn/DawnTestContext.h"
#ifdef SK_BUILD_FOR_UNIX
@@ -78,6 +77,10 @@ private:
ProcGetter* ProcGetter::fInstance;
#endif
+static void PrintDeviceError(WGPUErrorType, const char* message, void*) {
+ SkDebugf("Device error: %s\n", message);
+}
+
class DawnTestContextImpl : public sk_gpu_test::DawnTestContext {
public:
static wgpu::Device createDevice(const dawn_native::Instance& instance,
@@ -88,7 +91,7 @@ public:
std::vector<dawn_native::Adapter> adapters = instance.GetAdapters();
for (dawn_native::Adapter adapter : adapters) {
if (adapter.GetBackendType() == type) {
- return adapter.CreateDevice();
+ return wgpu::Device::Acquire(adapter.CreateDevice());
}
}
return nullptr;
@@ -125,6 +128,7 @@ public:
#endif
#endif
device = createDevice(*instance, type);
+ device.SetUncapturedErrorCallback(PrintDeviceError, 0);
}
if (!device) {
return nullptr;
@@ -150,15 +154,13 @@ protected:
private:
DawnTestContextImpl(std::unique_ptr<dawn_native::Instance> instance,
const wgpu::Device& device)
- : DawnTestContext(device)
- , fInstance(std::move(instance)) {
+ : DawnTestContext(std::move(instance), device) {
fFenceSupport = true;
}
void onPlatformMakeNotCurrent() const override {}
void onPlatformMakeCurrent() const override {}
std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
- std::unique_ptr<dawn_native::Instance> fInstance;
typedef sk_gpu_test::DawnTestContext INHERITED;
};
diff --git a/chromium/third_party/skia/tools/gpu/dawn/DawnTestContext.h b/chromium/third_party/skia/tools/gpu/dawn/DawnTestContext.h
index 63f35f6f261..73b4e5df260 100644
--- a/chromium/third_party/skia/tools/gpu/dawn/DawnTestContext.h
+++ b/chromium/third_party/skia/tools/gpu/dawn/DawnTestContext.h
@@ -9,6 +9,7 @@
#define DawnTestContext_DEFINED
#include "tools/gpu/TestContext.h"
+#include <dawn_native/DawnNative.h>
#ifdef SK_DAWN
@@ -22,8 +23,10 @@ public:
}
protected:
- DawnTestContext(const wgpu::Device& device) : fDevice(device) {}
+ DawnTestContext(std::unique_ptr<dawn_native::Instance> instance, const wgpu::Device& device)
+ : fInstance(std::move(instance)), fDevice(device) {}
+ std::unique_ptr<dawn_native::Instance> fInstance;
wgpu::Device fDevice;
private:
diff --git a/chromium/third_party/skia/tools/gpu/gl/GLTestContext.cpp b/chromium/third_party/skia/tools/gpu/gl/GLTestContext.cpp
index 75c1fee8fd5..f40657c9388 100644
--- a/chromium/third_party/skia/tools/gpu/gl/GLTestContext.cpp
+++ b/chromium/third_party/skia/tools/gpu/gl/GLTestContext.cpp
@@ -222,41 +222,6 @@ void GLTestContext::finish() {
#endif
}
-GrGLuint GLTestContext::createTextureRectangle(int width, int height, GrGLenum internalFormat,
- GrGLenum externalFormat, GrGLenum externalType,
- GrGLvoid* data) {
-#ifdef SK_GL
- // Should match GrGLCaps check for fRectangleTextureSupport.
- if (kGL_GrGLStandard != fGL->fStandard ||
- (GrGLGetVersion(fGL.get()) < GR_GL_VER(3, 1) &&
- !fGL->fExtensions.has("GL_ARB_texture_rectangle") &&
- !fGL->fExtensions.has("GL_ANGLE_texture_rectangle"))) {
- return 0;
- }
-
- if (GrGLGetGLSLVersion(fGL.get()) < GR_GLSL_VER(1, 40)) {
- return 0;
- }
-
- GrGLuint id;
- GR_GL_CALL(fGL.get(), GenTextures(1, &id));
- GR_GL_CALL(fGL.get(), BindTexture(GR_GL_TEXTURE_RECTANGLE, id));
- GR_GL_CALL(fGL.get(), TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_MAG_FILTER,
- GR_GL_NEAREST));
- GR_GL_CALL(fGL.get(), TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_MIN_FILTER,
- GR_GL_NEAREST));
- GR_GL_CALL(fGL.get(), TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_WRAP_S,
- GR_GL_CLAMP_TO_EDGE));
- GR_GL_CALL(fGL.get(), TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_WRAP_T,
- GR_GL_CLAMP_TO_EDGE));
- GR_GL_CALL(fGL.get(), TexImage2D(GR_GL_TEXTURE_RECTANGLE, 0, internalFormat, width, height, 0,
- externalFormat, externalType, data));
- return id;
-#else
- return 0;
-#endif
-}
-
sk_sp<GrContext> GLTestContext::makeGrContext(const GrContextOptions& options) {
#ifdef SK_GL
return GrContext::MakeGL(fGL, options);
diff --git a/chromium/third_party/skia/tools/gpu/gl/GLTestContext.h b/chromium/third_party/skia/tools/gpu/gl/GLTestContext.h
index 601c3b9f18c..54b47492504 100644
--- a/chromium/third_party/skia/tools/gpu/gl/GLTestContext.h
+++ b/chromium/third_party/skia/tools/gpu/gl/GLTestContext.h
@@ -33,10 +33,6 @@ public:
virtual void destroyEGLImage(GrEGLImage) const { }
- /** Used for testing GL_TEXTURE_RECTANGLE integration. */
- GrGLuint createTextureRectangle(int width, int height, GrGLenum internalFormat,
- GrGLenum externalFormat, GrGLenum externalType, GrGLvoid* data);
-
/**
* Used for testing EGLImage integration. Takes a EGLImage and wraps it in a
* GL_TEXTURE_EXTERNAL_OES.
diff --git a/chromium/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.cpp b/chromium/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.cpp
index 57d39e00fad..24eeb2f0441 100644
--- a/chromium/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.cpp
+++ b/chromium/third_party/skia/tools/gpu/gl/angle/GLTestContext_angle.cpp
@@ -25,6 +25,8 @@
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D
+#define EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE 0x3483
+
using sk_gpu_test::ANGLEBackend;
using sk_gpu_test::ANGLEContextVersion;
@@ -281,12 +283,20 @@ ANGLEGLContext::ANGLEGLContext(ANGLEBackend type, ANGLEContextVersion version,
}
int versionNum = ANGLEContextVersion::kES2 == version ? 2 : 3;
- const EGLint contextAttribs[] = {
+ std::vector<EGLint> contextAttribs = {
EGL_CONTEXT_CLIENT_VERSION, versionNum,
- EGL_NONE
};
+
+ const char* extensions = eglQueryString(fDisplay, EGL_EXTENSIONS);
+ if (strstr(extensions, "EGL_ANGLE_create_context_backwards_compatible")) {
+ contextAttribs.push_back(EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE);
+ contextAttribs.push_back(EGL_FALSE);
+ }
+
+ contextAttribs.push_back(EGL_NONE);
+
EGLContext eglShareContext = shareContext ? shareContext->fContext : nullptr;
- fContext = eglCreateContext(fDisplay, surfaceConfig, eglShareContext, contextAttribs);
+ fContext = eglCreateContext(fDisplay, surfaceConfig, eglShareContext, contextAttribs.data());
if (EGL_NO_CONTEXT == fContext) {
SkDebugf("Could not create context!");
this->destroyGLContext();
@@ -337,7 +347,6 @@ ANGLEGLContext::ANGLEGLContext(ANGLEBackend type, ANGLEContextVersion version,
break;
}
#endif
- const char* extensions = eglQueryString(fDisplay, EGL_EXTENSIONS);
if (strstr(extensions, "EGL_KHR_image")) {
fCreateImage = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
fDestroyImage = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
@@ -366,7 +375,7 @@ GrEGLImage ANGLEGLContext::texture2DToEGLImage(GrGLuint texID) const {
void ANGLEGLContext::destroyEGLImage(GrEGLImage image) const { fDestroyImage(fDisplay, image); }
GrGLuint ANGLEGLContext::eglImageToExternalTexture(GrEGLImage image) const {
- GrGLClearErr(this->gl());
+ while (this->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {}
if (!this->gl()->hasExtension("GL_OES_EGL_image_external")) {
return 0;
}
@@ -382,12 +391,12 @@ GrGLuint ANGLEGLContext::eglImageToExternalTexture(GrEGLImage image) const {
return 0;
}
GR_GL_CALL(this->gl(), BindTexture(GR_GL_TEXTURE_EXTERNAL, texID));
- if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
+ if (this->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {
GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
return 0;
}
glEGLImageTargetTexture2D(GR_GL_TEXTURE_EXTERNAL, image);
- if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
+ if (this->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {
GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
return 0;
}
diff --git a/chromium/third_party/skia/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp b/chromium/third_party/skia/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp
index e3228a4e787..325e034a07e 100644
--- a/chromium/third_party/skia/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp
+++ b/chromium/third_party/skia/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp
@@ -375,7 +375,7 @@ void EGLGLTestContext::destroyEGLImage(GrEGLImage image) const {
GrGLuint EGLGLTestContext::eglImageToExternalTexture(GrEGLImage image) const {
#ifdef SK_GL
- GrGLClearErr(this->gl());
+ while (this->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {}
if (!this->gl()->hasExtension("GL_OES_EGL_image_external")) {
return 0;
}
@@ -392,12 +392,12 @@ GrGLuint EGLGLTestContext::eglImageToExternalTexture(GrEGLImage image) const {
return 0;
}
GR_GL_CALL_NOERRCHECK(this->gl(), BindTexture(GR_GL_TEXTURE_EXTERNAL, texID));
- if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
+ if (this->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {
GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
return 0;
}
glEGLImageTargetTexture2D(GR_GL_TEXTURE_EXTERNAL, image);
- if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
+ if (this->gl()->fFunctions.fGetError() != GR_GL_NO_ERROR) {
GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
return 0;
}
diff --git a/chromium/third_party/skia/tools/gpu/gl/interface/templates.go b/chromium/third_party/skia/tools/gpu/gl/interface/templates.go
index ebed908c67d..5f3e3918bce 100644
--- a/chromium/third_party/skia/tools/gpu/gl/interface/templates.go
+++ b/chromium/third_party/skia/tools/gpu/gl/interface/templates.go
@@ -234,6 +234,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/tools/gpu/vk/VkTestHelper.cpp b/chromium/third_party/skia/tools/gpu/vk/VkTestHelper.cpp
new file mode 100644
index 00000000000..f1a02a495fb
--- /dev/null
+++ b/chromium/third_party/skia/tools/gpu/vk/VkTestHelper.cpp
@@ -0,0 +1,109 @@
+/*
+ * 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 "tools/gpu/vk/VkTestHelper.h"
+
+#ifdef SK_VULKAN
+
+#include "include/core/SkSurface.h"
+#include "include/gpu/GrContext.h"
+#include "tools/gpu/vk/VkTestUtils.h"
+
+#define ACQUIRE_INST_VK_PROC(name) \
+ fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, fBackendContext.fInstance,\
+ VK_NULL_HANDLE)); \
+ if (fVk##name == nullptr) { \
+ SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
+ return false; \
+ }
+
+#define ACQUIRE_DEVICE_VK_PROC(name) \
+ fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, VK_NULL_HANDLE, fDevice)); \
+ if (fVk##name == nullptr) { \
+ SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
+ return false; \
+ }
+
+bool VkTestHelper::init() {
+ PFN_vkGetInstanceProcAddr instProc;
+ PFN_vkGetDeviceProcAddr devProc;
+ if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
+ return false;
+ }
+ auto getProc = [&instProc, &devProc](const char* proc_name,
+ VkInstance instance, VkDevice device) {
+ if (device != VK_NULL_HANDLE) {
+ return devProc(device, proc_name);
+ }
+ return instProc(instance, proc_name);
+ };
+
+ fFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+ fFeatures.pNext = nullptr;
+
+ fBackendContext.fInstance = VK_NULL_HANDLE;
+ fBackendContext.fDevice = VK_NULL_HANDLE;
+
+ if (!sk_gpu_test::CreateVkBackendContext(getProc, &fBackendContext, &fExtensions,
+ &fFeatures, &fDebugCallback, nullptr,
+ sk_gpu_test::CanPresentFn(), fIsProtected)) {
+ return false;
+ }
+ fDevice = fBackendContext.fDevice;
+
+ if (fDebugCallback != VK_NULL_HANDLE) {
+ fDestroyDebugCallback = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
+ instProc(fBackendContext.fInstance, "vkDestroyDebugReportCallbackEXT"));
+ }
+ ACQUIRE_INST_VK_PROC(DestroyInstance)
+ ACQUIRE_INST_VK_PROC(DeviceWaitIdle)
+ ACQUIRE_INST_VK_PROC(DestroyDevice)
+
+ ACQUIRE_INST_VK_PROC(GetPhysicalDeviceFormatProperties)
+ ACQUIRE_INST_VK_PROC(GetPhysicalDeviceMemoryProperties)
+
+ ACQUIRE_DEVICE_VK_PROC(CreateImage)
+ ACQUIRE_DEVICE_VK_PROC(DestroyImage)
+ ACQUIRE_DEVICE_VK_PROC(GetImageMemoryRequirements)
+ ACQUIRE_DEVICE_VK_PROC(AllocateMemory)
+ ACQUIRE_DEVICE_VK_PROC(FreeMemory)
+ ACQUIRE_DEVICE_VK_PROC(BindImageMemory)
+ ACQUIRE_DEVICE_VK_PROC(MapMemory)
+ ACQUIRE_DEVICE_VK_PROC(UnmapMemory)
+ ACQUIRE_DEVICE_VK_PROC(FlushMappedMemoryRanges)
+ ACQUIRE_DEVICE_VK_PROC(GetImageSubresourceLayout)
+
+ fGrContext = GrContext::MakeVulkan(fBackendContext);
+ if (!fGrContext) {
+ return false;
+ }
+
+ return true;
+}
+
+void VkTestHelper::cleanup() {
+ fGrContext.reset();
+
+ fBackendContext.fMemoryAllocator.reset();
+ if (fDevice != VK_NULL_HANDLE) {
+ fVkDeviceWaitIdle(fDevice);
+ fVkDestroyDevice(fDevice, nullptr);
+ fDevice = VK_NULL_HANDLE;
+ }
+ if (fDebugCallback != VK_NULL_HANDLE) {
+ fDestroyDebugCallback(fBackendContext.fInstance, fDebugCallback, nullptr);
+ }
+
+ if (fBackendContext.fInstance != VK_NULL_HANDLE) {
+ fVkDestroyInstance(fBackendContext.fInstance, nullptr);
+ fBackendContext.fInstance = VK_NULL_HANDLE;
+ }
+
+ sk_gpu_test::FreeVulkanFeaturesStructs(&fFeatures);
+}
+
+#endif // SK_VULKAN
diff --git a/chromium/third_party/skia/tools/gpu/vk/VkTestHelper.h b/chromium/third_party/skia/tools/gpu/vk/VkTestHelper.h
new file mode 100644
index 00000000000..965885a1599
--- /dev/null
+++ b/chromium/third_party/skia/tools/gpu/vk/VkTestHelper.h
@@ -0,0 +1,71 @@
+/*
+ * 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 VkTestHelper_DEFINED
+#define VkTestHelper_DEFINED
+
+#include "include/core/SkTypes.h"
+
+#ifdef SK_VULKAN
+
+#include "include/core/SkRefCnt.h"
+#include "include/gpu/vk/GrVkBackendContext.h"
+#include "include/gpu/vk/GrVkExtensions.h"
+
+class GrContext;
+class SkSurface;
+
+#define DECLARE_VK_PROC(name) PFN_vk##name fVk##name
+
+class VkTestHelper {
+public:
+ VkTestHelper(bool isProtected) : fIsProtected(isProtected) {}
+
+ ~VkTestHelper() {
+ this->cleanup();
+ }
+
+ bool init();
+
+ GrContext* grContext() { return fGrContext.get(); }
+
+private:
+ void cleanup();
+
+ DECLARE_VK_PROC(DestroyInstance);
+ DECLARE_VK_PROC(DeviceWaitIdle);
+ DECLARE_VK_PROC(DestroyDevice);
+
+ DECLARE_VK_PROC(GetPhysicalDeviceFormatProperties);
+ DECLARE_VK_PROC(GetPhysicalDeviceMemoryProperties);
+
+ DECLARE_VK_PROC(CreateImage);
+ DECLARE_VK_PROC(DestroyImage);
+ DECLARE_VK_PROC(GetImageMemoryRequirements);
+ DECLARE_VK_PROC(AllocateMemory);
+ DECLARE_VK_PROC(FreeMemory);
+ DECLARE_VK_PROC(BindImageMemory);
+ DECLARE_VK_PROC(MapMemory);
+ DECLARE_VK_PROC(UnmapMemory);
+ DECLARE_VK_PROC(FlushMappedMemoryRanges);
+ DECLARE_VK_PROC(GetImageSubresourceLayout);
+
+ bool fIsProtected = false;
+ VkDevice fDevice = VK_NULL_HANDLE;
+
+ GrVkExtensions fExtensions;
+ VkPhysicalDeviceFeatures2 fFeatures = {};
+ VkDebugReportCallbackEXT fDebugCallback = VK_NULL_HANDLE;
+ PFN_vkDestroyDebugReportCallbackEXT fDestroyDebugCallback = nullptr;
+ GrVkBackendContext fBackendContext;
+ sk_sp<GrContext> fGrContext;
+};
+
+#undef DECLARE_VK_PROC
+
+#endif // SK_VULKAN
+#endif // VkTestHelper_DEFINED
diff --git a/chromium/third_party/skia/tools/gpu/vk/VkTestUtils.cpp b/chromium/third_party/skia/tools/gpu/vk/VkTestUtils.cpp
index a6026af739b..86084cf7935 100644
--- a/chromium/third_party/skia/tools/gpu/vk/VkTestUtils.cpp
+++ b/chromium/third_party/skia/tools/gpu/vk/VkTestUtils.cpp
@@ -110,6 +110,11 @@ VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
const char* pMessage,
void* pUserData) {
if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
+ // See https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/1887
+ if (strstr(pMessage, "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-01521") ||
+ strstr(pMessage, "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-01522")) {
+ return VK_FALSE;
+ }
SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
print_backtrace();
SkDEBUGFAIL("Vulkan debug layer error");
diff --git a/chromium/third_party/skia/tools/gpu/vk/VkYcbcrSamplerHelper.cpp b/chromium/third_party/skia/tools/gpu/vk/VkYcbcrSamplerHelper.cpp
new file mode 100644
index 00000000000..6e464a1c8a9
--- /dev/null
+++ b/chromium/third_party/skia/tools/gpu/vk/VkYcbcrSamplerHelper.cpp
@@ -0,0 +1,196 @@
+/*
+ * 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 "tools/gpu/vk/VkYcbcrSamplerHelper.h"
+
+#ifdef SK_VULKAN
+
+#include "include/gpu/GrContext.h"
+#include "src/gpu/GrContextPriv.h"
+#include "src/gpu/vk/GrVkGpu.h"
+#include "src/gpu/vk/GrVkUtil.h"
+
+int VkYcbcrSamplerHelper::GetExpectedY(int x, int y, int width, int height) {
+ return 16 + (x + y) * 219 / (width + height - 2);
+}
+
+std::pair<int, int> VkYcbcrSamplerHelper::GetExpectedUV(int x, int y, int width, int height) {
+ return { 16 + x * 224 / (width - 1), 16 + y * 224 / (height - 1) };
+}
+
+GrVkGpu* VkYcbcrSamplerHelper::vkGpu() {
+ return (GrVkGpu*) fContext->priv().getGpu();
+}
+
+VkYcbcrSamplerHelper::VkYcbcrSamplerHelper(GrContext* context) : fContext(context) {
+ SkASSERT_RELEASE(context->backend() == GrBackendApi::kVulkan);
+}
+
+VkYcbcrSamplerHelper::~VkYcbcrSamplerHelper() {
+ GrVkGpu* vkGpu = this->vkGpu();
+
+ if (fImage != VK_NULL_HANDLE) {
+ GR_VK_CALL(vkGpu->vkInterface(), DestroyImage(vkGpu->device(), fImage, nullptr));
+ fImage = VK_NULL_HANDLE;
+ }
+ if (fImageMemory != VK_NULL_HANDLE) {
+ GR_VK_CALL(vkGpu->vkInterface(), FreeMemory(vkGpu->device(), fImageMemory, nullptr));
+ fImageMemory = VK_NULL_HANDLE;
+ }
+}
+
+bool VkYcbcrSamplerHelper::isYCbCrSupported() {
+ GrVkGpu* vkGpu = this->vkGpu();
+
+ return vkGpu->vkCaps().supportsYcbcrConversion();
+}
+
+bool VkYcbcrSamplerHelper::createBackendTexture(uint32_t width, uint32_t height) {
+ GrVkGpu* vkGpu = this->vkGpu();
+ VkResult result;
+
+ // Verify that the image format is supported.
+ VkFormatProperties formatProperties;
+ GR_VK_CALL(vkGpu->vkInterface(),
+ GetPhysicalDeviceFormatProperties(vkGpu->physicalDevice(),
+ VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
+ &formatProperties));
+ if (!(formatProperties.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
+ // VK_FORMAT_G8_B8R8_2PLANE_420_UNORM is not supported
+ return false;
+ }
+
+ // Create YCbCr image.
+ VkImageCreateInfo vkImageInfo = {};
+ vkImageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ vkImageInfo.imageType = VK_IMAGE_TYPE_2D;
+ vkImageInfo.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
+ vkImageInfo.extent = VkExtent3D{width, height, 1};
+ vkImageInfo.mipLevels = 1;
+ vkImageInfo.arrayLayers = 1;
+ vkImageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+ vkImageInfo.tiling = VK_IMAGE_TILING_LINEAR;
+ vkImageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
+ vkImageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ vkImageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
+ SkASSERT(fImage == VK_NULL_HANDLE);
+ GR_VK_CALL_RESULT(vkGpu, result, CreateImage(vkGpu->device(), &vkImageInfo, nullptr, &fImage));
+ if (result != VK_SUCCESS) {
+ return false;
+ }
+
+ VkMemoryRequirements requirements;
+ GR_VK_CALL(vkGpu->vkInterface(), GetImageMemoryRequirements(vkGpu->device(),
+ fImage,
+ &requirements));
+
+ uint32_t memoryTypeIndex = 0;
+ bool foundHeap = false;
+ VkPhysicalDeviceMemoryProperties phyDevMemProps;
+ GR_VK_CALL(vkGpu->vkInterface(), GetPhysicalDeviceMemoryProperties(vkGpu->physicalDevice(),
+ &phyDevMemProps));
+ for (uint32_t i = 0; i < phyDevMemProps.memoryTypeCount && !foundHeap; ++i) {
+ if (requirements.memoryTypeBits & (1 << i)) {
+ // Map host-visible memory.
+ if (phyDevMemProps.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
+ memoryTypeIndex = i;
+ foundHeap = true;
+ }
+ }
+ }
+ if (!foundHeap) {
+ return false;
+ }
+
+ VkMemoryAllocateInfo allocInfo = {};
+ allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ allocInfo.allocationSize = requirements.size;
+ allocInfo.memoryTypeIndex = memoryTypeIndex;
+
+ SkASSERT(fImageMemory == VK_NULL_HANDLE);
+ GR_VK_CALL_RESULT(vkGpu, result, AllocateMemory(vkGpu->device(), &allocInfo,
+ nullptr, &fImageMemory));
+ if (result != VK_SUCCESS) {
+ return false;
+ }
+
+ void* mappedBuffer;
+ GR_VK_CALL_RESULT(vkGpu, result, MapMemory(vkGpu->device(), fImageMemory, 0u,
+ requirements.size, 0u, &mappedBuffer));
+ if (result != VK_SUCCESS) {
+ return false;
+ }
+
+ // Write Y channel.
+ VkImageSubresource subresource;
+ subresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT;
+ subresource.mipLevel = 0;
+ subresource.arrayLayer = 0;
+
+ VkSubresourceLayout yLayout;
+ GR_VK_CALL(vkGpu->vkInterface(), GetImageSubresourceLayout(vkGpu->device(), fImage,
+ &subresource, &yLayout));
+ uint8_t* bufferData = reinterpret_cast<uint8_t*>(mappedBuffer) + yLayout.offset;
+ for (size_t y = 0; y < height; ++y) {
+ for (size_t x = 0; x < width; ++x) {
+ bufferData[y * yLayout.rowPitch + x] = GetExpectedY(x, y, width, height);
+ }
+ }
+
+ // Write UV channels.
+ subresource.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT;
+ VkSubresourceLayout uvLayout;
+ GR_VK_CALL(vkGpu->vkInterface(), GetImageSubresourceLayout(vkGpu->device(), fImage,
+ &subresource, &uvLayout));
+ bufferData = reinterpret_cast<uint8_t*>(mappedBuffer) + uvLayout.offset;
+ for (size_t y = 0; y < height / 2; ++y) {
+ for (size_t x = 0; x < width / 2; ++x) {
+ auto [u, v] = GetExpectedUV(2*x, 2*y, width, height);
+ bufferData[y * uvLayout.rowPitch + x * 2] = u;
+ bufferData[y * uvLayout.rowPitch + x * 2 + 1] = v;
+ }
+ }
+
+ VkMappedMemoryRange flushRange;
+ flushRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
+ flushRange.pNext = nullptr;
+ flushRange.memory = fImageMemory;
+ flushRange.offset = 0;
+ flushRange.size = VK_WHOLE_SIZE;
+ GR_VK_CALL_RESULT(vkGpu, result, FlushMappedMemoryRanges(vkGpu->device(), 1, &flushRange));
+ if (result != VK_SUCCESS) {
+ return false;
+ }
+ GR_VK_CALL(vkGpu->vkInterface(), UnmapMemory(vkGpu->device(), fImageMemory));
+
+ // Bind image memory.
+ GR_VK_CALL_RESULT(vkGpu, result, BindImageMemory(vkGpu->device(), fImage, fImageMemory, 0u));
+ if (result != VK_SUCCESS) {
+ return false;
+ }
+
+ // Wrap the image into SkImage.
+ GrVkYcbcrConversionInfo ycbcrInfo(vkImageInfo.format,
+ /*externalFormat=*/0,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709,
+ VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
+ VK_CHROMA_LOCATION_COSITED_EVEN,
+ VK_CHROMA_LOCATION_COSITED_EVEN,
+ VK_FILTER_LINEAR,
+ false,
+ formatProperties.linearTilingFeatures);
+ GrVkAlloc alloc(fImageMemory, 0 /* offset */, requirements.size, 0 /* flags */);
+ GrVkImageInfo imageInfo(fImage, alloc, VK_IMAGE_TILING_LINEAR, VK_IMAGE_LAYOUT_UNDEFINED,
+ vkImageInfo.format, 1 /* levelCount */, VK_QUEUE_FAMILY_IGNORED,
+ GrProtected::kNo, ycbcrInfo);
+
+ fTexture = GrBackendTexture(width, height, imageInfo);
+ return true;
+}
+
+#endif // SK_VULKAN
diff --git a/chromium/third_party/skia/tools/gpu/vk/VkYcbcrSamplerHelper.h b/chromium/third_party/skia/tools/gpu/vk/VkYcbcrSamplerHelper.h
new file mode 100644
index 00000000000..929f4c94e87
--- /dev/null
+++ b/chromium/third_party/skia/tools/gpu/vk/VkYcbcrSamplerHelper.h
@@ -0,0 +1,48 @@
+/*
+ * 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 VkYcbcrSamplerHelper_DEFINED
+#define VkYcbcrSamplerHelper_DEFINED
+
+#include "include/core/SkTypes.h"
+
+#ifdef SK_VULKAN
+
+#include "include/gpu/GrBackendSurface.h"
+
+class GrContext;
+class GrVkGpu;
+
+// This helper will create and hold data for a Vulkan YCbCr backend texture. This format is
+// particularly interesting because its sampler is immutable.
+class VkYcbcrSamplerHelper {
+public:
+ VkYcbcrSamplerHelper(GrContext*);
+ ~VkYcbcrSamplerHelper();
+
+ bool isYCbCrSupported();
+
+ bool createBackendTexture(uint32_t width, uint32_t height);
+
+ const GrBackendTexture& backendTexture() const { return fTexture; }
+
+ static int GetExpectedY(int x, int y, int width, int height);
+ static std::pair<int, int> GetExpectedUV(int x, int y, int width, int height);
+
+private:
+ GrVkGpu* vkGpu();
+
+ GrContext* fContext;
+
+ VkImage fImage = VK_NULL_HANDLE;
+ VkDeviceMemory fImageMemory = VK_NULL_HANDLE;
+ GrBackendTexture fTexture;
+};
+
+#endif // SK_VULKAN
+
+#endif // VkYcbcrSamplerHelper_DEFINED
diff --git a/chromium/third_party/skia/tools/lottie-web-perf/lottie-web-canvas-perf.html b/chromium/third_party/skia/tools/lottie-web-perf/lottie-web-canvas-perf.html
index 746c0bcfed7..1cab30faad0 100644
--- a/chromium/third_party/skia/tools/lottie-web-perf/lottie-web-canvas-perf.html
+++ b/chromium/third_party/skia/tools/lottie-web-perf/lottie-web-canvas-perf.html
@@ -1,17 +1,17 @@
<!DOCTYPE html>
<html>
<head>
- <title>Lottie-Web Perf</title>
- <meta charset="utf-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=egde,chrome=1">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <script src="/res/lottie.js" type="text/javascript" charset="utf-8"></script>
- <style type="text/css" media="screen">
- body {
- margin: 0;
- padding: 0;
- }
- </style>
+ <title>Lottie-Web Perf</title>
+ <meta charset="utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <script src="/res/lottie.js" type="text/javascript" charset="utf-8"></script>
+ <style type="text/css" media="screen">
+ body {
+ margin: 0;
+ padding: 0;
+ }
+ </style>
</head>
<body>
<main>
diff --git a/chromium/third_party/skia/tools/lottie-web-perf/lottie-web-perf.html b/chromium/third_party/skia/tools/lottie-web-perf/lottie-web-perf.html
index 88cc992fa6f..9fc499b7c5c 100644
--- a/chromium/third_party/skia/tools/lottie-web-perf/lottie-web-perf.html
+++ b/chromium/third_party/skia/tools/lottie-web-perf/lottie-web-perf.html
@@ -1,17 +1,17 @@
<!DOCTYPE html>
<html>
<head>
- <title>Lottie-Web Perf</title>
- <meta charset="utf-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=egde,chrome=1">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <script src="/res/lottie.js" type="text/javascript" charset="utf-8"></script>
- <style type="text/css" media="screen">
- body {
- margin: 0;
- padding: 0;
- }
- </style>
+ <title>Lottie-Web Perf</title>
+ <meta charset="utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <script src="/res/lottie.js" type="text/javascript" charset="utf-8"></script>
+ <style type="text/css" media="screen">
+ body {
+ margin: 0;
+ padding: 0;
+ }
+ </style>
</head>
<body>
<main>
diff --git a/chromium/third_party/skia/tools/lottiecap/driver.html b/chromium/third_party/skia/tools/lottiecap/driver.html
index 2b6dc94049c..0811441c645 100644
--- a/chromium/third_party/skia/tools/lottiecap/driver.html
+++ b/chromium/third_party/skia/tools/lottiecap/driver.html
@@ -1,26 +1,26 @@
<!DOCTYPE html>
<html>
<head>
- <title>Lottie Filmstrip Capture</title>
- <meta charset="utf-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=egde,chrome=1">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <script src="/lottie.js" type="text/javascript" charset="utf-8"></script>
- <style type="text/css" media="screen">
- body,
- main,
- .anim {
- margin: 0;
- padding: 0;
- }
+ <title>Lottie Filmstrip Capture</title>
+ <meta charset="utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <script src="/lottie.js" type="text/javascript" charset="utf-8"></script>
+ <style type="text/css" media="screen">
+ body,
+ main,
+ .anim {
+ margin: 0;
+ padding: 0;
+ }
- main {
- display: flex;
- width: 1000px;
- height: 1000px;
- flex-flow: row wrap;
- }
- </style>
+ main {
+ display: flex;
+ width: 1000px;
+ height: 1000px;
+ flex-flow: row wrap;
+ }
+ </style>
</head>
<body>
<main>
diff --git a/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/Makefile b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/Makefile
index 1aad3a80185..3e6aece221d 100644
--- a/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/Makefile
+++ b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/Makefile
@@ -4,3 +4,23 @@ frames_load_lego_with_local:
--canvaskit_wasm ../../out/canvaskit_wasm/canvaskit.wasm --use_gpu \
--input_lottie ../../modules/canvaskit/perf/assets/lego_loader.json \
--bench_html skottie-frames.html
+
+test_path_transform_without_snap:
+ node perf-canvaskit-with-puppeteer.js --canvaskit_js --canvaskit_js ../../out/canvaskit_wasm/canvaskit.js \
+ --canvaskit_wasm ../../out/canvaskit_wasm/canvaskit.wasm --use_gpu \
+ --assets path_translate_assets \
+ --bench_html path-transform.html \
+ --query_params translate opacity
+
+test_path_transform_with_snap:
+ node perf-canvaskit-with-puppeteer.js --canvaskit_js --canvaskit_js ../../out/canvaskit_wasm/canvaskit.js \
+ --canvaskit_wasm ../../out/canvaskit_wasm/canvaskit.wasm --use_gpu \
+ --assets path_translate_assets \
+ --bench_html path-transform.html \
+ --query_params translate opacity snap
+
+skp_with_local:
+ node perf-canvaskit-with-puppeteer.js --canvaskit_js ../../out/canvaskit_wasm/canvaskit.js \
+ --canvaskit_wasm ../../out/canvaskit_wasm/canvaskit.wasm --use_gpu \
+ --input_skp ${HOME}/skps/desk_nytimes.skp \
+ --bench_html render-skp.html \ No newline at end of file
diff --git a/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/package-lock.json b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/package-lock.json
index f6f194a4616..2d6e0388481 100644
--- a/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/package-lock.json
+++ b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/package-lock.json
@@ -4,15 +4,10 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
- "@types/mime-types": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz",
- "integrity": "sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM="
- },
"@types/node": {
- "version": "13.13.4",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.4.tgz",
- "integrity": "sha512-x26ur3dSXgv5AwKS0lNfbjpCakGIduWU1DU91Zz58ONRWrIKGunmZBNv4P7N+e27sJkiGDsw/3fT4AtsqQBrBA==",
+ "version": "14.0.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.5.tgz",
+ "integrity": "sha512-90hiq6/VqtQgX8Sp0EzeIsv3r+ellbGj4URKj5j30tLlZvRUpnAe9YbYnjl3pJM93GyXU0tghHhvXHq+5rnCKA==",
"optional": true
},
"@types/yauzl": {
@@ -536,9 +531,9 @@
}
},
"mkdirp-classic": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.2.tgz",
- "integrity": "sha512-ejdnDQcR75gwknmMw/tx02AuRs8jCtqFoFqDZMjiNxsu85sRIJVXDKHuLYvUUPRBUtV2FpSZa9bL1BUa3BdR2g=="
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
},
"ms": {
"version": "2.0.0",
@@ -615,16 +610,14 @@
}
},
"puppeteer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-3.0.1.tgz",
- "integrity": "sha512-DxNnI9n4grVHC+9irUfNK2T6YFuRECJnvG7VzdVolxpVwWC5DQqI5ho9Z0af48K5MQW4sJY5cq3qQ5g6NkAjvw==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-3.1.0.tgz",
+ "integrity": "sha512-jLa9sqdVx0tPnr2FcwAq+8DSjGhSM4YpkwOf3JE22Ycyqm71SW7B5uGfTyMGFoLCmbCozbLZclCjasPb0flTRw==",
"requires": {
- "@types/mime-types": "^2.1.0",
"debug": "^4.1.0",
"extract-zip": "^2.0.0",
"https-proxy-agent": "^4.0.0",
"mime": "^2.0.3",
- "mime-types": "^2.1.25",
"progress": "^2.0.1",
"proxy-from-env": "^1.0.0",
"rimraf": "^3.0.2",
@@ -642,9 +635,9 @@
}
},
"mime": {
- "version": "2.4.4",
- "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
- "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
+ "version": "2.4.5",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.5.tgz",
+ "integrity": "sha512-3hQhEUF027BuxZjQA3s7rIv/7VCQPa27hN9u9g87sEkWaKwQPuXOkVKtOeiyUrnWqTDiOs8Ed2rwg733mB0R5w=="
},
"ms": {
"version": "2.1.2",
@@ -764,9 +757,9 @@
},
"dependencies": {
"safe-buffer": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
- "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
}
}
},
@@ -806,9 +799,9 @@
}
},
"tar-fs": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.1.tgz",
- "integrity": "sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.0.tgz",
+ "integrity": "sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==",
"requires": {
"chownr": "^1.1.1",
"mkdirp-classic": "^0.5.2",
@@ -903,9 +896,9 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"ws": {
- "version": "7.2.5",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz",
- "integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA=="
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz",
+ "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w=="
},
"yauzl": {
"version": "2.10.0",
diff --git a/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/package.json b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/package.json
index ca96fc13b03..f2efa67d912 100644
--- a/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/package.json
+++ b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/package.json
@@ -7,7 +7,7 @@
"command-line-args": "^5.0.2",
"command-line-usage": "^5.0.3",
"express": "^4.16.3",
- "puppeteer": "^3.0.0"
+ "puppeteer": "^3.0.4"
},
"devDependencies": {},
"scripts": {
diff --git a/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/path-transform.html b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/path-transform.html
new file mode 100644
index 00000000000..66a293bd255
--- /dev/null
+++ b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/path-transform.html
@@ -0,0 +1,189 @@
+<!-- This benchmark aims to measure performance degredation related to
+moving a complex path. May be related to caching an alpha mask of the path at
+subpixel coordinates i.e. (25.234, 43.119) instead of (25, 43).
+As a consequence the cache may get full very quickly. Effect of paint opacity
+and rotation transformations on performance can also be tested using the query param options.
+
+Available query param options:
+ - snap: Round all path translations to the nearest integer. This means subpixel coordinate.
+ translations will not be used. Only has an effect when the translating option is used.
+ - opacity: Use a transparent color to fill the path. If this option is
+ not included then opaque black is used.
+ - translate: The path will be randomly translated every frame.
+ - rotate: The path will be randomly rotated every frame.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Complex Path translation Perf</title>
+ <meta charset="utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <script src="/static/canvaskit.js" type="text/javascript" charset="utf-8"></script>
+ <style type="text/css" media="screen">
+ body {
+ margin: 0;
+ padding: 0;
+ }
+ #test-svg {
+ height: 0;
+ width: 0;
+ }
+ #complex-path {
+ height: 1000px;
+ width: 1000px;
+ }
+ </style>
+</head>
+<body>
+ <!-- Arbitrary svg for testing. Source: https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/gallardo.svg-->
+ <object type="image/svg+xml" data="/static/assets/car.svg" id="test-svg">
+ Car image
+ </object>
+
+ <main>
+ <button id="start_bench">Start Benchmark</button>
+ <br>
+ <canvas id=complex-path width=1000 height=1000></canvas>
+ </main>
+ <script type="text/javascript" charset="utf-8">
+ const urlSearchParams = new URLSearchParams(window.location.search);
+
+ // We sample MAX_FRAMES or until MAX_SAMPLE_SECONDS has elapsed.
+ const MAX_FRAMES = 60 * 30; // ~30s at 60fps
+ const MAX_SAMPLE_MS = 30 * 1000; // in case something takes a while, stop after 30 seconds.
+ const TRANSPARENT_PINK = new Float32Array([1,0,1,0.1]);
+
+ const svgObjectElement = document.getElementById('test-svg');
+ svgObjectElement.addEventListener('load', () => {
+ CanvasKitInit({
+ locateFile: (file) => '/static/' + file,
+ }).then(run);
+ });
+
+ function run(CanvasKit) {
+
+ const surface = getSurface(CanvasKit);
+ if (!surface) {
+ console.error('Could not make surface', window._error);
+ return;
+ }
+ const skcanvas = surface.getCanvas();
+ const grContext = surface.grContext;
+
+ document.getElementById('start_bench').addEventListener('click', () => {
+ // Initialize drawing related objects
+ const svgElement = svgObjectElement.contentDocument;
+ const svgPathAndFillColorPairs = svgToPathAndFillColorPairs(svgElement, CanvasKit);
+
+ const paint = new CanvasKit.SkPaint();
+ paint.setAntiAlias(true);
+ paint.setStyle(CanvasKit.PaintStyle.Fill);
+ let paintColor = CanvasKit.BLACK;
+
+ // Path is large, scale canvas so entire path is visible
+ skcanvas.scale(0.5, 0.5);
+
+ // Initialize perf data
+ let currentFrameNumber = 0;
+ const frameTimesMs = new Float32Array(MAX_FRAMES);
+ let startTimeMs = performance.now();
+ let previousFrameTimeMs = performance.now();
+
+ const resourceCacheUsageBytes = new Float32Array(MAX_FRAMES);
+ const usedJSHeapSizesBytes = new Float32Array(MAX_FRAMES);
+
+ function drawFrame() {
+ // Draw complex path with random translations and rotations.
+ let randomHorizontalTranslation = 0;
+ let randomVerticalTranslation = 0;
+ let randomRotation = 0;
+
+ if (urlSearchParams.has('translate')) {
+ randomHorizontalTranslation = Math.random() * 50 - 25;
+ randomVerticalTranslation = Math.random() * 50 - 25;
+ }
+ if (urlSearchParams.has('snap')) {
+ randomHorizontalTranslation = Math.round(randomHorizontalTranslation);
+ randomVerticalTranslation = Math.round(randomVerticalTranslation);
+ }
+ if (urlSearchParams.has('opacity')) {
+ paintColor = TRANSPARENT_PINK;
+ }
+ if (urlSearchParams.has('rotate')) {
+ randomRotation = (Math.random() - 0.5) / 20;
+ }
+
+ skcanvas.clear(CanvasKit.WHITE);
+ for (const [path, color] of svgPathAndFillColorPairs) {
+ path.transform([Math.cos(randomRotation), -Math.sin(randomRotation), randomHorizontalTranslation,
+ Math.sin(randomRotation), Math.cos(randomRotation), randomVerticalTranslation,
+ 0, 0, 1 ]);
+ paint.setColor(paintColor);
+ skcanvas.drawPath(path, paint);
+ }
+ surface.flush();
+
+ // Record perf data: measure frame times, memory usage
+ const currentFrameTimeMs = performance.now();
+ frameTimesMs[currentFrameNumber] = currentFrameTimeMs - previousFrameTimeMs;
+ previousFrameTimeMs = currentFrameTimeMs;
+
+ resourceCacheUsageBytes[currentFrameNumber] = grContext.getResourceCacheUsageBytes();
+ usedJSHeapSizesBytes[currentFrameNumber] = window.performance.memory.totalJSHeapSize;
+ currentFrameNumber++;
+
+ const timeSinceStart = performance.now() - startTimeMs;
+ if (currentFrameNumber >= MAX_FRAMES || timeSinceStart >= MAX_SAMPLE_MS) {
+ window._perfData = {
+ frames_ms: Array.from(frameTimesMs).slice(0, currentFrameNumber),
+ resourceCacheUsage_bytes: Array.from(resourceCacheUsageBytes).slice(0, currentFrameNumber),
+ usedJSHeapSizes_bytes: Array.from(usedJSHeapSizesBytes).slice(0, currentFrameNumber),
+ };
+ window._perfDone = true;
+ return;
+ }
+ window.requestAnimationFrame(drawFrame);
+ }
+ window.requestAnimationFrame(drawFrame);
+ });
+
+ console.log('Perf is ready');
+ window._perfReady = true;
+ }
+
+ function svgToPathAndFillColorPairs(svgElement, CanvasKit) {
+ const pathElements = Array.from(svgElement.getElementsByTagName('path'));
+ return pathElements.map((path) => [
+ CanvasKit.MakePathFromSVGString(path.getAttribute("d")),
+ CanvasKit.parseColorString(path.getAttribute("fill")??'#000000')
+ ]);
+ }
+
+ function getSurface(CanvasKit) {
+ let surface;
+ if (window.location.hash.indexOf('gpu') !== -1) {
+ surface = CanvasKit.MakeWebGLCanvasSurface('complex-path');
+ if (!surface) {
+ window._error = 'Could not make GPU surface';
+ return null;
+ }
+ let c = document.getElementById('complex-path');
+ // If CanvasKit was unable to instantiate a WebGL context, it will fallback
+ // to CPU and add a ck-replaced class to the canvas element.
+ if (c.classList.contains('ck-replaced')) {
+ window._error = 'fell back to CPU';
+ return null;
+ }
+ } else {
+ surface = CanvasKit.MakeSWCanvasSurface('complex-path');
+ if (!surface) {
+ window._error = 'Could not make CPU surface';
+ return null;
+ }
+ }
+ return surface;
+ }
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/path_translate_assets/car.svg b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/path_translate_assets/car.svg
new file mode 100644
index 00000000000..8fb17a713bf
--- /dev/null
+++ b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/path_translate_assets/car.svg
@@ -0,0 +1,5155 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="1901"
+ height="1018"
+ viewBox="0 0 1901 1018"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44+devel"
+ version="1.0"
+ sodipodi:docbase="/home/d/ink/inkscape/share/examples"
+ sodipodi:docname="gallardo.svgz"
+ inkscape:export-filename="C:\Documents and Settings\MichaelG\My Documents\My Pictures\gallardo.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:output_extension="org.inkscape.output.svgz.inkscape"
+ sodipodi:modified="true">
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient3931">
+ <stop
+ style="stop-color:#ebf3ff;stop-opacity:1;"
+ offset="0"
+ id="stop3933" />
+ <stop
+ id="stop3935"
+ offset="0.5"
+ style="stop-color:#cfeefe;stop-opacity:1;" />
+ <stop
+ style="stop-color:#8face1;stop-opacity:1;"
+ offset="0.75"
+ id="stop3937" />
+ <stop
+ style="stop-color:#9caedc;stop-opacity:1"
+ offset="1"
+ id="stop3940" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient6405">
+ <stop
+ id="stop6407"
+ offset="0"
+ style="stop-color:#434343;stop-opacity:1" />
+ <stop
+ style="stop-color:#69606d;stop-opacity:0;"
+ offset="0.78571427"
+ id="stop6409" />
+ <stop
+ id="stop6411"
+ offset="1"
+ style="stop-color:#705f78;stop-opacity:0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient4263">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop4265" />
+ <stop
+ style="stop-color:black;stop-opacity:0.26160339"
+ offset="1"
+ id="stop4267" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3838">
+ <stop
+ style="stop-color:#212152;stop-opacity:1"
+ offset="0"
+ id="stop3840" />
+ <stop
+ style="stop-color:#272768;stop-opacity:0;"
+ offset="1"
+ id="stop3842" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3877">
+ <stop
+ id="stop3879"
+ offset="0"
+ style="stop-color:#5b75ac;stop-opacity:1" />
+ <stop
+ id="stop3881"
+ offset="1"
+ style="stop-color:#829acf;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5016">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop5018" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop5020" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5002">
+ <stop
+ style="stop-color:#99bcfa;stop-opacity:1;"
+ offset="0"
+ id="stop5004" />
+ <stop
+ style="stop-color:#20376c;stop-opacity:1"
+ offset="1"
+ id="stop5006" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient4970">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop4972" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop4974" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2980">
+ <stop
+ style="stop-color:#19274c;stop-opacity:1"
+ offset="0"
+ id="stop2982" />
+ <stop
+ style="stop-color:#7b92af;stop-opacity:1"
+ offset="1"
+ id="stop2984" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3747">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop3749" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop3751" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2954"
+ id="linearGradient4332"
+ gradientUnits="userSpaceOnUse"
+ x1="814.44556"
+ y1="742.2583"
+ x2="814.44556"
+ y2="699.93915" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3937"
+ id="linearGradient4330"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.367696,0.367696)"
+ x1="809.74945"
+ y1="715.75433"
+ x2="822.82684"
+ y2="711.34198" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3771"
+ id="linearGradient4328"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,-0.357143,0.821429,258.463,86.94653)"
+ x1="815.54865"
+ y1="721.63739"
+ x2="812.54578"
+ y2="701.04614" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2957"
+ id="linearGradient4326"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.945605,-0.217581,0.40526,0.47818,-220.401,581.0172)"
+ x1="815.54865"
+ y1="721.63739"
+ x2="810.40088"
+ y2="701.04645" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3771"
+ id="linearGradient4324"
+ gradientUnits="userSpaceOnUse"
+ x1="815.54865"
+ y1="721.63739"
+ x2="810.40088"
+ y2="701.04645" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3937"
+ id="linearGradient4322"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-11.76626,14.70782)"
+ x1="812.69104"
+ y1="719.43127"
+ x2="822.82684"
+ y2="711.34198" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient4316"
+ gradientUnits="userSpaceOnUse"
+ x1="911.05261"
+ y1="548.50476"
+ x2="793.18713"
+ y2="793.88776" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3771"
+ id="radialGradient4314"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.76434,-2.35869e-2,0.426816,1.801459,-928.0471,-507.7961)"
+ cx="819.57001"
+ cy="681.40497"
+ fx="819.57001"
+ fy="681.40497"
+ r="89.050735" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3146"
+ id="linearGradient4312"
+ gradientUnits="userSpaceOnUse"
+ x1="823.68597"
+ y1="611.11115"
+ x2="806.85175"
+ y2="711.99713" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3463"
+ id="radialGradient4310"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.402597,0,-270.1008)"
+ cx="828.16028"
+ cy="706.72321"
+ fx="828.16028"
+ fy="706.72321"
+ r="84.93766" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3422"
+ id="linearGradient4308"
+ gradientUnits="userSpaceOnUse"
+ x1="837.68555"
+ y1="796.52527"
+ x2="780.84125"
+ y2="572.90417" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3422"
+ id="linearGradient4306"
+ gradientUnits="userSpaceOnUse"
+ x1="799.76501"
+ y1="597.83502"
+ x2="814.95313"
+ y2="814.15497" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient4286"
+ gradientUnits="userSpaceOnUse"
+ x1="823.10938"
+ y1="833.45209"
+ x2="823.10938"
+ y2="858.61041" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient4284"
+ gradientUnits="userSpaceOnUse"
+ x1="912.13434"
+ y1="738.04584"
+ x2="892.15674"
+ y2="785.84998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient4282"
+ gradientUnits="userSpaceOnUse"
+ x1="751.09253"
+ y1="735"
+ x2="732.11664"
+ y2="745.52069" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient4280"
+ gradientUnits="userSpaceOnUse"
+ x1="867.10388"
+ y1="601.625"
+ x2="850.70032"
+ y2="613.44067" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient4278"
+ gradientUnits="userSpaceOnUse"
+ x1="743.77771"
+ y1="577.80316"
+ x2="760.22034"
+ y2="597.8407" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient4276"
+ gradientUnits="userSpaceOnUse"
+ x1="911.05261"
+ y1="548.50476"
+ x2="771.66034"
+ y2="777.76068" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient4274"
+ gradientUnits="userSpaceOnUse"
+ x1="911.05261"
+ y1="548.50476"
+ x2="771.66034"
+ y2="777.76068" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient4272"
+ gradientUnits="userSpaceOnUse"
+ x1="911.05261"
+ y1="548.50476"
+ x2="771.66034"
+ y2="777.76068" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient4270"
+ gradientUnits="userSpaceOnUse"
+ x1="911.05261"
+ y1="548.50476"
+ x2="771.66034"
+ y2="777.76068" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient4268"
+ gradientUnits="userSpaceOnUse"
+ x1="911.05261"
+ y1="548.50476"
+ x2="771.66034"
+ y2="777.76068" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient4266"
+ gradientUnits="userSpaceOnUse"
+ x1="782.83337"
+ y1="799.42517"
+ x2="864.77716"
+ y2="577.03143" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3937">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop3939" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop3941" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3771">
+ <stop
+ style="stop-color:#808aa5;stop-opacity:1;"
+ offset="0"
+ id="stop3773" />
+ <stop
+ style="stop-color:#363c4d;stop-opacity:1;"
+ offset="1"
+ id="stop3775" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3463">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop3465" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop3467" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3422">
+ <stop
+ style="stop-color:#959db8;stop-opacity:1;"
+ offset="0"
+ id="stop3424" />
+ <stop
+ id="stop3432"
+ offset="0.25"
+ style="stop-color:#d3d7e2;stop-opacity:1;" />
+ <stop
+ id="stop3430"
+ offset="0.5"
+ style="stop-color:#566081;stop-opacity:1;" />
+ <stop
+ style="stop-color:#bdc2d3;stop-opacity:1;"
+ offset="0.75"
+ id="stop3434" />
+ <stop
+ id="stop3436"
+ offset="0.875"
+ style="stop-color:#959db8;stop-opacity:1;" />
+ <stop
+ style="stop-color:#586284;stop-opacity:1;"
+ offset="1"
+ id="stop3426" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4018">
+ <stop
+ style="stop-color:#272b3a;stop-opacity:1;"
+ offset="0"
+ id="stop4020" />
+ <stop
+ id="stop4044"
+ offset="0.5"
+ style="stop-color:#8b97a4;stop-opacity:1;" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop4022" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3611">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop3613" />
+ <stop
+ id="stop3619"
+ offset="0.5"
+ style="stop-color:#7f7f7f;stop-opacity:0;" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop3615" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3599">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop3601" />
+ <stop
+ style="stop-color:#474747;stop-opacity:1;"
+ offset="1"
+ id="stop3603" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3347">
+ <stop
+ style="stop-color:#434343;stop-opacity:0;"
+ offset="0"
+ id="stop3349" />
+ <stop
+ id="stop3357"
+ offset="0.78571427"
+ style="stop-color:#69606d;stop-opacity:0;" />
+ <stop
+ style="stop-color:#705f78;stop-opacity:1;"
+ offset="1"
+ id="stop3351" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3337">
+ <stop
+ style="stop-color:#1d1d1d;stop-opacity:1;"
+ offset="0"
+ id="stop3339" />
+ <stop
+ style="stop-color:#483030;stop-opacity:1;"
+ offset="1"
+ id="stop3342" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3660">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop3662" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop3664" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3651">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop3653" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop3655" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3602">
+ <stop
+ style="stop-color:#485276;stop-opacity:1;"
+ offset="0"
+ id="stop3604" />
+ <stop
+ style="stop-color:#485276;stop-opacity:0;"
+ offset="1"
+ id="stop3606" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3592">
+ <stop
+ style="stop-color:#141921;stop-opacity:1;"
+ offset="0"
+ id="stop3594" />
+ <stop
+ style="stop-color:#141921;stop-opacity:0;"
+ offset="1"
+ id="stop3596" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3582">
+ <stop
+ style="stop-color:#aaa4b9;stop-opacity:1;"
+ offset="0"
+ id="stop3584" />
+ <stop
+ style="stop-color:#aaa4b9;stop-opacity:0;"
+ offset="1"
+ id="stop3586" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3556">
+ <stop
+ style="stop-color:#506485;stop-opacity:1;"
+ offset="0"
+ id="stop3558" />
+ <stop
+ style="stop-color:#506485;stop-opacity:0;"
+ offset="1"
+ id="stop3560" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3535">
+ <stop
+ style="stop-color:#393e68;stop-opacity:1;"
+ offset="0"
+ id="stop3537" />
+ <stop
+ style="stop-color:#393e68;stop-opacity:0;"
+ offset="1"
+ id="stop3539" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3512">
+ <stop
+ id="stop3514"
+ offset="0"
+ style="stop-color:white;stop-opacity:1;" />
+ <stop
+ style="stop-color:#d8e6fd;stop-opacity:1;"
+ offset="0.5"
+ id="stop3518" />
+ <stop
+ id="stop3516"
+ offset="1"
+ style="stop-color:#9dc1f9;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3495">
+ <stop
+ style="stop-color:#181e34;stop-opacity:1;"
+ offset="0"
+ id="stop3497" />
+ <stop
+ style="stop-color:#181e34;stop-opacity:0;"
+ offset="1"
+ id="stop3499" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3483">
+ <stop
+ style="stop-color:#7b7ecb;stop-opacity:1;"
+ offset="0"
+ id="stop3485" />
+ <stop
+ style="stop-color:#969eba;stop-opacity:1;"
+ offset="1"
+ id="stop3487" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3475">
+ <stop
+ style="stop-color:#eef0f7;stop-opacity:1;"
+ offset="0"
+ id="stop3477" />
+ <stop
+ style="stop-color:#bec0f8;stop-opacity:1;"
+ offset="1"
+ id="stop3479" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3452">
+ <stop
+ style="stop-color:#6072b2;stop-opacity:1;"
+ offset="0"
+ id="stop3454" />
+ <stop
+ style="stop-color:#6072b2;stop-opacity:0;"
+ offset="1"
+ id="stop3456" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3419">
+ <stop
+ style="stop-color:#b8bce6;stop-opacity:1;"
+ offset="0"
+ id="stop3421" />
+ <stop
+ style="stop-color:#b8bce6;stop-opacity:0;"
+ offset="1"
+ id="stop3423" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3371">
+ <stop
+ id="stop3373"
+ offset="0"
+ style="stop-color:#1d44a6;stop-opacity:1;" />
+ <stop
+ id="stop3375"
+ offset="1"
+ style="stop-color:#2d82df;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3361">
+ <stop
+ style="stop-color:#818181;stop-opacity:1;"
+ offset="0"
+ id="stop3363" />
+ <stop
+ style="stop-color:#b6b6b6;stop-opacity:1;"
+ offset="1"
+ id="stop3365" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3293">
+ <stop
+ style="stop-color:#7987b8;stop-opacity:1;"
+ offset="0"
+ id="stop3295" />
+ <stop
+ style="stop-color:#2a324f;stop-opacity:1;"
+ offset="1"
+ id="stop3297" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3276">
+ <stop
+ style="stop-color:#000b17;stop-opacity:1;"
+ offset="0"
+ id="stop3278" />
+ <stop
+ style="stop-color:#000b17;stop-opacity:0;"
+ offset="1"
+ id="stop3280" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3232">
+ <stop
+ style="stop-color:#a7d0fe;stop-opacity:1;"
+ offset="0"
+ id="stop3235" />
+ <stop
+ style="stop-color:#7987b8;stop-opacity:1;"
+ offset="1"
+ id="stop3237" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3221">
+ <stop
+ style="stop-color:#5b78a4;stop-opacity:1;"
+ offset="0"
+ id="stop3224" />
+ <stop
+ style="stop-color:#4b5587;stop-opacity:1;"
+ offset="1"
+ id="stop3226" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3208">
+ <stop
+ style="stop-color:#7b90c5;stop-opacity:1;"
+ offset="0"
+ id="stop3210" />
+ <stop
+ style="stop-color:#7b90c5;stop-opacity:0;"
+ offset="1"
+ id="stop3212" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3314">
+ <stop
+ style="stop-color:#464e64;stop-opacity:1;"
+ offset="0"
+ id="stop3316" />
+ <stop
+ style="stop-color:#273251;stop-opacity:1;"
+ offset="1"
+ id="stop3318" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3254">
+ <stop
+ style="stop-color:#0e0d13;stop-opacity:1;"
+ offset="0"
+ id="stop3257" />
+ <stop
+ style="stop-color:#45405e;stop-opacity:1;"
+ offset="1"
+ id="stop3259" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3197">
+ <stop
+ style="stop-color:#6b83ac;stop-opacity:1;"
+ offset="0"
+ id="stop3199" />
+ <stop
+ style="stop-color:#899cbd;stop-opacity:1;"
+ offset="1"
+ id="stop3201" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3172">
+ <stop
+ style="stop-color:#556c95;stop-opacity:1;"
+ offset="0"
+ id="stop3174" />
+ <stop
+ style="stop-color:#242e3f;stop-opacity:1;"
+ offset="1"
+ id="stop3176" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3725">
+ <stop
+ style="stop-color:#312e43;stop-opacity:1;"
+ offset="0"
+ id="stop3727" />
+ <stop
+ style="stop-color:#1d1b28;stop-opacity:1;"
+ offset="1"
+ id="stop3729" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3715">
+ <stop
+ style="stop-color:#6f7790;stop-opacity:1;"
+ offset="0"
+ id="stop3717" />
+ <stop
+ style="stop-color:#6f7790;stop-opacity:0;"
+ offset="1"
+ id="stop3719" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3688">
+ <stop
+ style="stop-color:#b3d2fe;stop-opacity:1;"
+ offset="0"
+ id="stop3690" />
+ <stop
+ id="stop3696"
+ offset="0.5"
+ style="stop-color:#e0edff;stop-opacity:1;" />
+ <stop
+ style="stop-color:#cbeafa;stop-opacity:1;"
+ offset="1"
+ id="stop3692" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3674">
+ <stop
+ style="stop-color:#9ea9cd;stop-opacity:1;"
+ offset="0"
+ id="stop3676" />
+ <stop
+ style="stop-color:#b3d2fe;stop-opacity:1;"
+ offset="1"
+ id="stop3678" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3664">
+ <stop
+ style="stop-color:#6681c4;stop-opacity:1;"
+ offset="0"
+ id="stop3666" />
+ <stop
+ style="stop-color:#6681c4;stop-opacity:0;"
+ offset="1"
+ id="stop3668" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2747">
+ <stop
+ style="stop-color:#c0faff;stop-opacity:1;"
+ offset="0"
+ id="stop2749" />
+ <stop
+ style="stop-color:#f9ffff;stop-opacity:1;"
+ offset="1"
+ id="stop2751" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3261">
+ <stop
+ style="stop-color:#8b9fdc;stop-opacity:1;"
+ offset="0"
+ id="stop3263" />
+ <stop
+ style="stop-color:#354572;stop-opacity:1;"
+ offset="1"
+ id="stop3265" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3241">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop3243" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop3245" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3229">
+ <stop
+ style="stop-color:#8390d3;stop-opacity:1;"
+ offset="0"
+ id="stop3231" />
+ <stop
+ style="stop-color:#253068;stop-opacity:1;"
+ offset="1"
+ id="stop3233" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3209">
+ <stop
+ style="stop-color:#ebf1ff;stop-opacity:1;"
+ offset="0"
+ id="stop3211" />
+ <stop
+ id="stop3269"
+ offset="0.2109797"
+ style="stop-color:#99bbd2;stop-opacity:1;" />
+ <stop
+ style="stop-color:#506d8e;stop-opacity:1;"
+ offset="0.64264262"
+ id="stop4996" />
+ <stop
+ id="stop4998"
+ offset="0.78125"
+ style="stop-color:#4f6586;stop-opacity:1;" />
+ <stop
+ style="stop-color:#20376c;stop-opacity:1;"
+ offset="1"
+ id="stop3213" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3190">
+ <stop
+ style="stop-color:#a6bee0;stop-opacity:1;"
+ offset="0"
+ id="stop3192" />
+ <stop
+ style="stop-color:#a6bee0;stop-opacity:0;"
+ offset="1"
+ id="stop3194" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3157">
+ <stop
+ style="stop-color:#214673;stop-opacity:1;"
+ offset="0"
+ id="stop3159" />
+ <stop
+ style="stop-color:#7e8cbe;stop-opacity:1;"
+ offset="1"
+ id="stop3161" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3059">
+ <stop
+ style="stop-color:#a5c1ff;stop-opacity:1;"
+ offset="0"
+ id="stop3061" />
+ <stop
+ id="stop3071"
+ offset="0.34999999"
+ style="stop-color:#8bbbff;stop-opacity:1;" />
+ <stop
+ id="stop3069"
+ offset="0.56"
+ style="stop-color:#96d5ff;stop-opacity:1;" />
+ <stop
+ style="stop-color:#f0f5ff;stop-opacity:1;"
+ offset="1"
+ id="stop3063" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3049">
+ <stop
+ style="stop-color:#19274c;stop-opacity:1;"
+ offset="0"
+ id="stop3051" />
+ <stop
+ style="stop-color:#19274c;stop-opacity:0;"
+ offset="1"
+ id="stop3053" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3033">
+ <stop
+ style="stop-color:#a8bbc8;stop-opacity:1;"
+ offset="0"
+ id="stop3035" />
+ <stop
+ id="stop3041"
+ offset="0.25"
+ style="stop-color:#223261;stop-opacity:1;" />
+ <stop
+ style="stop-color:#3d4c75;stop-opacity:1;"
+ offset="0.5"
+ id="stop3043" />
+ <stop
+ id="stop3045"
+ offset="0.75"
+ style="stop-color:#3d528b;stop-opacity:1;" />
+ <stop
+ style="stop-color:#9caedf;stop-opacity:1;"
+ offset="1"
+ id="stop3037" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3015">
+ <stop
+ style="stop-color:#a7bffb;stop-opacity:1;"
+ offset="0"
+ id="stop3017" />
+ <stop
+ id="stop3026"
+ offset="0.5"
+ style="stop-color:#a7cffb;stop-opacity:1;" />
+ <stop
+ style="stop-color:#dcf3fe;stop-opacity:1;"
+ offset="1"
+ id="stop3019" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3099">
+ <stop
+ style="stop-color:#9dc1ff;stop-opacity:1;"
+ offset="0"
+ id="stop3101" />
+ <stop
+ id="stop3107"
+ offset="0.60714287"
+ style="stop-color:#93b4f3;stop-opacity:1;" />
+ <stop
+ style="stop-color:#cbeaff;stop-opacity:1;"
+ offset="1"
+ id="stop3103" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3068">
+ <stop
+ style="stop-color:#aeccef;stop-opacity:1;"
+ offset="0"
+ id="stop3070" />
+ <stop
+ style="stop-color:#aeccef;stop-opacity:0;"
+ offset="1"
+ id="stop3072" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2979">
+ <stop
+ style="stop-color:#8c99c6;stop-opacity:1;"
+ offset="0"
+ id="stop2981" />
+ <stop
+ style="stop-color:#8c99c6;stop-opacity:0;"
+ offset="1"
+ id="stop2983" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3056">
+ <stop
+ style="stop-color:#4b72a9;stop-opacity:1;"
+ offset="0"
+ id="stop3058" />
+ <stop
+ style="stop-color:#4b72a9;stop-opacity:0;"
+ offset="1"
+ id="stop3060" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3046">
+ <stop
+ style="stop-color:#0b1e37;stop-opacity:1;"
+ offset="0"
+ id="stop3048" />
+ <stop
+ style="stop-color:#0b1e37;stop-opacity:0;"
+ offset="1"
+ id="stop3050" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3032">
+ <stop
+ style="stop-color:#27528b;stop-opacity:1;"
+ offset="0"
+ id="stop3034" />
+ <stop
+ style="stop-color:#0a3064;stop-opacity:1;"
+ offset="1"
+ id="stop3036" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3010">
+ <stop
+ style="stop-color:#c5c8ff;stop-opacity:0;"
+ offset="0"
+ id="stop3012" />
+ <stop
+ id="stop3030"
+ offset="0.5"
+ style="stop-color:#91d3ff;stop-opacity:0.72156864;" />
+ <stop
+ style="stop-color:#e0fdff;stop-opacity:1;"
+ offset="1"
+ id="stop3014" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3000">
+ <stop
+ style="stop-color:#34628c;stop-opacity:1;"
+ offset="0"
+ id="stop3002" />
+ <stop
+ style="stop-color:#34628c;stop-opacity:0;"
+ offset="1"
+ id="stop3004" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2972">
+ <stop
+ style="stop-color:#7d8da5;stop-opacity:1;"
+ offset="0"
+ id="stop2974" />
+ <stop
+ style="stop-color:#5f6f89;stop-opacity:1;"
+ offset="1"
+ id="stop2976" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2954">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop2956" />
+ <stop
+ id="stop2962"
+ offset="0.5"
+ style="stop-color:#b8b8b8;stop-opacity:1;" />
+ <stop
+ style="stop-color:#2a2a2a;stop-opacity:1;"
+ offset="1"
+ id="stop2958" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2938">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop2940" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop2942" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2916">
+ <stop
+ style="stop-color:#353c47;stop-opacity:1;"
+ offset="0"
+ id="stop2918" />
+ <stop
+ style="stop-color:#353c47;stop-opacity:0;"
+ offset="1"
+ id="stop2920" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3332">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop3334" />
+ <stop
+ id="stop3341"
+ offset="0.5535714"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop3336" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3317">
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="0"
+ id="stop3319" />
+ <stop
+ id="stop3325"
+ offset="0.5"
+ style="stop-color:black;stop-opacity:0.14432989;" />
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="1"
+ id="stop3321" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3931"
+ id="linearGradient3288"
+ x1="321.67255"
+ y1="442.76962"
+ x2="325.79459"
+ y2="409.21478"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,50)" />
+ <linearGradient
+ id="linearGradient3290">
+ <stop
+ id="stop3292"
+ offset="0"
+ style="stop-color:#ebf3ff;stop-opacity:1;" />
+ <stop
+ style="stop-color:#cfeefe;stop-opacity:1;"
+ offset="0.5"
+ id="stop3294" />
+ <stop
+ id="stop3298"
+ offset="0.75"
+ style="stop-color:#8face1;stop-opacity:1;" />
+ <stop
+ id="stop3296"
+ offset="1"
+ style="stop-color:#8aa3e1;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3262">
+ <stop
+ style="stop-color:#42495a;stop-opacity:1;"
+ offset="0"
+ id="stop3264" />
+ <stop
+ style="stop-color:#42495a;stop-opacity:0;"
+ offset="1"
+ id="stop3266" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3252">
+ <stop
+ style="stop-color:#afc3e6;stop-opacity:1;"
+ offset="0"
+ id="stop3254" />
+ <stop
+ style="stop-color:#afc3e6;stop-opacity:0;"
+ offset="1"
+ id="stop3256" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3240">
+ <stop
+ style="stop-color:#8c99c6;stop-opacity:1;"
+ offset="0"
+ id="stop3242" />
+ <stop
+ style="stop-color:#86a3ea;stop-opacity:1;"
+ offset="1"
+ id="stop3244" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3230">
+ <stop
+ style="stop-color:#b0ddfa;stop-opacity:1;"
+ offset="0"
+ id="stop3232" />
+ <stop
+ style="stop-color:#e5f5ff;stop-opacity:1;"
+ offset="1"
+ id="stop3234" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3214">
+ <stop
+ style="stop-color:#9ea9cd;stop-opacity:1;"
+ offset="0"
+ id="stop3216" />
+ <stop
+ style="stop-color:#9ea9cd;stop-opacity:0;"
+ offset="1"
+ id="stop3218" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3200">
+ <stop
+ style="stop-color:#8197da;stop-opacity:1;"
+ offset="0"
+ id="stop3202" />
+ <stop
+ style="stop-color:#232f54;stop-opacity:1"
+ offset="1"
+ id="stop3204" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3186">
+ <stop
+ style="stop-color:#a9c7fd;stop-opacity:1;"
+ offset="0"
+ id="stop3188" />
+ <stop
+ style="stop-color:#c7ebfe;stop-opacity:1;"
+ offset="1"
+ id="stop3190" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3176">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop3178" />
+ <stop
+ style="stop-color:white;stop-opacity:0.41237113;"
+ offset="1"
+ id="stop3180" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3168">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop3170" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop3172" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3156">
+ <stop
+ style="stop-color:#ebf3ff;stop-opacity:1;"
+ offset="0"
+ id="stop3158" />
+ <stop
+ id="stop3164"
+ offset="0.5"
+ style="stop-color:#cfeefe;stop-opacity:1;" />
+ <stop
+ style="stop-color:#b3d2fe;stop-opacity:1;"
+ offset="1"
+ id="stop3160" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3146">
+ <stop
+ style="stop-color:#687586;stop-opacity:1;"
+ offset="0"
+ id="stop3148" />
+ <stop
+ style="stop-color:#8ba7cb;stop-opacity:1;"
+ offset="1"
+ id="stop3150" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3126">
+ <stop
+ style="stop-color:#ff9739;stop-opacity:1;"
+ offset="0"
+ id="stop3128" />
+ <stop
+ style="stop-color:#ff9739;stop-opacity:0;"
+ offset="1"
+ id="stop3130" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3108">
+ <stop
+ style="stop-color:#ffaa57;stop-opacity:1;"
+ offset="0"
+ id="stop3110" />
+ <stop
+ style="stop-color:#c35c00;stop-opacity:0.76288658;"
+ offset="1"
+ id="stop3112" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3062">
+ <stop
+ style="stop-color:#444;stop-opacity:1;"
+ offset="0"
+ id="stop3064" />
+ <stop
+ style="stop-color:#6e6e6e;stop-opacity:1;"
+ offset="1"
+ id="stop3066" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3003">
+ <stop
+ style="stop-color:#6b96c6;stop-opacity:1;"
+ offset="0"
+ id="stop3005" />
+ <stop
+ id="stop3044"
+ offset="0.29464287"
+ style="stop-color:#84b2da;stop-opacity:1;" />
+ <stop
+ id="stop3013"
+ offset="0.5"
+ style="stop-color:#9eceee;stop-opacity:1;" />
+ <stop
+ style="stop-color:#cedcec;stop-opacity:1;"
+ offset="1"
+ id="stop3007" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2993">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop2995" />
+ <stop
+ style="stop-color:#9dc1f9;stop-opacity:1;"
+ offset="1"
+ id="stop2997" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2957">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop2959" />
+ <stop
+ id="stop3088"
+ offset="0.5"
+ style="stop-color:#c1d7fc;stop-opacity:0.79381442;" />
+ <stop
+ style="stop-color:#c1d7fc;stop-opacity:0;"
+ offset="1"
+ id="stop2961" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2848">
+ <stop
+ style="stop-color:#5b6879;stop-opacity:1;"
+ offset="0"
+ id="stop2850" />
+ <stop
+ style="stop-color:#6c7c90;stop-opacity:1;"
+ offset="1"
+ id="stop2852" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2848"
+ id="linearGradient2854"
+ x1="605.78571"
+ y1="693.82843"
+ x2="679.82141"
+ y2="416.68555"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2957"
+ id="linearGradient2963"
+ x1="1059.4688"
+ y1="542.11444"
+ x2="1008.7902"
+ y2="639.25726"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2993"
+ id="linearGradient2999"
+ x1="81.606529"
+ y1="264.65201"
+ x2="611.91901"
+ y2="264.65201"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3003"
+ id="radialGradient3011"
+ cx="575.95508"
+ cy="20.347525"
+ fx="575.95508"
+ fy="20.347525"
+ r="240.65582"
+ gradientTransform="matrix(1.330288,0.722981,-0.410079,0.754547,-166.9089,-302.4274)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3062"
+ id="linearGradient3086"
+ x1="538.01337"
+ y1="286.5759"
+ x2="618.42566"
+ y2="118.00446"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3108"
+ id="linearGradient3140"
+ gradientUnits="userSpaceOnUse"
+ x1="989.28571"
+ y1="1700.8572"
+ x2="990.71429"
+ y2="1690.8738" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3126"
+ id="linearGradient3142"
+ gradientUnits="userSpaceOnUse"
+ x1="995.00024"
+ y1="1697.8326"
+ x2="992.47485"
+ y2="1687.7312" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3146"
+ id="linearGradient3152"
+ x1="682.85712"
+ y1="509.42856"
+ x2="716.42859"
+ y2="397.57141"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3156"
+ id="radialGradient3162"
+ cx="574.18042"
+ cy="1347.757"
+ fx="574.18042"
+ fy="1347.757"
+ r="191.53386"
+ gradientTransform="matrix(1,0,0,0.55348,-14.28574,-379.0895)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3176"
+ id="radialGradient3182"
+ cx="1281.3784"
+ cy="1089.6825"
+ fx="1281.3784"
+ fy="1089.6825"
+ r="462.13467"
+ gradientTransform="matrix(0.418567,1.138515e-8,0,0.199982,745.0363,502.0475)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3186"
+ id="linearGradient3192"
+ x1="378.57144"
+ y1="1178"
+ x2="281.3913"
+ y2="1148"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-2.857144,-958.5714)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3186"
+ id="linearGradient3196"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-7.857129,-957.8571)"
+ x1="378.57144"
+ y1="1178"
+ x2="294.96271"
+ y2="1148" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3200"
+ id="linearGradient3206"
+ x1="302.69244"
+ y1="1206.0665"
+ x2="299.28571"
+ y2="1189.4286"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.285714,-1016.857)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3214"
+ id="linearGradient3220"
+ x1="312.85715"
+ y1="1122.2858"
+ x2="297.34143"
+ y2="1120.8572"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(5.285716,-959.1429)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3230"
+ id="linearGradient3236"
+ x1="260"
+ y1="1203"
+ x2="185"
+ y2="1170.1428"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(2.14286,-1043.571)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3240"
+ id="linearGradient3246"
+ x1="235.71429"
+ y1="1084.4683"
+ x2="237.14285"
+ y2="1102.2856"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.857136,-966.2856)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3252"
+ id="linearGradient3258"
+ x1="-265.71429"
+ y1="655.14288"
+ x2="105.71429"
+ y2="898"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(343.7143,-513.2857)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3262"
+ id="linearGradient3268"
+ x1="660.63977"
+ y1="714.95422"
+ x2="661.38232"
+ y2="527.64288"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3156"
+ id="linearGradient3310"
+ x1="198.10001"
+ y1="362.28571"
+ x2="276.1857"
+ y2="362.28571"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(20,0)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3317"
+ id="radialGradient3328"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.681717,-0.196991,1.189962,4.118073,-340.6222,-1084.458)"
+ cx="300.60941"
+ cy="366.53375"
+ fx="300.60941"
+ fy="366.53375"
+ r="33.840111" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3332"
+ id="radialGradient3343"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0.43825,-0.199228,0.4546,60.32876,28.03149)"
+ cx="315.1676"
+ cy="302.81201"
+ fx="315.1676"
+ fy="302.81201"
+ r="154.43303" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3290"
+ id="linearGradient2024"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-36.21248,-969.3161)"
+ x1="236.21936"
+ y1="1114.7728"
+ x2="234.11238"
+ y2="1072.989" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2916"
+ id="radialGradient2922"
+ cx="454.64285"
+ cy="610.14288"
+ fx="454.64285"
+ fy="610.14288"
+ r="249.64285"
+ gradientTransform="matrix(1,0,0,0.549356,0,274.9571)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2938"
+ id="linearGradient2944"
+ x1="306.85715"
+ y1="266.8215"
+ x2="357.2941"
+ y2="227.53578"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2954"
+ id="radialGradient2960"
+ cx="342.5"
+ cy="424.42856"
+ fx="342.5"
+ fy="424.42856"
+ r="32.785721"
+ gradientTransform="matrix(2.109187,-1.212215e-6,2.571153e-6,4.473662,-379.8976,-1474.32)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2972"
+ id="linearGradient2978"
+ x1="148.61224"
+ y1="381.59784"
+ x2="108.62619"
+ y2="201.59782"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3032"
+ id="linearGradient3136"
+ gradientUnits="userSpaceOnUse"
+ x1="1105.9832"
+ y1="1614.0305"
+ x2="917.41821"
+ y2="1754.0305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3046"
+ id="linearGradient3138"
+ gradientUnits="userSpaceOnUse"
+ x1="930"
+ y1="1780"
+ x2="1002"
+ y2="1698" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3000"
+ id="linearGradient3141"
+ gradientUnits="userSpaceOnUse"
+ x1="1202"
+ y1="1738"
+ x2="1226.4431"
+ y2="1812.2965" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3010"
+ id="linearGradient3143"
+ gradientUnits="userSpaceOnUse"
+ x1="1340.5737"
+ y1="1702.1013"
+ x2="1381.4182"
+ y2="1632.1013" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3056"
+ id="linearGradient3145"
+ gradientUnits="userSpaceOnUse"
+ x1="1140"
+ y1="1753"
+ x2="1128"
+ y2="1771" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2979"
+ id="linearGradient2985"
+ x1="72.359482"
+ y1="174.41611"
+ x2="87.939209"
+ y2="175.18224"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3068"
+ id="linearGradient3074"
+ x1="324.92596"
+ y1="477.6283"
+ x2="340.82547"
+ y2="440.29376"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3099"
+ id="linearGradient3177"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-90)"
+ x1="898"
+ y1="1078"
+ x2="1830"
+ y2="1237.4438" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2957"
+ id="linearGradient3179"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-450)"
+ x1="1035"
+ y1="1524"
+ x2="1377"
+ y2="1544" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2957"
+ id="linearGradient3181"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-90)"
+ x1="1258"
+ y1="939"
+ x2="1152"
+ y2="1126.6492" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2957"
+ id="linearGradient3183"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(312,-152)"
+ x1="1255"
+ y1="976"
+ x2="1234.5"
+ y2="1155" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3168"
+ id="linearGradient3185"
+ gradientUnits="userSpaceOnUse"
+ x1="1491"
+ y1="922"
+ x2="1643"
+ y2="1000" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3015"
+ id="radialGradient3028"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,2.342884e-7,-2.223753e-7,0.949152,9.885316e-5,-47.39676)"
+ cx="686.60065"
+ cy="439.31793"
+ fx="686.60065"
+ fy="439.31793"
+ r="83.438599" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3059"
+ id="radialGradient3083"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.384977,-5.035681e-8,2.308549e-8,0.63493,-225.5372,145.4852)"
+ cx="595.03033"
+ cy="230.00166"
+ fx="595.03033"
+ fy="230.00166"
+ r="75.30687" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3049"
+ id="linearGradient3088"
+ gradientUnits="userSpaceOnUse"
+ x1="612.35449"
+ y1="324.73068"
+ x2="624.37524"
+ y2="328.97333" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3033"
+ id="linearGradient3091"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1.414207,0.707104)"
+ x1="599.91406"
+ y1="356.82278"
+ x2="625.0824"
+ y2="363.18677" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3321">
+ <path
+ style="opacity:1;color:black;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 973.22231,1494.6884 C 980.29341,1498.729 1119.1893,1603.7849 1134.3416,1615.9067 C 1149.4938,1628.0285 1253.5396,1719.9524 1262.6309,1731.0641 C 1341.4228,1729.0438 1391.9305,1720.9626 1391.9305,1720.9626 C 1391.9305,1720.9626 1264.6512,1621.9676 1227.2756,1597.7239 C 1189.9,1573.4803 1111.1081,1524.993 1101.0065,1518.932 C 1090.905,1512.8711 1067.6715,1504.7899 1057.57,1503.7798 C 1047.4684,1502.7696 973.22231,1494.6884 973.22231,1494.6884 z "
+ sodipodi:nodetypes="csccsssc"
+ id="path3317" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3157"
+ id="linearGradient3340"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(37.44,-16.64)"
+ x1="1403.2334"
+ y1="1581.9968"
+ x2="1396.5648"
+ y2="1632.5245" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3190"
+ id="linearGradient3342"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(37.44,-16.64)"
+ x1="1155.48"
+ y1="1550.48"
+ x2="1355.08"
+ y2="1548.92" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3261"
+ id="linearGradient3344"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-216.9404,-73.53911)"
+ x1="1242.0754"
+ y1="1584.9865"
+ x2="1242.0754"
+ y2="1598.2235" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3209"
+ id="radialGradient3346"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.756834,0.11341,-6.052729e-2,0.937628,-578.1804,-19.99804)"
+ cx="1000.5534"
+ cy="1561.3158"
+ fx="1000.5534"
+ fy="1561.3158"
+ r="35.931072" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3209"
+ id="linearGradient3348"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(84.56997,2.206172)"
+ x1="952.80212"
+ y1="1525.0521"
+ x2="998.19037"
+ y2="1566.1309" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2954"
+ id="linearGradient3350"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.936508,0,0,0.936508,-23.6257,32.33626)"
+ x1="1125.1483"
+ y1="1587.5604"
+ x2="1123.6775"
+ y2="1597.8558" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3229"
+ id="radialGradient3352"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.609707,0.792627,-0.764705,0.588229,1686.72,-238.9536)"
+ cx="1146.1069"
+ cy="1620.7581"
+ fx="1146.1069"
+ fy="1620.7581"
+ r="18.752472" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3241"
+ id="radialGradient3354"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.0625,0,-101.0151)"
+ cx="1206.0413"
+ cy="1616.2406"
+ fx="1206.0413"
+ fy="1616.2406"
+ r="5.8831282" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3261"
+ id="linearGradient3356"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-132.3704,-14.70782)"
+ x1="1222.2198"
+ y1="1600.4297"
+ x2="1238.3984"
+ y2="1582.7803" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3209"
+ id="linearGradient3360"
+ gradientUnits="userSpaceOnUse"
+ x1="1107.2343"
+ y1="1611.0929"
+ x2="1179.0966"
+ y2="1611.0929" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2954"
+ id="linearGradient3362"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-11.03081,1.470782)"
+ x1="1125.1483"
+ y1="1587.5604"
+ x2="1123.6775"
+ y2="1597.8558" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3229"
+ id="radialGradient3364"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.609707,0.792627,-0.764705,0.588229,1686.72,-238.9536)"
+ cx="1146.1069"
+ cy="1620.7581"
+ fx="1146.1069"
+ fy="1620.7581"
+ r="18.752472" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3241"
+ id="radialGradient3366"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.0625,0,-101.0151)"
+ cx="1206.0413"
+ cy="1616.2406"
+ fx="1206.0413"
+ fy="1616.2406"
+ r="5.8831282" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2747"
+ id="linearGradient2753"
+ x1="354.45847"
+ y1="95.084274"
+ x2="356.66464"
+ y2="108.32131"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3059"
+ id="linearGradient3648"
+ x1="839.81659"
+ y1="215.09087"
+ x2="836.30078"
+ y2="153.0452"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,3.86443,0,-686.1124)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3240"
+ id="linearGradient3659"
+ x1="874.62329"
+ y1="121.56011"
+ x2="872.55994"
+ y2="147.18008"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-70)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3664"
+ id="linearGradient3670"
+ x1="606.31995"
+ y1="67.440048"
+ x2="674.95996"
+ y2="64.320045"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3674"
+ id="linearGradient3680"
+ x1="366.59244"
+ y1="186.64046"
+ x2="389.75723"
+ y2="203.92215"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3688"
+ id="linearGradient3694"
+ x1="131.56"
+ y1="129.32004"
+ x2="154.43999"
+ y2="135.56004"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3715"
+ id="linearGradient3721"
+ x1="240.25999"
+ y1="195.36005"
+ x2="327.83997"
+ y2="195.36005"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3725"
+ id="linearGradient3731"
+ x1="1095.7327"
+ y1="928.28229"
+ x2="1092.791"
+ y2="954.75635"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-40)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3172"
+ id="linearGradient3178"
+ x1="1483.5599"
+ y1="378.92004"
+ x2="1503.3199"
+ y2="386.72003"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-50)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3197"
+ id="linearGradient3203"
+ x1="1369.8599"
+ y1="336.50003"
+ x2="1482.9082"
+ y2="336.50003"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3172"
+ id="linearGradient3237"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-30,-50)"
+ x1="1529.6799"
+ y1="370.94003"
+ x2="1540.0798"
+ y2="370.16003" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3254"
+ id="linearGradient3263"
+ x1="1410.1123"
+ y1="317.54004"
+ x2="1411.583"
+ y2="326.91629"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3254"
+ id="linearGradient3267"
+ gradientUnits="userSpaceOnUse"
+ x1="1442.1018"
+ y1="321.95239"
+ x2="1506.8162"
+ y2="339.2341" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3254"
+ id="linearGradient3271"
+ gradientUnits="userSpaceOnUse"
+ x1="1288.0374"
+ y1="342.54333"
+ x2="1289.5081"
+ y2="358.90579" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3254"
+ id="linearGradient3275"
+ gradientUnits="userSpaceOnUse"
+ x1="1410.1123"
+ y1="327.46783"
+ x2="1413.0538"
+ y2="343.46259" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3254"
+ id="linearGradient3283"
+ gradientUnits="userSpaceOnUse"
+ x1="1065.2139"
+ y1="356.88348"
+ x2="1065.9492"
+ y2="373.79745" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3361"
+ id="linearGradient3367"
+ x1="1684.7999"
+ y1="745.52002"
+ x2="1694.1599"
+ y2="771.52002"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3371"
+ id="linearGradient3377"
+ gradientUnits="userSpaceOnUse"
+ x1="1684.7999"
+ y1="745.52002"
+ x2="1694.1599"
+ y2="771.52002" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3276"
+ id="linearGradient3380"
+ gradientUnits="userSpaceOnUse"
+ x1="1501.2399"
+ y1="852.64001"
+ x2="1506.4399"
+ y2="875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3314"
+ id="linearGradient3389"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-80)"
+ x1="1253.1063"
+ y1="937.10699"
+ x2="1841.4191"
+ y2="776.79175" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3232"
+ id="linearGradient3400"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-50)"
+ x1="1738.3599"
+ y1="851.60004"
+ x2="1528.7999"
+ y2="935.32001" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3208"
+ id="linearGradient3404"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-30,0)"
+ x1="1853.7999"
+ y1="719.00006"
+ x2="1847.5599"
+ y2="727.32001" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3221"
+ id="linearGradient3407"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-30,0)"
+ x1="1813.7599"
+ y1="765.79999"
+ x2="1807.5199"
+ y2="772.56" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3293"
+ id="linearGradient3411"
+ gradientUnits="userSpaceOnUse"
+ x1="1392.5599"
+ y1="917.12006"
+ x2="1314.5599"
+ y2="926.47998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3254"
+ id="linearGradient3415"
+ x1="1640.6"
+ y1="754.88"
+ x2="1645.7999"
+ y2="789.72003"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3419"
+ id="linearGradient3425"
+ x1="1492.1084"
+ y1="880.48187"
+ x2="1510.4932"
+ y2="874.59875"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3475"
+ id="linearGradient3481"
+ x1="1499.6799"
+ y1="290.52005"
+ x2="1138.7999"
+ y2="91.360046"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,10)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3483"
+ id="linearGradient3489"
+ x1="1127.8799"
+ y1="219.26003"
+ x2="1477.3199"
+ y2="219.26003"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-20)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3495"
+ id="linearGradient3501"
+ x1="1499.6799"
+ y1="300.40002"
+ x2="1490.3199"
+ y2="293.90002"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3452"
+ id="linearGradient3504"
+ gradientUnits="userSpaceOnUse"
+ x1="1410.7599"
+ y1="202.90004"
+ x2="1402.96"
+ y2="209.14005"
+ gradientTransform="translate(-40,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3240"
+ id="linearGradient3507"
+ gradientUnits="userSpaceOnUse"
+ x1="1394.86"
+ y1="194.71004"
+ x2="1409.1599"
+ y2="214.47005"
+ gradientTransform="translate(-40,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3512"
+ id="linearGradient3510"
+ gradientUnits="userSpaceOnUse"
+ x1="1391.3207"
+ y1="192.83658"
+ x2="1397.4015"
+ y2="207.39658"
+ gradientTransform="translate(-40,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3452"
+ id="linearGradient3522"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-40,0)"
+ x1="1370.4598"
+ y1="179.65312"
+ x2="1381.8999"
+ y2="194.58005" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3556"
+ id="linearGradient3618"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-30,0)"
+ x1="1775.2339"
+ y1="510.5802"
+ x2="1781.8524"
+ y2="517.19873" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3535"
+ id="linearGradient3620"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-20,0)"
+ x1="1736.2582"
+ y1="481.16455"
+ x2="1757.0873"
+ y2="498.28571" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3582"
+ id="linearGradient3622"
+ gradientUnits="userSpaceOnUse"
+ x1="1593.2843"
+ y1="384.09293"
+ x2="1627.7415"
+ y2="384.09293" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3592"
+ id="linearGradient3624"
+ gradientUnits="userSpaceOnUse"
+ x1="1615.6399"
+ y1="384.64005"
+ x2="1607.84"
+ y2="378.40002" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3602"
+ id="linearGradient3626"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-30,0)"
+ x1="1626.0399"
+ y1="366.96002"
+ x2="1639.3199"
+ y2="356.30002" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3651"
+ id="radialGradient3670"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,-2.449946e-5,3.26177e-5,1.331364,-9.189301e-3,-92.83615)"
+ cx="337.68991"
+ cy="281.73077"
+ fx="337.69009"
+ fy="281.73068"
+ r="26.197193" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3660"
+ id="radialGradient3672"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.184925,0.291241,-0.244616,0.995229,5.770674,-93.65263)"
+ cx="337.68951"
+ cy="278.87592"
+ fx="337.68961"
+ fy="278.87601"
+ r="30.057995" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient3617"
+ x1="782.83337"
+ y1="799.42517"
+ x2="864.77716"
+ y2="577.03143"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient3623"
+ gradientUnits="userSpaceOnUse"
+ x1="911.05261"
+ y1="548.50476"
+ x2="771.66034"
+ y2="777.76068" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient3627"
+ gradientUnits="userSpaceOnUse"
+ x1="911.05261"
+ y1="548.50476"
+ x2="771.66034"
+ y2="777.76068" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient3631"
+ gradientUnits="userSpaceOnUse"
+ x1="911.05261"
+ y1="548.50476"
+ x2="771.66034"
+ y2="777.76068" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient3635"
+ gradientUnits="userSpaceOnUse"
+ x1="911.05261"
+ y1="548.50476"
+ x2="771.66034"
+ y2="777.76068" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient3640"
+ gradientUnits="userSpaceOnUse"
+ x1="911.05261"
+ y1="548.50476"
+ x2="771.66034"
+ y2="777.76068" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient3852"
+ gradientUnits="userSpaceOnUse"
+ x1="751.09253"
+ y1="735"
+ x2="732.11664"
+ y2="745.52069" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient3854"
+ gradientUnits="userSpaceOnUse"
+ x1="743.77771"
+ y1="577.80316"
+ x2="760.22034"
+ y2="597.8407" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient3856"
+ gradientUnits="userSpaceOnUse"
+ x1="867.10388"
+ y1="601.625"
+ x2="850.70032"
+ y2="613.44067" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient3858"
+ gradientUnits="userSpaceOnUse"
+ x1="912.13434"
+ y1="738.04584"
+ x2="892.15674"
+ y2="785.84998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient3860"
+ gradientUnits="userSpaceOnUse"
+ x1="823.10938"
+ y1="833.45209"
+ x2="823.10938"
+ y2="858.61041" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3422"
+ id="linearGradient3711"
+ x1="799.76501"
+ y1="597.83502"
+ x2="814.95313"
+ y2="814.15497"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3611"
+ id="linearGradient3769"
+ gradientUnits="userSpaceOnUse"
+ x1="911.05261"
+ y1="548.50476"
+ x2="793.18713"
+ y2="793.88776" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3771"
+ id="radialGradient3777"
+ cx="819.57001"
+ cy="681.40497"
+ fx="819.57001"
+ fy="681.40497"
+ r="89.050735"
+ gradientTransform="matrix(1.76434,-2.35869e-2,0.426816,1.801459,-928.0471,-507.7961)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3422"
+ id="linearGradient3823"
+ gradientUnits="userSpaceOnUse"
+ x1="837.68555"
+ y1="796.52527"
+ x2="780.84125"
+ y2="572.90417" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3463"
+ id="radialGradient3825"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.402597,0,-270.1008)"
+ cx="828.16028"
+ cy="706.72321"
+ fx="828.16028"
+ fy="706.72321"
+ r="84.93766" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3146"
+ id="linearGradient3827"
+ gradientUnits="userSpaceOnUse"
+ x1="823.68597"
+ y1="611.11115"
+ x2="806.85175"
+ y2="711.99713" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3833">
+ <path
+ style="color:black;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:7.03952456;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 959.1425,564.82625 C 958.9956,564.82625 958.8509,564.85409 958.705,564.8575 C 961.2854,564.93481 963.8642,565.51476 966.3925,566.57625 C 954.3198,572.32964 947.5839,591.64301 950.8613,614.57625 C 954.1381,637.50677 966.3961,656.82032 980.1113,662.57625 C 977.8891,663.63465 975.4796,664.21731 972.9238,664.295 C 973.0707,664.29841 973.2143,664.32625 973.3613,664.32625 C 990.1318,664.32625 1000.5676,642.0416 996.6425,614.57625 C 992.7175,587.11092 975.913,564.82627 959.1425,564.82625 z M 927.6738,573.51375 C 927.3371,573.69114 927.0075,573.89192 926.6738,574.07625 C 926.7234,578.55327 926.3543,582.80673 925.6113,586.7325 C 919.4843,593.25496 914.1454,601.22202 909.7363,610.38875 C 909.9551,610.48576 910.173,610.57965 910.3925,610.67 C 908.1368,611.726 905.6807,612.32482 903.08,612.38875 C 903.2563,612.39364 903.4348,612.38875 903.6113,612.38875 C 918.2837,612.38875 928.0972,595.68484 927.6738,573.51375 z M 907.1113,624.38875 C 906.9645,624.38875 906.8195,624.41667 906.6738,624.42 C 909.2562,624.49606 911.8301,625.06603 914.3613,626.1075 C 902.3011,631.72743 895.5873,650.58123 898.8613,672.9825 C 902.1345,695.37929 914.3493,714.23337 928.0488,719.8575 C 925.828,720.89233 923.4162,721.46813 920.8613,721.545 C 921.008,721.54833 921.152,721.57625 921.2988,721.57625 C 938.0517,721.57625 948.4696,699.81075 944.5488,672.9825 C 940.6278,646.15426 923.8643,624.38876 907.1113,624.38875 z M 1026.2363,642.76375 C 1026.0897,642.76375 1025.9444,642.79173 1025.7988,642.795 C 1028.3705,642.87004 1030.9296,643.43172 1033.455,644.45125 C 1020.76,650.25663 1013.6554,670.40681 1017.08,694.3575 C 1020.5058,718.3161 1033.3753,738.46594 1047.7363,744.26375 C 1045.4992,745.28674 1043.1036,745.84538 1040.5488,745.92 C 1040.6953,745.92327 1040.8397,745.95125 1040.9863,745.95125 C 1058.3863,745.95125 1069.1835,722.83766 1065.1113,694.3575 C 1061.0389,665.87733 1043.6362,642.76378 1026.2363,642.76375 z M 937.2363,739.1075 C 937.0865,739.1075 936.9475,739.1352 936.7988,739.13875 C 939.3775,739.21619 941.9607,739.7971 944.4863,740.8575 C 932.4421,746.61998 925.7459,765.90143 929.0175,788.795 C 932.291,811.70197 944.5042,831.01373 958.205,836.76375 C 955.9853,837.82106 953.5716,838.40468 951.0175,838.4825 C 951.1643,838.48591 951.3082,838.51375 951.455,838.51375 C 968.208,838.51375 978.6259,816.23209 974.705,788.795 C 970.7841,761.35788 953.9893,739.1075 937.2363,739.1075 z M 1010.0488,755.295 C 1009.9022,755.295 1009.7569,755.32298 1009.6113,755.32625 C 1012.183,755.40129 1014.7421,755.96297 1017.2675,756.9825 C 1004.5739,762.78928 997.4681,782.93954 1000.8925,806.88875 C 1004.3184,830.84781 1017.2187,850.99762 1031.58,856.795 C 1029.3699,857.80582 1026.9794,858.36539 1024.455,858.45125 C 1024.5702,858.45327 1024.6835,858.4825 1024.7988,858.4825 C 1042.1988,858.4825 1053.0273,835.36894 1048.955,806.88875 C 1044.8826,778.40858 1027.4487,755.295 1010.0488,755.295 z M 977.83,841.7325 C 977.6941,841.7325 977.5588,841.76088 977.4238,841.76375 C 979.983,841.84501 982.5447,842.42434 985.0488,843.45125 C 981.1116,845.30446 977.7441,848.58583 975.1113,852.92 C 984.5554,858.6399 994.3582,862.32873 1004.2363,863.63875 C 1001.955,863.95668 999.6342,864.13326 997.2675,864.17 C 1000.3379,864.17 1003.3416,863.95003 1006.2675,863.4825 C 998.9144,850.38461 988.3818,841.73252 977.83,841.7325 z "
+ id="path3535"
+ sodipodi:nodetypes="cccsccsscccccccsccccsccssccccsccssccccsccssccccsccssccccccccc" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2954"
+ id="linearGradient3912"
+ gradientUnits="userSpaceOnUse"
+ x1="814.44556"
+ y1="742.2583"
+ x2="814.44556"
+ y2="699.93915" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3771"
+ id="linearGradient3917"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,-0.357143,0.821429,258.463,86.94653)"
+ x1="815.54865"
+ y1="721.63739"
+ x2="812.54578"
+ y2="701.04614" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2957"
+ id="linearGradient3921"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.945605,-0.217581,0.40526,0.47818,-220.401,581.0172)"
+ x1="815.54865"
+ y1="721.63739"
+ x2="810.40088"
+ y2="701.04645" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3771"
+ id="linearGradient3925"
+ gradientUnits="userSpaceOnUse"
+ x1="815.54865"
+ y1="721.63739"
+ x2="810.40088"
+ y2="701.04645" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3932">
+ <path
+ transform="matrix(0.31032,0,5.178125e-2,0.352536,530.9291,471.175)"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335"
+ sodipodi:rx="84.93766"
+ sodipodi:cy="670.89545"
+ sodipodi:cx="813.71014"
+ id="path3895"
+ style="opacity:1;color:black;fill:#fc0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:8.22614479;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ sodipodi:type="arc" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3937"
+ id="linearGradient3943"
+ x1="809.74945"
+ y1="715.75433"
+ x2="822.82684"
+ y2="711.34198"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.367696,0.367696)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3937"
+ id="linearGradient3947"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-11.76626,14.70782)"
+ x1="812.69104"
+ y1="719.43127"
+ x2="822.82684"
+ y2="711.34198" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2830"
+ gradientUnits="userSpaceOnUse"
+ x1="909.77393"
+ y1="748.375"
+ x2="909.77393"
+ y2="799.96875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3463"
+ id="linearGradient2833"
+ gradientUnits="userSpaceOnUse"
+ x1="812.26624"
+ y1="665.6875"
+ x2="820.95752"
+ y2="739.92749" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2851"
+ gradientUnits="userSpaceOnUse"
+ x1="812.26831"
+ y1="842.35431"
+ x2="814.00519"
+ y2="851.5625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2855"
+ gradientUnits="userSpaceOnUse"
+ x1="733.65625"
+ y1="696.75964"
+ x2="744.9621"
+ y2="768.34375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2858"
+ gradientUnits="userSpaceOnUse"
+ x1="847.7276"
+ y1="557.90625"
+ x2="894.53625"
+ y2="619.54285" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2861"
+ gradientUnits="userSpaceOnUse"
+ x1="752.10992"
+ y1="576.96875"
+ x2="752.10992"
+ y2="635.84375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2864"
+ gradientUnits="userSpaceOnUse"
+ x1="761.6665"
+ y1="621.93903"
+ x2="759.14404"
+ y2="753.24847" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2867"
+ gradientUnits="userSpaceOnUse"
+ x1="773.9549"
+ y1="732.1875"
+ x2="782.68182"
+ y2="850.28198" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2870"
+ gradientUnits="userSpaceOnUse"
+ x1="858.75"
+ y1="748.375"
+ x2="858.01459"
+ y2="865.15143" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2873"
+ gradientUnits="userSpaceOnUse"
+ x1="879.375"
+ y1="642.57867"
+ x2="879.375"
+ y2="744.06262" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2876"
+ gradientUnits="userSpaceOnUse"
+ x1="813.66602"
+ y1="557.90625"
+ x2="813.41272"
+ y2="657.40625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3599"
+ id="linearGradient2891"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.220779,0,0.203704,1.382716,-313.0049,-219.993)"
+ x1="819.11285"
+ y1="555.48511"
+ x2="793.83105"
+ y2="790.02881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2905"
+ gradientUnits="userSpaceOnUse"
+ x1="909.77393"
+ y1="748.375"
+ x2="909.77393"
+ y2="799.96875"
+ gradientTransform="matrix(0.490589,0,-1.152337e-2,0.695881,-273.6179,-92.35558)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3463"
+ id="linearGradient2908"
+ gradientUnits="userSpaceOnUse"
+ x1="812.26624"
+ y1="665.6875"
+ x2="820.95752"
+ y2="739.92749"
+ gradientTransform="matrix(0.490589,0,-1.152337e-2,0.695881,-273.6179,-92.35558)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2926"
+ gradientUnits="userSpaceOnUse"
+ x1="812.26831"
+ y1="842.35431"
+ x2="814.00519"
+ y2="851.5625"
+ gradientTransform="matrix(0.490589,0,-1.152337e-2,0.695881,-273.6179,-92.35558)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2929"
+ gradientUnits="userSpaceOnUse"
+ x1="733.65625"
+ y1="696.75964"
+ x2="744.9621"
+ y2="768.34375"
+ gradientTransform="matrix(0.490589,0,-1.152337e-2,0.695881,-273.6179,-92.35558)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2932"
+ gradientUnits="userSpaceOnUse"
+ x1="847.7276"
+ y1="557.90625"
+ x2="879.375"
+ y2="601.625"
+ gradientTransform="matrix(0.490589,0,-1.152337e-2,0.695881,-273.6179,-92.35558)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2935"
+ gradientUnits="userSpaceOnUse"
+ x1="752.10992"
+ y1="576.96875"
+ x2="752.10992"
+ y2="635.84375"
+ gradientTransform="matrix(0.490589,0,-1.152337e-2,0.695881,-273.6179,-92.35558)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2939"
+ gradientUnits="userSpaceOnUse"
+ x1="761.6665"
+ y1="621.93903"
+ x2="759.14404"
+ y2="714.65625"
+ gradientTransform="matrix(0.490589,0,-1.152337e-2,0.695881,-273.6179,-92.35558)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2942"
+ gradientUnits="userSpaceOnUse"
+ x1="773.9549"
+ y1="732.1875"
+ x2="782.68182"
+ y2="850.28198"
+ gradientTransform="matrix(0.490589,0,-1.152337e-2,0.695881,-273.6179,-92.35558)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2945"
+ gradientUnits="userSpaceOnUse"
+ x1="858.75"
+ y1="748.375"
+ x2="858.01459"
+ y2="865.15143"
+ gradientTransform="matrix(0.490589,0,-1.152337e-2,0.695881,-273.6179,-92.35558)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2948"
+ gradientUnits="userSpaceOnUse"
+ x1="879.375"
+ y1="642.57867"
+ x2="879.375"
+ y2="744.06262"
+ gradientTransform="matrix(0.490589,0,-1.152337e-2,0.695881,-273.6179,-92.35558)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4018"
+ id="linearGradient2951"
+ gradientUnits="userSpaceOnUse"
+ x1="813.66602"
+ y1="557.90625"
+ x2="813.41272"
+ y2="657.40625"
+ gradientTransform="matrix(0.490589,0,-1.152337e-2,0.695881,-273.6179,-92.35558)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3599"
+ id="linearGradient2966"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.598901,0,8.400139e-2,0.962206,-424.6396,-245.4445)"
+ x1="819.11285"
+ y1="555.48511"
+ x2="793.83105"
+ y2="790.02881" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3747"
+ id="radialGradient3753"
+ cx="900.87634"
+ cy="429.33759"
+ fx="900.87634"
+ fy="429.33759"
+ r="48.691078"
+ gradientTransform="matrix(1,0,0,0.848475,0,65.71196)"
+ gradientUnits="userSpaceOnUse" />
+ <filter
+ inkscape:collect="always"
+ id="filter3933">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="22.417147"
+ id="feGaussianBlur3935" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3347"
+ id="radialGradient3380"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.336911,-6.393033e-3,7.168639e-3,1.499105,-315.1945,-350.4958)"
+ cx="889.67188"
+ cy="707.07434"
+ fx="889.67188"
+ fy="707.07434"
+ r="145.07635" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3337"
+ id="linearGradient3392"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-240,0)"
+ x1="1088.0862"
+ y1="752.67523"
+ x2="1070.9225"
+ y2="516.59521" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3347"
+ id="radialGradient3395"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.855854,-4.721012e-3,-1.795074e-2,1.107032,-573.9138,-379.4444)"
+ cx="889.67188"
+ cy="707.07434"
+ fx="889.67188"
+ fy="707.07434"
+ r="145.07635" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3337"
+ id="linearGradient3408"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.640101,0,-1.503523e-2,0.738462,-531.0515,-120.6166)"
+ x1="1088.0862"
+ y1="752.67523"
+ x2="1070.9225"
+ y2="516.59521" />
+ <filter
+ inkscape:collect="always"
+ id="filter4382">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="5.8935163"
+ id="feGaussianBlur4384" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2980"
+ id="radialGradient2993"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.945085,0.545627,-0.270591,0.468689,142.3973,-159.4092)"
+ cx="628.70422"
+ cy="407.33719"
+ fx="628.48901"
+ fy="398.23914"
+ r="38.580692" />
+ <filter
+ inkscape:collect="always"
+ x="-0.23653734"
+ width="1.4730747"
+ y="-0.35096824"
+ height="1.7019365"
+ id="filter4877">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="7.6348052"
+ id="feGaussianBlur4879" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ x="-0.17345947"
+ width="1.3469189"
+ y="-0.27603572"
+ height="1.5520714"
+ id="filter4958">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.6896932"
+ id="feGaussianBlur4960" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4970"
+ id="linearGradient4976"
+ x1="627.0163"
+ y1="374.24841"
+ x2="582.94659"
+ y2="386.46796"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5002"
+ id="linearGradient5008"
+ x1="1105.0763"
+ y1="556.67267"
+ x2="1116.7949"
+ y2="540.26642"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3209"
+ id="radialGradient5012"
+ cx="1217.5303"
+ cy="1610.0789"
+ fx="1217.5303"
+ fy="1610.0789"
+ r="35.931072"
+ gradientTransform="matrix(1.618346,-0.534976,1.718181,1.15679,-3572.63,429.4414)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5016"
+ id="linearGradient5022"
+ x1="1070.3107"
+ y1="525.81335"
+ x2="1072.6544"
+ y2="544.75861"
+ gradientUnits="userSpaceOnUse" />
+ <filter
+ inkscape:collect="always"
+ x="-0.026605937"
+ width="1.0532119"
+ y="-0.11884383"
+ height="1.2376877"
+ id="filter5154">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.9936009"
+ id="feGaussianBlur5156" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ x="-0.058378786"
+ width="1.1167576"
+ y="-0.14122266"
+ height="1.2824453"
+ id="filter5194">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.3537535"
+ id="feGaussianBlur5196" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter5254">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="12.362587"
+ id="feGaussianBlur5256" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ x="-0.33162393"
+ width="1.6632479"
+ y="-0.50389611"
+ height="2.0077922"
+ id="filter5329">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="15.236484"
+ id="feGaussianBlur5331" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath5339">
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path5198"
+ id="use5337"
+ width="1"
+ height="1"
+ transform="translate(0,-540)" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ x="-0.059271395"
+ width="1.1185428"
+ y="-0.2476752"
+ height="1.4953504"
+ id="filter3952">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="6.568345"
+ id="feGaussianBlur3954" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ x="-0.067821837"
+ width="1.1356437"
+ y="-0.13965996"
+ height="1.2793199"
+ id="filter4914">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="7.9175213"
+ id="feGaussianBlur4916" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter3871">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="6.9266087"
+ id="feGaussianBlur3873" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3877"
+ id="linearGradient3875"
+ gradientUnits="userSpaceOnUse"
+ x1="1843.3077"
+ y1="1139.8347"
+ x2="1798.4442"
+ y2="1145.3904" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3877"
+ id="linearGradient2949"
+ gradientUnits="userSpaceOnUse"
+ x1="1332.6165"
+ y1="1341.6736"
+ x2="1329.6609"
+ y2="1290.606" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3838"
+ id="linearGradient3844"
+ x1="1306.5068"
+ y1="1474.1163"
+ x2="1334.7703"
+ y2="1533.567"
+ gradientUnits="userSpaceOnUse" />
+ <filter
+ inkscape:collect="always"
+ x="-0.284216"
+ width="1.568432"
+ y="-0.23374538"
+ height="1.4674908"
+ id="filter3912">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="12.342325"
+ id="feGaussianBlur3914" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3918">
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path3144"
+ id="use3916"
+ width="1"
+ height="1" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter4167">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.164557"
+ id="feGaussianBlur4169" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2957"
+ id="linearGradient4211"
+ gradientUnits="userSpaceOnUse"
+ x1="1059.4688"
+ y1="542.11444"
+ x2="1044.2227"
+ y2="593.19513" />
+ <filter
+ inkscape:collect="always"
+ id="filter4217">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="10.108017"
+ id="feGaussianBlur4219" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ x="-0.21888952"
+ width="1.437779"
+ y="-0.19940901"
+ height="1.398818"
+ id="filter4259">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="12.615137"
+ id="feGaussianBlur4261" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4263"
+ id="linearGradient4269"
+ x1="1182.5635"
+ y1="429.21915"
+ x2="1247.7144"
+ y2="430.47183"
+ gradientUnits="userSpaceOnUse" />
+ <filter
+ inkscape:collect="always"
+ x="-0.050900629"
+ width="1.1018013"
+ y="-0.10984331"
+ height="1.2196866"
+ id="filter4601">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="9.025964"
+ id="feGaussianBlur4603" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3059"
+ id="linearGradient4607"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,4.496947,0,-822.1609)"
+ x1="839.81659"
+ y1="215.09087"
+ x2="836.30078"
+ y2="153.0452" />
+ <filter
+ inkscape:collect="always"
+ id="filter4653">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="8.6485882"
+ id="feGaussianBlur4655" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ x="-0.10894429"
+ width="1.2178886"
+ y="-0.17668761"
+ height="1.3533752"
+ id="filter4826">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.9101588"
+ id="feGaussianBlur4828" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ x="-0.1440634"
+ width="1.2881268"
+ y="-0.21936503"
+ height="1.4387301"
+ id="filter5032">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.7103122"
+ id="feGaussianBlur5034" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ x="-0.30684853"
+ width="1.6136971"
+ y="-0.20180214"
+ height="1.4036043"
+ id="filter5106">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="5.8270206"
+ id="feGaussianBlur5108" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ x="-0.094454055"
+ width="1.1889081"
+ y="-0.14074299"
+ height="1.281486"
+ id="filter5200">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="5.3388835"
+ id="feGaussianBlur5202" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ x="-0.12801512"
+ width="1.2560302"
+ y="-0.3464887"
+ height="1.6929774"
+ id="filter5304">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="3.7809852"
+ id="feGaussianBlur5306" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ x="-0.035006558"
+ width="1.0700131"
+ y="-0.14665898"
+ height="1.293318"
+ id="filter6393">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="6.4832538"
+ id="feGaussianBlur6395" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6405"
+ id="linearGradient6403"
+ x1="931.52002"
+ y1="872.21838"
+ x2="1079.7725"
+ y2="885.69226"
+ gradientUnits="userSpaceOnUse" />
+ <filter
+ inkscape:collect="always"
+ id="filter3915">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="3.0141434"
+ id="feGaussianBlur3917" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3332"
+ id="radialGradient3919"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.200899,0.579174,-0.2156105,0.4470627,8.8637985,-8.9711893)"
+ cx="347.41388"
+ cy="303.43369"
+ fx="347.41388"
+ fy="303.43369"
+ r="154.43303" />
+ <filter
+ inkscape:collect="always"
+ x="-0.097929535"
+ width="1.1958591"
+ y="-0.11166643"
+ height="1.2233329"
+ id="filter3927">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.8517745"
+ id="feGaussianBlur3929" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3946">
+ <path
+ style="opacity:1;color:#000000;fill:url(#linearGradient3949);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3944"
+ sodipodi:nodetypes="csscsccsc"
+ d="M 544.28571,615.14286 C 502.85714,590.85714 445.71429,549.42857 421.42857,533.71429 C 397.14286,518 368.57143,493.71429 354.28571,479.42857 C 340,465.14286 317.14286,445.14286 312.85714,435.14286 C 290,446.57143 297.14286,456.57143 295.71429,462.28571 C 294.28571,468 291.42857,472.28571 291.42857,472.28571 L 218.57143,436.57143 C 218.57143,436.57143 348.57143,509.42857 364.28571,518 C 380,526.57143 548.57143,619.42857 544.28571,615.14286 z " />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3931"
+ id="linearGradient3949"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,50)"
+ x1="321.67255"
+ y1="442.76962"
+ x2="325.79459"
+ y2="409.21478" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath3953">
+ <path
+ style="opacity:1;color:#000000;fill:url(#linearGradient3956);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3951"
+ sodipodi:nodetypes="csscsccsc"
+ d="M 544.28571,615.14286 C 502.85714,590.85714 445.71429,549.42857 421.42857,533.71429 C 397.14286,518 368.57143,493.71429 354.28571,479.42857 C 340,465.14286 317.14286,445.14286 312.85714,435.14286 C 290,446.57143 297.14286,456.57143 295.71429,462.28571 C 294.28571,468 291.42857,472.28571 291.42857,472.28571 L 218.57143,436.57143 C 218.57143,436.57143 348.57143,509.42857 364.28571,518 C 380,526.57143 548.57143,619.42857 544.28571,615.14286 z " />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3931"
+ id="linearGradient3956"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,50)"
+ x1="321.67255"
+ y1="442.76962"
+ x2="325.79459"
+ y2="409.21478" />
+ <filter
+ inkscape:collect="always"
+ id="filter3982">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.2477499"
+ id="feGaussianBlur3984" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter4008">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.5339087"
+ id="feGaussianBlur4010" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3156"
+ id="linearGradient4012"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(18.081772,0)"
+ x1="198.10001"
+ y1="362.28571"
+ x2="276.1857"
+ y2="362.28571" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3156"
+ id="linearGradient4016"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(84,0)"
+ x1="198.10001"
+ y1="362.28571"
+ x2="276.1857"
+ y2="362.28571" />
+ <filter
+ inkscape:collect="always"
+ id="filter4022">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.0729348"
+ id="feGaussianBlur4024" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter4070">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.2671386"
+ id="feGaussianBlur4072" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ x="-0.04195043"
+ width="1.0839009"
+ y="-0.14643413"
+ height="1.2928683"
+ id="filter4097">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.7365391"
+ id="feGaussianBlur4099" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3230"
+ id="linearGradient4101"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(2.14286,-1045.1974)"
+ x1="260"
+ y1="1203"
+ x2="185"
+ y2="1170.1428" />
+ <filter
+ inkscape:collect="always"
+ x="-0.038803903"
+ width="1.0776078"
+ y="-0.1411126"
+ height="1.2822252"
+ id="filter4119">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.419179"
+ id="feGaussianBlur4121" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter4139">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="5.6950996"
+ id="feGaussianBlur4141" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter4161">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="4.9493976"
+ id="feGaussianBlur4163" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.48036041"
+ inkscape:cx="851.92362"
+ inkscape:cy="521.2444"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer3"
+ width="1901px"
+ height="1018px"
+ inkscape:window-width="900"
+ inkscape:window-height="687"
+ inkscape:window-x="10"
+ inkscape:window-y="20"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ showborder="false" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Lamborghini Gallardo</dc:title>
+ <dc:date>10.25.2006</dc:date>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Michael Grosberg</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:description>A traced Lamborghini Gallardo.
+The source image can be found at:
+http://en.wikipedia.org/wiki/Image:Lamborghini_Gallardo_silver.jpg</dc:description>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/by-nc-sa/2.5/" />
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/by-nc-sa/2.5/">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Notice" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Attribution" />
+ <cc:prohibits
+ rdf:resource="http://web.resource.org/cc/CommercialUse" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/ShareAlike" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="shadow"
+ style="opacity:1;display:inline"
+ id="layer6"
+ inkscape:groupmode="layer">
+ <path
+ style="opacity:0.75652179;fill:url(#linearGradient6403);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6393)"
+ d="M 833.92042,891.98536 C 852.45199,895.69167 862.33549,901.86886 873.45443,900.63342 C 884.57337,899.39798 1151.4279,910.51692 1144.0153,901.86886 C 1136.6027,893.2208 1103.2458,841.33241 1081.008,843.80329 C 1058.7701,846.27416 996.9982,826.50716 971.054,826.50716 C 945.10981,826.50716 869.74812,812.91735 847.51024,817.8591 C 825.27236,822.80085 765.97135,831.44891 774.61942,841.33241 C 783.26748,851.21592 799.32817,887.04361 833.92042,891.98536 z "
+ id="path5398" />
+ <path
+ style="opacity:0.75;color:black;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.4000001;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter3933)"
+ d="M 1723.6555,787.9542 C 1760.3047,803.4157 1777.1834,823.7398 1754.1015,846.0505 C 1749.1968,851.3011 1737.9063,858.5431 1721.797,866.8706 C 1637.8809,910.3155 1423.8477,988.2316 1316.0696,988.3291 C 1303.4824,988.3491 1284.8718,986.4359 1262.8773,983.2064 C 1180.5796,970.8403 1042.9036,938.2083 1001.7948,921.9216 C 975.7298,911.4804 942.7654,911.8916 910.653,911.7278 C 875.7047,911.2128 838.4307,909.9972 808.9547,893.2168 C 791.2046,882.9509 779.904,873.7065 772.6421,865.0477 C 752.7058,840.9555 763.5005,822.0002 748.5703,799.5818 C 742.099,790.8866 714.0216,771.8511 672.6307,748.8436 C 560.35406,686.2063 339.78489,576.1304 279.061,551.8925 C 271.83005,549.0114 266.67254,547.2996 264.04046,546.9561 C 234.24042,543.1389 148.46794,567.8161 130.10669,542.5468 C 130.07796,542.5073 130.04939,542.4676 130.02098,542.4279 C 111.74379,516.8365 152.20544,475.4745 188.8197,471.533 C 188.97119,471.5167 189.1229,471.5009 189.27482,471.4856 C 226.04741,467.7881 642.21633,370.1412 716.9405,387.9473 C 719.5366,388.561 723.0239,389.5757 727.3347,390.965 C 848.5229,430.0548 1700.6312,778.9385 1723.6555,787.9542 C 1723.6555,787.9542 1723.6555,787.9542 1723.6555,787.9542"
+ id="path7090" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path5398"
+ id="use6413"
+ transform="matrix(0.9136,0,0,0.9136,-620.2102,-276.0885)"
+ width="1901"
+ height="1018" />
+ </g>
+ <g
+ inkscape:label="paint"
+ style="opacity:1;display:inline"
+ id="layer3"
+ inkscape:groupmode="layer">
+ <path
+ style="opacity:1;color:black;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ d="M 1033.7599,832.88001 C 946.39995,785.04001 809.11996,712.24001 782.07996,718.48001 C 755.03996,724.72001 700.95997,747.60001 700.95997,747.60001 L 659.35997,691.44002 L 671.83997,473.04003 L 794.55996,435.60003 L 960.95995,518.80002 L 1033.7599,832.88001 z "
+ id="path3635" />
+ <path
+ d="M 988,874.48001 C 931.84,892.16001 885.04,899.44001 865.28,899.44001 C 845.52,899.44001 786.24,884.88001 757.11996,840.16001 C 727.99996,795.44001 701.99997,724.72001 703.03997,669.60002 C 704.07997,614.48002 706.15997,502.16002 819.52,508.40002 C 932.88,514.64002 979.68,647.76002 989.04,684.16002 C 998.4,720.56001 989.04,874.48001 988,874.48001 z "
+ id="path3331"
+ style="opacity:1;color:black;fill:url(#linearGradient3392);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible" />
+ <path
+ id="path3540"
+ d="M 988,874.48001 C 931.84,892.16001 885.04,899.44001 865.28,899.44001 C 845.52,899.44001 786.24,884.88001 757.11996,840.16001 C 727.99996,795.44001 701.99997,724.72001 703.03997,669.60002 C 704.07997,614.48002 706.15997,502.16002 819.52,508.40002 C 932.88,514.64002 979.68,647.76002 989.04,684.16002 C 998.4,720.56001 989.04,874.48001 988,874.48001 z "
+ style="opacity:0.29444442;color:black;fill:url(#radialGradient3380);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible" />
+ <path
+ style="opacity:1;color:black;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ d="M 76.959996,366.96003 C 69.679996,358.64003 58.239997,336.80004 58.239997,294.16004 C 58.239997,271.28004 72.799996,225.52004 72.799996,225.52004 L 147.67999,227.60004 L 241.27999,402.32003 L 265.19999,467.84003 C 265.19999,467.84003 190.55853,384.49949 130.31349,390.57618 C 101.54215,393.47824 76.959996,366.96003 76.959996,366.96003 z "
+ sodipodi:nodetypes="csccccsc"
+ id="path3637" />
+ <path
+ id="path4128"
+ sodipodi:nodetypes="csssssc"
+ d="M 241.84448,525.15366 C 205.63058,538.20967 175.5644,543.58567 162.91601,543.58567 C 150.26761,543.58567 112.54134,532.83366 94.573945,499.80964 C 76.606579,466.78562 61.027251,414.56159 62.521698,373.85757 C 64.016144,333.15354 67.036312,250.20949 139.50436,254.8175 C 211.97239,259.4255 263.84761,445.08956 269.29167,471.96957 C 274.73573,498.84958 242.51018,525.15366 241.84448,525.15366 z "
+ style="opacity:1;color:black;fill:url(#linearGradient3408);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible" />
+ <path
+ d="M 232.48448,518.91366 C 196.27059,531.96967 175.5644,543.58567 162.91601,543.58567 C 150.26761,543.58567 112.54134,532.83366 94.573945,499.80964 C 76.606579,466.78562 61.027251,414.56159 62.521698,373.85757 C 64.016144,333.15354 67.036312,250.20949 139.50436,254.8175 C 211.97239,259.4255 256.5676,459.64955 262.01166,486.52957 C 267.45572,513.40958 233.15019,518.91366 232.48448,518.91366 z "
+ sodipodi:nodetypes="csssssc"
+ id="path4144"
+ style="opacity:0.29444442;color:black;fill:url(#radialGradient3395);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible" />
+ <path
+ style="color:black;fill:#5b6879;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1482.9039,285.6394 C 1482.9039,285.6394 1562.706,300.79169 1609.173,327.05566 C 1655.64,353.31962 1764.4406,443.34576 1833.131,534.25949 C 1833.131,534.25949 1846.4286,550.14286 1859.2857,581.57143 M 1482.9039,285.63941 C 1482.9039,285.63941 1371.7872,215.93888 1326.3303,189.67491 C 1280.8734,163.41095 1185.9191,114.92362 1140.4622,98.761184 C 1095.0054,82.598743 1018.2338,67.446455 978.83782,62.395693 C 939.44187,57.34493 769.73624,50.273862 717.20831,53.30432 C 664.68037,56.334777 553.56359,65.426151 485.88337,77.547981 C 435.37575,81.588591 323.24881,88.659659 284.86302,92.700269 C 246.47722,96.740879 200.89409,102.80179 200.95723,102.80179 C 171.72593,104.8221 109.09647,121.99469 76.588293,132.59549 L 65.714286,197.28571 L 62.142857,202.28571 C 62.142857,202.28571 58.571429,245.14286 57.142857,252.28571 C 55.714286,259.42857 52.857143,292.28571 60,325.85714 C 56.428571,268.71429 67.142857,253 72.857143,244.42857 C 78.571429,235.85714 91.428571,229.42857 103.57143,233 C 115.71429,236.57143 164.28571,282.28571 185,363.71429 C 205.71429,445.14286 204.28571,457.28571 204.28571,457.28571 L 201.42857,461.57143 L 207.85714,503 C 207.85714,503 309.28571,541.57143 391.42857,585.85714 C 473.57143,630.14286 704.28571,747.28571 704.28571,747.28571 L 692.14286,713.71429 L 696.42857,708 L 690.71429,704.42857 C 690.71429,704.42857 680,662.31034 680.71429,616.57143 C 681.62886,558.00714 711.42857,477.28571 786.42857,488 C 854.22975,497.68587 902.85714,573.71429 910,586.57143 C 908.57143,589.42857 909.28571,589.42857 909.28571,589.42857 C 909.28571,589.42857 962.14286,681.57143 969.28571,751.57143 C 976.42857,821.57143 975,853 975,853 C 975,853 1143.5714,905.14286 1211.4286,915.14286 C 1299.2857,771.57143 1304.2857,768.71429 1304.1963,769.61346 C 1400.0714,766.47202 1597.0512,729.09637 1692.0055,698.7918 C 1786.9599,668.48722 1839.4878,611.91868 1858.6807,580.60395"
+ sodipodi:nodetypes="cscccsssscsccccscssscccsccccssccscccsc"
+ id="path2801" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2854);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 664.28571,423.35714 C 630,406.21428 361.42857,252.28571 325.71429,233.71429 C 290,215.14286 172.85714,145.14286 142.85714,135.14286 C 112.85714,125.14286 96.132704,131.69398 76.588293,132.59549 L 65.714286,197.28571 L 62.142857,202.28571 C 62.142857,202.28571 58.571429,245.14286 57.142857,252.28571 C 55.714286,259.42857 52.857143,292.28571 60,325.85714 C 56.428571,268.71429 67.142857,253 72.857143,244.42857 C 78.571429,235.85714 91.428571,229.42857 103.57143,233 C 115.71429,236.57143 164.28571,282.28571 185,363.71429 C 205.71429,445.14286 204.28571,457.28571 204.28571,457.28571 L 201.42857,461.57143 L 207.85714,503 C 207.85714,503 309.28571,541.57143 391.42857,585.85714 C 473.57143,630.14286 704.28571,747.28571 704.28571,747.28571 L 692.14286,713.71429 L 696.42857,708 L 690.71429,704.42857 C 690.71429,704.42857 680,662.31034 680.71429,616.57143 C 681.62886,558.00714 711.42857,477.28571 786.42857,488 C 854.22975,497.68587 902.85714,573.71429 910,586.57143 C 908.57143,589.42857 909.28571,589.42857 909.28571,589.42857 C 909.28571,589.42857 962.14286,681.57143 969.28571,751.57143 C 976.42857,821.57143 975,853 975,853 C 975,853 1143.5714,905.14286 1211.4286,915.14286 C 1299.2857,771.57143 1304.2857,768.71429 1304.2857,768.71429 L 1252.1429,715.14286 C 1252.1429,715.14286 1067.8571,548 987.85714,498.71429 C 907.85714,449.42857 849.33268,417.77137 818.57143,411.57143 C 757.12842,399.18757 696.88216,394.82973 672.36316,398.77249 C 669.37512,408.00389 664.28571,423.35714 664.28571,423.35714 z "
+ sodipodi:nodetypes="csscccscssscccsccccssccsccccsscc"
+ id="path2973" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3258);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3248"
+ sodipodi:nodetypes="csscccscssscccscc"
+ d="M 665.14286,421.5 C 630.85715,404.35714 362.28571,250.42857 326.57143,231.85715 C 290.85714,213.28572 173.71429,143.28572 143.71429,133.28572 C 113.71429,123.28572 98.505075,132.36222 78.960665,133.26373 L 66.571426,195.42857 L 62.999996,200.42857 C 62.999996,200.42857 59.428576,243.28572 57.999996,250.42857 C 56.571426,257.57143 53.714286,290.42857 60.857146,324 C 57.285716,266.85715 67.999996,251.14286 73.714286,242.57143 C 79.428576,234 92.285716,227.57143 104.42858,231.14286 C 116.57144,234.71429 165.14286,280.42857 185.85715,361.85715 C 206.57144,443.28572 205.14286,455.42857 205.14286,455.42857 L 202.28572,459.71429 L 208.71429,501.14289 C 208.71429,501.14289 310.14285,539.71429 392.28571,583.99999 C 474.42858,628.28569 705.14286,745.42859 705.14286,745.42859 C 627.05373,594.84069 665.0035,569.41479 665.14286,421.5 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2985);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.35526315;visibility:visible;display:inline;overflow:visible"
+ id="path2976"
+ sodipodi:nodetypes="ccccccccc"
+ d="M 75.23606,243.22315 L 60.164992,238.5404 L 63.170068,201.47441 L 65.123833,198.26601 L 65.979144,197.98959 L 78.999998,132.50002 L 115.71343,132.18931 L 97.999997,215.50002 L 75.23606,243.22315 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2999);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path2965"
+ sodipodi:nodetypes="cssssccsssssssssscsscccssssc"
+ d="M 117.95028,131.82387 C 118.96044,143.94577 118.96979,142.91927 113.91903,148.98017 C 108.86827,155.04107 105.82528,155.05507 105.82528,163.13637 C 105.82528,171.21757 104.8237,181.31457 98.762783,185.35517 C 92.701872,189.39567 92.700282,189.37697 92.700282,193.41767 C 92.700282,197.45827 82.111603,202.51219 80.596379,216.14927 C 102.15149,218.96692 120.15358,226.87465 132.10653,243.94887 C 143.21819,239.90827 139.15808,237.88487 137.13778,231.82387 C 135.11747,225.76297 137.14873,225.74957 139.16903,220.69887 C 141.18933,215.64807 139.15808,217.66597 137.13778,211.60517 C 135.11747,205.54427 151.28467,215.66527 155.32528,206.57387 C 159.3659,197.48257 150.2761,195.44817 161.38778,192.41767 C 172.49946,189.38707 174.51515,186.36767 183.60653,194.44887 C 192.6979,202.53007 206.83939,209.59657 220.98153,216.66767 C 235.12367,223.73867 258.35969,231.82457 270.48153,234.85517 C 282.60336,237.88567 294.72297,233.84567 301.79403,237.88637 C 308.86509,241.92697 303.82845,244.94967 315.95028,247.98017 C 324.91012,250.22007 369.39404,263.24968 435.24677,296.16641 C 404.4122,278.76461 329.19878,237.08445 315.6868,228.67135 C 262.14871,195.33635 190.67601,157.07237 177.54403,151.01137 C 164.41206,144.95047 130.07211,131.82387 117.95028,131.82387 z M 153.54403,177.16767 C 155.24491,177.05947 156.5896,177.32287 157.35653,178.26137 C 149.7542,185.86367 152.56806,190.38397 150.29403,199.48017 C 148.22327,207.76317 141.64769,206.14957 138.16903,201.51137 C 136.45178,199.22167 124.01278,195.89187 124.01278,194.44887 C 124.01278,187.42117 125.91394,181.29257 134.10653,181.29267 C 140.06869,181.29267 148.44138,177.49197 153.54403,177.16767 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3152);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 685.71429,527.57141 C 695.71429,497.57141 730.9746,446.39679 807.03486,462.89842 C 802.74915,424.32702 747.14286,401.85711 747.14286,401.85711 L 675.71429,397.57141 C 675.71429,397.57141 664.28571,410.42861 664.28571,426.14281 C 664.28571,441.85711 662.85714,509.00001 662.85714,509.00001 L 685.71429,527.57141 z "
+ id="path3144"
+ sodipodi:nodetypes="ccccscc" />
+ <path
+ style="opacity:0.56956522;color:black;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;filter:url(#filter3912)"
+ id="path3850"
+ d="M 721.67688,456.86456 C 729.30457,453.42935 737.72355,453.00826 745.85283,451.55583 C 748.01123,452.31667 765.21374,447.8819 756.84996,448.67261 C 756.38575,458.55317 751.28724,445.55918 748.77771,441.88811 C 745.65845,435.95671 742.29659,430.31658 738.09673,425.11953 C 734.77045,421.97746 730.50938,420.36682 726.42252,418.49738 C 714.57034,413.07586 720.69767,396.05939 732.68987,401.16374 L 732.68987,401.16374 C 738.75684,403.74608 744.72407,406.56833 749.74464,410.94576 C 754.9415,416.39336 759.11042,422.53887 762.23822,429.40789 C 768.44893,439.08502 775.13182,445.24087 772.54164,458.10853 C 765.79028,467.62205 759.32448,468.59758 748.32866,469.57403 C 742.02784,470.81009 703.27245,512.99529 697.2797,515.37227 C 692.16919,519.10918 714.84173,460.77048 721.67688,456.86456 z "
+ sodipodi:nodetypes="cccccscccccccc"
+ clip-path="url(#clipPath3918)" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2963);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path2857"
+ sodipodi:nodetypes="cccssccccssc"
+ d="M 696.90625,397.375 C 716.31072,399.15039 730.7816,403.02757 724.08756,414.24651 C 747.87178,417.64391 763.29567,436.9156 769.42747,458.40244 C 784.47414,462.16706 851.21242,454.70446 912.71875,547.46875 C 933.43519,578.71344 951.13573,647.06961 967.29118,659.67127 C 983.40346,672.23925 994.08962,609.51337 1009.375,623.0625 C 1036.9696,640.7111 1085.7096,694.90941 1117,705.0625 C 1169.4389,716.82057 1227.3539,726.23713 1280.2188,744 L 1252.1563,715.15625 C 1252.1562,715.15623 1067.8437,548.00446 987.84375,498.71875 C 907.84377,449.43303 849.32375,417.76244 818.5625,411.5625 C 772.48026,402.2746 727.07461,397.51778 696.90625,397.375 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#radialGradient3011);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.99999976;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 487.2123,108.89615 C 439.26568,111.09441 391.38329,115.92628 344.28114,124.95681 C 336.96091,127.43505 330.58931,131.91334 324.56325,136.56314 C 364.74696,171.77294 403.98097,208.3632 451.13456,233.88525 C 521.94112,275.56005 594.70245,314.22138 669.45346,348.45715 C 706.54686,364.87734 747.03861,370.7207 787.14746,374.61313 C 793.3854,375.23462 799.63181,375.77396 805.87489,376.34372 C 770.04529,320.75944 736.35336,263.76108 696.2648,211.20112 C 671.43459,181.40361 644.97507,152.66792 612.06086,131.70103 C 584.15074,117.98769 552.47933,115.39278 522.06312,110.85314 C 510.49462,109.57466 498.85779,108.74629 487.2123,108.89615 z "
+ id="path3001" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3192);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3184"
+ sodipodi:nodetypes="cssscc"
+ d="M 402.85715,215.14287 C 388.57143,205.14287 344.99997,175.14291 337.85715,172.28573 C 330.71429,169.42853 282.10983,172.87456 268.92244,184.68104 C 261.47206,191.35126 309.60572,206.31147 318.57143,216.57147 C 325.73041,224.76393 325.71429,235.14287 325.71429,235.14287 C 325.71429,235.14287 368.57143,217.99997 402.85715,215.14287 z " />
+ <path
+ style="opacity:1;color:black;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 494.9375,104.78125 C 461.60246,104.78125 358.55933,116.91799 346.4375,121.96875 C 334.31567,127.01952 319.15625,140.15625 319.15625,140.15625 C 319.15624,140.15626 379.77902,194.70399 411.09375,217.9375 C 442.40846,241.171 618.66281,335.20635 689.90625,362.12054 C 735.36314,379.29314 814.41316,380.79911 812.39286,380.79911 C 812.39285,380.79912 737.54278,259.00793 713.29911,226.68304 C 689.05546,194.35816 641.39912,136.11168 614.125,125 C 586.85088,113.88832 528.27253,104.78125 494.9375,104.78125 z M 497.0625,111.90625 C 506.75642,112.04153 516.42756,112.77895 526.0625,113.84375 C 556.47871,118.38339 588.15239,120.97416 616.0625,134.6875 C 648.97671,155.65439 675.41982,184.38998 700.25,214.1875 C 703.63285,218.62274 706.95293,223.09864 710.25,227.59375 C 709.11316,230.30784 682.77602,293.60911 675.96875,352.53125 C 675.13851,352.17562 674.29566,351.8348 673.46875,351.46875 C 598.71774,317.23298 525.93157,278.5498 455.125,236.875 C 444.49805,231.12313 434.26704,224.79545 424.34375,218.0625 C 444.27323,174.03577 483.54579,130.27867 497.0625,111.90625 z M 484.65625,112.21875 C 474.51946,123.1227 437.29401,164.90878 416,212.25 C 385.21587,190.30191 357.12398,164.58866 328.5625,139.5625 C 334.58856,134.9127 340.96103,130.44699 348.28125,127.96875 C 393.23692,119.34975 438.90106,114.54918 484.65625,112.21875 z M 716.0625,235.59375 C 749.41739,282.03967 778.8563,331.22286 809.875,379.34375 C 803.63192,378.77399 797.39419,378.24649 791.15625,377.625 C 754.84036,374.10066 718.2297,368.96977 684.09375,355.84375 C 690.00797,305.83151 710.97052,256.43507 716.0625,235.59375 z "
+ sodipodi:nodetypes="cscsssssccccccccccccccccccccc"
+ id="path3270" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3086);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 490.9375,101.78125 C 457.60246,101.78125 354.55933,113.91799 342.4375,118.96875 C 330.31567,124.01952 315.15625,137.15625 315.15625,137.15625 C 315.15624,137.15626 375.77902,191.70399 407.09375,214.9375 C 438.40846,238.171 614.66281,336.49206 685.90625,363.40625 C 731.36314,380.57885 823.2703,385.65625 821.25,385.65625 C 821.24999,385.65626 736.39992,250.29364 712.15625,217.96875 C 687.9126,185.64387 637.39912,133.11168 610.125,122 C 582.85088,110.88832 524.27253,101.78125 490.9375,101.78125 z M 493.0625,108.90625 C 502.75642,109.04153 512.42756,109.77895 522.0625,110.84375 C 552.47871,115.38339 584.15239,117.97416 612.0625,131.6875 C 644.97671,152.65439 671.41982,181.38998 696.25,211.1875 C 699.63285,215.62274 702.95293,220.09864 706.25,224.59375 C 705.11316,227.30784 678.77602,290.60911 671.96875,349.53125 C 671.13851,349.17562 670.29566,348.8348 669.46875,348.46875 C 594.71774,314.23298 521.93157,275.5498 451.125,233.875 C 440.49805,228.12313 430.26704,221.79545 420.34375,215.0625 C 440.27323,171.03577 479.54579,127.27867 493.0625,108.90625 z M 480.65625,109.21875 C 470.51946,120.1227 433.29401,161.90878 412,209.25 C 381.21587,187.30191 353.12398,161.58866 324.5625,136.5625 C 330.58856,131.9127 336.96103,127.44699 344.28125,124.96875 C 389.23692,116.34975 434.90106,111.54918 480.65625,109.21875 z M 712.0625,232.59375 C 745.41739,279.03967 774.8563,328.22286 805.875,376.34375 C 799.63192,375.77399 793.39419,375.24649 787.15625,374.625 C 750.84036,371.10066 714.2297,365.96977 680.09375,352.84375 C 686.00797,302.83151 706.97052,253.43507 712.0625,232.59375 z "
+ id="path3053" />
+ <g
+ id="g3134"
+ transform="translate(-10,-1074.286)">
+ <path
+ style="opacity:1;color:black;fill:#76452b;fill-opacity:0.77631579;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 952.57385,1666.5179 L 964.69568,1694.8022 C 964.69568,1694.8022 994.58841,1704.537 1003.0815,1707.9342 C 1018.2338,1713.9952 1043.4876,1703.8936 1043.4876,1703.8936 L 952.57385,1666.5179 z "
+ sodipodi:nodetypes="ccscc"
+ id="path3090" />
+ <path
+ style="opacity:1;color:black;fill:#d17827;fill-opacity:0.77631579;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3092"
+ d="M 956.0625,1670.2188 C 960.19233,1677.1049 962.13721,1684.9727 965.75,1692.0625 C 969.11452,1696.2138 975.70112,1694.9161 980.12825,1697.6204 C 995.4794,1703.1908 1011.5555,1711.0394 1028.1563,1706.375 C 1030.7134,1705.6178 1037.675,1704.642 1037.1563,1703.2188 C 1020.6011,1697.4663 1004.6387,1689.635 988.1997,1683.3083 C 977.52337,1678.9651 966.59327,1674.3794 956.0625,1670.2188 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3140);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3100"
+ d="M 963.34375,1676 C 961.22401,1679.6177 964.66365,1684.3186 965.96875,1688.0938 C 969.26394,1695.2571 978.36466,1693.5937 984.24841,1696.9772 C 997.14095,1701.693 1010.9742,1708.0754 1024.9688,1704.9375 C 1028.8342,1701.44 1022.0874,1699.0432 1019.375,1698.4063 C 1000.9085,1691.0721 982.67631,1682.46 964.00071,1675.9752 L 963.34375,1676 z " />
+ <path
+ sodipodi:cy="1692.2769"
+ sodipodi:type="arc"
+ sodipodi:cx="992.47485"
+ style="opacity:1;color:black;fill:url(#linearGradient3142);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3124"
+ sodipodi:rx="7.5761442"
+ d="M 1000.051 1692.2769 A 7.5761442 4.5456862 0 1 1 984.89871,1692.2769 A 7.5761442 4.5456862 0 1 1 1000.051 1692.2769 z"
+ sodipodi:ry="4.5456862" />
+ </g>
+ <path
+ style="opacity:1;color:black;fill:url(#radialGradient3162);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3154"
+ sodipodi:nodetypes="csssscscsscc"
+ d="M 325.50371,235.26855 C 325.50371,235.26855 499.60709,332.18715 515.76953,342.28875 C 531.93197,352.39025 655.17058,421.08065 663.2518,421.08065 C 671.33302,421.08065 680.71429,428.71425 683.57143,424.42855 C 686.42857,420.14285 677.14286,413.00005 683.57143,413.00005 C 690,413.00005 700,410.14285 708.57143,410.85715 C 682.85714,405.14285 690,405.14285 682.85714,405.85715 C 675.71429,406.57145 673.06747,416.91511 666.63889,411.91511 C 660.21032,406.91511 665,403.00005 657.85714,396.57145 C 650.71429,390.14285 591.42857,320.85715 577.14286,313.71425 C 562.85714,306.57145 443.18263,243.8982 407.46834,213.8981 C 358.89691,221.041 326.78572,233.17855 325.50371,235.26855 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3196);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 341.42857,228.00005 C 231.07143,162.82145 182.02366,134.71267 167.98858,135.98859 C 162.26858,136.50859 154.87714,136.63436 147.85714,138.71436 C 165.20537,146.18896 230.32484,179.03195 326.03913,235.46055 C 326.03913,235.46055 324.64286,231.03575 341.42857,228.00005 z "
+ sodipodi:nodetypes="ccccc"
+ id="path3194" />
+ <path
+ style="opacity:1;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4070)"
+ d="M 314.15745,145.20789 C 300.01531,148.23839 284.86302,150.25869 273.75134,155.30939 C 262.63967,160.36019 241.42646,171.47189 241.42646,171.47189 L 276.81165,189.88479 L 326.27928,170.46169 L 314.15745,145.20789 z "
+ sodipodi:nodetypes="cscccc"
+ id="path3222" />
+ <path
+ style="opacity:0.94782609;color:black;fill:url(#linearGradient3206);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4119)"
+ id="path3198"
+ sodipodi:nodetypes="ccsccsc"
+ d="M 281.14286,192.5715 C 307.33928,189.99763 351.04624,198.41235 378.28572,198.2858 C 360.46198,188.17501 341.57637,182.42027 334.43352,178.13457 C 327.29066,173.84887 328.28572,172.5715 328.28572,172.5715 L 305.42858,164 C 305.42858,164 248.28572,172.5715 254,176.8572 C 259.71429,181.1429 282.57143,194 281.14286,192.5715 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3220);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 316.38881,143.34171 L 380.43346,199.677 C 380.43346,199.677 323.85715,174.57144 308.14286,174.57144 C 292.42858,174.57144 316.38881,143.34171 316.38881,143.34171 z "
+ sodipodi:nodetypes="ccsc"
+ id="path3212" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3246);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 316.86447,143.55277 C 306.86447,143.55277 287.71429,148.94155 280.57143,148.94155 C 275.22263,148.94155 209.34077,132.57172 173.91411,135.06808 C 162.30428,135.88617 165.37429,135.73719 165.37429,135.73719 L 146.03715,128.33719 C 146.03715,128.33719 199.14286,113.14289 207.71429,113.14289 C 216.28572,113.14289 222.04221,104.16151 240.61364,107.01871 C 259.18507,109.87581 304.00733,130.69567 316.86447,143.55277 z "
+ sodipodi:nodetypes="cssccssc"
+ id="path3238" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3236);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 294.07695,145.84997 C 265.79267,136.75857 244.57947,134.73827 231.44749,136.75857 C 218.3155,138.77887 208.21398,133.72807 198.11245,133.72807 C 188.01093,133.72807 163.76727,135.74837 163.76727,135.74837 C 163.76727,135.74837 179.92971,140.79917 195.082,147.87027 C 210.23428,154.94127 239.52871,171.10377 239.52871,171.10377 C 239.52871,171.10377 263.77237,156.96157 270.84344,153.93117 C 277.9145,150.90067 296.09725,144.83977 294.07695,145.84997 z "
+ id="path3224" />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#6b89a2;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3228"
+ sodipodi:nodetypes="cc"
+ d="M 315.84571,144.68857 C 286.75428,147.93427 263.44,157.15717 242.01143,172.15717" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3268);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3260"
+ sodipodi:nodetypes="cccccccccc"
+ d="M 664.28571,423.35714 C 630,406.21428 361.42857,252.28571 325.71429,233.71429 C 210.11211,477.92779 168.54943,473.07191 391.42857,585.85714 C 473.57143,630.14286 704.28571,747.28571 704.28571,747.28571 L 692.14286,713.71429 L 696.42857,708 L 690.71429,704.42857 C 690.71429,704.42857 680,662.31034 680.71429,616.57143 C 684.07606,583.66932 689.97812,551.14682 701.35097,531.37465 C 677.62453,492.14479 666.70522,466.89564 664.28571,423.35714 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2024);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 235.40172,107.87418 L 137.94474,130.42048 L 85.864752,130.37242 C 112.70742,123.24989 168.02796,105.98041 197.22153,103.80642 C 204.68128,103.12799 223.55473,105.1186 235.40172,107.87418 z "
+ sodipodi:nodetypes="ccccc"
+ id="path2022" />
+ <path
+ style="opacity:0.71111115;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:4.5;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path2911"
+ sodipodi:nodetypes="cc"
+ d="M 688.57143,710.85714 L 204.28571,459.42857" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2978);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 201.96428,456.39285 C 201.96428,456.39285 209.03535,459.42331 209.03535,459.42331 C 209.03535,459.42331 215.69326,444.13271 194.97897,362.70414 C 174.26468,281.27556 138.76871,224.10864 103.57143,213.8071 C 80.911886,207.17511 68.469904,224.74546 62.755618,233.31689 C 57.041332,241.88832 51.785714,292.64286 60,325.85714 C 56.428571,268.71429 67.142857,253 72.857143,244.42857 C 78.571429,235.85714 91.151034,230.56322 103.57143,233 C 121.77521,236.57143 162.14285,282.28571 182.85714,363.71429 C 203.57143,445.14286 201.96428,456.39285 201.96428,456.39285 z "
+ sodipodi:nodetypes="ccssscsssc"
+ id="path2964" />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#efefef;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 73.23606,244.22315 L 66.164992,226.0404 L 66.670068,219.47441 L 64.144687,199.77644"
+ id="path2980" />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#37404e;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.35526315;visibility:visible;display:inline;overflow:visible"
+ id="path2983"
+ d="M 75.23606,243.22315 L 68.164992,225.0404 L 68.670068,218.47441 L 66.144687,198.77644" />
+ <g
+ style="opacity:1;display:inline"
+ id="g3105"
+ transform="translate(-59.41309,-1435.706)">
+ <path
+ style="color:black;fill:url(#linearGradient3136);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path2985"
+ sodipodi:nodetypes="csscscssssc"
+ d="M 1201.4927,1535.7713 C 1157.046,1536.7815 1068.1525,1535.7713 1010.5738,1541.8322 C 952.99516,1547.8932 770.15754,1570.1165 758.03571,1572.1368 C 745.91388,1574.1571 746.92404,1578.1977 749.95449,1581.2282 C 809.55349,1637.7967 923.70073,1807.5024 932.7921,1820.6343 C 941.88348,1833.7663 948.95455,1829.7257 948.95455,1829.7257 C 948.95455,1829.7257 1172.9422,1847.1973 1237.8582,1843.8679 C 1340.1822,1838.6717 1419.6856,1810.5328 1467.1628,1800.4313 C 1514.6399,1790.3298 1552.0156,1752.9541 1531.8126,1733.7612 C 1521.4554,1723.9219 1420.6958,1653.9592 1405.5435,1644.8678 C 1390.3912,1635.7764 1231.7973,1546.883 1201.4927,1535.7713 z " />
+ <path
+ style="color:black;fill:url(#linearGradient3138);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.35526315;visibility:visible;display:inline;overflow:visible"
+ d="M 766.25989,1588.4609 L 926,1812 L 1178,1754 L 1184,1684 L 766.25989,1588.4609 z "
+ sodipodi:nodetypes="ccccc"
+ id="path3044" />
+ <path
+ style="color:black;fill:url(#linearGradient3141);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.35526315;visibility:visible;display:inline;overflow:visible"
+ id="path2987"
+ d="M 1453.0625,1704.7813 C 1442.9429,1704.7349 1435.125,1705.375 1432,1706 C 1422,1708 1354,1730 1340,1730 C 1326,1730 1266,1734 1252,1734 C 1238,1734 1190,1718 1176,1716 C 1162,1714 1138,1718 1118,1724 C 1098,1730 1104,1734 1094,1742 C 1084,1750 1060,1752 1060,1752 L 922,1788 C 922.83382,1788.8338 921.93726,1798.7449 921.46875,1810.8438 C 923.57963,1813.9369 926.02664,1817.535 926.78125,1818.625 C 935.87262,1831.757 942.96875,1827.7188 942.96875,1827.7188 C 942.96877,1827.7187 1166.9277,1845.2044 1231.8438,1841.875 C 1334.1678,1836.6788 1413.6791,1808.539 1461.1563,1798.4375 C 1508.6333,1788.336 1546.0155,1750.9429 1525.8125,1731.75 C 1522.6238,1728.7207 1510.8466,1719.99 1495.6563,1709.0938 C 1480.8889,1705.8916 1465.2921,1704.8373 1453.0625,1704.7813 z " />
+ <path
+ style="color:black;fill:#4c75a1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.35526315;visibility:visible;display:inline;overflow:visible"
+ d="M 1043.3753,1607.2495 C 1110.3746,1638.7505 1241.0441,1666.2137 1339.3753,1689.2495 L 1334,1678 L 1034,1594 L 1043.3753,1607.2495 z "
+ sodipodi:nodetypes="ccccc"
+ id="path2992" />
+ <path
+ style="color:black;fill:#6ea9d5;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.35526315;visibility:visible;display:inline;overflow:visible"
+ id="path2994"
+ d="M 1154,1556 L 1024,1564 L 1032,1596 C 1163.8555,1639.7684 1250.8514,1659.3815 1336,1678 L 1322,1626 L 1154,1556 z M 1372,1650 L 1384,1686 L 1446,1704 L 1372,1650 z "
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="color:black;fill:url(#linearGradient3143);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1201.4927,1535.7713 C 1157.046,1536.7815 1068.1525,1535.7713 1010.5738,1541.8322 C 1201.0479,1637.8143 1308.2698,1670.0197 1467.1628,1800.4313 C 1514.6399,1790.3298 1552.0156,1752.9541 1531.8126,1733.7612 C 1521.4554,1723.9219 1420.6958,1653.9592 1405.5435,1644.8678 C 1390.3912,1635.7764 1231.7973,1546.883 1201.4927,1535.7713 z "
+ sodipodi:nodetypes="cccssc"
+ id="path3008" />
+ <path
+ style="color:black;fill:#184177;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.35526315;visibility:visible;display:inline;overflow:visible"
+ id="path3040"
+ d="M 1086,1566 C 1068,1566 1014,1568 1002,1572 C 990,1576 986,1584 994,1594 C 1002,1604 1018,1608 1032,1608 C 1046,1608 1106,1610 1110,1600 C 1114,1590 1112,1576 1102,1570 C 1092,1564 1086,1564 1086,1566 z " />
+ <path
+ style="color:black;fill:#1a4680;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.35526315;visibility:visible;display:inline;overflow:visible"
+ id="path3042"
+ d="M 802,1590 C 816,1588 870,1584 870,1584 L 860,1624 C 860,1624 832,1632 828,1624 C 824,1616 798,1590 802,1590 z " />
+ <path
+ style="color:black;fill:url(#linearGradient3145);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.35526315;visibility:visible;display:inline;overflow:visible"
+ id="path3054"
+ d="M 1086,1748 C 1098,1750 1170,1792 1188,1810 C 1206,1828 1216,1838 1216,1838 C 1216,1838 1186,1786 1162,1766 C 1138,1746 1120,1728 1112,1728 C 1104,1728 1086,1752 1086,1748 z " />
+ </g>
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2944);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.85526315;visibility:visible;display:inline;overflow:visible"
+ d="M 405.66291,214.21444 C 405.66291,214.21444 436.97763,237.44794 405.6886,214.32151 C 405.71429,214.42857 330.23183,229.19675 325.71429,233.71429 C 320,239.42857 295,292.28571 295,292.28571"
+ id="path2924" />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient2960);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.85526315;visibility:visible;display:inline;overflow:visible"
+ id="path2928"
+ sodipodi:nodetypes="csssc"
+ d="M 310.71428,303 C 312.14285,316.57143 320.71428,348.71429 328.57143,378 C 336.42857,407.28571 368.92857,490.14286 372.14285,495.67857 C 373.97171,498.82827 364.46428,514.25 364.46428,518.53571 C 364.46428,522.82142 374.28572,545.85714 374.28572,545.85714" />
+ <path
+ style="opacity:1;color:black;fill:black;fill-opacity:0.30263157;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1142.1875,99.750032 C 1097.7408,100.76023 1008.8599,99.751632 951.2812,105.81253 C 893.70262,111.87353 710.87183,134.10473 698.75,136.12503 C 686.62817,138.14543 687.6258,142.18833 690.65625,145.21883 C 750.25527,201.78733 864.40863,371.49313 873.5,384.62503 C 882.59136,397.75703 889.65625,393.71883 889.65625,393.71883 C 889.65627,393.71873 1113.6465,411.17313 1178.5625,407.84383 C 1280.8866,402.64753 1360.3978,374.50783 1407.875,364.40633 C 1455.3521,354.30483 1492.7343,316.94293 1472.5313,297.75003 C 1462.174,287.91063 1361.4023,217.93523 1346.25,208.84383 C 1331.0978,199.75233 1172.4921,110.86173 1142.1875,99.750032 z M 1158.1875,110.81253 C 1201.5324,130.30313 1239.0798,151.33873 1280.625,174.46883 C 1344.1639,207.05073 1403.1865,247.21713 1460.625,289.62503 C 1465.7201,295.19363 1459.3367,303.65383 1461.75,311.40633 C 1455.5213,326.68703 1440.0107,335.79223 1425.375,341.96883 C 1404.6546,348.96473 1383.0983,353.82113 1361.9688,359.65633 C 1305.2556,374.08683 1247.8693,387.80073 1189.25,390.93753 C 1091.1562,394.69503 993.346,383.78543 895.53125,378.25003 C 889.18828,379.82653 886.5665,373.84663 883.15625,369.81253 C 829.6456,295.32933 779.53599,217.81223 717.34375,150.09383 C 765.92012,143.17733 815.62684,137.89733 864.71875,131.96883 C 950.1476,118.94013 1036.8226,111.07603 1123.1875,110.93753 C 1128.1875,110.89583 1153.1875,110.85423 1158.1875,110.81253 z "
+ id="path2993" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path2744"
+ id="use4125"
+ style="filter:url(#filter4139)" />
+ <path
+ style="opacity:1;color:black;fill:black;fill-opacity:0.1842105;fill-rule:evenodd;stroke:none;stroke-width:1.99999976;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 481.24773,109.96447 C 435.34721,112.28647 389.53367,117.0681 344.43523,125.71447 C 337.11499,128.19271 330.74254,132.65842 324.71648,137.30822 C 353.08617,162.16634 380.98495,187.7046 411.52898,209.55822 C 413.09557,206.34504 414.77574,203.13089 416.49773,199.93322 C 394.90233,186.48643 374.10949,169.1597 360.15398,155.90197 C 365.15398,145.18769 370.86379,140.16536 384.43523,127.30822 C 409.94324,123.3839 445.52563,121.86778 471.65398,121.08947 C 475.42332,116.61121 478.70818,112.82887 481.24773,109.96447 z M 713.12273,234.58947 C 705.71323,258.8358 686.01622,309.31718 679.62273,353.37072 C 713.92701,366.66493 750.78553,371.82612 787.31023,375.37072 C 793.54817,375.99221 799.7859,376.51971 806.02898,377.08947 C 775.28355,329.39251 746.1125,280.67101 713.12273,234.58947 z M 717.31023,260.90197 C 718.02452,260.18768 743.02449,298.73679 782.31023,362.30822 C 735.88166,357.30822 692.31021,342.30822 692.31023,342.30822 C 692.31023,342.30822 703.0245,289.47339 717.31023,260.90197 z "
+ id="path3024" />
+ <g
+ id="g3639">
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3288);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3280"
+ sodipodi:nodetypes="csscsccsc"
+ d="M 544.28571,615.14286 C 502.85714,590.85714 445.71429,549.42857 421.42857,533.71429 C 397.14286,518 368.57143,493.71429 354.28571,479.42857 C 340,465.14286 317.14286,445.14286 312.85714,435.14286 C 290,446.57143 297.14286,456.57143 295.71429,462.28571 C 294.28571,468 291.42857,472.28571 291.42857,472.28571 L 218.57143,436.57143 C 218.57143,436.57143 348.57143,509.42857 364.28571,518 C 380,526.57143 548.57143,619.42857 544.28571,615.14286 z " />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3310);stroke-width:3.79999995;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3302"
+ d="M 291.89344,471.33463 C 256.17916,395.62034 254.28571,382.28571 245.71429,353.71429 C 237.14286,325.14286 222.85714,286.57143 220,259.42857"
+ sodipodi:nodetypes="csc" />
+ <path
+ style="opacity:0.53913043;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient3343);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3466"
+ d="M 162.63456,229.06071 L 467.70063,378.56329" />
+ <path
+ style="opacity:1;color:black;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3313"
+ d="M 220.21325,257.35513 C 230.31478,301.80185 245.5406,343.25376 250.73194,363.42115 C 257.61909,390.17647 287.84328,458.35575 292.89404,469.46743 C 301.91998,453.44571 313.14729,436.15213 313.14729,436.15213 C 313.14729,436.15213 284.86302,376.55313 278.8021,352.30947 C 272.74119,328.06581 261.62951,279.57849 261.62951,279.57849 L 220.21325,257.35513 z "
+ sodipodi:nodetypes="csccscc" />
+ <path
+ style="opacity:1;color:black;fill:url(#radialGradient3328);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 277.22995,287.19347 C 278.76005,305.9259 289.25026,344.10569 297.33148,366.87002 C 304.29823,386.49495 305.81009,407.50891 322.16687,447.61044 C 316.43155,441.448 317.20277,442.83451 311.71872,435.43784 C 296.94896,410.89831 283.43445,375.83884 277.37353,351.59518 C 271.31262,327.35152 260.20094,278.8642 260.20094,278.8642 L 277.22995,287.19347 z "
+ sodipodi:nodetypes="csccscc"
+ id="path3469" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3074);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.35526315;visibility:visible;display:inline;overflow:visible"
+ id="path3066"
+ d="M 313.9554,436.75824 C 323.14779,448.77906 344.36099,470.69937 348.60363,474.2349 C 352.84627,477.77043 371.23105,495.4481 371.23105,495.4481 L 347.18942,438.87956 L 302.64169,416.25215 L 313.9554,436.75824 z " />
+ <path
+ d="M 163.5275,231.29306 L 557.77109,424.49853"
+ id="path3000"
+ style="opacity:0.41304345;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient3919);stroke-width:3.79999995;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter3915)"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:nodetypes="csc"
+ d="M 289.9752,471.33463 C 254.26092,395.62034 252.36747,382.28571 243.79605,353.71429 C 235.22462,325.14286 220.9389,286.57143 218.08176,259.42857"
+ id="path3986"
+ style="opacity:0.38260869;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4012);stroke-width:3.79999995;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4008)" />
+ <path
+ style="opacity:0.10869565;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4016);stroke-width:3.79999995;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4022)"
+ id="path4014"
+ d="M 329.55771,453.04593 C 307.89786,393.24881 295.66955,355.75004 284.73154,290.88513"
+ sodipodi:nodetypes="cc" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path3280"
+ id="use4143"
+ style="filter:url(#filter4161);opacity:0.9173913" />
+ </g>
+ <path
+ style="opacity:1;color:black;fill:url(#radialGradient2922);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path2914"
+ sodipodi:nodetypes="ccsccc"
+ d="M 205,473 L 207.85714,503 C 207.85714,503 309.28571,541.57143 391.42857,585.85714 C 473.57143,630.14286 704.28571,747.28571 704.28571,747.28571 L 692.85715,720.85715 L 205,473 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#radialGradient3028);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3013"
+ sodipodi:nodetypes="ccsccccc"
+ d="M 761.55397,401.40291 L 756.60423,379.4826 C 756.60423,379.4826 697.20726,370.99732 688.01487,366.75468 C 678.82248,362.51204 577.70621,315.84299 577.70621,315.84299 L 594.67678,383.72524 L 662.55903,422.61611 L 673.16563,398.57448 C 673.16563,398.57448 723.37021,397.16027 761.55397,401.40291 z " />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.45394736;visibility:visible;display:inline;overflow:visible"
+ d="M 687.94679,365.35343 C 616.70335,338.43924 438.99996,236.8964 407.68524,213.6629 C 407.68524,213.6629 330.23183,229.19675 325.71429,233.71429 C 320,239.42857 295,292.28571 295,292.28571 C 295,292.28571 296.42857,295.14286 312.85714,302.28571 C 314.28571,315.85714 322.85714,348.71429 330.71429,378 C 338.57143,407.28571 373.57143,493.71429 374.28571,497.28571 C 375,500.85714 366.42857,513.71429 366.42857,518 C 366.42857,522.28571 377.14286,548 377.14286,548 L 675.71429,701.57143 C 675.71429,701.57143 668.57143,697.28571 668.57143,693 C 668.57143,688.71429 665.71429,625.85714 663.57143,573.71429 C 661.42857,521.57143 662.16391,437.14531 664.28571,423 C 666.42857,408.71429 687.94679,365.35343 687.94679,365.35343 z "
+ id="path1897" />
+ <g
+ style="opacity:1;display:inline"
+ id="g3159"
+ transform="translate(-2.641884,-561.5901)">
+ <path
+ style="color:black;fill:url(#linearGradient3177);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3089"
+ sodipodi:nodetypes="ccscccccccccsccsccsz"
+ d="M 819.54383,974.21723 C 783.31746,965.09822 758.63736,962.71531 730.75908,961.06724 C 776.39437,962.12044 815.84589,943.8445 823.55086,945.3846 C 844.20909,949.5138 884.75481,954.5533 884.75481,954.5533 C 884.75481,954.5533 1131.232,968.6954 1177.699,974.7563 C 1184.7701,978.7969 1184.7701,978.7969 1184.7701,978.7969 L 1190.831,972.736 C 1190.831,972.736 1415.0849,948.4924 1484.7854,918.1878 C 1489.8362,917.1776 1491.8565,917.1776 1491.8565,917.1776 L 1491.8565,913.137 C 1491.8565,913.137 1538.3235,871.7208 1492.8666,851.5177 C 1481.7549,845.4568 1481.7549,845.4568 1481.7549,845.4568 C 1481.7549,845.4568 1560.9961,861.62723 1608.024,886.8731 C 1655.011,912.097 1762.7716,997.9632 1831.982,1094.0769 C 1831.982,1094.0769 1845.2796,1109.9603 1857.8342,1140.9051 C 1838.3388,1171.7361 1785.8109,1228.3046 1690.8565,1258.6092 C 1595.9022,1288.9138 1398.9224,1326.2894 1303.0473,1329.4309 L 1250.9939,1274.9603 C 1250.9939,1274.9603 1066.7081,1107.8174 986.70821,1058.5317 C 906.70821,1009.246 855.10484,983.16875 819.54383,974.21723 z " />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3179);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3109"
+ d="M 1178,978 C 1178,978 1264,1060 1280,1080 C 1296,1100 1354,1176 1376,1210" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3181);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1178,978 C 1178,978 1264,1060 1280,1080 C 1296,1100 1354,1176 1376,1210 L 1374,1208 C 1374,1208 1218,1136 1168,1110 C 1118,1084 927.99997,956 927.99997,956 C 927.99997,956 1142,970 1178,978 z "
+ sodipodi:nodetypes="csccscc"
+ id="path3119" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3183);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1488,915 C 1488,915 1600.7516,975.6995 1622,990 C 1678.3886,1027.9505 1718.2001,1046.9778 1738,1080 C 1738,1080 1530,1074 1480,1048 C 1430,1022 1291.8654,960.62692 1291.8654,960.62692 C 1291.8654,960.62692 1452,928 1488,915 z "
+ sodipodi:nodetypes="cscscc"
+ id="path3129" />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#7a99d9;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3133"
+ d="M 1492,916 C 1526,930 1688,1014 1794,1122" />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3185);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1492,912 C 1526,926 1688,1010 1794,1118"
+ id="path3137" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3875);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1516,876 C 1573,887 1622,924 1668,972 C 1714,1020 1724,1041 1730,1050 C 1736,1059 1742,1072 1751,1080 C 1760,1088 1775,1117 1776,1129 C 1777,1141 1777,1149 1777,1149 L 1787,1142 C 1787,1142 1786,1154 1791,1162 C 1796,1170 1809,1174 1812,1174 C 1815,1174 1791,1194 1782,1203 C 1773,1212 1749,1224 1738,1225 C 1727,1226 1716,1238 1709,1242 C 1702,1246 1688,1245 1680,1245 C 1672,1245 1669,1251 1660,1251 C 1651,1251 1662,1249 1646,1249 C 1630,1249 1598,1259 1586,1259 C 1574,1259 1557,1256 1551,1256 C 1545,1256 1521,1270 1507,1270 C 1493,1270 1477,1263 1458,1263 C 1439,1263 1382,1274 1362,1280 C 1342,1286 1278.6891,1304.0674 1278.6891,1304.0674 L 1305.04,1326.08 C 1305.04,1326.08 1456.08,1318.48 1534,1300 C 1561.8628,1293.3919 1700.8868,1257.7496 1725,1247 C 1757.84,1232.36 1798.32,1208.72 1824,1182.5 C 1839.3459,1166.8314 1853.28,1151.44 1859,1140 C 1859,1140 1837.2311,1103.6399 1831.4,1095.64 C 1802.04,1055.36 1754.371,1007.035 1729.28,982.52 C 1699.4373,953.35054 1644.3563,910.269 1610.6323,890.47078 C 1594.7053,881.12058 1565.1202,868.00854 1530.1031,858.49311 C 1533.1031,866.49311 1532,864.83848 1532,864.83848 L 1498,851 C 1498,851 1517,866 1516,876 z "
+ sodipodi:nodetypes="cssssccsssssssssssssccssscssscccc"
+ id="path3149" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path3149"
+ id="use3857"
+ style="filter:url(#filter3871)" />
+ <path
+ id="path2946"
+ sodipodi:nodetypes="csssssssssccsss"
+ d="M 1738,1225 C 1727,1226 1716,1238 1709,1242 C 1702,1246 1688,1245 1680,1245 C 1672,1245 1669,1251 1660,1251 C 1651,1251 1662,1249 1646,1249 C 1630,1249 1598,1259 1586,1259 C 1574,1259 1557,1256 1551,1256 C 1545,1256 1521,1270 1507,1270 C 1493,1270 1477,1263 1458,1263 C 1439,1263 1382,1274 1362,1280 C 1342,1286 1280,1303.9326 1280,1303.9326 L 1302.9726,1330.2149 C 1302.9726,1330.2149 1456.08,1318.48 1534,1300 C 1561.8628,1293.3919 1700.8868,1257.7496 1725,1247 C 1757.84,1232.36 1749,1224 1738,1225 z "
+ style="opacity:1;color:black;fill:url(#linearGradient2949);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient3182);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3166"
+ d="M 909.13729,592.69532 L 941.46217,594.71563 L 953.584,624.01005 L 991.9698,638.15219 C 991.9698,638.15219 1011.1627,641.18264 1019.2439,638.15219 C 1027.3251,635.12173 1031.3657,632.09127 1031.3657,632.09127 L 1250.5689,718.96439 C 1250.5689,718.96439 1366.7364,711.89332 1395.0207,706.84256 C 1395.0207,706.84256 1588.97,679.56844 1656.6502,652.29432 C 1724.3304,625.0202 1791.0005,586.63441 1805.1426,575.52273 C 1819.2847,564.41105 1831.4066,536.12678 1831.4066,536.12678" />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.36842107;visibility:visible;display:inline;overflow:visible"
+ d="M 909.13729,589.69532 L 941.46217,591.71563 L 953.584,621.01005 L 991.9698,635.15219 C 991.9698,635.15219 1011.1627,638.18264 1019.2439,635.15219 C 1027.3251,632.12173 1031.3657,629.09127 1031.3657,629.09127 L 1250.5689,715.96439 C 1250.5689,715.96439 1366.7364,708.89332 1395.0207,703.84256 C 1395.0207,703.84256 1588.97,676.56844 1656.6502,649.29432 C 1724.3304,622.0202 1791.0005,583.63441 1805.1426,572.52273 C 1819.2847,561.41105 1831.4066,533.12678 1831.4066,533.12678"
+ id="path3190" />
+ <path
+ style="opacity:1;color:black;fill:#9fbbf1;fill-opacity:1;fill-rule:evenodd;stroke:#89a2db;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3010"
+ sodipodi:nodetypes="csc"
+ d="M 820.95094,386.55367 C 810.34434,395.74606 782.76718,400.13237 765.79661,398.01105 C 748.82605,395.88973 725.49153,396.45317 715.59203,374.53286" />
+ <g
+ style="opacity:1;display:inline"
+ id="g3138"
+ transform="translate(-26,12)">
+ <path
+ style="opacity:1;color:black;fill:#0d1021;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3134"
+ sodipodi:nodetypes="cscsc"
+ d="M 1634.4173,588.01711 C 1639.4239,593.82868 1666.7798,620.28293 1673.2523,616.79474 C 1679.7248,613.30654 1662.33,580.60468 1657.8802,576.24443 C 1652.2167,574.50034 1646.1487,574.50034 1642.9125,575.80841 C 1639.6762,577.11647 1633.3559,582.92805 1634.4173,588.01711 z " />
+ <path
+ style="opacity:1;color:black;fill:#c0c6e6;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1636.2504,587.33066 C 1641.029,592.83866 1667.1394,617.91103 1673.3173,614.60505 C 1679.4951,611.29906 1662.8922,580.30543 1658.645,576.17295 C 1653.2394,574.51996 1647.4477,574.51996 1644.3588,575.7597 C 1641.2698,576.99944 1635.2373,582.50744 1636.2504,587.33066 z "
+ sodipodi:nodetypes="cscsc"
+ id="path3130" />
+ <path
+ style="opacity:1;color:black;fill:#494d83;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3132"
+ sodipodi:nodetypes="cscsc"
+ d="M 1641.0142,590.19024 C 1645.109,594.68633 1667.483,615.15244 1672.7768,612.45383 C 1678.0705,609.75521 1663.8435,584.45568 1660.2041,581.08242 C 1655.5721,579.7331 1650.6092,579.7331 1647.9623,580.74508 C 1645.3154,581.75706 1640.1461,586.25314 1641.0142,590.19024 z " />
+ <path
+ style="opacity:1;color:black;fill:#ebf0e9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3136"
+ d="M 1656.0489,585.98123 C 1650.6163,588.06746 1655.2132,591.40541 1655.631,595.16063 C 1656.0489,598.91584 1656.0489,604.75728 1658.9742,604.34003 C 1661.8994,603.92279 1659.8099,597.6641 1661.8994,597.24686 C 1663.9889,596.8296 1670.6753,599.33309 1668.1679,595.99512 C 1665.6604,592.65716 1662.7353,591.40541 1660.2279,588.4847 C 1657.7204,585.56398 1655.2132,585.56398 1656.0489,585.98123 z " />
+ </g>
+ <g
+ style="opacity:1;display:inline"
+ id="g3324"
+ transform="translate(-210.08,-960.96)">
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3340);fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1187.4623,1436.4484 C 1194.5334,1440.489 1333.4293,1545.5449 1348.5816,1557.6667 C 1363.7338,1569.7885 1467.7796,1661.7124 1476.8709,1672.8241 C 1555.6628,1670.8038 1606.1705,1662.7226 1606.1705,1662.7226 C 1606.1705,1662.7226 1478.8912,1563.7276 1441.5156,1539.4839 C 1404.14,1515.2403 1325.3481,1466.753 1315.2465,1460.692 C 1305.145,1454.6311 1281.9115,1446.5499 1271.81,1445.5398 C 1261.7084,1444.5296 1187.4623,1436.4484 1187.4623,1436.4484 z "
+ sodipodi:nodetypes="csccsssc"
+ id="path3155" />
+ <path
+ style="opacity:1;color:black;fill:#202c54;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1422.333,1622.4002 C 1453.3979,1650.0085 1472.8742,1665.7815 1477.7376,1671.7257 C 1556.5295,1669.7053 1598.9295,1663.1027 1605.5481,1662.3673 C 1605.5481,1662.3673 1579.6649,1640.958 1543.2124,1613.2078 C 1543.2124,1613.2078 1559.6435,1626.8251 1551.5542,1627.1928 L 1442.7745,1632.732 C 1433.9499,1633.8351 1422.333,1622.4002 1422.333,1622.4002 z "
+ sodipodi:nodetypes="ccccccc"
+ id="path3165" />
+ <path
+ id="path2951"
+ sodipodi:nodetypes="csccsssc"
+ d="M 1187.4623,1436.4484 C 1194.5334,1440.489 1333.4293,1545.5449 1348.5816,1557.6667 C 1363.7338,1569.7885 1467.7796,1661.7124 1476.8709,1672.8241 C 1555.6628,1670.8038 1606.1705,1662.7226 1606.1705,1662.7226 C 1606.1705,1662.7226 1478.8912,1563.7276 1441.5156,1539.4839 C 1404.14,1515.2403 1325.3481,1466.753 1315.2465,1460.692 C 1305.145,1454.6311 1281.9115,1446.5499 1271.81,1445.5398 C 1261.7084,1444.5296 1187.4623,1436.4484 1187.4623,1436.4484 z "
+ style="opacity:1;color:black;fill:url(#linearGradient3844);fill-opacity:1.0;fill-rule:evenodd;stroke:black;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3342);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1193.92,1438.16 C 1206.4,1448.56 1277.12,1498.48 1306.24,1520.32 C 1335.36,1542.16 1432.08,1626.4 1432.08,1626.4"
+ sodipodi:nodetypes="csc"
+ id="path3180" />
+ <g
+ clip-path="url(#clipPath3321)"
+ transform="translate(216.32,-62.4)"
+ id="g3305">
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3344);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1052.3445,1512.1827 L 997.92562,1511.4474 L 1006.0149,1549.6877 L 1052.3445,1512.1827 z "
+ sodipodi:nodetypes="cccc"
+ id="path3301" />
+ <path
+ style="opacity:1;color:black;fill:url(#radialGradient3346);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3348);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3271"
+ sodipodi:nodetypes="csccsc"
+ d="M 1101.6157,1537.9215 C 1101.6157,1553.3647 1101.6157,1567.3371 1087.6432,1567.3371 C 1073.6709,1567.3371 1014.8396,1547.4816 1014.8396,1547.4816 L 1022.9289,1529.8322 C 1022.9289,1529.8322 1017.7901,1514.2279 1044.2553,1513.6536 C 1068.5286,1513.1269 1088.3786,1529.8322 1101.6157,1537.9215 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3350);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1035.7458,1514.1206 C 1050.2085,1515.4979 1059.0099,1518.066 1059.0099,1533.9061 C 1059.0099,1549.7461 1050.7455,1554.567 1050.7455,1554.567 L 1022.9291,1527.8945 C 1022.9291,1527.8945 1024.2597,1514.8092 1035.7458,1514.1206 z "
+ sodipodi:nodetypes="csccc"
+ id="path3289" />
+ <path
+ transform="matrix(0.818861,0,0,0.818861,108.7186,219.3779)"
+ sodipodi:cy="1611.8282"
+ sodipodi:type="arc"
+ sodipodi:cx="1141.6946"
+ style="opacity:1;color:black;fill:url(#radialGradient3352);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3291"
+ sodipodi:rx="18.752472"
+ d="M 1160.4471 1611.8282 A 18.752472 23.164818 0 1 1 1122.9421,1611.8282 A 18.752472 23.164818 0 1 1 1160.4471 1611.8282 z"
+ sodipodi:ry="23.164818" />
+ <path
+ transform="matrix(1.330649,0,0,1.541385,-556.0913,-957.7293)"
+ sodipodi:cy="1616.2406"
+ sodipodi:type="arc"
+ sodipodi:cx="1206.0413"
+ style="opacity:1;color:black;fill:url(#radialGradient3354);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3293"
+ sodipodi:rx="5.8831282"
+ d="M 1211.9244 1616.2406 A 5.8831282 6.250824 0 1 1 1200.1581,1616.2406 A 5.8831282 6.250824 0 1 1 1211.9244 1616.2406 z"
+ sodipodi:ry="6.250824" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3356);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1136.9145,1571.014 L 1032.489,1544.54 L 1090.5849,1608.519 L 1136.9145,1571.014 z "
+ id="path3259" />
+ <path
+ inkscape:transform-center-y="-16.160042"
+ transform="matrix(1.093875,0,0.39879,0.998849,-751.9213,1.854308)"
+ sodipodi:cy="1611.0929"
+ sodipodi:type="arc"
+ sodipodi:cx="1143.1654"
+ style="opacity:1;color:black;fill:url(#radialGradient5012);fill-opacity:1.0;fill-rule:evenodd;stroke:url(#linearGradient3360);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ inkscape:transform-center-x="-66.767625"
+ id="path3199"
+ sodipodi:rx="34.931072"
+ d="M 1178.0965 1611.0929 A 34.931072 39.343422 0 1 1 1108.2343,1611.0929 A 34.931072 39.343422 0 1 1 1178.0965 1611.0929 z"
+ sodipodi:ry="39.343422" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3362);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1106.0282,1580.5742 C 1121.4714,1582.0449 1145.0039,1587.9281 1145.0039,1604.8421 C 1145.0039,1621.7561 1136.1792,1626.9038 1136.1792,1626.9038 L 1099.4097,1595.282 C 1099.4097,1595.282 1101.6158,1581.3095 1106.0282,1580.5742 z "
+ id="path3249" />
+ <path
+ transform="translate(-14.70782,-0.735389)"
+ sodipodi:cy="1611.8282"
+ sodipodi:type="arc"
+ sodipodi:cx="1141.6946"
+ style="opacity:1;color:black;fill:url(#radialGradient3364);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3227"
+ sodipodi:rx="18.752472"
+ d="M 1160.4471 1611.8282 A 18.752472 23.164818 0 1 1 1122.9421,1611.8282 A 18.752472 23.164818 0 1 1 1160.4471 1611.8282 z"
+ sodipodi:ry="23.164818" />
+ <path
+ transform="matrix(1.625,0,0,1.882353,-826.5795,-1438.229)"
+ sodipodi:cy="1616.2406"
+ sodipodi:type="arc"
+ sodipodi:cx="1206.0413"
+ style="opacity:1;color:black;fill:url(#radialGradient3366);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3239"
+ sodipodi:rx="5.8831282"
+ d="M 1211.9244 1616.2406 A 5.8831282 6.250824 0 1 1 1200.1581,1616.2406 A 5.8831282 6.250824 0 1 1 1211.9244 1616.2406 z"
+ sodipodi:ry="6.250824" />
+ <path
+ style="fill:url(#linearGradient5008);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 1139.4511,548.07893 C 1133.2012,545.73519 1052.342,525.81334 1052.342,525.81334 C 1052.342,525.81334 1105.0763,563.70391 1105.0763,563.70391 C 1109.6261,555.79874 1116.2816,546.34848 1139.4511,548.07893 z "
+ id="path5000"
+ transform="translate(-6.24,1023.36)"
+ sodipodi:nodetypes="ccsc" />
+ <path
+ sodipodi:nodetypes="ccsc"
+ transform="translate(-6.24,1023.36)"
+ id="path5014"
+ d="M 1139.4511,548.07893 C 1133.2012,545.73519 1052.342,525.81334 1052.342,525.81334 C 1052.342,525.81334 1105.0763,563.70391 1105.0763,563.70391 C 1109.6261,555.79874 1116.2816,546.34848 1139.4511,548.07893 z "
+ style="fill:url(#linearGradient5022);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;opacity:0.53043478" />
+ </g>
+ <path
+ style="opacity:0.53043476;color:black;fill:black;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter5154);enable-background:accumulate"
+ id="path5120"
+ d="M 1260.6097,709.68561 C 1257.6313,704.30499 1239.4961,688.30688 1234.577,684.7353 C 1228.2945,680.6957 1222.9763,679.17553 1224.0869,670.89591 C 1229.2219,665.71476 1236.5969,667.5455 1243.1906,667.69223 C 1249.4113,667.46897 1255.5898,667.91808 1261.7893,668.32645 C 1267.6422,669.15685 1273.5001,668.84644 1279.3758,668.57004 C 1285.2286,668.33741 1291.0871,668.40966 1296.9426,668.44226 C 1303.0974,668.32722 1309.116,667.17398 1315.1554,666.12154 C 1321.2855,664.59528 1327.4489,665.08165 1333.6472,665.66824 C 1339.4381,666.36866 1345.0483,664.5506 1350.7503,665.85513 C 1356.0675,668.54094 1361.4074,671.31639 1366.4208,674.54242 C 1368.9944,676.18397 1380.7414,685.76626 1382.8034,687.97895 C 1384.7121,690.02703 1372.4913,685.70059 1370.5986,683.63778 L 1395.266,701.22932 C 1393.4024,699.19824 1366.8843,679.56838 1364.5526,678.04932 C 1359.8751,674.95511 1354.7869,672.47209 1349.8852,669.75235 C 1344.3862,669.14513 1338.8855,669.99885 1333.2771,669.61947 C 1327.3648,669.05538 1321.5066,668.56124 1315.6556,670.03526 C 1309.4299,671.14148 1303.2094,672.27139 1296.864,672.40329 C 1291.0632,672.37703 1285.259,672.3107 1279.4613,672.54699 C 1273.4672,672.80913 1267.4891,673.12262 1261.5222,672.25095 C 1255.3642,671.87067 1249.2292,671.43545 1243.0526,671.64262 C 1237.7859,671.51322 1232.0143,670.11783 1227.418,673.07591 C 1228.1031,674.37246 1231.8653,679.74443 1236.5843,681.30791 C 1241.7547,685.04603 1246.2248,689.19799 1249.3066,694.8863 C 1250.6351,697.33819 1261.9602,712.12539 1260.6097,709.68561 z "
+ transform="matrix(0.932847,-2.173754e-2,2.173754e-2,0.932847,282.4787,1035.819)"
+ sodipodi:nodetypes="cccccccccccsccccccccccccsc" />
+ <path
+ style="opacity:0.53043476;color:black;fill:#2f5586;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;filter:url(#filter5194)"
+ id="path5164"
+ d="M 1405.28,1598.9689 C 1408.5084,1603.5631 1412.5544,1607.5013 1417.0856,1610.7914 C 1421.5033,1614.403 1426.0316,1617.8695 1430.4945,1621.4221 C 1434.8239,1625.8799 1438.1193,1627.7707 1444.3084,1627.4335 C 1450.4682,1626.3484 1456.653,1626.1557 1462.8803,1626.0455 C 1468.7654,1625.8212 1527.2793,1627.0102 1533.149,1627.3891 C 1535.9556,1627.5702 1483.0042,1630.7045 1480.198,1630.5183 L 1480.198,1630.5183 C 1474.4214,1630.135 1487.0152,1627.2823 1481.223,1627.493 C 1475.0342,1627.6316 1450.5006,1630.2885 1444.3804,1631.3774 C 1437.4396,1631.7493 1433.1059,1629.754 1428.3131,1624.7551 C 1423.9114,1621.2114 1419.3929,1617.815 1415.0452,1614.201 C 1410.1759,1610.6946 1388.3146,1590.6488 1384.7734,1585.7857 C 1383.1077,1583.4985 1403.6531,1596.6538 1405.28,1598.9689 z "
+ sodipodi:nodetypes="cccccsccccccsc" />
+ </g>
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2753);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 218.2913,105.33514 C 221.37881,104.86014 244.52449,105.13105 249.0731,104.59612 C 286.777,100.16207 368.65601,93.953045 394.90498,90.67193 C 424.32062,86.99497 471.38564,81.11185 486.09346,81.11185 C 500.80128,81.11185 540.5124,81.11185 552.27865,82.58263 C 564.04491,84.05341 571.39882,106.85053 541.98318,103.90897 C 512.56754,100.9674 486.09346,101.70279 466.2379,102.43819 C 446.38235,103.17358 352.2523,114.20444 345.63378,117.14601 C 339.01526,120.08757 314.74735,136.26617 314.74735,136.26617 L 405.93585,213.11453 C 405.93585,213.11453 325.04283,150.2386 311.0704,139.20774 C 297.09797,128.17687 261.06381,113.46905 255.91607,111.26288 C 250.76834,109.0567 217.55591,105.33514 218.2913,105.33514 z "
+ sodipodi:nodetypes="csssssssccssc"
+ id="path2744" />
+ <path
+ style="opacity:1;color:black;fill:url(#radialGradient2993);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 624.9099,362.64482 C 624.09528,371.41246 616.44404,377.72566 606.63474,377.19246 C 606.63474,377.19246 598.87477,378.0361 604.58709,382.60576 C 621.10593,395.82025 658.50309,402.80443 666.47502,413.26303 C 669.6844,405.24161 670.24637,402.3972 671.50922,400.269 C 675.26049,393.94718 653.17204,375.81556 624.9099,362.64482 z "
+ id="path2977"
+ sodipodi:nodetypes="ccscsc"
+ transform="matrix(1.017743,0,0,0.97895,-11.88466,7.633765)" />
+ <g
+ id="g3114">
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3091);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 610.23313,317.25719 C 610.23313,317.25719 598.91942,359.6836 596.7981,366.75467 C 594.67678,373.82573 601.04074,381.60391 605.99049,383.01812 C 610.94024,384.43233 622.25395,384.43233 626.49659,373.11863 C 630.73923,361.80492 636.39608,313.01455 636.39608,313.01455 L 610.23313,317.25719 z "
+ sodipodi:nodetypes="cssscc"
+ id="path3043" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3088);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3047"
+ d="M 630.03213,315.84298 C 626.49659,325.03537 623.66816,333.52065 619.42552,336.34908 C 615.18288,339.17751 607.40471,352.61254 607.40471,348.3699 C 607.40471,344.12726 607.40471,341.29883 601.04075,340.59172 C 594.67679,339.88461 516.89504,332.10644 508.40976,329.27801 C 499.92448,326.44959 487.90367,313.01456 487.90367,309.47902 C 487.90367,305.94349 630.03213,316.55009 630.03213,315.84298 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#radialGradient3083);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 487.82661,309.06261 C 487.82661,309.06261 612.78264,315.54446 620.56082,315.54446 C 628.33899,315.54446 637.10319,315.84299 637.10319,310.18613 C 637.10319,304.52928 633.56766,291.09425 627.2037,284.73029 C 620.83974,278.36633 603.16207,268.46684 589.72704,268.46684 C 576.29201,268.46684 526.08743,267.75973 511.9453,276.95212 C 497.80316,286.1445 488.53372,294.21337 487.82661,309.06261 z "
+ sodipodi:nodetypes="csssssc"
+ id="path3057" />
+ <path
+ style="opacity:0.23043478;color:black;fill:black;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4877);enable-background:accumulate"
+ id="path4827"
+ d="M 672.07967,364.71084 C 670.42546,367.09722 667.6541,367.90897 665.12408,369.03759 C 661.84684,370.84217 658.86544,373.12904 655.77552,375.23387 C 652.90706,376.82391 650.61188,381.34386 647.23238,380.84 C 645.2797,383.53727 641.40304,382.52314 638.35458,383.56296 C 635.0111,383.653 632.64311,384.42579 629.47719,384.25502 C 626.47028,384.38201 623.38674,382.77046 621.49606,380.48683 C 621.21102,380.15219 620.92599,379.81754 620.64095,379.4829 C 610.74633,367.8662 616.36466,345.22463 624.35511,358.22478 L 624.35511,358.22478 C 624.59646,358.61746 624.83782,359.01014 625.07918,359.40282 C 626.83581,361.71888 628.11608,362.94479 631.22893,362.78295 C 634.30209,362.79263 636.3171,363.77923 639.57541,362.89681 C 642.51192,362.74924 645.52592,360.42208 647.93092,361.13382 C 650.1124,358.71938 653.49086,358.40258 656.108,356.28295 C 659.2285,354.04751 662.60734,352.15958 665.42704,349.54001 C 667.55521,347.38156 669.52413,345.01154 671.97224,343.20794 C 684.21379,334.18921 680.74194,352.21452 672.07967,364.71084 z "
+ transform="matrix(1,0,-0.718026,1,264.3032,6)" />
+ </g>
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3659);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 451.35998,84.08005 C 497.11997,79.92005 533.51997,83.04005 556.39997,86.16005 C 579.27997,89.28005 623.99997,102.80005 623.99997,102.80005 C 623.99997,102.80005 867.35996,80.960049 893.35995,83.040049 C 919.35995,85.120049 1013.9999,102.28005 1013.9999,102.28005 L 1143.9999,99.68005 C 1117.9999,90.32005 1070.9668,79.065394 1029.5999,70.56005 C 973.95995,59.12005 892.31996,56.52005 857.99996,54.96005 C 826.76296,53.540186 744.63996,49.76005 711.35996,52.88005 C 678.07997,56.00005 548.07997,67.44005 523.11997,71.60005 C 498.15997,75.76005 450.31998,84.08005 451.35998,84.08005 z "
+ sodipodi:nodetypes="cscsccssssc"
+ id="path3651" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3648);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;"
+ d="M 689.79677,145.09086 C 686.11982,133.72341 690.53216,113.83034 695.6799,108.14662 C 700.82764,102.46288 885.41078,20.048761 917.76799,5.8394101 C 950.12519,-8.3699012 1064.1108,-31.104839 1069.9939,-31.104839 C 1075.8771,-31.104839 1089.8495,-39.630427 1070.7293,-59.523501 C 1051.6092,-79.416577 980.27622,-122.04455 949.3898,-133.41204 C 918.50338,-144.77949 892.76469,-161.8307 883.20461,-164.67256 C 873.64453,-167.51443 849.37662,-187.40746 838.34576,-178.88188 C 827.31489,-170.35629 807.45934,-133.41204 819.96098,-130.57014 C 832.46263,-127.72828 857.46592,-122.04455 847.90584,-119.20269 C 838.34576,-116.36083 750.83423,-87.942164 732.44945,-82.258439 C 714.06468,-76.574675 633.17167,-22.579252 622.1408,-22.579252 C 660.38114,37.099974 683.17825,113.83034 689.79677,145.09086 z "
+ sodipodi:nodetypes="csssssssssscc"
+ id="path3640"
+ transform="matrix(1,0,0,0.255782,0,107.9793)" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3670);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 538.71997,84.080047 C 552.23997,75.760047 582.39997,71.600048 602.15997,69.520048 C 621.91997,67.440048 683.27997,63.280048 683.27997,63.280048 L 629.19997,59.120048 C 629.19997,59.120048 555.35997,66.400048 528.31997,70.560048 C 501.27997,74.720048 457.59998,83.040047 457.59998,83.040047 C 457.59998,83.040047 515.83997,82.000047 538.71997,84.080047 z "
+ id="path3662" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3680);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 315.48275,142.88469 L 355.99906,187.62087 L 376.8879,197.67132 L 400.42041,214.21762 L 407.03893,213.48222 L 315.48275,142.88469 z "
+ sodipodi:nodetypes="cccccc"
+ id="path3672" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3694);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 79.039996,133.48004 C 96.719995,131.92004 107.63999,131.40004 118.03999,131.92004 C 128.43999,132.44004 151.05999,140.50004 151.05999,140.50004 L 167.69999,137.12004 C 167.69999,137.12004 152.87999,128.28004 137.79999,127.24004 C 122.71999,126.20004 107.63999,124.12004 99.839995,126.20004 C 92.039995,128.28004 79.039996,133.48004 79.039996,133.48004 z "
+ sodipodi:nodetypes="csccssc"
+ id="path3686" />
+ <path
+ style="opacity:1;color:black;fill:#a4b0ea;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 186.15999,105.92005 C 210.68921,105.43701 222.94616,105.66005 242.70616,105.40005 C 292.01695,101.36622 366.07998,93.440047 366.07998,93.440047 L 458.63998,82.000047 L 485.67998,77.840047 C 485.67998,77.840047 395.28036,82.546991 355.67998,85.855438 C 314.6892,89.280047 201.75999,101.76005 186.15999,105.92005 z "
+ sodipodi:nodetypes="cccccsc"
+ id="path3699" />
+ <path
+ style="opacity:1;color:black;fill:#7a8cbd;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3701"
+ sodipodi:nodetypes="cccccsc"
+ d="M 186.15999,105.92005 C 210.13767,104.15008 207.4268,102.49544 229.57141,103.40927 C 278.8822,97.295437 362.77072,89.395396 362.77072,89.395396 L 458.63998,82.000047 L 485.67998,77.840047 C 485.67998,77.840047 395.28036,82.546991 355.67998,85.855438 C 314.6892,89.280047 201.75999,101.76005 186.15999,105.92005 z " />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3721);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 240.75999,171.44004 C 268.31999,184.44004 312.51999,209.92004 327.33998,219.28004"
+ sodipodi:nodetypes="cc"
+ id="path3705" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3731);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1322.9685,950.34403 C 1283.2573,940.04855 1211.9244,915.04526 1211.9244,915.04526 C 1211.9244,915.04526 1057.4923,875.33414 975.12849,850.33085 C 985.42396,878.27571 991.30709,887.1004 991.30709,887.1004 C 991.30709,887.1004 1209.7182,938.57777 1322.9685,950.34403 z "
+ sodipodi:nodetypes="ccccc"
+ id="path3723" />
+ <path
+ style="opacity:1;color:black;fill:#201e2b;fill-opacity:0.73026315;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1360.3199,219.28004 C 1384.2399,239.04004 1400.8799,247.36004 1410.2399,259.84004 C 1419.5999,272.32004 1431.0399,286.88004 1445.5999,298.32003 C 1460.1599,309.76003 1475.7599,323.28003 1475.7599,323.28003 C 1475.7599,323.28003 1486.1599,309.76003 1476.7999,301.44003 C 1467.4399,293.12004 1374.8799,226.56004 1360.3199,219.28004 z "
+ id="path2273" />
+ <path
+ style="opacity:1;color:black;fill:#201e2b;fill-opacity:0.73026315;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1452.8799,283.76004 C 1438.3199,306.64003 1397.7599,325.36003 1377.9999,333.68003 C 1358.2399,342.00003 1198.0799,372.16003 1176.2399,372.16003 C 1154.3999,372.16003 880.87996,369.04003 880.87996,369.04003 L 896.47996,392.96003 C 896.47996,392.96003 1138.7999,410.64003 1173.1199,406.48003 C 1207.4399,402.32003 1407.1199,370.08003 1422.7199,363.84003 C 1438.3199,357.60003 1462.2399,343.04003 1467.4399,337.84003 C 1472.6399,332.64003 1487.1999,309.76003 1477.8399,302.48003 C 1468.4799,295.20004 1452.8799,283.76004 1452.8799,283.76004 z "
+ sodipodi:nodetypes="cssccssssc"
+ id="path3167" />
+ <g
+ style="display:inline"
+ id="g3224">
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3178);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3170"
+ sodipodi:nodetypes="ccssscsccccsc"
+ d="M 1496.5599,303.00003 C 1488.7599,297.80003 1478.3599,291.04003 1478.3599,291.04003 C 1478.3599,291.04003 1486.6799,308.72003 1484.0799,318.08003 C 1481.4799,327.44003 1462.2399,346.68003 1454.4399,351.88003 C 1446.6399,357.08003 1424.2799,365.40003 1411.7999,371.12003 C 1400.2112,376.43153 1312.9999,396.60003 1312.9999,396.60003 C 1312.9999,396.60003 1409.7199,382.04003 1426.8799,376.32003 C 1444.0399,370.60003 1486.1599,356.56003 1486.1599,356.56003 L 1490.3199,358.12003 L 1492.3999,353.44003 L 1507.9999,336.80003 C 1507.9999,336.80003 1503.8399,332.12003 1501.7599,325.36003 C 1499.6799,318.60003 1496.5599,303.00003 1496.5599,303.00003 z " />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3181"
+ sodipodi:nodetypes="cssc"
+ d="M 1480.3199,293.08003 C 1484.4799,304.52003 1485.5199,319.08003 1481.3599,326.36003 C 1477.1999,333.64003 1466.2799,346.64003 1450.1599,354.96003 C 1434.0399,363.28003 1374.2399,381.22003 1350.8399,386.42003" />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3203);stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3183"
+ sodipodi:nodetypes="cssc"
+ d="M 1479.3999,292.56003 C 1483.5599,304.00003 1482.5199,319.08003 1478.3599,326.36003 C 1474.1999,333.64003 1463.2799,346.64003 1447.1599,354.96003 C 1431.0399,363.28003 1373.3199,381.22003 1349.9199,386.42003" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3237);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3205"
+ sodipodi:nodetypes="ccsccc"
+ d="M 1496.0399,302.48003 C 1495.5199,312.88003 1506.7761,338.48079 1506.7761,338.48079 C 1506.7761,338.48079 1513.7199,331.08003 1513.7199,323.80003 C 1513.7199,316.52003 1512.5646,314.59233 1512.5646,314.59233 L 1500.1999,302.48003 L 1496.0399,302.48003 z " />
+ <path
+ style="opacity:1;color:black;fill:#0e0d13;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3210"
+ d="M 1513.7199,320.68003 C 1513.7199,310.28003 1511.6399,303.52003 1507.4799,299.88003 C 1503.3199,296.24003 1485.1199,289.48003 1485.1199,289.48003 L 1502.7999,299.88003 L 1500.1999,304.04003 L 1513.7199,320.68003 z " />
+ </g>
+ <g
+ style="display:inline"
+ id="g3285">
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3275);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3273"
+ d="M 1492.1084,342.17566 C 1471.8851,336.66022 1436.5864,334.82174 1428.1294,335.55714 C 1419.6724,336.29253 1377.3874,345.11722 1375.5489,346.22031 C 1373.7104,347.32339 1365.6211,359.45734 1365.6211,359.45734 L 1350.9133,356.51578 L 1350.9133,342.54335 C 1350.9133,342.54335 1436.5864,327.46783 1442.4695,327.46783 C 1448.3526,327.46783 1494.3145,336.66022 1494.3145,336.66022 L 1492.1084,342.17566 z " />
+ <path
+ style="opacity:1;color:black;fill:#0e0d13;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3240"
+ sodipodi:nodetypes="cccssscsscc"
+ d="M 1503.3199,338.36003 C 1494.7399,333.42003 1465.6199,323.28003 1454.1799,323.28003 C 1445.3399,318.08003 1448.7199,320.68003 1448.7199,320.68003 C 1448.7199,320.68003 1427.9268,321.95005 1405.0104,325.60107 C 1379.3059,329.69629 1351.0643,336.25021 1349.1399,336.80003 C 1347.3633,337.30762 1347.0996,340.16875 1350.7559,342.96511 C 1354.5909,345.89819 1362.3999,348.76003 1362.3999,348.76003 C 1362.3999,348.76003 1381.3799,337.06003 1398.5399,334.98003 C 1415.6999,332.90003 1453.9199,329.52003 1466.3999,331.60003 C 1478.8799,333.68003 1492.9199,342.52003 1492.9199,342.52003 L 1503.3199,338.36003 z " />
+ <path
+ style="opacity:1;color:black;fill:#0e0d13;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3242"
+ sodipodi:nodetypes="cssccccsscscsc"
+ d="M 1494.4799,342.26003 C 1471.5999,334.98003 1448.7199,333.16003 1438.3199,333.68003 C 1427.9199,334.20003 1377.9999,342.52003 1374.8799,344.60003 C 1371.7599,346.68003 1364.9999,358.64003 1364.9999,358.64003 L 1353.5599,355.52003 L 1349.3999,360.20003 L 1369.1599,363.32003 C 1369.1599,363.32003 1372.7999,349.28003 1379.5599,347.72003 C 1386.3199,346.16003 1423.2399,337.32003 1430.5199,337.84003 C 1437.7999,338.36003 1448.7199,338.88003 1448.7199,338.88003 C 1448.7199,338.88003 1452.3599,342.52003 1454.9599,342.52003 C 1457.5599,342.52003 1460.6799,339.92003 1460.6799,339.92003 C 1460.6799,339.92003 1472.1199,341.48003 1475.2399,344.08003 C 1478.3599,346.68003 1493.9599,343.30003 1494.4799,342.26003 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3271);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3269"
+ d="M 1353.1195,351.73574 C 1353.8549,347.69109 1349.8102,337.39561 1346.8686,337.39561 C 1343.9271,337.39561 1343.9271,341.44026 1339.8824,341.44026 C 1335.8378,341.44026 1301.2744,344.01413 1298.3328,342.91105 C 1295.3913,341.80796 1295.3913,340.70487 1290.6112,340.70487 C 1285.8312,340.70487 1282.5219,343.27874 1281.0512,343.27874 C 1279.5804,343.27874 1280.3158,346.22031 1275.5357,346.22031 C 1270.7557,346.22031 1140.9592,356.88348 1139.1207,359.08965 C 1137.2822,361.29582 1131.3991,370.8559 1135.076,370.8559 C 1138.753,370.8559 1353.4872,352.83882 1353.1195,351.73574 z " />
+ <path
+ style="opacity:1;color:black;fill:#0e0d13;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3244"
+ d="M 1354.0799,349.80003 C 1349.9199,346.16003 1346.7999,344.60003 1340.5599,349.28003 C 1330.1599,350.84003 1300.5199,351.88003 1300.5199,351.88003 C 1300.5199,351.88003 1298.4399,348.24003 1295.3199,348.24003 C 1292.1999,348.24003 1289.0799,351.88003 1289.0799,351.88003 C 1289.0799,351.88003 1289.5999,348.24003 1285.4399,348.24003 C 1281.2799,348.24003 1275.5599,353.44003 1275.5599,353.44003 L 1136.1999,367.48003 L 1133.5999,373.72003 L 1269.8399,363.32003 L 1351.4799,357.08003 L 1354.0799,349.80003 z " />
+ <path
+ style="opacity:1;color:black;fill:#0e0d13;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3246"
+ sodipodi:nodetypes="ccssssccccssssc"
+ d="M 1428.4399,373.20003 C 1412.8399,374.24003 1387.3599,382.04003 1368.1199,380.48003 C 1305.7199,387.76003 1279.1999,392.96003 1267.7599,395.04003 C 1256.3199,397.12003 1236.5599,400.24003 1226.1599,398.16003 C 1215.7599,396.08003 1173.1199,377.36003 1163.2399,375.80003 C 1153.3599,374.24003 1136.1999,371.64003 1125.7999,371.64003 C 1115.3999,371.64003 1077.6999,363.84003 1077.6999,363.84003 L 1060.7999,370.60003 L 879.62457,366.85999 L 876.71996,377.88003 C 876.71996,377.88003 1076.3999,377.36003 1097.7199,378.92003 C 1119.0399,380.48003 1165.8399,383.08003 1177.7999,387.76003 C 1189.7599,392.44003 1219.9199,405.96003 1227.1999,405.44003 C 1234.4799,404.92003 1313.5199,395.56003 1333.2799,393.48003 C 1353.0399,391.40003 1428.9599,373.72003 1428.4399,373.20003 z " />
+ <path
+ style="opacity:1;color:black;fill:#0e0d13;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3250"
+ d="M 1060.7999,382.56003 C 1093.0399,384.64003 1140.3599,385.68003 1150.2399,390.88003 C 1160.1199,396.08003 1169.9999,404.40003 1179.8799,404.92003 C 1189.7599,405.44003 1168.9599,408.04003 1159.5999,405.44003 C 1150.2399,402.84003 1139.3199,395.56003 1130.4799,395.56003 C 1121.6399,395.56003 1077.9599,393.48003 1072.7599,390.88003 C 1067.5599,388.28003 1061.8399,382.56003 1060.7999,382.56003 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3263);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3252"
+ d="M 1447.6172,320.48162 C 1436.5864,323.05549 1417.8339,325.62936 1414.8923,325.26166 C 1411.9508,324.89397 1357.8995,337.76331 1355.6933,337.76331 C 1353.4872,337.76331 1347.9717,339.23409 1347.9717,339.23409 L 1346.1333,334.82174 C 1346.1333,334.82174 1348.7071,331.14479 1352.0164,330.4094 C 1355.3256,329.67401 1398.7137,317.54006 1401.6553,317.54006 C 1404.5968,317.54006 1442.1018,314.59849 1442.1018,314.59849 L 1447.6172,320.48162 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3267);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3265"
+ d="M 1446.8818,320.11392 L 1451.2942,324.15858 C 1451.2942,324.15858 1473.7236,327.83553 1482.5483,330.0417 C 1491.373,332.24788 1503.8746,339.23409 1503.8746,339.23409 L 1506.8162,335.92483 C 1506.8162,335.92483 1482.5483,327.10014 1476.2975,325.99705 C 1470.0466,324.89397 1457.1773,322.68779 1453.868,321.58471 C 1450.5588,320.48162 1446.8818,319.37853 1446.8818,320.11392 z " />
+ <path
+ style="opacity:1;color:black;fill:#0e0d13;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3277"
+ d="M 1458.0799,343.56003 C 1446.6399,345.12003 1421.6799,346.68003 1421.6799,346.68003 L 1411.2799,338.36003 C 1411.2799,338.36003 1383.1999,342.00003 1377.4799,344.60003 C 1371.7599,347.20003 1353.5599,355.52003 1353.5599,355.52003 L 1347.8399,360.72003 L 1333.2799,360.72003 L 1327.5599,365.40003 L 1295.3199,367.48003 L 1298.4399,357.08003 L 1267.2399,360.20003 L 1280.2399,375.28003 L 1330.1599,370.60003 C 1330.1599,370.60003 1329.6399,374.24003 1333.7999,374.76003 C 1337.9599,375.28003 1350.9599,374.24003 1356.1599,374.24003 C 1361.3599,374.24003 1405.0399,366.96003 1410.7599,366.44003 C 1416.4799,365.92003 1457.0399,345.64003 1458.0799,343.56003 z " />
+ <path
+ style="opacity:1;color:black;fill:#0e0d13;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3279"
+ d="M 1188.1999,370.08003 C 1203.2799,370.60003 1250.0799,375.28003 1254.2399,377.36003 C 1258.3999,379.44003 1259.4399,388.28003 1259.4399,388.28003 C 1259.4399,388.28003 1228.7599,395.04003 1221.9999,393.48003 C 1215.2399,391.92003 1155.4399,371.12003 1155.4399,371.12003 L 1188.1999,370.08003 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3283);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3281"
+ sodipodi:nodetypes="cccccssscccccc"
+ d="M 1132.5022,366.44356 C 1119.2651,364.97278 1088.3787,362.7666 1088.3787,362.7666 L 1081.0248,356.88348 L 1066.317,357.61887 L 1060.4338,362.03121 C 1060.4338,362.03121 939.09433,359.08965 916.29721,359.08965 C 893.50009,359.08965 884.67539,359.08965 882.46922,362.03121 C 880.26305,364.97277 876.58609,368.64973 880.26305,370.12051 C 883.94,371.5913 1064.1108,370.85591 1064.1108,370.85591 L 1072.2001,367.17895 L 1084.7017,367.17895 L 1090.5849,370.85591 L 1137.6499,373.79747 L 1132.5022,366.44356 z " />
+ </g>
+ <path
+ style="color:black;fill:url(#linearGradient3411);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1496.5599,904.12001 L 1491.3599,853.68001 L 1246.9599,905.16001 L 1323.9199,940.52 L 1496.5599,904.12001 z "
+ id="path3288" />
+ <path
+ style="color:black;fill:#100f15;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1522.0399,780.88001 L 1473.1599,889.04001 C 1473.1599,889.04001 1336.3999,917.12 1323.9199,917.12 C 1311.4399,917.12 1270.3599,914 1270.3599,914 L 1230.8399,901.00001 L 1309.8799,774.64001 L 1522.0399,780.88001 z "
+ sodipodi:nodetypes="ccscccc"
+ id="path3202" />
+ <path
+ style="color:black;fill:url(#linearGradient3407);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1810.1199,713.80001 L 1766.4399,762.68001 L 1784.6399,779.32001 L 1832.4799,730.96001 L 1832.4799,720.56001 L 1810.1199,713.80001 z "
+ id="path3217" />
+ <path
+ style="color:black;fill:url(#linearGradient3404);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1825.7199,688.32002 C 1831.9599,698.20002 1832.4799,726.28001 1830.9199,730.96001 C 1829.3599,735.64001 1810.1199,719.00001 1810.1199,719.00001 L 1825.7199,688.32002 z "
+ sodipodi:nodetypes="cscc"
+ id="path3206" />
+ <path
+ style="color:black;fill:#222537;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1549.0799,777.24001 L 1522.5599,846.40001 L 1484.5999,859.92001 L 1521.5199,778.80001 L 1549.0799,777.24001 z "
+ sodipodi:nodetypes="ccccc"
+ id="path3284" />
+ <path
+ style="color:black;fill:url(#linearGradient3400);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1754.9999,751.76001 L 1784.6399,779.32001 C 1784.6399,779.32001 1732.1199,817.28001 1717.5599,825.60001 C 1702.9999,833.92001 1599.5199,879.68001 1594.3199,881.24001 C 1589.1199,882.80001 1496.0399,908.80001 1496.0399,908.80001 L 1489.7999,857.84001 L 1520.9999,847.44001 C 1520.9999,847.44001 1545.9599,869.80001 1555.8399,866.68001 L 1748.2399,781.92001 C 1756.0399,777.24001 1754.9999,751.76001 1754.9999,751.76001 z "
+ sodipodi:nodetypes="ccsscccccc"
+ id="path3230" />
+ <path
+ id="path3258"
+ d="M 1754.4799,760.60916 C 1754.4799,760.60916 1750.3199,779.84916 1749.2799,784.52916 C 1748.2399,789.20916 1744.5999,793.36916 1736.2799,797.52916 C 1727.9599,801.68916 1569.8799,872.40916 1562.0799,872.92916 C 1554.2799,873.44916 1545.9599,875.52916 1542.3199,871.88916 C 1538.6799,868.24916 1520.9999,855.76916 1520.9999,855.76916 L 1754.4799,760.60916 z "
+ style="opacity:0.91739131;color:black;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4914)"
+ transform="matrix(1.041323,0,0,1.079015,-62.85208,-69.7474)" />
+ <path
+ style="color:black;fill:#100f15;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1857.9599,591.60002 C 1855.8799,607.20002 1834.0399,665.96002 1831.4399,673.24002 C 1828.8399,680.52002 1814.7999,717.44001 1814.7999,717.44001 C 1814.7999,717.44001 1786.1999,751.76001 1767.4799,763.72001 C 1750.8399,753.84001 1754.9999,752.80001 1754.9999,752.80001 L 1761.7599,693.52002 L 1857.9599,591.60002 z "
+ sodipodi:nodetypes="csccccc"
+ id="path3204" />
+ <path
+ style="color:black;fill:url(#linearGradient3415);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1546.4799,775.68001 L 1518.3999,846.40001 L 1550.6399,870.32001 L 1752.3999,779.84001 L 1763.3199,708.60001 L 1759.1599,696.12002 L 1554.2799,776.20001 L 1546.4799,775.68001 z "
+ sodipodi:nodetypes="cccccccc"
+ id="path3286" />
+ <path
+ style="opacity:1;color:black;fill:#12131d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1544.3999,780.88001 L 1517.8799,845.88001 L 1551.6799,870.32001 L 1559.9999,770.48001 L 1544.3999,780.88001 z "
+ id="path3413" />
+ <path
+ style="color:black;fill:url(#linearGradient3389);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3312"
+ sodipodi:nodetypes="cscccsccccsscssscsccc"
+ d="M 1858.6807,580.60395 C 1837.9278,610.87868 1786.4399,665.88722 1691.4855,696.1918 C 1596.5312,726.49637 1397.8652,764.63354 1301.9007,768.67415 C 1219.0682,897.97367 1221.2744,896.78169 1211.1729,915.97459 C 1316.2288,954.3604 1284.3241,945.63264 1323.2998,949.3096 C 1323.2998,949.3096 1583.9192,910.92383 1679.8837,852.33498 C 1775.8482,793.74613 1799.0817,779.604 1833.4269,733.13698 C 1833.4269,694.75119 1827.1801,679.50192 1827.1801,679.50192 L 1824.7921,686.2053 C 1824.7921,686.2053 1831.4066,702.83241 1829.3863,730.10652 C 1785.9497,777.58369 1782.9192,788.69537 1670.7923,845.26391 C 1558.6654,901.83246 1338.8092,931.7186 1328.7077,932.7288 C 1318.6062,933.7389 1245.5181,900.8223 1245.5181,900.8223 C 1245.5181,900.8223 1238.447,895.77154 1245.5181,885.67002 C 1252.5892,875.56849 1305.1171,796.77659 1307.1374,791.72583 C 1309.1577,786.67507 1315.2186,780.61415 1326.3303,781.6243 C 1337.442,782.63446 1540.4826,781.6243 1540.4826,781.6243 C 1540.4826,781.6243 1650.5893,756.37049 1693.0157,736.16744 C 1735.4421,715.96439 1780.8989,689.70042 1780.8989,689.70042 C 1780.8989,689.70042 1850.5995,607.87807 1857.6705,596.76639 C 1861.7111,580.60395 1858.6807,581.6141 1858.6807,580.60395 z " />
+ <path
+ style="color:black;fill:url(#linearGradient3380);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1543.3599,863.04001 L 1520.9999,846.40001 L 1486.1599,857.84001 L 1472.6399,887.48001 L 1543.3599,863.04001 z "
+ sodipodi:nodetypes="ccccc"
+ id="path3274" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3367);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1753.4399,718.48001 L 1745.1199,773.60001 L 1580.7999,844.32001 L 1589.1199,781.92001 L 1753.4399,718.48001 z "
+ id="path3358" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3377);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3369"
+ sodipodi:nodetypes="ccccc"
+ d="M 1574.0045,786.13598 L 1566.4199,850.81607 L 1580.7999,844.32001 L 1589.1199,781.92001 L 1574.0045,786.13598 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3425);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1489.9022,861.36171 C 1489.9022,861.36171 1499.4623,899.60205 1492.1084,903.279 C 1484.7545,906.95596 1531.0841,892.98353 1531.0841,892.98353 L 1509.0224,856.21398 L 1489.9022,861.36171 z "
+ id="path3417" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3481);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1473.6799,292.60003 C 1477.3199,290.52003 1480.4399,291.56003 1483.5599,293.64003 C 1486.6799,295.72003 1494.9999,301.96003 1494.9999,301.96003 L 1504.3599,301.44003 C 1504.3599,301.44003 1397.7599,232.80004 1388.3999,227.60004 C 1379.0399,222.40004 1286.9999,166.76004 1278.1599,162.60004 C 1269.3199,158.44004 1186.1199,116.62465 1176.7599,112.46465 C 1167.3999,108.30465 1129.6021,95.514632 1129.6021,95.514632 C 1129.6021,95.514632 1214.7199,132.44004 1225.1199,138.16004 C 1235.5199,143.88004 1319.7599,190.68004 1329.1199,195.88004 C 1338.4799,201.08004 1413.3599,251.00004 1420.6399,255.68004 C 1427.9199,260.36004 1473.6799,292.60003 1473.6799,292.60003 z "
+ sodipodi:nodetypes="csccssscsssc"
+ id="path3471" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3489);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1475.2399,292.08003 C 1474.7199,294.68003 1477.3199,303.00003 1477.3199,303.00003 C 1477.3199,303.00003 1426.8799,266.08004 1417.5199,258.28004 C 1408.1599,250.48004 1293.6299,180.02004 1283.2299,173.26004 C 1272.8299,166.50004 1172.1872,114.82406 1127.8799,95.52004 C 1142.3701,100.02183 1173.5183,113.47569 1189.4237,120.63234 C 1216.9739,133.02854 1299.7457,177.23751 1351.8476,210.07234 C 1362.9509,217.06966 1475.7599,292.60003 1475.2399,292.08003 z "
+ sodipodi:nodetypes="ccsscssc"
+ id="path3473" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3501);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1485.6399,294.68003 L 1495.5199,302.74003 L 1501.7599,305.34003 L 1505.3999,300.66003 L 1488.4999,290.52003 L 1485.6399,294.68003 z "
+ id="path3493" />
+ <g
+ id="g3524">
+ <path
+ style="color:black;fill:url(#linearGradient3510);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3430"
+ d="M 1324.4399,188.60004 C 1332.2399,183.92004 1338.4799,184.96004 1343.6799,186.00004 C 1348.8799,187.04004 1367.5999,198.48004 1371.7599,203.16004 C 1375.9199,207.84004 1379.0399,214.08004 1377.9999,216.68004 C 1376.9599,219.28004 1376.4399,220.32004 1376.4399,220.32004 L 1324.4399,188.60004 z " />
+ <path
+ style="color:black;fill:url(#linearGradient3507);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3440"
+ sodipodi:nodetypes="cccscc"
+ d="M 1363.4399,212.52004 C 1358.7599,202.12004 1350.6999,189.38004 1340.5599,185.22004 C 1347.0599,186.00004 1346.7999,186.52004 1350.6999,189.12004 C 1350.6999,189.12004 1368.3799,204.20004 1371.4999,209.40004 C 1374.6199,214.60004 1375.9199,219.80004 1375.9199,219.80004 L 1363.4399,212.52004 z " />
+ <path
+ style="color:black;fill:url(#linearGradient3504);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1324.4399,188.60004 C 1332.2399,183.92004 1338.4799,184.96004 1343.6799,186.00004 C 1348.8799,187.04004 1367.5999,198.48004 1371.7599,203.16004 C 1375.9199,207.84004 1379.0399,214.08004 1377.9999,216.68004 C 1376.9599,219.28004 1376.4399,220.32004 1376.4399,220.32004 L 1324.4399,188.60004 z "
+ id="path3450" />
+ <path
+ style="color:black;fill:url(#linearGradient3522);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3520"
+ d="M 1324.4399,188.60004 C 1332.2399,183.92004 1338.4799,184.96004 1343.6799,186.00004 C 1348.8799,187.04004 1367.5999,198.48004 1371.7599,203.16004 C 1375.9199,207.84004 1379.0399,214.08004 1377.9999,216.68004 C 1376.9599,219.28004 1376.4399,220.32004 1376.4399,220.32004 L 1324.4399,188.60004 z " />
+ </g>
+ <g
+ style="opacity:1;display:inline"
+ id="g3610"
+ transform="translate(50,0)">
+ <path
+ style="opacity:1;color:black;fill:#1d1a2f;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 1595.9588,373.84137 L 1589.4953,350.56353 C 1643.1377,389.45686 1723.127,460.2671 1777.626,533.33599 C 1777.1209,533.84106 1765.4843,556.84949 1755.4026,568.31252 C 1755.4026,568.31252 1697.0302,458.84137 1595.9588,373.84137 z "
+ sodipodi:nodetypes="cccsc"
+ id="path3600" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3618);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3543"
+ d="M 1713.0313,458.53125 L 1696.1875,479.59375 C 1713.2501,501.66495 1726.8181,521.63941 1736.6563,537.03125 L 1758.1563,508.59375 C 1743.9913,491.44477 1728.7149,474.64744 1713.0313,458.53125 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3620);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path3530"
+ d="M 1628.4063,380.71875 L 1626.375,401.28125 C 1658.3763,432.14635 1684.9703,464.2647 1705.5625,492 C 1713.2991,496.18976 1722.4132,500.14931 1725.2188,497.34375 C 1727.8055,494.75703 1729.459,485.49122 1730.4688,476.90625 C 1697.2378,440.8052 1660.8438,407.36778 1628.4063,380.71875 z " />
+ <path
+ style="opacity:1;color:black;fill:#506485;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3622);stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path3564"
+ d="M 1625.9561,398.80076 L 1626.6915,381.88677 L 1594.3343,369.38512 L 1625.9561,398.80076 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3624);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path3590"
+ d="M 1624.9999,382.56003 L 1611.9999,385.68003 L 1596.3999,371.12003 L 1624.9999,382.56003 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3626);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path3606"
+ d="M 1587.4799,349.28003 L 1594.2399,366.96003 L 1631.1599,385.16003 C 1631.1599,385.16003 1604.1199,361.24003 1587.4799,349.28003 z " />
+ </g>
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#292531;stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ d="M 306.65805,271.57812 C 338.27987,287.75672 358.59115,294.40654 356.84849,308.34767 C 356.1131,314.2308 353.90692,320.11393 353.90692,320.11393"
+ sodipodi:nodetypes="csc"
+ id="path3647" />
+ <path
+ style="opacity:1;color:black;fill:url(#radialGradient3672);fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient3670);stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path3649"
+ sodipodi:nodetypes="ccscc"
+ d="M 295.99489,293.27215 L 304.45188,272.68121 C 336.0737,288.85981 357.12037,293.67115 355.37771,307.61228 C 354.64232,313.49541 352.43614,318.64315 352.43614,318.64315 L 352.2523,318.27545" />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.49342107;visibility:visible;display:inline;overflow:visible"
+ d="M 883.88348,393.72573 C 882.87332,405.84756 881.86317,415.94908 881.86317,415.94908 C 881.86317,415.94908 881.86317,424.0303 893.985,431.10137 C 906.10683,438.17244 970.48587,471.41454 977.55694,475.45515"
+ id="path2850"
+ sodipodi:nodetypes="ccss" />
+ <path
+ sodipodi:nodetypes="ccss"
+ id="path3737"
+ d="M 886.51578,393.35803 C 885.50562,405.47986 884.12778,415.21369 884.12778,415.21369 C 884.12778,415.21369 882.657,421.82413 894.77883,428.8952 C 906.90066,435.96627 972.38278,469.94376 979.45385,473.98437"
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient3753);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ style="opacity:1;color:black;fill:#7b6c69;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible;filter:url(#filter4382)"
+ id="path3424"
+ d="M 796.91629,519.29625 C 774.88799,519.36309 755.14159,533.70664 744.29124,552.17125 C 726.5769,581.5909 721.62479,616.57722 720.32249,650.3275 C 729.55311,601.29909 739.33496,539.6491 808.55376,547.80836 C 884.45036,556.75478 912.62913,637.71705 929.38499,695.9525 C 926.38479,643.06364 906.55029,589.39343 867.07249,552.73375 C 849.07199,536.47244 827.32319,521.73935 802.57249,519.3275 C 800.68969,519.23667 798.80019,519.24332 796.91629,519.29625 z "
+ sodipodi:nodetypes="cccscccc"
+ transform="matrix(1,0,-6.65908e-2,0.916762,36.4609,43.22222)" />
+ <path
+ sodipodi:nodetypes="cccscccc"
+ d="M 143.30141,264.49705 C 121.27311,264.56389 101.52671,278.90744 90.676363,297.37205 C 72.962023,326.7917 68.009913,361.77802 66.707613,395.5283 C 75.938233,346.49989 85.720083,284.8499 154.93888,293.00916 C 230.83548,301.95558 259.01425,382.91785 275.77011,441.1533 C 272.76991,388.26444 252.93541,334.59423 213.45761,297.93455 C 195.45711,281.67324 173.70831,266.94015 148.95761,264.5283 C 147.07481,264.43747 145.18531,264.44412 143.30141,264.49705 z "
+ id="path4386"
+ style="opacity:1;color:black;fill:#7b6c69;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible;filter:url(#filter4382)"
+ transform="matrix(0.514575,0,0,0.941733,38.26461,25.70466)" />
+ <g
+ style="display:inline"
+ id="g3061">
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2891);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4026"
+ d="M 790.94698,540.19833 C 754.72619,540.71825 728.95453,571.11018 717.7422,605.83687 C 697.98987,666.7463 708.92894,743.88739 745.26374,805.52032 C 765.90842,840.20434 798.62328,871.23818 834.78799,874.8156 C 868.48817,878.5734 895.99243,855.5754 909.73018,825.72918 C 935.97225,768.86578 929.36771,692.18826 898.79143,628.21685 C 880.06413,589.66458 848.74089,552.44694 810.32088,542.48845 C 803.85764,540.79759 797.31924,540.03971 790.94698,540.19833 z " />
+ <path
+ transform="matrix(1.217408,0,0.203141,1.378897,-309.8841,-217.4311)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3617);stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4028"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <g
+ style="opacity:1;display:inline"
+ id="g4030">
+ <path
+ transform="matrix(0.35769,0,5.968548e-2,0.41765,475.067,327.4519)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3623);stroke-width:7.03952456;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4032"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.371116,0,6.192573e-2,0.433082,529.996,396.8886)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3627);stroke-width:6.7867713;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4034"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.371116,0,6.192573e-2,0.433082,513.8174,509.4034)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3631);stroke-width:6.7867713;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4036"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.357317,0,5.96232e-2,0.417221,453.5199,501.9763)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3635);stroke-width:7.04681969;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4038"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.357317,0,5.96232e-2,0.407962,423.3689,392.3642)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3640);stroke-width:7.12633991;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4040"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3854);stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ d="M 767.59375,566.59375 C 753.99813,573.75695 742.77156,586.59663 734.65625,603.46875 C 737.57614,604.76217 740.53964,605.46875 743.53125,605.46875 C 758.20373,605.46875 768.01733,588.76484 767.59375,566.59375 z "
+ id="path4042" />
+ <path
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3856);stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ d="M 839.125,576.96875 C 839.15658,577.19851 839.18506,577.42573 839.21875,577.65625 C 843.13967,604.48448 859.90323,626.28126 876.65625,626.28125 C 877.93248,626.28125 879.17587,626.12033 880.375,625.875 C 868.75343,605.36177 854.56788,588.48788 839.125,576.96875 z "
+ id="path4044" />
+ <path
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3852);stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ d="M 721.78125,701.65625 C 722.05446,703.99289 722.37332,706.35522 722.71875,708.71875 C 725.81891,729.93104 731.5407,750.08353 739.21875,768.34375 C 742.24009,760.7239 743.30883,750.78622 741.71875,739.90625 C 739.29936,723.35199 731.3693,708.97479 721.78125,701.65625 z "
+ id="path4046" />
+ <path
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3858);stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ d="M 910.75,739.40625 C 898.12259,744.48579 890.98865,763.76215 894.34375,786.71875 C 895.35456,793.63507 897.21958,800.19825 899.71875,806.15625 C 907.15716,787.43227 911.12123,764.58884 910.75,739.40625 z "
+ id="path4048" />
+ <path
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3860);stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ d="M 817.75,834.8125 C 810.39953,834.8125 804.26586,839.02904 800.03125,846 C 812.03051,853.2674 824.61494,857.25 837.1875,857.25 C 840.25793,857.25 843.26165,857.03003 846.1875,856.5625 C 838.83437,843.46461 828.30177,834.81252 817.75,834.8125 z "
+ id="path4050" />
+ </g>
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2876);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:7.03952456;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4052"
+ d="M 798.0625,557.90625 C 781.29199,557.90625 770.85622,580.19093 774.78125,607.65625 C 778.70626,635.12159 795.51073,657.40627 812.28125,657.40625 C 815.04721,657.40625 817.64641,656.79216 820.03125,655.65625 C 806.31614,649.90032 794.0582,630.58677 790.78125,607.65625 C 787.50389,584.72301 794.23982,565.40964 806.3125,559.65625 C 803.59909,558.51703 800.83263,557.90625 798.0625,557.90625 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2873);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6.7867713;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4054"
+ d="M 865.15625,635.84375 C 847.75626,635.84375 836.92769,658.95733 841,687.4375 C 845.07234,715.91767 862.50626,739.03127 879.90625,739.03125 C 882.67354,739.03125 885.2554,738.44165 887.65625,737.34375 C 873.29529,731.54594 860.4258,711.3961 857,687.4375 C 853.57535,663.48681 860.67997,643.33663 873.375,637.53125 C 870.66474,636.43706 867.91871,635.84375 865.15625,635.84375 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2870);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6.7867713;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4056"
+ d="M 848.96875,748.375 C 831.56876,748.375 820.74018,771.48861 824.8125,799.96875 C 828.88484,828.44892 846.31875,851.56249 863.71875,851.5625 C 866.48647,851.5625 869.09884,850.97322 871.5,849.875 C 857.1387,844.07762 844.23837,823.92781 840.8125,799.96875 C 837.38805,776.01954 844.49392,755.86928 857.1875,750.0625 C 854.47724,748.96831 851.73121,748.375 848.96875,748.375 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2867);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:7.04681969;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4058"
+ sodipodi:nodetypes="csscscc"
+ d="M 776.15625,732.1875 C 759.40323,732.1875 749.01657,754.43791 752.9375,781.875 C 756.85842,809.31212 773.62199,831.59376 790.375,831.59375 C 793.13807,831.59375 803.09656,825.83075 805.47891,824.69601 C 791.77811,818.94599 772.21103,804.78197 768.9375,781.875 C 765.66587,758.98143 772.36213,739.69998 784.40625,733.9375 C 781.69566,732.79945 778.92349,732.1875 776.15625,732.1875 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2864);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:7.12633991;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4060"
+ d="M 746.03125,617.46875 C 729.27823,617.46875 718.86032,639.23429 722.78125,666.0625 C 726.70217,692.89074 743.46574,714.65622 760.21875,714.65625 C 762.98318,714.65625 765.58543,714.04811 767.96875,712.9375 C 754.26931,707.31337 742.05452,688.45929 738.78125,666.0625 C 735.50732,643.66123 742.22116,624.80743 754.28125,619.1875 C 751.5647,618.06976 748.80485,617.46875 746.03125,617.46875 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2861);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4062"
+ d="M 766.59375,566.59375 C 752.99813,573.75695 741.77156,586.59663 733.65625,603.46875 C 736.57614,604.76217 739.53964,605.46875 742.53125,605.46875 C 745.30699,605.46875 747.92096,604.86955 750.3125,603.75 C 750.09302,603.65965 749.87524,603.56576 749.65625,603.46875 C 754.06535,594.30202 759.40441,586.33496 765.53125,579.8125 C 766.30565,575.72087 766.68328,571.27999 766.59375,566.59375 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2858);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4064"
+ d="M 838.125,576.96875 C 838.15658,577.19851 838.18506,577.42573 838.21875,577.65625 C 842.13967,604.48448 858.90323,626.28126 875.65625,626.28125 C 876.93248,626.28125 878.17587,626.12033 879.375,625.875 C 878.26443,623.91474 877.125,621.98605 875.96875,620.09375 C 869.58799,615.02694 863.91172,607.14937 859.84375,597.65625 C 853.01371,589.60687 845.71836,582.63277 838.125,576.96875 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2855);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4066"
+ d="M 720.78125,701.65625 C 721.05446,703.99289 721.37332,706.35522 721.71875,708.71875 C 724.81891,729.93104 730.5407,750.08353 738.21875,768.34375 C 741.24009,760.7239 742.30883,750.78622 740.71875,739.90625 C 738.29936,723.35199 730.3693,708.97479 720.78125,701.65625 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2851);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4068"
+ d="M 816.75,834.8125 C 809.39953,834.8125 803.26586,839.02904 799.03125,846 C 811.03051,853.2674 823.61494,857.25 836.1875,857.25 C 838.90063,857.25 841.555,857.08129 844.15625,856.71875 C 834.27818,855.40873 824.47543,851.7199 815.03125,846 C 817.6641,841.66583 821.03164,838.38446 824.96875,836.53125 C 822.27037,835.42464 819.50739,834.81251 816.75,834.8125 z " />
+ <g
+ clip-path="url(#clipPath3833)"
+ style="opacity:1;display:inline"
+ id="g4084"
+ transform="translate(-160.08,-6.92)">
+ <path
+ transform="matrix(1.182067,0,0.197245,1.342882,-116.3514,-181.2832)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="color:black;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.50316167;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4086"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.728694,0,0.121593,0.827829,330.3581,158.0236)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="color:black;fill:url(#linearGradient3823);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.50316167;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4088"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.399961,0,6.673916e-2,0.454373,634.653,408.5734)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="color:black;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.50316167;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4090"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(5.083673e-2,0,8.482827e-3,5.775273e-2,992.1429,635.1441)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="color:black;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.50316167;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4092"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.728694,0,0.121593,0.827829,333.4781,155.9436)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="color:black;fill:url(#radialGradient3825);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.50316167;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4094"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.245003,0,4.088223e-2,0.278334,778.0912,526.6771)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="color:black;fill:url(#linearGradient3827);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.50316167;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4096"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ </g>
+ <g
+ style="opacity:1;display:inline"
+ id="g4070">
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient3711);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 766.46875,579.125 L 745.6875,604.09375 L 746.34375,605.25 C 756.58142,603.68632 764.04784,593.60291 766.625,579.375 L 766.46875,579.125 z M 775.03125,593.09375 C 774.82821,597.70319 775.05675,602.58655 775.78125,607.65625 C 779.70626,635.12159 796.51072,657.40626 813.28125,657.40625 C 813.63747,657.40625 813.99333,657.39495 814.34375,657.375 L 775.03125,593.09375 z M 844.75,597.4375 C 850.54334,611.07565 859.64242,621.40204 869.40625,624.9375 L 869.4375,624.875 L 844.75,597.4375 z M 836.8125,609.8125 L 824.53125,653.5 C 834.01028,646.20806 839.11131,629.48445 836.8125,609.8125 z M 754.0625,618.71875 L 785.1875,673 C 785.0588,670.73508 784.81279,668.41655 784.46875,666.0625 C 781.10031,643.01452 768.24142,623.70504 754.0625,618.71875 z M 865.71875,635.875 C 848.57591,636.25991 837.96199,659.19725 842,687.4375 C 846.07233,715.91767 863.50626,739.03127 880.90625,739.03125 C 884.96968,739.03125 888.66667,737.76385 891.90625,735.46875 L 844.75,697.90625 L 844.46875,698.71875 L 844.46875,697.6875 L 844.75,697.90625 L 865.71875,635.875 z M 783.1875,693.46875 L 744.3125,707.5 C 749.59407,712.04565 755.40496,714.65624 761.21875,714.65625 C 771.62157,714.65625 779.58739,706.25677 783.1875,693.46875 z M 731.34375,712.15625 L 731.125,712.25 L 741.53125,755.90625 L 742.15625,755.71875 C 742.64506,750.81799 742.53466,745.48907 741.71875,739.90625 C 740.17452,729.3401 736.3762,719.67921 731.34375,712.15625 z M 777.15625,732.1875 C 767.34788,732.1875 759.73316,739.822 755.875,751.65625 L 794.75,740.125 C 789.29318,735.10731 783.21605,732.1875 777.15625,732.1875 z M 849.96875,748.375 C 846.5652,748.375 843.43136,749.27029 840.59375,750.90625 L 881.5625,775.46875 C 873.92485,759.33771 861.95309,748.375 849.96875,748.375 z M 840.28125,751.09375 C 828.81261,757.98705 822.56628,777.26606 825.8125,799.96875 C 827.20724,809.72295 830.19739,818.84266 834.1875,826.625 L 840.28125,751.09375 z M 898.78125,751.21875 C 895.36157,757.78637 893.46241,766.41429 893.53125,776.125 L 898.78125,751.21875 z M 807.5625,758.21875 L 806.03125,824.46875 C 813.58502,815.76206 817.20471,799.9269 814.625,781.875 C 813.40117,773.31113 810.89987,765.25546 807.5625,758.21875 z "
+ id="path4072" />
+ <path
+ style="opacity:1;color:black;fill:#7d86a4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 840.10457,750.72001 L 834.07996,825.60001 L 847.07996,821.96001 L 852.21687,757.48001 L 840.10457,750.72001 z "
+ sodipodi:nodetypes="ccccc"
+ id="path4074" />
+ <path
+ style="opacity:1;color:black;fill:#5e6787;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 865.27996,635.80002 L 844.47996,696.64002 L 857.99996,693.52002 L 878.27996,640.48002 C 878.27996,640.48002 871.51996,636.32002 865.27996,635.80002 z "
+ id="path4076" />
+ <path
+ style="opacity:1;color:black;fill:#dadee2;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 844.47996,696.12002 L 857.99996,694.56002 L 899.59996,724.20001 C 899.59996,724.20001 895.43996,732.00001 891.79996,735.12001 C 847.07996,699.76002 844.47996,697.16002 844.47996,696.12002 z "
+ id="path4078" />
+ <path
+ style="opacity:1;color:black;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 775.31996,592.64002 L 790.39996,588.48002 L 825.23996,650.88002 C 825.23996,650.88002 822.36762,656.89703 813.24719,656.28749 C 806.00627,647.65603 789.21488,610.71836 775.31996,592.64002 z "
+ sodipodi:nodetypes="ccccc"
+ id="path4080" />
+ </g>
+ <path
+ style="opacity:1;color:black;fill:#d8dbe4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72083974;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4082"
+ sodipodi:nodetypes="ccc"
+ d="M 767.57222,770.53227 C 766.71066,794.14766 786.67074,822.30157 806.43074,823.34157 C 782.51074,795.26157 770.69222,780.93227 767.57222,770.53227 z " />
+ <path
+ transform="matrix(0.31032,0,5.178125e-2,0.352536,530.9291,471.175)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="opacity:1;color:black;fill:url(#radialGradient3777);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3769);stroke-width:8.22614479;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4098"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2833);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:8.22614479;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4100"
+ d="M 812,665.6875 C 797.45046,665.6875 788.40727,684.50414 791.8125,707.6875 C 795.21772,730.87083 809.7942,749.68749 824.34375,749.6875 C 827.69586,749.6875 830.75473,748.66455 833.4375,746.84375 C 822.68304,740.76704 813.43435,725.53755 810.8125,707.6875 C 808.19259,689.85074 812.94987,674.6171 821.90625,668.53125 C 818.69301,666.71563 815.34709,665.68751 812,665.6875 z " />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2830);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4102"
+ d="M 909.75,739.40625 C 897.12259,744.48579 889.98865,763.76215 893.34375,786.71875 C 894.35456,793.63507 896.21958,800.19825 898.71875,806.15625 C 906.15716,787.43227 910.12123,764.58884 909.75,739.40625 z " />
+ <g
+ style="opacity:1;display:inline"
+ id="g4104">
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3947);stroke-width:2.4000001;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4106"
+ sodipodi:nodetypes="css"
+ d="M 829.88877,749.94997 C 820.63051,755.49288 804.26228,742.54343 797.53157,728.25594 C 792.49647,717.56778 789.07457,708.40038 791.64844,693.32487" />
+ <path
+ style="color:black;fill:url(#linearGradient3925);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72083974;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 810.4009,701.04647 C 801.57621,704.72343 800.10543,704.72343 794.95769,707.66499 C 789.80995,710.60655 789.80995,721.63742 796.42847,721.63742 C 803.04699,721.63742 815.54864,719.43125 815.54864,719.43125 L 810.4009,701.04647 z "
+ id="path4108" />
+ <path
+ style="color:black;fill:url(#linearGradient3921);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72083974;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 830.02351,739.91505 C 823.16897,743.59338 821.77819,743.9134 818.10255,746.44005 C 814.42692,748.96669 817.33727,752.55142 823.59578,751.11135 C 829.85428,749.67129 835.19183,745.24622 835.19183,745.24622 L 830.02351,739.91505 z "
+ sodipodi:nodetypes="csscc"
+ id="path4110" />
+ <path
+ style="color:black;fill:url(#linearGradient3917);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72083974;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4112"
+ sodipodi:nodetypes="csscc"
+ d="M 813.74521,665.86114 C 803.60732,668.8815 806.88154,665.8265 800.68324,668.24278 C 794.48494,670.65906 790.54534,679.72013 797.16386,679.72013 C 803.78238,679.72013 817.07195,677.90792 817.07195,677.90792 L 813.74521,665.86114 z " />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3943);stroke-width:2.4000001;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 835.7719,738.18372 C 824.37333,732.30059 814.44556,726.78516 811.87169,710.23886 C 809.29782,693.69257 811.1363,685.23557 813.34247,679.72014 C 815.54864,674.2047 815.91634,674.2047 815.91634,674.2047"
+ id="path4114" />
+ <g
+ clip-path="url(#clipPath3932)"
+ id="g4116">
+ <path
+ transform="matrix(0.846668,0.225827,0,0.854372,123.8091,-80.38611)"
+ sodipodi:cy="710.97424"
+ sodipodi:type="arc"
+ sodipodi:cx="814.44556"
+ style="color:black;fill:#9faec6;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:3.19906235;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.51315792;visibility:visible;display:inline;overflow:visible"
+ id="path4118"
+ sodipodi:rx="6.9862146"
+ d="M 821.43177 710.97424 A 6.9862146 9.9277792 0 1 1 807.45934,710.97424 A 6.9862146 9.9277792 0 1 1 821.43177 710.97424 z"
+ sodipodi:ry="9.9277792" />
+ <path
+ transform="matrix(0.846668,0.225827,0,0.854372,146.6062,-53.17664)"
+ sodipodi:cy="710.97424"
+ sodipodi:type="arc"
+ sodipodi:cx="814.44556"
+ style="color:black;fill:#9faec6;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:3.19906235;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.51315792;visibility:visible;display:inline;overflow:visible"
+ id="path4120"
+ sodipodi:rx="6.9862146"
+ d="M 821.43177 710.97424 A 6.9862146 9.9277792 0 1 1 807.45934,710.97424 A 6.9862146 9.9277792 0 1 1 821.43177 710.97424 z"
+ sodipodi:ry="9.9277792" />
+ <path
+ transform="matrix(0.846668,0.225827,0,0.854372,129.6922,-117.891)"
+ sodipodi:cy="710.97424"
+ sodipodi:type="arc"
+ sodipodi:cx="814.44556"
+ style="color:black;fill:#9faec6;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:3.19906235;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.51315792;visibility:visible;display:inline;overflow:visible"
+ id="path4122"
+ sodipodi:rx="6.9862146"
+ d="M 821.43177 710.97424 A 6.9862146 9.9277792 0 1 1 807.45934,710.97424 A 6.9862146 9.9277792 0 1 1 821.43177 710.97424 z"
+ sodipodi:ry="9.9277792" />
+ </g>
+ <path
+ transform="matrix(1.478247,0.384378,0,1.454217,-369.2512,-643.1703)"
+ sodipodi:cy="710.97424"
+ sodipodi:type="arc"
+ sodipodi:cx="814.44556"
+ style="color:black;fill:#263141;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3912);stroke-width:0.68204319;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4124"
+ sodipodi:rx="6.9862146"
+ d="M 821.43177 710.97424 A 6.9862146 9.9277792 0 1 1 807.45934,710.97424 A 6.9862146 9.9277792 0 1 1 821.43177 710.97424 z"
+ sodipodi:ry="9.9277792" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g3163">
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2966);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.0999999;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ d="M 108.18708,283.55817 C 90.41157,283.91998 77.41806,305.06914 71.517246,329.23479 C 61.125088,371.6205 65.60275,425.30152 82.717984,468.19071 C 92.44636,492.32666 108.1383,513.92252 125.83908,516.41197 C 142.32872,519.02696 156.08702,503.02308 163.17054,482.25367 C 176.69987,442.68351 174.34333,389.32508 160.08011,344.80859 C 151.33696,317.9808 136.39899,292.08175 117.66532,285.15183 C 114.51401,283.97519 111.31507,283.44779 108.18708,283.55817 z "
+ id="path4148" />
+ <path
+ transform="matrix(0.597247,0,8.37692e-2,0.959548,-423.1381,-243.6618)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4266);stroke-width:3.59412193;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4150"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <g
+ transform="matrix(0.490589,0,-1.152337e-2,0.695881,-273.6179,-92.35558)"
+ style="opacity:1;display:inline"
+ id="g4152">
+ <path
+ transform="matrix(0.35769,0,5.968548e-2,0.41765,475.067,327.4519)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4268);stroke-width:12.04805183;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4154"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.371116,0,6.192573e-2,0.433082,529.996,396.8886)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4270);stroke-width:11.61547089;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4156"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.371116,0,6.192573e-2,0.433082,513.8174,509.4034)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4272);stroke-width:11.61547089;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4158"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.357317,0,5.96232e-2,0.417221,453.5199,501.9763)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4274);stroke-width:12.06053925;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4160"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.357317,0,5.96232e-2,0.407962,423.3689,392.3642)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4276);stroke-width:12.19663715;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4162"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4278);stroke-width:4.6566844;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4164"
+ d="M 767.59375,566.59375 C 753.99813,573.75695 742.77156,586.59663 734.65625,603.46875 C 737.57614,604.76217 740.53964,605.46875 743.53125,605.46875 C 758.20373,605.46875 768.01733,588.76484 767.59375,566.59375 z " />
+ <path
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4280);stroke-width:4.6566844;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4166"
+ d="M 839.125,576.96875 C 839.15658,577.19851 839.18506,577.42573 839.21875,577.65625 C 843.13967,604.48448 859.90323,626.28126 876.65625,626.28125 C 877.93248,626.28125 879.17587,626.12033 880.375,625.875 C 868.75343,605.36177 854.56788,588.48788 839.125,576.96875 z " />
+ <path
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4282);stroke-width:4.6566844;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4168"
+ d="M 721.78125,701.65625 C 722.05446,703.99289 722.37332,706.35522 722.71875,708.71875 C 725.81891,729.93104 731.5407,750.08353 739.21875,768.34375 C 742.24009,760.7239 743.30883,750.78622 741.71875,739.90625 C 739.29936,723.35199 731.3693,708.97479 721.78125,701.65625 z " />
+ <path
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4284);stroke-width:4.6566844;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4170"
+ d="M 910.75,739.40625 C 898.12259,744.48579 890.98865,763.76215 894.34375,786.71875 C 895.35456,793.63507 897.21958,800.19825 899.71875,806.15625 C 907.15716,787.43227 911.12123,764.58884 910.75,739.40625 z " />
+ <path
+ style="opacity:1;color:black;fill:#959db8;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4286);stroke-width:4.6566844;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4172"
+ d="M 817.75,834.8125 C 810.39953,834.8125 804.26586,839.02904 800.03125,846 C 812.03051,853.2674 824.61494,857.25 837.1875,857.25 C 840.25793,857.25 843.26165,857.03003 846.1875,856.5625 C 838.83437,843.46461 828.30177,834.81252 817.75,834.8125 z " />
+ </g>
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2951);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:7.03952456;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 111.47382,295.88078 C 103.2464,295.88078 97.869927,311.38826 99.479011,330.50086 C 101.08808,349.61347 109.07538,365.12095 117.30281,365.12094 C 118.65976,365.12094 119.94198,364.69361 121.12504,363.90315 C 114.46289,359.8977 108.67183,346.45777 107.32843,330.50086 C 105.98487,314.54205 109.51199,301.10225 115.50102,297.09857 C 114.18298,296.30581 112.83282,295.88078 111.47382,295.88078 z "
+ id="path4174" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2948);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6.7867713;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 143.49118,350.116 C 134.95493,350.116 129.37621,366.20031 131.04585,386.01911 C 132.71551,405.83792 141.00205,421.92224 149.5383,421.92223 C 150.8959,421.92223 152.16933,421.51193 153.35981,420.74793 C 146.38129,416.71334 140.29985,402.69145 138.89528,386.01911 C 137.49117,369.35228 141.20882,355.33016 147.50376,351.2903 C 146.18674,350.52888 144.84641,350.116 143.49118,350.116 z "
+ id="path4176" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2945);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6.7867713;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 134.25303,428.42436 C 125.71678,428.42436 120.13806,444.50869 121.8077,464.32747 C 123.47736,484.14628 131.7639,500.23058 140.30015,500.23058 C 141.65796,500.23058 142.94635,499.82052 144.13699,499.05628 C 137.1583,495.022 131.06173,481.00013 129.65713,464.32747 C 128.25311,447.66167 131.97137,433.63949 138.26561,429.59866 C 136.9486,428.83724 135.60826,428.42436 134.25303,428.42436 z "
+ id="path4178" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2942);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:7.04681969;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 98.718551,417.15979 C 90.499704,417.15979 85.147723,432.64343 86.75512,451.73638 C 88.362512,470.82935 96.329776,486.33472 104.54862,486.33471 C 105.90415,486.33471 110.85608,482.32435 112.03792,481.5347 C 105.38271,477.53337 95.946537,467.6769 94.604544,451.73638 C 93.26333,435.80518 96.770628,422.38758 102.74574,418.37758 C 101.42907,417.58563 100.07613,417.15979 98.718551,417.15979 z "
+ sodipodi:nodetypes="csscscc"
+ id="path4180" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2939);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:7.12633991;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 85.261504,337.32919 C 77.042657,337.32919 71.680932,352.47542 73.295346,371.14466 C 74.909755,389.81392 82.882966,404.96011 91.101808,404.96013 C 92.458007,404.96013 93.74165,404.53693 94.923678,403.76408 C 88.267693,399.85036 82.492514,386.73016 81.14477,371.14466 C 79.796754,355.55604 83.307749,342.43604 89.289057,338.52524 C 87.969228,337.74742 86.622202,337.32919 85.261504,337.32919 z "
+ id="path4182" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2935);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 95.935492,301.92625 C 89.183086,306.91098 83.527498,315.84587 79.351792,327.58686 C 80.769354,328.48692 82.215072,328.97862 83.682723,328.97862 C 85.04447,328.97862 86.33376,328.56165 87.519924,327.78257 C 87.413291,327.7197 87.307533,327.65436 87.201216,327.58686 C 89.469904,321.2079 92.180995,315.66378 95.261916,311.12492 C 95.688978,308.27763 95.925413,305.18731 95.935492,301.92625 z "
+ id="path4184" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2932);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 130.90838,309.14601 C 130.92123,309.3059 130.93258,309.46401 130.94645,309.62443 C 132.56086,328.29368 140.53371,343.46165 148.75255,343.46164 C 149.37866,343.46164 149.99051,343.34966 150.58161,343.17894 C 150.05937,341.81483 149.5226,340.47269 148.97716,339.15588 C 145.90522,335.62998 143.21128,330.14813 141.32497,323.54205 C 138.06698,317.94064 134.56833,313.08749 130.90838,309.14601 z "
+ id="path4186" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2929);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 71.904008,395.91367 C 72.011116,397.5397 72.140323,399.1836 72.282551,400.82833 C 73.559019,415.58956 76.133841,429.6133 79.690189,442.32024 C 81.260232,437.01773 81.899059,430.10229 81.244357,422.53112 C 80.248192,411.01133 76.523466,401.00651 71.904008,395.91367 z "
+ id="path4188" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2926);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 117.45081,488.57458 C 113.84475,488.57458 110.78705,491.50879 108.62927,496.35975 C 114.43223,501.41699 120.56012,504.18841 126.72808,504.18841 C 128.05911,504.18841 129.36326,504.07101 130.64358,503.81872 C 125.81261,502.9071 121.04599,500.34012 116.47869,496.35975 C 117.82029,493.34368 119.51018,491.06024 121.46303,489.77062 C 120.15199,489.00055 118.80356,488.57458 117.45081,488.57458 z "
+ id="path4190" />
+ <g
+ clip-path="url(#clipPath3833)"
+ style="opacity:1;display:inline"
+ id="g4206"
+ transform="matrix(0.490589,0,-1.152337e-2,0.695881,-352.0716,-97.17108)">
+ <path
+ transform="matrix(1.182067,0,0.197245,1.342882,-116.3514,-181.2832)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="color:black;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.50316167;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4208"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.728694,0,0.121593,0.827829,330.3581,158.0236)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="color:black;fill:url(#linearGradient4308);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.50316167;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4210"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.399961,0,6.673916e-2,0.454373,634.653,408.5734)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="color:black;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.50316167;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4212"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(5.083673e-2,0,8.482827e-3,5.775273e-2,992.1429,635.1441)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="color:black;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.50316167;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4214"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.728694,0,0.121593,0.827829,333.4781,155.9436)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="color:black;fill:url(#radialGradient4310);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.50316167;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4216"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ transform="matrix(0.245003,0,4.088223e-2,0.278334,778.0912,526.6771)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="color:black;fill:url(#linearGradient4312);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.50316167;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4218"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ </g>
+ <g
+ transform="matrix(0.490589,0,-1.152337e-2,0.695881,-273.6179,-92.35558)"
+ style="opacity:1;display:inline"
+ id="g4192">
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient4306);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4194"
+ d="M 766.46875,579.125 L 745.6875,604.09375 L 746.34375,605.25 C 756.58142,603.68632 764.04784,593.60291 766.625,579.375 L 766.46875,579.125 z M 775.03125,593.09375 C 774.82821,597.70319 775.05675,602.58655 775.78125,607.65625 C 779.70626,635.12159 796.51072,657.40626 813.28125,657.40625 C 813.63747,657.40625 813.99333,657.39495 814.34375,657.375 L 775.03125,593.09375 z M 844.75,597.4375 C 850.54334,611.07565 859.64242,621.40204 869.40625,624.9375 L 869.4375,624.875 L 844.75,597.4375 z M 836.8125,609.8125 L 824.53125,653.5 C 834.01028,646.20806 839.11131,629.48445 836.8125,609.8125 z M 754.0625,618.71875 L 785.1875,673 C 785.0588,670.73508 784.81279,668.41655 784.46875,666.0625 C 781.10031,643.01452 768.24142,623.70504 754.0625,618.71875 z M 865.71875,635.875 C 848.57591,636.25991 837.96199,659.19725 842,687.4375 C 846.07233,715.91767 863.50626,739.03127 880.90625,739.03125 C 884.96968,739.03125 888.66667,737.76385 891.90625,735.46875 L 844.75,697.90625 L 844.46875,698.71875 L 844.46875,697.6875 L 844.75,697.90625 L 865.71875,635.875 z M 783.1875,693.46875 L 744.3125,707.5 C 749.59407,712.04565 755.40496,714.65624 761.21875,714.65625 C 771.62157,714.65625 779.58739,706.25677 783.1875,693.46875 z M 731.34375,712.15625 L 731.125,712.25 L 741.53125,755.90625 L 742.15625,755.71875 C 742.64506,750.81799 742.53466,745.48907 741.71875,739.90625 C 740.17452,729.3401 736.3762,719.67921 731.34375,712.15625 z M 777.15625,732.1875 C 767.34788,732.1875 759.73316,739.822 755.875,751.65625 L 794.75,740.125 C 789.29318,735.10731 783.21605,732.1875 777.15625,732.1875 z M 849.96875,748.375 C 846.5652,748.375 843.43136,749.27029 840.59375,750.90625 L 881.5625,775.46875 C 873.92485,759.33771 861.95309,748.375 849.96875,748.375 z M 840.28125,751.09375 C 828.81261,757.98705 822.56628,777.26606 825.8125,799.96875 C 827.20724,809.72295 830.19739,818.84266 834.1875,826.625 L 840.28125,751.09375 z M 898.78125,751.21875 C 895.36157,757.78637 893.46241,766.41429 893.53125,776.125 L 898.78125,751.21875 z M 807.5625,758.21875 L 806.03125,824.46875 C 813.58502,815.76206 817.20471,799.9269 814.625,781.875 C 813.40117,773.31113 810.89987,765.25546 807.5625,758.21875 z " />
+ <path
+ style="opacity:1;color:black;fill:#7d86a4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4196"
+ sodipodi:nodetypes="ccccc"
+ d="M 840.10457,750.72001 L 834.07996,825.60001 L 847.07996,821.96001 L 852.21687,757.48001 L 840.10457,750.72001 z " />
+ <path
+ style="opacity:1;color:black;fill:#5e6787;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4198"
+ d="M 865.27996,635.80002 L 844.47996,696.64002 L 857.99996,693.52002 L 878.27996,640.48002 C 878.27996,640.48002 871.51996,636.32002 865.27996,635.80002 z " />
+ <path
+ style="opacity:1;color:black;fill:#dadee2;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4200"
+ d="M 844.47996,696.12002 L 857.99996,694.56002 L 899.59996,724.20001 C 899.59996,724.20001 895.43996,732.00001 891.79996,735.12001 C 847.07996,699.76002 844.47996,697.16002 844.47996,696.12002 z " />
+ <path
+ style="opacity:1;color:black;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4202"
+ sodipodi:nodetypes="ccccc"
+ d="M 775.31996,592.64002 L 790.39996,588.48002 L 825.23996,650.88002 C 825.23996,650.88002 822.36762,656.89703 813.24719,656.28749 C 806.00627,647.65603 789.21488,610.71836 775.31996,592.64002 z " />
+ </g>
+ <path
+ style="opacity:1;color:black;fill:#d8dbe4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72083974;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ d="M 94.065459,443.84319 C 93.370659,460.27669 102.83843,479.86846 112.52048,480.59218 C 101.10917,461.05184 95.476254,451.08035 94.065459,443.84319 z "
+ sodipodi:nodetypes="ccc"
+ id="path4204" />
+ <path
+ transform="matrix(0.15224,0,2.134091e-2,0.245323,-18.57945,235.5262)"
+ sodipodi:cy="670.89545"
+ sodipodi:type="arc"
+ sodipodi:cx="813.71014"
+ style="opacity:1;color:black;fill:url(#radialGradient4314);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4316);stroke-width:14.07893753;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ id="path4220"
+ sodipodi:rx="84.93766"
+ d="M 898.6478 670.89545 A 84.93766 119.13335 0 1 1 728.77248,670.89545 A 84.93766 119.13335 0 1 1 898.6478 670.89545 z"
+ sodipodi:ry="119.13335" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2908);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:8.22614479;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.625;visibility:visible;display:inline;overflow:visible"
+ d="M 117.0694,370.8837 C 109.93156,370.8837 105.27824,383.97785 106.68166,400.11071 C 108.08507,416.24354 115.0193,429.3377 122.15715,429.33771 C 123.80166,429.33771 125.31409,428.62586 126.65121,427.3588 C 121.44522,423.13013 117.08341,412.53222 116.00285,400.11071 C 114.92309,387.69844 117.4325,377.09764 121.89653,372.86261 C 120.34107,371.59916 118.71145,370.88371 117.0694,370.8837 z "
+ id="path4222" />
+ <path
+ style="opacity:1;color:black;fill:url(#linearGradient2905);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72084141;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 164.17499,422.18318 C 157.92159,425.71794 154.19963,439.13199 155.58107,455.10705 C 155.99726,459.91999 156.83659,464.48718 157.994,468.63324 C 161.85896,455.60358 164.06692,439.70727 164.17499,422.18318 z "
+ id="path4224" />
+ <g
+ transform="matrix(0.490589,0,-1.152337e-2,0.695881,-273.6179,-92.35558)"
+ style="opacity:1;display:inline"
+ id="g4226">
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4322);stroke-width:4.10756874;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4228"
+ sodipodi:nodetypes="css"
+ d="M 829.88877,749.94997 C 820.63051,755.49288 804.26228,742.54343 797.53157,728.25594 C 792.49647,717.56778 789.07457,708.40038 791.64844,693.32487" />
+ <path
+ style="color:black;fill:url(#linearGradient4324);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72083974;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4230"
+ d="M 810.4009,701.04647 C 801.57621,704.72343 800.10543,704.72343 794.95769,707.66499 C 789.80995,710.60655 789.80995,721.63742 796.42847,721.63742 C 803.04699,721.63742 815.54864,719.43125 815.54864,719.43125 L 810.4009,701.04647 z " />
+ <path
+ style="color:black;fill:url(#linearGradient4326);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72083974;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4232"
+ sodipodi:nodetypes="csscc"
+ d="M 830.02351,739.91505 C 823.16897,743.59338 821.77819,743.9134 818.10255,746.44005 C 814.42692,748.96669 817.33727,752.55142 823.59578,751.11135 C 829.85428,749.67129 835.19183,745.24622 835.19183,745.24622 L 830.02351,739.91505 z " />
+ <path
+ style="color:black;fill:url(#linearGradient4328);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.72083974;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4234"
+ sodipodi:nodetypes="csscc"
+ d="M 813.74521,665.86114 C 803.60732,668.8815 806.88154,665.8265 800.68324,668.24278 C 794.48494,670.65906 790.54534,679.72013 797.16386,679.72013 C 803.78238,679.72013 817.07195,677.90792 817.07195,677.90792 L 813.74521,665.86114 z " />
+ <path
+ style="opacity:1;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4330);stroke-width:4.10756874;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4236"
+ d="M 835.7719,738.18372 C 824.37333,732.30059 814.44556,726.78516 811.87169,710.23886 C 809.29782,693.69257 811.1363,685.23557 813.34247,679.72014 C 815.54864,674.2047 815.91634,674.2047 815.91634,674.2047" />
+ <g
+ clip-path="url(#clipPath3932)"
+ id="g4238">
+ <path
+ transform="matrix(0.846668,0.225827,0,0.854372,123.8091,-80.38611)"
+ sodipodi:cy="710.97424"
+ sodipodi:type="arc"
+ sodipodi:cx="814.44556"
+ style="color:black;fill:#9faec6;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:5.47515392;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.51315792;visibility:visible;display:inline;overflow:visible"
+ id="path4240"
+ sodipodi:rx="6.9862146"
+ d="M 821.43177 710.97424 A 6.9862146 9.9277792 0 1 1 807.45934,710.97424 A 6.9862146 9.9277792 0 1 1 821.43177 710.97424 z"
+ sodipodi:ry="9.9277792" />
+ <path
+ transform="matrix(0.846668,0.225827,0,0.854372,146.6062,-53.17664)"
+ sodipodi:cy="710.97424"
+ sodipodi:type="arc"
+ sodipodi:cx="814.44556"
+ style="color:black;fill:#9faec6;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:5.47515392;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.51315792;visibility:visible;display:inline;overflow:visible"
+ id="path4242"
+ sodipodi:rx="6.9862146"
+ d="M 821.43177 710.97424 A 6.9862146 9.9277792 0 1 1 807.45934,710.97424 A 6.9862146 9.9277792 0 1 1 821.43177 710.97424 z"
+ sodipodi:ry="9.9277792" />
+ <path
+ transform="matrix(0.846668,0.225827,0,0.854372,129.6922,-117.891)"
+ sodipodi:cy="710.97424"
+ sodipodi:type="arc"
+ sodipodi:cx="814.44556"
+ style="color:black;fill:#9faec6;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:5.47515392;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.51315792;visibility:visible;display:inline;overflow:visible"
+ id="path4244"
+ sodipodi:rx="6.9862146"
+ d="M 821.43177 710.97424 A 6.9862146 9.9277792 0 1 1 807.45934,710.97424 A 6.9862146 9.9277792 0 1 1 821.43177 710.97424 z"
+ sodipodi:ry="9.9277792" />
+ </g>
+ <path
+ transform="matrix(1.478247,0.384378,0,1.454217,-369.2512,-643.1703)"
+ sodipodi:cy="710.97424"
+ sodipodi:type="arc"
+ sodipodi:cx="814.44556"
+ style="color:black;fill:#263141;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4332);stroke-width:1.16730797;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path4246"
+ sodipodi:rx="6.9862146"
+ d="M 821.43177 710.97424 A 6.9862146 9.9277792 0 1 1 807.45934,710.97424 A 6.9862146 9.9277792 0 1 1 821.43177 710.97424 z"
+ sodipodi:ry="9.9277792" />
+ </g>
+ </g>
+ <path
+ style="opacity:0.70434783;color:black;fill:url(#linearGradient4976);fill-opacity:1.0;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;filter:url(#filter4958)"
+ id="path4896"
+ d="M 603.49401,376.6917 C 605.68022,380.29314 608.90095,381.472 612.89829,381.76628 C 616.55274,381.84427 619.06683,380.48985 621.67203,378.153 C 623.23324,374.8852 625.20964,371.78876 626.4345,368.37411 C 627.56726,365.21619 631.64398,367.99002 630.33308,371.07825 L 630.33308,371.07825 C 628.7101,374.90167 626.80709,378.7071 624.37026,382.06935 C 621.03262,385.02787 617.1318,386.70851 612.5883,386.43999 C 607.52089,386.17306 603.14577,384.3949 600.14288,380.10581 C 598.20277,377.33469 601.73866,373.80002 603.49401,376.6917 z " />
+ <path
+ style="opacity:1;color:black;fill:#f2ffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path5198"
+ d="M 819.33652,386.084 C 819.33652,386.084 742.11653,260.504 717.15653,226.184 C 702.80803,206.4548 683.47615,183.6325 665.18672,165.0271 C 651.66069,151.2674 638.70481,139.814 628.75653,133.624 C 614.9308,125.0214 593.16949,114.6801 563.22582,108.0611 C 544.26429,103.8698 522.02171,101.1711 496.43539,101.3517 C 495.48043,101.3584 494.52081,101.3692 493.55653,101.384 C 497.64803,91.431 504.87858,87.738226 511.22886,83.615245 C 511.22886,83.615245 520.47,82.410986 534.03338,83.054232 C 555.83602,84.088187 587.81986,90.862122 612.11653,98.685902 C 627.1091,103.51371 638.77262,109.155 649.73884,115.1879 C 681.02965,132.402 702.34177,152.356 737.9938,195.3709 C 741.95339,200.1482 746.08986,205.2099 750.43653,210.584 C 768.47858,232.8905 816.99652,294.824 876.27652,391.544 C 862.43288,391.544 847.93403,390.4957 834.73361,388.6781 C 829.34006,387.9355 824.16328,387.0644 819.33652,386.084 C 819.33652,386.084 819.33652,386.084 819.33652,386.084"
+ sodipodi:nodetypes="csssssccssssscscc" />
+ <path
+ style="opacity:1;color:black;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;filter:url(#filter5106)"
+ id="path5036"
+ d="M 507.64262,283.34374 C 505.47606,286.36974 503.8547,288.55197 500.0401,288.96742 C 499.76275,292.25488 497.62043,293.52247 496.82896,296.74274 C 496.30525,299.70348 494.86523,301.70693 494.4431,304.92175 C 492.4482,309.38606 491.50333,307.70402 488.77311,311.1671 C 490.33377,312.96016 492.02997,315.08438 493.24677,317.57662 C 496.22657,319.77266 496.30264,324.27833 500.393,323.55709 C 501.86827,326.8485 505.64254,329.88761 501.60307,328.55147 C 498.23646,325.77417 494.98031,326.44889 492.24951,322.50889 C 493.21978,318.4119 488.66429,317.54931 487.90971,313.44211 C 487.97774,309.1429 486.8583,305.68217 488.34447,301.43637 C 490.2953,298.7153 490.51305,295.57962 491.09746,292.57097 C 493.67001,289.94427 494.26715,285.99688 496.49521,283.03536 C 499.73376,282.12685 502.34667,281.70501 503.96776,278.28573 C 505.86163,274.29107 510.21623,279.74922 507.64262,283.34374 z "
+ sodipodi:nodetypes="cccccccccccccsc" />
+ <g
+ id="g5333"
+ clip-path="url(#clipPath5339)"
+ transform="translate(0,540)">
+ <path
+ sodipodi:nodetypes="cssssssscscsssccc"
+ d="M 864.07817,-148.146 C 852.74527,-169.7657 812.50322,-226.4162 780.2559,-270.6337 C 764.41493,-292.3548 750.50317,-310.29031 742.89522,-320.38451 C 734.07075,-332.09281 725.47937,-341.77351 718.65114,-350.21231 C 705.71545,-366.19931 695.2722,-376.94443 680.9193,-389.36203 C 660.51571,-407.01443 657.09804,-411.15079 639.21395,-420.99159 C 638.5411,-421.36179 637.09908,-421.3337 636.45801,-421.6927 C 628.24674,-426.292 622.59004,-429.9982 618.14947,-433.3989 C 612.77561,-437.5143 563.64397,-446.73572 559.46006,-450.99712 C 574.39687,-446.01812 642.36945,-429.9353 661.28336,-418.3569 C 671.70217,-411.9789 681.05291,-405.2825 687.49412,-399.0202 C 710.25855,-376.9147 721.18315,-365.913 750.43653,-329.416 C 753.01933,-326.1937 756.22228,-322.1731 759.98828,-317.3664 C 779.98013,-291.8495 815.83892,-244.1753 859.02259,-176.123 C 864.65559,-167.2461 892.46594,-151.13093 898.32924,-141.56453 C 894.824,-141.01303 868.33803,-148.0219 864.07817,-148.146 C 864.07817,-148.146 870.96964,-132.98476 870.96964,-132.98476"
+ id="path5200"
+ style="opacity:1;color:black;fill:#2556dd;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter5254)" />
+ <path
+ transform="matrix(2.242215,0.424538,-0.186032,0.982545,-876.716,-289.2858)"
+ d="M 691.13947 -447.13715 A 45.945068 30.237352 0 1 1 599.24933,-447.13715 A 45.945068 30.237352 0 1 1 691.13947 -447.13715 z"
+ sodipodi:ry="30.237352"
+ sodipodi:rx="45.945068"
+ sodipodi:cy="-447.13715"
+ sodipodi:cx="645.1944"
+ id="path5263"
+ style="opacity:0.72608696;color:black;fill:#6488ea;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter5329);enable-background:accumulate"
+ sodipodi:type="arc" />
+ </g>
+ <path
+ transform="matrix(0.916345,0,0,0.916345,113.2764,74.39469)"
+ style="opacity:1;color:black;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter3952)"
+ d="M 1272.4399,903.60001 L 1469.5199,872.40001 C 1469.5199,872.40001 1496.0399,893.20001 1493.9599,893.20001 C 1491.8799,893.20001 1315.5999,925.44 1315.5999,925.44 L 1272.4399,903.60001 z "
+ id="path3321"
+ sodipodi:nodetypes="ccscc" />
+ <path
+ style="opacity:0.60434783;color:black;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;filter:url(#filter4167)"
+ id="path4085"
+ d="M 837.87844,577.98179 C 841.46692,584.35026 845.6653,603.51883 851.56879,607.74463 C 854.38266,613.5104 862.93242,621.44522 874.67166,626.5043 C 875.61093,626.90908 867.52797,625.20659 866.57168,624.84382 L 866.57168,624.84382 C 858.90138,621.93405 854.13398,616.4021 849.03714,610.27999 C 843.93926,604.80748 840.54667,597.01066 840.00857,590.29176 C 839.91024,589.064 837.27379,576.90873 837.87844,577.98179 z "
+ sodipodi:nodetypes="ccscccsc" />
+ <path
+ d="M 696.90625,397.375 C 716.31072,399.15039 730.7816,403.02757 724.08756,414.24651 C 747.87178,417.64391 763.29567,436.9156 769.42747,458.40244 C 784.47414,462.16706 851.21242,454.70446 912.71875,547.46875 C 933.43519,578.71344 951.13573,647.06961 967.29118,659.67127 C 983.40346,672.23925 994.08962,609.51337 1009.375,623.0625 C 1036.9696,640.7111 1085.7096,694.90941 1117,705.0625 C 1169.4389,716.82057 1227.3539,726.23713 1280.2188,744 L 1252.1563,715.15625 C 1252.1562,715.15623 1067.8437,548.00446 987.84375,498.71875 C 907.84377,449.43303 849.32375,417.76244 818.5625,411.5625 C 772.48026,402.2746 727.07461,397.51778 696.90625,397.375 z "
+ sodipodi:nodetypes="cccssccccssc"
+ id="use4171"
+ style="opacity:0.32173917;color:black;fill:url(#linearGradient4211);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4217)" />
+ <path
+ style="fill:url(#linearGradient4269);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;opacity:0.11304348;filter:url(#filter4259)"
+ d="M 1342.9215,394.1428 C 1309.0979,396.64825 1181.3199,409.1755 1182.5726,415.43913 C 1183.8254,421.70275 1320.3725,567.01889 1340.4161,595.83157 C 1277.2878,487.51853 1221.3106,404.78717 1342.9215,394.1428 z "
+ id="path4221"
+ sodipodi:nodetypes="cscc" />
+ <path
+ d="M 117.95028,131.82387 C 118.96044,143.94577 118.96979,142.91927 113.91903,148.98017 C 108.86827,155.04107 105.82528,155.05507 105.82528,163.13637 C 105.82528,171.21757 104.8237,181.31457 98.762783,185.35517 C 92.701872,189.39567 92.700282,189.37697 92.700282,193.41767 C 92.700282,197.45827 82.111603,202.51219 80.596379,216.14927 C 109.46712,205.68175 140.65228,235.39211 137.13778,231.82387 C 132.65466,227.27219 137.14873,225.74957 139.16903,220.69887 C 141.18933,215.64807 139.15808,217.66597 137.13778,211.60517 C 135.11747,205.54427 151.28467,215.66527 155.32528,206.57387 C 159.3659,197.48257 150.2761,195.44817 161.38778,192.41767 C 172.49946,189.38707 174.51515,186.36767 183.60653,194.44887 C 192.6979,202.53007 206.83939,209.59657 220.98153,216.66767 C 235.12367,223.73867 258.35969,231.82457 270.48153,234.85517 C 282.60336,237.88567 294.72297,233.84567 301.79403,237.88637 C 308.86509,241.92697 303.82845,244.94967 315.95028,247.98017 C 324.91012,250.22007 369.39404,263.24968 435.24677,296.16641 C 404.4122,278.76461 329.19878,237.08445 315.6868,228.67135 C 262.14871,195.33635 190.67601,157.07237 177.54403,151.01137 C 164.41206,144.95047 130.07211,131.82387 117.95028,131.82387 z M 153.54403,177.16767 C 155.24491,177.05947 156.5896,177.32287 157.35653,178.26137 C 149.7542,185.86367 152.56806,190.38397 150.29403,199.48017 C 148.22327,207.76317 141.64769,206.14957 138.16903,201.51137 C 136.45178,199.22167 124.01278,195.89187 124.01278,194.44887 C 124.01278,187.42117 125.91394,181.29257 134.10653,181.29267 C 140.06869,181.29267 148.44138,177.49197 153.54403,177.16767 z "
+ sodipodi:nodetypes="csssscsssssssssscsscccssssc"
+ id="path4539"
+ style="opacity:1;color:black;fill:url(#linearGradient2999);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4601)" />
+ <path
+ id="path4605"
+ sodipodi:nodetypes="csssssssssscc"
+ d="M 689.79677,145.09093 C 686.11982,131.86289 690.53216,108.71379 695.6799,102.09978 C 700.82764,95.485746 885.41078,-0.41763823 917.76799,-16.952728 C 950.12519,-33.487771 1064.1108,-59.943887 1069.9939,-59.943887 C 1075.8771,-59.943887 1089.8495,-69.864915 1070.7293,-93.01402 C 1051.6092,-116.16313 980.27622,-165.7683 949.3898,-178.99639 C 918.50338,-192.22442 892.76469,-212.06652 883.20461,-215.37352 C 873.64453,-218.68054 849.37662,-241.82959 838.34576,-231.90858 C 827.31489,-221.98755 807.45934,-178.99639 819.96098,-175.68933 C 832.46263,-172.38233 857.46592,-165.7683 847.90584,-162.4613 C 838.34576,-159.15429 750.83423,-126.08415 732.44945,-119.47014 C 714.06468,-112.85607 633.17167,-50.022861 622.1408,-50.022861 C 660.38114,19.42446 683.17825,108.71379 689.79677,145.09093 z "
+ style="opacity:0.52173911;color:black;fill:url(#linearGradient4607);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4653)"
+ transform="matrix(1,0,0,0.230566,0,111.6378)" />
+ <g
+ id="g4663"
+ style="opacity:0.55652174;filter:url(#filter5200)">
+ <path
+ d="M 1806.6185,615.58146 C 1804.8267,618.06369 1801.5664,622.79015 1799.2825,623.09218 C 1795.8213,625.05097 1795.0148,626.6908 1794.0321,630.38076 C 1790.965,632.01807 1786.8719,633.70351 1784.249,636.31985 C 1780.2709,637.10109 1781.1876,640.68028 1778.8384,642.70679 C 1776.1233,643.71768 1771.3524,647.51399 1770.2967,646.7437 C 1770.6412,652.46947 1765.0568,651.9056 1762.0387,653.61314 C 1758.4097,655.05792 1756.6452,655.14756 1754.0337,658.71823 C 1749.8519,659.95696 1746.8734,661.40411 1742.3186,660.94588 C 1739.432,661.27862 1736.2825,663.54249 1733.3868,662.82183 C 1732.0885,664.62847 1727.0652,667.14698 1724.4244,666.98569 C 1721.8266,669.88342 1719.7227,668.9769 1718.3407,672.86742 C 1715.7651,673.60629 1698.523,685.49074 1694.735,680.6428 C 1692.0002,677.14269 1710.1394,673.98852 1711.7567,669.85154 L 1711.7567,669.85154 C 1713.5151,665.35349 1711.2316,670.9242 1713.0912,667.1255 C 1716.6749,665.98631 1717.6014,660.15728 1722.751,661.93537 C 1724.9849,657.41233 1727.3308,658.69344 1731.6397,656.90311 C 1734.6912,654.91325 1738.5185,654.83707 1741.8144,653.74433 C 1745.1175,653.36767 1749.4778,653.51689 1750.0423,651.1683 C 1754.3519,652.0677 1755.938,646.12295 1760.8569,647.4964 C 1762.1851,644.618 1765.7421,646.55097 1767.0513,643.08916 C 1768.4207,637.70231 1771.3409,640.26201 1773.764,636.84834 C 1776.6794,635.21098 1778.4886,632.14392 1781.2052,629.90534 C 1784.6968,628.25744 1785.3112,625.39949 1788.9987,625.25998 C 1789.5916,621.20235 1793.5739,620.0327 1795.3326,616.4096 C 1798.0704,616.0827 1800.5443,612.6309 1802.3968,611.17285 C 1805.7884,608.50339 1809.1446,612.08181 1806.6185,615.58146 z "
+ id="path4657"
+ style="opacity:1;color:black;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccccccccscccccccccccccsc" />
+ <path
+ d="M 1798.0216,613.29382 C 1797.0874,616.28412 1796.2418,620.33359 1793.1599,622.9797 C 1792.0706,626.89824 1787.453,627.48264 1785.5451,630.11989 C 1782.5165,631.86806 1781.8122,636.90866 1778.0487,638.3375 C 1775.9998,639.03739 1775.3976,640.4401 1773.259,640.85512 C 1768.1978,641.83731 1765.6928,637.04124 1770.061,634.30273 L 1770.061,634.30273 C 1772.9697,632.47918 1774.1144,637.36387 1774.0334,632.09126 C 1778.2644,631.31327 1778.0743,625.32316 1782.4137,625.5583 C 1783.5676,621.94087 1785.4312,620.61344 1788.3529,617.85061 C 1791.4004,614.47009 1790.9779,612.08063 1793.6707,608.75029 C 1796.4676,605.29131 1799.348,609.04795 1798.0216,613.29382 z "
+ id="path4659"
+ style="opacity:1;color:black;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ d="M 1793.516,613.20171 C 1789.0948,614.37009 1791.8615,616.25358 1790.4862,619.02314 C 1789.9465,620.10983 1788.1005,619.9809 1787.4209,620.98606 C 1785.4294,624.4117 1783.8327,626.96005 1780.7755,629.96653 C 1776.9483,633.73013 1774.8728,628.65432 1776.655,623.59116 L 1776.655,623.59116 C 1777.9141,620.01393 1781.4593,619.97533 1782.8182,616.60362 C 1784.4707,613.27159 1786.0483,610.14364 1788.2172,607.19962 C 1791.5752,602.64166 1798.9895,611.75524 1793.516,613.20171 z "
+ id="path4661"
+ style="opacity:1;color:black;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <path
+ style="opacity:0.55652173;color:black;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4826);enable-background:accumulate"
+ d="M 317.50085,276.97238 C 318.91462,278.18011 320.89037,278.6003 322.09804,280.07033 C 323.10794,281.15753 324.37269,281.98621 325.7251,282.58431 C 328.14276,282.86624 330.32574,284.10473 332.23001,285.56005 C 332.78645,285.94644 333.43594,286.28302 334.13296,286.24069 C 334.63876,285.96515 335.28921,286.34027 335.45206,286.85688 C 336.45064,287.83774 337.8631,288.14129 339.14048,288.59061 C 340.57356,289.01305 342.02214,289.38162 343.45021,289.82128 C 344.02793,289.73077 344.53147,290.19207 344.75215,290.6874 C 345.59739,291.67816 346.89755,292.03777 347.99638,292.65643 C 348.55012,292.88332 349.20346,293.06136 349.51388,293.62488 C 350.10693,294.52567 350.437,295.64836 350.27185,296.72641 C 350.17573,297.23743 349.96656,297.80674 349.50023,298.08296 C 348.98543,298.27415 348.45039,297.87311 348.23552,297.42072 C 347.73255,296.79085 347.05164,296.32111 346.59887,295.64847 C 345.91925,295.09362 345.04567,294.82639 344.41247,294.20674 C 343.89341,293.79526 343.39893,293.35403 342.88408,292.93741 C 341.57502,292.64655 340.15875,292.54569 339.02699,291.75417 C 338.65852,291.23834 337.96258,291.43337 337.42808,291.36442 C 335.81585,291.16081 334.57881,289.82757 332.93478,289.74715 C 331.73001,289.52779 330.89356,288.56076 329.93606,287.88576 C 329.4197,287.63165 328.91352,287.34895 328.46107,286.99101 C 327.54252,286.58713 326.49926,286.66729 325.568,286.29898 C 325.1333,286.14956 324.71368,285.93696 324.36976,285.62824 C 322.81805,285.06953 321.92727,283.41936 320.29848,283.01199 C 319.58779,282.64075 319.21632,281.82892 318.45559,281.53047 C 317.44533,280.9046 316.26687,280.43866 315.55467,279.43804 C 314.9945,278.54539 315.19953,277.19556 316.1202,276.62161 C 316.59581,276.41325 317.14929,276.62779 317.50085,276.97238 z "
+ id="path4788" />
+ <path
+ style="fill:#5b6879;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;opacity:0.23043478"
+ d="M 487.89301,308.72039 C 488.3326,300.80774 491.4635,295.31127 491.4635,295.31127 C 491.4635,295.31127 501.13452,293.11331 499.81575,297.50923 C 498.49697,301.90515 494.98024,306.74065 497.1782,306.74065 C 499.37615,306.74065 505.53044,305.42188 505.53044,305.42188 C 505.53044,305.42188 512.78213,307.83806 512.78213,310.03602 C 512.78213,312.23398 487.45342,308.72039 487.89301,308.72039 z "
+ id="path4956"
+ sodipodi:nodetypes="ccsscsc" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3927);opacity:0.27391304"
+ d="M 292.19051,471.87988 C 294.6394,467.05863 286.53648,469.6405 284.16343,463.44555 C 280.55878,454.03548 311.62618,435.19934 312.40474,435.78326 C 313.79552,436.82635 332.5711,458.20965 330.65877,456.47117 C 328.74645,454.73269 302.01065,468.12376 292.19051,471.87988 z "
+ id="path3921"
+ sodipodi:nodetypes="csssc"
+ clip-path="url(#clipPath3953)" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path4956"
+ id="use4958"
+ style="opacity:1;filter:url(#filter5032)" />
+ <path
+ style="fill:#080000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter5304)"
+ d="M 1501.9565,338.98683 C 1498.1548,339.12763 1478.721,343.40924 1476.0457,341.8604 C 1473.3704,340.31156 1471.2584,342.14201 1471.2584,342.14201 L 1465.063,340.17075 C 1465.063,340.17075 1447.6033,353.2655 1437.4655,357.20801 C 1427.3276,361.15051 1417.7347,368.3163 1417.7347,368.3163 C 1417.7347,368.3163 1450.1378,357.63042 1451.8275,356.9264 C 1453.5171,356.22238 1466.3302,350.87184 1467.8791,350.59023 C 1469.4279,350.30862 1483.5689,346.80325 1485.5401,346.66244 C 1487.5114,346.52164 1501.9565,339.26844 1501.9565,338.98683 z "
+ id="path5282"
+ sodipodi:nodetypes="csccscsssc" />
+ <path
+ sodipodi:nodetypes="csssc"
+ id="path3942"
+ d="M 292.19051,471.87988 C 294.6394,467.05863 286.53648,469.6405 284.16343,463.44555 C 280.55878,454.03548 311.62618,435.19934 312.40474,435.78326 C 313.79552,436.82635 322.74618,448.20609 320.83385,446.46761 C 318.92153,444.72913 302.01065,468.12376 292.19051,471.87988 z "
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3927);opacity:0.33913043"
+ clip-path="url(#clipPath3946)" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#b2d1fd;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3982)"
+ d="M 323.69746,231.50388 L 405.14932,213.56953"
+ id="path3960"
+ sodipodi:nodetypes="cc" />
+ <path
+ id="path4075"
+ d="M 294.07695,144.22375 C 265.79267,135.13235 244.57947,133.11205 231.44749,135.13235 C 218.3155,137.15265 208.21398,132.10185 198.11245,132.10185 C 188.01093,132.10185 163.76727,134.12215 163.76727,134.12215 C 163.76727,134.12215 179.92971,139.17295 195.082,146.24405 C 210.23428,153.31505 239.52871,169.47755 239.52871,169.47755 C 239.52871,169.47755 263.77237,155.33535 270.84344,152.30495 C 277.9145,149.27445 296.09725,143.21355 294.07695,144.22375 z "
+ style="opacity:0.92173911;color:#000000;fill:url(#linearGradient4101);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter4097)" />
+ </g>
+</svg>
diff --git a/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/perf-canvaskit-with-puppeteer.js b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/perf-canvaskit-with-puppeteer.js
index 903702ad3ee..402f4c14dce 100644
--- a/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/perf-canvaskit-with-puppeteer.js
+++ b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/perf-canvaskit-with-puppeteer.js
@@ -33,9 +33,14 @@ const opts = [
description: 'The Lottie JSON file to process.'
},
{
+ name: 'input_skp',
+ typeLabel: '{underline file}',
+ description: 'The SKP file to process.'
+ },
+ {
name: 'assets',
typeLabel: '{underline file}',
- description: 'Any assets needed by the lottie file (e.g. images/fonts).'
+ description: 'A directory containing any assets needed by the lottie file (e.g. images/fonts).'
},
{
name: 'output',
@@ -59,6 +64,13 @@ const opts = [
type: Number,
},
{
+ name: 'query_params',
+ description: 'The query params to be added to the testing page URL. Useful for passing' +
+ 'options to the perf html page.',
+ type: String,
+ multiple: true
+ },
+ {
name: 'help',
alias: 'h',
type: Boolean,
@@ -130,6 +142,12 @@ if (options.input_lottie) {
const lottieJSON = fs.readFileSync(options.input_lottie, 'utf8');
app.get('/static/lottie.json', (req, res) => res.send(lottieJSON));
}
+if (options.input_skp) {
+ const skpBytes = fs.readFileSync(options.input_skp, 'binary');
+ app.get('/static/test.skp', (req, res) => {
+ res.send(new Buffer(skpBytes, 'binary'));
+ });
+}
if (options.assets) {
app.use('/static/assets/', express.static(options.assets));
console.log('assets served from', options.assets);
@@ -141,7 +159,13 @@ let hash = "#cpu";
if (options.use_gpu) {
hash = "#gpu";
}
-const targetURL = `http://localhost:${options.port}/${hash}`;
+let query_param_string = '?';
+if (options.query_params) {
+ for (const string of options.query_params) {
+ query_param_string += string + '&';
+ }
+}
+const targetURL = `http://localhost:${options.port}/${query_param_string}${hash}`;
const viewPort = {width: 1000, height: 1000};
// Drive chrome to load the web page from the server we have running.
@@ -154,6 +178,11 @@ async function driveBrowser() {
'--no-sandbox',
'--disable-setuid-sandbox',
'--window-size=' + viewPort.width + ',' + viewPort.height,
+ // The following two params allow Chrome to run at an unlimited fps. Note, if there is
+ // already a chrome instance running, these arguments will have NO EFFECT, as the existing
+ // Chrome instance will be used instead of puppeteer spinning up a new one.
+ '--disable-frame-rate-limit',
+ '--disable-gpu-vsync',
];
if (options.use_gpu) {
browser_args.push('--ignore-gpu-blacklist');
diff --git a/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/render-skp.html b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/render-skp.html
new file mode 100644
index 00000000000..ef1ed254580
--- /dev/null
+++ b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/render-skp.html
@@ -0,0 +1,157 @@
+<!-- This benchmark aims to accurately measure the time it takes for CanvasKit to render
+ an SKP from our test corpus. It is very careful to measure the time between frames. This form
+ of measurement makes sure we are capturing the GPU draw time. CanvasKit.flush() returns after
+ it has sent all the instructions to the GPU, but we don't know the GPU is done until the next
+ frame is requested. Thus, we need to keep track of the time between frames in order to
+ accurately calculate draw time. Keeping track of the drawPicture and drawPicture+flush is still
+ useful for telling us how much time we are spending in WASM land and if our drawing is CPU
+ bound or GPU bound. If total_frame_ms is close to with_flush_ms, we are CPU bound; if
+ total_frame_ms >> with_flush_ms, we are GPU bound.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+ <title>CanvasKit SKP Perf</title>
+ <meta charset="utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <script src="/static/canvaskit.js" type="text/javascript" charset="utf-8"></script>
+ <style type="text/css" media="screen">
+ body {
+ margin: 0;
+ padding: 0;
+ }
+ </style>
+</head>
+<body>
+ <main>
+ <button id="start_bench">Start Benchmark</button>
+ <br>
+ <canvas id=anim width=1000 height=1000 style="height: 1000px; width: 1000px;"></canvas>
+ </main>
+ <script type="text/javascript" charset="utf-8">
+ const WIDTH = 1000;
+ const HEIGHT = 1000;
+ // Run this number of frames before starting to measure things. This allows us to make sure
+ // the noise from the first few renders (e.g shader compilation, caches) is removed from the
+ // data we capture.
+ const WARM_UP_FRAMES = 10;
+ const MAX_FRAMES = 201; // This should be sufficient to have low noise.
+
+ const SKP_PATH = '/static/test.skp';
+ (function() {
+
+ const loadKit = CanvasKitInit({
+ locateFile: (file) => '/static/' + file,
+ });
+
+ const loadSKP = fetch(SKP_PATH).then((resp) => {
+ return resp.arrayBuffer();
+ });
+
+ Promise.all([loadKit, loadSKP]).then((values) => {
+ const [CanvasKit, skpBytes] = values;
+ const loadStart = performance.now();
+ const skp = CanvasKit.MakeSkPicture(skpBytes);
+ const loadTime = performance.now() - loadStart;
+ console.log('loaded skp', skp, loadTime);
+ if (!skp) {
+ window._error = 'could not read skp';
+ return;
+ }
+
+ const surface = getSurface(CanvasKit);
+ if (!surface) {
+ console.error('Could not make surface', window._error);
+ return;
+ }
+ const canvas = surface.getCanvas();
+
+ document.getElementById('start_bench').addEventListener('click', () => {
+ const clearColor = CanvasKit.WHITE;
+ const totalFrame = new Float32Array(MAX_FRAMES);
+ const withFlush = new Float32Array(MAX_FRAMES);
+ const withoutFlush = new Float32Array(MAX_FRAMES);
+ let warmUp = true;
+ let idx = 0;
+
+ let previousFrame;
+
+ function drawFrame() {
+ const start = performance.now();
+ canvas.clear(clearColor);
+ canvas.drawPicture(skp);
+ const afterDraw = performance.now();
+ surface.flush();
+ const end = performance.now();
+
+ if (warmUp) {
+ idx++;
+ if (idx >= WARM_UP_FRAMES) {
+ idx = -1;
+ warmUp = false;
+ }
+ window.requestAnimationFrame(drawFrame);
+ return;
+ }
+ if (idx >= 0) {
+ // Fill out total time the previous frame took to draw.
+ totalFrame[idx] = start - previousFrame;
+ }
+ previousFrame = start;
+ idx++;
+ // If we have maxed out the frames we are measuring or have completed the animation,
+ // we stop benchmarking.
+ if (idx >= withFlush.length) {
+ window._perfData = {
+ total_frame_ms: Array.from(totalFrame).slice(0, idx),
+ with_flush_ms: Array.from(withFlush).slice(0, idx),
+ without_flush_ms: Array.from(withoutFlush).slice(0, idx),
+ skp_load_ms: loadTime,
+ };
+ window._perfDone = true;
+ return;
+ }
+
+ // We can fill out this frame's intermediate steps.
+ withFlush[idx] = end - start;
+ withoutFlush[idx] = afterDraw - start;
+ window.requestAnimationFrame(drawFrame);
+ }
+ window.requestAnimationFrame(drawFrame);
+ });
+ console.log('Perf is ready');
+ window._perfReady = true;
+ });
+ }
+ )();
+
+ // TODO(kjlubick) make this configurable to return a WEBGL 1 or WEBGL 2 surface.
+ function getSurface(CanvasKit) {
+ let surface;
+ if (window.location.hash.indexOf('gpu') !== -1) {
+ surface = CanvasKit.MakeWebGLCanvasSurface('anim');
+ if (!surface) {
+ window._error = 'Could not make GPU surface';
+ return null;
+ }
+ let c = document.getElementById('anim');
+ // If CanvasKit was unable to instantiate a WebGL context, it will fallback
+ // to CPU and add a ck-replaced class to the canvas element.
+ if (c.classList.contains('ck-replaced')) {
+ window._error = 'fell back to CPU';
+ return null;
+ }
+ } else {
+ surface = CanvasKit.MakeSWCanvasSurface('anim');
+ if (!surface) {
+ window._error = 'Could not make CPU surface';
+ return null;
+ }
+ }
+ return surface;
+ }
+
+ </script>
+</body>
+</html>
diff --git a/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/skottie-frames.html b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/skottie-frames.html
index f6bbf1a6837..19728d3cc40 100644
--- a/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/skottie-frames.html
+++ b/chromium/third_party/skia/tools/perf-canvaskit-puppeteer/skottie-frames.html
@@ -36,7 +36,7 @@ would display the animation (e.g. using clock time to determine where to seek, n
const loadKit = CanvasKitInit({
locateFile: (file) => '/static/' + file,
- }).ready();
+ });
const loadLottie = fetch(LOTTIE_JSON_PATH).then((resp) => {
return resp.text()
@@ -118,7 +118,7 @@ would display the animation (e.g. using clock time to determine where to seek, n
function getSurface(CanvasKit) {
let surface;
if (window.location.hash.indexOf('gpu') !== -1) {
- surface = CanvasKit.MakeWebGLCanvasSurface('anim', WIDTH, HEIGHT);
+ surface = CanvasKit.MakeWebGLCanvasSurface('anim');
if (!surface) {
window._error = 'Could not make GPU surface';
return null;
@@ -131,7 +131,7 @@ would display the animation (e.g. using clock time to determine where to seek, n
return null;
}
} else {
- surface = CanvasKit.MakeSWCanvasSurface('anim', WIDTH, HEIGHT);
+ surface = CanvasKit.MakeSWCanvasSurface('anim');
if (!surface) {
window._error = 'Could not make CPU surface';
return null;
diff --git a/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.cpp b/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.cpp
index 4abbd9d667d..970c67ec0c1 100644
--- a/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.cpp
+++ b/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.cpp
@@ -317,12 +317,14 @@ bool VulkanWindowContext::createSwapchain(int width, int height,
fDestroySwapchainKHR(fDevice, swapchainCreateInfo.oldSwapchain, nullptr);
}
- this->createBuffers(swapchainCreateInfo.imageFormat, colorType);
+ this->createBuffers(swapchainCreateInfo.imageFormat, colorType,
+ swapchainCreateInfo.imageSharingMode);
return true;
}
-void VulkanWindowContext::createBuffers(VkFormat format, SkColorType colorType) {
+void VulkanWindowContext::createBuffers(VkFormat format, SkColorType colorType,
+ VkSharingMode sharingMode) {
fGetSwapchainImagesKHR(fDevice, fSwapchain, &fImageCount, nullptr);
SkASSERT(fImageCount);
fImages = new VkImage[fImageCount];
@@ -342,6 +344,7 @@ void VulkanWindowContext::createBuffers(VkFormat format, SkColorType colorType)
info.fFormat = format;
info.fLevelCount = 1;
info.fCurrentQueueFamily = fPresentQueueIndex;
+ info.fSharingMode = sharingMode;
if (fSampleCount == 1) {
GrBackendRenderTarget backendRT(fWidth, fHeight, fSampleCount, info);
@@ -525,7 +528,9 @@ void VulkanWindowContext::swapBuffers() {
GrFlushInfo info;
info.fNumSemaphores = 1;
info.fSignalSemaphores = &beSemaphore;
- surface->flush(SkSurface::BackendSurfaceAccess::kPresent, info);
+ GrBackendSurfaceMutableState presentState(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, fPresentQueueIndex);
+ surface->flush(info, &presentState);
+ surface->getContext()->submit();
// Submit present operation to present queue
const VkPresentInfoKHR presentInfo =
diff --git a/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.h b/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.h
index 2db9e79ae62..5e245aff700 100644
--- a/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.h
+++ b/chromium/third_party/skia/tools/sk_app/VulkanWindowContext.h
@@ -61,7 +61,7 @@ private:
BackbufferInfo* getAvailableBackbuffer();
bool createSwapchain(int width, int height, const DisplayParams& params);
- void createBuffers(VkFormat format, SkColorType colorType);
+ void createBuffers(VkFormat format, SkColorType colorType, VkSharingMode);
void destroyBuffers();
VkInstance fInstance = VK_NULL_HANDLE;
diff --git a/chromium/third_party/skia/tools/sk_app/Window.cpp b/chromium/third_party/skia/tools/sk_app/Window.cpp
index bf125a83200..c8c6cd278dc 100644
--- a/chromium/third_party/skia/tools/sk_app/Window.cpp
+++ b/chromium/third_party/skia/tools/sk_app/Window.cpp
@@ -89,7 +89,7 @@ void Window::onPaint() {
this->visitLayers([](Layer* layer) { layer->onPrePaint(); });
this->visitLayers([=](Layer* layer) { layer->onPaint(backbuffer.get()); });
- backbuffer->flush();
+ backbuffer->flushAndSubmit();
fWindowContext->swapBuffers();
}
diff --git a/chromium/third_party/skia/tools/sk_app/Window.h b/chromium/third_party/skia/tools/sk_app/Window.h
index 0648e970ce8..f2d40360fc8 100644
--- a/chromium/third_party/skia/tools/sk_app/Window.h
+++ b/chromium/third_party/skia/tools/sk_app/Window.h
@@ -61,6 +61,9 @@ public:
#ifdef SK_METAL
kMetal_BackendType,
#endif
+#ifdef SK_DIRECT3D
+ kDirect3D_BackendType,
+#endif
kRaster_BackendType,
kLast_BackendType = kRaster_BackendType
diff --git a/chromium/third_party/skia/tools/sk_app/win/D3D12WindowContext_win.cpp b/chromium/third_party/skia/tools/sk_app/win/D3D12WindowContext_win.cpp
new file mode 100644
index 00000000000..55df2820a27
--- /dev/null
+++ b/chromium/third_party/skia/tools/sk_app/win/D3D12WindowContext_win.cpp
@@ -0,0 +1,243 @@
+/*
+ * 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 "tools/sk_app/WindowContext.h"
+#include "tools/sk_app/win/WindowContextFactory_win.h"
+
+#include "tools/gpu/d3d/D3DTestUtils.h"
+
+#include "include/core/SkSurface.h"
+#include "include/gpu/d3d/GrD3DBackendContext.h"
+
+#include <d3d12.h>
+#include <dxgi1_4.h>
+#include <wrl/client.h>
+
+#define GR_D3D_CALL_ERRCHECK(X) \
+ do { \
+ HRESULT result = X; \
+ SkASSERT(SUCCEEDED(result)); \
+ if (!SUCCEEDED(result)) { \
+ SkDebugf("Failed Direct3D call. Error: 0x%08x\n", result); \
+ } \
+ } while(false)
+
+using namespace Microsoft::WRL;
+
+namespace sk_app {
+
+class D3D12WindowContext : public WindowContext {
+public:
+ D3D12WindowContext(HWND hwnd, const DisplayParams& params);
+ ~D3D12WindowContext() override;
+ void initializeContext();
+ void destroyContext();
+ void setupSurfaces(int width, int height);
+
+ bool isValid() override {
+ return fDevice.get() != nullptr;
+ }
+
+ sk_sp<SkSurface> getBackbufferSurface() override;
+ void swapBuffers() override;
+
+ void resize(int width, int height) override;
+ void setDisplayParams(const DisplayParams& params) override;
+private:
+ static constexpr int kNumFrames = 2;
+
+ HWND fWindow;
+ gr_cp<ID3D12Device> fDevice;
+ gr_cp<ID3D12CommandQueue> fQueue;
+ gr_cp<IDXGISwapChain3> fSwapChain;
+ gr_cp<ID3D12Resource> fBuffers[kNumFrames];
+ sk_sp<SkSurface> fSurfaces[kNumFrames];
+
+ // Synchronization objects.
+ unsigned int fBufferIndex;
+ HANDLE fFenceEvent;
+ gr_cp<ID3D12Fence> fFence;
+ uint64_t fFenceValues[kNumFrames];
+};
+
+D3D12WindowContext::D3D12WindowContext(HWND hwnd, const DisplayParams& params)
+ : WindowContext(params)
+ , fWindow(hwnd) {
+
+ this->initializeContext();
+}
+
+D3D12WindowContext::~D3D12WindowContext() {
+ this->destroyContext();
+}
+
+void D3D12WindowContext::initializeContext() {
+ GrD3DBackendContext backendContext;
+ sk_gpu_test::CreateD3DBackendContext(&backendContext);
+ fDevice = backendContext.fDevice;
+ fQueue = backendContext.fQueue;
+
+ fContext = GrContext::MakeDirect3D(backendContext, fDisplayParams.fGrContextOptions);
+ SkASSERT(fContext);
+
+ // Make the swapchain
+ RECT windowRect;
+ GetWindowRect(fWindow, &windowRect);
+ unsigned int width = windowRect.right - windowRect.left;
+ unsigned int height = windowRect.bottom - windowRect.top;
+
+ UINT dxgiFactoryFlags = 0;
+ SkDEBUGCODE(dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;)
+
+ gr_cp<IDXGIFactory4> factory;
+ GR_D3D_CALL_ERRCHECK(CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory)));
+
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
+ swapChainDesc.BufferCount = kNumFrames;
+ swapChainDesc.Width = width;
+ swapChainDesc.Height = height;
+ swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
+ swapChainDesc.SampleDesc.Count = 1; // TODO: support MSAA
+
+ gr_cp<IDXGISwapChain1> swapChain;
+ GR_D3D_CALL_ERRCHECK(factory->CreateSwapChainForHwnd(
+ fQueue.get(), fWindow, &swapChainDesc, nullptr, nullptr, &swapChain));
+
+ // We don't support fullscreen transitions.
+ GR_D3D_CALL_ERRCHECK(factory->MakeWindowAssociation(fWindow, DXGI_MWA_NO_ALT_ENTER));
+
+ GR_D3D_CALL_ERRCHECK(swapChain->QueryInterface(IID_PPV_ARGS(&fSwapChain)));
+
+ fBufferIndex = fSwapChain->GetCurrentBackBufferIndex();
+
+ this->setupSurfaces(width, height);
+
+ for (int i = 0; i < kNumFrames; ++i) {
+ fFenceValues[i] = 1;
+ }
+ GR_D3D_CALL_ERRCHECK(fDevice->CreateFence(fFenceValues[fBufferIndex], D3D12_FENCE_FLAG_NONE,
+ IID_PPV_ARGS(&fFence)));
+
+ fFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ SkASSERT(fFenceEvent);
+
+ fWidth = width;
+ fHeight = height;
+}
+
+void D3D12WindowContext::setupSurfaces(int width, int height) {
+ // set up base resource info
+ GrD3DTextureResourceInfo info(nullptr,
+ D3D12_RESOURCE_STATE_PRESENT,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ 1,
+ 0);
+ for (int i = 0; i < kNumFrames; ++i) {
+ GR_D3D_CALL_ERRCHECK(fSwapChain->GetBuffer(i, IID_PPV_ARGS(&fBuffers[i])));
+
+ SkASSERT(fBuffers[i]->GetDesc().Width == (UINT64)width &&
+ fBuffers[i]->GetDesc().Height == (UINT64)height);
+
+ // TODO: support MSAA
+ info.fResource = fBuffers[i];
+ GrBackendRenderTarget backendRT(width, height, 1, info);
+ fSurfaces[i] = SkSurface::MakeFromBackendRenderTarget(
+ fContext.get(), backendRT, kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType,
+ fDisplayParams.fColorSpace, &fDisplayParams.fSurfaceProps);
+ }
+}
+
+void D3D12WindowContext::destroyContext() {
+ CloseHandle(fFenceEvent);
+ fFence.reset(nullptr);
+
+ for (int i = 0; i < kNumFrames; ++i) {
+ fSurfaces[i].reset(nullptr);
+ fBuffers[i].reset(nullptr);
+ }
+
+ fSwapChain.reset(nullptr);
+ fQueue.reset(nullptr);
+ fDevice.reset(nullptr);
+}
+
+sk_sp<SkSurface> D3D12WindowContext::getBackbufferSurface() {
+ // Update the frame index.
+ const UINT64 currentFenceValue = fFenceValues[fBufferIndex];
+ fBufferIndex = fSwapChain->GetCurrentBackBufferIndex();
+
+ // If the last frame for this buffer index is not done, wait until it is ready.
+ if (fFence->GetCompletedValue() < fFenceValues[fBufferIndex]) {
+ GR_D3D_CALL_ERRCHECK(fFence->SetEventOnCompletion(fFenceValues[fBufferIndex], fFenceEvent));
+ WaitForSingleObjectEx(fFenceEvent, INFINITE, FALSE);
+ }
+
+ // Set the fence value for the next frame.
+ fFenceValues[fBufferIndex] = currentFenceValue + 1;
+
+ return fSurfaces[fBufferIndex];
+}
+
+void D3D12WindowContext::swapBuffers() {
+ SkSurface* surface = fSurfaces[fBufferIndex].get();
+
+ GrFlushInfo info;
+ surface->flush(SkSurface::BackendSurfaceAccess::kPresent, info);
+ fContext->submit();
+
+ GR_D3D_CALL_ERRCHECK(fSwapChain->Present(1, 0));
+
+ // Schedule a Signal command in the queue.
+ GR_D3D_CALL_ERRCHECK(fQueue->Signal(fFence.get(), fFenceValues[fBufferIndex]));
+}
+
+void D3D12WindowContext::resize(int width, int height) {
+ // Clean up any outstanding resources in command lists
+ fContext->flush({});
+ fContext->submit(true);
+
+ // release the previous surface and backbuffer resources
+ for (int i = 0; i < kNumFrames; ++i) {
+ // Let present complete
+ if (fFence->GetCompletedValue() < fFenceValues[i]) {
+ GR_D3D_CALL_ERRCHECK(fFence->SetEventOnCompletion(fFenceValues[i], fFenceEvent));
+ WaitForSingleObjectEx(fFenceEvent, INFINITE, FALSE);
+ }
+ fSurfaces[i].reset(nullptr);
+ fBuffers[i].reset(nullptr);
+ }
+
+ GR_D3D_CALL_ERRCHECK(fSwapChain->ResizeBuffers(0, width, height,
+ DXGI_FORMAT_R8G8B8A8_UNORM, 0));
+
+ this->setupSurfaces(width, height);
+
+ fWidth = width;
+ fHeight = height;
+}
+
+void D3D12WindowContext::setDisplayParams(const DisplayParams& params) {
+ this->destroyContext();
+ fDisplayParams = params;
+ this->initializeContext();
+}
+
+namespace window_context_factory {
+
+std::unique_ptr<WindowContext> MakeD3D12ForWin(HWND hwnd, const DisplayParams& params) {
+ std::unique_ptr<WindowContext> ctx(new D3D12WindowContext(hwnd, params));
+ if (!ctx->isValid()) {
+ return nullptr;
+ }
+ return ctx;
+}
+
+}
+
+} //namespace sk_app
diff --git a/chromium/third_party/skia/tools/sk_app/win/WindowContextFactory_win.h b/chromium/third_party/skia/tools/sk_app/win/WindowContextFactory_win.h
index 33dd6d413b8..c05a4f0acf5 100644
--- a/chromium/third_party/skia/tools/sk_app/win/WindowContextFactory_win.h
+++ b/chromium/third_party/skia/tools/sk_app/win/WindowContextFactory_win.h
@@ -26,6 +26,10 @@ std::unique_ptr<WindowContext> MakeGLForWin(HWND, const DisplayParams&);
std::unique_ptr<WindowContext> MakeANGLEForWin(HWND, const DisplayParams&);
+#ifdef SK_DIRECT3D
+std::unique_ptr<WindowContext> MakeD3D12ForWin(HWND, const DisplayParams&);
+#endif
+
#ifdef SK_DAWN
std::unique_ptr<WindowContext> MakeDawnD3D12ForWin(HWND, const DisplayParams&);
#endif
diff --git a/chromium/third_party/skia/tools/sk_app/win/Window_win.cpp b/chromium/third_party/skia/tools/sk_app/win/Window_win.cpp
index 9afe0886b40..de001bfbb04 100644
--- a/chromium/third_party/skia/tools/sk_app/win/Window_win.cpp
+++ b/chromium/third_party/skia/tools/sk_app/win/Window_win.cpp
@@ -377,6 +377,12 @@ bool Window_win::attach(BackendType attachType) {
window_context_factory::MakeVulkanForWin(fHWnd, fRequestedDisplayParams);
break;
#endif
+#ifdef SK_DIRECT3D
+ case kDirect3D_BackendType:
+ fWindowContext =
+ window_context_factory::MakeD3D12ForWin(fHWnd, fRequestedDisplayParams);
+ break;
+#endif
}
this->onBackendCreated();
diff --git a/chromium/third_party/skia/tools/skiaserve/Response.cpp b/chromium/third_party/skia/tools/skiaserve/Response.cpp
index d74963a62d5..6ad5c3bfeb0 100644
--- a/chromium/third_party/skia/tools/skiaserve/Response.cpp
+++ b/chromium/third_party/skia/tools/skiaserve/Response.cpp
@@ -25,7 +25,7 @@ static SkString generate_template(SkString source) {
"<head>\n"
" <title>SkDebugger</title>\n"
" <meta charset='utf-8' />\n"
- " <meta http-equiv='X-UA-Compatible' content='IE=egde,chrome=1'>\n"
+ " <meta http-equiv='X-UA-Compatible' content='IE=edge'>\n"
" <meta name='viewport' content='width=device-width, initial-scale=1.0'>\n"
" <script src='%s/res/js/core.js' type='text/javascript' charset='utf-8'></script>\n"
" <link href='%s/res/vul/elements.html' rel='import' />\n"
diff --git a/chromium/third_party/skia/tools/skottie-wasm-perf/skottie-wasm-perf.html b/chromium/third_party/skia/tools/skottie-wasm-perf/skottie-wasm-perf.html
index f7fd4a1e485..ac29945eb0e 100644
--- a/chromium/third_party/skia/tools/skottie-wasm-perf/skottie-wasm-perf.html
+++ b/chromium/third_party/skia/tools/skottie-wasm-perf/skottie-wasm-perf.html
@@ -1,17 +1,17 @@
<!DOCTYPE html>
<html>
<head>
- <title>Skottie-WASM Perf</title>
- <meta charset="utf-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=egde,chrome=1">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <script src="res/canvaskit.js" type="text/javascript" charset="utf-8"></script>
- <style type="text/css" media="screen">
- body {
- margin: 0;
- padding: 0;
- }
- </style>
+ <title>Skottie-WASM Perf</title>
+ <meta charset="utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <script src="res/canvaskit.js" type="text/javascript" charset="utf-8"></script>
+ <style type="text/css" media="screen">
+ body {
+ margin: 0;
+ padding: 0;
+ }
+ </style>
</head>
<body>
<main>
@@ -26,7 +26,7 @@
CanvasKitInit({
locateFile: (file) => '/res/'+file,
- }).ready().then((CanvasKit) => {
+ }).then((CanvasKit) => {
CK = CanvasKit;
Bench(CK, lottieJSON);
});
diff --git a/chromium/third_party/skia/tools/skottie2movie.cpp b/chromium/third_party/skia/tools/skottie2movie.cpp
index ca887b5d729..e9da0d111c6 100644
--- a/chromium/third_party/skia/tools/skottie2movie.cpp
+++ b/chromium/third_party/skia/tools/skottie2movie.cpp
@@ -146,6 +146,7 @@ int main(int argc, char** argv) {
SkSurface::RescaleGamma::kSrc,
kNone_SkFilterQuality,
read_pixels_cb, &asyncRec);
+ surf->getContext()->submit();
} else {
SkPixmap pm;
SkAssertResult(surf->peekPixels(&pm));
diff --git a/chromium/third_party/skia/tools/skottie_ios_app/SkiaGLContext.mm b/chromium/third_party/skia/tools/skottie_ios_app/SkiaGLContext.mm
index 4b12f38f98d..e6e4e048806 100644
--- a/chromium/third_party/skia/tools/skottie_ios_app/SkiaGLContext.mm
+++ b/chromium/third_party/skia/tools/skottie_ios_app/SkiaGLContext.mm
@@ -87,7 +87,7 @@ static sk_sp<SkSurface> make_gl_surface(GrContext* grContext, int width, int hei
[viewController draw:rect
toCanvas:(surface->getCanvas())
atSize:CGSize{(CGFloat)width, (CGFloat)height}];
- surface->flush();
+ surface->flushAndSubmit();
}
if (next) {
[NSTimer scheduledTimerWithTimeInterval:std::max(0.0, next - SkTime::GetNSecs() * 1e-9)
diff --git a/chromium/third_party/skia/tools/skottie_ios_app/SkiaMetalContext.mm b/chromium/third_party/skia/tools/skottie_ios_app/SkiaMetalContext.mm
index b49e360110d..f67d547885f 100644
--- a/chromium/third_party/skia/tools/skottie_ios_app/SkiaMetalContext.mm
+++ b/chromium/third_party/skia/tools/skottie_ios_app/SkiaMetalContext.mm
@@ -55,7 +55,7 @@
return;
}
[viewController draw:rect toCanvas:surface->getCanvas() atSize:size];
- surface->flush();
+ surface->flushAndSubmit();
surface = nullptr;
id<MTLCommandBuffer> commandBuffer = [fQueue commandBuffer];
diff --git a/chromium/third_party/skia/tools/skp/page_sets/skia_css3gradients_desktop.py b/chromium/third_party/skia/tools/skp/page_sets/skia_css3gradients_desktop.py
index 594faf15600..9eaa54a4541 100644
--- a/chromium/third_party/skia/tools/skp/page_sets/skia_css3gradients_desktop.py
+++ b/chromium/third_party/skia/tools/skp/page_sets/skia_css3gradients_desktop.py
@@ -37,7 +37,8 @@ class SkiaCss3gradientsDesktopPageSet(story.StorySet):
urls_list = [
# Why: http://code.google.com/p/chromium/issues/detail?id=168448
- 'https://www.webkit.org/blog/1424/css3-gradients/',
+ # and https://bugs.chromium.org/p/skia/issues/detail?id=10390
+ 'https://www.w3schools.com/css/css3_gradients.asp',
]
for url in urls_list:
diff --git a/chromium/third_party/skia/tools/skpbench/README.md b/chromium/third_party/skia/tools/skpbench/README.md
new file mode 100644
index 00000000000..830c1568e2d
--- /dev/null
+++ b/chromium/third_party/skia/tools/skpbench/README.md
@@ -0,0 +1,67 @@
+# skpbench
+
+skpbench is a benchmarking tool for replaying skp or mksp files on android devices.
+it achieves a lower variance in framerate by controlling the clock speed and stopping
+all other processes that could cause interference.
+
+## Build
+
+skpbench consists of the skpbench binary which must be built for the phone you intend to run on,
+and skpbench.py which runs on the machine the phone is connected to via ADB and is the entry point.
+
+The to build skia for android are at https://skia.org/user/build#android and reproduced here.
+
+Download the Android NDK
+
+```
+cipd auth-login
+python2 infra/bots/assets/android_ndk_linux/download.py -t /tmp/ndk
+
+```
+
+After this is set up once, build skpbench for your target cpu (assumed to be arm64 here for a Pixel 3)
+
+```
+bin/gn gen out/arm64 --args='ndk="/tmp/ndk" target_cpu="arm64" is_debug=false'
+ninja -C out/arm64 skpbench
+```
+
+## Benchmark an SKP on a connected device.
+
+First, copy the built skpbench binary and an example skp file to the device.
+
+```
+adb push out/arm64/skpbench /data/local/tmp
+adb push /home/nifong/Downloads/foo.skp /data/local/tmp/skps/
+```
+
+Run skpbench.py (in my case on a Pixel 3)
+
+```
+python tools/skpbench/skpbench.py \
+ --adb \
+ --force \
+ --config gles \
+ /data/local/tmp/skpbench \
+ /data/local/tmp/skps/foo.skp
+```
+
+`--adb` specifies that it should use adb to the only connected device and run skpbench there.
+`--force` is necessary because we don't yet have a configuration to monitor vitals on the Pixel 3.
+`--config gles` specifies Open GL ES is the backend GPU config to use.
+
+Additional documentation of arguments is printed by `python tools/skpbench/skpbench.py --help`
+
+Output appears in the following format
+```
+ accum median max min stddev samples sample_ms clock metric config bench
+ 0.1834 0.1832 0.1897 0.1707 1.59% 101 50 cpu ms gles foo.skp
+```
+
+`accum` is the time taken to draw all frames, divided by the number of frames.
+`metric` specifies that the unit is ms (milliseconds per frame)
+
+## Production
+
+skpbench is run as a tryjob from gerrit, where it uploads the results to perf.skia.org.
+TODO(nifong, csmartdalton): elaborate on this section. \ No newline at end of file
diff --git a/chromium/third_party/skia/tools/skpbench/skpbench.cpp b/chromium/third_party/skia/tools/skpbench/skpbench.cpp
index 8a0dda48a0b..e0c0fcb5776 100644
--- a/chromium/third_party/skia/tools/skpbench/skpbench.cpp
+++ b/chromium/third_party/skia/tools/skpbench/skpbench.cpp
@@ -60,8 +60,7 @@
*/
static DEFINE_bool(ddl, false, "record the skp into DDLs before rendering");
-static DEFINE_int(ddlNumAdditionalThreads, 0,
- "number of DDL recording threads in addition to main one");
+static DEFINE_int(ddlNumRecordingThreads, 0, "number of DDL recording threads (0=num_cores)");
static DEFINE_int(ddlTilingWidthHeight, 0, "number of tiles along one edge when in DDL mode");
static DEFINE_bool(comparableDDL, false, "render in a way that is comparable to 'comparableSKP'");
@@ -201,7 +200,8 @@ private:
std::vector<SkDocumentPage> fFrames;
};
-static void ddl_sample(GrContext* context, DDLTileHelper* tiles, GpuSync& gpuSync, Sample* sample,
+static void ddl_sample(GrContext* context, DDLTileHelper* tiles, GpuSync& gpuSync,
+ Sample* sample, SkTaskGroup* recordingTaskGroup, SkTaskGroup* gpuTaskGroup,
std::chrono::high_resolution_clock::time_point* startStopTime) {
using clock = std::chrono::high_resolution_clock;
@@ -220,12 +220,18 @@ static void ddl_sample(GrContext* context, DDLTileHelper* tiles, GpuSync& gpuSyn
// through a DDL.
tiles->drawAllTilesDirectly(context);
} else {
- // TODO: Here we create all the DDLs, wait, and then draw them all. This should be updated
- // to use the GPUDDLSink method of having a separate GPU thread.
- tiles->createDDLsInParallel();
- tiles->precompileAndDrawAllTiles(context);
+ tiles->kickOffThreadedWork(recordingTaskGroup, gpuTaskGroup, context);
+ recordingTaskGroup->wait();
+ }
+
+ if (gpuTaskGroup) {
+ gpuTaskGroup->add([&]{
+ flush_with_sync(context, gpuSync);
+ });
+ gpuTaskGroup->wait();
+ } else {
+ flush_with_sync(context, gpuSync);
}
- flush_with_sync(context, gpuSync);
*startStopTime = clock::now();
@@ -235,8 +241,9 @@ static void ddl_sample(GrContext* context, DDLTileHelper* tiles, GpuSync& gpuSyn
}
}
-static void run_ddl_benchmark(GrContext* context, sk_sp<SkSurface> dstSurface,
- SkPicture* inputPicture, std::vector<Sample>* samples) {
+static void run_ddl_benchmark(sk_gpu_test::TestContext* testContext, GrContext *context,
+ sk_sp<SkSurface> dstSurface, SkPicture* inputPicture,
+ std::vector<Sample>* samples) {
using clock = std::chrono::high_resolution_clock;
const Sample::duration sampleDuration = std::chrono::milliseconds(FLAGS_sampleMs);
const clock::duration benchDuration = std::chrono::milliseconds(FLAGS_duration);
@@ -262,12 +269,26 @@ static void run_ddl_benchmark(GrContext* context, sk_sp<SkSurface> dstSurface,
tiles.createSKPPerTile(compressedPictureData.get(), promiseImageHelper);
- SkTaskGroup::Enabler enabled(FLAGS_ddlNumAdditionalThreads);
+ // In comparable modes, there is no GPU thread. The following pointers are all null.
+ // Otherwise, we transfer testContext onto the GPU thread until after the bench.
+ std::unique_ptr<SkExecutor> gpuThread;
+ std::unique_ptr<SkTaskGroup> gpuTaskGroup;
+ std::unique_ptr<SkExecutor> recordingThreadPool;
+ std::unique_ptr<SkTaskGroup> recordingTaskGroup;
+ if (!FLAGS_comparableDDL && !FLAGS_comparableSKP) {
+ gpuThread = SkExecutor::MakeFIFOThreadPool(1, false);
+ gpuTaskGroup = std::make_unique<SkTaskGroup>(*gpuThread);
+ recordingThreadPool = SkExecutor::MakeFIFOThreadPool(FLAGS_ddlNumRecordingThreads, false);
+ recordingTaskGroup = std::make_unique<SkTaskGroup>(*recordingThreadPool);
+ testContext->makeNotCurrent();
+ gpuTaskGroup->add([=]{ testContext->makeCurrent(); });
+ }
clock::time_point startStopTime = clock::now();
GpuSync gpuSync;
- ddl_sample(context, &tiles, gpuSync, nullptr, &startStopTime);
+ ddl_sample(context, &tiles, gpuSync, nullptr, recordingTaskGroup.get(),
+ gpuTaskGroup.get(), &startStopTime);
clock::duration cumulativeDuration = std::chrono::milliseconds(0);
@@ -277,16 +298,26 @@ static void run_ddl_benchmark(GrContext* context, sk_sp<SkSurface> dstSurface,
do {
tiles.resetAllTiles();
- ddl_sample(context, &tiles, gpuSync, &sample, &startStopTime);
+ ddl_sample(context, &tiles, gpuSync, &sample, recordingTaskGroup.get(),
+ gpuTaskGroup.get(), &startStopTime);
} while (sample.fDuration < sampleDuration);
cumulativeDuration += sample.fDuration;
} while (cumulativeDuration < benchDuration || 0 == samples->size() % 2);
+ // Move the context back to this thread now that we're done benching.
+ if (gpuTaskGroup) {
+ gpuTaskGroup->add([=]{
+ testContext->makeNotCurrent();
+ });
+ gpuTaskGroup->wait();
+ testContext->makeCurrent();
+ }
+
if (!FLAGS_png.isEmpty()) {
// The user wants to see the final result
dstSurface->draw(tiles.composeDDL());
- dstSurface->flush();
+ dstSurface->flushAndSubmit();
}
tiles.resetAllTiles();
@@ -296,6 +327,7 @@ static void run_ddl_benchmark(GrContext* context, sk_sp<SkSurface> dstSurface,
GrFlushInfo flushInfo;
flushInfo.fFlags = kSyncCpu_GrFlushFlag;
context->flush(flushInfo);
+ context->submit(true);
promiseImageHelper.deleteAllFromGPU(nullptr, context);
@@ -335,6 +367,7 @@ static void run_benchmark(GrContext* context, SkSurface* surface, SkpProducer* s
GrFlushInfo flushInfo;
flushInfo.fFlags = kSyncCpu_GrFlushFlag;
surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
+ context->submit(true);
}
static void run_gpu_time_benchmark(sk_gpu_test::GpuTimer* gpuTimer, GrContext* context,
@@ -377,8 +410,10 @@ static void run_gpu_time_benchmark(sk_gpu_test::GpuTimer* gpuTimer, GrContext* c
using QueryStatus = sk_gpu_test::GpuTimer::QueryStatus;
case QueryStatus::kInvalid:
exitf(ExitErr::kUnavailable, "GPU timer failed");
+ break;
case QueryStatus::kPending:
exitf(ExitErr::kUnavailable, "timer query still not ready after fence sync");
+ break;
case QueryStatus::kDisjoint:
if (FLAGS_verbosity >= 4) {
fprintf(stderr, "discarding timer query due to disjoint operations.\n");
@@ -402,6 +437,7 @@ static void run_gpu_time_benchmark(sk_gpu_test::GpuTimer* gpuTimer, GrContext* c
GrFlushInfo flushInfo;
flushInfo.fFlags = kSyncCpu_GrFlushFlag;
surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
+ context->submit(true);
}
void print_result(const std::vector<Sample>& samples, const char* config, const char* bench) {
@@ -577,7 +613,7 @@ int main(int argc, char** argv) {
}
if (!FLAGS_gpuClock) {
if (FLAGS_ddl) {
- run_ddl_benchmark(ctx, surface, skp.get(), &samples);
+ run_ddl_benchmark(testCtx, ctx, surface, skp.get(), &samples);
} else if (!mskp) {
auto s = std::make_unique<StaticSkp>(skp);
run_benchmark(ctx, surface.get(), s.get(), &samples);
@@ -621,6 +657,7 @@ static void flush_with_sync(GrContext* context, GpuSync& gpuSync) {
flushInfo.fFinishedContext = gpuSync.newFlushTracker(context);
context->flush(flushInfo);
+ context->submit();
}
static void draw_skp_and_flush_with_sync(GrContext* context, SkSurface* surface,
diff --git a/chromium/third_party/skia/tools/skpbench/skpbench.py b/chromium/third_party/skia/tools/skpbench/skpbench.py
index 8c53e9aed45..8c148188808 100755
--- a/chromium/third_party/skia/tools/skpbench/skpbench.py
+++ b/chromium/third_party/skia/tools/skpbench/skpbench.py
@@ -73,9 +73,9 @@ __argparse.add_argument('-a', '--resultsfile',
help="optional file to append results into")
__argparse.add_argument('--ddl',
action='store_true', help="record the skp into DDLs before rendering")
-__argparse.add_argument('--ddlNumAdditionalThreads',
+__argparse.add_argument('--ddlNumRecordingThreads',
type=int, default=0,
- help="number of DDL recording threads in addition to main one")
+ help="number of DDL recording threads (0=num_cores)")
__argparse.add_argument('--ddlTilingWidthHeight',
type=int, default=0, help="number of tiles along one edge when in DDL mode")
__argparse.add_argument('--gpuThreads',
@@ -144,9 +144,9 @@ class SKPBench:
# DDL parameters
if FLAGS.ddl:
ARGV.extend(['--ddl', 'true'])
- if FLAGS.ddlNumAdditionalThreads:
- ARGV.extend(['--ddlNumAdditionalThreads',
- str(FLAGS.ddlNumAdditionalThreads)])
+ if FLAGS.ddlNumRecordingThreads:
+ ARGV.extend(['--ddlNumRecordingThreads',
+ str(FLAGS.ddlNumRecordingThreads)])
if FLAGS.ddlTilingWidthHeight:
ARGV.extend(['--ddlTilingWidthHeight', str(FLAGS.ddlTilingWidthHeight)])
diff --git a/chromium/third_party/skia/tools/skqp/bad_gms.txt b/chromium/third_party/skia/tools/skqp/bad_gms.txt
index 551ba444af8..bf0c1f3b676 100644
--- a/chromium/third_party/skia/tools/skqp/bad_gms.txt
+++ b/chromium/third_party/skia/tools/skqp/bad_gms.txt
@@ -1,5 +1,4 @@
arcs_as_paths
-atlastext
bigbitmaprect_i
bigbitmaprect_s
blurcircles2
diff --git a/chromium/third_party/skia/tools/valgrind.supp b/chromium/third_party/skia/tools/valgrind.supp
index 1e3a3e84106..57f7586ecfb 100644
--- a/chromium/third_party/skia/tools/valgrind.supp
+++ b/chromium/third_party/skia/tools/valgrind.supp
@@ -317,3 +317,19 @@
fun:_Z12GrClearImageRK11GrImageInfoPvm8SkRGBA4fIL11SkAlphaType3EE
...
}
+{
+ make_get_error_with_random_oom1
+ Memcheck:Leak
+ match-leak-kinds: definite
+ ...
+ fun:_Z30make_get_error_with_random_oom12GrGLFunctionIFjvEE
+ ...
+}
+{
+ make_get_error_with_random_oom2
+ Memcheck:Leak
+ match-leak-kinds: definite
+ ...
+ fun:make_get_error_with_random_oom
+ ...
+}
diff --git a/chromium/third_party/skia/tools/viewer/GMSlide.cpp b/chromium/third_party/skia/tools/viewer/GMSlide.cpp
index 24d8421b304..1f904eb9dce 100644
--- a/chromium/third_party/skia/tools/viewer/GMSlide.cpp
+++ b/chromium/third_party/skia/tools/viewer/GMSlide.cpp
@@ -21,10 +21,15 @@ GMSlide::GMSlide(std::unique_ptr<skiagm::GM> gm) : fGM(std::move(gm)) {
GMSlide::~GMSlide() = default;
void GMSlide::draw(SkCanvas* canvas) {
+ SkString msg;
+
+ fGM->setMode(skiagm::GM::kSample_Mode);
+
+ fGM->gpuSetup(canvas->getGrContext(), &msg);
// Do we care about timing the draw of the background (once)?
// Does the GM ever rely on drawBackground to lazily compute something?
fGM->drawBackground(canvas);
- fGM->drawContent(canvas);
+ fGM->drawContent(canvas, &msg);
}
bool GMSlide::animate(double nanos) { return fGM->animate(nanos); }
diff --git a/chromium/third_party/skia/tools/viewer/ImGuiLayer.cpp b/chromium/third_party/skia/tools/viewer/ImGuiLayer.cpp
index 31b3a54eaae..768e2cce629 100644
--- a/chromium/third_party/skia/tools/viewer/ImGuiLayer.cpp
+++ b/chromium/third_party/skia/tools/viewer/ImGuiLayer.cpp
@@ -53,7 +53,7 @@ ImGuiLayer::ImGuiLayer() {
io.Fonts->GetTexDataAsAlpha8(&pixels, &w, &h);
SkImageInfo info = SkImageInfo::MakeA8(w, h);
SkPixmap pmap(info, pixels, info.minRowBytes());
- SkMatrix localMatrix = SkMatrix::MakeScale(1.0f / w, 1.0f / h);
+ SkMatrix localMatrix = SkMatrix::Scale(1.0f / w, 1.0f / h);
auto fontImage = SkImage::MakeFromRaster(pmap, nullptr, nullptr);
auto fontShader = fontImage->makeShader(&localMatrix);
fFontPaint.setShader(fontShader);
diff --git a/chromium/third_party/skia/tools/viewer/SKPSlide.cpp b/chromium/third_party/skia/tools/viewer/SKPSlide.cpp
index 1c03a5e4df0..b4655090641 100644
--- a/chromium/third_party/skia/tools/viewer/SKPSlide.cpp
+++ b/chromium/third_party/skia/tools/viewer/SKPSlide.cpp
@@ -11,7 +11,12 @@
#include "include/core/SkStream.h"
#include "src/core/SkOSFile.h"
-SKPSlide::SKPSlide(const SkString& name, const SkString& path) : fPath(path) {
+SKPSlide::SKPSlide(const SkString& name, const SkString& path)
+ : SKPSlide(name, SkStream::MakeFromFile(path.c_str())) {
+}
+
+SKPSlide::SKPSlide(const SkString& name, std::unique_ptr<SkStream> stream)
+ : fStream(std::move(stream)) {
fName = name;
}
@@ -33,25 +38,18 @@ void SKPSlide::draw(SkCanvas* canvas) {
}
}
-static sk_sp<SkPicture> read_picture(const char path[]) {
- std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(path);
- if (!stream) {
- SkDebugf("Could not read %s.\n", path);
- return nullptr;
- }
-
- auto pic = SkPicture::MakeFromStream(stream.get());
- if (!pic) {
- SkDebugf("Could not read %s as an SkPicture.\n", path);
- }
- return pic;
-}
-
void SKPSlide::load(SkScalar, SkScalar) {
- fPic = read_picture(fPath.c_str());
- if (fPic) {
- fCullRect = fPic->cullRect().roundOut();
+ if (!fStream) {
+ SkDebugf("No skp stream for slide %s.\n", fName.c_str());
+ return;
+ }
+ fStream->rewind();
+ fPic = SkPicture::MakeFromStream(fStream.get());
+ if (!fPic) {
+ SkDebugf("Could parse SkPicture from skp stream for slide %s.\n", fName.c_str());
+ return;
}
+ fCullRect = fPic->cullRect().roundOut();
}
void SKPSlide::unload() {
diff --git a/chromium/third_party/skia/tools/viewer/SKPSlide.h b/chromium/third_party/skia/tools/viewer/SKPSlide.h
index e20225038cb..5e88ae0a39e 100644
--- a/chromium/third_party/skia/tools/viewer/SKPSlide.h
+++ b/chromium/third_party/skia/tools/viewer/SKPSlide.h
@@ -14,6 +14,7 @@
class SKPSlide : public Slide {
public:
SKPSlide(const SkString& name, const SkString& path);
+ SKPSlide(const SkString& name, std::unique_ptr<SkStream>);
~SKPSlide() override;
SkISize getDimensions() const override { return fCullRect.size(); }
@@ -23,9 +24,9 @@ public:
void unload() override;
private:
- SkString fPath;
+ std::unique_ptr<SkStream> fStream;
sk_sp<const SkPicture> fPic;
- SkIRect fCullRect;
+ SkIRect fCullRect;
};
#endif
diff --git a/chromium/third_party/skia/tools/viewer/SkRiveSlide.cpp b/chromium/third_party/skia/tools/viewer/SkRiveSlide.cpp
new file mode 100644
index 00000000000..de29104c01d
--- /dev/null
+++ b/chromium/third_party/skia/tools/viewer/SkRiveSlide.cpp
@@ -0,0 +1,69 @@
+/*
+ * 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 "tools/viewer/SkRiveSlide.h"
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkStream.h"
+
+#if defined(SK_ENABLE_SKRIVE)
+
+SkRiveSlide::SkRiveSlide(const SkString& name, const SkString& path)
+ : fPath(path) {
+ fName = name;
+}
+
+SkRiveSlide::~SkRiveSlide() = default;
+
+void SkRiveSlide::load(SkScalar w, SkScalar h) {
+ fWinSize = {w , h};
+ fRive = skrive::SkRive::Builder().make(SkFILEStream::Make(fPath.c_str()));
+ fRiveBounds = SkRect::MakeEmpty();
+
+ if (fRive) {
+ SkDebugf("Loaded Rive animation: %zu artboards\n", fRive->artboards().size());
+ for (const auto& ab : fRive->artboards()) {
+ const auto& pos = ab->getTranslation();
+ const auto& size = ab->getSize();
+
+ fRiveBounds.join(SkRect::MakeXYWH(pos.x, pos.y, size.x, size.y));
+ }
+ } else {
+ SkDebugf("Failed to load Rive animation: %s\n", fPath.c_str());
+ }
+}
+
+void SkRiveSlide::unload() {
+ fRive.reset();
+}
+
+void SkRiveSlide::resize(SkScalar w, SkScalar h) {
+ fWinSize = {w , h};
+}
+
+SkISize SkRiveSlide::getDimensions() const {
+ // We always scale to fill the window.
+ return fWinSize.toCeil();
+}
+
+void SkRiveSlide::draw(SkCanvas* canvas) {
+ if (!fRive) {
+ return;
+ }
+
+ // Scale the Rive artboards to fill our window.
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->concat(SkMatrix::MakeRectToRect(fRiveBounds,
+ SkRect::MakeSize(fWinSize),
+ SkMatrix::kCenter_ScaleToFit ));
+
+ for (const auto& ab : fRive->artboards()) {
+ ab->render(canvas);
+ }
+}
+
+#endif // defined(SK_ENABLE_SKRIVE)
diff --git a/chromium/third_party/skia/tools/viewer/SkRiveSlide.h b/chromium/third_party/skia/tools/viewer/SkRiveSlide.h
new file mode 100644
index 00000000000..820902e76e1
--- /dev/null
+++ b/chromium/third_party/skia/tools/viewer/SkRiveSlide.h
@@ -0,0 +1,41 @@
+/*
+ * 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 SkRiveSlide_DEFINED
+#define SkRiveSlide_DEFINED
+
+#include "tools/viewer/Slide.h"
+
+#if defined(SK_ENABLE_SKRIVE)
+
+#include "experimental/skrive/include/SkRive.h"
+
+class SkRiveSlide final : public Slide {
+public:
+ SkRiveSlide(const SkString& name, const SkString& path);
+ ~SkRiveSlide() override;
+
+private:
+ void load(SkScalar winWidth, SkScalar winHeight) override;
+ void unload() override;
+ void resize(SkScalar, SkScalar) override;
+
+ SkISize getDimensions() const override;
+
+ void draw(SkCanvas*) override;
+
+ const SkString fPath;
+
+ sk_sp<skrive::SkRive> fRive;
+ SkRect fRiveBounds;
+ SkSize fWinSize;
+
+ using INHERITED = Slide;
+};
+
+#endif // defined(SK_ENABLE_SKRIVE)
+#endif // SkRiveSlide_DEFINED
diff --git a/chromium/third_party/skia/tools/viewer/SkSLSlide.cpp b/chromium/third_party/skia/tools/viewer/SkSLSlide.cpp
index f564df25a94..81a628cd28c 100644
--- a/chromium/third_party/skia/tools/viewer/SkSLSlide.cpp
+++ b/chromium/third_party/skia/tools/viewer/SkSLSlide.cpp
@@ -10,12 +10,9 @@
#include "include/core/SkCanvas.h"
#include "include/effects/SkGradientShader.h"
#include "include/effects/SkPerlinNoiseShader.h"
-#include "include/gpu/GrContext.h"
#include "src/core/SkEnumerate.h"
-#include "src/gpu/GrContextPriv.h"
-#include "src/gpu/GrShaderUtils.h"
#include "tools/Resources.h"
-#include "tools/viewer/ImGuiLayer.h"
+#include "tools/viewer/Viewer.h"
#include <algorithm>
#include "imgui.h"
@@ -41,10 +38,10 @@ SkSLSlide::SkSLSlide() {
fSkSL =
- "in fragmentProcessor fp;\n"
+ "in shader child;\n"
"\n"
"void main(float2 p, inout half4 color) {\n"
- " color = sample(fp, p);\n"
+ " color = sample(child, p);\n"
"}\n";
fCodeIsDirty = true;
@@ -80,10 +77,10 @@ void SkSLSlide::unload() {
fShaders.reset();
}
-bool SkSLSlide::rebuild(GrContextOptions::ShaderErrorHandler* errorHandler) {
+bool SkSLSlide::rebuild() {
auto [effect, errorText] = SkRuntimeEffect::Make(fSkSL);
if (!effect) {
- errorHandler->compileError(fSkSL.c_str(), errorText.c_str());
+ Viewer::ShaderErrorHandler()->compileError(fSkSL.c_str(), errorText.c_str());
return false;
}
@@ -105,10 +102,6 @@ bool SkSLSlide::rebuild(GrContextOptions::ShaderErrorHandler* errorHandler) {
}
void SkSLSlide::draw(SkCanvas* canvas) {
- GrContextOptions::ShaderErrorHandler* errorHandler = GrShaderUtils::DefaultShaderErrorHandler();
- if (auto grContext = canvas->getGrContext()) {
- errorHandler = grContext->priv().getShaderErrorHandler();
- }
canvas->clear(SK_ColorWHITE);
ImGui::Begin("SkSL", nullptr, ImGuiWindowFlags_AlwaysVerticalScrollbar);
@@ -122,7 +115,7 @@ void SkSLSlide::draw(SkCanvas* canvas) {
}
if (fCodeIsDirty || !fEffect) {
- this->rebuild(errorHandler);
+ this->rebuild();
}
if (!fEffect) {
diff --git a/chromium/third_party/skia/tools/viewer/SkSLSlide.h b/chromium/third_party/skia/tools/viewer/SkSLSlide.h
index a778350ef11..4287c398b9d 100644
--- a/chromium/third_party/skia/tools/viewer/SkSLSlide.h
+++ b/chromium/third_party/skia/tools/viewer/SkSLSlide.h
@@ -11,7 +11,6 @@
#include "tools/viewer/Slide.h"
#include "include/effects/SkRuntimeEffect.h"
-#include "include/gpu/GrContextOptions.h"
class SkSLSlide : public Slide {
public:
@@ -26,7 +25,7 @@ public:
void unload() override;
private:
- bool rebuild(GrContextOptions::ShaderErrorHandler*);
+ bool rebuild();
SkString fSkSL;
bool fCodeIsDirty;
diff --git a/chromium/third_party/skia/tools/viewer/SkottieSlide.cpp b/chromium/third_party/skia/tools/viewer/SkottieSlide.cpp
index 9467c52c0c4..18561356dde 100644
--- a/chromium/third_party/skia/tools/viewer/SkottieSlide.cpp
+++ b/chromium/third_party/skia/tools/viewer/SkottieSlide.cpp
@@ -96,7 +96,12 @@ void SkottieSlide::load(SkScalar w, SkScalar h) {
};
auto logger = sk_make_sp<Logger>();
- skottie::Animation::Builder builder;
+
+ uint32_t flags = 0;
+ if (fPreferGlyphPaths) {
+ flags |= skottie::Animation::Builder::kPreferEmbeddedFonts;
+ }
+ skottie::Animation::Builder builder(flags);
auto resource_provider =
skresources::DataURIResourceProviderProxy::Make(
@@ -221,9 +226,11 @@ bool SkottieSlide::onChar(SkUnichar c) {
switch (c) {
case 'I':
fShowAnimationStats = !fShowAnimationStats;
- break;
- default:
- break;
+ return true;
+ case 'G':
+ fPreferGlyphPaths = !fPreferGlyphPaths;
+ this->load(fWinSize.width(), fWinSize.height());
+ return true;
}
return INHERITED::onChar(c);
diff --git a/chromium/third_party/skia/tools/viewer/SkottieSlide.h b/chromium/third_party/skia/tools/viewer/SkottieSlide.h
index dd0a49f66b1..aec76a32cac 100644
--- a/chromium/third_party/skia/tools/viewer/SkottieSlide.h
+++ b/chromium/third_party/skia/tools/viewer/SkottieSlide.h
@@ -53,7 +53,8 @@ private:
bool fShowAnimationInval = false,
fShowAnimationStats = false,
fShowUI = false,
- fDraggingProgress = false;
+ fDraggingProgress = false,
+ fPreferGlyphPaths = false;
typedef Slide INHERITED;
};
diff --git a/chromium/third_party/skia/tools/viewer/SvgSlide.cpp b/chromium/third_party/skia/tools/viewer/SvgSlide.cpp
index 3779ffd3f7f..c420843464c 100644
--- a/chromium/third_party/skia/tools/viewer/SvgSlide.cpp
+++ b/chromium/third_party/skia/tools/viewer/SvgSlide.cpp
@@ -14,18 +14,26 @@
#include "include/core/SkStream.h"
SvgSlide::SvgSlide(const SkString& name, const SkString& path)
- : fPath(path) {
+ : SvgSlide(name, SkStream::MakeFromFile(path.c_str())) {
+}
+
+SvgSlide::SvgSlide(const SkString& name, std::unique_ptr<SkStream> stream)
+ : fStream(std::move(stream)) {
fName = name;
}
void SvgSlide::load(SkScalar w, SkScalar h) {
- fWinSize = SkSize::Make(w, h);
+ if (!fStream) {
+ SkDebugf("No svg stream for slide %s.\n", fName.c_str());
+ return;
+ }
- if (const auto svgStream = SkStream::MakeFromFile(fPath.c_str())) {
- fDom = SkSVGDOM::MakeFromStream(*svgStream);
- if (fDom) {
- fDom->setContainerSize(fWinSize);
- }
+ fWinSize = SkSize::Make(w, h);
+
+ fStream->rewind();
+ fDom = SkSVGDOM::MakeFromStream(*fStream);
+ if (fDom) {
+ fDom->setContainerSize(fWinSize);
}
}
diff --git a/chromium/third_party/skia/tools/viewer/SvgSlide.h b/chromium/third_party/skia/tools/viewer/SvgSlide.h
index ccc840ed8c8..6a15a307b0c 100644
--- a/chromium/third_party/skia/tools/viewer/SvgSlide.h
+++ b/chromium/third_party/skia/tools/viewer/SvgSlide.h
@@ -15,6 +15,7 @@ class SkSVGDOM;
class SvgSlide final : public Slide {
public:
SvgSlide(const SkString& name, const SkString& path);
+ SvgSlide(const SkString& name, std::unique_ptr<SkStream>);
void load(SkScalar winWidth, SkScalar winHeight) override;
void unload() override;
@@ -24,9 +25,8 @@ public:
void draw(SkCanvas*) override;
private:
- const SkString fPath;
-
- SkSize fWinSize = SkSize::MakeEmpty();
+ std::unique_ptr<SkStream> fStream;
+ SkSize fWinSize = SkSize::MakeEmpty();
sk_sp<SkSVGDOM> fDom;
typedef Slide INHERITED;
diff --git a/chromium/third_party/skia/tools/viewer/Viewer.cpp b/chromium/third_party/skia/tools/viewer/Viewer.cpp
index 6d41aad1ce7..45d4fbd177b 100644
--- a/chromium/third_party/skia/tools/viewer/Viewer.cpp
+++ b/chromium/third_party/skia/tools/viewer/Viewer.cpp
@@ -50,9 +50,16 @@
#include "imgui.h"
#include "misc/cpp/imgui_stdlib.h" // For ImGui support of std::string
+#ifdef SK_VULKAN
+#include "spirv-tools/libspirv.hpp"
+#endif
+
#if defined(SK_ENABLE_SKOTTIE)
#include "tools/viewer/SkottieSlide.h"
#endif
+#if defined(SK_ENABLE_SKRIVE)
+ #include "tools/viewer/SkRiveSlide.h"
+#endif
class CapturingShaderErrorHandler : public GrContextOptions::ShaderErrorHandler {
public:
@@ -72,6 +79,8 @@ public:
static CapturingShaderErrorHandler gShaderErrorHandler;
+GrContextOptions::ShaderErrorHandler* Viewer::ShaderErrorHandler() { return &gShaderErrorHandler; }
+
using namespace sk_app;
static std::map<GpuPathRenderers, std::string> gPathRendererNames;
@@ -83,15 +92,34 @@ Application* Application::Create(int argc, char** argv, void* platformData) {
static DEFINE_string(slide, "", "Start on this sample.");
static DEFINE_bool(list, false, "List samples?");
-#if defined(SK_VULKAN)
-# define BACKENDS_STR "\"sw\", \"gl\", and \"vk\""
-#elif defined(SK_METAL) && defined(SK_BUILD_FOR_MAC)
-# define BACKENDS_STR "\"sw\", \"gl\", and \"mtl\""
-#elif defined(SK_DAWN)
-# define BACKENDS_STR "\"sw\", \"gl\", and \"dawn\""
+#ifdef SK_GL
+#define GL_BACKEND_STR ", \"gl\""
+#else
+#define GL_BACKEND_STR
+#endif
+#ifdef SK_VULKAN
+#define VK_BACKEND_STR ", \"vk\""
+#else
+#define VK_BACKEND_STR
+#endif
+#ifdef SK_METAL
+#define MTL_BACKEND_STR ", \"mtl\""
+#else
+#define MTL_BACKEND_STR
+#endif
+#ifdef SK_DIRECT3D
+#define D3D_BACKEND_STR ", \"d3d\""
#else
-# define BACKENDS_STR "\"sw\" and \"gl\""
+#define D3D_BACKEND_STR
#endif
+#ifdef SK_DAWN
+#define DAWN_BACKEND_STR ", \"dawn\""
+#else
+#define DAWN_BACKEND_STR
+#endif
+#define BACKENDS_STR_EVALUATOR(sw, gl, vk, mtl, d3d, dawn) sw gl vk mtl d3d dawn
+#define BACKENDS_STR BACKENDS_STR_EVALUATOR( \
+ "\"sw\"", GL_BACKEND_STR, VK_BACKEND_STR, MTL_BACKEND_STR, D3D_BACKEND_STR, DAWN_BACKEND_STR)
static DEFINE_string2(backend, b, "sw", "Backend to use. Allowed values are " BACKENDS_STR ".");
@@ -116,10 +144,13 @@ static DEFINE_string2(match, m, nullptr,
static DEFINE_string(skps, "/data/local/tmp/skps", "Directory to read skps from.");
static DEFINE_string(lotties, "/data/local/tmp/lotties",
"Directory to read (Bodymovin) jsons from.");
+ static DEFINE_string(rives, "/data/local/tmp/rives",
+ "Directory to read Rive (Flare) files from.");
#else
static DEFINE_string(jpgs, "jpgs", "Directory to read jpgs from.");
static DEFINE_string(skps, "skps", "Directory to read skps from.");
static DEFINE_string(lotties, "lotties", "Directory to read (Bodymovin) jsons from.");
+ static DEFINE_string(rives, "rives", "Directory to read Rive (Flare) files from.");
#endif
static DEFINE_string(svgs, "", "Directory to read SVGs from, or a single SVG file.");
@@ -153,6 +184,9 @@ const char* kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = {
#ifdef SK_METAL
"Metal",
#endif
+#ifdef SK_DIRECT3D
+ "Direct3D",
+#endif
"Raster"
};
@@ -177,6 +211,12 @@ static sk_app::Window::BackendType get_backend_type(const char* str) {
return sk_app::Window::kMetal_BackendType;
} else
#endif
+#ifdef SK_DIRECT3D
+ if (0 == strcmp(str, "d3d")) {
+ return sk_app::Window::kDirect3D_BackendType;
+ } else
+#endif
+
if (0 == strcmp(str, "gl")) {
return sk_app::Window::kNativeGL_BackendType;
} else if (0 == strcmp(str, "sw")) {
@@ -666,6 +706,12 @@ void Viewer::initSlides() {
return sk_make_sp<SkottieSlide>(name, path);}
},
#endif
+ #if defined(SK_ENABLE_SKRIVE)
+ { ".flr", "skrive-dir", FLAGS_rives,
+ [](const SkString& name, const SkString& path) -> sk_sp<Slide> {
+ return sk_make_sp<SkRiveSlide>(name, path);}
+ },
+ #endif
#if defined(SK_XML)
{ ".svg", "svg-dir", FLAGS_svgs,
[](const SkString& name, const SkString& path) -> sk_sp<Slide> {
@@ -1133,7 +1179,7 @@ SkMatrix Viewer::computeMatrix() {
void Viewer::setBackend(sk_app::Window::BackendType backendType) {
fPersistentCache.reset();
- fCachedGLSL.reset();
+ fCachedShaders.reset();
fBackendType = backendType;
fWindow->detach();
@@ -1422,7 +1468,7 @@ void Viewer::drawSlide(SkSurface* surface) {
// Force a flush so we can time that, too
fStatsLayer.beginTiming(fFlushTimer);
- slideSurface->flush();
+ slideSurface->flushAndSubmit();
fStatsLayer.endTiming(fFlushTimer);
// If we rendered offscreen, snap an image and push the results to the window's canvas
@@ -1647,6 +1693,35 @@ static bool ImGui_DragQuad(SkPoint* pts) {
return dc.fDragging;
}
+static SkSL::String build_sksl_highlight_shader() {
+ return SkSL::String("out half4 sk_FragColor;\n"
+ "void main() { sk_FragColor = half4(1, 0, 1, 0.5); }");
+}
+
+static SkSL::String build_metal_highlight_shader(const SkSL::String& inShader) {
+ // Metal fragment shaders need a lot of non-trivial boilerplate that we don't want to recompute
+ // here. So keep all shader code, but right before `return *_out;`, swap out the sk_FragColor.
+ size_t pos = inShader.rfind("return *_out;\n");
+ if (pos == std::string::npos) {
+ return inShader;
+ }
+
+ SkSL::String replacementShader = inShader;
+ replacementShader.insert(pos, "_out->sk_FragColor = float4(1.0, 0.0, 1.0, 0.5); ");
+ return replacementShader;
+}
+
+static SkSL::String build_glsl_highlight_shader(const GrShaderCaps& shaderCaps) {
+ const char* versionDecl = shaderCaps.versionDeclString();
+ SkSL::String highlight = versionDecl ? versionDecl : "";
+ if (shaderCaps.usesPrecisionModifiers()) {
+ highlight.append("precision mediump float;\n");
+ }
+ highlight.appendf("out vec4 sk_FragColor;\n"
+ "void main() { sk_FragColor = vec4(1, 0, 1, 0.5); }");
+ return highlight;
+}
+
void Viewer::drawImGui() {
// Support drawing the ImGui demo window. Superfluous, but gives a good idea of what's possible
if (fShowImGuiTestWindow) {
@@ -1684,6 +1759,10 @@ void Viewer::drawImGui() {
ImGui::SameLine();
ImGui::RadioButton("Metal", &newBackend, sk_app::Window::kMetal_BackendType);
#endif
+#if defined(SK_DIRECT3D)
+ ImGui::SameLine();
+ ImGui::RadioButton("Direct3D", &newBackend, sk_app::Window::kDirect3D_BackendType);
+#endif
if (newBackend != fBackendType) {
fDeferredActions.push_back([=]() {
this->setBackend(static_cast<sk_app::Window::BackendType>(newBackend));
@@ -2147,30 +2226,22 @@ void Viewer::drawImGui() {
}
}
- bool backendIsGL = Window::kNativeGL_BackendType == fBackendType
-#if SK_ANGLE && defined(SK_BUILD_FOR_WIN)
- || Window::kANGLE_BackendType == fBackendType
+ if (ImGui::CollapsingHeader("Shaders")) {
+ bool sksl = params.fGrContextOptions.fShaderCacheStrategy ==
+ GrContextOptions::ShaderCacheStrategy::kSkSL;
+#if defined(SK_VULKAN)
+ const bool isVulkan = fBackendType == sk_app::Window::kVulkan_BackendType;
+#else
+ const bool isVulkan = false;
#endif
- ;
-
- // HACK: If we get here when SKSL caching isn't enabled, and we're on a backend other
- // than GL, we need to force it on. Just do that on the first frame after the backend
- // switch, then resume normal operation.
- if (!backendIsGL &&
- params.fGrContextOptions.fShaderCacheStrategy !=
- GrContextOptions::ShaderCacheStrategy::kSkSL) {
- params.fGrContextOptions.fShaderCacheStrategy =
- GrContextOptions::ShaderCacheStrategy::kSkSL;
- paramsChanged = true;
- fPersistentCache.reset();
- } else if (ImGui::CollapsingHeader("Shaders")) {
- // To re-load shaders from the currently active programs, we flush all caches on one
- // frame, then set a flag to poll the cache on the next frame.
+
+ // To re-load shaders from the currently active programs, we flush all
+ // caches on one frame, then set a flag to poll the cache on the next frame.
static bool gLoadPending = false;
if (gLoadPending) {
auto collectShaders = [this](sk_sp<const SkData> key, sk_sp<SkData> data,
int hitCount) {
- CachedGLSL& entry(fCachedGLSL.push_back());
+ CachedShader& entry(fCachedShaders.push_back());
entry.fKey = key;
SkMD5 hash;
hash.write(key->bytes(), key->size());
@@ -2179,37 +2250,47 @@ void Viewer::drawImGui() {
entry.fKeyString.appendf("%02x", digest.data[i]);
}
- SkReader32 reader(data->data(), data->size());
+ SkReadBuffer reader(data->data(), data->size());
entry.fShaderType = GrPersistentCacheUtils::GetType(&reader);
GrPersistentCacheUtils::UnpackCachedShaders(&reader, entry.fShader,
entry.fInputs,
kGrShaderTypeCount);
};
- fCachedGLSL.reset();
+ fCachedShaders.reset();
fPersistentCache.foreach(collectShaders);
gLoadPending = false;
+
+#if defined(SK_VULKAN)
+ if (isVulkan && !sksl) {
+ spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
+ for (auto& entry : fCachedShaders) {
+ for (int i = 0; i < kGrShaderTypeCount; ++i) {
+ const SkSL::String& spirv(entry.fShader[i]);
+ std::string disasm;
+ tools.Disassemble((const uint32_t*)spirv.c_str(), spirv.size() / 4,
+ &disasm);
+ entry.fShader[i].assign(disasm);
+ }
+ }
+ }
+#endif
}
// Defer actually doing the load/save logic so that we can trigger a save when we
// start or finish hovering on a tree node in the list below:
bool doLoad = ImGui::Button("Load"); ImGui::SameLine();
- bool doSave = ImGui::Button("Save");
- if (backendIsGL) {
- ImGui::SameLine();
- bool sksl = params.fGrContextOptions.fShaderCacheStrategy ==
- GrContextOptions::ShaderCacheStrategy::kSkSL;
- if (ImGui::Checkbox("SkSL", &sksl)) {
- params.fGrContextOptions.fShaderCacheStrategy = sksl
- ? GrContextOptions::ShaderCacheStrategy::kSkSL
- : GrContextOptions::ShaderCacheStrategy::kBackendSource;
- paramsChanged = true;
- doLoad = true;
- fDeferredActions.push_back([=]() { fPersistentCache.reset(); });
- }
+ bool doSave = ImGui::Button("Save"); ImGui::SameLine();
+ if (ImGui::Checkbox("SkSL", &sksl)) {
+ params.fGrContextOptions.fShaderCacheStrategy =
+ sksl ? GrContextOptions::ShaderCacheStrategy::kSkSL
+ : GrContextOptions::ShaderCacheStrategy::kBackendSource;
+ paramsChanged = true;
+ doLoad = true;
+ fDeferredActions.push_back([=]() { fPersistentCache.reset(); });
}
ImGui::BeginChild("##ScrollingRegion");
- for (auto& entry : fCachedGLSL) {
+ for (auto& entry : fCachedShaders) {
bool inTreeNode = ImGui::TreeNode(entry.fKeyString.c_str());
bool hovered = ImGui::IsItemHovered();
if (hovered != entry.fHovered) {
@@ -2234,30 +2315,35 @@ void Viewer::drawImGui() {
fWindow->getGrContext()->priv().getGpu()->resetShaderCacheForTesting();
gLoadPending = true;
}
+ // We don't support updating SPIRV shaders. We could re-assemble them (with edits),
+ // but I'm not sure anyone wants to do that.
+ if (isVulkan && !sksl) {
+ doSave = false;
+ }
if (doSave) {
- // The hovered item (if any) gets a special shader to make it identifiable
- auto shaderCaps = ctx->priv().caps()->shaderCaps();
- bool sksl = params.fGrContextOptions.fShaderCacheStrategy ==
- GrContextOptions::ShaderCacheStrategy::kSkSL;
-
- SkSL::String highlight;
- if (!sksl) {
- highlight = shaderCaps->versionDeclString();
- if (shaderCaps->usesPrecisionModifiers()) {
- highlight.append("precision mediump float;\n");
- }
- }
- const char* f4Type = sksl ? "half4" : "vec4";
- highlight.appendf("out %s sk_FragColor;\n"
- "void main() { sk_FragColor = %s(1, 0, 1, 0.5); }",
- f4Type, f4Type);
-
fPersistentCache.reset();
fWindow->getGrContext()->priv().getGpu()->resetShaderCacheForTesting();
- for (auto& entry : fCachedGLSL) {
+ for (auto& entry : fCachedShaders) {
SkSL::String backup = entry.fShader[kFragment_GrShaderType];
if (entry.fHovered) {
- entry.fShader[kFragment_GrShaderType] = highlight;
+ // The hovered item (if any) gets a special shader to make it
+ // identifiable.
+ SkSL::String& fragShader = entry.fShader[kFragment_GrShaderType];
+ switch (entry.fShaderType) {
+ case SkSetFourByteTag('S', 'K', 'S', 'L'): {
+ fragShader = build_sksl_highlight_shader();
+ break;
+ }
+ case SkSetFourByteTag('G', 'L', 'S', 'L'): {
+ fragShader = build_glsl_highlight_shader(
+ *ctx->priv().caps()->shaderCaps());
+ break;
+ }
+ case SkSetFourByteTag('M', 'S', 'L', ' '): {
+ fragShader = build_metal_highlight_shader(fragShader);
+ break;
+ }
+ }
}
auto data = GrPersistentCacheUtils::PackCachedShaders(entry.fShaderType,
diff --git a/chromium/third_party/skia/tools/viewer/Viewer.h b/chromium/third_party/skia/tools/viewer/Viewer.h
index 41c478e7bcb..47913ae660d 100644
--- a/chromium/third_party/skia/tools/viewer/Viewer.h
+++ b/chromium/third_party/skia/tools/viewer/Viewer.h
@@ -11,6 +11,7 @@
#include "gm/gm.h"
#include "include/core/SkExecutor.h"
#include "include/core/SkFont.h"
+#include "include/gpu/GrContextOptions.h"
#include "src/core/SkScan.h"
#include "src/sksl/SkSLString.h"
#include "src/sksl/ir/SkSLProgram.h"
@@ -45,6 +46,8 @@ public:
bool onPinch(skui::InputState state, float scale, float x, float y) override;
bool onFling(skui::InputState state) override;
+ static GrContextOptions::ShaderErrorHandler* ShaderErrorHandler();
+
struct SkFontFields {
bool fTypeface = false;
bool fSize = false;
@@ -193,7 +196,7 @@ private:
SkFontFields fFontOverrides;
bool fPixelGeometryOverrides = false;
- struct CachedGLSL {
+ struct CachedShader {
bool fHovered = false;
sk_sp<const SkData> fKey;
@@ -205,7 +208,7 @@ private:
};
sk_gpu_test::MemoryCache fPersistentCache;
- SkTArray<CachedGLSL> fCachedGLSL;
+ SkTArray<CachedShader> fCachedShaders;
};
#endif