Revert "[skwasm] Dynamic Threading (#164748)" (#165350)

This reverts commit b2a4a05683.

This has been causing issues when rolling to flutter/packages repo. See
https://github.com/flutter/flutter/issues/165347.
This commit is contained in:
Jackson Gardner 2025-03-17 16:40:59 -07:00 committed by GitHub
parent b836fb2682
commit 1d954f4e96
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 314 additions and 210 deletions

View File

@ -277,9 +277,9 @@ config("compiler") {
}
if (is_wasm) {
if (wasm_use_workers) {
cflags += [ "-sWASM_WORKERS=1" ]
ldflags += [ "-sWASM_WORKERS=1" ]
if (wasm_use_pthreads) {
cflags += [ "-pthread" ]
ldflags += [ "-pthread" ]
} if (wasm_shared_memory) {
cflags += [ "-sSHARED_MEMORY=1" ]
ldflags += [ "-sSHARED_MEMORY=1" ]
@ -396,12 +396,12 @@ config("compiler") {
# to say that it does. Define them here instead.
defines += [ "HAVE_SYS_UIO_H" ]
# When Android requires new flags consider also editing the flags in
# the following locations.
# When Android requires new flags consider also editing the flags in
# the following locations.
# Framework plugin_ffi template: packages/flutter_tools/templates/plugin_ffi/src.tmpl/CMakeLists.txt.tmpl
# Example PR: https://github.com/flutter/flutter/pull/155508
# Dart Lang JNI package: pkgs/jni/src/CMakeLists.txt
# Example PR: https://github.com/dart-lang/native/pull/1615
# Dart Lang JNI package: pkgs/jni/src/CMakeLists.txt
# Example PR: https://github.com/dart-lang/native/pull/1615
ldflags += [
"-Wl,--no-undefined",
"-Wl,--exclude-libs,ALL",

View File

@ -11,7 +11,7 @@ declare_args() {
# The location of an activated embedded emsdk.
emsdk_dir = rebase_path("//flutter/prebuilts/emsdk")
wasm_use_workers = false
wasm_use_pthreads = false
wasm_shared_memory = false
wasm_use_dwarf = false
}

View File

@ -42734,6 +42734,8 @@ ORIGIN: ../../../flutter/lib/web_ui/skwasm/filters.cpp + ../../../flutter/LICENS
ORIGIN: ../../../flutter/lib/web_ui/skwasm/fonts.cpp + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/helpers.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/image.cpp + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/library_skwasm_multi_threaded.js + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/library_skwasm_single_threaded.js + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/library_skwasm_support.js + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/paint.cpp + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/path.cpp + ../../../flutter/LICENSE
@ -42743,6 +42745,8 @@ ORIGIN: ../../../flutter/lib/web_ui/skwasm/skwasm_support.h + ../../../flutter/L
ORIGIN: ../../../flutter/lib/web_ui/skwasm/string.cpp + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/surface.cpp + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/surface.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/surface_mt.cpp + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/surface_st.cpp + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/text/line_metrics.cpp + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/text/paragraph.cpp + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/skwasm/text/paragraph_builder.cpp + ../../../flutter/LICENSE
@ -45705,6 +45709,8 @@ FILE: ../../../flutter/lib/web_ui/skwasm/filters.cpp
FILE: ../../../flutter/lib/web_ui/skwasm/fonts.cpp
FILE: ../../../flutter/lib/web_ui/skwasm/helpers.h
FILE: ../../../flutter/lib/web_ui/skwasm/image.cpp
FILE: ../../../flutter/lib/web_ui/skwasm/library_skwasm_multi_threaded.js
FILE: ../../../flutter/lib/web_ui/skwasm/library_skwasm_single_threaded.js
FILE: ../../../flutter/lib/web_ui/skwasm/library_skwasm_support.js
FILE: ../../../flutter/lib/web_ui/skwasm/paint.cpp
FILE: ../../../flutter/lib/web_ui/skwasm/path.cpp
@ -45714,6 +45720,8 @@ FILE: ../../../flutter/lib/web_ui/skwasm/skwasm_support.h
FILE: ../../../flutter/lib/web_ui/skwasm/string.cpp
FILE: ../../../flutter/lib/web_ui/skwasm/surface.cpp
FILE: ../../../flutter/lib/web_ui/skwasm/surface.h
FILE: ../../../flutter/lib/web_ui/skwasm/surface_mt.cpp
FILE: ../../../flutter/lib/web_ui/skwasm/surface_st.cpp
FILE: ../../../flutter/lib/web_ui/skwasm/text/line_metrics.cpp
FILE: ../../../flutter/lib/web_ui/skwasm/text/paragraph.cpp
FILE: ../../../flutter/lib/web_ui/skwasm/text/paragraph_builder.cpp

View File

@ -76,6 +76,7 @@ class CopyArtifactsStep implements PipelineStep {
final String canvaskitSourceDirectory;
final String canvaskitChromiumSourceDirectory;
final String skwasmSourceDirectory;
final String skwasmStSourceDirectory;
switch (source) {
case LocalArtifactSource(:final mode):
final buildDirectory = getBuildDirectoryForRuntimeMode(mode).path;
@ -83,6 +84,7 @@ class CopyArtifactsStep implements PipelineStep {
canvaskitSourceDirectory = pathlib.join(buildDirectory, 'canvaskit');
canvaskitChromiumSourceDirectory = pathlib.join(buildDirectory, 'canvaskit_chromium');
skwasmSourceDirectory = pathlib.join(buildDirectory, 'skwasm');
skwasmStSourceDirectory = pathlib.join(buildDirectory, 'skwasm_st');
case GcsArtifactSource(:final realm):
final artifactsDirectory = (await _downloadArtifacts(realm)).path;
@ -94,6 +96,7 @@ class CopyArtifactsStep implements PipelineStep {
'chromium',
);
skwasmSourceDirectory = pathlib.join(artifactsDirectory, 'canvaskit');
skwasmStSourceDirectory = pathlib.join(artifactsDirectory, 'canvaskit');
}
await environment.webTestsArtifactsDir.create(recursive: true);
@ -113,6 +116,7 @@ class CopyArtifactsStep implements PipelineStep {
if (artifactDeps.skwasm) {
copied.add('Skwasm');
await copyWasmLibrary('skwasm', skwasmSourceDirectory, 'canvaskit');
await copyWasmLibrary('skwasm_st', skwasmStSourceDirectory, 'canvaskit');
}
print('Copied artifacts: ${copied.join(', ')}');
}

View File

@ -6,64 +6,24 @@ import { createWasmInstantiator } from "./instantiate_wasm.js";
import { resolveUrlWithSegments } from "./utils.js";
export const loadSkwasm = async (deps, config, browserEnvironment, baseUrl) => {
const rawSkwasmUrl = resolveUrlWithSegments(baseUrl, 'skwasm.js')
const fileStem = (browserEnvironment.crossOriginIsolated && !config.forceSingleThreadedSkwasm) ? "skwasm" : "skwasm_st";
const rawSkwasmUrl = resolveUrlWithSegments(baseUrl, `${fileStem}.js`)
let skwasmUrl = rawSkwasmUrl;
if (deps.flutterTT.policy) {
skwasmUrl = deps.flutterTT.policy.createScriptURL(skwasmUrl);
}
const wasmInstantiator = createWasmInstantiator(resolveUrlWithSegments(baseUrl, 'skwasm.wasm'));
const wasmInstantiator = createWasmInstantiator(resolveUrlWithSegments(baseUrl, `${fileStem}.wasm`));
const skwasm = await import(skwasmUrl);
return await skwasm.default({
skwasmSingleThreaded: !browserEnvironment.crossOriginIsolated || config.forceSingleThreadedSkwasm,
instantiateWasm: wasmInstantiator,
locateFile: (filename, scriptDirectory) => {
// The wasm workers API has a separate .ww.js file that bootstraps the
// web worker. However, it turns out this worker bootstrapper doesn't
// actually work with ES6 modules, which we have enabled. So we instead
// pass our own bootstrapper that loads skwasm.js as an ES6 module, and
// queues/flushes pending messages that were received during the
// asynchronous load.
if (filename.endsWith('.ww.js')) {
const url = resolveUrlWithSegments(baseUrl, filename);
return URL.createObjectURL(new Blob(
[`
"use strict";
let eventListener;
eventListener = (message) => {
const pendingMessages = [];
const data = message.data;
data["instantiateWasm"] = (info,receiveInstance) => {
const instance = new WebAssembly.Instance(data["wasm"], info);
return receiveInstance(instance, data["wasm"])
};
import(data.js).then(async (skwasm) => {
await skwasm.default(data);
removeEventListener("message", eventListener);
for (const message of pendingMessages) {
dispatchEvent(message);
}
});
console.log("removing initial listener");
removeEventListener("message", eventListener);
eventListener = (message) => {
pendingMessages.push(message);
};
addEventListener("message", eventListener);
};
addEventListener("message", eventListener);
`
],
{ 'type': 'application/javascript' }));
}
return url;
},
// Because of the above workaround, the worker is just a blob and
// can't locate the main script using a relative path to itself,
// so we pass the main script location in.
mainScriptUrlOrBlob: rawSkwasmUrl,
// When hosted via a CDN or some other url that is not the same
// origin as the main script of the page, we will fail to create
// a web worker with the bootstrapping script. This workaround will
// make sure that the worker JS can be loaded regardless of where
// it is hosted.
mainScriptUrlOrBlob: new Blob(
[`import '${skwasmUrl}'`],
{ 'type': 'application/javascript' },
),
});
}

View File

@ -4,69 +4,96 @@
import("//build/toolchain/wasm.gni")
wasm_lib("skwasm") {
public_configs = [ "//flutter:config" ]
template("skwasm_variant") {
wasm_lib(target_name) {
public_configs = [ "//flutter:config" ]
sources = [
"canvas.cpp",
"contour_measure.cpp",
"data.cpp",
"export.h",
"filters.cpp",
"fonts.cpp",
"helpers.h",
"image.cpp",
"paint.cpp",
"path.cpp",
"picture.cpp",
"shaders.cpp",
"skwasm_support.h",
"string.cpp",
"surface.cpp",
"text/line_metrics.cpp",
"text/paragraph.cpp",
"text/paragraph_builder.cpp",
"text/paragraph_style.cpp",
"text/strut_style.cpp",
"text/text_style.cpp",
"vertices.cpp",
"wrappers.h",
]
cflags = [ "-mreference-types" ]
ldflags = [
"-std=c++20",
"-lGL",
"-sUSE_WEBGL2=1",
"-sMAX_WEBGL_VERSION=2",
"-sOFFSCREENCANVAS_SUPPORT",
"-sALLOW_MEMORY_GROWTH",
"-sALLOW_TABLE_GROWTH",
"-lexports.js",
"-sEXPORTED_FUNCTIONS=[stackAlloc]",
"-sEXPORTED_RUNTIME_METHODS=[addFunction,wasmExports,wasmMemory,stackAlloc]",
"-sINCOMING_MODULE_JS_API=[instantiateWasm,locateFile,noExitRuntime,mainScriptUrlOrBlob,wasmMemory,wasm,skwasmSingleThreaded]",
"-sUSE_ES6_IMPORT_META=0",
"--js-library",
rebase_path("library_skwasm_support.js"),
]
inputs = [ rebase_path("library_skwasm_support.js") ]
if (is_debug) {
ldflags += [
"-sASSERTIONS=1",
"-sGL_ASSERTIONS=1",
"-sSTACK_OVERFLOW_CHECK=2",
sources = [
"canvas.cpp",
"contour_measure.cpp",
"data.cpp",
"export.h",
"filters.cpp",
"fonts.cpp",
"helpers.h",
"image.cpp",
"paint.cpp",
"path.cpp",
"picture.cpp",
"shaders.cpp",
"skwasm_support.h",
"string.cpp",
"surface.cpp",
"text/line_metrics.cpp",
"text/paragraph.cpp",
"text/paragraph_builder.cpp",
"text/paragraph_style.cpp",
"text/strut_style.cpp",
"text/text_style.cpp",
"vertices.cpp",
"wrappers.h",
]
} else {
ldflags += [ "--closure=1" ]
}
deps = [
"//flutter/skia",
"//flutter/skia/modules/skparagraph",
"//flutter/skia/modules/skunicode",
]
cflags = [ "-mreference-types" ]
ldflags = [
"-std=c++20",
"-lGL",
"-sUSE_WEBGL2=1",
"-sMAX_WEBGL_VERSION=2",
"-sOFFSCREENCANVAS_SUPPORT",
"-sALLOW_MEMORY_GROWTH",
"-sALLOW_TABLE_GROWTH",
"-lexports.js",
"-sEXPORTED_FUNCTIONS=[stackAlloc]",
"-sEXPORTED_RUNTIME_METHODS=[addFunction,wasmExports,wasmMemory,stackAlloc]",
"-sINCOMING_MODULE_JS_API=[instantiateWasm,noExitRuntime,mainScriptUrlOrBlob]",
"-sUSE_ES6_IMPORT_META=0",
"--js-library",
rebase_path("library_skwasm_support.js"),
]
inputs = [ rebase_path("library_skwasm_support.js") ]
if (invoker.multi_threaded) {
sources += [ "surface_mt.cpp" ]
ldflags += [
"-sPTHREAD_POOL_SIZE=1",
"-Wno-pthreads-mem-growth",
"--js-library",
rebase_path("library_skwasm_multi_threaded.js"),
]
inputs += [ rebase_path("library_skwasm_multi_threaded.js") ]
} else {
sources += [ "surface_st.cpp" ]
ldflags += [
"--js-library",
rebase_path("library_skwasm_single_threaded.js"),
]
inputs += [ rebase_path("library_skwasm_single_threaded.js") ]
}
if (is_debug) {
ldflags += [
"-sASSERTIONS=1",
"-sGL_ASSERTIONS=1",
]
} else {
ldflags += [ "--closure=1" ]
}
deps = [
"//flutter/skia",
"//flutter/skia/modules/skparagraph",
"//flutter/skia/modules/skunicode",
]
}
}
skwasm_variant("skwasm") {
multi_threaded = true
}
skwasm_variant("skwasm_st") {
multi_threaded = false
}

View File

@ -0,0 +1,57 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file adds JavaScript APIs that are accessible to the C++ layer.
// See: https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#implement-a-c-api-in-javascript
mergeInto(LibraryManager.library, {
$skwasm_threading_setup__postset: 'skwasm_threading_setup();',
$skwasm_threading_setup: function() {
// This value represents the difference between the time origin of the main
// thread and whichever web worker this code is running on. This is so that
// when we report frame timings, that they are in the same time domain
// regardless of whether they are captured on the main thread or the web
// worker.
let timeOriginDelta = 0;
skwasm_registerMessageListener = function(threadId, listener) {
const eventListener = function({data}) {
const skwasmMessage = data.skwasmMessage;
if (!skwasmMessage) {
return;
}
if (skwasmMessage == 'syncTimeOrigin') {
timeOriginDelta = performance.timeOrigin - data.timeOrigin;
return;
}
listener(data);
};
if (!threadId) {
addEventListener("message", eventListener);
} else {
PThread.pthreads[threadId].addEventListener("message", eventListener);
PThread.pthreads[threadId].postMessage({
skwasmMessage: 'syncTimeOrigin',
timeOrigin: performance.timeOrigin,
});
}
};
skwasm_getCurrentTimestamp = function() {
return performance.now() + timeOriginDelta;
};
skwasm_postMessage = function(message, transfers, threadId) {
if (threadId) {
PThread.pthreads[threadId].postMessage(message, transfers);
} else {
postMessage(message, transfers);
}
};
},
$skwasm_threading_setup__deps: ['$skwasm_registerMessageListener', '$skwasm_getCurrentTimestamp', '$skwasm_postMessage'],
$skwasm_registerMessageListener: function() {},
$skwasm_registerMessageListener__deps: ['$skwasm_threading_setup'],
$skwasm_getCurrentTimestamp: function () {},
$skwasm_getCurrentTimestamp__deps: ['$skwasm_threading_setup'],
$skwasm_postMessage: function () {},
$skwasm_postMessage__deps: ['$skwasm_threading_setup'],
});

View File

@ -0,0 +1,31 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file adds JavaScript APIs that are accessible to the C++ layer.
// See: https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#implement-a-c-api-in-javascript
mergeInto(LibraryManager.library, {
$skwasm_threading_setup__postset: 'skwasm_threading_setup();',
$skwasm_threading_setup: function() {
let messageListener;
skwasm_registerMessageListener = function(threadId, listener) {
messageListener = listener;
};
skwasm_getCurrentTimestamp = function() {
return performance.now();
};
skwasm_postMessage = function(message, transfers, threadId) {
queueMicrotask(() => {
messageListener(message);
})
};
},
$skwasm_threading_setup__deps: ['$skwasm_registerMessageListener', '$skwasm_getCurrentTimestamp', '$skwasm_postMessage'],
$skwasm_registerMessageListener: function() {},
$skwasm_registerMessageListener__deps: ['$skwasm_threading_setup'],
$skwasm_getCurrentTimestamp: function () {},
$skwasm_getCurrentTimestamp__deps: ['$skwasm_threading_setup'],
$skwasm_postMessage: function () {},
$skwasm_postMessage__deps: ['$skwasm_threading_setup'],
});

View File

@ -8,51 +8,9 @@
mergeInto(LibraryManager.library, {
$skwasm_support_setup__postset: 'skwasm_support_setup();',
$skwasm_support_setup: function() {
// This value represents the difference between the time origin of the main
// thread and whichever web worker this code is running on. This is so that
// when we report frame timings, that they are in the same time domain
// regardless of whether they are captured on the main thread or the web
// worker.
let timeOriginDelta = 0;
skwasm_registerMessageListener = function(threadId, listener) {
const eventListener = function({data}) {
const skwasmMessage = data.skwasmMessage;
if (!skwasmMessage) {
return;
}
if (skwasmMessage == 'syncTimeOrigin') {
timeOriginDelta = performance.timeOrigin - data.timeOrigin;
return;
}
listener(data);
};
if (!threadId) {
addEventListener("message", eventListener);
} else {
_wasmWorkers[threadId].addEventListener("message", eventListener);
_wasmWorkers[threadId].postMessage({
skwasmMessage: 'syncTimeOrigin',
timeOrigin: performance.timeOrigin,
});
}
};
skwasm_getCurrentTimestamp = function() {
return performance.now() + timeOriginDelta;
};
skwasm_postMessage = function(message, transfers, threadId) {
if (threadId) {
_wasmWorkers[threadId].postMessage(message, transfers);
} else {
postMessage(message, transfers);
}
};
const handleToCanvasMap = new Map();
const associatedObjectsMap = new Map();
_skwasm_isSingleThreaded = function() {
return Module["skwasmSingleThreaded"];
};
_skwasm_setAssociatedObjectOnThread = function(threadId, pointer, object) {
skwasm_postMessage({
skwasmMessage: 'setAssociatedObject',
@ -217,22 +175,15 @@ mergeInto(LibraryManager.library, {
});
}
},
$skwasm_registerMessageListener: function() {},
$skwasm_registerMessageListener__deps: ['$skwasm_support_setup'],
$skwasm_getCurrentTimestamp: function () {},
$skwasm_getCurrentTimestamp__deps: ['$skwasm_support_setup'],
$skwasm_postMessage: function () {},
$skwasm_postMessage__deps: ['$skwasm_support_setup'],
skwasm_isSingleThreaded: function() {},
skwasm_isSingleThreaded__deps: ['$skwasm_support_setup'],
$skwasm_support_setup__deps: [ '$skwasm_threading_setup'],
skwasm_setAssociatedObjectOnThread: function () {},
skwasm_setAssociatedObjectOnThread__deps: ['$skwasm_support_setup', '$skwasm_postMessage'],
skwasm_setAssociatedObjectOnThread__deps: ['$skwasm_support_setup'],
skwasm_getAssociatedObject: function () {},
skwasm_getAssociatedObject__deps: ['$skwasm_support_setup'],
skwasm_disposeAssociatedObjectOnThread: function () {},
skwasm_disposeAssociatedObjectOnThread__deps: ['$skwasm_support_setup'],
skwasm_connectThread: function() {},
skwasm_connectThread__deps: ['$skwasm_support_setup', '$skwasm_registerMessageListener', '$skwasm_getCurrentTimestamp'],
skwasm_connectThread__deps: ['$skwasm_support_setup'],
skwasm_dispatchRenderPictures: function() {},
skwasm_dispatchRenderPictures__deps: ['$skwasm_support_setup'],
skwasm_createOffscreenCanvas: function () {},

View File

@ -13,7 +13,6 @@
using SkwasmObject = __externref_t;
extern "C" {
extern bool skwasm_isSingleThreaded();
extern void skwasm_setAssociatedObjectOnThread(unsigned long threadId,
void* pointer,
SkwasmObject object);

View File

@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "surface.h"
#include <emscripten/wasm_worker.h>
#include <algorithm>
#include "skwasm_support.h"
@ -15,23 +14,6 @@
using namespace Skwasm;
Surface::Surface() {
if (skwasm_isSingleThreaded()) {
skwasm_connectThread(0);
} else {
assert(emscripten_is_main_browser_thread());
_thread = emscripten_malloc_wasm_worker(65536);
emscripten_wasm_worker_post_function_v(_thread, []() {
// Listen to the main thread from the worker
skwasm_connectThread(0);
});
// Listen to messages from the worker
skwasm_connectThread(_thread);
}
}
// Worker thread only
void Surface::dispose() {
delete this;
@ -76,8 +58,16 @@ void Surface::setCallbackHandler(CallbackHandler* callbackHandler) {
_callbackHandler = callbackHandler;
}
// Worker thread only
void Surface::_runWorker() {
_init();
emscripten_exit_with_live_runtime();
}
// Worker thread only
void Surface::_init() {
// Listen to messages from the main thread
skwasm_connectThread(0);
_glContext = skwasm_createOffscreenCanvas(256, 256);
if (!_glContext) {
printf("Failed to create context!\n");
@ -105,8 +95,6 @@ void Surface::_init() {
emscripten_glGetIntegerv(GL_SAMPLES, &_sampleCount);
emscripten_glGetIntegerv(GL_STENCIL_BITS, &_stencil);
_isInitialized = true;
}
// Worker thread only
@ -134,10 +122,6 @@ void Surface::renderPicturesOnWorker(sk_sp<SkPicture>* pictures,
int pictureCount,
uint32_t callbackId,
double rasterStart) {
if (!_isInitialized) {
_init();
}
// This is populated by the `captureImageBitmap` call the first time it is
// passed in.
SkwasmObject imageBitmapArray = __builtin_wasm_ref_null_extern();
@ -163,10 +147,6 @@ void Surface::renderPicturesOnWorker(sk_sp<SkPicture>* pictures,
void Surface::rasterizeImageOnWorker(SkImage* image,
ImageByteFormat format,
uint32_t callbackId) {
if (!_isInitialized) {
_init();
}
// We handle PNG encoding with browser APIs so that we can omit libpng from
// skia to save binary size.
assert(format != ImageByteFormat::png);
@ -301,7 +281,3 @@ SKWASM_EXPORT void surface_onRasterizeComplete(Surface* surface,
uint32_t callbackId) {
surface->onRasterizeComplete(callbackId, data);
}
SKWASM_EXPORT bool skwasm_isMultiThreaded() {
return !skwasm_isSingleThreaded();
}

View File

@ -75,10 +75,12 @@ class Surface {
uint32_t callbackId);
private:
void _runWorker();
void _init();
void _resizeCanvasToFit(int width, int height);
void _recreateSurface();
std::string _canvasID;
CallbackHandler* _callbackHandler = nullptr;
uint32_t _currentCallbackId = 0;
@ -93,8 +95,6 @@ class Surface {
GrGLint _stencil;
pthread_t _thread;
bool _isInitialized = false;
};
} // namespace Skwasm

View File

@ -0,0 +1,31 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "surface.h"
#include "skwasm_support.h"
using namespace Skwasm;
Surface::Surface() {
assert(emscripten_is_main_browser_thread());
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(
&_thread, &attr,
[](void* context) -> void* {
static_cast<Surface*>(context)->_runWorker();
return nullptr;
},
this);
// Listen to messages from the worker
skwasm_connectThread(_thread);
}
SKWASM_EXPORT bool skwasm_isMultiThreaded() {
return true;
}

View File

@ -0,0 +1,15 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "surface.h"
using namespace Skwasm;
Surface::Surface() : _thread(0) {
_init();
}
SKWASM_EXPORT bool skwasm_isMultiThreaded() {
return false;
}

View File

@ -88,7 +88,31 @@ wasm_toolchain("skwasm") {
skia_use_libpng_encode = false
# skwasm is multithreaded
wasm_use_workers = true
wasm_use_pthreads = true
wasm_prioritize_size = true
}
}
wasm_toolchain("skwasm_st") {
extra_toolchain_args = {
# In Chromium browsers, we can use the browser's APIs to get the necessary
# ICU data.
skia_use_icu = false
skia_use_client_icu = true
skia_icu_bidi_third_party_dir = "//flutter/third_party/canvaskit/icu_bidi"
skia_use_libjpeg_turbo_decode = false
skia_use_libpng_decode = false
skia_use_libwebp_decode = false
# We use OffscreenCanvas to produce PNG data instead of skia
skia_use_no_png_encode = true
skia_use_libpng_encode = false
# skwasm_st doesn't use pthreads, but does pass the shared memory flag in order
# to be compatible with the way app modules import the memory object.
wasm_use_pthreads = false
wasm_shared_memory = true
wasm_prioritize_size = true
}
}
@ -109,3 +133,20 @@ copy("skwasm_group") {
}
outputs = [ "$root_out_dir/flutter_web_sdk/canvaskit/{{source_file_part}}" ]
}
copy("skwasm_st_group") {
visibility = [ "//flutter/web_sdk:*" ]
public_deps = [ "//flutter/lib/web_ui/skwasm:skwasm_st(:skwasm_st)" ]
sources = [
"$root_out_dir/skwasm_st/skwasm_st.js",
"$root_out_dir/skwasm_st/skwasm_st.js.symbols",
"$root_out_dir/skwasm_st/skwasm_st.wasm",
]
if (is_debug) {
if (!wasm_use_dwarf) {
sources += [ "$root_out_dir/skwasm_st/skwasm_st.wasm.map" ]
}
}
outputs = [ "$root_out_dir/flutter_web_sdk/canvaskit/{{source_file_part}}" ]
}

View File

@ -414,6 +414,7 @@ if (!is_fuchsia) {
"//flutter/third_party/canvaskit:canvaskit_chromium_group",
"//flutter/third_party/canvaskit:canvaskit_group",
"//flutter/third_party/canvaskit:skwasm_group",
"//flutter/third_party/canvaskit:skwasm_st_group",
]
}
deps += [ "//flutter/lib/web_ui/flutter_js" ]
@ -438,6 +439,9 @@ if (!is_fuchsia) {
"$root_out_dir/flutter_web_sdk/canvaskit/skwasm.js",
"$root_out_dir/flutter_web_sdk/canvaskit/skwasm.js.symbols",
"$root_out_dir/flutter_web_sdk/canvaskit/skwasm.wasm",
"$root_out_dir/flutter_web_sdk/canvaskit/skwasm_st.js",
"$root_out_dir/flutter_web_sdk/canvaskit/skwasm_st.js.symbols",
"$root_out_dir/flutter_web_sdk/canvaskit/skwasm_st.wasm",
]
}