[skottie] Non-legacy brightness effect
Includes POW intrinsic plumbing.
Change-Id: Ida961718e28822c8559f17f97003f67082dd44cc
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/287156
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Mike Klein <mtklein@google.com>
diff --git a/include/private/SkVx.h b/include/private/SkVx.h
index cd73ab4..696c6d6 100644
--- a/include/private/SkVx.h
+++ b/include/private/SkVx.h
@@ -280,6 +280,7 @@
SIT Vec<1,T> min(const Vec<1,T>& x, const Vec<1,T>& y) { return std::min(x.val, y.val); }
SIT Vec<1,T> max(const Vec<1,T>& x, const Vec<1,T>& y) { return std::max(x.val, y.val); }
+SIT Vec<1,T> pow(const Vec<1,T>& x, const Vec<1,T>& y) { return std::pow(x.val, y.val); }
SIT Vec<1,T> atan(const Vec<1,T>& x) { return std:: atan(x.val); }
SIT Vec<1,T> ceil(const Vec<1,T>& x) { return std:: ceil(x.val); }
@@ -314,6 +315,7 @@
SINT Vec<N,T> min(const Vec<N,T>& x, const Vec<N,T>& y) { return join(min(x.lo, y.lo), min(x.hi, y.hi)); }
SINT Vec<N,T> max(const Vec<N,T>& x, const Vec<N,T>& y) { return join(max(x.lo, y.lo), max(x.hi, y.hi)); }
+SINT Vec<N,T> pow(const Vec<N,T>& x, const Vec<N,T>& y) { return join(pow(x.lo, y.lo), pow(x.hi, y.hi)); }
SINT Vec<N,T> atan(const Vec<N,T>& x) { return join( atan(x.lo), atan(x.hi)); }
SINT Vec<N,T> ceil(const Vec<N,T>& x) { return join( ceil(x.lo), ceil(x.hi)); }
@@ -351,6 +353,7 @@
SINTU Vec<N,M<T>> operator> (U x, const Vec<N,T>& y) { return Vec<N,T>(x) > y; }
SINTU Vec<N,T> min(U x, const Vec<N,T>& y) { return min(Vec<N,T>(x), y); }
SINTU Vec<N,T> max(U x, const Vec<N,T>& y) { return max(Vec<N,T>(x), y); }
+SINTU Vec<N,T> pow(U x, const Vec<N,T>& y) { return pow(Vec<N,T>(x), y); }
// ... and same deal for vector/scalar operations.
SINTU Vec<N,T> operator+ (const Vec<N,T>& x, U y) { return x + Vec<N,T>(y); }
@@ -368,6 +371,7 @@
SINTU Vec<N,M<T>> operator> (const Vec<N,T>& x, U y) { return x > Vec<N,T>(y); }
SINTU Vec<N,T> min(const Vec<N,T>& x, U y) { return min(x, Vec<N,T>(y)); }
SINTU Vec<N,T> max(const Vec<N,T>& x, U y) { return max(x, Vec<N,T>(y)); }
+SINTU Vec<N,T> pow(const Vec<N,T>& x, U y) { return pow(x, Vec<N,T>(y)); }
// All vector/scalar combinations for mad() with at least one vector.
SINTU Vec<N,T> mad(U f, const Vec<N,T>& m, const Vec<N,T>& a) { return Vec<N,T>(f)*m + a; }
diff --git a/modules/skottie/src/effects/BrightnessContrastEffect.cpp b/modules/skottie/src/effects/BrightnessContrastEffect.cpp
index 1c3e828..479e14d 100644
--- a/modules/skottie/src/effects/BrightnessContrastEffect.cpp
+++ b/modules/skottie/src/effects/BrightnessContrastEffect.cpp
@@ -101,6 +101,28 @@
#endif
+// Brightness transfer function approximation:
+//
+// f(x) = 1 - (1 - x)^(2^(1.8*B))
+//
+// where B is the normalized [-1..1] brightness value
+//
+// Visualization: https://www.desmos.com/calculator/wuyqa2wtol
+//
+static sk_sp<SkData> make_brightness_coeffs(float brightness) {
+ const float coeff_a = std::pow(2.0f, brightness * 1.8f);
+
+ return SkData::MakeWithCopy(&coeff_a, sizeof(coeff_a));
+}
+
+static constexpr char BRIGHTNESS_EFFECT[] = R"(
+ uniform half a;
+
+ void main(inout half4 color) {
+ color.rgb = 1 - pow(1 - color.rgb, half3(a));
+ }
+)";
+
class BrightnessContrastAdapter final : public DiscardableAdapterBase<BrightnessContrastAdapter,
sksg::ExternalColorFilter> {
public:
@@ -108,7 +130,9 @@
const AnimationBuilder& abuilder,
sk_sp<sksg::RenderNode> layer)
: INHERITED(sksg::ExternalColorFilter::Make(std::move(layer)))
+ , fBrightnessEffect(std::get<0>(SkRuntimeEffect::Make(SkString(BRIGHTNESS_EFFECT))))
, fContrastEffect(std::get<0>(SkRuntimeEffect::Make(SkString(CONTRAST_EFFECT)))) {
+ SkASSERT(fBrightnessEffect);
SkASSERT(fContrastEffect);
enum : size_t {
@@ -183,17 +207,22 @@
}
sk_sp<SkColorFilter> makeCF() const {
- // TODO: brightness
- const auto contrast = SkTPin(fContrast, -50.0f, 100.0f) / 100; // [-0.5 .. 1]
+ const auto brightness = SkTPin(fBrightness, -150.0f, 150.0f) / 150, // [-1.0 .. 1]
+ contrast = SkTPin(fContrast , -50.0f, 100.0f) / 100; // [-0.5 .. 1]
- if (SkScalarNearlyZero(fContrast)) {
- return nullptr;
- }
- return fContrastEffect->makeColorFilter(make_contrast_coeffs(contrast));
+ auto b_eff = SkScalarNearlyZero(brightness)
+ ? nullptr
+ : fBrightnessEffect->makeColorFilter(make_brightness_coeffs(brightness)),
+ c_eff = SkScalarNearlyZero(fContrast)
+ ? nullptr
+ : fContrastEffect->makeColorFilter(make_contrast_coeffs(contrast));
+
+ return SkColorFilters::Compose(std::move(c_eff), std::move(b_eff));
}
- const sk_sp<SkRuntimeEffect> fContrastEffect;
+ const sk_sp<SkRuntimeEffect> fBrightnessEffect,
+ fContrastEffect;
ScalarValue fBrightness = 0,
fContrast = 0,
diff --git a/src/sksl/SkSLByteCode.cpp b/src/sksl/SkSLByteCode.cpp
index e36f554..166e621 100644
--- a/src/sksl/SkSLByteCode.cpp
+++ b/src/sksl/SkSLByteCode.cpp
@@ -156,6 +156,7 @@
case ByteCodeInstruction::kNotB: printf("notb"); break;
case ByteCodeInstruction::kOrB: printf("orb"); break;
VECTOR_MATRIX_DISASSEMBLE(kPop, "pop")
+ VECTOR_DISASSEMBLE(kPow, "pow")
case ByteCodeInstruction::kPushImmediate: {
uint32_t v = READ32();
union { uint32_t u; float f; } pun = { v };
@@ -846,6 +847,8 @@
sp -= READ8();
continue;
+ VECTOR_BINARY_FN(kPow, fFloat, skvx::pow)
+
case ByteCodeInstruction::kPushImmediate:
PUSH(U32(READ32()));
continue;
diff --git a/src/sksl/SkSLByteCode.h b/src/sksl/SkSLByteCode.h
index 7c1f1ec..7477558 100644
--- a/src/sksl/SkSLByteCode.h
+++ b/src/sksl/SkSLByteCode.h
@@ -92,6 +92,7 @@
kNotB,
kOrB,
VECTOR_MATRIX(kPop),
+ VECTOR(kPow),
// Followed by a 32 bit value containing the value to push
kPushImmediate,
// Followed by a byte indicating external value to read
diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp
index 4415fd5..474ea79 100644
--- a/src/sksl/SkSLByteCodeGenerator.cpp
+++ b/src/sksl/SkSLByteCodeGenerator.cpp
@@ -49,6 +49,7 @@
{ "fract", ByteCodeInstruction::kFract },
{ "inverse", ByteCodeInstruction::kInverse2x2 },
{ "length", SpecialIntrinsic::kLength },
+ { "pow", ByteCodeInstruction::kPow },
{ "sin", ByteCodeInstruction::kSin },
{ "sqrt", ByteCodeInstruction::kSqrt },
{ "tan", ByteCodeInstruction::kTan },
@@ -283,6 +284,7 @@
VECTOR_MATRIX_BINARY_OP(kDivideF)
VECTOR_BINARY_OP(kMultiplyI)
VECTOR_MATRIX_BINARY_OP(kMultiplyF)
+ VECTOR_BINARY_OP(kPow)
VECTOR_BINARY_OP(kRemainderF)
VECTOR_BINARY_OP(kRemainderS)
VECTOR_BINARY_OP(kRemainderU)
@@ -1013,6 +1015,7 @@
case ByteCodeInstruction::kATan:
case ByteCodeInstruction::kCos:
case ByteCodeInstruction::kFract:
+ case ByteCodeInstruction::kPow:
case ByteCodeInstruction::kSin:
case ByteCodeInstruction::kSqrt:
case ByteCodeInstruction::kTan: