59 auto f16Format =
args.fContext->priv().caps()->getDefaultBackendFormat(
61 if (f16Format.isValid()) {
74 intermediateColorSpace,
85 SkDebugf(
"Gradient won't draw. Could not create texture.");
96 "uniform half4 start;"
98 "half4 main(float2 coord) {"
101 "return mix(start, end, half(coord.x));"
116 "uniform float4 scale[2];"
117 "uniform float4 bias[2];"
118 "uniform half threshold;"
120 "half4 main(float2 coord) {"
121 "half t = half(coord.x);"
124 "if (t < threshold) {"
132 "return half4(t * s + b);"
142 const Vec4 scale[2] = {(vc1 - vc0) / threshold,
143 (vc3 - vc2) / (1 - threshold)};
144 const Vec4 bias[2] = {vc0,
145 vc2 - threshold *
scale[1]};
150 "threshold", threshold);
164 SkASSERT(intervalCount >= 1 && intervalCount <= 8);
169 once[intervalCount - 1]([intervalCount] {
185 sksl.
append(
"uniform half4 thresholds1_7, thresholds9_13;");
190 sksl.
appendf(
"uniform float4 scale[%d];", intervalCount);
191 sksl.
appendf(
"uniform float4 bias[%d];", intervalCount);
197 "half4 main(float2 coord) {"
198 "half t = half(coord.x);"
201 "if (%d <= 4 || t < thresholds1_7.w) {"
203 "if (%d <= 2 || t < thresholds1_7.y) {"
205 "if (%d <= 1 || t < thresholds1_7.x) {"
212 "if (%d <= 3 || t < thresholds1_7.z) {"
220 "if (%d <= 6 || t < thresholds9_13.y) {"
222 "if (%d <= 5 || t < thresholds9_13.x) {"
229 "if (%d <= 7 || t < thresholds9_13.z) {"
241 (intervalCount <= 0) ?
"" :
"s = scale[0]; b = bias[0];",
242 (intervalCount <= 1) ?
"" :
"s = scale[1]; b = bias[1];",
244 (intervalCount <= 2) ?
"" :
"s = scale[2]; b = bias[2];",
245 (intervalCount <= 3) ?
"" :
"s = scale[3]; b = bias[3];",
248 (intervalCount <= 4) ?
"" :
"s = scale[4]; b = bias[4];",
249 (intervalCount <= 5) ?
"" :
"s = scale[5]; b = bias[5];",
251 (intervalCount <= 6) ?
"" :
"s = scale[6]; b = bias[6];",
252 (intervalCount <= 7) ?
"" :
"s = scale[7]; b = bias[7];");
256 effects[intervalCount - 1] =
result.effect.release();
259 return GrSkSLFP::Make(effects[intervalCount - 1],
"UnrolledBinaryColorizer",
261 "thresholds1_7", thresholds1_7,
262 "thresholds9_13", thresholds9_13,
264 "bias",
SkSpan(bias, intervalCount));
277 int intervalChunks = intervalCount / 4;
278 int cacheIndex = (size_t)intervalChunks - 1;
280 struct EffectCacheEntry {
287 EffectCacheEntry* cacheEntry = &effectCache[cacheIndex];
289 cacheEntry->once([intervalCount, intervalChunks, cacheEntry] {
306 "uniform half4 thresholds[%d];"
307 "uniform float4 scale[%d];"
308 "uniform float4 bias[%d];"
310 "half4 main(float2 coord) {"
311 "half t = half(coord.x);"
317 "for (int loop = 0; loop < %d; ++loop) {"
318 "if (t < thresholds[chunk].w) {"
323 "chunk = (low + high) / 2;"
328 "if (t < thresholds[chunk].y) {"
329 "pos = (t < thresholds[chunk].x) ? 0 : 1;"
331 "pos = (t < thresholds[chunk].z) ? 2 : 3;"
336 "return t * scale[pos] + bias[pos];"
342 (intervalChunks - 1) / 2,
348 cacheEntry->effect =
result.effect.release();
351 return GrSkSLFP::Make(cacheEntry->effect,
"LoopingBinaryColorizer",
353 "thresholds",
SkSpan((
const SkV4*)thresholds, intervalChunks),
355 "bias",
SkSpan(bias, intervalCount));
372 int intervalCount = 0;
373 for (
int i = 0;
i < inputLength - 1;
i++) {
374 if (intervalCount >= outputLength) {
395 scale.store(outScales + intervalCount);
396 bias.
store(outBiases + intervalCount);
397 outThresholds[intervalCount] = t1;
400 return intervalCount;
415 if (intervalCount <= 0) {
419 SkRect thresholds1_7 = {thresholds[0], thresholds[1], thresholds[2], thresholds[3]},
420 thresholds9_13 = {thresholds[4], thresholds[5], thresholds[6], 0.0};
438 if (intervalCount <= 0) {
447 for (; intervalCount < roundedSize; ++intervalCount) {
448 thresholds[intervalCount] = thresholds[intervalCount - 1];
449 scales[intervalCount] = scales[intervalCount - 1];
450 biases[intervalCount] = biases[intervalCount - 1];
473 if (bottomHardStop) {
489 auto intervalsExceedPrecisionLimit = [&]() ->
bool {
499 for (
int i = 0;
i <
count - 1;
i++) {
509 auto makeDualIntervalColorizer = [&]() -> std::unique_ptr<GrFragmentProcessor> {
531 if ((
count <= binaryColorizerLimit) && !intervalsExceedPrecisionLimit()) {
534 std::unique_ptr<GrFragmentProcessor> colorizer = makeDualIntervalColorizer();
561 std::unique_ptr<GrFragmentProcessor> colorizer,
562 std::unique_ptr<GrFragmentProcessor> gradLayout,
565 bool colorsAreOpaque) {
567 "uniform shader colorizer;"
568 "uniform shader gradLayout;"
570 "uniform half4 leftBorderColor;"
571 "uniform half4 rightBorderColor;"
573 "uniform int layoutPreservesOpacity;"
575 "half4 main(float2 coord) {"
576 "half4 t = gradLayout.eval(coord);"
582 "if (!bool(layoutPreservesOpacity) && t.y < 0) {"
585 "outColor = half4(0);"
586 "} else if (t.x < 0) {"
587 "outColor = leftBorderColor;"
588 "} else if (t.x > 1.0) {"
589 "outColor = rightBorderColor;"
593 "outColor = colorizer.eval(t.x0);"
602 bool layoutPreservesOpacity = gradLayout->preservesOpaqueInput();
604 if (colorsAreOpaque && layoutPreservesOpacity) {
608 return GrSkSLFP::Make(effect,
"ClampedGradient",
nullptr, optFlags,
611 "leftBorderColor", leftBorderColor,
612 "rightBorderColor", rightBorderColor,
613 "layoutPreservesOpacity",
614 GrSkSLFP::Specialize<int>(layoutPreservesOpacity));
619 std::unique_ptr<GrFragmentProcessor> colorizer,
620 std::unique_ptr<GrFragmentProcessor> gradLayout,
622 bool colorsAreOpaque) {
624 "uniform shader colorizer;"
625 "uniform shader gradLayout;"
627 "uniform int mirror;"
628 "uniform int layoutPreservesOpacity;"
629 "uniform int useFloorAbsWorkaround;"
631 "half4 main(float2 coord) {"
632 "half4 t = gradLayout.eval(coord);"
634 "if (!bool(layoutPreservesOpacity) && t.y < 0) {"
639 "if (bool(mirror)) {"
640 "half t_1 = t.x - 1;"
641 "half tiled_t = t_1 - 2 * floor(t_1 * 0.5) - 1;"
642 "if (bool(useFloorAbsWorkaround)) {"
646 "tiled_t = clamp(tiled_t, -1, 1);"
648 "t.x = abs(tiled_t);"
656 "half4 outColor = colorizer.eval(t.x0);"
665 bool layoutPreservesOpacity = gradLayout->preservesOpaqueInput();
667 if (colorsAreOpaque && layoutPreservesOpacity) {
670 const bool useFloorAbsWorkaround =
671 args.fContext->priv().caps()->shaderCaps()->fMustDoOpBetweenFloorAndAbs;
676 "mirror", GrSkSLFP::Specialize<int>(
mirror),
677 "layoutPreservesOpacity",
678 GrSkSLFP::Specialize<int>(layoutPreservesOpacity),
679 "useFloorAbsWorkaround",
680 GrSkSLFP::Specialize<int>(useFloorAbsWorkaround));
684 std::unique_ptr<GrFragmentProcessor> gradient,
692 static_assert(
static_cast<int>(ColorSpace::kDestination) == 0);
693 static_assert(
static_cast<int>(ColorSpace::kSRGBLinear) == 1);
694 static_assert(
static_cast<int>(ColorSpace::kLab) == 2);
695 static_assert(
static_cast<int>(ColorSpace::kOKLab) == 3);
696 static_assert(
static_cast<int>(ColorSpace::kOKLabGamutMap) == 4);
697 static_assert(
static_cast<int>(ColorSpace::kLCH) == 5);
698 static_assert(
static_cast<int>(ColorSpace::kOKLCH) == 6);
699 static_assert(
static_cast<int>(ColorSpace::kOKLCHGamutMap) == 7);
700 static_assert(
static_cast<int>(ColorSpace::kSRGB) == 8);
701 static_assert(
static_cast<int>(ColorSpace::kHSL) == 9);
702 static_assert(
static_cast<int>(ColorSpace::kHWB) == 10);
705 "uniform int colorSpace;"
706 "uniform int do_unpremul;"
708 "half4 main(half4 color) {"
709 "return $interpolated_to_rgb_unpremul(color, colorSpace, do_unpremul);"
715 bool inputPremul =
static_cast<bool>(interpolation.
fInPremul);
718 case ColorSpace::kLab:
719 case ColorSpace::kOKLab:
720 case ColorSpace::kOKLabGamutMap:
721 case ColorSpace::kLCH:
722 case ColorSpace::kOKLCH:
723 case ColorSpace::kOKLCHGamutMap:
724 case ColorSpace::kHSL:
725 case ColorSpace::kHWB:
728 gradient =
GrSkSLFP::Make(effect,
"GradientCS", std::move(gradient),
730 "colorSpace", GrSkSLFP::Specialize<int>(
732 "do_unpremul", GrSkSLFP::Specialize<int>(
733 inputPremul && !allOpaque));
768 intermediateColorSpace, intermediateAlphaType,
769 dstColorSpace, dstAlphaType);
786 return {
false, std::move(
fp)};
797 std::unique_ptr<GrFragmentProcessor> layout,
801 if (layout ==
nullptr) {
807 if (!overrideMatrix) {
811 std::tie(success, layout) =
apply_matrix(std::move(layout), mRec, *overrideMatrix);
824 &shader,
args.fDstColorInfo->colorSpace(),
true);
827 const int colorCount = xformedColors.
fColors.
size();
829 bool allOpaque =
true;
830 for (
int i = 0;
i < colorCount;
i++) {
861 args.fDstColorInfo->colorSpace(),
865 if (colorizer ==
nullptr) {
873 std::unique_ptr<GrFragmentProcessor> gradient;
896 p.append(SkRasterPipelineOp::load_f32, &ctx);
903 args.fDstColorInfo->colorSpace());
904 p.append(SkRasterPipelineOp::store_f32, &ctx);
908 borderColors[0], borderColors[1], allOpaque);
934 "half4 main(float2 coord) {"
935 "return half4(half(coord.x) + 0.00001, 1, 0, 0);"
944#if defined(GR_TEST_UTILS)
945RandomParams::RandomParams(
SkRandom* random) {
948 fColorCount = random->
nextRangeU(2, kMaxRandomGradientColors);
952 if (fColorCount == 1 || (fColorCount >= 2 && random->
nextBool())) {
955 fStops = fStopStorage;
960 fColorSpace = GrTest::TestColorSpace(random);
964 for (
int i = 0;
i < fColorCount; ++
i) {
971 fColors[
i] = random->
nextU();
975 stop =
i < fColorCount - 1 ? stop + random->
nextUScalar1() * (1.f - stop) : 1.f;
std::tuple< bool, std::unique_ptr< GrFragmentProcessor > > GrFPResult
static std::unique_ptr< GrFragmentProcessor > make_clamped_gradient(std::unique_ptr< GrFragmentProcessor > colorizer, std::unique_ptr< GrFragmentProcessor > gradLayout, SkPMColor4f leftBorderColor, SkPMColor4f rightBorderColor, bool colorsAreOpaque)
static std::unique_ptr< GrFragmentProcessor > make_looping_binary_colorizer(const SkPMColor4f *colors, const SkScalar *positions, int count)
static std::unique_ptr< GrFragmentProcessor > make_uniform_colorizer(const SkPMColor4f *colors, const SkScalar *positions, int count, bool premul, const GrFPArgs &args)
static std::unique_ptr< GrFragmentProcessor > make_tiled_gradient(const GrFPArgs &args, std::unique_ptr< GrFragmentProcessor > colorizer, std::unique_ptr< GrFragmentProcessor > gradLayout, bool mirror, bool colorsAreOpaque)
static std::unique_ptr< GrFragmentProcessor > make_dual_interval_colorizer(const SkPMColor4f &c0, const SkPMColor4f &c1, const SkPMColor4f &c2, const SkPMColor4f &c3, float threshold)
static std::unique_ptr< GrFragmentProcessor > make_interpolated_to_dst(std::unique_ptr< GrFragmentProcessor > gradient, const SkGradientShader::Interpolation &interpolation, SkColorSpace *intermediateColorSpace, const GrColorInfo &dstInfo, bool allOpaque)
static std::unique_ptr< GrFragmentProcessor > make_textured_colorizer(const SkPMColor4f *colors, const SkScalar *positions, int count, bool colorsAreOpaque, const SkGradientShader::Interpolation &interpolation, const SkColorSpace *intermediateColorSpace, const SkColorSpace *dstColorSpace, const GrFPArgs &args)
static const int kMaxNumCachedGradientBitmaps
int build_intervals(int inputLength, const SkPMColor4f *inColors, const SkScalar *inPositions, int outputLength, SkPMColor4f *outScales, SkPMColor4f *outBiases, SkScalar *outThresholds)
static constexpr int kMaxLoopingIntervalCount
static constexpr int kMaxLoopingColorCount
static std::unique_ptr< GrFragmentProcessor > make_unrolled_colorizer(int intervalCount, const SkPMColor4f *scale, const SkPMColor4f *bias, SkRect thresholds1_7, SkRect thresholds9_13)
static constexpr int kMaxUnrolledColorCount
static constexpr int kMaxUnrolledIntervalCount
static const SkScalar kLowPrecisionIntervalLimit
static std::unique_ptr< GrFragmentProcessor > make_unrolled_binary_colorizer(const SkPMColor4f *colors, const SkScalar *positions, int count)
static const int kGradientTextureSize
static std::unique_ptr< GrFragmentProcessor > make_looping_colorizer(int intervalCount, const SkPMColor4f *scale, const SkPMColor4f *bias, const SkScalar *thresholds)
static std::unique_ptr< GrFragmentProcessor > make_single_interval_colorizer(const SkPMColor4f &start, const SkPMColor4f &end)
static constexpr bool GrColorTypeIsWiderThan(GrColorType colorType, int n)
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
#define SkASSERTF(cond, fmt,...)
static unsigned mirror(SkFixed fx, int max)
constexpr SkPMColor4f SK_PMColor4fTRANSPARENT
SkColorSpace * sk_srgb_singleton()
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
std::tuple< GrSurfaceProxyView, GrColorType > GrMakeCachedBitmapProxyView(GrRecordingContext *rContext, const SkBitmap &bitmap, std::string_view label, skgpu::Mipmapped mipmapped)
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
static bool ok(int result)
static int SkNextPow2(int value)
static int SkNextLog2(uint32_t value)
constexpr bool SkIsPow2(T value)
SkRuntimeEffect * SkMakeRuntimeEffect(SkRuntimeEffect::Result(*make)(SkString, const SkRuntimeEffect::Options &), const char *sksl, SkRuntimeEffect::Options options=SkRuntimeEffect::Options{})
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
#define SK_ScalarNearlyZero
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
static constexpr int kSkTileModeCount
static uint32_t premul(uint32_t color)
SkColorSpace * colorSpace() const
static std::unique_ptr< GrFragmentProcessor > Make(const SkMatrix &matrix, std::unique_ptr< GrFragmentProcessor > child)
@ kCompatibleWithCoverageAsAlpha
static GrIgnoreOptFlags IgnoreOptFlags(std::unique_ptr< GrFragmentProcessor > child)
static std::unique_ptr< GrSkSLFP > Make(const SkRuntimeEffect *effect, const char *name, std::unique_ptr< GrFragmentProcessor > inputFP, OptFlags optFlags, Args &&... args)
static std::unique_ptr< GrFragmentProcessor > Make(GrSurfaceProxyView, SkAlphaType, const SkMatrix &=SkMatrix::I(), GrSamplerState::Filter=GrSamplerState::Filter::kNearest, GrSamplerState::MipmapMode mipmapMode=GrSamplerState::MipmapMode::kNone)
Interpolation fInterpolation
bool interpolateInPremul() const
static void AppendInterpolatedToDstStages(SkRasterPipeline *p, SkArenaAlloc *alloc, bool colorsAreOpaque, const Interpolation &interpolation, const SkColorSpace *intermediateColorSpace, const SkColorSpace *dstColorSpace)
const SkMatrix & getGradientMatrix() const
SkTileMode getTileMode() const
static SkMatrix Scale(SkScalar sx, SkScalar sy)
uint32_t nextULessThan(uint32_t count)
uint32_t nextRangeU(uint32_t min, uint32_t max)
static Result MakeForColorFilter(SkString sksl, const Options &)
static Result MakeForShader(SkString sksl, const Options &)
std::tuple< SkMatrix, bool > applyForFragmentProcessor(const SkMatrix &postInv) const
void append(const char text[])
void void void appendf(const char format[],...) SK_PRINTF_LIKE(2
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static float max(float r, float g, float b)
std::unique_ptr< GrFragmentProcessor > MakeGradientFP(const SkGradientBaseShader &shader, const GrFPArgs &args, const SkShaders::MatrixRec &mRec, std::unique_ptr< GrFragmentProcessor > layout, const SkMatrix *overrideMatrix)
static GrFPResult apply_matrix(std::unique_ptr< GrFragmentProcessor > fp, const SkShaders::MatrixRec &rec, const SkMatrix &postInv)
std::unique_ptr< GrFragmentProcessor > MakeLinear(const SkLinearGradient &shader, const GrFPArgs &args, const SkShaders::MatrixRec &mRec)
PODArray< SkColor > colors
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
const myers::Point & get< 0 >(const myers::Segment &s)
static thread_local void * gCache
bool fNonconstantArrayIndexSupport
const float * vec() const
static SKVX_ALWAYS_INLINE Vec Load(const void *ptr)
SKVX_ALWAYS_INLINE void store(void *ptr) const