Unverified Commit 60191b83 authored by Shagen Ogandzhanian's avatar Shagen Ogandzhanian Committed by GitHub

Introduce minimal initialization layer for using it as API on the frontend side (#194)

parent 16b2dee5
package org.jetbrains.skiko.sample.js
import org.jetbrains.skia.Paint
import org.jetbrains.skiko.wasm.onWasmReady
fun main(args: Array<String>) {
println(Paint())
onWasmReady {
println(Paint())
}
}
\ No newline at end of file
......@@ -4,10 +4,6 @@
<meta charset="UTF-8">
<title>skiko for web demo</title>
<script src="skiko.js"> </script>
<script>
// Temporary, to debug loading issues.
initRuntime();
</script>
<script src="SkiaJsSample.js"> </script>
</head>
<body>
......
......@@ -354,13 +354,16 @@ val wasmCompile = project.tasks.register<Exec>("wasmCompile") {
val outJs = "$outDir/skiko.js"
val outWasm = "$outDir/skiko.wasm"
workingDir = File(outDir)
val skikoJsPrefix = "$projectDir/src/jsMain/resources/setup.js"
if (supportWasm) {
commandLine = listOf(
"emcc",
*buildType.clangFlags,
*Arch.Wasm.clangFlags,
"-I$projectDir/src/commonMain/cpp",
*skiaPreprocessorFlags(skiaDir),
"-o", outJs,
"--extern-post-js", skikoJsPrefix,
*srcs
)
argumentProviders.add(CommandLineArgumentProvider {
......@@ -377,7 +380,7 @@ val wasmCompile = project.tasks.register<Exec>("wasmCompile") {
)
}
file(outDir).mkdirs()
inputs.files(srcs)
inputs.files(srcs + listOf(skikoJsPrefix))
outputs.files(outJs, outWasm)
}
......
......@@ -6,13 +6,11 @@ config.browserConsoleLogOptions.level = "debug";
const basePath = config.basePath;
const projectPath = path.resolve(basePath, "..", "..", "..", "..", "..");
const setupPath = path.resolve(projectPath, "src", "jsTest", "config");
const wasmPath = path.resolve(projectPath, "build", "wasm")
const debug = message => console.log(`[karma-config] ${message}`);
debug(`karma basePath: ${basePath}`);
debug(`karma setupPath: ${setupPath}`);
debug(`karma wasmPath: ${wasmPath}`);
config.proxies = {
......@@ -20,7 +18,6 @@ config.proxies = {
}
config.files = [
path.resolve(setupPath, "wasmsetup.js"),
path.resolve(wasmPath, "skiko.js"),
{pattern: path.resolve(wasmPath, "skiko.wasm"), included: false, served: true, watched: false},
].concat(config.files);
......
#include "common.h"
#include <emscripten.h>
typedef void (*finalizer_t)(void*);
EMSCRIPTEN_KEEPALIVE
extern "C" void org_jetbrains_skia_ColorSpace__nInvokeFinalizer(KPointer finalizer, KPointer obj) {
SKIKO_EXPORT void org_jetbrains_skia_impl_Managed__invokeFinalizer(KNativePointer finalizer, KNativePointer obj) {
finalizer_t finalizer_f = reinterpret_cast<finalizer_t>(finalizer);
finalizer_f(obj);
}
\ No newline at end of file
}
#include "common.h"
#include "SkRefCnt.h"
class SkRefCntHack {
......@@ -11,12 +12,11 @@ void unrefSkRefCnt(SkRefCnt* p) {
p->unref();
}
extern "C" KNativePointer org_jetbrains_skia_impl_RefCnt__1nGetFinalizer() {
SKIKO_EXPORT KNativePointer org_jetbrains_skia_impl_RefCnt__getFinalizer() {
return reinterpret_cast<KNativePointer>(&unrefSkRefCnt);
}
extern "C" KInt org_jetbrains_skia_impl_RefCnt__1nGetRefCount(KNativePointer ptr) {
SKIKO_EXPORT KInt org_jetbrains_skia_impl_RefCnt__getRefCount(KNativePointer ptr) {
SkRefCnt* instance = reinterpret_cast<SkRefCnt*>(ptr);
return reinterpret_cast<SkRefCntHack*>(instance)->fRefCnt.load(std::memory_order_relaxed);
}
......@@ -11,17 +11,15 @@
#include "SkFilterQuality.h"
#include "common.h"
static void deletePaint(SkPaint* paint) {
void deletePaint(SkPaint* paint) {
delete paint;
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Paint__1nGetFinalizer
(){
return reinterpret_cast<KNativePointer>((&deletePaint));
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Paint__1nGetFinalizer(){
return reinterpret_cast<KNativePointer>(&deletePaint);
}
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Paint__1nMake
(){
SKIKO_EXPORT KNativePointer org_jetbrains_skia_Paint__1nMake(){
SkPaint* obj = new SkPaint();
obj->setAntiAlias(true);
return reinterpret_cast<KNativePointer>(obj);
......
......@@ -11,6 +11,8 @@ expect abstract class Native(ptr: NativePointer) {
companion object {
val NullPointer: NativePointer
}
override fun toString(): String
}
expect fun reachabilityBarrier(obj: Any?)
......
#include <emscripten.h>
#include "common.h"
#include "SkRefCnt.h"
class SkRefCntHack {
public:
void* x;
mutable std::atomic<int32_t> fRefCnt;
};
void unrefSkRefCnt(SkRefCnt* p) {
p->unref();
}
EMSCRIPTEN_KEEPALIVE
extern "C" KPointer org_jetbrains_skia_impl_RefCnt__1nGetFinalizer() {
return reinterpret_cast<KPointer>(&unrefSkRefCnt);
}
EMSCRIPTEN_KEEPALIVE
extern "C" KInt org_jetbrains_skia_impl_RefCnt__1nGetRefCount(KPointer ptr) {
SkRefCnt* instance = reinterpret_cast<SkRefCnt*>(ptr);
return reinterpret_cast<SkRefCntHack*>(instance)->fRefCnt.load(std::memory_order_relaxed);
}
#pragma once
#include <stdint.h>
typedef int32_t KInt;
typedef int64_t KLong;
typedef void* KPointer;
typedef uint8_t* KByteArray;
......@@ -3,8 +3,6 @@ package org.jetbrains.skia.impl
actual class Library {
actual companion object {
actual fun staticLoad() {
// TODO: load wasm and js modules, maybe just js, as it will load Wasm.
TODO()
}
}
}
......@@ -49,12 +49,12 @@ actual abstract class Managed actual constructor(ptr: NativePointer, finalizer:
if (managed) {
require(ptr != 0) { "Managed ptr is 0" }
require(finalizer != 0) { "Managed finalizer is 0" }
val thunk = FinalizationThunk(ptr, finalizer)
val thunk = FinalizationThunk(finalizer, ptr)
register(this, thunk)
cleaner = thunk
}
}
}
@JsName("org_jetbrains_skia_Managed__invokeFinalizer")
@JsName("org_jetbrains_skia_impl_Managed__invokeFinalizer")
private external fun _nInvokeFinalizer(finalizer: NativePointer, obj: NativePointer)
\ No newline at end of file
......@@ -10,6 +10,10 @@ actual abstract class Native actual constructor(ptr: NativePointer) {
get() = 0
}
actual override fun toString(): String {
return this::class.simpleName + "(_ptr=0x" + _ptr.toString(16) + ")"
}
init {
if (ptr == NullPointer) throw RuntimeException("Can't wrap nullptr")
_ptr = ptr
......
......@@ -20,7 +20,7 @@ private object _FinalizerHolder {
val PTR = _nGetFinalizer()
}
@JsName("org_jetbrains_skia_RefCnt__nGetFinalizer")
@JsName("org_jetbrains_skia_impl_RefCnt__getFinalizer")
private external fun _nGetFinalizer(): NativePointer
@JsName("org_jetbrains_skia_RefCnt__nGetCount")
@JsName("org_jetbrains_skia_impl_RefCnt__getCount")
private external fun _nGetRefCount(ptr: NativePointer): Int
......@@ -3,7 +3,10 @@ package org.jetbrains.skiko.wasm
import kotlinx.dom.createElement
import kotlinx.browser.document
import org.w3c.dom.HTMLCanvasElement
import kotlin.js.Promise
external val wasmSetup: Promise<Boolean>
external fun onWasmReady(onReady: () -> Unit)
@JsExport
fun createSkikoCanvas(): HTMLCanvasElement {
......
var Module = {};
Module['locateFile'] = (path, scriptDirectory) => {
return "/wasm/skiko.wasm";
};
var ModulePromised = new Promise(function(resolve, reject) {
var wasmSetup = new Promise(function(resolve, reject) {
Module['onRuntimeInitialized'] = _ => {
resolve(Module);
};
});
function onWasmReady(onReady) { wasmSetup.then(onReady); }
......@@ -12,24 +12,20 @@ external interface ModuleInterface {
fun ping(): Boolean
}
external val ModulePromised: Promise<ModuleInterface>
external val Module: ModuleInterface
suspend fun <T> Promise<T>.await(): T = suspendCoroutine { cont ->
then({ cont.resume(it) }, { cont.resumeWithException(it) })
}
private fun async(block: suspend () -> Unit): dynamic = GlobalScope.promise {
block()
}
private fun withModule(block: ModuleInterface.() -> Unit) = async {
val module = ModulePromised.await()
block.invoke(module)
private fun wasmTest(block: () -> Unit) = GlobalScope.promise {
wasmSetup.await()
block.invoke()
}
class WasmTests {
@Test
fun pingTest() = withModule {
assertTrue(this.ping())
@Test
fun pingTest() = wasmTest {
assertTrue(Module.ping())
}
}
\ No newline at end of file
......@@ -10,7 +10,7 @@ actual abstract class Native actual constructor(ptr: NativePointer) {
get() = 0L
}
override fun toString(): String {
actual override fun toString(): String {
return javaClass.simpleName + "(_ptr=0x" + _ptr.toString(16) + ")"
}
......
#include <iostream>
#include "common.h"
typedef void (*FreeFunction)(void*);
extern "C" void org_jetbrains_skia_impl_Managed__1nInvokeFinalizer
(KNativePointer finalizerPtr, KNativePointer ptr) {
FreeFunction finalizer = reinterpret_cast<FreeFunction>(finalizerPtr);
finalizer(ptr);
}
......@@ -59,5 +59,5 @@ actual abstract class Managed actual constructor(
get() = _ptr == NullPointer
}
@ExternalSymbolName("org_jetbrains_skia_impl_Managed__1nInvokeFinalizer")
@ExternalSymbolName("org_jetbrains_skia_impl_Managed__invokeFinalizer")
external fun _nInvokeFinalizer(finalizer: NativePointer, ptr: NativePointer)
......@@ -7,9 +7,6 @@ import kotlin.native.internal.NativePtr
actual abstract class Native actual constructor(ptr: NativePointer) {
actual var _ptr: NativePointer
override fun toString(): String {
return this::class.simpleName + "(_ptr=0x$_ptr)"
}
actual open fun _nativeEquals(other: Native?): Boolean = this._ptr == other?._ptr ?: Native.NullPointer
......@@ -18,6 +15,10 @@ actual abstract class Native actual constructor(ptr: NativePointer) {
get() = NativePtr.NULL
}
actual override fun toString(): String {
return this::class.simpleName + "(_ptr=0x" + _ptr.toString() + ")"
}
init {
if (ptr == NativePtr.NULL) throw RuntimeException("Can't wrap nullptr")
_ptr = ptr
......
......@@ -24,7 +24,7 @@ actual abstract class RefCnt : Managed {
}
}
@ExternalSymbolName("org_jetbrains_skia_impl_RefCnt__1nGetFinalizer")
@ExternalSymbolName("org_jetbrains_skia_impl_RefCnt__getFinalizer")
private external fun _nGetFinalizer(): NativePointer
@ExternalSymbolName("org_jetbrains_skia_impl_RefCnt__1nGetRefCount")
@ExternalSymbolName("org_jetbrains_skia_impl_RefCnt__getRefCount")
private external fun _nGetRefCount(ptr: NativePointer): Int
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment