Flutter Engine
The Flutter Engine
WasmCommon.h
Go to the documentation of this file.
1/*
2 * Copyright 2019 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef WasmCommon_DEFINED
9#define WasmCommon_DEFINED
10
11#include <emscripten.h>
12#include <emscripten/bind.h>
15#include "include/core/SkSpan.h"
17
18#include <memory>
19
20class SkData;
21class SkCodec;
22
23using namespace emscripten;
24
25// Self-documenting types
26using JSColor = int32_t;
27using JSArray = emscripten::val;
28using JSObject = emscripten::val;
29using JSString = emscripten::val;
30using SkPathOrNull = emscripten::val;
31using TypedArray = emscripten::val;
32using Uint8Array = emscripten::val;
33using Uint16Array = emscripten::val;
34using Uint32Array = emscripten::val;
35using Float32Array = emscripten::val;
36
37// If we are using C++ and EMSCRIPTEN_BINDINGS, we can't have primitive pointers in our function
38// type signatures. (this gives an error message like "Cannot call foo due to unbound
39// types Pi, Pf"). But, we can just pretend they are numbers and cast them to be pointers and
40// the compiler is happy.
41// These types refer to the TypedArray that the JS interface wrote into or will read out of.
42// This doesn't stop us from using these as different types; e.g. a float* can be treated as an
43// SkPoint* in some APIs.
44using WASMPointerF32 = uintptr_t;
45using WASMPointerI32 = uintptr_t;
46using WASMPointerU8 = uintptr_t;
47using WASMPointerU16 = uintptr_t;
48using WASMPointerU32 = uintptr_t;
49using WASMPointer = uintptr_t;
50
51#define SPECIALIZE_JSARRAYTYPE(type, name) \
52 template <> struct JSArrayType<type> { \
53 static constexpr const char* const gName = name; \
54 }
55
56template <typename T> struct JSArrayType {};
57
58SPECIALIZE_JSARRAYTYPE( int8_t, "Int8Array");
59SPECIALIZE_JSARRAYTYPE(uint8_t, "Uint8Array");
60SPECIALIZE_JSARRAYTYPE( int16_t, "Int16Array");
61SPECIALIZE_JSARRAYTYPE(uint16_t, "Uint16Array");
62SPECIALIZE_JSARRAYTYPE( int32_t, "Int32Array");
63SPECIALIZE_JSARRAYTYPE(uint32_t, "Uint32Array");
64SPECIALIZE_JSARRAYTYPE(float, "Float32Array");
65
66#undef SPECIALIZE_JSARRAYTYPE
67
68/**
69 * Create a typed-array (in the JS heap) and initialize it with the provided
70 * data (from the wasm heap).
71 */
72template <typename T> TypedArray MakeTypedArray(int count, const T src[]) {
73 emscripten::val length = emscripten::val(count);
74 emscripten::val jarray = emscripten::val::global(JSArrayType<T>::gName).new_(count);
75 jarray.call<void>("set", val(typed_memory_view(count, src)));
76 return jarray;
77}
78
80
81std::unique_ptr<SkCodec> DecodeImageData(sk_sp<SkData>);
82
83/**
84 * Gives read access to a JSArray
85 *
86 * We explicitly use malloc/free (not new/delete) so this can be used with allocations from the JS
87 * side (ala CanvasKit.Malloc).
88 */
89template <typename T> class JSSpan {
90public:
91 // Note: Use of this constructor is 5-20x slower than manually copying the data on the JS side
92 // and sending over a pointer, length, and boolean for the other constructor.
94 const size_t len = src["length"].as<size_t>();
95 T* data;
96
97 // If the buffer was allocated via CanvasKit' Malloc, we can peek directly at it!
98 if (src["_ck"].isTrue()) {
99 fOwned = false;
100 data = reinterpret_cast<T*>(src["byteOffset"].as<size_t>());
101 } else {
102 fOwned = true;
103 data = static_cast<T*>(sk_malloc_throw(len, sizeof(T)));
104
105 // now actually copy into 'data'
106 if (src.instanceof(emscripten::val::global(JSArrayType<T>::gName))) {
107 auto dst_view = emscripten::val(typed_memory_view(len, data));
108 dst_view.call<void>("set", src);
109 } else {
110 for (size_t i = 0; i < len; ++i) {
111 data[i] = src[i].as<T>();
112 }
113 }
114 }
115 fSpan = SkSpan(data, len);
116 }
117
118 JSSpan(WASMPointer ptr, size_t len, bool takeOwnership): fOwned(takeOwnership) {
119 fSpan = SkSpan(reinterpret_cast<T*>(ptr), len);
120 }
121
123 if (fOwned) {
124 sk_free(fSpan.data());
125 }
126 }
127
128 const T* data() const { return fSpan.data(); }
129 size_t size() const { return fSpan.size(); }
130
131private:
132 SkSpan<T> fSpan;
133 bool fOwned;
134};
135
136#endif
int count
Definition: FontMgrTest.cpp:50
SK_API void sk_free(void *)
static void * sk_malloc_throw(size_t size)
Definition: SkMalloc.h:67
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
emscripten::val JSObject
Definition: WasmCommon.h:28
int32_t JSColor
Definition: WasmCommon.h:26
std::unique_ptr< SkCodec > DecodeImageData(sk_sp< SkData >)
#define SPECIALIZE_JSARRAYTYPE(type, name)
Definition: WasmCommon.h:51
uintptr_t WASMPointer
Definition: WasmCommon.h:49
uintptr_t WASMPointerU8
Definition: WasmCommon.h:46
emscripten::val Uint32Array
Definition: WasmCommon.h:34
emscripten::val SkPathOrNull
Definition: WasmCommon.h:30
emscripten::val JSString
Definition: WasmCommon.h:29
uintptr_t WASMPointerU16
Definition: WasmCommon.h:47
emscripten::val Uint16Array
Definition: WasmCommon.h:33
uintptr_t WASMPointerU32
Definition: WasmCommon.h:48
uintptr_t WASMPointerI32
Definition: WasmCommon.h:45
uintptr_t WASMPointerF32
Definition: WasmCommon.h:44
TypedArray MakeTypedArray(int count, const T src[])
Definition: WasmCommon.h:72
SkColor4f ptrToSkColor4f(WASMPointerF32)
emscripten::val TypedArray
Definition: WasmCommon.h:31
emscripten::val Float32Array
Definition: WasmCommon.h:35
emscripten::val Uint8Array
Definition: WasmCommon.h:32
emscripten::val JSArray
Definition: WasmCommon.h:27
JSSpan(WASMPointer ptr, size_t len, bool takeOwnership)
Definition: WasmCommon.h:118
const T * data() const
Definition: WasmCommon.h:128
~JSSpan()
Definition: WasmCommon.h:122
JSSpan(JSArray src)
Definition: WasmCommon.h:93
size_t size() const
Definition: WasmCommon.h:129
Definition: SkData.h:25
size_t length
#define T
Definition: precompiler.cc:65