45class InvalidationController;
64static constexpr char gDisplacementSkSL[] =
65 "uniform shader child;"
66 "uniform shader displ;"
68 "uniform half4x4 selector_matrix;"
69 "uniform half4 selector_offset;"
71 "half4 main(float2 xy) {"
72 "half4 d = displ.eval(xy);"
74 "d = selector_matrix*unpremul(d) + selector_offset;"
76 "return child.eval(xy + d.xy*d.zw);"
85 printf(
"!!! %s\n", err.c_str());
94 ~DisplacementNode()
override {
95 this->unobserveInval(fDisplSource);
101 const SkSize& displ_size) {
102 if (!child || !displ) {
107 std::move(displ), displ_size));
110 enum class Pos :
unsigned {
118 enum class Selector :
unsigned {
145 , fDisplSource(std::move(displ))
146 , fDisplSize(displ_size)
147 , fChildSize(child_size)
149 this->observeInval(fDisplSource);
152 struct SelectorCoeffs {
157 static SelectorCoeffs Coeffs(Selector sel) {
160 static constexpr SelectorCoeffs gCoeffs[] = {
171 { 0,0,0,0,.5f, 0,1 },
175 const auto i =
static_cast<size_t>(sel);
181 static bool IsConst(Selector
s) {
182 return s == Selector::kFull
183 ||
s == Selector::kHalf
184 ||
s == Selector::kOff;
190 if ((IsConst(fXSelector) && IsConst(fYSelector)) ||
208 const auto child_content = get_content_picture(this->children()[0], ic, ctm),
209 displ_content = get_content_picture(fDisplSource, ic, ctm);
210 if (!child_content || !displ_content) {
215 auto child_shader = child_content->makeShader(fChildTileMode,
222 const auto displ_mode = this->displacementTileMode();
223 const auto displ_matrix = this->displacementMatrix();
224 auto displ_shader = displ_content->makeShader(displ_mode,
231 builder.child(
"child") = std::move(child_shader);
232 builder.child(
"displ") = std::move(displ_shader);
234 const auto xc = Coeffs(fXSelector),
235 yc = Coeffs(fYSelector);
237 const auto s = fScale * 2;
239 const float selector_m[] = {
240 xc.dr*
s.
x, yc.dr*
s.
y, 0, 0,
241 xc.dg*
s.
x, yc.dg*
s.
y, 0, 0,
242 xc.db*
s.
x, yc.db*
s.
y, 0, 0,
243 xc.da*
s.
x, yc.da*
s.
y, xc.c_scale, yc.c_scale,
250 const float selector_o[] = {
251 (xc.d_offset - .5f) *
s.
x,
252 (yc.d_offset - .5f) *
s.
y,
257 builder.uniform(
"selector_matrix") = selector_m;
258 builder.uniform(
"selector_offset") = selector_o;
265 fEffectShader = this->buildEffectShader(ic, ctm);
267 auto bounds = this->children()[0]->revalidate(ic, ctm);
276 void onRender(
SkCanvas* canvas,
const RenderContext* ctx)
const override {
277 if (!fEffectShader) {
279 this->children()[0]->render(canvas, ctx);
283 auto local_ctx = ScopedRenderContext(canvas, ctx).setIsolation(this->
bounds(),
293 return fPos == Pos::kTile
298 SkMatrix displacementMatrix()
const {
311 const RenderNode* onNodeAt(
const SkPoint&)
const override {
return nullptr; }
320 SkV2 fScale = { 0, 0 };
322 Pos fPos = Pos::kCenter;
323 Selector fXSelector = Selector::kR,
324 fYSelector = Selector::kR;
325 bool fExpandBounds =
false;
330class DisplacementMapAdapter final :
public DiscardableAdapterBase<DisplacementMapAdapter,
334 const AnimationBuilder* abuilder,
337 EffectBinder(jprops, *abuilder,
this)
338 .bind(kUseForHorizontal_Index, fHorizontalSelector)
339 .bind(kMaxHorizontal_Index , fMaxHorizontal )
340 .bind(kUseForVertical_Index , fVerticalSelector )
341 .bind(kMaxVertical_Index , fMaxVertical )
342 .bind(kMapBehavior_Index , fMapBehavior )
343 .bind(kEdgeBehavior_Index , fEdgeBehavior )
344 .bind(kExpandOutput_Index , fExpandOutput );
347 static std::tuple<sk_sp<sksg::RenderNode>,
SkSize> GetDisplacementSource(
349 const EffectBuilder* ebuilder) {
352 auto* map_builder = ebuilder->getLayerBuilder(
ParseDefault((*jv)[
"k"], -1));
354 return std::make_tuple(map_builder->contentTree(), map_builder->size());
358 return std::make_tuple<sk_sp<sksg::RenderNode>,
SkSize>(
nullptr, {0,0});
364 kUseForHorizontal_Index = 1,
365 kMaxHorizontal_Index = 2,
366 kUseForVertical_Index = 3,
367 kMaxVertical_Index = 4,
368 kMapBehavior_Index = 5,
369 kEdgeBehavior_Index = 6,
370 kExpandOutput_Index = 7,
373 template <
typename E>
376 const auto uv =
std::min(
static_cast<unsigned>(v) - 1,
377 static_cast<unsigned>(E::kLast));
379 return static_cast<E>(uv);
382 void onSync()
override {
387 this->node()->setScale({fMaxHorizontal, fMaxVertical});
391 this->node()->setPos(ToEnum<DisplacementNode::Pos>(fMapBehavior));
392 this->node()->setXSelector(ToEnum<DisplacementNode::Selector>(fHorizontalSelector));
393 this->node()->setYSelector(ToEnum<DisplacementNode::Selector>(fVerticalSelector));
394 this->node()->setExpandBounds(fExpandOutput != 0);
398 fVerticalSelector = 0,
405 using INHERITED = DiscardableAdapterBase<DisplacementMapAdapter, DisplacementNode>;
412 auto [ displ, displ_size ] = DisplacementMapAdapter::GetDisplacementSource(jprops,
this);
422 std::move(displ_node));
#define INHERITED(method,...)
sk_sp< T > sk_ref_sp(T *obj)
#define SG_ATTRIBUTE(attr_name, attr_type, attr_container)
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
void drawRect(const SkRect &rect, const SkPaint &paint)
SkMatrix getTotalMatrix() const
static SkMatrix Scale(SkScalar sx, SkScalar sy)
static SkMatrix Translate(SkScalar dx, SkScalar dy)
static const SkMatrix & I()
void setShader(sk_sp< SkShader > shader)
SkCanvas * beginRecording(const SkRect &bounds, sk_sp< SkBBoxHierarchy > bbh)
sk_sp< SkPicture > finishRecordingAsPicture()
static Result MakeForShader(SkString sksl, const Options &)
void attachDiscardableAdapter(sk_sp< T > adapter) const
static const skjson::Value & GetPropValue(const skjson::ArrayValue &jprops, size_t prop_index)
const SkRect & revalidate(InvalidationController *, const SkMatrix &)
void render(SkCanvas *, const RenderContext *=nullptr) const
static float min(float r, float g, float b)
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
Optional< SkRect > bounds
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
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
@ kSaturation
saturation of source with hue and luminosity of destination
@ kHue
hue of source with saturation and luminosity of destination
T ParseDefault(const skjson::Value &v, const T &defaultValue)
SIN Vec< N, float > abs(const Vec< N, float > &x)
static constexpr SkRect MakeSize(const SkSize &size)
sk_sp< SkRuntimeEffect > effect