diff --git a/build.gradle b/build.gradle index 5bfda51..217e079 100644 --- a/build.gradle +++ b/build.gradle @@ -25,6 +25,7 @@ repositories { dependencies { teavm(teavm.libs.jso) teavm(teavm.libs.jsoApis) + compileOnly "org.teavm:teavm-core:0.10.2" // workaround for a few hacks } def folder = "javascript" diff --git a/sp-server/build.gradle b/sp-server/build.gradle index 61cb48d..5af9856 100644 --- a/sp-server/build.gradle +++ b/sp-server/build.gradle @@ -24,6 +24,7 @@ repositories { dependencies { teavm(teavm.libs.jso) teavm(teavm.libs.jsoApis) + compileOnly "org.teavm:teavm-core:0.10.2" // workaround for a few hacks } def folder = "../javascript" diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/IntegratedServer.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/IntegratedServer.java index 1d4e376..51c9468 100644 --- a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/IntegratedServer.java +++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/IntegratedServer.java @@ -71,14 +71,8 @@ public class IntegratedServer { return; } - Uint8Array a = new Uint8Array(buf); - byte[] pkt = new byte[a.getLength()]; - for(int i = 0; i < pkt.length; ++i) { - pkt[i] = (byte) a.get(i); - } - synchronized(messageQueue) { - messageQueue.add(new PKT(channel, pkt)); + messageQueue.add(new PKT(channel, TeaVMUtils.wrapByteArrayBuffer(buf))); } } @@ -720,18 +714,12 @@ public class IntegratedServer { return; } - ArrayBuffer arb = new ArrayBuffer(serialized.length); - Uint8Array ar = new Uint8Array(arb); - ar.set(serialized); - sendWorkerPacket("IPC", arb); + sendWorkerPacket("IPC", TeaVMUtils.unwrapArrayBuffer(serialized)); } public static void sendPlayerPacket(String channel, byte[] buf) { //System.out.println("[Server][SEND][" + channel + "]: " + buf.length); - ArrayBuffer arb = new ArrayBuffer(buf.length); - Uint8Array ar = new Uint8Array(arb); - ar.set(buf); - sendWorkerPacket("NET|" + channel, arb); + sendWorkerPacket("NET|" + channel, TeaVMUtils.unwrapArrayBuffer(buf)); } private static boolean isRunning = false; diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/TeaVMUtils.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/TeaVMUtils.java new file mode 100644 index 0000000..9f1a3d1 --- /dev/null +++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/TeaVMUtils.java @@ -0,0 +1,93 @@ +package net.lax1dude.eaglercraft.sp; + +import org.teavm.backend.javascript.spi.GeneratedBy; +import org.teavm.backend.javascript.spi.InjectedBy; +import org.teavm.jso.typedarrays.ArrayBuffer; +import org.teavm.jso.typedarrays.ArrayBufferView; +import org.teavm.jso.typedarrays.Float32Array; +import org.teavm.jso.typedarrays.Int16Array; +import org.teavm.jso.typedarrays.Int32Array; +import org.teavm.jso.typedarrays.Int8Array; +import org.teavm.jso.typedarrays.Uint8Array; + +public class TeaVMUtils { + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native Int8Array unwrapByteArray(byte[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapArrayBuffer.class) + public static native ArrayBuffer unwrapArrayBuffer(byte[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native ArrayBufferView unwrapArrayBufferView(byte[] buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapTypedArray.class) + public static native byte[] wrapByteArray(Int8Array buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBuffer.class) + public static native byte[] wrapByteArrayBuffer(ArrayBuffer buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class) + public static native byte[] wrapByteArrayBufferView(ArrayBufferView buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapUnsignedTypedArray.class) + public static native Uint8Array unwrapUnsignedByteArray(byte[] buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class) + public static native byte[] wrapUnsignedByteArray(Uint8Array buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native Int32Array unwrapIntArray(int[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapArrayBuffer.class) + public static native ArrayBuffer unwrapArrayBuffer(int[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native ArrayBufferView unwrapArrayBufferView(int[] buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapTypedArray.class) + public static native int[] wrapIntArray(Int32Array buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBuffer.class) + public static native int[] wrapIntArrayBuffer(ArrayBuffer buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class) + public static native int[] wrapIntArrayBufferView(ArrayBufferView buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native Float32Array unwrapFloatArray(float[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapArrayBuffer.class) + public static native ArrayBuffer unwrapArrayBuffer(float[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native ArrayBufferView unwrapArrayBufferView(float[] buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapTypedArray.class) + public static native float[] wrapFloatArray(Float32Array buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBuffer.class) + public static native float[] wrapFloatArrayBuffer(ArrayBuffer buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class) + public static native float[] wrapFloatArrayBufferView(ArrayBufferView buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native Int16Array unwrapShortArray(short[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapArrayBuffer.class) + public static native ArrayBuffer unwrapArrayBuffer(short[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native ArrayBufferView unwrapArrayBufferView(short[] buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapTypedArray.class) + public static native short[] wrapShortArray(Int16Array buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBuffer.class) + public static native short[] wrapShortArrayBuffer(ArrayBuffer buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class) + public static native short[] wrapShortArrayBuffer(ArrayBufferView buf); + +} diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/TeaVMUtilsUnwrapGenerator.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/TeaVMUtilsUnwrapGenerator.java new file mode 100644 index 0000000..6358d93 --- /dev/null +++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/TeaVMUtilsUnwrapGenerator.java @@ -0,0 +1,158 @@ +package net.lax1dude.eaglercraft.sp; + +import org.teavm.backend.javascript.codegen.SourceWriter; +import org.teavm.backend.javascript.spi.Generator; +import org.teavm.backend.javascript.spi.GeneratorContext; +import org.teavm.backend.javascript.spi.Injector; +import org.teavm.backend.javascript.spi.InjectorContext; +import org.teavm.model.MethodReference; + +public class TeaVMUtilsUnwrapGenerator { + + // WARNING: This code uses internal TeaVM APIs that may not have + // been intended for end users of the compiler to program with + + public static class UnwrapArrayBuffer implements Injector { + + @Override + public void generate(InjectorContext context, MethodReference methodRef) { + context.writeExpr(context.getArgument(0)); + context.getWriter().append(".data.buffer"); + } + + } + + public static class UnwrapTypedArray implements Injector { + + @Override + public void generate(InjectorContext context, MethodReference methodRef) { + context.writeExpr(context.getArgument(0)); + context.getWriter().append(".data"); + } + + } + + public static class WrapArrayBuffer implements Generator { + + @Override + public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) { + String parName = context.getParameterName(1); + switch (methodRef.getName()) { + case "wrapByteArrayBuffer": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_bytecls").append(',').ws(); + writer.append("new Int8Array(").append(parName).append("))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapIntArrayBuffer": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_intcls").append(',').ws(); + writer.append("new Int32Array(").append(parName).append("))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapFloatArrayBuffer": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_floatcls").append(',').ws(); + writer.append("new Float32Array(").append(parName).append("))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapShortArrayBuffer": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_shortcls").append(',').ws(); + writer.append("new Int16Array(").append(parName).append("))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + default: + break; + } + } + + } + + public static class WrapArrayBufferView implements Generator { + + @Override + public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) { + String parName = context.getParameterName(1); + switch (methodRef.getName()) { + case "wrapByteArrayBufferView": + case "wrapUnsignedByteArray": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_bytecls").append(',').ws(); + writer.append("new Int8Array(").append(parName).append(".buffer))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapIntArrayBufferView": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_intcls").append(',').ws(); + writer.append("new Int32Array(").append(parName).append(".buffer))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapFloatArrayBufferView": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_floatcls").append(',').ws(); + writer.append("new Float32Array(").append(parName).append(".buffer))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapShortArrayBufferView": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_shortcls").append(',').ws(); + writer.append("new Int16Array(").append(parName).append(".buffer))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + default: + break; + } + } + + } + + public static class WrapTypedArray implements Generator { + + @Override + public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) { + String parName = context.getParameterName(1); + switch (methodRef.getName()) { + case "wrapByteArray": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_shortcls").append(',').ws(); + writer.append(parName).append(")").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapIntArray": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_intcls").append(',').ws(); + writer.append(parName).append(")").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapFloatArray": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_floatcls").append(',').ws(); + writer.append(parName).append(")").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapShortArray": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_shortcls").append(',').ws(); + writer.append(parName).append(")").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + default: + break; + } + } + + } + + public static class UnwrapUnsignedTypedArray implements Injector { + + @Override + public void generate(InjectorContext context, MethodReference methodRef) { + context.getWriter().append("new Uint8Array("); + context.writeExpr(context.getArgument(0)); + context.getWriter().append(".data.buffer)"); + } + + } + +} diff --git a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VirtualFilesystem.java b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VirtualFilesystem.java index 729b4b3..1ad4c9b 100644 --- a/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VirtualFilesystem.java +++ b/sp-server/src/main/java/net/lax1dude/eaglercraft/sp/VirtualFilesystem.java @@ -29,6 +29,7 @@ import org.teavm.jso.indexeddb.IDBRequest; import org.teavm.jso.indexeddb.IDBTransaction; import org.teavm.jso.indexeddb.IDBVersionChangeEvent; import org.teavm.jso.typedarrays.ArrayBuffer; +import org.teavm.jso.typedarrays.Int8Array; import org.teavm.jso.typedarrays.Uint8Array; public class VirtualFilesystem { @@ -129,20 +130,14 @@ public class VirtualFilesystem { exists = false; throw new ArrayIndexOutOfBoundsException("file '" + filePath + "' does not exist"); } - Uint8Array a = new Uint8Array(aa); - this.fileSize = a.getByteLength(); + this.fileSize = aa.getByteLength(); if(cacheEnabled) { - cache = new byte[fileSize]; - for(int i = 0; i < fileSize; ++i) { - cache[i] = (byte)a.get(i); - } + cache = TeaVMUtils.wrapByteArrayBuffer(aa); } - if(a.getLength() < fileOffset + length) { - throw new ArrayIndexOutOfBoundsException("file '" + filePath + "' size was "+a.getLength()+" but user tried to read index "+(fileOffset + length - 1)); - } - for(int i = 0; i < length; ++i) { - array[i + offset] = (byte)a.get(i + fileOffset); + if(fileSize < fileOffset + length) { + throw new ArrayIndexOutOfBoundsException("file '" + filePath + "' size was "+fileSize+" but user tried to read index "+(fileOffset + length - 1)); } + TeaVMUtils.unwrapByteArray(array).set(new Int8Array(aa, fileOffset, length), offset); } } @@ -187,21 +182,16 @@ public class VirtualFilesystem { exists = false; return null; } - Uint8Array a = new Uint8Array(b); - this.fileSize = a.getByteLength(); - byte[] array = new byte[fileSize]; - for(int i = 0; i < a.getByteLength(); ++i) { - array[i] = (byte)a.get(i); - } + this.fileSize = b.getByteLength(); if(cacheEnabled) { if(copy) { cache = new byte[fileSize]; - System.arraycopy(b, 0, cache, 0, cache.length); + TeaVMUtils.unwrapByteArray(cache).set(new Int8Array(b)); }else { - cache = array; + cache = TeaVMUtils.wrapByteArrayBuffer(b); } } - return array; + return TeaVMUtils.wrapByteArrayBuffer(b); } } @@ -228,10 +218,8 @@ public class VirtualFilesystem { cache = copz; return sync(); }else { - ArrayBuffer a = new ArrayBuffer(bytes.length); - Uint8Array ar = new Uint8Array(a); - ar.set(bytes); - boolean s = AsyncHandlers.writeWholeFile(virtualFilesystem.indexeddb, filePath, a).bool; + boolean s = AsyncHandlers.writeWholeFile(virtualFilesystem.indexeddb, filePath, + TeaVMUtils.unwrapArrayBuffer(bytes)).bool; hasBeenAccessed = true; exists = exists || s; return s; @@ -241,10 +229,8 @@ public class VirtualFilesystem { public boolean sync() { if(cacheEnabled && cache != null && !hasBeenDeleted) { cacheHit = SysUtil.steadyTimeMillis(); - ArrayBuffer a = new ArrayBuffer(cache.length); - Uint8Array ar = new Uint8Array(a); - ar.set(cache); - boolean tryWrite = AsyncHandlers.writeWholeFile(virtualFilesystem.indexeddb, filePath, a).bool; + boolean tryWrite = AsyncHandlers.writeWholeFile(virtualFilesystem.indexeddb, filePath, + TeaVMUtils.unwrapArrayBuffer(cache)).bool; hasBeenAccessed = true; exists = exists || tryWrite; return tryWrite; diff --git a/src/teavm/java/net/lax1dude/eaglercraft/adapter/DetectAnisotropicGlitch.java b/src/teavm/java/net/lax1dude/eaglercraft/adapter/DetectAnisotropicGlitch.java index db51e74..3f5c968 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/adapter/DetectAnisotropicGlitch.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/adapter/DetectAnisotropicGlitch.java @@ -4,10 +4,10 @@ import static net.lax1dude.eaglercraft.adapter.teavm.WebGL2RenderingContext.*; import org.teavm.jso.browser.Window; import org.teavm.jso.dom.html.HTMLCanvasElement; -import org.teavm.jso.typedarrays.Float32Array; import org.teavm.jso.typedarrays.Uint8Array; import net.lax1dude.eaglercraft.Client; +import net.lax1dude.eaglercraft.adapter.teavm.TeaVMUtils; import net.lax1dude.eaglercraft.adapter.teavm.WebGL2RenderingContext; import net.lax1dude.eaglercraft.adapter.teavm.WebGLVertexArray; @@ -127,9 +127,6 @@ public class DetectAnisotropicGlitch { x0, x0, x0, x1 }; - Uint8Array pixels = new Uint8Array(pixelsData.length); - pixels.set(pixelsData); - WebGLTexture tex = ctx.createTexture(); ctx.bindTexture(TEXTURE_2D, tex); @@ -140,7 +137,7 @@ public class DetectAnisotropicGlitch { ctx.texParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, NEAREST); ctx.texParameterf(TEXTURE_2D, TEXTURE_MAX_ANISOTROPY_EXT, 16.0f); - ctx.texImage2D(TEXTURE_2D, 0, RGBA, 4, 3, 0, RGBA, UNSIGNED_BYTE, pixels); + ctx.texImage2D(TEXTURE_2D, 0, RGBA, 4, 3, 0, RGBA, UNSIGNED_BYTE, TeaVMUtils.unwrapUnsignedByteArray(pixelsData)); ctx.generateMipmap(TEXTURE_2D); float[] vertsData = new float[] { @@ -152,13 +149,10 @@ public class DetectAnisotropicGlitch { 0.0f, 1.0f }; - Float32Array verts = new Float32Array(vertsData.length); - verts.set(vertsData); - WebGLBuffer buf = ctx.createBuffer(); ctx.bindBuffer(ARRAY_BUFFER, buf); - ctx.bufferData(ARRAY_BUFFER, verts, STATIC_DRAW); + ctx.bufferData(ARRAY_BUFFER, TeaVMUtils.unwrapFloatArray(vertsData), STATIC_DRAW); WebGLVertexArray arr = ctx.createVertexArray(); diff --git a/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java b/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java index 75505dd..a6b8e77 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java @@ -107,11 +107,13 @@ import net.lax1dude.eaglercraft.RelayServerSocket; import net.lax1dude.eaglercraft.RelayWorldsQuery; import net.lax1dude.eaglercraft.ServerQuery; import net.lax1dude.eaglercraft.Voice; +import net.lax1dude.eaglercraft.adapter.teavm.BufferConverter; import net.lax1dude.eaglercraft.adapter.teavm.EaglercraftLANClient; import net.lax1dude.eaglercraft.adapter.teavm.EaglercraftLANServer; import net.lax1dude.eaglercraft.adapter.teavm.EaglercraftVoiceClient; import net.lax1dude.eaglercraft.adapter.teavm.MessageChannel; import net.lax1dude.eaglercraft.adapter.teavm.SelfDefence; +import net.lax1dude.eaglercraft.adapter.teavm.TeaVMUtils; import net.lax1dude.eaglercraft.adapter.teavm.WebGL2RenderingContext; import net.lax1dude.eaglercraft.adapter.teavm.WebGLQuery; import net.lax1dude.eaglercraft.adapter.teavm.WebGLVertexArray; @@ -182,11 +184,7 @@ public class EaglerAdapterImpl2 { @Override public void stateChanged() { if(request.getReadyState() == XMLHttpRequest.DONE) { - Uint8Array bl = new Uint8Array((ArrayBuffer)request.getResponse()); - loadedPackage = new byte[bl.getByteLength()]; - for(int i = 0; i < loadedPackage.length; ++i) { - loadedPackage[i] = (byte) bl.get(i); - } + loadedPackage = TeaVMUtils.wrapByteArrayBuffer((ArrayBuffer)request.getResponse()); cb.complete("yee"); } } @@ -209,12 +207,7 @@ public class EaglerAdapterImpl2 { @Override public void stateChanged() { if(request.getReadyState() == XMLHttpRequest.DONE) { - Uint8Array bl = new Uint8Array((ArrayBuffer)request.getResponse()); - byte[] res = new byte[bl.getByteLength()]; - for(int i = 0; i < res.length; ++i) { - res[i] = (byte) bl.get(i); - } - cb.complete(res); + cb.complete(TeaVMUtils.wrapByteArrayBuffer((ArrayBuffer)request.getResponse())); } } }); @@ -763,19 +756,8 @@ public class EaglerAdapterImpl2 { public static final void _wglFlush() { //webgl.flush(); } - private static Uint8Array uploadBuffer = new Uint8Array(new ArrayBuffer(4 * 1024 * 1024)); public static final void _wglTexImage2D(int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, ByteBuffer p9) { - if(p9 == null) { - webgl.texImage2D(p1, p2, p3, p4, p5, p6, p7, p8, null); - }else { - int len = p9.remaining(); - Uint8Array uploadBuffer1 = uploadBuffer; - for(int i = 0; i < len; ++i) { - uploadBuffer1.set(i, (short) ((int)p9.get() & 0xff)); - } - Uint8Array data = new Uint8Array(uploadBuffer.getBuffer(), 0, len); - webgl.texImage2D(p1, p2, p3, p4, p5, p6, p7, p8, data); - } + webgl.texImage2D(p1, p2, p3, p4, p5, p6, p7, p8, p9 != null ? BufferConverter.convertByteBufferUnsigned(p9) : null); } public static final void _wglBlendFunc(int p1, int p2) { webgl.blendFunc(p1, p2); @@ -805,22 +787,10 @@ public class EaglerAdapterImpl2 { webgl.texParameterf(p1, p2, p3); } public static final void _wglTexImage2D(int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, IntBuffer p9) { - int len = p9.remaining(); - DataView deevis = new DataView(uploadBuffer.getBuffer()); - for(int i = 0; i < len; ++i) { - deevis.setInt32(i * 4, p9.get(), true); - } - Uint8Array data = new Uint8Array(uploadBuffer.getBuffer(), 0, len*4); - webgl.texImage2D(p1, p2, p3, p4, p5, p6, p7, p8, data); + webgl.texImage2D(p1, p2, p3, p4, p5, p6, p7, p8, p9 != null ? BufferConverter.convertIntBufferUnsigned(p9) : null); } public static final void _wglTexSubImage2D(int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, IntBuffer p9) { - int len = p9.remaining(); - DataView deevis = new DataView(uploadBuffer.getBuffer()); - for(int i = 0; i < len; ++i) { - deevis.setInt32(i * 4, p9.get(), true); - } - Uint8Array data = new Uint8Array(uploadBuffer.getBuffer(), 0, len*4); - webgl.texSubImage2D(p1, p2, p3, p4, p5, p6, p7, p8, data); + webgl.texSubImage2D(p1, p2, p3, p4, p5, p6, p7, p8, p9 != null ? BufferConverter.convertIntBufferUnsigned(p9) : null); } public static final void _wglDeleteTextures(TextureGL p1) { webgl.deleteTexture(p1.obj); @@ -835,13 +805,7 @@ public class EaglerAdapterImpl2 { return new TextureGL(webgl.createTexture()); } public static final void _wglTexSubImage2D(int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, ByteBuffer p9) { - int len = p9.remaining(); - for(int i = 0; i < len; ++i) { - //uploadBuffer.set(swapEndian ? ((i >> 2) + (3 - (i & 3))) : i, (short) ((int)p9.get() & 0xff)); - uploadBuffer.set(i, (short) ((int)p9.get() & 0xff)); - } - Uint8Array data = new Uint8Array(uploadBuffer.getBuffer(), 0, len); - webgl.texSubImage2D(p1, p2, p3, p4, p5, p6, p7, p8, data); + webgl.texSubImage2D(p1, p2, p3, p4, p5, p6, p7, p8, p9 != null ? BufferConverter.convertByteBufferUnsigned(p9) : null); } public static final void _wglActiveTexture(int p1) { webgl.activeTexture(p1); @@ -895,22 +859,10 @@ public class EaglerAdapterImpl2 { webgl.bindBuffer(p1, p2 == null ? null : p2.obj); } public static final void _wglBufferData0(int p1, IntBuffer p2, int p3) { - int len = p2.remaining(); - DataView deevis = new DataView(uploadBuffer.getBuffer()); - for(int i = 0; i < len; ++i) { - deevis.setInt32(i * 4, p2.get(), true); - } - Uint8Array data = new Uint8Array(uploadBuffer.getBuffer(), 0, len*4); - webgl.bufferData(p1, data, p3); + webgl.bufferData(p1, p2 != null ? BufferConverter.convertIntBufferUnsigned(p2) : null, p3); } public static final void _wglBufferSubData0(int p1, int p2, IntBuffer p3) { - int len = p3.remaining(); - DataView deevis = new DataView(uploadBuffer.getBuffer()); - for(int i = 0; i < len; ++i) { - deevis.setInt32(i * 4, p3.get(), true); - } - Uint8Array data = new Uint8Array(uploadBuffer.getBuffer(), 0, len*4); - webgl.bufferSubData(p1, p2, data); + webgl.bufferSubData(p1, p2, p3 != null ? BufferConverter.convertIntBufferUnsigned(p3) : null); } public static final void _wglBufferData(int p1, Object p2, int p3) { webgl.bufferData(p1, (Int32Array)p2, p3); @@ -961,20 +913,14 @@ public class EaglerAdapterImpl2 { public static final void _wglUniform4i(UniformGL p1, int p2, int p3, int p4, int p5) { if(p1 != null) webgl.uniform4i(p1.obj, p2, p3, p4, p5); } - private static Float32Array mat2 = new Float32Array(4); - private static Float32Array mat3 = new Float32Array(9); - private static Float32Array mat4 = new Float32Array(16); public static final void _wglUniformMat2fv(UniformGL p1, float[] mat) { - mat2.set(mat); - if(p1 != null) webgl.uniformMatrix2fv(p1.obj, false, mat2); + if(p1 != null) webgl.uniformMatrix2fv(p1.obj, false, TeaVMUtils.unwrapFloatArray(mat)); } public static final void _wglUniformMat3fv(UniformGL p1, float[] mat) { - mat3.set(mat); - if(p1 != null) webgl.uniformMatrix3fv(p1.obj, false, mat3); + if(p1 != null) webgl.uniformMatrix3fv(p1.obj, false, TeaVMUtils.unwrapFloatArray(mat)); } public static final void _wglUniformMat4fv(UniformGL p1, float[] mat) { - mat4.set(mat); - if(p1 != null) webgl.uniformMatrix4fv(p1.obj, false, mat4); + if(p1 != null) webgl.uniformMatrix4fv(p1.obj, false, TeaVMUtils.unwrapFloatArray(mat)); } private static int currentProgram = -1; public static final void _wglUseProgram(ProgramGL p1) { @@ -1094,9 +1040,7 @@ public class EaglerAdapterImpl2 { private static native void freeDataURL(String url); public static final EaglerImage loadPNG(byte[] data) { - ArrayBuffer arr = new ArrayBuffer(data.length); - (new Uint8Array(arr)).set(data); - return loadPNG0(arr); + return loadPNG0(TeaVMUtils.unwrapArrayBuffer(data)); } @JSBody(params = { "cccc", "ennn" }, script = "cccc.imageSmoothingEnabled = ennn;") @@ -2124,12 +2068,7 @@ public class EaglerAdapterImpl2 { sock.close(); return; } - Uint8Array a = new Uint8Array(evt.getDataAsArray()); - byte[] b = new byte[a.getByteLength()]; - for(int i = 0; i < b.length; ++i) { - b[i] = (byte) (a.get(i) & 0xFF); - } - readPackets.add(b); + readPackets.add(TeaVMUtils.wrapByteArrayBuffer(evt.getDataAsArray())); } }); } @@ -2162,9 +2101,7 @@ public class EaglerAdapterImpl2 { private static native void nativeBinarySend(WebSocket sock, ArrayBuffer buffer); public static final void writePacket(byte[] packet) { if(sock != null && !sockIsConnecting) { - Uint8Array arr = new Uint8Array(packet.length); - arr.set(packet); - nativeBinarySend(sock, arr.getBuffer()); + nativeBinarySend(sock, TeaVMUtils.unwrapArrayBuffer(packet)); } } public static final byte[] readPacket() { @@ -2221,12 +2158,7 @@ public class EaglerAdapterImpl2 { public static final byte[] getFileChooserResult() { ArrayBuffer b = getFileChooserResult0(); if(b == null) return null; - Uint8Array array = new Uint8Array(b); - byte[] ret = new byte[array.getByteLength()]; - for(int i = 0; i < ret.length; ++i) { - ret[i] = (byte) array.get(i); - } - return ret; + return TeaVMUtils.wrapByteArrayBuffer(b); } public static final void clearFileChooserResult() { @@ -3049,13 +2981,7 @@ public class EaglerAdapterImpl2 { return; } - Uint8Array a = new Uint8Array(buf); - byte[] pkt = new byte[a.getLength()]; - for(int i = 0; i < pkt.length; ++i) { - pkt[i] = (byte) a.get(i); - } - - existingQueue.add(new PKT(channel, pkt)); + existingQueue.add(new PKT(channel, TeaVMUtils.wrapByteArrayBuffer(buf))); } } @@ -3105,10 +3031,7 @@ public class EaglerAdapterImpl2 { } public static final void sendToIntegratedServer(String channel, byte[] pkt) { - ArrayBuffer arb = new ArrayBuffer(pkt.length); - Uint8Array ar = new Uint8Array(arb); - ar.set(pkt); - sendWorkerPacket(server, channel, arb); + sendWorkerPacket(server, channel, TeaVMUtils.unwrapArrayBuffer(pkt)); //System.out.println("[Client][WRITE][" + channel + "]: " + pkt.length); } @@ -3152,9 +3075,7 @@ public class EaglerAdapterImpl2 { private static final native void downloadBytesImpl(String str, ArrayBuffer buf); public static final void downloadBytes(String str, byte[] dat) { - ArrayBuffer d = new ArrayBuffer(dat.length); - (new Uint8Array(d)).set(dat); - downloadBytesImpl(str, d); + downloadBytesImpl(str, TeaVMUtils.unwrapArrayBuffer(dat)); } @JSFunctor @@ -3281,12 +3202,7 @@ public class EaglerAdapterImpl2 { System.err.println("Query response could not be parsed: " + t.toString()); } }else { - Uint8Array a = new Uint8Array(evt.getDataAsArray()); - byte[] b = new byte[a.getByteLength()]; - for(int i = 0; i < b.length; ++i) { - b[i] = (byte) (a.get(i) & 0xFF); - } - queryResponsesBytes.add(b); + queryResponsesBytes.add(TeaVMUtils.wrapByteArrayBuffer(evt.getDataAsArray())); } } }); @@ -3415,12 +3331,6 @@ public class EaglerAdapterImpl2 { return !isLittleEndian; } - private static final ArrayBuffer convertToArrayBuffer(byte[] arr) { - Uint8Array buf = new Uint8Array(arr.length); - buf.set(arr); - return buf.getBuffer(); - } - private static final Map relayQueryLimited = new HashMap<>(); private static final Map relayQueryBlocked = new HashMap<>(); @@ -3468,7 +3378,7 @@ public class EaglerAdapterImpl2 { public void handleEvent(Event evt) { try { connectionPingStart = steadyTimeMillis(); - nativeBinarySend(sock, convertToArrayBuffer( + nativeBinarySend(sock, TeaVMUtils.unwrapArrayBuffer( IPacket.writePacket(new IPacket00Handshake(0x03, IntegratedServer.preferredRelayVersion, "")) )); } catch (IOException e) { @@ -3483,11 +3393,7 @@ public class EaglerAdapterImpl2 { public void handleEvent(MessageEvent evt) { if(evt.getData() != null && !isString(evt.getData())) { hasRecievedAnyData = true; - Uint8Array buf = new Uint8Array(evt.getDataAsArray()); - byte[] arr = new byte[buf.getLength()]; - for(int i = 0; i < arr.length; ++i) { - arr[i] = (byte)buf.get(i); - } + byte[] arr = TeaVMUtils.wrapByteArrayBuffer(evt.getDataAsArray()); if(arr.length == 2 && arr[0] == (byte)0xFC) { long millis = steadyTimeMillis(); if(arr[1] == (byte)0x00 || arr[1] == (byte)0x01) { @@ -3731,7 +3637,7 @@ public class EaglerAdapterImpl2 { @Override public void handleEvent(Event evt) { try { - nativeBinarySend(sock, convertToArrayBuffer( + nativeBinarySend(sock, TeaVMUtils.unwrapArrayBuffer( IPacket.writePacket(new IPacket00Handshake(0x04, IntegratedServer.preferredRelayVersion, "")) )); } catch (IOException e) { @@ -3747,11 +3653,7 @@ public class EaglerAdapterImpl2 { public void handleEvent(MessageEvent evt) { if(evt.getData() != null && !isString(evt.getData())) { hasRecievedAnyData = true; - Uint8Array buf = new Uint8Array(evt.getDataAsArray()); - byte[] arr = new byte[buf.getLength()]; - for(int i = 0; i < arr.length; ++i) { - arr[i] = (byte)buf.get(i); - } + byte[] arr = TeaVMUtils.wrapByteArrayBuffer(evt.getDataAsArray()); if(arr.length == 2 && arr[0] == (byte)0xFC) { long millis = steadyTimeMillis(); if(arr[1] == (byte)0x00 || arr[1] == (byte)0x01) { @@ -3966,11 +3868,7 @@ public class EaglerAdapterImpl2 { public void handleEvent(MessageEvent evt) { if(evt.getData() != null && !isString(evt.getData())) { hasRecievedAnyData = true; - Uint8Array buf = new Uint8Array(evt.getDataAsArray()); - byte[] arr = new byte[buf.getLength()]; - for(int i = 0; i < arr.length; ++i) { - arr[i] = (byte)buf.get(i); - } + byte[] arr = TeaVMUtils.wrapByteArrayBuffer(evt.getDataAsArray()); try { packets.add(IPacket.readPacket(new DataInputStream(new ByteArrayInputStream(arr)))); } catch (IOException e) { @@ -4044,7 +3942,7 @@ public class EaglerAdapterImpl2 { @Override public void writePacket(IPacket pkt) { try { - nativeBinarySend(sock, convertToArrayBuffer(IPacket.writePacket(pkt))); + nativeBinarySend(sock, TeaVMUtils.unwrapArrayBuffer(IPacket.writePacket(pkt))); } catch (Throwable e) { System.err.println("Relay connection error: " + e.toString()); e.printStackTrace(); @@ -4192,7 +4090,7 @@ public class EaglerAdapterImpl2 { } public static final void clientLANSendPacket(byte[] pkt) { - rtcLANClient.sendPacketToServer(convertToArrayBuffer(pkt)); + rtcLANClient.sendPacketToServer(TeaVMUtils.unwrapArrayBuffer(pkt)); } public static final byte[] clientLANReadPacket() { @@ -4224,12 +4122,7 @@ public class EaglerAdapterImpl2 { rtcLANClient.setRemotePacketHandler(new EaglercraftLANClient.RemotePacketHandler() { @Override public void call(ArrayBuffer buffer) { - Uint8Array array = new Uint8Array(buffer); - byte[] ret = new byte[array.getByteLength()]; - for(int i = 0; i < ret.length; ++i) { - ret[i] = (byte) array.get(i); - } - clientLANPacketBuffer.add(ret); + clientLANPacketBuffer.add(TeaVMUtils.wrapByteArrayBuffer(buffer)); } }); rtcLANClient.setRemoteDisconnectHandler(new EaglercraftLANClient.ClientSignalHandler() { @@ -4334,12 +4227,7 @@ public class EaglerAdapterImpl2 { rtcLANServer.setRemoteClientPacketHandler(new EaglercraftLANServer.PeerPacketHandler() { @Override public void call(String peerId, ArrayBuffer buffer) { - Uint8Array array = new Uint8Array(buffer); - byte[] ret = new byte[array.getByteLength()]; - for(int i = 0; i < ret.length; ++i) { - ret[i] = (byte) array.get(i); - } - serverLANEventBuffer.add(new LANPeerEvent.LANPeerPacketEvent(peerId, ret)); + serverLANEventBuffer.add(new LANPeerEvent.LANPeerPacketEvent(peerId, TeaVMUtils.wrapByteArrayBuffer(buffer))); } }); rtcLANServer.setRemoteClientDisconnectHandler(new EaglercraftLANServer.ClientSignalHandler() { @@ -4379,17 +4267,13 @@ public class EaglerAdapterImpl2 { byte[] fragData = new byte[((i + fragmentSize > data.length) ? (data.length % fragmentSize) : fragmentSize) + 1]; System.arraycopy(data, i, fragData, 1, fragData.length - 1); fragData[0] = (i + fragmentSize < data.length) ? (byte) 1 : (byte) 0; - ArrayBuffer arr = new ArrayBuffer(fragData.length); - (new Uint8Array(arr)).set(fragData); - rtcLANServer.sendPacketToRemoteClient(peer, arr); + rtcLANServer.sendPacketToRemoteClient(peer, TeaVMUtils.unwrapArrayBuffer(fragData)); } } else { byte[] sendData = new byte[data.length + 1]; sendData[0] = 0; System.arraycopy(data, 0, sendData, 1, data.length); - ArrayBuffer arr = new ArrayBuffer(sendData.length); - (new Uint8Array(arr)).set(sendData); - rtcLANServer.sendPacketToRemoteClient(peer, arr); + rtcLANServer.sendPacketToRemoteClient(peer, TeaVMUtils.unwrapArrayBuffer(sendData)); } } diff --git a/src/teavm/java/net/lax1dude/eaglercraft/adapter/SimpleStorage.java b/src/teavm/java/net/lax1dude/eaglercraft/adapter/SimpleStorage.java index 7ecd0a4..3974610 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/adapter/SimpleStorage.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/adapter/SimpleStorage.java @@ -10,7 +10,8 @@ import org.teavm.jso.indexeddb.IDBObjectStore; import org.teavm.jso.indexeddb.IDBOpenDBRequest; import org.teavm.jso.indexeddb.IDBRequest; import org.teavm.jso.typedarrays.ArrayBuffer; -import org.teavm.jso.typedarrays.Uint8Array; + +import net.lax1dude.eaglercraft.adapter.teavm.TeaVMUtils; public class SimpleStorage { private static IDBDatabase database; @@ -50,12 +51,7 @@ public class SimpleStorage { } IDBGetRequest request = getStore().get(JSString.valueOf(key)); request.setOnSuccess(() -> { - Uint8Array a = new Uint8Array((ArrayBuffer) request.getResult().cast()); - byte[] b = new byte[a.getByteLength()]; - for(int i = 0; i < b.length; ++i) { - b[i] = (byte) (a.get(i) & 0xFF); - } - cb.complete(b); + cb.complete(TeaVMUtils.wrapByteArrayBuffer((ArrayBuffer) request.getResult())); }); request.setOnError(() -> { cb.complete(null); @@ -118,8 +114,7 @@ public class SimpleStorage { }); }); } else { - ArrayBuffer arr = new ArrayBuffer(value.length); - (new Uint8Array(arr)).set(value); + ArrayBuffer arr = TeaVMUtils.unwrapArrayBuffer(value); IDBRequest request2 = getStore().put(arr, JSString.valueOf(key)); request2.setOnSuccess(() -> { IDBGetRequest request3 = getStore().get(JSString.valueOf("__LIST__")); diff --git a/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/BufferConverter.java b/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/BufferConverter.java index 17a8300..879d594 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/BufferConverter.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/BufferConverter.java @@ -1,34 +1,59 @@ package net.lax1dude.eaglercraft.adapter.teavm; import java.nio.ByteBuffer; -import java.nio.FloatBuffer; import java.nio.IntBuffer; -import java.nio.ShortBuffer; + +import org.teavm.jso.typedarrays.Int8Array; +import org.teavm.jso.typedarrays.Uint8Array; public class BufferConverter { - public static final byte[] convertByteBuffer(ByteBuffer b) { - byte[] ret = new byte[b.limit() - b.position()]; - b.get(ret); - return ret; + public static final Int8Array convertByteBuffer(ByteBuffer b) { + if(b.hasArray()) { + int p = b.position(); + int l = b.remaining(); + return new Int8Array(TeaVMUtils.unwrapArrayBuffer(b.array()), p, l); + }else { + byte[] ret = new byte[b.remaining()]; + b.get(ret); + return TeaVMUtils.unwrapByteArray(ret); + } } - public static final short[] convertShortBuffer(ShortBuffer b) { - short[] ret = new short[b.limit() - b.position()]; - b.get(ret); - return ret; + public static final Uint8Array convertByteBufferUnsigned(ByteBuffer b) { + if(b.hasArray()) { + int p = b.position(); + int l = b.remaining(); + return new Uint8Array(TeaVMUtils.unwrapArrayBuffer(b.array()), p, l); + }else { + byte[] ret = new byte[b.remaining()]; + b.get(ret); + return TeaVMUtils.unwrapUnsignedByteArray(ret); + } } - public static final int[] convertIntBuffer(IntBuffer b) { - int[] ret = new int[b.limit() - b.position()]; - b.get(ret); - return ret; + public static final Int8Array convertIntBuffer(IntBuffer b) { + if(b.hasArray()) { + int p = b.position() << 2; + int l = b.remaining() << 2; + return new Int8Array(TeaVMUtils.unwrapArrayBuffer(b.array()), p, l); + }else { + int[] ret = new int[b.remaining()]; + b.get(ret); + return new Int8Array(TeaVMUtils.unwrapArrayBuffer(ret)); + } } - public static final float[] convertFloatBuffer(FloatBuffer b) { - float[] ret = new float[b.limit() - b.position()]; - b.get(ret); - return ret; + public static final Uint8Array convertIntBufferUnsigned(IntBuffer b) { + if(b.hasArray()) { + int p = b.position() << 2; + int l = b.remaining() << 2; + return new Uint8Array(TeaVMUtils.unwrapArrayBuffer(b.array()), p, l); + }else { + int[] ret = new int[b.remaining()]; + b.get(ret); + return new Uint8Array(TeaVMUtils.unwrapArrayBuffer(ret)); + } } } diff --git a/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/TeaVMUtils.java b/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/TeaVMUtils.java new file mode 100644 index 0000000..5fb0005 --- /dev/null +++ b/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/TeaVMUtils.java @@ -0,0 +1,95 @@ +package net.lax1dude.eaglercraft.adapter.teavm; + +import org.teavm.backend.javascript.spi.GeneratedBy; +import org.teavm.backend.javascript.spi.InjectedBy; +import org.teavm.jso.typedarrays.ArrayBuffer; +import org.teavm.jso.typedarrays.ArrayBufferView; +import org.teavm.jso.typedarrays.Float32Array; +import org.teavm.jso.typedarrays.Int16Array; +import org.teavm.jso.typedarrays.Int32Array; +import org.teavm.jso.typedarrays.Int8Array; +import org.teavm.jso.typedarrays.Uint8Array; + +import net.lax1dude.eaglercraft.adapter.teavm.generators.TeaVMUtilsUnwrapGenerator; + +public class TeaVMUtils { + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native Int8Array unwrapByteArray(byte[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapArrayBuffer.class) + public static native ArrayBuffer unwrapArrayBuffer(byte[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native ArrayBufferView unwrapArrayBufferView(byte[] buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapTypedArray.class) + public static native byte[] wrapByteArray(Int8Array buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBuffer.class) + public static native byte[] wrapByteArrayBuffer(ArrayBuffer buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class) + public static native byte[] wrapByteArrayBufferView(ArrayBufferView buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapUnsignedTypedArray.class) + public static native Uint8Array unwrapUnsignedByteArray(byte[] buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class) + public static native byte[] wrapUnsignedByteArray(Uint8Array buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native Int32Array unwrapIntArray(int[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapArrayBuffer.class) + public static native ArrayBuffer unwrapArrayBuffer(int[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native ArrayBufferView unwrapArrayBufferView(int[] buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapTypedArray.class) + public static native int[] wrapIntArray(Int32Array buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBuffer.class) + public static native int[] wrapIntArrayBuffer(ArrayBuffer buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class) + public static native int[] wrapIntArrayBufferView(ArrayBufferView buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native Float32Array unwrapFloatArray(float[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapArrayBuffer.class) + public static native ArrayBuffer unwrapArrayBuffer(float[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native ArrayBufferView unwrapArrayBufferView(float[] buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapTypedArray.class) + public static native float[] wrapFloatArray(Float32Array buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBuffer.class) + public static native float[] wrapFloatArrayBuffer(ArrayBuffer buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class) + public static native float[] wrapFloatArrayBufferView(ArrayBufferView buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native Int16Array unwrapShortArray(short[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapArrayBuffer.class) + public static native ArrayBuffer unwrapArrayBuffer(short[] buf); + + @InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapTypedArray.class) + public static native ArrayBufferView unwrapArrayBufferView(short[] buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapTypedArray.class) + public static native short[] wrapShortArray(Int16Array buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBuffer.class) + public static native short[] wrapShortArrayBuffer(ArrayBuffer buf); + + @GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class) + public static native short[] wrapShortArrayBuffer(ArrayBufferView buf); + +} diff --git a/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/generators/TeaVMUtilsUnwrapGenerator.java b/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/generators/TeaVMUtilsUnwrapGenerator.java new file mode 100644 index 0000000..c30672f --- /dev/null +++ b/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/generators/TeaVMUtilsUnwrapGenerator.java @@ -0,0 +1,158 @@ +package net.lax1dude.eaglercraft.adapter.teavm.generators; + +import org.teavm.backend.javascript.codegen.SourceWriter; +import org.teavm.backend.javascript.spi.Generator; +import org.teavm.backend.javascript.spi.GeneratorContext; +import org.teavm.backend.javascript.spi.Injector; +import org.teavm.backend.javascript.spi.InjectorContext; +import org.teavm.model.MethodReference; + +public class TeaVMUtilsUnwrapGenerator { + + // WARNING: This code uses internal TeaVM APIs that may not have + // been intended for end users of the compiler to program with + + public static class UnwrapArrayBuffer implements Injector { + + @Override + public void generate(InjectorContext context, MethodReference methodRef) { + context.writeExpr(context.getArgument(0)); + context.getWriter().append(".data.buffer"); + } + + } + + public static class UnwrapTypedArray implements Injector { + + @Override + public void generate(InjectorContext context, MethodReference methodRef) { + context.writeExpr(context.getArgument(0)); + context.getWriter().append(".data"); + } + + } + + public static class WrapArrayBuffer implements Generator { + + @Override + public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) { + String parName = context.getParameterName(1); + switch (methodRef.getName()) { + case "wrapByteArrayBuffer": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_bytecls").append(',').ws(); + writer.append("new Int8Array(").append(parName).append("))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapIntArrayBuffer": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_intcls").append(',').ws(); + writer.append("new Int32Array(").append(parName).append("))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapFloatArrayBuffer": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_floatcls").append(',').ws(); + writer.append("new Float32Array(").append(parName).append("))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapShortArrayBuffer": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_shortcls").append(',').ws(); + writer.append("new Int16Array(").append(parName).append("))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + default: + break; + } + } + + } + + public static class WrapArrayBufferView implements Generator { + + @Override + public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) { + String parName = context.getParameterName(1); + switch (methodRef.getName()) { + case "wrapByteArrayBufferView": + case "wrapUnsignedByteArray": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_bytecls").append(',').ws(); + writer.append("new Int8Array(").append(parName).append(".buffer))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapIntArrayBufferView": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_intcls").append(',').ws(); + writer.append("new Int32Array(").append(parName).append(".buffer))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapFloatArrayBufferView": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_floatcls").append(',').ws(); + writer.append("new Float32Array(").append(parName).append(".buffer))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapShortArrayBufferView": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_shortcls").append(',').ws(); + writer.append("new Int16Array(").append(parName).append(".buffer))").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + default: + break; + } + } + + } + + public static class WrapTypedArray implements Generator { + + @Override + public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) { + String parName = context.getParameterName(1); + switch (methodRef.getName()) { + case "wrapByteArray": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_shortcls").append(',').ws(); + writer.append(parName).append(")").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapIntArray": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_intcls").append(',').ws(); + writer.append(parName).append(")").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapFloatArray": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_floatcls").append(',').ws(); + writer.append(parName).append(")").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + case "wrapShortArray": + writer.append("return ").append(parName).ws().append('?').ws(); + writer.appendFunction("$rt_wrapArray").append('(').appendFunction("$rt_shortcls").append(',').ws(); + writer.append(parName).append(")").ws(); + writer.append(':').ws().append("null;").softNewLine(); + break; + default: + break; + } + } + + } + + public static class UnwrapUnsignedTypedArray implements Injector { + + @Override + public void generate(InjectorContext context, MethodReference methodRef) { + context.getWriter().append("new Uint8Array("); + context.writeExpr(context.getArgument(0)); + context.getWriter().append(".data.buffer)"); + } + + } + +}