From 9c38c91f58b4edfe8a0f1bdc8e23ac1a28a8efa7 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Wed, 21 Apr 2021 22:38:37 -0500 Subject: [PATCH] starting to work on reusable modules for webgl and event systems --- bin/onyx-loader.js | 47 +++ build.sh | 3 +- core/js/webgl.js | 285 ----------------- modules/js_events/js_events.js | 67 ++++ modules/js_events/js_events.onyx | 109 +++++++ modules/js_events/module.onyx | 2 + modules/webgl2/module.onyx | 2 + modules/webgl2/webgl2.js | 291 ++++++++++++++++++ .../webgl.onyx => modules/webgl2/webgl2.onyx | 1 + 9 files changed, 521 insertions(+), 286 deletions(-) create mode 100644 bin/onyx-loader.js delete mode 100644 core/js/webgl.js create mode 100644 modules/js_events/js_events.js create mode 100644 modules/js_events/js_events.onyx create mode 100644 modules/js_events/module.onyx create mode 100644 modules/webgl2/module.onyx create mode 100644 modules/webgl2/webgl2.js rename core/js/webgl.onyx => modules/webgl2/webgl2.onyx (99%) diff --git a/bin/onyx-loader.js b/bin/onyx-loader.js new file mode 100644 index 00000000..a48a38ac --- /dev/null +++ b/bin/onyx-loader.js @@ -0,0 +1,47 @@ + +window.ONYX_MODULES = window.ONYX_MODULES || []; +window.ONYX_MEMORY = null; +window.ONYX_INSTANCE = null; + +window.ONYX_MODULES.push({ + module_name: "host", + + print_str: function(ptr, len) { + var buffer = new Uint8Array(ONYX_MEMORY.buffer, ptr, len); + var string = new TextDecoder().decode(buffer); + console.log(string); + }, + + exit: function() { debugger; } +}); + +function launch_onyx_program(script_path, call_start) { + fetch(script_path) + .then(function(res) { return res.arrayBuffer(); }) + .then(function(wasm_code) { + var import_object = {}; + + for (var i = 0; i < window.ONYX_MODULES.length; i++) { + import_object[window.ONYX_MODULES[i].module_name] = window.ONYX_MODULES[i]; + } + + return WebAssembly.instantiate(wasm_code, import_object); + }) + .then(function(wasm_module) { + window.ONYX_MEMORY = wasm_module.instance.exports.memory; + window.ONYX_INSTANCE = wasm_module.instance; + + wasm_module.instance.exports._start(); + }); +} + +window.onload = function() { + var script_tags = document.getElementsByTagName("script"); + + for (var i = 0; i < script_tags.length; i++) { + if (script_tags[i].getAttribute("type") == "application/onyx") { + // @ROBUSTNESS: It should be configurable which function is called on start up of a Onyx WASM module. + launch_onyx_program(script_tags[i].getAttribute("src"), true); + } + } +}; diff --git a/build.sh b/build.sh index 07fbeb47..1558a98c 100755 --- a/build.sh +++ b/build.sh @@ -8,15 +8,16 @@ sudo cp -r ./core/ "$CORE_DIR" [ "$1" = "libs_only" ] && exit 0 C_FILES="onyx onyxastnodes onyxbuiltins onyxchecker onyxclone onyxdoc onyxentities onyxerrors onyxlex onyxparser onyxsymres onyxtypes onyxutils onyxwasm" -TARGET='./bin/onyx' CC='gcc' WARNINGS='-Wimplicit -Wmisleading-indentation -Wparentheses -Wsequence-point -Wreturn-type -Wshift-negative-value -Wunused-but-set-parameter -Wunused-but-set-variable -Wunused-function -Wunused-label -Wmaybe-uninitialized -Wsign-compare -Wstrict-overflow -Wduplicated-branches -Wduplicated-cond -Wtrigraphs -Waddress -Wlogical-op' if [ "$1" = "debug" ]; then FLAGS="$WARNINGS -g3 -I./include" + TARGET="./bin/onyx-debug" else FLAGS="$WARNINGS -O3 -I./include" + TARGET='./bin/onyx' fi BUILD_DIR='.' diff --git a/core/js/webgl.js b/core/js/webgl.js deleted file mode 100644 index 4c483c9d..00000000 --- a/core/js/webgl.js +++ /dev/null @@ -1,285 +0,0 @@ -WebGl_Wasm = { - init(name, namelen) { - const decoder = new TextDecoder(); - const str = new Uint8Array(WASM_MEMORY.buffer, name, namelen); - const canvasname = decoder.decode(str); - - this.programs = []; - this.shaders = []; - this.buffers = []; - this.framebuffers = []; - this.renderbuffers = []; - this.textures = []; - this.uniformlocs = []; - this.vertexArrays = []; - - this.canvas = document.getElementById(canvasname); - if (this.canvas == null) return 0; - - this.gl = this.canvas.getContext("webgl2"); - if (this.gl == null) return 0; - - return 1; - }, - - activeTexture(texture) { this.gl.activeTexture(texture); }, - attachShader(program, shader) { this.gl.attachShader(this.programs[program], this.shaders[shader]); return this.programs[program]; }, - bindAttribLocation(program, index, name, namelen) { console.log("NOT IMPLEMENTED!"); }, - bindBuffer(target, buffer) { - if (buffer == -1) { - this.gl.bindBuffer(target, null); - } else { - this.gl.bindBuffer(target, this.buffers[buffer]); - } - }, - bindFramebuffer(target, framebuffer) { this.gl.bindFramebuffer(target, this.framebuffers[framebuffer]); }, - bindRenderbuffer(target, renderbuffer) { this.gl.bindRenderbuffer(target, this.renderbuffers[renderbuffer]); }, - bindTexture(target, texture) { this.gl.bindTexture(target, this.textures[texture]); }, - bindVertexArray(vertexArray) { this.gl.bindVertexArray(this.vertexArrays[vertexArray]); }, - - blendColor(red, green, blue, alpha) { this.gl.blendColor(red, green, blue, alpha); }, - blendEquation(mode) { this.gl.blendEquation(mode); }, - blendEquationSeparate(modeRGB, modeAlpha) { this.gl.blendEquationSeparate(modeRGB, modeAlpha); }, - blendFunc(sfactor, dfactor) { this.gl.blendFunc(sfactor, dfactor); }, - blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha) { this.gl.blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); }, - - blitFramebuffer(sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1, mask, filter) { - this.gl.blitFramebuffer(sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1, mask, filter); - }, - - bufferDataWithData(target, bufferdata, bufferlen, usage) { - const data = new DataView(WASM_MEMORY.buffer, bufferdata, bufferlen); - this.gl.bufferData(target, data, usage); - }, - - bufferDataNoData(target, size, usage) { this.gl.bufferData(target, size, usage); }, - bufferSubData(target, offset, bufferdata, bufferlen) { - const data = new DataView(WASM_MEMORY.buffer, bufferdata, bufferlen); - this.gl.bufferSubData(target, offset, data); - }, - canvasSize(width, height) { - this.canvas.width = width; - this.canvas.height = height; - }, - checkFrameBufferStatus(target) { return this.gl.checkFrameBufferStatus(target); }, - clear(bit) { this.gl.clear(bit); }, - clearColor(r, g, b, a) { this.gl.clearColor(r, g, b, a); }, - clearDepth(depth) { this.gl.clearDepth(depth); }, - clearStencil(stencil) { this.gl.clearStencil(stencil); }, - colorMask(r, g, b, a) { this.gl.colorMask(r, g, b, a); }, - compileShader(shader) { this.gl.compileShader(this.shaders[shader]); }, - compressedTexImage2D(target, level, internalformat, width, height, border, data, datalen) { - const pixels = new DataView(WASM_MEMORY.buffer, data, datalen); - this.gl.compressedTexImage2D(target, level, internalformat, width, height, border, pixels); - }, - compressedTexSubImage2D(target, level, internalformat, xoff, yoff, width, height, format, data, datalen) { - const pixels = new DataView(WASM_MEMORY.buffer, data, datalen); - this.gl.compressedSubTexImage2D(target, level, internalformat, xoff, yoff, width, height, format, pixels); - }, - copyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size) { this.gl.copyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size); }, - copyTexImage2D(target, level, internalforamt, x, y, width, height, border) { - this.gl.copyTexImage2D(target, level, internalforamt, x, y, width, height, border); - }, - copyTexSubImage2D(target, level, xoff, yoff, x, y, width, height) { - this.gl.copyTexSubImage2D(target, level, xoff, yoff, x, y, width, height); - }, - createBuffer() { - const buf = this.gl.createBuffer(); - if (buf == null) return -1; - - this.buffers.push(buf); - return this.buffers.length - 1; - }, - createFramebuffer() { - const buf = this.gl.createFramebuffer(); - if (buf == null) return -1; - - this.framebuffers.push(buf); - return this.framebuffers.length - 1; - }, - createProgram() { - const prog = this.gl.createProgram(); - if (prog == null) return -1; - - this.programs.push(prog); - return this.programs.length - 1; - }, - createRenderbuffer() { - const buf = this.gl.createRenderbuffer(); - if (buf == null) return -1; - - this.renderbuffers.push(buf); - return this.renderbuffers.length - 1; - }, - createShader(type) { - const shader = this.gl.createShader(type); - if (shader == null) return -1; - - this.shaders.push(shader); - return this.shaders.length - 1; - }, - createTexture() { - const texture = this.gl.createTexture(); - if (texture == null) return -1; - - this.textures.push(texture); - return this.textures.length - 1; - }, - createVertexArray() { - const vao = this.gl.createVertexArray(); - if (vao == null) return -1; - - this.vertexArrays.push(vao); - return this.vertexArrays.length - 1; - }, - cullFace(mode) { this.gl.cullFace(mode); }, - deleteBuffer(buffer) { this.gl.deleteBuffer(this.buffers[buffer]); }, - deleteFramebuffer(framebuffer) { this.gl.deleteFramebuffer(this.framebuffers[framebuffer]); }, - deleteProgram(program) { this.gl.deleteProgram(this.programs[program]); }, - deleteRenderbuffer(renderbuffer) { this.gl.deleteRenderbuffer(this.renderbuffers[renderbuffer]); }, - deleteShader(shader) { this.gl.deleteShader(this.shaders[shader]); }, - deleteTexture(texture) { this.gl.deleteTexture(this.textures[texture]); }, - deleteVertexArray(vertexArray) { this.gl.deleteVertexArray(this.vertexArrays[vertexArray]); }, - depthFunc(func) { this.gl.depthFunc(func); }, - depthMask(flag) { this.gl.depthMask(flag); }, - depthRange(znear, zfar) { this.gl.depthRange(znear, zfar); }, - detachShader(program, shader) { this.gl.detachShader(this.programs[program], this.shaders[shader]); }, - disable(cap) { this.gl.disable(cap); }, - disableVertexAttribArray(index) { this.gl.disableVertexAttribArray(index); }, - drawArrays(mode, first, count) { this.gl.drawArrays(mode, first, count); }, - drawArraysInstanced(mode, first, count, instanceCount) { this.gl.drawArraysInstanced(mode, first, count, instanceCount); }, - drawElements(mode, count, type, offset) { this.gl.drawElements(mode, count, type, offset); }, - drawElementsInstanced(mode, count, type, offset, instanceCount) { this.gl.drawElementsInstanced(mode, count, type, offset, instanceCount); }, - enable(cap) { this.gl.enable(cap); }, - enableVertexAttribArray(index) { this.gl.enableVertexAttribArray(index); }, - finish() { this.gl.finish(); }, - flush() { this.gl.flush(); }, - framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer) { - this.gl.framebufferRenderbuffer(target, attachment, renderbuffertarget, this.renderbuffers[renderbuffer]); - }, - framebufferTexture2D(target, attachment, texttarget, texture, level) { - this.gl.framebufferTexture2D(target, attachment, texttarget, this.textures[texture], level); - }, - framebufferTextureLayer(target, attachment, texture, level, layer) { this.gl.framebufferTextureLayer(target, attachment, this.textures[texture], level, layer); }, - frontFace(mode) { this.gl.frontFace(mode); }, - generateMipmap(target) { this.gl.generateMipmap(target); }, - getActiveAttrib(program, index, out) { - const loc = this.gl.getActiveAttrib(this.programs[program], index); - const data = new Int32Array(WASM_MEMORY.buffer, out, 2); - data[0] = loc.size; - data[1] = loc.type; - }, - getActiveUniform(program, index, out) { - const loc = this.gl.getActiveUniform(this.programs[program], index); - const data = new Int32Array(WASM_MEMORY.buffer, out, 2); - data[0] = loc.size; - data[1] = loc.type; - }, - // getAttachedShaders() { console.log("NOT IMPLEMENTED!"); }, - getAttribLocation(program, name, namelen) { - const decoder = new TextDecoder(); - const str = new Uint8Array(WASM_MEMORY.buffer, name, namelen); - const attribname = decoder.decode(str); - - return this.gl.getAttribLocation(this.programs[program], attribname); - }, - // getBufferParameter() { console.log("NOT IMPLEMENTED!"); }, - getBufferSubData(target, srcbyteoffset, dstbufferdata, dstbufferlen, dstoffset, length) { - const dst = new DataView(WASM_MEMORY.buffer, dstbufferdata, dstbufferlen); - this.gl.getBufferSubData(target, srcbyteoffset, dst, dstoffset, length); - }, - getError() { return this.gl.getError(); }, - getInternalformatParameter(target, internalformat, pname) { return this.gl.getInternalformatParameter(target, internalformat, pname); }, - // many of the 'gets() { console.log("NOT IMPLEMENTED!"); }, - getShaderParameter(shader, param) { return this.gl.getShaderParameter(this.shaders[shader], param); }, - getProgramParameter(program, param) { return this.gl.getProgramParameter(this.programs[program], param); }, - getUniformLocation(program, name, namelen) { - const decoder = new TextDecoder(); - const str = new Int8Array(WASM_MEMORY.buffer, name, namelen); - const uniname = decoder.decode(str); - - this.uniformlocs.push(this.gl.getUniformLocation(this.programs[program], uniname)); - return this.uniformlocs.length - 1; - }, - getVertexAttribOffset(index, pname) { return this.gl.getVertexAttribOffset(index, pname); }, - hint(target, mode) { this.gl.hint(target, mode); }, - isEnabled(cap) { return this.gl.isEnabled(cap); }, - invalidateFramebuffer(target, attachdata, attachlen) { - const attachments = new Int32Array(WASM_MEMORY.buffer, attachdata, attachlen); - this.gl.invalidateFramebuffer(target, attacements); - }, - invalidateSubFramebuffer(target, attachdata, attachlen, x, y, width, height) { - const attachments = new Int32Array(WASM_MEMORY.buffer, attachdata, attachlen); - this.gl.invalidateFramebuffer(target, attacements, x, y, width, height); - }, - lineWidth(width) { this.gl.lineWidth(width); }, - linkProgram(program) { this.gl.linkProgram(this.programs[program]); }, - pixelStorei(pname, param) { this.gl.pixelStorei(pname, param); }, - polygonOffset(factor, units) { this.gl.polygonOffset(factor, units); }, - printProgramInfoLog(program) { console.log(this.gl.getProgramInfoLog(this.programs[program])); }, - printShaderInfoLog(shader) { console.log(this.gl.getShaderInfoLog(this.shaders[shader])); }, - readPixels(x, y, width, height, format, type, pixels, pixelslen) { - const pixeldata = new Uint8Array(WASM_MEMORY.buffer, pixels, pixelslen); - this.gl.readPixels(x, y, width, height, format, type, pixeldata); - }, - readBuffer(src) { this.gl.readBuffer(src); }, - renderbufferStorageMultisample(target, samples, internalforamt, width, height) { - this.gl.renderbufferStorageMultisample(target, samples, internalforamt, width, height); - }, - sampleCoverage(value, invert) { this.gl.sampleCoverage(value, invert); }, - scissor(x, y, width, height) { this.gl.scissor(x, y, width, height); }, - setSize(width, height) { this.canvas.width = width; this.canvas.height = height; }, - shaderSource(shader, source, sourcelen) { - const decoder = new TextDecoder(); - const str = new Int8Array(WASM_MEMORY.buffer, source, sourcelen); - const sourcedata = decoder.decode(str); - - this.gl.shaderSource(this.shaders[shader], sourcedata); - }, - stencilFunc(func, ref, mask) { this.gl.stencilFunc(func, ref, mask); }, - stencilFuncSeparate(face, func, ref, mask) { this.gl.stencilFuncSeparate(face, func, ref, mask); }, - stencilMask(mask) { this.gl.stencilMask(mask); }, - stencilMaskSeparate(face, mask) { this.gl.stencilMaskSeparate(face, mask); }, - stencilOp(fail, zfail, mask) { this.gl.stencilOp(fail, zfail, mask); }, - stencilOpSeparate(face, fail, zfail, zpass) { this.gl.stencilOpSeparate(face, fail, zfail, zpass); }, - texImage2D(target, level, internalforamt, width, height, border, format, type, pixels, pixelslen) { - const data = new DataView(WASM_MEMORY.buffer, pixels, pixelslen); - this.gl.texImage2D(target, level, internalforamt, width, height, border, format, type, data); - }, - texParameterf(target, pname, param) { this.gl.texParameterf(target, pname, param); }, - texParameteri(target, pname, param) { this.gl.texParameteri(target, pname, param); }, - texSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels, pixelslen) { - const data = new Uint8Array(WASM_MEMORY.buffer, pixels, pixelslen); - this.gl.texSubImage2D(target, level, xoff, yoff, width, height, format, type, data); - }, - uniform1f(loc, x) { this.gl.uniform1f(this.uniformlocs[loc], x); }, - uniform1i(loc, x) { this.gl.uniform1i(this.uniformlocs[loc], x); }, - uniform2f(loc, x, y) { this.gl.uniform2f(this.uniformlocs[loc], x, y); }, - uniform2i(loc, x, y) { this.gl.uniform2i(this.uniformlocs[loc], x, y); }, - uniform3f(loc, x, y, z) { this.gl.uniform3f(this.uniformlocs[loc], x, y, z); }, - uniform3i(loc, x, y, z) { this.gl.uniform3i(this.uniformlocs[loc], x, y, z); }, - uniform4f(loc, x, y, z, w) { this.gl.uniform4f(this.uniformlocs[loc], x, y, z, w); }, - uniform4i(loc, x, y, z, w) { this.gl.uniform4i(this.uniformlocs[loc], x, y, z, w); }, - uniformMatrix2(loc, transpose, valueptr) { - const data = new Float32Array(WASM_MEMORY.buffer, valueptr, 4); - this.gl.uniformMatrix2fv(this.uniformlocs[loc], transpose, data); - }, - uniformMatrix3(loc, transpose, valueptr) { - const data = new Float32Array(WASM_MEMORY.buffer, valueptr, 9); - this.gl.uniformMatrix3fv(this.uniformlocs[loc], transpose, data); - }, - uniformMatrix4(loc, transpose, valueptr) { - const data = new Float32Array(WASM_MEMORY.buffer, valueptr, 16); - this.gl.uniformMatrix4fv(this.uniformlocs[loc], transpose, data); - }, - useProgram(program) { this.gl.useProgram(this.programs[program]); }, - validateProgram(program) { this.gl.validateProgram(this.program[program]); }, - vertexAttrib1f(idx, x) { this.gl.vertexAttrib1f(idx, x); }, - vertexAttrib2f(idx, x, y) { this.gl.vertexAttrib2f(idx, x, y); }, - vertexAttrib3f(idx, x, y, z) { this.gl.vertexAttrib3f(idx, x, y, z); }, - vertexAttrib4f(idx, x, y, z, w) { this.gl.vertexAttrib4f(idx, x, y, z, w); }, - vertexAttribPointer(idx, size, type, normalized, stride, offset) { this.gl.vertexAttribPointer(idx, size, type, normalized, stride, offset); }, - vertexAttribDivisor(idx, divisor) { this.gl.vertexAttribDivisor(idx, divisor); }, - viewport(x, y, width, height) { this.gl.viewport(x, y, width, height); }, - -}; diff --git a/modules/js_events/js_events.js b/modules/js_events/js_events.js new file mode 100644 index 00000000..df3bb834 --- /dev/null +++ b/modules/js_events/js_events.js @@ -0,0 +1,67 @@ +window.ONYX_MODULES = window.ONYX_MODULES || []; + +function push_event_to_buffer(esp, event_size, event_kind, data) { + let WASM_U32 = new Uint32Array(ONYX_MEMORY.buffer); + + if (WASM_U32[esp] >= WASM_U32[esp + 1]) { + console.log("Event buffer full!"); + return; + } + + WASM_U32[esp] += 1; + + let event_idx = esp + (WASM_U32[esp] - 1) * (event_size / 4) + 2; + WASM_U32[event_idx] = event_kind; + WASM_U32[event_idx + 1] = Date.now(); + + for (let i = 0; i < data.length; i++) { + WASM_U32[event_idx + 2 + i] = data[i]; + } +} + +window.ONYX_MODULES.push({ + module_name: "js_events", + + setup: function(esp, event_size) { + // Indicies into a Uint32Array are not based on bytes, + // but on the index. + esp /= 4; + + document.addEventListener("keydown", function (ev) { + if (ev.isComposing || ev.keyCode === 229) return; + push_event_to_buffer(esp, event_size, 0x04, [ ev.keyCode ]); + }); + + document.addEventListener("keyup", function (ev) { + if (ev.isComposing || ev.keyCode === 229) return; + push_event_to_buffer(esp, event_size, 0x05, [ ev.keyCode ]); + }); + + document.addEventListener("mousedown", function (ev) { + push_event_to_buffer(esp, event_size, 0x01, [ ev.clientX, ev.clientY, ev.button ]); + }); + + document.addEventListener("mouseup", function (ev) { + push_event_to_buffer(esp, event_size, 0x02, [ ev.clientX, ev.clientY, ev.button ]); + }); + + document.addEventListener("mousemove", function (ev) { + push_event_to_buffer(esp, event_size, 0x03, [ ev.clientX, ev.clientY, -1 ]); + }); + + document.addEventListener("wheel", function (ev) { + push_event_to_buffer(esp, event_size, 0x07, [ ev.clientX, ev.clientY, ev.deltaY >= 0 ? 0x04 : 0x03 ]); + }); + + window.addEventListener("resize", function (ev) { + push_event_to_buffer(esp, event_size, 0x06, [ window.innerWidth, window.innerHeight ]); + }); + + push_event_to_buffer(esp, event_size, 0x06, [ window.innerWidth, window.innerHeight ]); + + document.oncontextmenu = (e) => { + e.preventDefault = true; + return false; + }; + }, +}); diff --git a/modules/js_events/js_events.onyx b/modules/js_events/js_events.onyx new file mode 100644 index 00000000..f7fbee98 --- /dev/null +++ b/modules/js_events/js_events.onyx @@ -0,0 +1,109 @@ +// This is a simple buffered system to receive events from the webbrowser +// in a buffer that you can poll and consume all of the events. It is not +// direclty used by the immediate mode graphics, but it makes standing up +// a simple application much easier. + +package js_events + +#private_file Num_Buffered_Events :: 16 + +// NOTE: These need to match exactly what is in the corresponding javascript +DomEventKind :: enum { + None :: 0x00; + + MouseDown :: 0x01; + MouseUp :: 0x02; + MouseMove :: 0x03; + MouseWheel :: 0x07; + + KeyDown :: 0x04; + KeyUp :: 0x05; + + Resize :: 0x06; +} + +DomEvent :: struct { + kind : DomEventKind; + timestamp : u32; +} + +KeyboardEvent :: struct { + use event : DomEvent; + + keycode : u32; +} + +MouseButton :: enum { + Left :: 0x00; + Middle :: 0x01; + Right :: 0x02; + + WheelUp :: 0x03; + WheelDown :: 0x04; +} + +MouseEvent :: struct { + use event : DomEvent; + + pos_x : u32; + pos_y : u32; + button : MouseButton; +} + +ResizeEvent :: struct { + use event : DomEvent; + + width : u32; + height : u32; +} + +Event :: struct #union { + use dom : DomEvent; + + keyboard : KeyboardEvent; + mouse : MouseEvent; + resize : ResizeEvent; +} + +clear_event :: (ev: ^Event) { + ev.kind = DomEventKind.None; + ev.timestamp = 0; +} + +init :: () { + event_storage.event_count = 0; + event_storage.max_events = Num_Buffered_Events; + + for ^ev: event_storage.event_buffer do clear_event(ev); + + event_setup(^event_storage, sizeof Event); +} + +consume :: () -> Iterator(Event) { + next :: (_: rawptr) -> (Event, bool) { + use package core.intrinsics.onyx { __zero_value } + if event_storage.event_count == 0 do return __zero_value(Event), false; + + event := event_storage.event_buffer[0]; + + for i: 0 .. Num_Buffered_Events - 2 { + event_storage.event_buffer[i] = event_storage.event_buffer[i + 1]; + } + event_storage.event_count -= 1; + + return event, true; + } + + return .{ null, next }; +} + +/* Private members */ + +#private_file EventStorage :: struct { + event_count : u32; + max_events : u32; + event_buffer : [Num_Buffered_Events] Event; +} + +#private_file event_storage : EventStorage; +#private_file event_setup :: (event_storage: ^EventStorage, event_size: u32) -> void #foreign "js_events" "setup" --- diff --git a/modules/js_events/module.onyx b/modules/js_events/module.onyx new file mode 100644 index 00000000..23215cf3 --- /dev/null +++ b/modules/js_events/module.onyx @@ -0,0 +1,2 @@ + +#load "modules/js_events/js_events" diff --git a/modules/webgl2/module.onyx b/modules/webgl2/module.onyx new file mode 100644 index 00000000..77b04ea5 --- /dev/null +++ b/modules/webgl2/module.onyx @@ -0,0 +1,2 @@ + +#load "modules/webgl2/webgl2" diff --git a/modules/webgl2/webgl2.js b/modules/webgl2/webgl2.js new file mode 100644 index 00000000..61d565a1 --- /dev/null +++ b/modules/webgl2/webgl2.js @@ -0,0 +1,291 @@ +window.ONYX_MODULES = window.ONYX_MODULES || []; + +var programs = []; +var shaders = []; +var buffers = []; +var framebuffers = []; +var renderbuffers = []; +var textures = []; +var uniformlocs = []; +var vertexArrays = []; +var canvas = null; +var gl = null; + +window.ONYX_MODULES.push({ + module_name: "gl", + + init(name, namelen) { + const decoder = new TextDecoder(); + const str = new Uint8Array(window.ONYX_MEMORY.buffer, name, namelen); + const canvasname = decoder.decode(str); + + canvas = document.getElementById(canvasname); + if (canvas == null) return 0; + + gl = canvas.getContext("webgl2"); + if (gl == null) return 0; + + return 1; + }, + + activeTexture(texture) { gl.activeTexture(texture); }, + attachShader(program, shader) { gl.attachShader(programs[program], shaders[shader]); return programs[program]; }, + bindAttribLocation(program, index, name, namelen) { console.log("NOT IMPLEMENTED!"); }, + bindBuffer(target, buffer) { + if (buffer == -1) { + gl.bindBuffer(target, null); + } else { + gl.bindBuffer(target, buffers[buffer]); + } + }, + bindFramebuffer(target, framebuffer) { gl.bindFramebuffer(target, framebuffers[framebuffer]); }, + bindRenderbuffer(target, renderbuffer) { gl.bindRenderbuffer(target, renderbuffers[renderbuffer]); }, + bindTexture(target, texture) { gl.bindTexture(target, textures[texture]); }, + bindVertexArray(vertexArray) { gl.bindVertexArray(vertexArrays[vertexArray]); }, + + blendColor(red, green, blue, alpha) { gl.blendColor(red, green, blue, alpha); }, + blendEquation(mode) { gl.blendEquation(mode); }, + blendEquationSeparate(modeRGB, modeAlpha) { gl.blendEquationSeparate(modeRGB, modeAlpha); }, + blendFunc(sfactor, dfactor) { gl.blendFunc(sfactor, dfactor); }, + blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha) { gl.blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); }, + + blitFramebuffer(sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1, mask, filter) { + gl.blitFramebuffer(sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1, mask, filter); + }, + + bufferDataWithData(target, bufferdata, bufferlen, usage) { + const data = new DataView(window.ONYX_MEMORY.buffer, bufferdata, bufferlen); + gl.bufferData(target, data, usage); + }, + + bufferDataNoData(target, size, usage) { gl.bufferData(target, size, usage); }, + bufferSubData(target, offset, bufferdata, bufferlen) { + const data = new DataView(window.ONYX_MEMORY.buffer, bufferdata, bufferlen); + gl.bufferSubData(target, offset, data); + }, + canvasSize(width, height) { + canvas.width = width; + canvas.height = height; + }, + checkFrameBufferStatus(target) { return gl.checkFrameBufferStatus(target); }, + clear(bit) { gl.clear(bit); }, + clearColor(r, g, b, a) { gl.clearColor(r, g, b, a); }, + clearDepth(depth) { gl.clearDepth(depth); }, + clearStencil(stencil) { gl.clearStencil(stencil); }, + colorMask(r, g, b, a) { gl.colorMask(r, g, b, a); }, + compileShader(shader) { gl.compileShader(shaders[shader]); }, + compressedTexImage2D(target, level, internalformat, width, height, border, data, datalen) { + const pixels = new DataView(window.ONYX_MEMORY.buffer, data, datalen); + gl.compressedTexImage2D(target, level, internalformat, width, height, border, pixels); + }, + compressedTexSubImage2D(target, level, internalformat, xoff, yoff, width, height, format, data, datalen) { + const pixels = new DataView(window.ONYX_MEMORY.buffer, data, datalen); + gl.compressedSubTexImage2D(target, level, internalformat, xoff, yoff, width, height, format, pixels); + }, + copyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size) { gl.copyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size); }, + copyTexImage2D(target, level, internalforamt, x, y, width, height, border) { + gl.copyTexImage2D(target, level, internalforamt, x, y, width, height, border); + }, + copyTexSubImage2D(target, level, xoff, yoff, x, y, width, height) { + gl.copyTexSubImage2D(target, level, xoff, yoff, x, y, width, height); + }, + createBuffer() { + const buf = gl.createBuffer(); + if (buf == null) return -1; + + buffers.push(buf); + return buffers.length - 1; + }, + createFramebuffer() { + const buf = gl.createFramebuffer(); + if (buf == null) return -1; + + framebuffers.push(buf); + return framebuffers.length - 1; + }, + createProgram() { + const prog = gl.createProgram(); + if (prog == null) return -1; + + programs.push(prog); + return programs.length - 1; + }, + createRenderbuffer() { + const buf = gl.createRenderbuffer(); + if (buf == null) return -1; + + renderbuffers.push(buf); + return renderbuffers.length - 1; + }, + createShader(type) { + const shader = gl.createShader(type); + if (shader == null) return -1; + + shaders.push(shader); + return shaders.length - 1; + }, + createTexture() { + const texture = gl.createTexture(); + if (texture == null) return -1; + + textures.push(texture); + return textures.length - 1; + }, + createVertexArray() { + const vao = gl.createVertexArray(); + if (vao == null) return -1; + + vertexArrays.push(vao); + return vertexArrays.length - 1; + }, + cullFace(mode) { gl.cullFace(mode); }, + deleteBuffer(buffer) { gl.deleteBuffer(buffers[buffer]); }, + deleteFramebuffer(framebuffer) { gl.deleteFramebuffer(framebuffers[framebuffer]); }, + deleteProgram(program) { gl.deleteProgram(programs[program]); }, + deleteRenderbuffer(renderbuffer) { gl.deleteRenderbuffer(renderbuffers[renderbuffer]); }, + deleteShader(shader) { gl.deleteShader(shaders[shader]); }, + deleteTexture(texture) { gl.deleteTexture(textures[texture]); }, + deleteVertexArray(vertexArray) { gl.deleteVertexArray(vertexArrays[vertexArray]); }, + depthFunc(func) { gl.depthFunc(func); }, + depthMask(flag) { gl.depthMask(flag); }, + depthRange(znear, zfar) { gl.depthRange(znear, zfar); }, + detachShader(program, shader) { gl.detachShader(programs[program], shaders[shader]); }, + disable(cap) { gl.disable(cap); }, + disableVertexAttribArray(index) { gl.disableVertexAttribArray(index); }, + drawArrays(mode, first, count) { gl.drawArrays(mode, first, count); }, + drawArraysInstanced(mode, first, count, instanceCount) { gl.drawArraysInstanced(mode, first, count, instanceCount); }, + drawElements(mode, count, type, offset) { gl.drawElements(mode, count, type, offset); }, + drawElementsInstanced(mode, count, type, offset, instanceCount) { gl.drawElementsInstanced(mode, count, type, offset, instanceCount); }, + enable(cap) { gl.enable(cap); }, + enableVertexAttribArray(index) { gl.enableVertexAttribArray(index); }, + finish() { gl.finish(); }, + flush() { gl.flush(); }, + framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer) { + gl.framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffers[renderbuffer]); + }, + framebufferTexture2D(target, attachment, texttarget, texture, level) { + gl.framebufferTexture2D(target, attachment, texttarget, textures[texture], level); + }, + framebufferTextureLayer(target, attachment, texture, level, layer) { gl.framebufferTextureLayer(target, attachment, textures[texture], level, layer); }, + frontFace(mode) { gl.frontFace(mode); }, + generateMipmap(target) { gl.generateMipmap(target); }, + getActiveAttrib(program, index, out) { + const loc = gl.getActiveAttrib(programs[program], index); + const data = new Int32Array(window.ONYX_MEMORY.buffer, out, 2); + data[0] = loc.size; + data[1] = loc.type; + }, + getActiveUniform(program, index, out) { + const loc = gl.getActiveUniform(programs[program], index); + const data = new Int32Array(window.ONYX_MEMORY.buffer, out, 2); + data[0] = loc.size; + data[1] = loc.type; + }, + // getAttachedShaders() { console.log("NOT IMPLEMENTED!"); }, + getAttribLocation(program, name, namelen) { + const decoder = new TextDecoder(); + const str = new Uint8Array(window.ONYX_MEMORY.buffer, name, namelen); + const attribname = decoder.decode(str); + + return gl.getAttribLocation(programs[program], attribname); + }, + // getBufferParameter() { console.log("NOT IMPLEMENTED!"); }, + getBufferSubData(target, srcbyteoffset, dstbufferdata, dstbufferlen, dstoffset, length) { + const dst = new DataView(window.ONYX_MEMORY.buffer, dstbufferdata, dstbufferlen); + gl.getBufferSubData(target, srcbyteoffset, dst, dstoffset, length); + }, + getError() { return gl.getError(); }, + getInternalformatParameter(target, internalformat, pname) { return gl.getInternalformatParameter(target, internalformat, pname); }, + // many of the 'gets() { console.log("NOT IMPLEMENTED!"); }, + getShaderParameter(shader, param) { return gl.getShaderParameter(shaders[shader], param); }, + getProgramParameter(program, param) { return gl.getProgramParameter(programs[program], param); }, + getUniformLocation(program, name, namelen) { + const decoder = new TextDecoder(); + const str = new Int8Array(window.ONYX_MEMORY.buffer, name, namelen); + const uniname = decoder.decode(str); + + uniformlocs.push(gl.getUniformLocation(programs[program], uniname)); + return uniformlocs.length - 1; + }, + getVertexAttribOffset(index, pname) { return gl.getVertexAttribOffset(index, pname); }, + hint(target, mode) { gl.hint(target, mode); }, + isEnabled(cap) { return gl.isEnabled(cap); }, + invalidateFramebuffer(target, attachdata, attachlen) { + const attachments = new Int32Array(window.ONYX_MEMORY.buffer, attachdata, attachlen); + gl.invalidateFramebuffer(target, attacements); + }, + invalidateSubFramebuffer(target, attachdata, attachlen, x, y, width, height) { + const attachments = new Int32Array(window.ONYX_MEMORY.buffer, attachdata, attachlen); + gl.invalidateFramebuffer(target, attacements, x, y, width, height); + }, + lineWidth(width) { gl.lineWidth(width); }, + linkProgram(program) { gl.linkProgram(programs[program]); }, + pixelStorei(pname, param) { gl.pixelStorei(pname, param); }, + polygonOffset(factor, units) { gl.polygonOffset(factor, units); }, + printProgramInfoLog(program) { console.log(gl.getProgramInfoLog(programs[program])); }, + printShaderInfoLog(shader) { console.log(gl.getShaderInfoLog(shaders[shader])); }, + readPixels(x, y, width, height, format, type, pixels, pixelslen) { + const pixeldata = new Uint8Array(window.ONYX_MEMORY.buffer, pixels, pixelslen); + gl.readPixels(x, y, width, height, format, type, pixeldata); + }, + readBuffer(src) { gl.readBuffer(src); }, + renderbufferStorageMultisample(target, samples, internalforamt, width, height) { + gl.renderbufferStorageMultisample(target, samples, internalforamt, width, height); + }, + sampleCoverage(value, invert) { gl.sampleCoverage(value, invert); }, + scissor(x, y, width, height) { gl.scissor(x, y, width, height); }, + setSize(width, height) { canvas.width = width; canvas.height = height; }, + shaderSource(shader, source, sourcelen) { + const decoder = new TextDecoder(); + const str = new Int8Array(window.ONYX_MEMORY.buffer, source, sourcelen); + const sourcedata = decoder.decode(str); + + gl.shaderSource(shaders[shader], sourcedata); + }, + stencilFunc(func, ref, mask) { gl.stencilFunc(func, ref, mask); }, + stencilFuncSeparate(face, func, ref, mask) { gl.stencilFuncSeparate(face, func, ref, mask); }, + stencilMask(mask) { gl.stencilMask(mask); }, + stencilMaskSeparate(face, mask) { gl.stencilMaskSeparate(face, mask); }, + stencilOp(fail, zfail, mask) { gl.stencilOp(fail, zfail, mask); }, + stencilOpSeparate(face, fail, zfail, zpass) { gl.stencilOpSeparate(face, fail, zfail, zpass); }, + texImage2D(target, level, internalforamt, width, height, border, format, type, pixels, pixelslen) { + const data = new DataView(window.ONYX_MEMORY.buffer, pixels, pixelslen); + gl.texImage2D(target, level, internalforamt, width, height, border, format, type, data); + }, + texParameterf(target, pname, param) { gl.texParameterf(target, pname, param); }, + texParameteri(target, pname, param) { gl.texParameteri(target, pname, param); }, + texSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels, pixelslen) { + const data = new Uint8Array(window.ONYX_MEMORY.buffer, pixels, pixelslen); + gl.texSubImage2D(target, level, xoff, yoff, width, height, format, type, data); + }, + uniform1f(loc, x) { gl.uniform1f(uniformlocs[loc], x); }, + uniform1i(loc, x) { gl.uniform1i(uniformlocs[loc], x); }, + uniform2f(loc, x, y) { gl.uniform2f(uniformlocs[loc], x, y); }, + uniform2i(loc, x, y) { gl.uniform2i(uniformlocs[loc], x, y); }, + uniform3f(loc, x, y, z) { gl.uniform3f(uniformlocs[loc], x, y, z); }, + uniform3i(loc, x, y, z) { gl.uniform3i(uniformlocs[loc], x, y, z); }, + uniform4f(loc, x, y, z, w) { gl.uniform4f(uniformlocs[loc], x, y, z, w); }, + uniform4i(loc, x, y, z, w) { gl.uniform4i(uniformlocs[loc], x, y, z, w); }, + uniformMatrix2(loc, transpose, valueptr) { + const data = new Float32Array(window.ONYX_MEMORY.buffer, valueptr, 4); + gl.uniformMatrix2fv(uniformlocs[loc], transpose, data); + }, + uniformMatrix3(loc, transpose, valueptr) { + const data = new Float32Array(window.ONYX_MEMORY.buffer, valueptr, 9); + gl.uniformMatrix3fv(uniformlocs[loc], transpose, data); + }, + uniformMatrix4(loc, transpose, valueptr) { + const data = new Float32Array(window.ONYX_MEMORY.buffer, valueptr, 16); + gl.uniformMatrix4fv(uniformlocs[loc], transpose, data); + }, + useProgram(program) { gl.useProgram(programs[program]); }, + validateProgram(program) { gl.validateProgram(program[program]); }, + vertexAttrib1f(idx, x) { gl.vertexAttrib1f(idx, x); }, + vertexAttrib2f(idx, x, y) { gl.vertexAttrib2f(idx, x, y); }, + vertexAttrib3f(idx, x, y, z) { gl.vertexAttrib3f(idx, x, y, z); }, + vertexAttrib4f(idx, x, y, z, w) { gl.vertexAttrib4f(idx, x, y, z, w); }, + vertexAttribIPointer(idx, size, type, stride, offset) { gl.vertexAttribIPointer(idx, size, type, stride, offset); }, + vertexAttribPointer(idx, size, type, normalized, stride, offset) { gl.vertexAttribPointer(idx, size, type, normalized, stride, offset); }, + vertexAttribDivisor(idx, divisor) { gl.vertexAttribDivisor(idx, divisor); }, + viewport(x, y, width, height) { gl.viewport(x, y, width, height); }, +}); diff --git a/core/js/webgl.onyx b/modules/webgl2/webgl2.onyx similarity index 99% rename from core/js/webgl.onyx rename to modules/webgl2/webgl2.onyx index 8ec5a144..d59501b6 100644 --- a/core/js/webgl.onyx +++ b/modules/webgl2/webgl2.onyx @@ -851,6 +851,7 @@ vertexAttrib1f :: (idx: GLuint, x: GLfloat) -> void #foreign "gl vertexAttrib2f :: (idx: GLuint, x: GLfloat, y: GLfloat) -> void #foreign "gl" "vertexAttrib2f" --- vertexAttrib3f :: (idx: GLuint, x: GLfloat, y: GLfloat, z: GLfloat) -> void #foreign "gl" "vertexAttrib3f" --- vertexAttrib4f :: (idx: GLuint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) -> void #foreign "gl" "vertexAttrib4f" --- +vertexAttribIPointer :: (idx: GLuint, size: GLint, type: GLenum, stride: GLsizei, offset: GLint) -> void #foreign "gl" "vertexAttribIPointer" --- vertexAttribPointer :: (idx: GLuint, size: GLint, type: GLenum, normalized: GLboolean, stride: GLsizei, offset: GLint) -> void #foreign "gl" "vertexAttribPointer" --- vertexAttribDivisor :: (idx: GLuint, divisor: GLuint) -> void #foreign "gl" "vertexAttribDivisor" --- viewport :: (x: GLint, y: GLint, width: GLsizei, height: GLsizei) -> void #foreign "gl" "viewport" --- -- 2.25.1