From e1824da6b51f33bdd67d3b823b4bfb08e711d730 Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Thu, 12 Jul 2018 10:33:39 -0400 Subject: PathKit/WASM tweaks The most interesting part is using variadic calls to push all verb data in one native -> JS go. This speeds up SkPathToVerbsArgsArray and SkPathToCmdArray by 30-35%. Other misc changes: * use SkPath::RawIter instead of Iter * add a VisitPath helper to cut down on boiler plate * use uintptr_t for pointer arguments (just in case we get to wasm64 some day) Change-Id: Ia0240f0e00e81db78eb1e9b48b31abbb3e33bfaf Reviewed-on: https://skia-review.googlesource.com/140984 Reviewed-by: Kevin Lubick Commit-Queue: Florin Malita --- experimental/wasm/wasm_main.cpp | 161 +++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 86 deletions(-) (limited to 'experimental') diff --git a/experimental/wasm/wasm_main.cpp b/experimental/wasm/wasm_main.cpp index 4486b06f40..a2876d9f40 100644 --- a/experimental/wasm/wasm_main.cpp +++ b/experimental/wasm/wasm_main.cpp @@ -26,50 +26,52 @@ static const int CLOSE = 5; // Creating/Exporting Paths // ================================================================================= -void EMSCRIPTEN_KEEPALIVE SkPathToVerbsArgsArray(SkPath path, emscripten::val /*Array*/ verbs, - emscripten::val /*Array*/ args) { - SkPath::Iter iter(path, false); +template +void VisitPath(const SkPath& p, VisitFunc&& f) { + SkPath::RawIter iter(p); SkPoint pts[4]; SkPath::Verb verb; - while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { + while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { + f(verb, pts); + } +} + +void EMSCRIPTEN_KEEPALIVE SkPathToVerbsArgsArray(const SkPath& path, + emscripten::val /*Array*/ verbs, + emscripten::val /*Array*/ args) { + VisitPath(path, [&verbs, &args](SkPath::Verb verb, const SkPoint pts[4]) { switch (verb) { - case SkPath::kMove_Verb: - verbs.call("push", MOVE); - args.call("push", pts[0].x()); - args.call("push", pts[0].y()); - break; - case SkPath::kLine_Verb: - verbs.call("push", LINE); - args.call("push", pts[1].x()); - args.call("push", pts[1].y()); - break; - case SkPath::kQuad_Verb: - verbs.call("push", QUAD); - args.call("push", pts[1].x()); - args.call("push", pts[1].y()); - args.call("push", pts[2].x()); - args.call("push", pts[2].y()); - break; - case SkPath::kConic_Verb: - printf("unsupported conic verb\n"); - // TODO(kjlubick): Port in the logic from SkParsePath::ToSVGString? - break; - case SkPath::kCubic_Verb: - verbs.call("push", CUBIC); - args.call("push", pts[1].x()); - args.call("push", pts[1].y()); - args.call("push", pts[2].x()); - args.call("push", pts[2].y()); - args.call("push", pts[3].x()); - args.call("push", pts[3].y()); - break; - case SkPath::kClose_Verb: - verbs.call("push", CLOSE); - break; - case SkPath::kDone_Verb: - break; + case SkPath::kMove_Verb: + verbs.call("push", MOVE); + args.call("push", pts[0].x(), pts[0].y()); + break; + case SkPath::kLine_Verb: + verbs.call("push", LINE); + args.call("push", pts[1].x(), pts[1].y()); + break; + case SkPath::kQuad_Verb: + verbs.call("push", QUAD); + args.call("push", pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y()); + break; + case SkPath::kConic_Verb: + printf("unsupported conic verb\n"); + // TODO(kjlubick): Port in the logic from SkParsePath::ToSVGString? + break; + case SkPath::kCubic_Verb: + verbs.call("push", CUBIC); + args.call("push", + pts[1].x(), pts[1].y(), + pts[2].x(), pts[2].y(), + pts[3].x(), pts[3].y()); + break; + case SkPath::kClose_Verb: + verbs.call("push", CLOSE); + break; + case SkPath::kDone_Verb: + SkASSERT(false); + break; } - } + }); } emscripten::val JSArray = emscripten::val::global("Array"); @@ -77,50 +79,37 @@ emscripten::val JSArray = emscripten::val::global("Array"); emscripten::val EMSCRIPTEN_KEEPALIVE SkPathToCmdArray(SkPath path) { val cmds = JSArray.new_(); - SkPath::Iter iter(path, false); - SkPoint pts[4]; - SkPath::Verb verb; - while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { + VisitPath(path, [&cmds](SkPath::Verb verb, const SkPoint pts[4]) { val cmd = JSArray.new_(); switch (verb) { - case SkPath::kMove_Verb: - cmd.call("push", MOVE); - cmd.call("push", pts[0].x()); - cmd.call("push", pts[0].y()); - break; - case SkPath::kLine_Verb: - cmd.call("push", LINE); - cmd.call("push", pts[1].x()); - cmd.call("push", pts[1].y()); - break; - case SkPath::kQuad_Verb: - cmd.call("push", QUAD); - cmd.call("push", pts[1].x()); - cmd.call("push", pts[1].y()); - cmd.call("push", pts[2].x()); - cmd.call("push", pts[2].y()); - break; - case SkPath::kConic_Verb: - printf("unsupported conic verb\n"); - // TODO(kjlubick): Port in the logic from SkParsePath::ToSVGString? - break; - case SkPath::kCubic_Verb: - cmd.call("push", CUBIC); - cmd.call("push", pts[1].x()); - cmd.call("push", pts[1].y()); - cmd.call("push", pts[2].x()); - cmd.call("push", pts[2].y()); - cmd.call("push", pts[3].x()); - cmd.call("push", pts[3].y()); - break; - case SkPath::kClose_Verb: - cmd.call("push", CLOSE); - break; - case SkPath::kDone_Verb: - break; + case SkPath::kMove_Verb: + cmd.call("push", MOVE, pts[0].x(), pts[0].y()); + break; + case SkPath::kLine_Verb: + cmd.call("push", LINE, pts[1].x(), pts[1].y()); + break; + case SkPath::kQuad_Verb: + cmd.call("push", QUAD, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y()); + break; + case SkPath::kConic_Verb: + printf("unsupported conic verb\n"); + // TODO(kjlubick): Port in the logic from SkParsePath::ToSVGString? + break; + case SkPath::kCubic_Verb: + cmd.call("push", CUBIC, + pts[1].x(), pts[1].y(), + pts[2].x(), pts[2].y(), + pts[3].x(), pts[3].y()); + break; + case SkPath::kClose_Verb: + cmd.call("push", CLOSE); + break; + case SkPath::kDone_Verb: + SkASSERT(false); + break; } cmds.call("push", cmd); - } + }); return cmds; } @@ -134,10 +123,10 @@ emscripten::val EMSCRIPTEN_KEEPALIVE SkPathToCmdArray(SkPath path) { // in our function type signatures. (this gives an error message like "Cannot call foo due to unbound // types Pi, Pf"). But, we can just pretend they are numbers and cast them to be pointers and // the compiler is happy. -SkPath EMSCRIPTEN_KEEPALIVE SkPathFromVerbsArgsTyped(int /* uint8_t* */ vptr, int numVerbs, - int /* float* */aptr, int numArgs) { - auto verbs = reinterpret_cast(vptr); - auto args = reinterpret_cast(aptr); +SkPath EMSCRIPTEN_KEEPALIVE SkPathFromVerbsArgsTyped(uintptr_t /* uint8_t* */ vptr, int numVerbs, + uintptr_t /* float* */ aptr, int numArgs) { + const auto* verbs = reinterpret_cast(vptr); + const auto* args = reinterpret_cast(aptr); SkPath path; int argsIndex = 0; float x1, y1, x2, y2, x3, y3; @@ -189,8 +178,8 @@ SkPath EMSCRIPTEN_KEEPALIVE SkPathFromVerbsArgsTyped(int /* uint8_t* */ vptr, i } // See above comment for rational of pointer mess -SkPath EMSCRIPTEN_KEEPALIVE SkPathFromCmdTyped(int /* float* */cptr, int numCmds) { - auto cmds = reinterpret_cast(cptr); +SkPath EMSCRIPTEN_KEEPALIVE SkPathFromCmdTyped(uintptr_t /* float* */ cptr, int numCmds) { + const auto* cmds = reinterpret_cast(cptr); SkPath path; float x1, y1, x2, y2, x3, y3; -- cgit v1.2.3