[graphite] New Combination API
Bug: skia:13430
Change-Id: I816c57d0ed8694d21911c449d67c035580dd63d1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/548776
Reviewed-by: Herb Derby <herb@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/gn/core.gni b/gn/core.gni
index 3ba41e0..94a6ab2 100644
--- a/gn/core.gni
+++ b/gn/core.gni
@@ -212,6 +212,8 @@
"$_src/core/SkEnumerate.h",
"$_src/core/SkExecutor.cpp",
"$_src/core/SkFDot6.h",
+ "$_src/core/SkFactoryFunctions.cpp",
+ "$_src/core/SkFactoryFunctions.h",
"$_src/core/SkFlattenable.cpp",
"$_src/core/SkFont.cpp",
"$_src/core/SkFontDescriptor.cpp",
@@ -317,6 +319,7 @@
"$_src/core/SkPixmap.cpp",
"$_src/core/SkPoint.cpp",
"$_src/core/SkPoint3.cpp",
+ "$_src/core/SkPrecompile.h",
"$_src/core/SkPromiseImageTexture.cpp",
"$_src/core/SkPtrRecorder.cpp",
"$_src/core/SkPtrRecorder.h",
diff --git a/public.bzl b/public.bzl
index 8cc4ee3..d2fb611 100644
--- a/public.bzl
+++ b/public.bzl
@@ -457,6 +457,8 @@
"src/core/SkEnumerate.h",
"src/core/SkExecutor.cpp",
"src/core/SkFDot6.h",
+ "src/core/SkFactoryFunctions.h",
+ "src/core/SkFactoryFunctions.cpp",
"src/core/SkFlattenable.cpp",
"src/core/SkFont.cpp",
"src/core/SkFontDescriptor.cpp",
@@ -589,6 +591,7 @@
"src/core/SkPoint.cpp",
"src/core/SkPoint3.cpp",
"src/core/SkPointPriv.h",
+ "src/core/SkPrecompile.h",
"src/core/SkPromiseImageTexture.cpp",
"src/core/SkPtrRecorder.cpp",
"src/core/SkPtrRecorder.h",
diff --git a/src/core/BUILD.bazel b/src/core/BUILD.bazel
index d2b54f0..8c214a6 100644
--- a/src/core/BUILD.bazel
+++ b/src/core/BUILD.bazel
@@ -405,11 +405,14 @@
# These files are only needed if SkSL is enabled (GPU backend or SkVM).
SKSL_FILES = [
"SkCombinationBuilder.cpp",
+ "SkFactoryFunctions.h",
+ "SkFactoryFunctions.cpp",
"SkKeyContext.h",
"SkKeyHelpers.cpp",
"SkKeyHelpers.h",
"SkPaintParamsKey.cpp",
"SkPaintParamsKey.h",
+ "SkPrecompile.h",
"SkRuntimeEffect.cpp",
"SkSLTypeShared.h",
"SkScopeExit.h",
diff --git a/src/core/SkFactoryFunctions.cpp b/src/core/SkFactoryFunctions.cpp
new file mode 100644
index 0000000..a57f23f
--- /dev/null
+++ b/src/core/SkFactoryFunctions.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/core/SkFactoryFunctions.h"
+
+#include "src/core/SkPrecompile.h"
+
+// TODO: wrap this in an SK_PRECOMPILE check
+
+//--------------------------------------------------------------------------------------------------
+class SkPrecompileBlendModeBlender : public SkPrecompileBlender {
+public:
+ SkPrecompileBlendModeBlender(SkBlendMode blendMode) : fBlendMode(blendMode) {}
+
+ std::optional<SkBlendMode> asBlendMode() const final { return fBlendMode; }
+
+private:
+ SkBlendMode fBlendMode;
+};
+
+sk_sp<SkPrecompileBlender> SkPrecompileBlender::Mode(SkBlendMode blendMode) {
+ return sk_make_sp<SkPrecompileBlendModeBlender>(blendMode);
+}
+
+//--------------------------------------------------------------------------------------------------
+class SkBlendPrecompileShader : public SkPrecompileShader {
+public:
+ SkBlendPrecompileShader(SkSpan<const sk_sp<SkPrecompileBlender>> blenders,
+ SkSpan<const sk_sp<SkPrecompileShader>> dsts,
+ SkSpan<const sk_sp<SkPrecompileShader>> srcs)
+ : fBlenders(blenders.begin(), blenders.end())
+ , fDsts(dsts.begin(), dsts.end())
+ , fSrcs(srcs.begin(), srcs.end()) {
+ }
+
+private:
+ std::vector<sk_sp<SkPrecompileBlender>> fBlenders;
+ std::vector<sk_sp<SkPrecompileShader>> fDsts;
+ std::vector<sk_sp<SkPrecompileShader>> fSrcs;
+};
+
+//--------------------------------------------------------------------------------------------------
+sk_sp<SkPrecompileShader> SkPrecompileShaders::Color() {
+ return sk_make_sp<SkPrecompileShader>();
+}
+
+sk_sp<SkPrecompileShader> SkPrecompileShaders::Blend(
+ SkSpan<const sk_sp<SkPrecompileBlender>> blenders,
+ SkSpan<const sk_sp<SkPrecompileShader>> dsts,
+ SkSpan<const sk_sp<SkPrecompileShader>> srcs) {
+ return sk_make_sp<SkBlendPrecompileShader>(std::move(blenders),
+ std::move(dsts), std::move(srcs));
+}
+
+sk_sp<SkPrecompileShader> SkPrecompileShaders::Blend(
+ SkSpan<SkBlendMode> blendModes,
+ SkSpan<const sk_sp<SkPrecompileShader>> dsts,
+ SkSpan<const sk_sp<SkPrecompileShader>> srcs) {
+ std::vector<sk_sp<SkPrecompileBlender>> tmp;
+ tmp.reserve(blendModes.size());
+ for (SkBlendMode bm : blendModes) {
+ tmp.emplace_back(SkPrecompileBlender::Mode(bm));
+ }
+
+ return sk_make_sp<SkBlendPrecompileShader>(tmp, std::move(dsts), std::move(srcs));
+}
+
+sk_sp<SkPrecompileShader> SkPrecompileShaders::Image() {
+ return sk_make_sp<SkPrecompileShader>();
+}
+
+sk_sp<SkPrecompileShader> SkPrecompileShaders::LinearGradient() {
+ return sk_make_sp<SkPrecompileShader>();
+}
+
+sk_sp<SkPrecompileShader> SkPrecompileShaders::RadialGradient() {
+ return sk_make_sp<SkPrecompileShader>();
+}
+
+sk_sp<SkPrecompileShader> SkPrecompileShaders::TwoPointConicalGradient() {
+ return sk_make_sp<SkPrecompileShader>();
+}
+
+sk_sp<SkPrecompileShader> SkPrecompileShaders::SweepGradient() {
+ return sk_make_sp<SkPrecompileShader>();
+}
+
+//--------------------------------------------------------------------------------------------------
+sk_sp<SkPrecompileMaskFilter> SkPrecompileMaskFilters::Blur() {
+ return sk_make_sp<SkPrecompileMaskFilter>();
+}
+
+//--------------------------------------------------------------------------------------------------
+sk_sp<SkPrecompileColorFilter> SkPrecompileColorFilters::Matrix() {
+ return sk_make_sp<SkPrecompileColorFilter>();
+}
+
+//--------------------------------------------------------------------------------------------------
+sk_sp<SkPrecompileImageFilter> SkPrecompileImageFilters::Blur() {
+ return sk_make_sp<SkPrecompileImageFilter>();
+}
+
+sk_sp<SkPrecompileImageFilter> SkPrecompileImageFilters::Image() {
+ return sk_make_sp<SkPrecompileImageFilter>();
+}
+
+//--------------------------------------------------------------------------------------------------
diff --git a/src/core/SkFactoryFunctions.h b/src/core/SkFactoryFunctions.h
new file mode 100644
index 0000000..ea40e04
--- /dev/null
+++ b/src/core/SkFactoryFunctions.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFactoryFunctions_DEFINED
+#define SkFactoryFunctions_DEFINED
+
+#include "include/core/SkBlendMode.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSpan.h"
+
+class SkPrecompileBlender;
+class SkPrecompileColorFilter;
+class SkPrecompileImageFilter;
+class SkPrecompileMaskFilter;
+class SkPrecompileShader;
+class SkRuntimeEffect;
+
+// All of these factory functions will be moved elsewhere once the pre-compile API becomes public
+
+// TODO: wrap this in an SK_PRECOMPILE check
+
+//--------------------------------------------------------------------------------------------------
+// This will move to be beside SkShaders in include/core/SkShader.h
+class SkPrecompileShaders {
+public:
+ //TODO: Add Empty? - see skbug.com/12165
+ static sk_sp<SkPrecompileShader> Color();
+ static sk_sp<SkPrecompileShader> Blend(SkSpan<const sk_sp<SkPrecompileBlender>> blenders,
+ SkSpan<const sk_sp<SkPrecompileShader>> dsts,
+ SkSpan<const sk_sp<SkPrecompileShader>> srcs);
+ static sk_sp<SkPrecompileShader> Blend(SkSpan<SkBlendMode> blendModes,
+ SkSpan<const sk_sp<SkPrecompileShader>> dsts,
+ SkSpan<const sk_sp<SkPrecompileShader>> srcs);
+ // TODO: add an SkShaders::Image to match this and SkImageFilters (skbug.com/13440)
+ static sk_sp<SkPrecompileShader> Image();
+
+ // TODO: make SkGradientShader match this convention (skbug.com/13438)
+ static sk_sp<SkPrecompileShader> LinearGradient();
+ static sk_sp<SkPrecompileShader> RadialGradient();
+ static sk_sp<SkPrecompileShader> TwoPointConicalGradient();
+ static sk_sp<SkPrecompileShader> SweepGradient();
+
+private:
+ SkPrecompileShaders() = delete;
+};
+
+//--------------------------------------------------------------------------------------------------
+// Initially this will go next to SkMaskFilter in include/core/SkMaskFilter.h but the
+// SkMaskFilter::MakeBlur factory should be split out or removed. This namespace will follow
+// where ever that factory goes.
+class SkPrecompileMaskFilters {
+public:
+ // TODO: change SkMaskFilter::MakeBlur to match this and SkImageFilters::Blur (skbug.com/13441)
+ static sk_sp<SkPrecompileMaskFilter> Blur();
+
+private:
+ SkPrecompileMaskFilters() = delete;
+};
+
+//--------------------------------------------------------------------------------------------------
+// This will move to be beside SkColorFilters in include/core/SkColorFilter.h
+class SkPrecompileColorFilters {
+public:
+ static sk_sp<SkPrecompileColorFilter> Matrix();
+ // TODO: Compose, Blend, HSLAMatrix, LinearToSRGBGamma, SRGBToLinearGamma, Lerp
+
+private:
+ SkPrecompileColorFilters() = delete;
+};
+
+//--------------------------------------------------------------------------------------------------
+// This will move to be beside SkImageFilters in include/effects/SkImageFilters.h
+class SkPrecompileImageFilters {
+public:
+ static sk_sp<SkPrecompileImageFilter> Blur();
+ static sk_sp<SkPrecompileImageFilter> Image();
+ // TODO: AlphaThreshold, Arithmetic, Blend (2 kinds), ColorFilter, Compose, DisplacementMap,
+ // DropShadow, DropShadowOnly, Magnifier, MatrixConvolution, MatrixTransform, Merge, Offset,
+ // Picture, Runtime, Shader, Tile, Dilate, Erode, DistantLitDiffuse, PointLitDiffuse,
+ // SpotLitDiffuse, DistantLitSpecular, PointLitSpecular, SpotLitSpecular
+
+private:
+ SkPrecompileImageFilters() = delete;
+};
+
+#endif // SkFactoryFunctions_DEFINED
diff --git a/src/core/SkPrecompile.h b/src/core/SkPrecompile.h
new file mode 100644
index 0000000..26a4af7
--- /dev/null
+++ b/src/core/SkPrecompile.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPrecompile_DEFINED
+#define SkPrecompile_DEFINED
+
+#include "include/core/SkBlendMode.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSpan.h"
+
+#include <optional>
+#include <vector>
+
+class SkRuntimeEffect;
+
+// TODO: wrap this in an SK_PRECOMPILE check
+
+//--------------------------------------------------------------------------------------------------
+class SkPrecompileShader : public SkRefCnt {
+public:
+ // TODO: add a type enum to each of these base classes
+};
+
+class SkPrecompileMaskFilter : public SkRefCnt {
+public:
+
+};
+
+class SkPrecompileColorFilter : public SkRefCnt {
+public:
+
+};
+
+class SkPrecompileImageFilter : public SkRefCnt {
+public:
+
+};
+
+class SkPrecompileBlender : public SkRefCnt {
+public:
+ virtual std::optional<SkBlendMode> asBlendMode() const { return {}; }
+
+ static sk_sp<SkPrecompileBlender> Mode(SkBlendMode blendMode);
+
+};
+
+//--------------------------------------------------------------------------------------------------
+class SkPaintOptions {
+public:
+ void setShaders(SkSpan<const sk_sp<SkPrecompileShader>> shaders) {
+ fShaders.assign(shaders.begin(), shaders.end());
+ }
+
+ void setMaskFilters(SkSpan<const sk_sp<SkPrecompileMaskFilter>> maskFilters) {
+ fMaskFilters.assign(maskFilters.begin(), maskFilters.end());
+ }
+
+ void setColorFilters(SkSpan<const sk_sp<SkPrecompileColorFilter>> colorFilters) {
+ fColorFilters.assign(colorFilters.begin(), colorFilters.end());
+ }
+
+ void setImageFilters(SkSpan<const sk_sp<SkPrecompileImageFilter>> imageFilters) {
+ fImageFilters.assign(imageFilters.begin(), imageFilters.end());
+ }
+
+ void setBlendModes(SkSpan<SkBlendMode> blendModes) {
+ fBlenders.reserve(blendModes.size());
+ for (SkBlendMode bm : blendModes) {
+ fBlenders.emplace_back(SkPrecompileBlender::Mode(bm));
+ }
+ }
+ void setBlenders(SkSpan<const sk_sp<SkPrecompileBlender>> blenders) {
+ fBlenders.assign(blenders.begin(), blenders.end());
+ }
+
+private:
+ std::vector<sk_sp<SkPrecompileShader>> fShaders;
+ std::vector<sk_sp<SkPrecompileMaskFilter>> fMaskFilters;
+ std::vector<sk_sp<SkPrecompileColorFilter>> fColorFilters;
+ std::vector<sk_sp<SkPrecompileImageFilter>> fImageFilters;
+ std::vector<sk_sp<SkPrecompileBlender>> fBlenders;
+};
+
+#endif // SkPrecompile_DEFINED
diff --git a/tests/graphite/CombinationBuilderTest.cpp b/tests/graphite/CombinationBuilderTest.cpp
index 9ce2280..a091611 100644
--- a/tests/graphite/CombinationBuilderTest.cpp
+++ b/tests/graphite/CombinationBuilderTest.cpp
@@ -8,16 +8,19 @@
#include "tests/Test.h"
#include "include/core/SkCombinationBuilder.h"
-
+#include "src/core/SkFactoryFunctions.h"
+#include "src/core/SkPrecompile.h"
#include "tests/graphite/CombinationBuilderTestAccess.h"
+#include <array>
+
using namespace::skgpu::graphite;
namespace {
// For an entirely empty combination builder, both solid color shader and kSrcOver options
// will be added
-void empty_test(Context *context, skiatest::Reporter* reporter) {
+void empty_test(Context* context, skiatest::Reporter* reporter) {
SkCombinationBuilder builder(context);
REPORTER_ASSERT(reporter, CombinationBuilderTestAccess::NumCombinations(&builder) == 1);
@@ -25,7 +28,7 @@
// It is expected that the builder will supply a default solid color shader if no other shader
// option is provided
-void no_shader_option_test(Context *context, skiatest::Reporter* reporter) {
+void no_shader_option_test(Context* context, skiatest::Reporter* reporter) {
SkCombinationBuilder builder(context);
builder.addOption(SkBlendMode::kSrcOver);
@@ -35,7 +38,7 @@
// It is expected that the builder will supply a default kSrcOver blend mode if no other
// options are added
-void no_blend_mode_option_test(Context *context, skiatest::Reporter* reporter) {
+void no_blend_mode_option_test(Context* context, skiatest::Reporter* reporter) {
SkCombinationBuilder builder(context);
builder.addOption(SkShaderType::kSolidColor);
@@ -43,7 +46,62 @@
REPORTER_ASSERT(reporter, CombinationBuilderTestAccess::NumCombinations(&builder) == 1);
}
-void big_test(Context *context, skiatest::Reporter* reporter) {
+void big_test_new(Context* context, skiatest::Reporter* reporter) {
+
+ // paintOptions
+ // |- sweepGrad_0 | blendShader_0
+ // | 0: linearGrad_0 | solid_0
+ // | 1: linearGrad_1 | blendShader_1
+ // | 0: radGrad_0 | solid_1
+ // | 1: imageShader_0
+ // |
+ // |- 4-built-in-blend-modes
+
+ SkPaintOptions paintOptions;
+
+ // first, shaders. First top-level option (sweepGrad_0)
+ sk_sp<SkPrecompileShader> sweepGrad_0 = SkPrecompileShaders::SweepGradient();
+
+ std::array<SkBlendMode, 1> blendModes{ SkBlendMode::kSrc };
+
+ std::vector<SkBlendMode> moreBlendModes{ SkBlendMode::kDst };
+
+ // Second top-level option (blendShader_0)
+ auto blendShader_0 = SkPrecompileShaders::Blend(
+ SkSpan<SkBlendMode>(blendModes), // std::array
+ { // initializer_list
+ SkPrecompileShaders::LinearGradient(),
+ SkPrecompileShaders::Color()
+ },
+ {
+ SkPrecompileShaders::LinearGradient(),
+ SkPrecompileShaders::Blend(
+ SkSpan<SkBlendMode>(moreBlendModes),// std::vector
+ {
+ SkPrecompileShaders::RadialGradient(),
+ SkPrecompileShaders::Color()
+ },
+ {
+ SkPrecompileShaders::Image()
+ })
+ });
+
+ paintOptions.setShaders({ sweepGrad_0, blendShader_0 });
+
+ SkBlendMode evenMoreBlendModes[] = {
+ SkBlendMode::kSrcOver,
+ SkBlendMode::kSrc,
+ SkBlendMode::kDstOver,
+ SkBlendMode::kDst
+ };
+
+ // now, blend modes
+ paintOptions.setBlendModes(evenMoreBlendModes); // c array
+
+// context->precompile({paintOptions});
+}
+
+void big_test(Context* context, skiatest::Reporter* reporter) {
SkCombinationBuilder builder(context);
static constexpr int kMinNumStops = 4;
@@ -128,7 +186,7 @@
}
#ifdef SK_DEBUG
-void epoch_test(Context *context, skiatest::Reporter* reporter) {
+void epoch_test(Context* context, skiatest::Reporter* reporter) {
SkCombinationBuilder builder(context);
// Check that epochs are updated upon builder reset
@@ -148,6 +206,8 @@
} // anonymous namespace
DEF_GRAPHITE_TEST_FOR_CONTEXTS(CombinationBuilderTest, reporter, context) {
+ big_test_new(context, reporter);
+
empty_test(context, reporter);
no_shader_option_test(context, reporter);
no_blend_mode_option_test(context, reporter);