mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-06 06:38:20 +00:00
webgl: Add bindings, fix Tex*Image*D
This commit is contained in:
@@ -10,7 +10,7 @@ function getElement(name) {
|
||||
}
|
||||
|
||||
function stripNewline(str) {
|
||||
return str.replace(/\n/, ' ')
|
||||
return str.replace(/\n/, ' ')
|
||||
}
|
||||
|
||||
class WasmMemoryInterface {
|
||||
@@ -40,22 +40,14 @@ class WasmMemoryInterface {
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
loadF32Array(addr, len) { return new Float32Array(this.memory.buffer, addr, len); }
|
||||
loadF64Array(addr, len) { return new Float64Array(this.memory.buffer, addr, len); }
|
||||
loadU32Array(addr, len) { return new Uint32Array(this.memory.buffer, addr, len); }
|
||||
loadI32Array(addr, len) { return new Int32Array(this.memory.buffer, addr, len); }
|
||||
loadU16Array(addr, len) { return new Uint16Array(this.memory.buffer, addr, len); }
|
||||
loadI16Array(addr, len) { return new Int16Array(this.memory.buffer, addr, len); }
|
||||
loadU8Array(addr, len) { return new Uint8Array(this.memory.buffer, addr, len); }
|
||||
loadI8Array(addr, len) { return new Int8Array(this.memory.buffer, addr, len); }
|
||||
|
||||
|
||||
loadU8(addr) { return this.mem.getUint8 (addr); }
|
||||
@@ -200,6 +192,7 @@ class WebGLInterface {
|
||||
this.transformFeedbacks = [];
|
||||
this.syncs = [];
|
||||
this.programInfos = {};
|
||||
this.extensions = [];
|
||||
}
|
||||
|
||||
get mem() {
|
||||
@@ -225,6 +218,9 @@ class WebGLInterface {
|
||||
} else {
|
||||
this.ctxVersion = 1.0;
|
||||
}
|
||||
|
||||
this.extensions = this.ctx.getSupportedExtensions();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -281,6 +277,30 @@ class WebGLInterface {
|
||||
return source;
|
||||
}
|
||||
|
||||
loadTypedArrayFromTexelType(type, size, data) {
|
||||
switch (type) {
|
||||
case this.ctx.SHORT: return this.mem.loadI16Array(data, size/2);
|
||||
case this.ctx.UNSIGNED_SHORT_5_5_5_1:
|
||||
case this.ctx.UNSIGNED_SHORT_5_6_5:
|
||||
case this.ctx.UNSIGNED_SHORT_4_4_4_4:
|
||||
case this.ctx.UNSIGNED_SHORT:
|
||||
case this.ctx.HALF_FLOAT: return this.mem.loadU16Array(data, size/2);
|
||||
case this.ctx.FLOAT: return this.mem.loadF32Array(data, size/4);
|
||||
case this.ctx.INT: return this.mem.loadI32Array(data, size/4)
|
||||
case this.ctx.UNSIGNED_INT_24_8:
|
||||
case this.ctx.UNSIGNED_INT_5_9_9_9_REV:
|
||||
case this.ctx.UNSIGNED_INT_10F_11F_11F_REV:
|
||||
case this.ctx.UNSIGNED_INT_2_10_10_10_REV:
|
||||
case this.ctx.UNSIGNED_INT: return this.mem.loadU32Array(data, size/4)
|
||||
case this.ctx.BYTE: return this.mem.loadI8Array(data, size);
|
||||
case this.ctx.UNSIGNED_BYTE: return this.mem.loadU8Array(data, size);
|
||||
case this.ctx.FLOAT_32_UNSIGNED_INT_24_8_REV:
|
||||
throw new Error("Source data of type FLOAT_32_UNSIGNED_INT_24_8_REV must be null");
|
||||
}
|
||||
|
||||
throw new Error(`Unsupported texture data type: 0x${type.toString(16)}`);
|
||||
}
|
||||
|
||||
getWebGL1Interface() {
|
||||
return {
|
||||
SetCurrentContextById: (name_ptr, name_len) => {
|
||||
@@ -327,10 +347,30 @@ class WebGLInterface {
|
||||
|
||||
IsExtensionSupported: (name_ptr, name_len) => {
|
||||
let name = this.mem.loadString(name_ptr, name_len);
|
||||
let extensions = this.ctx.getSupportedExtensions();
|
||||
let extensions = this.extensions;
|
||||
return extensions.indexOf(name) !== -1
|
||||
},
|
||||
|
||||
GetSupportedExtensionFromIndex: (index, buf_ptr, buf_len, length_ptr) => {
|
||||
let extensions = this.extensions;
|
||||
if (index < 0 || index >= extensions.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let ext = extensions[index];
|
||||
const n = Math.min(buf_len, ext.length);
|
||||
ext = ext.substring(0, n);
|
||||
this.mem.loadBytes(buf_ptr, buf_len).set(new TextEncoder().encode(ext));
|
||||
|
||||
this.mem.storeInt(length_ptr, n);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
GetExtension: (name_ptr, name_len) => {
|
||||
let name = this.mem.loadString(name_ptr, name_len);
|
||||
this.ctx.getExtension(name);
|
||||
},
|
||||
|
||||
GetError: () => {
|
||||
let err = this.lastError;
|
||||
@@ -628,6 +668,11 @@ class WebGLInterface {
|
||||
this.ctx.generateMipmap(target);
|
||||
},
|
||||
|
||||
GetBufferParameter: (target, pname) => {
|
||||
return this.ctx.getBufferParameter(target, pname);
|
||||
},
|
||||
|
||||
|
||||
GetActiveAttrib: (program, index, size_ptr, type_ptr, name_buf_ptr, name_buf_len, name_len_ptr) => {
|
||||
const info = this.ctx.getActiveAttrib(this.programs[program], index);
|
||||
|
||||
@@ -830,7 +875,8 @@ class WebGLInterface {
|
||||
|
||||
TexImage2D: (target, level, internalformat, width, height, border, format, type, size, data) => {
|
||||
if (data) {
|
||||
this.ctx.texImage2D(target, level, internalformat, width, height, border, format, type, this.mem.loadBytes(data, size));
|
||||
const texelData = this.loadTypedArrayFromTexelType(type, size, data);
|
||||
this.ctx.texImage2D(target, level, internalformat, width, height, border, format, type, texelData);
|
||||
} else {
|
||||
this.ctx.texImage2D(target, level, internalformat, width, height, border, format, type, null);
|
||||
}
|
||||
@@ -842,7 +888,8 @@ class WebGLInterface {
|
||||
this.ctx.texParameteri(target, pname, param);
|
||||
},
|
||||
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));
|
||||
const texelData = this.loadTypedArrayFromTexelType(type, size, data);
|
||||
this.ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, texelData);
|
||||
},
|
||||
|
||||
|
||||
@@ -976,7 +1023,10 @@ class WebGLInterface {
|
||||
},
|
||||
|
||||
/* Texture objects */
|
||||
|
||||
TexStorage2D: (target, levels, internalformat, width, height) => {
|
||||
this.assertWebGL2();
|
||||
this.ctx.texStorage2D(target, levels, internalformat, width, height);
|
||||
},
|
||||
TexStorage3D: (target, levels, internalformat, width, height, depth) => {
|
||||
this.assertWebGL2();
|
||||
this.ctx.texStorage3D(target, levels, internalformat, width, height, depth);
|
||||
@@ -984,14 +1034,16 @@ class WebGLInterface {
|
||||
TexImage3D: (target, level, internalformat, width, height, depth, border, format, type, size, data) => {
|
||||
this.assertWebGL2();
|
||||
if (data) {
|
||||
this.ctx.texImage3D(target, level, internalformat, width, height, depth, border, format, type, this.mem.loadBytes(data, size));
|
||||
const texelData = this.loadTypedArrayFromTexelType(type, size, data);
|
||||
this.ctx.texImage3D(target, level, internalformat, width, height, depth, border, format, type, texelData);
|
||||
} else {
|
||||
this.ctx.texImage3D(target, level, internalformat, width, height, depth, border, format, type, null);
|
||||
}
|
||||
},
|
||||
TexSubImage3D: (target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, size, data) => {
|
||||
this.assertWebGL2();
|
||||
this.ctx.texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, this.mem.loadBytes(data, size));
|
||||
const texelData = this.loadTypedArrayFromTexelType(type, size, data);
|
||||
this.ctx.texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texelData);
|
||||
},
|
||||
CompressedTexImage3D: (target, level, internalformat, width, height, depth, border, imageSize, data) => {
|
||||
this.assertWebGL2();
|
||||
|
||||
16
vendor/wasm/WebGL/webgl.odin
vendored
16
vendor/wasm/WebGL/webgl.odin
vendored
@@ -52,6 +52,7 @@ foreign webgl {
|
||||
GetError :: proc() -> Enum ---
|
||||
|
||||
IsExtensionSupported :: proc(name: string) -> bool ---
|
||||
GetExtension :: proc(name: string) ---
|
||||
|
||||
ActiveTexture :: proc(x: Enum) ---
|
||||
AttachShader :: proc(program: Program, shader: Shader) ---
|
||||
@@ -118,6 +119,7 @@ foreign webgl {
|
||||
|
||||
GenerateMipmap :: proc(target: Enum) ---
|
||||
|
||||
GetBufferParameter :: proc(target, name: Enum) -> int ---
|
||||
GetAttribLocation :: proc(program: Program, name: string) -> i32 ---
|
||||
GetUniformLocation :: proc(program: Program, name: string) -> i32 ---
|
||||
GetVertexAttribOffset :: proc(index: i32, pname: Enum) -> uintptr ---
|
||||
@@ -373,7 +375,21 @@ GetShaderInfoLog :: proc "contextless" (shader: Shader, buf: []byte) -> string {
|
||||
return string(buf[:length])
|
||||
}
|
||||
|
||||
IterateSupportedExtensions :: proc(index: ^int, buf: []byte) -> (string, bool) {
|
||||
foreign webgl {
|
||||
@(link_name="GetSupportedExtensionFromIndex")
|
||||
_GetSupportedExtensionFromIndex :: proc "contextless" (index: int, buf: []byte, length: ^int) -> bool ---
|
||||
}
|
||||
|
||||
length: int
|
||||
if !_GetSupportedExtensionFromIndex(index^, buf[:], &length) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
index^ += 1
|
||||
|
||||
return string(buf[:length]), true
|
||||
}
|
||||
|
||||
BufferDataSlice :: proc "contextless" (target: Enum, slice: $S/[]$E, usage: Enum) {
|
||||
BufferData(target, len(slice)*size_of(E), raw_data(slice), usage)
|
||||
|
||||
1
vendor/wasm/WebGL/webgl2.odin
vendored
1
vendor/wasm/WebGL/webgl2.odin
vendored
@@ -35,6 +35,7 @@ foreign webgl2 {
|
||||
RenderbufferStorageMultisample :: proc(target: Enum, samples: i32, internalformat: Enum, width, height: i32) ---
|
||||
|
||||
/* Texture objects */
|
||||
TexStorage2D :: proc(target: Enum, levels: i32, internalformat: Enum, width, height: i32) ---
|
||||
TexStorage3D :: proc(target: Enum, levels: i32, internalformat: Enum, width, height, depth: i32) ---
|
||||
TexImage3D :: proc(target: Enum, level: i32, internalformat: Enum, width, height, depth: i32, border: i32, format, type: Enum, size: int, data: rawptr) ---
|
||||
TexSubImage3D :: proc(target: Enum, level: i32, xoffset, yoffset, zoffset, width, height, depth: i32, format, type: Enum, size: int, data: rawptr) ---
|
||||
|
||||
Reference in New Issue
Block a user