mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Begin work on Event System for js_wasm32 target
This commit is contained in:
Vendored
+1
@@ -32,6 +32,7 @@ const runWasm = async (wasm_path, webglCanvasElement, consoleElement) => {
|
|||||||
const file = await response.arrayBuffer();
|
const file = await response.arrayBuffer();
|
||||||
const wasm = await WebAssembly.instantiate(file, imports);
|
const wasm = await WebAssembly.instantiate(file, imports);
|
||||||
const exports = wasm.instance.exports;
|
const exports = wasm.instance.exports;
|
||||||
|
wasmMemoryInterface.setExports(exports);
|
||||||
wasmMemoryInterface.setMemory(exports.memory);
|
wasmMemoryInterface.setMemory(exports.memory);
|
||||||
|
|
||||||
exports._start();
|
exports._start();
|
||||||
|
|||||||
+99
-99
@@ -23,11 +23,11 @@ class WebGLInterface {
|
|||||||
this.transformFeedbacks = [];
|
this.transformFeedbacks = [];
|
||||||
this.syncs = [];
|
this.syncs = [];
|
||||||
this.programInfos = {};
|
this.programInfos = {};
|
||||||
|
|
||||||
if (contextSettings === undefined) {
|
if (contextSettings === undefined) {
|
||||||
contextSettings = {antialias: false};
|
contextSettings = {antialias: false};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ctx = canvasElement.getContext("webgl2", contextSettings) || canvasElement.getContext("webgl", contextSettings);
|
this.ctx = canvasElement.getContext("webgl2", contextSettings) || canvasElement.getContext("webgl", contextSettings);
|
||||||
if (!this.ctx) {
|
if (!this.ctx) {
|
||||||
return;
|
return;
|
||||||
@@ -38,11 +38,11 @@ class WebGLInterface {
|
|||||||
this.ctx_version = 1.0;
|
this.ctx_version = 1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get mem() {
|
get mem() {
|
||||||
return this.wasmMemoryInterface
|
return this.wasmMemoryInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
assertWebGL2() {
|
assertWebGL2() {
|
||||||
if (this.ctx_version < 2) {
|
if (this.ctx_version < 2) {
|
||||||
throw new Error("WebGL2 procedure called in a canvas without a WebGL2 context");
|
throw new Error("WebGL2 procedure called in a canvas without a WebGL2 context");
|
||||||
@@ -95,19 +95,19 @@ class WebGLInterface {
|
|||||||
}
|
}
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
getWebGL1Interface() {
|
getWebGL1Interface() {
|
||||||
return {
|
return {
|
||||||
DrawingBufferWidth: () => this.ctx.drawingBufferWidth,
|
DrawingBufferWidth: () => this.ctx.drawingBufferWidth,
|
||||||
DrawingBufferHeight: () => this.ctx.drawingBufferHeight,
|
DrawingBufferHeight: () => this.ctx.drawingBufferHeight,
|
||||||
|
|
||||||
IsExtensionSupported: (name_ptr, name_len) => {
|
IsExtensionSupported: (name_ptr, name_len) => {
|
||||||
let name = this.mem.loadString(name_ptr, name_len);
|
let name = this.mem.loadString(name_ptr, name_len);
|
||||||
let extensions = this.ctx.getSupportedExtensions();
|
let extensions = this.ctx.getSupportedExtensions();
|
||||||
return extensions.indexOf(name) !== -1
|
return extensions.indexOf(name) !== -1
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
GetError: () => {
|
GetError: () => {
|
||||||
let err = this.lastError;
|
let err = this.lastError;
|
||||||
this.recordError(0);
|
this.recordError(0);
|
||||||
@@ -116,7 +116,7 @@ class WebGLInterface {
|
|||||||
}
|
}
|
||||||
return this.ctx.getError();
|
return this.ctx.getError();
|
||||||
},
|
},
|
||||||
|
|
||||||
GetWebGLVersion: (major_ptr, minor_ptr) => {
|
GetWebGLVersion: (major_ptr, minor_ptr) => {
|
||||||
let version = this.ctx.getParameter(0x1F02);
|
let version = this.ctx.getParameter(0x1F02);
|
||||||
if (version.indexOf("WebGL 2.0") !== -1) {
|
if (version.indexOf("WebGL 2.0") !== -1) {
|
||||||
@@ -124,7 +124,7 @@ class WebGLInterface {
|
|||||||
this.mem.storeI32(minor_ptr, 0);
|
this.mem.storeI32(minor_ptr, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mem.storeI32(major_ptr, 1);
|
this.mem.storeI32(major_ptr, 1);
|
||||||
this.mem.storeI32(minor_ptr, 0);
|
this.mem.storeI32(minor_ptr, 0);
|
||||||
},
|
},
|
||||||
@@ -135,12 +135,12 @@ class WebGLInterface {
|
|||||||
this.mem.storeI32(minor_ptr, 0);
|
this.mem.storeI32(minor_ptr, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mem.storeI32(major_ptr, 2);
|
this.mem.storeI32(major_ptr, 2);
|
||||||
this.mem.storeI32(minor_ptr, 0);
|
this.mem.storeI32(minor_ptr, 0);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
ActiveTexture: (x) => {
|
ActiveTexture: (x) => {
|
||||||
this.ctx.activeTexture(x);
|
this.ctx.activeTexture(x);
|
||||||
},
|
},
|
||||||
@@ -180,8 +180,8 @@ class WebGLInterface {
|
|||||||
BlendFuncSeparate: (srcRGB, dstRGB, srcAlpha, dstAlpha) => {
|
BlendFuncSeparate: (srcRGB, dstRGB, srcAlpha, dstAlpha) => {
|
||||||
this.ctx.blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
this.ctx.blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
BufferData: (target, size, data, usage) => {
|
BufferData: (target, size, data, usage) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
this.ctx.bufferData(target, this.mem.loadBytes(data, size), usage);
|
this.ctx.bufferData(target, this.mem.loadBytes(data, size), usage);
|
||||||
@@ -196,8 +196,8 @@ class WebGLInterface {
|
|||||||
this.ctx.bufferSubData(target, offset, null);
|
this.ctx.bufferSubData(target, offset, null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
Clear: (x) => {
|
Clear: (x) => {
|
||||||
this.ctx.clear(x);
|
this.ctx.clear(x);
|
||||||
},
|
},
|
||||||
@@ -216,8 +216,8 @@ class WebGLInterface {
|
|||||||
CompileShader: (shader) => {
|
CompileShader: (shader) => {
|
||||||
this.ctx.compileShader(this.shaders[shader]);
|
this.ctx.compileShader(this.shaders[shader]);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
CompressedTexImage2D: (target, level, internalformat, width, height, border, imageSize, data) => {
|
CompressedTexImage2D: (target, level, internalformat, width, height, border, imageSize, data) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
this.ctx.compressedTexImage2D(target, level, internalformat, width, height, border, this.mem.loadBytes(data, imageSize));
|
this.ctx.compressedTexImage2D(target, level, internalformat, width, height, border, this.mem.loadBytes(data, imageSize));
|
||||||
@@ -232,15 +232,15 @@ class WebGLInterface {
|
|||||||
this.ctx.compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, null);
|
this.ctx.compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
CopyTexImage2D: (target, level, internalformat, x, y, width, height, border) => {
|
CopyTexImage2D: (target, level, internalformat, x, y, width, height, border) => {
|
||||||
this.ctx.copyTexImage2D(target, level, internalformat, x, y, width, height, border);
|
this.ctx.copyTexImage2D(target, level, internalformat, x, y, width, height, border);
|
||||||
},
|
},
|
||||||
CopyTexSubImage2D: (target, level, xoffset, yoffset, x, y, width, height) => {
|
CopyTexSubImage2D: (target, level, xoffset, yoffset, x, y, width, height) => {
|
||||||
this.ctx.copyTexImage2D(target, level, xoffset, yoffset, x, y, width, height);
|
this.ctx.copyTexImage2D(target, level, xoffset, yoffset, x, y, width, height);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
CreateBuffer: () => {
|
CreateBuffer: () => {
|
||||||
let buffer = this.ctx.createBuffer();
|
let buffer = this.ctx.createBuffer();
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
@@ -291,13 +291,13 @@ class WebGLInterface {
|
|||||||
this.textures[id] = texture;
|
this.textures[id] = texture;
|
||||||
return id;
|
return id;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
CullFace: (mode) => {
|
CullFace: (mode) => {
|
||||||
this.ctx.cullFace(mode);
|
this.ctx.cullFace(mode);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
DeleteBuffer: (id) => {
|
DeleteBuffer: (id) => {
|
||||||
let obj = this.buffers[id];
|
let obj = this.buffers[id];
|
||||||
if (obj && id != 0) {
|
if (obj && id != 0) {
|
||||||
@@ -366,8 +366,8 @@ class WebGLInterface {
|
|||||||
DrawElements: (mode, count, type, indices) => {
|
DrawElements: (mode, count, type, indices) => {
|
||||||
this.ctx.drawElements(mode, count, type, indices);
|
this.ctx.drawElements(mode, count, type, indices);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
Enable: (cap) => {
|
Enable: (cap) => {
|
||||||
this.ctx.enable(cap);
|
this.ctx.enable(cap);
|
||||||
},
|
},
|
||||||
@@ -389,20 +389,20 @@ class WebGLInterface {
|
|||||||
FrontFace: (mode) => {
|
FrontFace: (mode) => {
|
||||||
this.ctx.frontFace(mode);
|
this.ctx.frontFace(mode);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
GenerateMipmap: (target) => {
|
GenerateMipmap: (target) => {
|
||||||
this.ctx.generateMipmap(target);
|
this.ctx.generateMipmap(target);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
GetAttribLocation: (program, name_ptr, name_len) => {
|
GetAttribLocation: (program, name_ptr, name_len) => {
|
||||||
let name = this.mem.loadString(name_ptr, name_len);
|
let name = this.mem.loadString(name_ptr, name_len);
|
||||||
return this.ctx.getAttribLocation(this.programs[program], name);
|
return this.ctx.getAttribLocation(this.programs[program], name);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GetProgramParameter: (program, pname) => {
|
GetProgramParameter: (program, pname) => {
|
||||||
return this.ctx.getProgramParameter(this.programs[program], pname)
|
return this.ctx.getProgramParameter(this.programs[program], pname)
|
||||||
},
|
},
|
||||||
@@ -415,7 +415,7 @@ class WebGLInterface {
|
|||||||
let n = Math.min(buf_len, log.length);
|
let n = Math.min(buf_len, log.length);
|
||||||
log = log.substring(0, n);
|
log = log.substring(0, n);
|
||||||
this.mem.loadBytes(buf_ptr, buf_len).set(new TextEncoder("utf-8").encode(log))
|
this.mem.loadBytes(buf_ptr, buf_len).set(new TextEncoder("utf-8").encode(log))
|
||||||
|
|
||||||
this.mem.storeInt(length_ptr, n);
|
this.mem.storeInt(length_ptr, n);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -428,7 +428,7 @@ class WebGLInterface {
|
|||||||
let n = Math.min(buf_len, log.length);
|
let n = Math.min(buf_len, log.length);
|
||||||
log = log.substring(0, n);
|
log = log.substring(0, n);
|
||||||
this.mem.loadBytes(buf_ptr, buf_len).set(new TextEncoder("utf-8").encode(log))
|
this.mem.loadBytes(buf_ptr, buf_len).set(new TextEncoder("utf-8").encode(log))
|
||||||
|
|
||||||
this.mem.storeInt(length_ptr, n);
|
this.mem.storeInt(length_ptr, n);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -452,8 +452,8 @@ class WebGLInterface {
|
|||||||
this.recordError(1281);
|
this.recordError(1281);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
GetUniformLocation: (program, name_ptr, name_len) => {
|
GetUniformLocation: (program, name_ptr, name_len) => {
|
||||||
let name = this.mem.loadString(name_ptr, name_len);
|
let name = this.mem.loadString(name_ptr, name_len);
|
||||||
let arrayOffset = 0;
|
let arrayOffset = 0;
|
||||||
@@ -472,18 +472,18 @@ class WebGLInterface {
|
|||||||
var uniformInfo = ptable.uniforms[name];
|
var uniformInfo = ptable.uniforms[name];
|
||||||
return (uniformInfo && arrayOffset < uniformInfo[0]) ? uniformInfo[1] + arrayOffset : -1
|
return (uniformInfo && arrayOffset < uniformInfo[0]) ? uniformInfo[1] + arrayOffset : -1
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
GetVertexAttribOffset: (index, pname) => {
|
GetVertexAttribOffset: (index, pname) => {
|
||||||
return this.ctx.getVertexAttribOffset(index, pname);
|
return this.ctx.getVertexAttribOffset(index, pname);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
Hint: (target, mode) => {
|
Hint: (target, mode) => {
|
||||||
this.ctx.hint(target, mode);
|
this.ctx.hint(target, mode);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
IsBuffer: (buffer) => this.ctx.isBuffer(this.buffers[buffer]),
|
IsBuffer: (buffer) => this.ctx.isBuffer(this.buffers[buffer]),
|
||||||
IsEnabled: (enabled) => this.ctx.isEnabled(this.enableds[enabled]),
|
IsEnabled: (enabled) => this.ctx.isEnabled(this.enableds[enabled]),
|
||||||
IsFramebuffer: (framebuffer) => this.ctx.isFramebuffer(this.framebuffers[framebuffer]),
|
IsFramebuffer: (framebuffer) => this.ctx.isFramebuffer(this.framebuffers[framebuffer]),
|
||||||
@@ -491,7 +491,7 @@ class WebGLInterface {
|
|||||||
IsRenderbuffer: (renderbuffer) => this.ctx.isRenderbuffer(this.renderbuffers[renderbuffer]),
|
IsRenderbuffer: (renderbuffer) => this.ctx.isRenderbuffer(this.renderbuffers[renderbuffer]),
|
||||||
IsShader: (shader) => this.ctx.isShader(this.shaders[shader]),
|
IsShader: (shader) => this.ctx.isShader(this.shaders[shader]),
|
||||||
IsTexture: (texture) => this.ctx.isTexture(this.textures[texture]),
|
IsTexture: (texture) => this.ctx.isTexture(this.textures[texture]),
|
||||||
|
|
||||||
LineWidth: (width) => {
|
LineWidth: (width) => {
|
||||||
this.ctx.lineWidth(width);
|
this.ctx.lineWidth(width);
|
||||||
},
|
},
|
||||||
@@ -506,8 +506,8 @@ class WebGLInterface {
|
|||||||
PolygonOffset: (factor, units) => {
|
PolygonOffset: (factor, units) => {
|
||||||
this.ctx.polygonOffset(factor, units);
|
this.ctx.polygonOffset(factor, units);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
ReadnPixels: (x, y, width, height, format, type, bufSize, data) => {
|
ReadnPixels: (x, y, width, height, format, type, bufSize, data) => {
|
||||||
this.ctx.readPixels(x, y, width, format, type, this.mem.loadBytes(data, bufSize));
|
this.ctx.readPixels(x, y, width, format, type, this.mem.loadBytes(data, bufSize));
|
||||||
},
|
},
|
||||||
@@ -524,7 +524,7 @@ class WebGLInterface {
|
|||||||
let source = this.getSource(shader, strings_ptr, strings_length);
|
let source = this.getSource(shader, strings_ptr, strings_length);
|
||||||
this.ctx.shaderSource(this.shaders[shader], source);
|
this.ctx.shaderSource(this.shaders[shader], source);
|
||||||
},
|
},
|
||||||
|
|
||||||
StencilFunc: (func, ref, mask) => {
|
StencilFunc: (func, ref, mask) => {
|
||||||
this.ctx.stencilFunc(func, ref, mask);
|
this.ctx.stencilFunc(func, ref, mask);
|
||||||
},
|
},
|
||||||
@@ -543,8 +543,8 @@ class WebGLInterface {
|
|||||||
StencilOpSeparate: (face, fail, zfail, zpass) => {
|
StencilOpSeparate: (face, fail, zfail, zpass) => {
|
||||||
this.ctx.stencilOpSeparate(face, fail, zfail, zpass);
|
this.ctx.stencilOpSeparate(face, fail, zfail, zpass);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
TexImage2D: (target, level, internalformat, width, height, border, format, type, size, data) => {
|
TexImage2D: (target, level, internalformat, width, height, border, format, type, size, data) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
this.ctx.texImage2D(target, level, internalformat, width, height, border, format, type, this.mem.loadBytes(data, size));
|
this.ctx.texImage2D(target, level, internalformat, width, height, border, format, type, this.mem.loadBytes(data, size));
|
||||||
@@ -561,18 +561,18 @@ class WebGLInterface {
|
|||||||
TexSubImage2D: (target, level, xoffset, yoffset, width, height, format, type, size, data) => {
|
TexSubImage2D: (target, level, xoffset, yoffset, width, height, format, type, size, data) => {
|
||||||
this.ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, this.mem.loadBytes(data, size));
|
this.ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, this.mem.loadBytes(data, size));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
Uniform1f: (location, v0) => { this.ctx.uniform1f(this.uniforms[location], v0); },
|
Uniform1f: (location, v0) => { this.ctx.uniform1f(this.uniforms[location], v0); },
|
||||||
Uniform2f: (location, v0, v1) => { this.ctx.uniform2f(this.uniforms[location], v0, v1); },
|
Uniform2f: (location, v0, v1) => { this.ctx.uniform2f(this.uniforms[location], v0, v1); },
|
||||||
Uniform3f: (location, v0, v1, v2) => { this.ctx.uniform3f(this.uniforms[location], v0, v1, v2); },
|
Uniform3f: (location, v0, v1, v2) => { this.ctx.uniform3f(this.uniforms[location], v0, v1, v2); },
|
||||||
Uniform4f: (location, v0, v1, v2, v3) => { this.ctx.uniform4f(this.uniforms[location], v0, v1, v2, v3); },
|
Uniform4f: (location, v0, v1, v2, v3) => { this.ctx.uniform4f(this.uniforms[location], v0, v1, v2, v3); },
|
||||||
|
|
||||||
Uniform1i: (location, v0) => { this.ctx.uniform1i(this.uniforms[location], v0); },
|
Uniform1i: (location, v0) => { this.ctx.uniform1i(this.uniforms[location], v0); },
|
||||||
Uniform2i: (location, v0, v1) => { this.ctx.uniform2i(this.uniforms[location], v0, v1); },
|
Uniform2i: (location, v0, v1) => { this.ctx.uniform2i(this.uniforms[location], v0, v1); },
|
||||||
Uniform3i: (location, v0, v1, v2) => { this.ctx.uniform3i(this.uniforms[location], v0, v1, v2); },
|
Uniform3i: (location, v0, v1, v2) => { this.ctx.uniform3i(this.uniforms[location], v0, v1, v2); },
|
||||||
Uniform4i: (location, v0, v1, v2, v3) => { this.ctx.uniform4i(this.uniforms[location], v0, v1, v2, v3); },
|
Uniform4i: (location, v0, v1, v2, v3) => { this.ctx.uniform4i(this.uniforms[location], v0, v1, v2, v3); },
|
||||||
|
|
||||||
UniformMatrix2fv: (location, addr) => {
|
UniformMatrix2fv: (location, addr) => {
|
||||||
let array = this.mem.loadF32Array(addr, 2*2);
|
let array = this.mem.loadF32Array(addr, 2*2);
|
||||||
this.ctx.uniformMatrix4fv(this.uniforms[location], false, array);
|
this.ctx.uniformMatrix4fv(this.uniforms[location], false, array);
|
||||||
@@ -585,15 +585,15 @@ class WebGLInterface {
|
|||||||
let array = this.mem.loadF32Array(addr, 4*4);
|
let array = this.mem.loadF32Array(addr, 4*4);
|
||||||
this.ctx.uniformMatrix4fv(this.uniforms[location], false, array);
|
this.ctx.uniformMatrix4fv(this.uniforms[location], false, array);
|
||||||
},
|
},
|
||||||
|
|
||||||
UseProgram: (program) => {
|
UseProgram: (program) => {
|
||||||
this.ctx.useProgram(this.programs[program]);
|
if (program) this.ctx.useProgram(this.programs[program]);
|
||||||
},
|
},
|
||||||
ValidateProgram: (program) => {
|
ValidateProgram: (program) => {
|
||||||
this.ctx.validateProgram(this.programs[program]);
|
if (program) this.ctx.validateProgram(this.programs[program]);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
VertexAttrib1f: (index, x) => {
|
VertexAttrib1f: (index, x) => {
|
||||||
this.ctx.vertexAttrib1f(index, x);
|
this.ctx.vertexAttrib1f(index, x);
|
||||||
},
|
},
|
||||||
@@ -609,13 +609,13 @@ class WebGLInterface {
|
|||||||
VertexAttribPointer: (index, size, type, normalized, stride, ptr) => {
|
VertexAttribPointer: (index, size, type, normalized, stride, ptr) => {
|
||||||
this.ctx.vertexAttribPointer(index, size, type, !!normalized, stride, ptr);
|
this.ctx.vertexAttribPointer(index, size, type, !!normalized, stride, ptr);
|
||||||
},
|
},
|
||||||
|
|
||||||
Viewport: (x, y, w, h) => {
|
Viewport: (x, y, w, h) => {
|
||||||
this.ctx.viewport(x, y, w, h);
|
this.ctx.viewport(x, y, w, h);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getWebGL2Interface() {
|
getWebGL2Interface() {
|
||||||
return {
|
return {
|
||||||
/* Buffer objects */
|
/* Buffer objects */
|
||||||
@@ -627,7 +627,7 @@ class WebGLInterface {
|
|||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
this.ctx.getBufferSubData(target, srcByteOffset, this.mem.loadBytes(dst_buffer_ptr, dst_buffer_len), dstOffset, length);
|
this.ctx.getBufferSubData(target, srcByteOffset, this.mem.loadBytes(dst_buffer_ptr, dst_buffer_len), dstOffset, length);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Framebuffer objects */
|
/* Framebuffer objects */
|
||||||
BlitFramebuffer: (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter) => {
|
BlitFramebuffer: (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
@@ -642,7 +642,7 @@ class WebGLInterface {
|
|||||||
let attachments = this.mem.loadU32Array(attachments_ptr, attachments_len);
|
let attachments = this.mem.loadU32Array(attachments_ptr, attachments_len);
|
||||||
this.ctx.invalidateFramebuffer(target, attachments);
|
this.ctx.invalidateFramebuffer(target, attachments);
|
||||||
},
|
},
|
||||||
InvalidateSubFramebuffer: (target, attachments_ptr, attachments_len, x, y, width, height) => {
|
InvalidateSubFramebuffer: (target, attachments_ptr, attachments_len, x, y, width, height) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
let attachments = this.mem.loadU32Array(attachments_ptr, attachments_len);
|
let attachments = this.mem.loadU32Array(attachments_ptr, attachments_len);
|
||||||
this.ctx.invalidateSubFramebuffer(target, attachments, x, y, width, height);
|
this.ctx.invalidateSubFramebuffer(target, attachments, x, y, width, height);
|
||||||
@@ -651,15 +651,15 @@ class WebGLInterface {
|
|||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
this.ctx.readBuffer(src);
|
this.ctx.readBuffer(src);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Renderbuffer objects */
|
/* Renderbuffer objects */
|
||||||
RenderbufferStorageMultisample: (target, samples, internalformat, width, height) => {
|
RenderbufferStorageMultisample: (target, samples, internalformat, width, height) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
this.ctx.renderbufferStorageMultisample(target, samples, internalformat, width, height);
|
this.ctx.renderbufferStorageMultisample(target, samples, internalformat, width, height);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Texture objects */
|
/* Texture objects */
|
||||||
|
|
||||||
TexStorage3D: (target, levels, internalformat, width, height, depth) => {
|
TexStorage3D: (target, levels, internalformat, width, height, depth) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
this.ctx.texStorage3D(target, level, internalformat, width, heigh, depth);
|
this.ctx.texStorage3D(target, level, internalformat, width, heigh, depth);
|
||||||
@@ -692,18 +692,18 @@ class WebGLInterface {
|
|||||||
this.ctx.compressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, null);
|
this.ctx.compressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
CopyTexSubImage3D: (target, level, xoffset, yoffset, zoffset, x, y, width, height) => {
|
CopyTexSubImage3D: (target, level, xoffset, yoffset, zoffset, x, y, width, height) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
this.ctx.copyTexImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
|
this.ctx.copyTexImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Programs and shaders */
|
/* Programs and shaders */
|
||||||
GetFragDataLocation: (program, name_ptr, name_len) => {
|
GetFragDataLocation: (program, name_ptr, name_len) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
return this.ctx.getFragDataLocation(this.programs[program], this.mem.loadString(name_ptr, name_len));
|
return this.ctx.getFragDataLocation(this.programs[program], this.mem.loadString(name_ptr, name_len));
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Uniforms */
|
/* Uniforms */
|
||||||
Uniform1ui: (location, v0) => {
|
Uniform1ui: (location, v0) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
@@ -721,7 +721,7 @@ class WebGLInterface {
|
|||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
this.ctx.uniform4ui(this.uniforms[location], v0, v1, v2, v3);
|
this.ctx.uniform4ui(this.uniforms[location], v0, v1, v2, v3);
|
||||||
},
|
},
|
||||||
|
|
||||||
UniformMatrix3x2fv: (location, addr) => {
|
UniformMatrix3x2fv: (location, addr) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
let array = this.mem.loadF32Array(addr, 3*2);
|
let array = this.mem.loadF32Array(addr, 3*2);
|
||||||
@@ -752,21 +752,21 @@ class WebGLInterface {
|
|||||||
let array = this.mem.loadF32Array(addr, 3*4);
|
let array = this.mem.loadF32Array(addr, 3*4);
|
||||||
this.ctx.uniformMatrix3x4fv(this.uniforms[location], false, array);
|
this.ctx.uniformMatrix3x4fv(this.uniforms[location], false, array);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Vertex attribs */
|
/* Vertex attribs */
|
||||||
VertexAttribI4i: (index, x, y, z, w) => {
|
VertexAttribI4i: (index, x, y, z, w) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
this.ctx.vertexAttribI4i(index, x, y, z, w);
|
this.ctx.vertexAttribI4i(index, x, y, z, w);
|
||||||
},
|
},
|
||||||
VertexAttribI4ui: (index, x, y, z, w) => {
|
VertexAttribI4ui: (index, x, y, z, w) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
this.ctx.vertexAttribI4ui(index, x, y, z, w);
|
this.ctx.vertexAttribI4ui(index, x, y, z, w);
|
||||||
},
|
},
|
||||||
VertexAttribIPointer: (index, size, type, stride, offset) => {
|
VertexAttribIPointer: (index, size, type, stride, offset) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
this.ctx.vertexAttribIPointer(index, size, type, stride, offset);
|
this.ctx.vertexAttribIPointer(index, size, type, stride, offset);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Writing to the drawing buffer */
|
/* Writing to the drawing buffer */
|
||||||
VertexAttribDivisor: (index, divisor) => {
|
VertexAttribDivisor: (index, divisor) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
@@ -818,7 +818,7 @@ class WebGLInterface {
|
|||||||
let id = this.getNewId(this.queries);
|
let id = this.getNewId(this.queries);
|
||||||
query.name = id;
|
query.name = id;
|
||||||
this.queries[id] = query;
|
this.queries[id] = query;
|
||||||
return id;
|
return id;
|
||||||
},
|
},
|
||||||
DeleteQuery: (id) => {
|
DeleteQuery: (id) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
@@ -829,7 +829,7 @@ class WebGLInterface {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
IsQuery: (query) => {
|
IsQuery: (query) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
return this.ctx.isQuery(this.queries[query]);
|
return this.ctx.isQuery(this.queries[query]);
|
||||||
},
|
},
|
||||||
BeginQuery: (target, query) => {
|
BeginQuery: (target, query) => {
|
||||||
@@ -852,9 +852,9 @@ class WebGLInterface {
|
|||||||
let id = this.getNewId(this.queries);
|
let id = this.getNewId(this.queries);
|
||||||
query.name = id;
|
query.name = id;
|
||||||
this.queries[id] = query;
|
this.queries[id] = query;
|
||||||
return id;
|
return id;
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Sampler Objects */
|
/* Sampler Objects */
|
||||||
CreateSampler: () => {
|
CreateSampler: () => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
@@ -862,7 +862,7 @@ class WebGLInterface {
|
|||||||
let id = this.getNewId(this.samplers);
|
let id = this.getNewId(this.samplers);
|
||||||
sampler.name = id;
|
sampler.name = id;
|
||||||
this.samplers[id] = sampler;
|
this.samplers[id] = sampler;
|
||||||
return id;
|
return id;
|
||||||
},
|
},
|
||||||
DeleteSampler: (id) => {
|
DeleteSampler: (id) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
@@ -873,11 +873,11 @@ class WebGLInterface {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
IsSampler: (sampler) => {
|
IsSampler: (sampler) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
return this.ctx.isSampler(this.samplers[sampler]);
|
return this.ctx.isSampler(this.samplers[sampler]);
|
||||||
},
|
},
|
||||||
BindSampler: (unit, sampler) => {
|
BindSampler: (unit, sampler) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
this.ctx.bindSampler(unit, this.samplers[Sampler]);
|
this.ctx.bindSampler(unit, this.samplers[Sampler]);
|
||||||
},
|
},
|
||||||
SamplerParameteri: (sampler, pname, param) => {
|
SamplerParameteri: (sampler, pname, param) => {
|
||||||
@@ -888,7 +888,7 @@ class WebGLInterface {
|
|||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
this.ctx.samplerParameterf(this.samplers[sampler], pname, param);
|
this.ctx.samplerParameterf(this.samplers[sampler], pname, param);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Sync objects */
|
/* Sync objects */
|
||||||
FenceSync: (condition, flags) => {
|
FenceSync: (condition, flags) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
@@ -896,10 +896,10 @@ class WebGLInterface {
|
|||||||
let id = this.getNewId(this.syncs);
|
let id = this.getNewId(this.syncs);
|
||||||
sync.name = id;
|
sync.name = id;
|
||||||
this.syncs[id] = sync;
|
this.syncs[id] = sync;
|
||||||
return id;
|
return id;
|
||||||
},
|
},
|
||||||
IsSync: (sync) => {
|
IsSync: (sync) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
return this.ctx.isSync(this.syncs[sync]);
|
return this.ctx.isSync(this.syncs[sync]);
|
||||||
},
|
},
|
||||||
DeleteSync: (id) => {
|
DeleteSync: (id) => {
|
||||||
@@ -908,7 +908,7 @@ class WebGLInterface {
|
|||||||
if (obj && id != 0) {
|
if (obj && id != 0) {
|
||||||
this.ctx.deleteSampler(obj);
|
this.ctx.deleteSampler(obj);
|
||||||
this.syncs[id] = null;
|
this.syncs[id] = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ClientWaitSync: (sync, flags, timeout) => {
|
ClientWaitSync: (sync, flags, timeout) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
@@ -918,8 +918,8 @@ class WebGLInterface {
|
|||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
this.ctx.waitSync(this.syncs[sync], flags, timeout) ;
|
this.ctx.waitSync(this.syncs[sync], flags, timeout) ;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/* Transform Feedback */
|
/* Transform Feedback */
|
||||||
CreateTransformFeedback: () => {
|
CreateTransformFeedback: () => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
@@ -927,7 +927,7 @@ class WebGLInterface {
|
|||||||
let id = this.getNewId(this.transformFeedbacks);
|
let id = this.getNewId(this.transformFeedbacks);
|
||||||
transformFeedback.name = id;
|
transformFeedback.name = id;
|
||||||
this.transformFeedbacks[id] = transformFeedback;
|
this.transformFeedbacks[id] = transformFeedback;
|
||||||
return id;
|
return id;
|
||||||
},
|
},
|
||||||
DeleteTransformFeedback: (id) => {
|
DeleteTransformFeedback: (id) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
@@ -935,7 +935,7 @@ class WebGLInterface {
|
|||||||
if (obj && id != 0) {
|
if (obj && id != 0) {
|
||||||
this.ctx.deleteTransformFeedback(obj);
|
this.ctx.deleteTransformFeedback(obj);
|
||||||
this.transformFeedbacks[id] = null;
|
this.transformFeedbacks[id] = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
IsTransformFeedback: (tf) => {
|
IsTransformFeedback: (tf) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
@@ -971,8 +971,8 @@ class WebGLInterface {
|
|||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
this.ctx.resumeTransformFeedback();
|
this.ctx.resumeTransformFeedback();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/* Uniform Buffer Objects and Transform Feedback Buffers */
|
/* Uniform Buffer Objects and Transform Feedback Buffers */
|
||||||
BindBufferBase: (target, index, buffer) => {
|
BindBufferBase: (target, index, buffer) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
@@ -990,7 +990,7 @@ class WebGLInterface {
|
|||||||
GetActiveUniformBlockName: (program, uniformBlockIndex, buf_ptr, buf_len, length_ptr) => {
|
GetActiveUniformBlockName: (program, uniformBlockIndex, buf_ptr, buf_len, length_ptr) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
let name = this.ctx.getActiveUniformBlockName(this.programs[program], uniformBlockIndex);
|
let name = this.ctx.getActiveUniformBlockName(this.programs[program], uniformBlockIndex);
|
||||||
|
|
||||||
let n = Math.min(buf_len, name.length);
|
let n = Math.min(buf_len, name.length);
|
||||||
name = name.substring(0, n);
|
name = name.substring(0, n);
|
||||||
this.mem.loadBytes(buf_ptr, buf_len).set(new TextEncoder("utf-8").encode(name))
|
this.mem.loadBytes(buf_ptr, buf_len).set(new TextEncoder("utf-8").encode(name))
|
||||||
@@ -1000,7 +1000,7 @@ class WebGLInterface {
|
|||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
this.ctx.uniformBlockBinding(this.programs[program], uniformBlockIndex, uniformBlockBinding);
|
this.ctx.uniformBlockBinding(this.programs[program], uniformBlockIndex, uniformBlockBinding);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Vertex Array Objects */
|
/* Vertex Array Objects */
|
||||||
CreateVertexArray: () => {
|
CreateVertexArray: () => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
@@ -1008,7 +1008,7 @@ class WebGLInterface {
|
|||||||
let id = this.getNewId(this.vaos);
|
let id = this.getNewId(this.vaos);
|
||||||
vao.name = id;
|
vao.name = id;
|
||||||
this.vaos[id] = vao;
|
this.vaos[id] = vao;
|
||||||
return id;
|
return id;
|
||||||
},
|
},
|
||||||
DeleteVertexArray: (id) => {
|
DeleteVertexArray: (id) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
@@ -1019,11 +1019,11 @@ class WebGLInterface {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
IsVertexArray: (vertexArray) => {
|
IsVertexArray: (vertexArray) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
return this.ctx.isVertexArray(this.vaos[vertexArray]);
|
return this.ctx.isVertexArray(this.vaos[vertexArray]);
|
||||||
},
|
},
|
||||||
BindVertexArray: (vertexArray) => {
|
BindVertexArray: (vertexArray) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
this.ctx.bindVertexArray(this.vaos[vertexArray]);
|
this.ctx.bindVertexArray(this.vaos[vertexArray]);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -1031,4 +1031,4 @@ class WebGLInterface {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export {WebGLInterface};
|
export {WebGLInterface};
|
||||||
Vendored
+22
@@ -0,0 +1,22 @@
|
|||||||
|
//+build js wasm32
|
||||||
|
package wasm_js_interface
|
||||||
|
|
||||||
|
foreign import dom_lib "odin_dom"
|
||||||
|
|
||||||
|
@(default_calling_convention="contextless")
|
||||||
|
foreign dom_lib {
|
||||||
|
get_element_value_f64 :: proc(id: string) -> f64 ---
|
||||||
|
get_element_min_max :: proc(id: string) -> (min, max: f64) ---
|
||||||
|
set_element_value :: proc(id: string, value: f64) ---
|
||||||
|
}
|
||||||
|
|
||||||
|
get_element_value_string :: proc(id: string, buf: []byte) -> string {
|
||||||
|
@(default_calling_convention="contextless")
|
||||||
|
foreign dom_lib {
|
||||||
|
@(link_name="get_element_value_string")
|
||||||
|
_get_element_value_string :: proc(id: string, buf: []byte) -> int ---
|
||||||
|
}
|
||||||
|
n := _get_element_value_string(id, buf)
|
||||||
|
return string(buf[:n])
|
||||||
|
|
||||||
|
}
|
||||||
Vendored
+320
@@ -0,0 +1,320 @@
|
|||||||
|
//+build js wasm32
|
||||||
|
package wasm_js_interface
|
||||||
|
|
||||||
|
foreign import dom_lib "odin_dom"
|
||||||
|
|
||||||
|
Event_Kind :: enum u32 {
|
||||||
|
Invalid,
|
||||||
|
|
||||||
|
Load,
|
||||||
|
Unload,
|
||||||
|
Error,
|
||||||
|
Resize,
|
||||||
|
Visibility_Change,
|
||||||
|
Fullscreen_Change,
|
||||||
|
Fullscreen_Error,
|
||||||
|
|
||||||
|
Click,
|
||||||
|
Double_Click,
|
||||||
|
Mouse_Move,
|
||||||
|
Mouse_Over,
|
||||||
|
Mouse_Out,
|
||||||
|
Mouse_Up,
|
||||||
|
Mouse_Down,
|
||||||
|
|
||||||
|
Key_Up,
|
||||||
|
Key_Down,
|
||||||
|
Key_Press,
|
||||||
|
|
||||||
|
Scroll,
|
||||||
|
Wheel,
|
||||||
|
|
||||||
|
Focus,
|
||||||
|
Submit,
|
||||||
|
Blur,
|
||||||
|
Change,
|
||||||
|
Select,
|
||||||
|
|
||||||
|
Animation_Start,
|
||||||
|
Animation_End,
|
||||||
|
Animation_Iteration,
|
||||||
|
Animation_Cancel,
|
||||||
|
|
||||||
|
Copy,
|
||||||
|
Cut,
|
||||||
|
Paste,
|
||||||
|
|
||||||
|
// Drag,
|
||||||
|
// Drag_Start,
|
||||||
|
// Drag_End,
|
||||||
|
// Drag_Enter,
|
||||||
|
// Drag_Leave,
|
||||||
|
// Drag_Over,
|
||||||
|
// Drop,
|
||||||
|
|
||||||
|
Pointer_Cancel,
|
||||||
|
Pointer_Down,
|
||||||
|
Pointer_Enter,
|
||||||
|
Pointer_Leave,
|
||||||
|
Pointer_Move,
|
||||||
|
Pointer_Over,
|
||||||
|
Pointer_Up,
|
||||||
|
Got_Pointer_Capture,
|
||||||
|
Lost_Pointer_Capture,
|
||||||
|
Pointer_Lock_Change,
|
||||||
|
Pointer_Lock_Error,
|
||||||
|
|
||||||
|
Selection_Change,
|
||||||
|
Selection_Start,
|
||||||
|
|
||||||
|
Touch_Cancel,
|
||||||
|
Touch_End,
|
||||||
|
Touch_Move,
|
||||||
|
Touch_Start,
|
||||||
|
|
||||||
|
Transition_Start,
|
||||||
|
Transition_End,
|
||||||
|
Transition_Run,
|
||||||
|
Transition_Cancel,
|
||||||
|
|
||||||
|
}
|
||||||
|
event_kind_string := [Event_Kind]string{
|
||||||
|
.Invalid = "",
|
||||||
|
|
||||||
|
.Load = "load",
|
||||||
|
.Unload = "unload",
|
||||||
|
.Error = "error",
|
||||||
|
.Resize = "resize",
|
||||||
|
.Visibility_Change = "visibilitychange",
|
||||||
|
.Fullscreen_Change = "fullscreenchange",
|
||||||
|
.Fullscreen_Error = "fullscreenerror",
|
||||||
|
|
||||||
|
.Click = "click",
|
||||||
|
.Double_Click = "dblclick",
|
||||||
|
.Mouse_Move = "mousemove",
|
||||||
|
.Mouse_Over = "mouseover",
|
||||||
|
.Mouse_Out = "mouseout",
|
||||||
|
.Mouse_Up = "mouseup",
|
||||||
|
.Mouse_Down = "mousedown",
|
||||||
|
|
||||||
|
.Key_Up = "keyup",
|
||||||
|
.Key_Down = "keydown",
|
||||||
|
.Key_Press = "keypress",
|
||||||
|
|
||||||
|
.Scroll = "scroll",
|
||||||
|
.Wheel = "wheel",
|
||||||
|
|
||||||
|
.Focus = "focus",
|
||||||
|
.Submit = "submit",
|
||||||
|
.Blur = "blur",
|
||||||
|
.Change = "change",
|
||||||
|
.Select = "select",
|
||||||
|
|
||||||
|
.Animation_Start = "animationstart",
|
||||||
|
.Animation_End = "animationend",
|
||||||
|
.Animation_Iteration = "animationiteration",
|
||||||
|
.Animation_Cancel = "animationcancel",
|
||||||
|
|
||||||
|
.Copy = "copy",
|
||||||
|
.Cut = "cut",
|
||||||
|
.Paste = "paste",
|
||||||
|
|
||||||
|
// .Drag, = "drag",
|
||||||
|
// .Drag_Start, = "dragstart",
|
||||||
|
// .Drag_End, = "dragend",
|
||||||
|
// .Drag_Enter, = "dragenter",
|
||||||
|
// .Drag_Leave, = "dragleave",
|
||||||
|
// .Drag_Over, = "dragover",
|
||||||
|
// .Drop, = "drop",
|
||||||
|
|
||||||
|
.Pointer_Cancel = "pointercancel",
|
||||||
|
.Pointer_Down = "pointerdown",
|
||||||
|
.Pointer_Enter = "pointerenter",
|
||||||
|
.Pointer_Leave = "pointerleave",
|
||||||
|
.Pointer_Move = "pointermove",
|
||||||
|
.Pointer_Over = "pointerover",
|
||||||
|
.Pointer_Up = "pointerup",
|
||||||
|
.Got_Pointer_Capture = "gotpointercapture",
|
||||||
|
.Lost_Pointer_Capture = "lostpointercapture",
|
||||||
|
.Pointer_Lock_Change = "pointerlockchange",
|
||||||
|
.Pointer_Lock_Error = "pointerlockerror",
|
||||||
|
|
||||||
|
.Selection_Change = "selectionchange",
|
||||||
|
.Selection_Start = "selectionstart",
|
||||||
|
|
||||||
|
.Transition_Start = "transitionstart",
|
||||||
|
.Transition_End = "transitionend",
|
||||||
|
.Transition_Run = "transitionrun",
|
||||||
|
.Transition_Cancel = "transitioncancel",
|
||||||
|
|
||||||
|
.Touch_Cancel = "touchcancel",
|
||||||
|
.Touch_End = "touchend",
|
||||||
|
.Touch_Move = "touchmove",
|
||||||
|
.Touch_Start = "touchstart",
|
||||||
|
}
|
||||||
|
|
||||||
|
Delta_Mode :: enum u32 {
|
||||||
|
Pixel = 0,
|
||||||
|
Line = 1,
|
||||||
|
Page = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
Key_Location :: enum u8 {
|
||||||
|
Standard = 0,
|
||||||
|
Left = 1,
|
||||||
|
Right = 2,
|
||||||
|
Numpad = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
KEYBOARD_MAX_KEY_SIZE :: 16
|
||||||
|
KEYBOARD_MAX_CODE_SIZE :: 16
|
||||||
|
|
||||||
|
Event_Target_Kind :: enum u32 {
|
||||||
|
Element = 0,
|
||||||
|
Document = 1,
|
||||||
|
Window = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
Event_Phase :: enum u8 {
|
||||||
|
None = 0,
|
||||||
|
Capturing_Phase = 1,
|
||||||
|
At_Target = 2,
|
||||||
|
Bubbling_Phase = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Event :: struct {
|
||||||
|
kind: Event_Kind,
|
||||||
|
target_kind: Event_Target_Kind,
|
||||||
|
current_target_kind: Event_Target_Kind,
|
||||||
|
id: string,
|
||||||
|
timestamp: f64,
|
||||||
|
|
||||||
|
phase: Event_Phase,
|
||||||
|
bubbles: bool,
|
||||||
|
cancelable: bool,
|
||||||
|
composed: bool,
|
||||||
|
is_composing: bool,
|
||||||
|
is_trusted: bool,
|
||||||
|
|
||||||
|
using data: struct #raw_union #align 8 {
|
||||||
|
scroll: struct {
|
||||||
|
delta: [2]f64,
|
||||||
|
},
|
||||||
|
visibility_change: struct {
|
||||||
|
is_visible: bool,
|
||||||
|
},
|
||||||
|
wheel: struct {
|
||||||
|
delta: [3]f64,
|
||||||
|
delta_mode: Delta_Mode,
|
||||||
|
},
|
||||||
|
|
||||||
|
key: struct {
|
||||||
|
key: string,
|
||||||
|
code: string,
|
||||||
|
location: Key_Location,
|
||||||
|
|
||||||
|
ctrl: bool,
|
||||||
|
shift: bool,
|
||||||
|
alt: bool,
|
||||||
|
meta: bool,
|
||||||
|
|
||||||
|
repeat: bool,
|
||||||
|
|
||||||
|
_key_buf: [KEYBOARD_MAX_KEY_SIZE]byte,
|
||||||
|
_code_buf: [KEYBOARD_MAX_KEY_SIZE]byte,
|
||||||
|
},
|
||||||
|
|
||||||
|
mouse: struct {
|
||||||
|
screen: [2]i64,
|
||||||
|
client: [2]i64,
|
||||||
|
offset: [2]i64,
|
||||||
|
page: [2]i64,
|
||||||
|
movement: [2]i64,
|
||||||
|
using pos: [2]i64,
|
||||||
|
|
||||||
|
ctrl: bool,
|
||||||
|
shift: bool,
|
||||||
|
alt: bool,
|
||||||
|
meta: bool,
|
||||||
|
|
||||||
|
button: i16,
|
||||||
|
buttons: bit_set[0..<16; u16],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
user_data: rawptr,
|
||||||
|
callback: proc(e: Event),
|
||||||
|
}
|
||||||
|
|
||||||
|
@(default_calling_convention="contextless")
|
||||||
|
foreign dom_lib {
|
||||||
|
event_stop_propagation :: proc() ---
|
||||||
|
event_stop_immediate_propagation :: proc() ---
|
||||||
|
event_prevent_default :: proc() ---
|
||||||
|
}
|
||||||
|
|
||||||
|
add_event_listener :: proc(id: string, kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
|
||||||
|
@(default_calling_convention="contextless")
|
||||||
|
foreign dom_lib {
|
||||||
|
@(link_name="add_event_listener")
|
||||||
|
_add_event_listener :: proc(id: string, name: string, name_code: Event_Kind, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool ---
|
||||||
|
}
|
||||||
|
// TODO: Pointer_Lock_Change etc related stuff for all different browsers
|
||||||
|
return _add_event_listener(id, event_kind_string[kind], kind, user_data, callback, use_capture)
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_event_listener :: proc(id: string, kind: Event_Kind, user_data: rawptr, callback: proc(e: Event)) -> bool {
|
||||||
|
@(default_calling_convention="contextless")
|
||||||
|
foreign dom_lib {
|
||||||
|
@(link_name="remove_event_listener")
|
||||||
|
_remove_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc "odin" (Event)) -> bool ---
|
||||||
|
}
|
||||||
|
return _remove_event_listener(id, event_kind_string[kind], user_data, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
add_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
|
||||||
|
@(default_calling_convention="contextless")
|
||||||
|
foreign dom_lib {
|
||||||
|
@(link_name="add_window_event_listener")
|
||||||
|
_add_window_event_listener :: proc(name: string, name_code: Event_Kind, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool ---
|
||||||
|
}
|
||||||
|
return _add_window_event_listener(event_kind_string[kind], kind, user_data, callback, use_capture)
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event)) -> bool {
|
||||||
|
@(default_calling_convention="contextless")
|
||||||
|
foreign dom_lib {
|
||||||
|
@(link_name="remove_window_event_listener")
|
||||||
|
_remove_window_event_listener :: proc(name: string, user_data: rawptr, callback: proc "odin" (Event)) -> bool ---
|
||||||
|
}
|
||||||
|
return _remove_window_event_listener(event_kind_string[kind], user_data, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_event_listener_from_event :: proc(e: Event) -> bool {
|
||||||
|
if e.id == "" {
|
||||||
|
return remove_window_event_listener(e.kind, e.user_data, e.callback)
|
||||||
|
}
|
||||||
|
return remove_event_listener(e.id, e.kind, e.user_data, e.callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@(export, link_name="odin_dom_do_event_callback")
|
||||||
|
do_event_callback :: proc(user_data: rawptr, callback: proc(e: Event)) {
|
||||||
|
@(default_calling_convention="contextless")
|
||||||
|
foreign dom_lib {
|
||||||
|
init_event_raw :: proc(e: ^Event) ---
|
||||||
|
}
|
||||||
|
|
||||||
|
if callback != nil {
|
||||||
|
event := Event{
|
||||||
|
user_data = user_data,
|
||||||
|
callback = callback,
|
||||||
|
}
|
||||||
|
init_event_raw(&event)
|
||||||
|
callback(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
-154
@@ -1,154 +0,0 @@
|
|||||||
class WasmMemoryInterface {
|
|
||||||
constructor() {
|
|
||||||
this.memory = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
setMemory(memory) {
|
|
||||||
this.memory = memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
get mem() {
|
|
||||||
return new DataView(this.memory.buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
loadF32Array(addr, len) {
|
|
||||||
let array = new Float32Array(this.memory.buffer, addr, len);
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
loadU32Array(addr, len) {
|
|
||||||
let array = new Uint32Array(this.memory.buffer, addr, len);
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
loadI32Array(addr, len) {
|
|
||||||
let array = new Int32Array(this.memory.buffer, addr, len);
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
loadU8(addr) { return this.mem.getUint8 (addr, true); }
|
|
||||||
loadI8(addr) { return this.mem.getInt8 (addr, true); }
|
|
||||||
loadU16(addr) { return this.mem.getUint16 (addr, true); }
|
|
||||||
loadI16(addr) { return this.mem.getInt16 (addr, true); }
|
|
||||||
loadU32(addr) { return this.mem.getUint32 (addr, true); }
|
|
||||||
loadI32(addr) { return this.mem.getInt32 (addr, true); }
|
|
||||||
loadU64(addr) {
|
|
||||||
const lo = this.mem.getUint32(addr + 0, true);
|
|
||||||
const hi = this.mem.getUint32(addr + 4, true);
|
|
||||||
return lo + hi*4294967296;
|
|
||||||
};
|
|
||||||
loadI64(addr) {
|
|
||||||
// TODO(bill): loadI64 correctly
|
|
||||||
const lo = this.mem.getUint32(addr + 0, true);
|
|
||||||
const hi = this.mem.getUint32(addr + 4, true);
|
|
||||||
return lo + hi*4294967296;
|
|
||||||
};
|
|
||||||
loadF32(addr) { return this.mem.getFloat32(addr, true); }
|
|
||||||
loadF64(addr) { return this.mem.getFloat64(addr, true); }
|
|
||||||
loadInt(addr) { return this.mem.getInt32 (addr, true); }
|
|
||||||
loadUint(addr) { return this.mem.getUint32 (addr, true); }
|
|
||||||
|
|
||||||
loadPtr(addr) { return this.loadUint(addr); }
|
|
||||||
|
|
||||||
loadBytes(ptr, len) {
|
|
||||||
return new Uint8Array(this.memory.buffer, ptr, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
loadString(ptr, len) {
|
|
||||||
const bytes = this.loadBytes(ptr, len);
|
|
||||||
return new TextDecoder("utf-8").decode(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
storeU8(addr, value) { this.mem.setUint8 (addr, value, true); }
|
|
||||||
storeI8(addr, value) { this.mem.setInt8 (addr, value, true); }
|
|
||||||
storeU16(addr, value) { this.mem.setUint16 (addr, value, true); }
|
|
||||||
storeI16(addr, value) { this.mem.setInt16 (addr, value, true); }
|
|
||||||
storeU32(addr, value) { this.mem.setUint32 (addr, value, true); }
|
|
||||||
storeI32(addr, value) { this.mem.setInt32 (addr, value, true); }
|
|
||||||
storeU64(addr, value) {
|
|
||||||
this.mem.setUint32(addr + 0, value, true);
|
|
||||||
this.mem.setUint32(addr + 4, Math.floor(value / 4294967296), true);
|
|
||||||
}
|
|
||||||
storeI64(addr, value) {
|
|
||||||
// TODO(bill): storeI64 correctly
|
|
||||||
this.mem.setUint32(addr + 0, value, true);
|
|
||||||
this.mem.setUint32(addr + 4, Math.floor(value / 4294967296), true);
|
|
||||||
}
|
|
||||||
storeF32(addr, value) { this.mem.setFloat32(addr, value, true); }
|
|
||||||
storeF64(addr, value) { this.mem.setFloat64(addr, value, true); }
|
|
||||||
storeInt(addr, value) { this.mem.setInt32 (addr, value, true); }
|
|
||||||
storeUint(addr, value) { this.mem.setUint32 (addr, value, true); }
|
|
||||||
};
|
|
||||||
|
|
||||||
function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
|
|
||||||
const MAX_INFO_CONSOLE_LINES = 512;
|
|
||||||
let infoConsoleLines = new Array();
|
|
||||||
const addConsoleLine = (line) => {
|
|
||||||
if (line === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (line.endsWith("\n")) {
|
|
||||||
line = line.substring(0, line.length-1);
|
|
||||||
} else if (infoConsoleLines.length > 0) {
|
|
||||||
let prev_line = infoConsoleLines.pop();
|
|
||||||
line = prev_line.concat(line);
|
|
||||||
}
|
|
||||||
infoConsoleLines.push(line);
|
|
||||||
|
|
||||||
if (infoConsoleLines.length > MAX_INFO_CONSOLE_LINES) {
|
|
||||||
infoConsoleLines.shift();
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = "";
|
|
||||||
for (let i = 0; i < infoConsoleLines.length; i++) {
|
|
||||||
if (i != 0) {
|
|
||||||
data = data.concat("\n");
|
|
||||||
}
|
|
||||||
data = data.concat(infoConsoleLines[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (consoleElement !== undefined) {
|
|
||||||
let info = consoleElement;
|
|
||||||
info.innerHTML = data;
|
|
||||||
info.scrollTop = info.scrollHeight;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
"env": {},
|
|
||||||
"odin_env": {
|
|
||||||
write: (fd, ptr, len) => {
|
|
||||||
const str = wasmMemoryInterface.loadString(ptr, len);
|
|
||||||
if (fd == 1) {
|
|
||||||
addConsoleLine(str);
|
|
||||||
return;
|
|
||||||
} else if (fd == 2) {
|
|
||||||
addConsoleLine(str);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
throw new Error("Invalid fd to 'write'" + stripNewline(str));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
trap: () => { throw new Error() },
|
|
||||||
alert: (ptr, len) => { alert(wasmMemoryInterface.loadString(ptr, len)) },
|
|
||||||
abort: () => { Module.abort() },
|
|
||||||
evaluate: (str_ptr, str_len) => { eval.call(null, wasmMemoryInterface.loadString(str_ptr, str_len)); },
|
|
||||||
|
|
||||||
time_now: () => {
|
|
||||||
return performance.now() * 1e6;
|
|
||||||
},
|
|
||||||
|
|
||||||
sqrt: (x) => Math.sqrt(x),
|
|
||||||
sin: (x) => Math.sin(x),
|
|
||||||
cos: (x) => Math.cos(x),
|
|
||||||
pow: (x) => Math.pow(x),
|
|
||||||
fmuladd: (x, y, z) => x*y + z,
|
|
||||||
ln: (x) => Math.log(x),
|
|
||||||
exp: (x) => Math.exp(x),
|
|
||||||
ldexp: (x) => Math.ldexp(x),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export {WasmMemoryInterface, odinSetupDefaultImports};
|
|
||||||
Vendored
+372
@@ -0,0 +1,372 @@
|
|||||||
|
class WasmMemoryInterface {
|
||||||
|
constructor() {
|
||||||
|
this.memory = null;
|
||||||
|
this.exports = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
setMemory(memory) {
|
||||||
|
this.memory = memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
setExports(exports) {
|
||||||
|
this.exports = exports;
|
||||||
|
this.listenerMap = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
get mem() {
|
||||||
|
return new DataView(this.memory.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
loadF32Array(addr, len) {
|
||||||
|
let array = new Float32Array(this.memory.buffer, addr, len);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
loadF64Array(addr, len) {
|
||||||
|
let array = new Float64Array(this.memory.buffer, addr, len);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
loadU32Array(addr, len) {
|
||||||
|
let array = new Uint32Array(this.memory.buffer, addr, len);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
loadI32Array(addr, len) {
|
||||||
|
let array = new Int32Array(this.memory.buffer, addr, len);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
loadU8(addr) { return this.mem.getUint8 (addr, true); }
|
||||||
|
loadI8(addr) { return this.mem.getInt8 (addr, true); }
|
||||||
|
loadU16(addr) { return this.mem.getUint16 (addr, true); }
|
||||||
|
loadI16(addr) { return this.mem.getInt16 (addr, true); }
|
||||||
|
loadU32(addr) { return this.mem.getUint32 (addr, true); }
|
||||||
|
loadI32(addr) { return this.mem.getInt32 (addr, true); }
|
||||||
|
loadU64(addr) {
|
||||||
|
const lo = this.mem.getUint32(addr + 0, true);
|
||||||
|
const hi = this.mem.getUint32(addr + 4, true);
|
||||||
|
return lo + hi*4294967296;
|
||||||
|
};
|
||||||
|
loadI64(addr) {
|
||||||
|
// TODO(bill): loadI64 correctly
|
||||||
|
const lo = this.mem.getUint32(addr + 0, true);
|
||||||
|
const hi = this.mem.getUint32(addr + 4, true);
|
||||||
|
return lo + hi*4294967296;
|
||||||
|
};
|
||||||
|
loadF32(addr) { return this.mem.getFloat32(addr, true); }
|
||||||
|
loadF64(addr) { return this.mem.getFloat64(addr, true); }
|
||||||
|
loadInt(addr) { return this.mem.getInt32 (addr, true); }
|
||||||
|
loadUint(addr) { return this.mem.getUint32 (addr, true); }
|
||||||
|
|
||||||
|
loadPtr(addr) { return this.loadUint(addr); }
|
||||||
|
|
||||||
|
loadBytes(ptr, len) {
|
||||||
|
return new Uint8Array(this.memory.buffer, ptr, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadString(ptr, len) {
|
||||||
|
const bytes = this.loadBytes(ptr, len);
|
||||||
|
return new TextDecoder("utf-8").decode(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
storeU8(addr, value) { this.mem.setUint8 (addr, value, true); }
|
||||||
|
storeI8(addr, value) { this.mem.setInt8 (addr, value, true); }
|
||||||
|
storeU16(addr, value) { this.mem.setUint16 (addr, value, true); }
|
||||||
|
storeI16(addr, value) { this.mem.setInt16 (addr, value, true); }
|
||||||
|
storeU32(addr, value) { this.mem.setUint32 (addr, value, true); }
|
||||||
|
storeI32(addr, value) { this.mem.setInt32 (addr, value, true); }
|
||||||
|
storeU64(addr, value) {
|
||||||
|
this.mem.setUint32(addr + 0, value, true);
|
||||||
|
this.mem.setUint32(addr + 4, Math.floor(value / 4294967296), true);
|
||||||
|
}
|
||||||
|
storeI64(addr, value) {
|
||||||
|
// TODO(bill): storeI64 correctly
|
||||||
|
this.mem.setUint32(addr + 0, value, true);
|
||||||
|
this.mem.setUint32(addr + 4, Math.floor(value / 4294967296), true);
|
||||||
|
}
|
||||||
|
storeF32(addr, value) { this.mem.setFloat32(addr, value, true); }
|
||||||
|
storeF64(addr, value) { this.mem.setFloat64(addr, value, true); }
|
||||||
|
storeInt(addr, value) { this.mem.setInt32 (addr, value, true); }
|
||||||
|
storeUint(addr, value) { this.mem.setUint32 (addr, value, true); }
|
||||||
|
};
|
||||||
|
|
||||||
|
function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
|
||||||
|
const MAX_INFO_CONSOLE_LINES = 512;
|
||||||
|
let infoConsoleLines = new Array();
|
||||||
|
const addConsoleLine = (line) => {
|
||||||
|
if (line === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (line.endsWith("\n")) {
|
||||||
|
line = line.substring(0, line.length-1);
|
||||||
|
} else if (infoConsoleLines.length > 0) {
|
||||||
|
let prev_line = infoConsoleLines.pop();
|
||||||
|
line = prev_line.concat(line);
|
||||||
|
}
|
||||||
|
infoConsoleLines.push(line);
|
||||||
|
|
||||||
|
if (infoConsoleLines.length > MAX_INFO_CONSOLE_LINES) {
|
||||||
|
infoConsoleLines.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = "";
|
||||||
|
for (let i = 0; i < infoConsoleLines.length; i++) {
|
||||||
|
if (i != 0) {
|
||||||
|
data = data.concat("\n");
|
||||||
|
}
|
||||||
|
data = data.concat(infoConsoleLines[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (consoleElement !== undefined) {
|
||||||
|
let info = consoleElement;
|
||||||
|
info.innerHTML = data;
|
||||||
|
info.scrollTop = info.scrollHeight;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let event_temp_data = {};
|
||||||
|
|
||||||
|
return {
|
||||||
|
"env": {},
|
||||||
|
"odin_env": {
|
||||||
|
write: (fd, ptr, len) => {
|
||||||
|
const str = wasmMemoryInterface.loadString(ptr, len);
|
||||||
|
if (fd == 1) {
|
||||||
|
addConsoleLine(str);
|
||||||
|
return;
|
||||||
|
} else if (fd == 2) {
|
||||||
|
addConsoleLine(str);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
throw new Error("Invalid fd to 'write'" + stripNewline(str));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trap: () => { throw new Error() },
|
||||||
|
alert: (ptr, len) => { alert(wasmMemoryInterface.loadString(ptr, len)) },
|
||||||
|
abort: () => { Module.abort() },
|
||||||
|
evaluate: (str_ptr, str_len) => { eval.call(null, wasmMemoryInterface.loadString(str_ptr, str_len)); },
|
||||||
|
|
||||||
|
time_now: () => {
|
||||||
|
return performance.now() * 1e6;
|
||||||
|
},
|
||||||
|
|
||||||
|
sqrt: (x) => Math.sqrt(x),
|
||||||
|
sin: (x) => Math.sin(x),
|
||||||
|
cos: (x) => Math.cos(x),
|
||||||
|
pow: (x) => Math.pow(x),
|
||||||
|
fmuladd: (x, y, z) => x*y + z,
|
||||||
|
ln: (x) => Math.log(x),
|
||||||
|
exp: (x) => Math.exp(x),
|
||||||
|
ldexp: (x) => Math.ldexp(x),
|
||||||
|
},
|
||||||
|
"odin_dom": {
|
||||||
|
init_event_raw: (ep) => {
|
||||||
|
const W = 4;
|
||||||
|
let offset = ep;
|
||||||
|
let off = (amount, alignment) => {
|
||||||
|
if (alignment === undefined) {
|
||||||
|
alignment = amount;
|
||||||
|
}
|
||||||
|
if (offset % alignment != 0) {
|
||||||
|
offset += alignment - (offset%alignment);
|
||||||
|
}
|
||||||
|
let x = offset;
|
||||||
|
offset += amount;
|
||||||
|
return x;
|
||||||
|
};
|
||||||
|
|
||||||
|
let wmi = wasmMemoryInterface;
|
||||||
|
|
||||||
|
let e = event_temp_data.event;
|
||||||
|
|
||||||
|
wmi.storeU32(off(4), event_temp_data.name_code);
|
||||||
|
if (e.target == document) {
|
||||||
|
wmi.storeU32(off(4), 1);
|
||||||
|
} else if (e.target == window) {
|
||||||
|
wmi.storeU32(off(4), 2);
|
||||||
|
} else {
|
||||||
|
wmi.storeU32(off(4), 0);
|
||||||
|
}
|
||||||
|
if (e.currentTarget == document) {
|
||||||
|
wmi.storeU32(off(4), 1);
|
||||||
|
} else if (e.currentTarget == window) {
|
||||||
|
wmi.storeU32(off(4), 2);
|
||||||
|
} else {
|
||||||
|
wmi.storeU32(off(4), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
wmi.storeUint(off(W), event_temp_data.id_ptr);
|
||||||
|
wmi.storeUint(off(W), event_temp_data.id_len);
|
||||||
|
|
||||||
|
wmi.storeF64(off(8), e.timeStamp*1e-3);
|
||||||
|
|
||||||
|
wmi.storeU8(off(1), e.eventPhase);
|
||||||
|
wmi.storeU8(off(1), !!e.bubbles);
|
||||||
|
wmi.storeU8(off(1), !!e.cancelable);
|
||||||
|
wmi.storeU8(off(1), !!e.composed);
|
||||||
|
wmi.storeU8(off(1), !!e.isComposing);
|
||||||
|
wmi.storeU8(off(1), !!e.isTrusted);
|
||||||
|
|
||||||
|
off(0, 8);
|
||||||
|
if (e instanceof MouseEvent) {
|
||||||
|
wmi.storeI64(off(8), e.screenX);
|
||||||
|
wmi.storeI64(off(8), e.screenY);
|
||||||
|
wmi.storeI64(off(8), e.clientX);
|
||||||
|
wmi.storeI64(off(8), e.clientY);
|
||||||
|
wmi.storeI64(off(8), e.offsetX);
|
||||||
|
wmi.storeI64(off(8), e.offsetY);
|
||||||
|
wmi.storeI64(off(8), e.pageX);
|
||||||
|
wmi.storeI64(off(8), e.pageY);
|
||||||
|
wmi.storeI64(off(8), e.movementX);
|
||||||
|
wmi.storeI64(off(8), e.movementY);
|
||||||
|
wmi.storeI64(off(8), e.x);
|
||||||
|
wmi.storeI64(off(8), e.y);
|
||||||
|
|
||||||
|
wmi.storeU8(off(1), !!e.ctrlKey);
|
||||||
|
wmi.storeU8(off(1), !!e.shiftKey);
|
||||||
|
wmi.storeU8(off(1), !!e.altKey);
|
||||||
|
wmi.storeU8(off(1), !!e.metaKey);
|
||||||
|
|
||||||
|
wmi.storeI16(off(2), e.button);
|
||||||
|
wmi.storeU16(off(2), e.buttons);
|
||||||
|
} else if (e instanceof KeyboardEvent) {
|
||||||
|
let keyOffset = off(W*2, W);
|
||||||
|
let codeOffet = off(W*2, W);
|
||||||
|
wmi.storeU8(off(1), e.location);
|
||||||
|
|
||||||
|
wmi.storeU8(off(1), !!e.ctrlKey);
|
||||||
|
wmi.storeU8(off(1), !!e.shiftKey);
|
||||||
|
wmi.storeU8(off(1), !!e.altKey);
|
||||||
|
wmi.storeU8(off(1), !!e.metaKey);
|
||||||
|
|
||||||
|
wmi.storeU8(off(1), !!e.repeat);
|
||||||
|
} else if (e instanceof WheelEvent) {
|
||||||
|
wmi.storeF64(off(8), e.deltaX);
|
||||||
|
wmi.storeF64(off(8), e.deltaY);
|
||||||
|
wmi.storeF64(off(8), e.deltaZ);
|
||||||
|
wmi.storeU32(off(4), e.deltaMode);
|
||||||
|
} else if (e instanceof Event) {
|
||||||
|
if ('scrollX' in e) {
|
||||||
|
wmi.storeF64(off(8), e.scrollX);
|
||||||
|
wmi.storeF64(off(8), e.scrollY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
add_event_listener: (id_ptr, id_len, name_ptr, name_len, name_code, data, callback, use_capture) => {
|
||||||
|
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
|
||||||
|
let name = wasmMemoryInterface.loadString(name_ptr, name_len);
|
||||||
|
let element = document.getElementById(id);
|
||||||
|
if (element == undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let listener = (e) => {
|
||||||
|
const odin_ctx = wasmMemoryInterface.exports.default_context_ptr();
|
||||||
|
event_temp_data.id_ptr = id_ptr;
|
||||||
|
event_temp_data.id_len = id_len;
|
||||||
|
event_temp_data.event = e;
|
||||||
|
event_temp_data.name_code = name_code;
|
||||||
|
// console.log(e);
|
||||||
|
wasmMemoryInterface.exports.odin_dom_do_event_callback(data, callback, odin_ctx);
|
||||||
|
};
|
||||||
|
wasmMemoryInterface.listenerMap[{data: data, callback: callback}] = listener;
|
||||||
|
element.addEventListener(name, listener, !!use_capture);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
remove_event_listener: (id_ptr, id_len, name_ptr, name_len, data, callback) => {
|
||||||
|
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
|
||||||
|
let name = wasmMemoryInterface.loadString(name_ptr, name_len);
|
||||||
|
let element = document.getElementById(id);
|
||||||
|
if (element == undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let listener = wasmMemoryInterface.listenerMap[{data: data, callback: callback}];
|
||||||
|
if (listener == undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
element.removeEventListener(name, listener);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
add_window_event_listener: (name_ptr, name_len, name_code, data, callback, use_capture) => {
|
||||||
|
let name = wasmMemoryInterface.loadString(name_ptr, name_len);
|
||||||
|
let element = window;
|
||||||
|
let listener = (e) => {
|
||||||
|
const odin_ctx = wasmMemoryInterface.exports.default_context_ptr();
|
||||||
|
event_temp_data.id_ptr = 0;
|
||||||
|
event_temp_data.id_len = 0;
|
||||||
|
event_temp_data.event = e;
|
||||||
|
event_temp_data.name_code = name_code;
|
||||||
|
// console.log(e);
|
||||||
|
wasmMemoryInterface.exports.odin_dom_do_event_callback(data, callback, odin_ctx);
|
||||||
|
};
|
||||||
|
wasmMemoryInterface.listenerMap[{data: data, callback: callback}] = listener;
|
||||||
|
element.addEventListener(name, listener, !!use_capture);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
remove_window_event_listener: (name_ptr, name_len, data, callback) => {
|
||||||
|
let name = wasmMemoryInterface.loadString(name_ptr, name_len);
|
||||||
|
let element = window;
|
||||||
|
let listener = wasmMemoryInterface.listenerMap[{data: data, callback: callback}];
|
||||||
|
if (listener == undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
element.removeEventListener(name, listener);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
event_stop_propagation: () => {
|
||||||
|
if (event_temp_data && event_temp_data.event) {
|
||||||
|
event_temp_data.event.eventStopPropagation();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
event_stop_immediate_propagation: () => {
|
||||||
|
if (event_temp_data && event_temp_data.event) {
|
||||||
|
event_temp_data.event.eventStopImmediatePropagation();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
event_prevent_default: () => {
|
||||||
|
if (event_temp_data && event_temp_data.event) {
|
||||||
|
event_temp_data.event.eventPreventDefault();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
get_element_value_f64: (id_ptr, id_len) => {
|
||||||
|
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
|
||||||
|
let element = document.getElementById(id);
|
||||||
|
return element.value;
|
||||||
|
},
|
||||||
|
get_element_value_string: (id_ptr, id_len, buf_ptr, buf_len) => {
|
||||||
|
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
|
||||||
|
let element = document.getElementById(id);
|
||||||
|
let str = element.value;
|
||||||
|
if (buf_len > 0 && buf_ptr) {
|
||||||
|
let n = Math.min(buf_len, str.length);
|
||||||
|
str = str.substring(0, n);
|
||||||
|
this.mem.loadBytes(buf_ptr, buf_len).set(new TextEncoder("utf-8").encode(str))
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
get_element_min_max: (ptr_array2_f64, id_ptr, id_len) => {
|
||||||
|
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
|
||||||
|
let element = document.getElementById(id);
|
||||||
|
let values = wasmMemoryInterface.loadF64Array(ptr_array2_f64, 2);
|
||||||
|
values[0] = element.min;
|
||||||
|
values[1] = element.max;
|
||||||
|
},
|
||||||
|
set_element_value: (id_ptr, id_len, value) => {
|
||||||
|
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
|
||||||
|
document.getElementById(id).value = value;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export {WasmMemoryInterface, odinSetupDefaultImports};
|
||||||
Vendored
+63
@@ -0,0 +1,63 @@
|
|||||||
|
import {WasmMemoryInterface, odinSetupDefaultImports} from "../js/runtime.mjs";
|
||||||
|
import {WebGLInterface} from "../WebGL/runtime.mjs";
|
||||||
|
|
||||||
|
export async function runWasmCanvas(wasmPath, webglCanvasElement, consoleElement, extraForeignImports) {
|
||||||
|
let wasmMemoryInterface = new WasmMemoryInterface();
|
||||||
|
|
||||||
|
let imports = odinSetupDefaultImports(wasmMemoryInterface, consoleElement);
|
||||||
|
let exports = {};
|
||||||
|
|
||||||
|
if (webglCanvasElement !== undefined) {
|
||||||
|
let gl_context = new WebGLInterface(
|
||||||
|
wasmMemoryInterface,
|
||||||
|
webglCanvasElement,
|
||||||
|
{antialias: false},
|
||||||
|
);
|
||||||
|
if (!gl_context.ctx) {
|
||||||
|
return "WebGL is not available.";
|
||||||
|
}
|
||||||
|
imports["webgl"] = gl_context.getWebGL1Interface();
|
||||||
|
imports["webgl2"] = gl_context.getWebGL2Interface();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extraForeignImports !== undefined) {
|
||||||
|
imports = {
|
||||||
|
...imports,
|
||||||
|
...extraForeignImports,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(wasmPath);
|
||||||
|
const file = await response.arrayBuffer();
|
||||||
|
const wasm = await WebAssembly.instantiate(file, imports);
|
||||||
|
exports = wasm.instance.exports;
|
||||||
|
wasmMemoryInterface.setExports(exports);
|
||||||
|
wasmMemoryInterface.setMemory(exports.memory);
|
||||||
|
|
||||||
|
exports._start();
|
||||||
|
|
||||||
|
if (exports.step) {
|
||||||
|
const odin_ctx = exports.default_context_ptr();
|
||||||
|
|
||||||
|
let prevTimeStamp = undefined;
|
||||||
|
const step = (currTimeStamp) => {
|
||||||
|
if (prevTimeStamp == undefined) {
|
||||||
|
prevTimeStamp = currTimeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dt = (currTimeStamp - prevTimeStamp)*0.001;
|
||||||
|
prevTimeStamp = currTimeStamp;
|
||||||
|
exports.step(dt, odin_ctx);
|
||||||
|
window.requestAnimationFrame(step);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.requestAnimationFrame(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports._end();
|
||||||
|
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export {runWasmCanvas};
|
||||||
Reference in New Issue
Block a user