Update #53 - Improved FPS, reduced WebGL context loss crashes

This commit is contained in:
lax1dude
2025-07-06 12:31:55 -07:00
parent f3281c037f
commit 332a7bb11f
53 changed files with 568 additions and 383 deletions

View File

@ -1 +1 @@
u52
u53

View File

@ -598,7 +598,7 @@
~ GlStateManager.viewport(0, 0, this.displayWidth, this.displayHeight);
~ GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
> DELETE 2 @ 2 : 4
> DELETE 1 @ 1 : 4
> DELETE 5 @ 5 : 6

View File

@ -5,13 +5,12 @@
# Version: 1.0
# Author: lax1dude
> INSERT 2 : 7 @ 2
> INSERT 2 : 6 @ 2
+ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
+ import net.lax1dude.eaglercraft.v1_8.opengl.VertexFormat;
+ import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer;
+ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager;
+ import net.lax1dude.eaglercraft.v1_8.opengl.ext.dynamiclights.DynamicLightsStateManager;
> DELETE 4 @ 4 : 5

View File

@ -89,7 +89,17 @@
~ stackTrace.append("\tat ").append(s).append('\n');
~ });
> CHANGE 1 : 2 @ 1 : 12
> CHANGE 1 : 8 @ 1 : 9
~ Throwable t = this.cause.getCause();
~ while (t != null) {
~ stackTrace.append("Caused by: " + t.toString()).append('\n');
~ EagRuntime.getStackTrace(t, (s) -> {
~ stackTrace.append("\tat ").append(s).append('\n');
~ });
~ t = t.getCause();
> CHANGE 2 : 3 @ 2 : 3
~ return stackTrace.toString();

View File

@ -16,7 +16,7 @@
~ eaglercraft.resourcePack.load.loading=Loading resource pack...
~ eaglercraft.resourcePack.load.deleting=Deleting resource pack...
> INSERT 1 : 247 @ 1
> INSERT 1 : 243 @ 1
+ eaglercraft.gui.exitKey=Use '%s' to close this screen!
+ eaglercraft.gui.exitKeyRetarded=Use Backtick (`) to close this screen!
@ -213,10 +213,6 @@
+ eaglercraft.shaders.gui.option.SCREEN_SPACE_REFLECTIONS.desc.6=ON: enable raytracing (slower)
+ eaglercraft.shaders.gui.option.SCREEN_SPACE_REFLECTIONS.desc.7=OFF: disable raytracing (faster)
+
+ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.desc.0=Render god rays (light shafts) for sunlight and moonlight shadows
+ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.desc.2=ON: render god rays (slower)
+ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.desc.3=OFF: disable god rays (faster)
+
+ eaglercraft.shaders.gui.option.POST_LENS_DISTORION.label=Lens Distort
+
+ eaglercraft.shaders.gui.option.POST_LENS_DISTORION.desc.0=Renders chromatic abberation and lens distorion

View File

@ -573,6 +573,10 @@ public class PlatformOpenGL {
glDrawElements(mode, count, type, offset);
}
public static void _wglDrawRangeElements(int mode, int start, int end, int count, int type, int offset) {
glDrawRangeElements(mode, start, end, count, type, offset);
}
public static void _wglDrawElementsInstanced(int mode, int count, int type, int offset, int instanced) {
switch(instancingImpl) {
case INSTANCE_IMPL_CORE:

View File

@ -10,7 +10,7 @@ public class EaglercraftVersion {
/// Customize these to fit your fork:
public static final String projectForkName = "EaglercraftX";
public static final String projectForkVersion = "u52";
public static final String projectForkVersion = "u53";
public static final String projectForkVendor = "lax1dude";
public static final String projectForkURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8";
@ -20,20 +20,20 @@ public class EaglercraftVersion {
public static final String projectOriginName = "EaglercraftX";
public static final String projectOriginAuthor = "lax1dude";
public static final String projectOriginRevision = "1.8";
public static final String projectOriginVersion = "u52";
public static final String projectOriginVersion = "u53";
public static final String projectOriginURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; // rest in peace
// EPK Version Identifier
public static final String EPKVersionIdentifier = "u52"; // Set to null to disable EPK version check
public static final String EPKVersionIdentifier = "u53"; // Set to null to disable EPK version check
// Updating configuration
public static final boolean enableUpdateService = true;
public static final String updateBundlePackageName = "net.lax1dude.eaglercraft.v1_8.client";
public static final int updateBundlePackageVersionInt = 52;
public static final int updateBundlePackageVersionInt = 53;
public static final String updateLatestLocalStorageKey = "latestUpdate_" + updateBundlePackageName;

View File

@ -19,7 +19,6 @@ package net.lax1dude.eaglercraft.v1_8.mojang.authlib;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;

View File

@ -94,7 +94,7 @@ public class TexturesProperty {
if(meta != null) {
String modelStr = meta.optString("model");
if(modelStr != null && modelStr.equalsIgnoreCase("slim")) {
model = SkinModel.STEVE;
model = SkinModel.ALEX;
}
}
}

View File

@ -26,7 +26,6 @@ class DisplayList {
int attribs = -1;
int mode = -1;
int count = 0;
boolean bindQuad16 = false;
boolean bindQuad32 = false;
byte bindQuad = 0;
}

View File

@ -40,7 +40,7 @@ import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
public class EaglercraftGPU {
static final GLObjectRecycler<IBufferGL> arrayBufferRecycler = new GLObjectRecycler<IBufferGL>(32) {
static final GLObjectRecycler<IBufferGL> arrayBufferRecycler = new GLObjectRecycler<IBufferGL>(256) {
@Override
protected IBufferGL create() {
@ -49,7 +49,14 @@ public class EaglercraftGPU {
@Override
protected void invalidate(IBufferGL object) {
// Don't bother
IBufferGL old = currentArrayBuffer;
if (old != object) {
_wglBindBuffer(GL_ARRAY_BUFFER, object);
}
_wglBufferData(GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW);
if (old != object) {
_wglBindBuffer(GL_ARRAY_BUFFER, old);
}
}
@Override
@ -59,7 +66,7 @@ public class EaglercraftGPU {
};
static final GLObjectRecycler<IBufferGL> elementArrayBufferRecycler = new GLObjectRecycler<IBufferGL>(32) {
static final GLObjectRecycler<IBufferGL> elementArrayBufferRecycler = new GLObjectRecycler<IBufferGL>(256) {
@Override
protected IBufferGL create() {
@ -68,7 +75,22 @@ public class EaglercraftGPU {
@Override
protected void invalidate(IBufferGL object) {
// Don't bother
IVertexArrayGL oldArray = currentVertexArray;
boolean vao = !emulatedVAOs;
if (vao && vertexArrayCapable && oldArray != null) {
_wglBindVertexArray(null);
}
IBufferGL old = currentEmulatedVAOIndexBuffer;
if (vao || old != object) {
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object);
}
_wglBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, GL_STATIC_DRAW);
if (!vao && old != object) {
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, old);
}
if (vao && vertexArrayCapable && oldArray != null) {
_wglBindVertexArray(oldArray);
}
}
@Override
@ -211,8 +233,7 @@ public class EaglercraftGPU {
if(dp.vertexArray == null) {
dp.vertexArray = createGLVertexArray();
dp.bindQuad16 = false;
dp.bindQuad32 = false;
dp.bindQuad = 0;
}
if(dp.vertexBuffer == null) {
dp.vertexBuffer = createGLArrayBuffer();
@ -252,8 +273,7 @@ public class EaglercraftGPU {
if(dp.vertexArray == null) {
dp.vertexArray = createGLVertexArray();
dp.bindQuad16 = false;
dp.bindQuad32 = false;
dp.bindQuad = 0;
}
if(dp.vertexBuffer == null) {
dp.vertexBuffer = createGLArrayBuffer();
@ -280,21 +300,19 @@ public class EaglercraftGPU {
if(dp.mode == GL_QUADS) {
int cnt = dp.count;
if(cnt > quad16MaxVertices) {
if(!dp.bindQuad32) {
dp.bindQuad16 = false;
dp.bindQuad32 = true;
if(dp.bindQuad != 32) {
dp.bindQuad = 32;
attachQuad32EmulationBuffer(cnt, true);
}else {
attachQuad32EmulationBuffer(cnt, false);
}
p.drawElements(GL_TRIANGLES, (cnt >> 2) * 6, GL_UNSIGNED_INT, 0);
p.drawRangeElements(GL_TRIANGLES, 0, cnt - 1, (cnt >> 2) * 6, GL_UNSIGNED_INT, 0);
}else {
if(!dp.bindQuad16) {
dp.bindQuad16 = true;
dp.bindQuad32 = false;
if(dp.bindQuad != 16) {
dp.bindQuad = 16;
attachQuad16EmulationBuffer(true);
}
p.drawElements(GL_TRIANGLES, (cnt >> 2) * 6, GL_UNSIGNED_SHORT, 0);
p.drawRangeElements(GL_TRIANGLES, 0, cnt - 1, (cnt >> 2) * 6, GL_UNSIGNED_SHORT, 0);
}
}else {
p.drawArrays(dp.mode, 0, dp.count);
@ -560,6 +578,21 @@ public class EaglercraftGPU {
_wglDrawElements(mode, count, type, offset);
}
public static void drawRangeElements(int mode, int start, int end, int count, int type, int offset) {
if(emulatedVAOs) {
if(currentVertexArray == null) {
logger.warn("Skipping draw call with emulated VAO because no known VAO is bound!");
return;
}
((SoftGLVertexArray)currentVertexArray).transitionToState(emulatedVAOState, true);
}
if(glesVers >= 300) {
_wglDrawRangeElements(mode, start, end, count, type, offset);
}else {
_wglDrawElements(mode, count, type, offset);
}
}
public static void drawArraysInstanced(int mode, int first, int count, int instances) {
if(emulatedVAOs) {
if(currentVertexArray == null) {
@ -768,7 +801,7 @@ public class EaglercraftGPU {
displayListBuffer.put(buffer);
lastRender = null;
}else {
lastRender = FixedFunctionPipeline.setupDirect(buffer, attrib).update();
lastRender = FixedFunctionPipeline.setupDirect(buffer, attrib, mode == GL_QUADS).update();
lastRender.drawDirectArrays(mode, 0, count);
lastMode = mode;
lastCount = count;
@ -845,7 +878,7 @@ public class EaglercraftGPU {
v3 = v2 + 1;
v4 = v3 + 1;
buf.put(v1 | (v2 << 16));
buf.put(v4 | (v2 << 16));
buf.put(v3 | (v1 << 16));
buf.put(v3 | (v4 << 16));
}
buf.flip();
@ -862,7 +895,7 @@ public class EaglercraftGPU {
v3 = v2 + 1;
v4 = v3 + 1;
buf.put(v1); buf.put(v2);
buf.put(v4); buf.put(v2);
buf.put(v3); buf.put(v1);
buf.put(v3); buf.put(v4);
}
buf.flip();
@ -891,7 +924,7 @@ public class EaglercraftGPU {
}
FixedFunctionPipeline p = FixedFunctionPipeline.setupRenderDisplayList(mesh.getAttribBits()).update();
EaglercraftGPU.bindGLVertexArray(mesh.vertexArray);
p.drawElements(GL_TRIANGLES, mesh.indexCount, GL_UNSIGNED_SHORT, 0);
p.drawRangeElements(GL_TRIANGLES, 0, mesh.vertexCount - 1, mesh.indexCount, GL_UNSIGNED_SHORT, 0);
}
static int glesVers = -1;

View File

@ -30,12 +30,9 @@ import net.lax1dude.eaglercraft.v1_8.internal.IVertexArrayGL;
import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL;
import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL;
import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.opengl.StreamBuffer.StreamBufferInstance;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.dynamiclights.DynamicLightsStateManager;
import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f;
import net.lax1dude.eaglercraft.v1_8.vector.Vector4f;
import net.minecraft.util.MathHelper;
@ -61,7 +58,7 @@ public class FixedFunctionPipeline {
(GlStateManager.stateEnableShaderBlendColor ? STATE_ENABLE_BLEND_ADD : 0);
}
static FixedFunctionPipeline setupDirect(ByteBuffer buffer, int attrib) {
static FixedFunctionPipeline setupDirect(ByteBuffer buffer, int attrib, boolean quads) {
FixedFunctionPipeline self;
int baseState = attrib | getFragmentState();
if(GlStateManager.stateUseExtensionPipeline) {
@ -74,13 +71,13 @@ public class FixedFunctionPipeline {
self = getPipelineInstanceCore(baseState);
}
StreamBufferInstance sb = self.streamBuffer.getBuffer(buffer.remaining());
self.currentVertexArray = sb;
EaglercraftGPU.bindGLVertexArray(self.getDirectModeVertexArray());
EaglercraftGPU.bindGLVertexArray(sb.getVertexArray());
EaglercraftGPU.bindGLArrayBuffer(sb.getVertexBuffer());
int off = StreamBuffer.uploadData(self.attribStride, buffer.remaining() / self.attribStride, quads);
_wglBufferSubData(GL_ARRAY_BUFFER, 0, buffer);
_wglBufferSubData(GL_ARRAY_BUFFER, off * self.attribStride, buffer);
self.directBaseOffset = off;
return self;
}
@ -132,16 +129,19 @@ public class FixedFunctionPipeline {
}
static FixedFunctionPipeline setupRenderDisplayList(int attribs) {
FixedFunctionPipeline self;
int baseState = attribs | getFragmentState();
if(GlStateManager.stateUseExtensionPipeline) {
if(extensionProvider != null) {
return getPipelineInstanceExt(baseState, extensionProvider.getCurrentExtensionStateBits(baseState));
self = getPipelineInstanceExt(baseState, extensionProvider.getCurrentExtensionStateBits(baseState));
}else {
throw new IllegalStateException("No extension pipeline is available!");
}
}else {
return getPipelineInstanceCore(baseState);
self = getPipelineInstanceCore(baseState);
}
return self;
}
void drawArrays(int mode, int offset, int count) {
@ -151,24 +151,26 @@ public class FixedFunctionPipeline {
void drawDirectArrays(int mode, int offset, int count) {
EaglercraftGPU.bindGLShaderProgram(shaderProgram);
offset += directBaseOffset;
if(mode == GL_QUADS) {
StreamBufferInstance sb = currentVertexArray;
if(count > EaglercraftGPU.quad16MaxVertices) {
if(!sb.bindQuad32) {
sb.bindQuad16 = false;
sb.bindQuad32 = true;
int offset2 = (offset >> 2) * 6;
int count2 = (count >> 2) * 6;
if(offset + count > EaglercraftGPU.quad16MaxVertices) {
if(directQuads != 32) {
directQuads = 32;
EaglercraftGPU.attachQuad32EmulationBuffer(count, true);
}else {
EaglercraftGPU.attachQuad32EmulationBuffer(count, false);
}
EaglercraftGPU.drawElements(GL_TRIANGLES, (count >> 2) * 6, GL_UNSIGNED_INT, 0);
EaglercraftGPU.drawRangeElements(GL_TRIANGLES, offset, offset + count - 1, count2, GL_UNSIGNED_INT,
offset2 << 2);
}else {
if(!sb.bindQuad16) {
sb.bindQuad16 = true;
sb.bindQuad32 = false;
if(directQuads != 16) {
directQuads = 16;
EaglercraftGPU.attachQuad16EmulationBuffer(true);
}
EaglercraftGPU.drawElements(GL_TRIANGLES, (count >> 2) * 6, GL_UNSIGNED_SHORT, 0);
EaglercraftGPU.drawRangeElements(GL_TRIANGLES, offset, offset + count - 1, count2, GL_UNSIGNED_SHORT,
offset2 << 1);
}
}else {
EaglercraftGPU.drawArrays(mode, offset, count);
@ -180,6 +182,11 @@ public class FixedFunctionPipeline {
EaglercraftGPU.drawElements(mode, count, type, offset);
}
void drawRangeElements(int mode, int start, int end, int count, int type, int offset) {
EaglercraftGPU.bindGLShaderProgram(shaderProgram);
EaglercraftGPU.drawRangeElements(mode, start, end, count, type, offset);
}
private static IExtPipelineCompiler extensionProvider;
public static void loadExtensionPipeline(IExtPipelineCompiler provider) {
@ -423,9 +430,9 @@ public class FixedFunctionPipeline {
private float stateAlphaTestRef = -999.0f;
private final IUniformGL stateLightsEnabledUniform1i;
private final IUniformGL[] stateLightsVectorsArrayUniform4f = new IUniformGL[4];
private final IUniformGL[] stateLightsVectorsArrayUniform4f = new IUniformGL[2];
private int stateLightsEnabled = -1;
private final Vector4f[] stateLightsVectors = new Vector4f[4];
private final Vector4f[] stateLightsVectors = new Vector4f[2];
private int stateLightingSerial = -1;
private final IUniformGL stateLightingAmbientUniform3f;
@ -496,8 +503,9 @@ public class FixedFunctionPipeline {
private float stateAnisotropicFixH = -999.0f;
private float stateAnisotropicFixSerial = 0;
private final StreamBuffer streamBuffer;
private StreamBufferInstance currentVertexArray = null;
private IVertexArrayGL directVertexArray;
private int directBaseOffset;
private byte directQuads;
private static FloatBuffer matrixCopyBuffer = null;
@ -572,39 +580,6 @@ public class FixedFunctionPipeline {
}
throw new IllegalStateException("Program could not be linked!");
}
streamBuffer = new StreamBuffer((vertexArray, vertexBuffer) -> {
EaglercraftGPU.bindGLVertexArray(vertexArray);
EaglercraftGPU.bindVAOGLArrayBuffer(vertexBuffer);
EaglercraftGPU.enableVertexAttribArray(0);
EaglercraftGPU.vertexAttribPointer(0, VertexFormat.COMPONENT_POSITION_SIZE,
VertexFormat.COMPONENT_POSITION_FORMAT, false, attribStride, 0);
if(attribTextureIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribTextureIndex);
EaglercraftGPU.vertexAttribPointer(attribTextureIndex, VertexFormat.COMPONENT_TEX_SIZE,
VertexFormat.COMPONENT_TEX_FORMAT, false, attribStride, attribTextureOffset);
}
if(attribColorIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribColorIndex);
EaglercraftGPU.vertexAttribPointer(attribColorIndex, VertexFormat.COMPONENT_COLOR_SIZE,
VertexFormat.COMPONENT_COLOR_FORMAT, true, attribStride, attribColorOffset);
}
if(attribNormalIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribNormalIndex);
EaglercraftGPU.vertexAttribPointer(attribNormalIndex, VertexFormat.COMPONENT_NORMAL_SIZE,
VertexFormat.COMPONENT_NORMAL_FORMAT, true, attribStride, attribNormalOffset);
}
if(attribLightmapIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribLightmapIndex);
EaglercraftGPU.vertexAttribPointer(attribLightmapIndex, VertexFormat.COMPONENT_LIGHTMAP_SIZE,
VertexFormat.COMPONENT_LIGHTMAP_FORMAT, false, attribStride, attribLightmapOffset);
}
});
stateEnableTexture2D = (bits & STATE_ENABLE_TEXTURE2D) != 0;
stateEnableLightmap = (bits & STATE_ENABLE_LIGHTMAP) != 0;
@ -899,9 +874,7 @@ public class FixedFunctionPipeline {
_wglUniform3f(stateLightingAmbientUniform3f, r, g, b);
}
}
}
if(stateEnableMCLighting || DynamicLightsStateManager.isInDynamicLightsPass()) {
if(!stateHasAttribNormal) {
serial = GlStateManager.stateNormalSerial;
if(stateNormalSerial != serial) {
@ -1089,13 +1062,51 @@ public class FixedFunctionPipeline {
}
pipelineListTracker.clear();
}
public void destroy() {
PlatformOpenGL._wglDeleteProgram(shaderProgram);
streamBuffer.destroy();
}
public IVertexArrayGL getDirectModeVertexArray() {
return currentVertexArray.vertexArray;
if (directVertexArray == null) {
directVertexArray = EaglercraftGPU.createGLVertexArray();
EaglercraftGPU.bindGLVertexArray(directVertexArray);
EaglercraftGPU.bindVAOGLArrayBuffer(StreamBuffer.getBuffer());
EaglercraftGPU.enableVertexAttribArray(0);
EaglercraftGPU.vertexAttribPointer(0, VertexFormat.COMPONENT_POSITION_SIZE,
VertexFormat.COMPONENT_POSITION_FORMAT, false, attribStride, 0);
if (attribTextureIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribTextureIndex);
EaglercraftGPU.vertexAttribPointer(attribTextureIndex, VertexFormat.COMPONENT_TEX_SIZE,
VertexFormat.COMPONENT_TEX_FORMAT, false, attribStride, attribTextureOffset);
}
if (attribColorIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribColorIndex);
EaglercraftGPU.vertexAttribPointer(attribColorIndex, VertexFormat.COMPONENT_COLOR_SIZE,
VertexFormat.COMPONENT_COLOR_FORMAT, true, attribStride, attribColorOffset);
}
if (attribNormalIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribNormalIndex);
EaglercraftGPU.vertexAttribPointer(attribNormalIndex, VertexFormat.COMPONENT_NORMAL_SIZE,
VertexFormat.COMPONENT_NORMAL_FORMAT, true, attribStride, attribNormalOffset);
}
if (attribLightmapIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribLightmapIndex);
EaglercraftGPU.vertexAttribPointer(attribLightmapIndex, VertexFormat.COMPONENT_LIGHTMAP_SIZE,
VertexFormat.COMPONENT_LIGHTMAP_FORMAT, false, attribStride, attribLightmapOffset);
}
return directVertexArray;
}
return directVertexArray;
}
public void destroy() {
_wglDeleteProgram(shaderProgram);
if (directVertexArray != null) {
EaglercraftGPU.destroyGLVertexArray(directVertexArray);
}
}
}

View File

@ -44,7 +44,7 @@ public class FixedFunctionShader {
public static final String FILENAME_VSH = "/assets/eagler/glsl/core.vsh";
public static final String FILENAME_FSH = "/assets/eagler/glsl/core.fsh";
public static final String PRECISION_INT = "lowp";
public static final String PRECISION_INT = "mediump";
public static final String PRECISION_FLOAT = "highp";
public static final String PRECISION_SAMPLER = "mediump";

View File

@ -76,9 +76,9 @@ public class GlStateManager {
static boolean stateMaterial = false;
static boolean stateLighting = false;
static int stateLightsStackPointer = 0;
static final boolean[][] stateLightsEnabled = new boolean[4][8];
static final Vector4f[][] stateLightsStack = new Vector4f[4][8];
static final int[] stateLightingSerial = new int[4];
static final boolean[][] stateLightsEnabled = new boolean[2][8];
static final Vector4f[][] stateLightsStack = new Vector4f[2][8];
static final int[] stateLightingSerial = new int[2];
static float stateLightingAmbientR = 0.0f;
static float stateLightingAmbientG = 0.0f;

View File

@ -206,8 +206,7 @@ public class InstancedFontRenderer {
EaglercraftGPU.vertexAttribPointer(0, 3, GL_FLOAT, false, 12, 0);
EaglercraftGPU.vertexAttribDivisor(0, 0);
EaglercraftGPU.bindVAOGLArrayBufferNow(instancesBuffer);
_wglBufferData(GL_ARRAY_BUFFER, fontDataBuffer.capacity(), GL_STREAM_DRAW);
EaglercraftGPU.bindVAOGLArrayBuffer(instancesBuffer);
EaglercraftGPU.enableVertexAttribArray(1);
EaglercraftGPU.vertexAttribPointer(1, 2, GL_SHORT, false, 10, 0);
@ -381,7 +380,7 @@ public class InstancedFontRenderer {
int l = fontDataBuffer.limit();
fontDataBuffer.flip();
_wglBufferData(GL_ARRAY_BUFFER, fontDataBuffer.capacity(), GL_STREAM_DRAW);
_wglBufferData(GL_ARRAY_BUFFER, (fontDataBuffer.remaining() + 0x3FF) & 0xFFFFFC00, GL_STREAM_DRAW);
_wglBufferSubData(GL_ARRAY_BUFFER, 0, fontDataBuffer);
fontDataBuffer.position(p);
@ -395,7 +394,7 @@ public class InstancedFontRenderer {
int l = fontBoldDataBuffer.limit();
fontBoldDataBuffer.flip();
_wglBufferData(GL_ARRAY_BUFFER, fontBoldDataBuffer.capacity(), GL_STREAM_DRAW);
_wglBufferData(GL_ARRAY_BUFFER, (fontBoldDataBuffer.remaining() + 0x3FF) & 0xFFFFFC00, GL_STREAM_DRAW);
_wglBufferSubData(GL_ARRAY_BUFFER, 0, fontBoldDataBuffer);
fontBoldDataBuffer.position(p);

View File

@ -187,8 +187,7 @@ public class InstancedParticleRenderer {
EaglercraftGPU.vertexAttribPointer(0, 2, GL_FLOAT, false, 8, 0);
EaglercraftGPU.vertexAttribDivisor(0, 0);
EaglercraftGPU.bindVAOGLArrayBufferNow(instancesBuffer);
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.capacity(), GL_STREAM_DRAW);
EaglercraftGPU.bindVAOGLArrayBuffer(instancesBuffer);
EaglercraftGPU.enableVertexAttribArray(1);
EaglercraftGPU.vertexAttribPointer(1, 3, GL_FLOAT, false, 24, 0);
@ -315,7 +314,7 @@ public class InstancedParticleRenderer {
int l = particleBuffer.limit();
particleBuffer.flip();
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.capacity(), GL_STREAM_DRAW);
_wglBufferData(GL_ARRAY_BUFFER, (particleBuffer.remaining() + 0xFFF) & 0xFFFFF000, GL_STREAM_DRAW);
_wglBufferSubData(GL_ARRAY_BUFFER, 0, particleBuffer);
particleBuffer.position(p);

View File

@ -16,108 +16,53 @@
package net.lax1dude.eaglercraft.v1_8.opengl;
import net.lax1dude.eaglercraft.v1_8.internal.IVertexArrayGL;
import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
/**
* This streaming implementation was designed by reverse engineering the OpenGL
* driver that powers most Intel-based Chromebooks, performance may vary on
* other platforms
*/
public class StreamBuffer {
public static final int poolSize = 4;
protected static IBufferGL buffer = null;
protected static final PoolInstance[] pool = new PoolInstance[poolSize];
protected static int poolBufferID = 0;
protected static int currentOffset = 0;
protected static int currentSize = 0;
static {
for(int i = 0; i < poolSize; ++i) {
pool[i] = new PoolInstance();
}
}
protected static class PoolInstance {
protected IBufferGL vertexBuffer = null;
protected int vertexBufferSize = 0;
}
private static void resizeInstance(PoolInstance instance, int requiredMemory) {
IBufferGL buffer = instance.vertexBuffer;
public static IBufferGL getBuffer() {
if (buffer == null) {
buffer = _wglGenBuffers();
instance.vertexBuffer = buffer;
return buffer = _wglGenBuffers();
}
int newSize = instance.vertexBufferSize;
if (newSize < requiredMemory) {
newSize = (requiredMemory + 0xFFFF) & 0xFFFF0000;
instance.vertexBufferSize = newSize;
}
EaglercraftGPU.bindGLArrayBuffer(buffer);
_wglBufferData(GL_ARRAY_BUFFER, newSize, GL_STREAM_DRAW);
return buffer;
}
protected StreamBufferInstance[] buffers;
protected final IStreamBufferInitializer initializer;
public static class StreamBufferInstance {
protected PoolInstance poolInstance = null;
protected IVertexArrayGL vertexArray = null;
public boolean bindQuad16 = false;
public boolean bindQuad32 = false;
public IVertexArrayGL getVertexArray() {
return vertexArray;
public static int uploadData(int elSize, int elCount, boolean quads) {
EaglercraftGPU.bindGLArrayBuffer(getBuffer());
int off = (currentOffset + elSize - 1) / elSize;
if (quads) {
off = (off + 3) & -4;
}
public IBufferGL getVertexBuffer() {
return poolInstance.vertexBuffer;
}
}
public static interface IStreamBufferInitializer {
void initialize(IVertexArrayGL vertexArray, IBufferGL vertexBuffer);
}
public StreamBuffer(IStreamBufferInitializer initializer) {
this.buffers = new StreamBufferInstance[poolSize];
for(int i = 0; i < this.buffers.length; ++i) {
StreamBufferInstance j = new StreamBufferInstance();
j.poolInstance = pool[i];
this.buffers[i] = j;
}
this.initializer = initializer;
}
public StreamBufferInstance getBuffer(int requiredMemory) {
StreamBufferInstance next = buffers[poolBufferID++ % buffers.length];
resizeInstance(next.poolInstance, requiredMemory);
if(next.vertexArray == null) {
next.vertexArray = EaglercraftGPU.createGLVertexArray();
initializer.initialize(next.vertexArray, next.poolInstance.vertexBuffer);
}
return next;
}
public void destroy() {
for(int i = 0; i < buffers.length; ++i) {
StreamBufferInstance next = buffers[i];
if(next.vertexArray != null) {
EaglercraftGPU.destroyGLVertexArray(next.vertexArray);
}
int offBytes = off * elSize;
int reqBytes = elCount * elSize;
if (currentSize - offBytes >= reqBytes) {
currentOffset = offBytes + reqBytes;
return off;
} else {
currentOffset = 0;
currentSize = (reqBytes + 0xFFFF) & 0xFFFFF000;
_wglBufferData(GL_ARRAY_BUFFER, currentSize, GL_STREAM_DRAW);
return 0;
}
}
public static void destroyPool() {
for(int i = 0; i < pool.length; ++i) {
if(pool[i].vertexBuffer != null) {
_wglDeleteBuffers(pool[i].vertexBuffer);
pool[i].vertexBuffer = null;
}
if (buffer != null) {
_wglDeleteBuffers(buffer);
buffer = null;
}
}

View File

@ -316,7 +316,8 @@ public class LensFlareMeshRenderer {
_wglUniform3f(streaksProgram.uniforms.u_flareColor3f, v.x * mag * 0.5f, v.y * mag * 0.5f, v.z * mag * 0.5f);
EaglercraftGPU.bindGLVertexArray(streaksVertexArray);
_wglDrawElements(GL_TRIANGLES, streaksVertexCount + (streaksVertexCount >> 1), GL_UNSIGNED_SHORT, 0);
_wglDrawRangeElements(GL_TRIANGLES, 0, streaksVertexCount - 1, streaksVertexCount + (streaksVertexCount >> 1),
GL_UNSIGNED_SHORT, 0);
ghostsProgram.useProgram();

View File

@ -46,8 +46,8 @@ public class DynamicLightBucketLoader {
private int currentLightSourceBucketId = -1;
private int lightingBufferSliceLength = -1;
public static final int MAX_LIGHTS_PER_CHUNK = 12;
public static final int LIGHTING_BUFFER_LENGTH = 16 * MAX_LIGHTS_PER_CHUNK + 16;
public static final int MAX_LIGHTS_PER_CHUNK = 8;
public static final int LIGHTING_BUFFER_LENGTH = 8 * MAX_LIGHTS_PER_CHUNK + 16;
private final int lightSourceBucketsWidth;
private final int lightSourceBucketsHeight;
@ -114,26 +114,36 @@ public class DynamicLightBucketLoader {
int ser = currentLightSourceBucket.getEaglerSerial();
int max = currentLightSourceBucket.size();
if(max > 0) {
if(max > MAX_LIGHTS_PER_CHUNK) {
max = MAX_LIGHTS_PER_CHUNK;
}
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData);
int offset = currentLightSourceBucketId * lightingBufferSliceLength;
if (lightSourceBucketsSerials[currentLightSourceBucketId] != ser
|| lightSourceRenderPosSerials[currentLightSourceBucketId] != currentRenderPosSerial) {
lightSourceBucketsSerials[currentLightSourceBucketId] = ser;
lightSourceRenderPosSerials[currentLightSourceBucketId] = currentRenderPosSerial;
if(max > MAX_LIGHTS_PER_CHUNK) {
max = MAX_LIGHTS_PER_CHUNK;
}
int bucketXOff = -relativeBlockX & -16;
int bucketYOff = -relativeBlockY & -16;
int bucketZOff = -relativeBlockZ & -16;
chunkLightingDataCopyBuffer.clear();
chunkLightingDataCopyBuffer.putInt(
((bucketXOff & 0xFF) << 8) |
((bucketYOff & 0xFF) << 16) |
((bucketZOff & 0xFF) << 24)
);
chunkLightingDataCopyBuffer.putInt(max);
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putInt(0); // padding
chunkLightingDataCopyBuffer.putInt(0); // padding
for(int i = 0; i < max; ++i) {
DynamicLightInstance dl = currentLightSourceBucket.get(i);
chunkLightingDataCopyBuffer.putFloat((float)(dl.posX - currentRenderX));
chunkLightingDataCopyBuffer.putFloat((float)(dl.posY - currentRenderY));
chunkLightingDataCopyBuffer.putFloat((float)(dl.posZ - currentRenderZ));
chunkLightingDataCopyBuffer.putFloat(dl.radius);
int x = (int)((dl.posX - currentRenderX + bucketXOff) * (1.0f / 0.0009765923f));
int y = (int)((dl.posY - currentRenderY + bucketYOff) * (1.0f / 0.0009765923f));
int z = (int)((dl.posZ - currentRenderZ + bucketZOff) * (1.0f / 0.0009765923f));
int r = (int)(dl.radius * (1.0f / 0.0009765923f));
if (r > 32767) r = 32767;
chunkLightingDataCopyBuffer.putInt((x & 0xFFFF) | (z << 16));
chunkLightingDataCopyBuffer.putInt((y & 0xFFFF) | (r << 16));
}
chunkLightingDataCopyBuffer.flip();
_wglBufferSubData(_GL_UNIFORM_BUFFER, offset, chunkLightingDataCopyBuffer);

View File

@ -204,6 +204,8 @@ public class PlatformOpenGL {
public static native void _wglDrawElements(int mode, int count, int type, int offset);
public static native void _wglDrawRangeElements(int mode, int start, int end, int count, int type, int offset);
public static native void _wglDrawArraysInstanced(int mode, int first, int count, int instanced);
public static native void _wglDrawElementsInstanced(int mode, int count, int type, int offset, int instanced);

View File

@ -1 +1 @@
u52
u53

View File

@ -63,7 +63,7 @@ uniform float u_alphaTestRef1f;
#ifdef COMPILE_ENABLE_MC_LIGHTING
uniform int u_lightsEnabled1i;
uniform vec4 u_lightsDirections4fv[4];
uniform vec4 u_lightsDirections4fv[2];
uniform vec3 u_lightsAmbient3f;
#ifndef COMPILE_NORMAL_ATTRIB
uniform vec3 u_uniformNormal3f;
@ -166,20 +166,14 @@ void main() {
#else
vec3 normal = u_uniformNormal3f;
#endif
float diffuse = 0.0;
vec4 light;
#ifdef EAGLER_HAS_GLES_300
for(int i = 0; i < u_lightsEnabled1i; ++i) {
#else
for(int i = 0; i < 4; ++i) {
#endif
light = u_lightsDirections4fv[i];
diffuse += max(dot(light.xyz, normal), 0.0) * light.w;
#ifndef EAGLER_HAS_GLES_300
if(i + 1 >= u_lightsEnabled1i) {
float diffuse = 0.0;
for(int i = 0; i < 2; ++i) {
if(i >= u_lightsEnabled1i) {
break;
}
#endif
light = u_lightsDirections4fv[i];
diffuse += max(dot(light.xyz, normal), 0.0) * light.w;
}
color.rgb *= min(u_lightsAmbient3f + vec3(diffuse), 1.0);
#endif

View File

@ -20,7 +20,6 @@ precision lowp int;
precision mediump float;
precision mediump sampler2D;
in vec4 v_position4f;
in vec2 v_texCoord2f;
in vec4 v_color4f;
in vec2 v_lightmap2f;
@ -30,16 +29,6 @@ layout(location = 0) out vec4 output4f;
uniform sampler2D u_inputTexture;
uniform sampler2D u_lightmapTexture;
uniform mat4 u_inverseViewMatrix4f;
layout(std140) uniform u_chunkLightingData {
mediump int u_dynamicLightCount1i;
mediump int _paddingA_;
mediump int _paddingB_;
mediump int _paddingC_;
mediump vec4 u_dynamicLightArray[12];
};
void main() {
vec4 color = texture(u_inputTexture, v_texCoord2f) * v_color4f;
@ -47,20 +36,7 @@ void main() {
discard;
}
vec4 dlight;
float blockLight = v_lightmap2f.x;
if(u_dynamicLightCount1i > 0) {
vec4 worldPosition4f = u_inverseViewMatrix4f * v_position4f;
worldPosition4f.xyz /= worldPosition4f.w;
int safeLightCount = u_dynamicLightCount1i > 12 ? 0 : u_dynamicLightCount1i;
for(int i = 0; i < safeLightCount; ++i) {
dlight = u_dynamicLightArray[i];
dlight.xyz = dlight.xyz - worldPosition4f.xyz;
blockLight = max((dlight.w - length(dlight.xyz)) * 0.066667, blockLight);
}
}
color *= texture(u_lightmapTexture, vec2(blockLight, v_lightmap2f.y));
color *= texture(u_lightmapTexture, v_lightmap2f);
output4f = color;
}

View File

@ -28,21 +28,27 @@ layout(location = 3) in vec2 p_lightMap2f;
layout(location = 4) in vec2 p_particleSize_texCoordsSize_2i;
layout(location = 5) in vec4 p_color4f;
out vec4 v_position4f;
out vec2 v_texCoord2f;
out vec4 v_color4f;
out vec2 v_lightmap2f;
uniform mat4 u_modelViewMatrix4f;
uniform mat4 u_projectionMatrix4f;
uniform mat4 u_inverseViewMatrix4f;
uniform vec3 u_texCoordSize2f_particleSize1f;
uniform vec3 u_transformParam_1_2_5_f;
uniform vec2 u_transformParam_3_4_f;
uniform vec4 u_color4f;
layout(std140) uniform u_chunkLightingData {
mediump uvec2 u_dynamicLightOffsetCount2i;
mediump int _paddingA_;
mediump int _paddingB_;
mediump uvec4 u_dynamicLightArray[4];
};
void main() {
v_color4f = u_color4f * p_color4f.bgra;
v_lightmap2f = p_lightMap2f;
vec2 tex2f = a_position2f * 0.5 + 0.5;
tex2f.y = 1.0 - tex2f.y;
@ -56,6 +62,40 @@ void main() {
pos3f += u_transformParam_1_2_5_f * spos2f.xyy;
pos3f.zx += u_transformParam_3_4_f * spos2f;
v_position4f = u_modelViewMatrix4f * vec4(pos3f, 1.0);
gl_Position = u_projectionMatrix4f * v_position4f;
vec4 pos4f = u_modelViewMatrix4f * vec4(pos3f, 1.0);
gl_Position = u_projectionMatrix4f * pos4f;
float blockLight = 0.0;
vec4 dlight;
uvec4 dlighti1, dlighti2;
if(u_dynamicLightOffsetCount2i.y > 0u) {
vec3 dlightOffset = vec3(ivec3(
int(u_dynamicLightOffsetCount2i.x << 16),
int(u_dynamicLightOffsetCount2i.x << 8),
int(u_dynamicLightOffsetCount2i.x)
) >> 24);
vec4 worldPosition4f = u_inverseViewMatrix4f * pos4f;
worldPosition4f.xyz = worldPosition4f.xyz / worldPosition4f.w + dlightOffset;
for(uint i = 0u; i < 4u; ++i) {
dlighti1 = u_dynamicLightArray[i];
dlighti2 = dlighti1 << 16;
dlight = vec4(ivec4(ivec2(dlighti2.xy), ivec2(dlighti1.xy)) >> 16) * 0.0009765923;
dlight.xyz = dlight.xyz - worldPosition4f.xyz;
blockLight = max((dlight.w - length(dlight.xyz)) * 0.066667, blockLight);
if(i * 2u + 1u >= u_dynamicLightOffsetCount2i.y) {
break;
}
dlight = vec4(ivec4(ivec2(dlighti2.zw), ivec2(dlighti1.zw)) >> 16) * 0.0009765923;
dlight.xyz = dlight.xyz - worldPosition4f.xyz;
blockLight = max((dlight.w - length(dlight.xyz)) * 0.066667, blockLight);
if(i * 2u + 2u >= u_dynamicLightOffsetCount2i.y) {
break;
}
}
}
v_lightmap2f = vec2(max(p_lightMap2f.x, blockLight), p_lightMap2f.y);
}

View File

@ -16,7 +16,9 @@
*
*/
#if defined(COMPILE_ENABLE_TEX_GEN) || defined(COMPILE_ENABLE_FOG)
in vec4 v_position4f;
#endif
#ifdef COMPILE_TEXTURE_ATTRIB
in vec2 v_texture2f;
@ -61,7 +63,7 @@ uniform float u_alphaTestRef1f;
#ifdef COMPILE_ENABLE_MC_LIGHTING
uniform int u_lightsEnabled1i;
uniform vec4 u_lightsDirections4fv[4];
uniform vec4 u_lightsDirections4fv[2];
uniform vec3 u_lightsAmbient3f;
#endif
@ -88,15 +90,9 @@ uniform mat4 u_textureMat4f01;
uniform vec2 u_textureAnisotropicFix;
#endif
uniform mat4 u_inverseViewMatrix4f;
layout(std140) uniform u_chunkLightingData {
mediump int u_dynamicLightCount1i;
mediump int _paddingA_;
mediump int _paddingB_;
mediump int _paddingC_;
mediump vec4 u_dynamicLightArray[12];
};
#ifdef COMPILE_ENABLE_LIGHTMAP
in float v_dynamicLight1f;
#endif
layout(location = 0) out vec4 output4f;
@ -151,17 +147,9 @@ void main() {
#else
float blockLight = u_textureCoords02.x;
#endif
vec4 dlight;
if(u_dynamicLightCount1i > 0) {
vec4 worldPosition4f = u_inverseViewMatrix4f * v_position4f;
worldPosition4f.xyz /= worldPosition4f.w;
int safeLightCount = u_dynamicLightCount1i > 12 ? 0 : u_dynamicLightCount1i;
for(int i = 0; i < safeLightCount; ++i) {
dlight = u_dynamicLightArray[i];
dlight.xyz = dlight.xyz - worldPosition4f.xyz;
blockLight = max((dlight.w - length(dlight.xyz)) * 0.066667, blockLight);
}
}
blockLight = max(blockLight, v_dynamicLight1f);
#ifdef COMPILE_LIGHTMAP_ATTRIB
color *= texture(u_samplerLightmap, vec2(blockLight, v_lightmap2f.y));
#else
@ -179,16 +167,18 @@ void main() {
#endif
#ifdef COMPILE_ENABLE_MC_LIGHTING
#ifdef COMPILE_NORMAL_ATTRIB
vec3 normal = v_normal3f;
#else
vec3 normal = u_uniformNormal3f;
#endif
#ifdef COMPILE_ENABLE_MC_LIGHTING
vec4 light;
float diffuse = 0.0;
for(int i = 0; i < u_lightsEnabled1i; ++i) {
for(int i = 0; i < 2; ++i) {
if(i >= u_lightsEnabled1i) {
break;
}
light = u_lightsDirections4fv[i];
diffuse += max(dot(light.xyz, normal), 0.0) * light.w;
}

View File

@ -18,7 +18,13 @@
in vec3 a_position3f;
#if defined(COMPILE_ENABLE_TEX_GEN) || defined(COMPILE_ENABLE_FOG)
#define _COMPILE_VARYING_POSITION
#endif
#ifdef _COMPILE_VARYING_POSITION
out vec4 v_position4f;
#endif
#ifdef COMPILE_ENABLE_TEX_GEN
out vec3 v_objectPosition3f;
@ -46,16 +52,32 @@ out vec2 v_lightmap2f;
uniform mat4 u_textureMat4f02;
#endif
#ifdef COMPILE_ENABLE_LIGHTMAP
out float v_dynamicLight1f;
#endif
uniform mat4 u_modelviewMat4f;
uniform mat4 u_projectionMat4f;
uniform mat4 u_inverseViewMatrix4f;
#define TEX_MAT3(mat4In) mat3(mat4In[0].xyw,mat4In[1].xyw,mat4In[3].xyw)
layout(std140) uniform u_chunkLightingData {
mediump uvec2 u_dynamicLightOffsetCount2i;
mediump int _paddingA_;
mediump int _paddingB_;
mediump uvec4 u_dynamicLightArray[4];
};
void main() {
#ifdef COMPILE_ENABLE_TEX_GEN
v_objectPosition3f = a_position3f;
#endif
#ifndef _COMPILE_VARYING_POSITION
vec4 v_position4f;
#endif
v_position4f = u_modelviewMat4f * vec4(a_position3f, 1.0);
#ifdef COMPILE_TEXTURE_ATTRIB
@ -75,6 +97,42 @@ void main() {
vec3 v_lightmapTmp3f = TEX_MAT3(u_textureMat4f02) * vec3(a_lightmap2f, 1.0);
v_lightmap2f = v_lightmapTmp3f.xy / v_lightmapTmp3f.z;
#endif
gl_Position = u_projectionMat4f * v_position4f;
#ifdef COMPILE_ENABLE_LIGHTMAP
float blockLight = 0.0;
vec4 dlight;
uvec4 dlighti1, dlighti2;
if(u_dynamicLightOffsetCount2i.y > 0u) {
vec3 dlightOffset = vec3(ivec3(
int(u_dynamicLightOffsetCount2i.x << 16),
int(u_dynamicLightOffsetCount2i.x << 8),
int(u_dynamicLightOffsetCount2i.x)
) >> 24);
vec4 worldPosition4f = u_inverseViewMatrix4f * v_position4f;
worldPosition4f.xyz = worldPosition4f.xyz / worldPosition4f.w + dlightOffset;
for(uint i = 0u; i < 4u; ++i) {
dlighti1 = u_dynamicLightArray[i];
dlighti2 = dlighti1 << 16;
dlight = vec4(ivec4(ivec2(dlighti2.xy), ivec2(dlighti1.xy)) >> 16) * 0.0009765923;
dlight.xyz = dlight.xyz - worldPosition4f.xyz;
blockLight = max((dlight.w - length(dlight.xyz)) * 0.066667, blockLight);
if(i * 2u + 1u >= u_dynamicLightOffsetCount2i.y) {
break;
}
dlight = vec4(ivec4(ivec2(dlighti2.zw), ivec2(dlighti1.zw)) >> 16) * 0.0009765923;
dlight.xyz = dlight.xyz - worldPosition4f.xyz;
blockLight = max((dlight.w - length(dlight.xyz)) * 0.066667, blockLight);
if(i * 2u + 2u >= u_dynamicLightOffsetCount2i.y) {
break;
}
}
}
v_dynamicLight1f = blockLight;
#endif
}

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,8 @@
client-version-integer=52
client-version-integer=53
client-package-name=net.lax1dude.eaglercraft.v1_8.client
client-origin-name=EaglercraftX
client-origin-version=u52
client-origin-version=u53
client-origin-vendor=lax1dude
client-fork-name=EaglercraftX
client-fork-version=u52
client-fork-version=u53
client-fork-vendor=lax1dude

View File

@ -14,10 +14,10 @@ f&1023))}}else d+=String.fromCharCode(f)}return d},ta=a=>{sa||(e.onExit?.(a),O=!
20);const b=w(),d=document.createElement("div");d.setAttribute("style","z-index:100;position:absolute;top:10%;left:10%;right:10%;bottom:10%;background-color:white;border:2px solid #cccccc;overflow-x:hidden;overflow-y:scroll;");d.classList.add("_eaglercraftX_loader_failed_container");a=a?W(a):"";console.error("LoaderMain: [FAILED] "+a);const c=document.createElement("h2");c.style.color="#AA0000";c.style.padding="25px";c.style.fontFamily="sans-serif";c.style.marginBlock="0px";c.appendChild(document.createTextNode(a));
d.appendChild(c);a=document.createElement("h4");a.style.color="#AA0000";a.style.padding="25px";a.style.fontFamily="sans-serif";a.style.marginBlock="0px";a.appendChild(document.createTextNode("Try again later"));d.appendChild(a);b.appendChild(d)},h:function(a){var b=a>>2;a=v[A[b]];var d=v[A[b+1]];a=a?URL.createObjectURL(new Blob([a],{type:d||"image/png"})):null;b=(b=v[A[b+2]])?U.decode(b):"<h1>Failed to load error screen</h1>";t=v=null;setTimeout(x,20);d=w();var c=document.createElement("img");c.setAttribute("style",
"z-index:100;position:absolute;top:10px;left:calc(50% - 151px);");c.src=a;d.appendChild(c);a=document.createElement("div");a.setAttribute("style","z-index:100;position:absolute;top:135px;left:10%;right:10%;bottom:50px;background-color:white;border:2px solid #cccccc;");a.classList.add("_eaglercraftX_jspi_unsupported_container");c=document.createElement("iframe");c.classList.add("_eaglercraftX_jspi_unsupported_frame");c.setAttribute("style","border:none;width:100%;height:100%;");c.srcdoc=b;a.appendChild(c);
d.appendChild(a)},m:function(a){a>>=2;const b=URL.createObjectURL(new Blob([v[A[a]]],{type:"text/javascript;charset=utf-8"})),d=URL.createObjectURL(new Blob([v[A[a+1]]],{type:"application/wasm"})),c=URL.createObjectURL(new Blob([v[A[a+2]]],{type:"application/octet-stream"})),f=URL.createObjectURL(new Blob([v[A[a+3]]],{type:"application/wasm"})),u=URL.createObjectURL(new Blob([v[A[a+4]]],{type:v[A[a+5]]})),m=URL.createObjectURL(new Blob([v[A[a+6]]],{type:v[A[a+7]]})),V=URL.createObjectURL(new Blob([v[A[a+
8]]],{type:v[A[a+9]]})),I=A[a+10],q=Array(I);for(var h=0,l;h<I;++h)l=a+11+3*h,q[h]={data:v[A[l]],name:v[A[l+1]],path:v[A[l+2]]};t=v=null;setTimeout(x,20);window.__eaglercraftXLoaderContext={getEaglercraftXOpts:function(){return ca},getEagRuntimeJSURL:function(){return b},getClassesWASMURL:function(){return d},getClassesDeobfWASMURL:function(){return f},getClassesTEADBGURL:function(){return c},getEPKFiles:function(){return q},getRootElement:function(){return r},getMainArgs:function(){return[]},getImageURL:function(p){switch(p){case 0:return da;
case 1:return u;case 2:return m;case 3:return V;default:return null}},runMain:function(p){setTimeout(p,10)}};a=document.createElement("script");a.type="text/javascript";a.src=b;document.head.appendChild(a)}},X=function(){function a(d){X=d.exports;y=X.o;fa();ia.unshift(X.p);P--;e.monitorRunDependencies?.(P);0==P&&(null!==Q&&(clearInterval(Q),Q=null),R&&(d=R,R=null,d()));return X}P++;e.monitorRunDependencies?.(P);var b={a:ua};if(e.instantiateWasm)try{return e.instantiateWasm(b,a)}catch(d){return M(`Module.instantiateWasm callback failed with error: ${d}`),
!1}S??=ma("loader.wasm")?"loader.wasm":e.locateFile?e.locateFile("loader.wasm",G):G+"loader.wasm";qa(b,function(d){a(d.instance)});return{}}(),va=e._main=(a,b)=>(va=e._main=X.q)(a,b),Y=a=>(Y=X.s)(a),Z;R=function wa(){Z||xa();Z||(R=wa)};
d.appendChild(a)},m:function(a){a>>=2;const b=URL.createObjectURL(new Blob([v[A[a]]],{type:"text/javascript;charset=utf-8"})),d=URL.createObjectURL(new Blob([v[A[a+1]]],{type:"application/wasm"})),c=-1!==A[a+2]?URL.createObjectURL(new Blob([v[A[a+2]]],{type:"application/octet-stream"})):null,f=-1!==A[a+3]?URL.createObjectURL(new Blob([v[A[a+3]]],{type:"application/wasm"})):null,u=URL.createObjectURL(new Blob([v[A[a+4]]],{type:v[A[a+5]]})),m=URL.createObjectURL(new Blob([v[A[a+6]]],{type:v[A[a+7]]})),
V=URL.createObjectURL(new Blob([v[A[a+8]]],{type:v[A[a+9]]})),I=A[a+10],q=Array(I);for(var h=0,l;h<I;++h)l=a+11+3*h,q[h]={data:v[A[l]],name:v[A[l+1]],path:v[A[l+2]]};t=v=null;setTimeout(x,20);window.__eaglercraftXLoaderContext={getEaglercraftXOpts:function(){return ca},getEagRuntimeJSURL:function(){return b},getClassesWASMURL:function(){return d},getClassesDeobfWASMURL:function(){return f},getClassesTEADBGURL:function(){return c},getEPKFiles:function(){return q},getRootElement:function(){return r},
getMainArgs:function(){return[]},getImageURL:function(p){switch(p){case 0:return da;case 1:return u;case 2:return m;case 3:return V;default:return null}},runMain:function(p){setTimeout(p,10)}};a=document.createElement("script");a.type="text/javascript";a.src=b;document.head.appendChild(a)}},X=function(){function a(d){X=d.exports;y=X.o;fa();ia.unshift(X.p);P--;e.monitorRunDependencies?.(P);0==P&&(null!==Q&&(clearInterval(Q),Q=null),R&&(d=R,R=null,d()));return X}P++;e.monitorRunDependencies?.(P);var b=
{a:ua};if(e.instantiateWasm)try{return e.instantiateWasm(b,a)}catch(d){return M(`Module.instantiateWasm callback failed with error: ${d}`),!1}S??=ma("loader.wasm")?"loader.wasm":e.locateFile?e.locateFile("loader.wasm",G):G+"loader.wasm";qa(b,function(d){a(d.instance)});return{}}(),va=e._main=(a,b)=>(va=e._main=X.q)(a,b),Y=a=>(Y=X.s)(a),Z;R=function wa(){Z||xa();Z||(R=wa)};
function ya(a=[]){var b=va;a.unshift(E);var d=a.length,c=Y(4*(d+1)),f=c;a.forEach(m=>{for(var V=B,I=f>>2,q=0,h=0;h<m.length;++h){var l=m.charCodeAt(h);127>=l?q++:2047>=l?q+=2:55296<=l&&57343>=l?(q+=4,++h):q+=3}var p=q+1;h=q=Y(p);l=z;if(0<p){p=h+p-1;for(var K=0;K<m.length;++K){var n=m.charCodeAt(K);if(55296<=n&&57343>=n){var Aa=m.charCodeAt(++K);n=65536+((n&1023)<<10)|Aa&1023}if(127>=n){if(h>=p)break;l[h++]=n}else{if(2047>=n){if(h+1>=p)break;l[h++]=192|n>>6}else{if(65535>=n){if(h+2>=p)break;l[h++]=
224|n>>12}else{if(h+3>=p)break;l[h++]=240|n>>18;l[h++]=128|n>>12&63}l[h++]=128|n>>6&63}l[h++]=128|n&63}}l[h]=0}V[I]=q;f+=4});B[f>>2]=0;try{var u=b(d,c);ta(u)}catch(m){m instanceof ra||"unwind"==m||F(1,m)}}
function xa(){var a=D;function b(){if(!Z&&(Z=!0,e.calledRun=!0,!O)){T(ia);T(ja);e.onRuntimeInitialized?.();za&&ya(a);if(e.postRun)for("function"==typeof e.postRun&&(e.postRun=[e.postRun]);e.postRun.length;){var d=e.postRun.shift();ka.unshift(d)}T(ka)}}if(!(0<P)){if(e.preRun)for("function"==typeof e.preRun&&(e.preRun=[e.preRun]);e.preRun.length;)la();T(ha);0<P||(e.setStatus?(e.setStatus("Running..."),setTimeout(()=>{setTimeout(()=>e.setStatus(""),1);b()},1)):b())}}

View File

@ -63,6 +63,7 @@ public class PlatformAudio {
static AudioBufferSourceNode recDestSilenceNode = null;
static GainNode micRecGain = null;
static GainNode gameRecGain = null;
static HTMLAudioElement silenceElement = null;
private static final Map<String, BrowserAudioResource> soundCache = new HashMap<>();
private static final List<BrowserAudioHandle> activeSounds = new LinkedList<>();
@ -253,16 +254,33 @@ public class PlatformAudio {
HTMLAudioElement audio = (HTMLAudioElement) PlatformRuntime.doc.createElement("audio");
audio.getClassList().add("_eaglercraftX_keepalive_hack");
audio.setAttribute("style", "display:none;");
audio.setAutoplay(true);
audio.setAutoplay(false);
audio.setLoop(true);
audio.addEventListener("seeked", (e) -> {
// NOP, wakes up the browser's event loop
});
audio.addEventListener("canplay", (e) -> {
if (PlatformRuntime.doc != null && silenceElement != null &&
!PlatformInput.getVisibilityState(PlatformRuntime.doc)) {
silenceElement.play();
}
});
HTMLSourceElement source = (HTMLSourceElement) PlatformRuntime.doc.createElement("source");
source.setType("audio/wav");
source.setSrc(TeaVMBlobURLManager.registerNewURLByte(silenceFile, "audio/wav").toExternalForm());
audio.appendChild(source);
audio.addEventListener("seeked", (e) -> {
// NOP, wakes up the browser's event loop
});
PlatformRuntime.parent.appendChild(audio);
silenceElement = audio;
}
}
}
static void handleVisibilityChange() {
if (silenceElement != null) {
if (!PlatformInput.getVisibilityState(PlatformRuntime.doc)) {
silenceElement.play();
} else {
silenceElement.pause();
}
}
}
@ -607,6 +625,11 @@ public class PlatformAudio {
micRecGain = null;
gameRecGain = null;
}
if(silenceElement != null) {
silenceElement.pause();
silenceElement.delete();
silenceElement = null;
}
}
}

View File

@ -103,6 +103,7 @@ public class PlatformInput {
private static EventListener<?> pointerlock = null;
private static EventListener<?> pointerlockerr = null;
private static EventListener<?> fullscreen = null;
private static EventListener<?> visibilitychange = null;
private static Map<String,LegacyKeycodeTranslator.LegacyKeycode> keyCodeTranslatorMap = null;
@ -636,6 +637,12 @@ public class PlatformInput {
isWindowFocused = true;
}
});
win.getDocument().addEventListener("visibilitychange", visibilitychange = new EventListener<Event>() {
@Override
public void handleEvent(Event evt) {
PlatformAudio.handleVisibilityChange();
}
});
try {
pointerLockSupported = getSupportedPointerLock(win.getDocument());
@ -865,7 +872,7 @@ public class PlatformInput {
}
@JSBody(params = { "doc" }, script = "return (typeof doc.visibilityState !== \"string\") || (doc.visibilityState === \"visible\");")
private static native boolean getVisibilityState(JSObject doc);
static native boolean getVisibilityState(JSObject doc);
@JSBody(params = { "win" }, script = "return (typeof win.devicePixelRatio === \"number\") ? win.devicePixelRatio : 1.0;")
static native double getDevicePixelRatio(Window win);
@ -1513,6 +1520,10 @@ public class PlatformInput {
win.removeEventListener("blur", blur);
blur = null;
}
if(visibilitychange != null) {
win.getDocument().removeEventListener("visibilitychange", blur);
visibilitychange = null;
}
if(wheel != null) {
canvas.removeEventListener("wheel", wheel);
wheel = null;

View File

@ -600,6 +600,11 @@ public class PlatformOpenGL {
//checkErr("_wglDrawElements(" + mode + ", " + count + ", " + type + ", " + offset + ");");
}
public static void _wglDrawRangeElements(int mode, int start, int end, int count, int type, int offset) {
ctx.drawRangeElements(mode, start, end, count, type, offset);
//checkErr("_wglDrawRangeElements(" + mode + ", " + start + ", " + end + ", " + count + ", " + type + ", " + offset + ");");
}
public static void _wglDrawElementsInstanced(int mode, int count, int type, int offset, int instances) {
switch(instancingImpl) {
case INSTANCE_IMPL_CORE:

View File

@ -72,6 +72,8 @@ public interface WebGL2RenderingContext extends WebGLRenderingContext {
void drawElementsInstanced(int p1, int p2, int p3, int p4, int p5);
void drawRangeElements(int p1, int p2, int p3, int p4, int p5, int p6);
int getUniformBlockIndex(WebGLProgram p1, String p2);
void bindBufferRange(int p1, int p2, WebGLBuffer p3, int p4, int p5);

View File

@ -26,6 +26,7 @@ static uint32_t initEPWBinaryCompressedHelper(struct epw_slice_compressed* slice
static uint32_t initEPWBinaryHelper(struct epw_slice* sliceIn, uint32_t epwLen);
static uint32_t initEPWStringHelper(struct epw_slice* sliceIn, uint32_t epwLen);
#define SLICE_IS_PRESENT(pSlice) (((struct epw_slice_compressed*)(pSlice))->sliceCompressedLength && ((struct epw_slice_compressed*)(pSlice))->sliceDecompressedLength)
#define SLICE_IN_BOUNDS(pSlice, epwLen) (((struct epw_slice*)(pSlice))->sliceOffset + ((struct epw_slice*)(pSlice))->sliceLength <= (epwLen))
// Note: Linux kernel uses 4096
@ -186,20 +187,28 @@ int main(int argc, char** argv) {
return -1;
}
dbgLog("Decompressing classes.wasm.teadbg...");
result->classesDeobfTEADBGData = initEPWBinaryCompressedHelper(&headerPtr->classesDeobfTEADBGData, epwLen);
if(!result->classesDeobfTEADBGData) {
resultFailed(EPW_INVALID);
return -1;
if(SLICE_IS_PRESENT(&headerPtr->classesDeobfTEADBGData)) {
dbgLog("Decompressing classes.wasm.teadbg...");
result->classesDeobfTEADBGData = initEPWBinaryCompressedHelper(&headerPtr->classesDeobfTEADBGData, epwLen);
if(!result->classesDeobfTEADBGData) {
resultFailed(EPW_INVALID);
return -1;
}
}else {
result->classesDeobfTEADBGData = -1;
}
dbgLog("Decompressing deobfuscator...");
result->classesDeobfWASMData = initEPWBinaryCompressedHelper(&headerPtr->classesDeobfWASMData, epwLen);
if(!result->classesDeobfWASMData) {
resultFailed(EPW_INVALID);
return -1;
if(SLICE_IS_PRESENT(&headerPtr->classesDeobfWASMData)) {
dbgLog("Decompressing deobfuscator...");
result->classesDeobfWASMData = initEPWBinaryCompressedHelper(&headerPtr->classesDeobfWASMData, epwLen);
if(!result->classesDeobfWASMData) {
resultFailed(EPW_INVALID);
return -1;
}
}else {
result->classesDeobfWASMData = -1;
}
result->numEPKs = numEPKs;

View File

@ -78,8 +78,8 @@ addToLibrary({
const eagRuntimeJSURL = URL.createObjectURL(new Blob([results[HEAP32[idx]]], { type: "text/javascript;charset=utf-8" }));
const classesWASMURL = URL.createObjectURL(new Blob([results[HEAP32[idx + 1]]], { type: "application/wasm" }));
const classesDeobfTEADBGURL = URL.createObjectURL(new Blob([results[HEAP32[idx + 2]]], { type: "application/octet-stream" }));
const classesDeobfWASMURL = URL.createObjectURL(new Blob([results[HEAP32[idx + 3]]], { type: "application/wasm" }));
const classesDeobfTEADBGURL = HEAP32[idx + 2] !== -1 ? URL.createObjectURL(new Blob([results[HEAP32[idx + 2]]], { type: "application/octet-stream" })) : null;
const classesDeobfWASMURL = HEAP32[idx + 3] !== -1 ? URL.createObjectURL(new Blob([results[HEAP32[idx + 3]]], { type: "application/wasm" })) : null;
const pressAnyKey = URL.createObjectURL(new Blob([results[HEAP32[idx + 4]]], { type: results[HEAP32[idx + 5]] }));
const crashImg = URL.createObjectURL(new Blob([results[HEAP32[idx + 6]]], { type: results[HEAP32[idx + 7]] }));

View File

@ -22,6 +22,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.teavm.interop.Address;
import org.teavm.interop.Import;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject;
@ -41,6 +42,7 @@ import org.teavm.jso.webaudio.PannerNode;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.MemoryStack;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.WASMGCDirectArrayConverter;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.WASMGCDirectArrayCopy;
import net.lax1dude.eaglercraft.v1_8.internal.wasm_gc_teavm.BetterJSStringConverter;
import net.lax1dude.eaglercraft.v1_8.internal.wasm_gc_teavm.JOrbisAudioBufferDecoder;
import net.lax1dude.eaglercraft.v1_8.internal.wasm_gc_teavm.WASMGCClientConfigAdapter;
@ -100,7 +102,10 @@ public class PlatformAudio {
if (silenceFile != null) {
MemoryStack.push();
try {
initKeepAliveHack(WASMGCDirectArrayConverter.byteArrayToStackU8Array(silenceFile));
int len = silenceFile.length;
Address addr = MemoryStack.malloc(len);
WASMGCDirectArrayCopy.memcpy(addr, silenceFile, 0, len);
initKeepAliveHack(addr, len);
}finally {
MemoryStack.pop();
}
@ -112,7 +117,7 @@ public class PlatformAudio {
private static native AudioContext getContext();
@Import(module = "platformAudio", name = "initKeepAliveHack")
private static native void initKeepAliveHack(Uint8Array array);
private static native void initKeepAliveHack(Address addr, int length);
protected static class BrowserAudioResource implements IAudioResource {

View File

@ -199,7 +199,7 @@ public class PlatformOpenGL {
@Import(module = "platformOpenGL", name = "glReadPixels")
static native void _wglReadPixelsN(int x, int y, int width, int height, int format, int type, ArrayBufferView array);
@Import(module = "platformOpenGL", name = "glReadPixels0")
@Import(module = "platformOpenGL", name = "glReadPixels")
static native void _wglReadPixelsN(int x, int y, int width, int height, int format, int type, ArrayBufferView array, int offset);
@Import(module = "platformOpenGL", name = "glPolygonOffset")
@ -367,7 +367,7 @@ public class PlatformOpenGL {
@Import(module = "platformOpenGL", name = "glBufferData")
static native void _wglBufferDataN(int target, ArrayBufferView typedArray, int usage);
@Import(module = "platformOpenGL", name = "glBufferData0")
@Import(module = "platformOpenGL", name = "glBufferData")
static native void _wglBufferDataN(int target, ArrayBufferView typedArray, int usage, int srcOffset, int length);
public static void _wglBufferSubData(int target, int dstOffset, ByteBuffer buffer) {
@ -397,7 +397,7 @@ public class PlatformOpenGL {
@Import(module = "platformOpenGL", name = "glBufferSubData")
static native void _wglBufferSubDataN(int target, int dstOffset, ArrayBufferView typedArray);
@Import(module = "platformOpenGL", name = "glBufferSubData0")
@Import(module = "platformOpenGL", name = "glBufferSubData")
static native void _wglBufferSubDataN(int target, int dstOffset, ArrayBufferView typedArray, int srcOffset, int length);
public static void _wglBindVertexArray(IVertexArrayGL objId) {
@ -450,7 +450,7 @@ public class PlatformOpenGL {
static native void _wglTexImage3DN(int target, int level, int internalFormat, int width, int height, int depth,
int border, int format, int type, ArrayBufferView typedArray);
@Import(module = "platformOpenGL", name = "glTexImage3D0")
@Import(module = "platformOpenGL", name = "glTexImage3D")
static native void _wglTexImage3DN(int target, int level, int internalFormat, int width, int height, int depth,
int border, int format, int type, ArrayBufferView typedArray, int offset);
@ -513,7 +513,7 @@ public class PlatformOpenGL {
static native void _wglTexImage2DN(int target, int level, int internalFormat, int width, int height, int border,
int format, int type, ArrayBufferView typedArray);
@Import(module = "platformOpenGL", name = "glTexImage2D0")
@Import(module = "platformOpenGL", name = "glTexImage2D")
static native void _wglTexImage2DN(int target, int level, int internalFormat, int width, int height, int border,
int format, int type, ArrayBufferView typedArray, int offset);
@ -565,7 +565,7 @@ public class PlatformOpenGL {
static native void _wglTexSubImage2D(int target, int level, int offsetx, int offsety, int width, int height,
int format, int type, ArrayBufferView typedArray);
@Import(module = "platformOpenGL", name = "glTexSubImage2D0")
@Import(module = "platformOpenGL", name = "glTexSubImage2D")
static native void _wglTexSubImage2D(int target, int level, int offsetx, int offsety, int width, int height,
int format, int type, ArrayBufferView typedArray, int offset);
@ -658,6 +658,9 @@ public class PlatformOpenGL {
@Import(module = "platformOpenGL", name = "glDrawElements")
public static native void _wglDrawElements(int mode, int count, int type, int offset);
@Import(module = "platformOpenGL", name = "glDrawRangeElements")
public static native void _wglDrawRangeElements(int mode, int start, int end, int count, int type, int offset);
@Import(module = "platformOpenGL", name = "glDrawArraysInstanced")
public static native void _wglDrawArraysInstanced(int mode, int first, int count, int instanced);

View File

@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.teavm.interop.Address;
import org.teavm.interop.Import;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject;
@ -32,6 +33,7 @@ import org.teavm.jso.typedarrays.Uint8Array;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime.JSEagRuntimeEvent;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.MemoryStack;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.WASMGCDirectArrayConverter;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.WASMGCDirectArrayCopy;
import net.lax1dude.eaglercraft.v1_8.internal.wasm_gc_teavm.BetterJSStringConverter;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
@ -226,8 +228,10 @@ public class PlatformWebView {
}else if(packet.type == SPacketWebViewMessageV4EAG.TYPE_BINARY) {
MemoryStack.push();
try {
sendBinaryMessage(BetterJSStringConverter.stringToJS(currentMessageChannelName),
WASMGCDirectArrayConverter.byteArrayToStackU8Array(packet.data));
int len = packet.data.length;
Address addr = MemoryStack.malloc(len);
WASMGCDirectArrayCopy.memcpy(addr, packet.data, 0, len);
sendBinaryMessage(BetterJSStringConverter.stringToJS(currentMessageChannelName), addr, len);
}finally {
MemoryStack.pop();
}
@ -241,7 +245,7 @@ public class PlatformWebView {
private static native void sendStringMessage(JSString ch, JSString str);
@Import(module = "platformWebView", name = "sendBinaryMessage")
private static native void sendBinaryMessage(JSString ch, Uint8Array bin);
private static native void sendBinaryMessage(JSString ch, Address addr, int length);
private static void sendMessageToServer(String channelName, int type, byte[] data) {
if(channelName.length() > 255) {

View File

@ -16,6 +16,7 @@
package net.lax1dude.eaglercraft.v1_8.internal.wasm_gc_teavm;
import org.teavm.interop.Address;
import org.teavm.interop.Import;
import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty;
@ -124,16 +125,14 @@ public class IndexedDBFilesystem implements IEaglerFilesystem {
@Override
public void eaglerWrite(String pathName, ByteBuffer data) {
int len = data.remaining();
Uint8Array arr = new Uint8Array(len);
arr.set(WASMGCBufferAllocator.getByteBufferView(data));
if(!eaglerWrite(database, BetterJSStringConverter.stringToJS(pathName), arr.getBuffer())) {
throw new EaglerFileSystemException("Failed to write " + len + " byte file to indexeddb table: " + pathName);
if(!eaglerWrite(database, BetterJSStringConverter.stringToJS(pathName),
WASMGCBufferAllocator.getByteBufferAddress(data), data.remaining())) {
throw new EaglerFileSystemException("Failed to write " + data.remaining() + " byte file to indexeddb table: " + pathName);
}
}
@Import(module = "platformFilesystem", name = "eaglerWrite")
private static native boolean eaglerWrite(IDBDatabase database, JSString pathName, ArrayBuffer arr);
private static native boolean eaglerWrite(IDBDatabase database, JSString pathName, Address addr, int length);
@Override
public boolean eaglerExists(String pathName) {

View File

@ -21,7 +21,6 @@ import java.util.List;
import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty;
import org.teavm.jso.core.JSString;
import org.teavm.jso.typedarrays.Uint8Array;
import net.lax1dude.eaglercraft.v1_8.EagUtils;

View File

@ -21,14 +21,14 @@ import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.teavm.interop.Address;
import org.teavm.interop.Import;
import org.teavm.jso.core.JSString;
import org.teavm.jso.typedarrays.Uint8Array;
import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.MemoryStack;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.WASMGCDirectArrayConverter;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.WASMGCDirectArrayCopy;
import net.lax1dude.eaglercraft.v1_8.internal.wasm_gc_teavm.BetterJSStringConverter;
import net.lax1dude.eaglercraft.v1_8.internal.wasm_gc_teavm.WASMGCClientConfigAdapter;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
@ -71,8 +71,10 @@ public class ClientPlatformSingleplayer {
}else {
MemoryStack.push();
try {
sendPacket0(BetterJSStringConverter.stringToJS(packet.channel),
WASMGCDirectArrayConverter.byteArrayToStackU8Array(packet.contents));
int len = packet.contents.length;
Address addr = MemoryStack.malloc(len);
WASMGCDirectArrayCopy.memcpy(addr, packet.contents, 0, len);
sendPacket0(BetterJSStringConverter.stringToJS(packet.channel), addr, len);
} finally {
MemoryStack.pop();
}
@ -80,7 +82,7 @@ public class ClientPlatformSingleplayer {
}
@Import(module = "clientPlatformSingleplayer", name = "sendPacket")
private static native void sendPacket0(JSString channel, Uint8Array arr);
private static native void sendPacket0(JSString channel, Address addr, int length);
public static List<IPCPacketData> recieveAllPacket() {
if(isSingleThreadMode) {

View File

@ -22,11 +22,11 @@ import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
import org.teavm.interop.Address;
import org.teavm.interop.Import;
import org.teavm.jso.JSFunctor;
import org.teavm.jso.JSObject;
import org.teavm.jso.core.JSString;
import org.teavm.jso.typedarrays.Uint8Array;
import net.lax1dude.eaglercraft.v1_8.Filesystem;
import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapter;
@ -34,7 +34,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.IEaglerFilesystem;
import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.MemoryStack;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.WASMGCDirectArrayConverter;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.WASMGCDirectArrayCopy;
import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2;
import net.lax1dude.eaglercraft.v1_8.internal.wasm_gc_teavm.BetterJSStringConverter;
import net.lax1dude.eaglercraft.v1_8.internal.wasm_gc_teavm.WASMGCClientConfigAdapter;
@ -74,8 +74,10 @@ public class ServerPlatformSingleplayer {
}else {
MemoryStack.push();
try {
sendPacket0(BetterJSStringConverter.stringToJS(packet.channel),
WASMGCDirectArrayConverter.byteArrayToStackU8Array(packet.contents));
int len = packet.contents.length;
Address addr = MemoryStack.malloc(len);
WASMGCDirectArrayCopy.memcpy(addr, packet.contents, 0, len);
sendPacket0(BetterJSStringConverter.stringToJS(packet.channel), addr, len);
} finally {
MemoryStack.pop();
}
@ -83,7 +85,7 @@ public class ServerPlatformSingleplayer {
}
@Import(module = "serverPlatformSingleplayer", name = "sendPacket")
private static native void sendPacket0(JSString channel, Uint8Array arr);
private static native void sendPacket0(JSString channel, Address addr, int length);
public static List<IPCPacketData> recieveAllPacket() {
if(singleThreadMode) {

View File

@ -100,8 +100,13 @@ function initializeClientPlatfSP(spImports) {
});
}));
const classesTEADBGCopy = new Int8Array(classesTEADBG.length);
classesTEADBGCopy.set(classesTEADBG, 0);
const transferList = [];
var classesTEADBGCopy = null;
if(classesTEADBG) {
classesTEADBGCopy = classesTEADBG.buffer.slice(classesTEADBG.byteOffset, classesTEADBG.byteOffset + classesTEADBG.byteLength);
transferList.push(classesTEADBGCopy);
}
var eagRuntimeJS;
try {
@ -116,13 +121,15 @@ function initializeClientPlatfSP(spImports) {
return false;
}
transferList.push(eagRuntimeJS);
workerObj.postMessage({
"eaglercraftXOpts": eaglercraftXOpts,
"eagruntimeJS": eagRuntimeJS,
"classesWASM": classesWASMModule,
"classesDeobfWASM": classesDeobfWASMModule,
"classesTEADBG": classesTEADBGCopy.buffer
});
"classesTEADBG": classesTEADBGCopy
}, transferList);
return true;
};
@ -131,16 +138,16 @@ function initializeClientPlatfSP(spImports) {
/**
* @param {string} channel
* @param {Uint8Array} arr
* @param {number} addr
* @param {number} length
*/
spImports["sendPacket"] = function(channel, arr) {
spImports["sendPacket"] = function(channel, addr, length) {
if(workerObj) {
const copiedArray = new Uint8Array(arr.length);
copiedArray.set(arr, 0);
const copiedArray = heapArrayBuffer.slice(addr, addr + length);
workerObj.postMessage({
"ch": channel,
"dat": copiedArray.buffer
}, [copiedArray.buffer]);
"dat": copiedArray
}, [copiedArray]);
}
};

View File

@ -45,7 +45,7 @@ async function entryPoint() {
const teavm = await wasmGC.load(classesWASM, {
stackDeobfuscator: {
enabled: true,
enabled: !!(classesDeobfWASM && classesTEADBGURL),
path: classesDeobfWASM,
infoLocation: "external",
externalInfoPath: classesTEADBGURL

View File

@ -106,6 +106,8 @@ var keepAliveCallback = null;
var showDebugConsole = null;
/** @type {function()|null} */
var resetSettings = null;
/** @type {function()|null} */
var handleVisibilityChange = null;
const runtimeOpts = {
localStorageNamespace: "_eaglercraftX",

View File

@ -16,6 +16,9 @@
const platfAudioName = "platformAudio";
/** @type {HTMLAudioElement|null} */
var silenceElement = null;
function setCurrentAudioContext(audioContext, audioImports) {
/**
@ -26,25 +29,41 @@ function setCurrentAudioContext(audioContext, audioImports) {
};
/**
* @param {Uint8Array} fileData
* @param {number} addr
* @param {number} length
*/
audioImports["initKeepAliveHack"] = function(fileData) {
const copiedData = new Uint8Array(fileData.length);
copiedData.set(fileData, 0);
audioImports["initKeepAliveHack"] = function(addr, length) {
const copiedData = heapArrayBuffer.slice(addr, addr + length);
const copiedDataURI = URL.createObjectURL(new Blob([copiedData], {type: "audio/wav"}));
const audioElement = /** @type {HTMLAudioElement} */ (document.createElement("audio"));
audioElement.classList.add("_eaglercraftX_keepalive_hack");
audioElement.setAttribute("style", "display:none;");
audioElement.autoplay = true;
audioElement.autoplay = false;
audioElement.loop = true;
audioElement.addEventListener("seeked", function() {
// NOP, wakes up the browser's event loop
});
audioElement.addEventListener("canplay", function() {
if (silenceElement && document.visibilityState === "hidden") {
silenceElement.play();
}
});
const sourceElement = /** @type {HTMLSourceElement} */ (document.createElement("source"));
sourceElement.type = "audio/wav";
sourceElement.src = copiedDataURI;
audioElement.appendChild(sourceElement);
audioElement.addEventListener("seeked", function() {
// NOP, wakes up the browser's event loop
});
parentElement.appendChild(audioElement);
silenceElement = audioElement;
};
handleVisibilityChange = function() {
if (silenceElement) {
if (document.visibilityState === "hidden") {
silenceElement.play();
} else {
silenceElement.pause();
}
}
};
/**

View File

@ -144,13 +144,24 @@ function eaglerReadImpl(database, pathName) {
eagruntimeImpl.platformFilesystem["eaglerRead"] = new WebAssembly.Suspending(eaglerReadImpl);
/**
* @param {IDBDatabase} database
* @param {string} pathName
* @param {number} addr
* @param {number} length
* @return {Promise}
*/
function eaglerWriteImpl(database, pathName, addr, length) {
return eaglerWriteImpl0(database, pathName, heapArrayBuffer.slice(addr, addr + length));
}
/**
* @param {IDBDatabase} database
* @param {string} pathName
* @param {ArrayBuffer} arr
* @return {Promise}
*/
function eaglerWriteImpl(database, pathName, arr) {
function eaglerWriteImpl0(database, pathName, arr) {
return new Promise(function(resolve) {
const tx = database.transaction("filesystem", "readwrite");
const r = tx.objectStore("filesystem").put(writeDBRow(pathName, arr));
@ -193,7 +204,7 @@ eagruntimeImpl.platformFilesystem["eaglerExists"] = new WebAssembly.Suspending(e
*/
async function eaglerMoveImpl(database, pathNameOld, pathNameNew) {
const oldData = await eaglerReadImpl(database, pathNameOld);
if(!oldData || !(await eaglerWriteImpl(database, pathNameNew, oldData))) {
if(!oldData || !(await eaglerWriteImpl0(database, pathNameNew, oldData))) {
return false;
}
return await eaglerDeleteImpl(database, pathNameOld);
@ -209,7 +220,7 @@ eagruntimeImpl.platformFilesystem["eaglerMove"] = new WebAssembly.Suspending(eag
*/
async function eaglerCopyImpl(database, pathNameOld, pathNameNew) {
const oldData = await eaglerReadImpl(database, pathNameOld);
return oldData && (await eaglerWriteImpl(database, pathNameNew, oldData));
return oldData && (await eaglerWriteImpl0(database, pathNameNew, oldData));
}
eagruntimeImpl.platformFilesystem["eaglerCopy"] = new WebAssembly.Suspending(eaglerCopyImpl);

View File

@ -118,7 +118,8 @@ async function initPlatformInput(inputImports) {
blur: null,
pointerlock: null,
pointerlockerr: null,
fullscreenChange: null
fullscreenChange: null,
visibilitychange: null
};
touchKeyboardOpenZone = document.createElement("div");
@ -351,6 +352,11 @@ async function initPlatformInput(inputImports) {
pushEvent(EVENT_TYPE_INPUT, EVENT_INPUT_FOCUS, null);
});
document.addEventListener("visibilitychange", currentEventListeners.visibilitychange = function(/** Event */ evt) {
if (handleVisibilityChange)
handleVisibilityChange();
});
/**
* @param {number} evtType
* @param {KeyboardEvent} evt
@ -1138,6 +1144,10 @@ async function initPlatformInput(inputImports) {
window.removeEventListener("blur", /** @type {function(Event)} */ (currentEventListeners.blur));
currentEventListeners.blur = null;
}
if(currentEventListeners.visibilitychange) {
document.removeEventListener("visibilitychange", currentEventListeners.visibilitychange);
currentEventListeners.visibilitychange = null;
}
if(currentEventListeners.pointerlock) {
document.removeEventListener("pointerlockchange", /** @type {function(Event)} */ (currentEventListeners.pointerlock));
currentEventListeners.pointerlock = null;

View File

@ -99,7 +99,7 @@ function setCurrentGLContext(ctx, glesVersIn, allowExts, glImports) {
glImports["glColorMask"] = ctx.colorMask.bind(ctx);
glImports["glDrawBuffers"] = glesVersIn >= 300 ? ctx.drawBuffers.bind(ctx) : unsupportedFunc(platfOpenGLName, "glDrawBuffers");
glImports["glReadBuffer"] = glesVersIn >= 300 ? ctx.readBuffer.bind(ctx) : unsupportedFunc(platfOpenGLName, "glReadBuffer");
glImports["glReadPixels"] = glImports["glReadPixels0"] = ctx.readPixels.bind(ctx);
glImports["glReadPixels"] = ctx.readPixels.bind(ctx);
glImports["glPolygonOffset"] = ctx.polygonOffset.bind(ctx);
glImports["glLineWidth"] = ctx.lineWidth.bind(ctx);
glImports["glGenBuffers"] = ctx.createBuffer.bind(ctx);
@ -117,8 +117,8 @@ function setCurrentGLContext(ctx, glesVersIn, allowExts, glImports) {
glImports["glDeleteRenderbuffer"] = ctx.deleteRenderbuffer.bind(ctx);
glImports["glDeleteQueries"] = glesVersIn >= 300 ? ctx.deleteQuery.bind(ctx) : unsupportedFunc(platfOpenGLName, "glDeleteQueries");
glImports["glBindBuffer"] = ctx.bindBuffer.bind(ctx);
glImports["glBufferData"] = glImports["glBufferData0"] = ctx.bufferData.bind(ctx);
glImports["glBufferSubData"] = glImports["glBufferSubData0"] = ctx.bufferSubData.bind(ctx);
glImports["glBufferData"] = ctx.bufferData.bind(ctx);
glImports["glBufferSubData"] = ctx.bufferSubData.bind(ctx);
glImports["glEnableVertexAttribArray"] = ctx.enableVertexAttribArray.bind(ctx);
glImports["glDisableVertexAttribArray"] = ctx.disableVertexAttribArray.bind(ctx);
glImports["glVertexAttribPointer"] = ctx.vertexAttribPointer.bind(ctx);
@ -126,9 +126,9 @@ function setCurrentGLContext(ctx, glesVersIn, allowExts, glImports) {
glImports["glBindTexture"] = ctx.bindTexture.bind(ctx);
glImports["glTexParameterf"] = ctx.texParameterf.bind(ctx);
glImports["glTexParameteri"] = ctx.texParameteri.bind(ctx);
glImports["glTexImage3D"] = glImports["glTexImage3D0"] = glesVersIn >= 300 ? ctx.texImage3D.bind(ctx) : unsupportedFunc(platfOpenGLName, "glTexImage3D");
glImports["glTexImage2D"] = glImports["glTexImage2D0"] = ctx.texImage2D.bind(ctx);
glImports["glTexSubImage2D"] = glImports["glTexSubImage2D0"] = ctx.texSubImage2D.bind(ctx);
glImports["glTexImage3D"] = glesVersIn >= 300 ? ctx.texImage3D.bind(ctx) : unsupportedFunc(platfOpenGLName, "glTexImage3D");
glImports["glTexImage2D"] = ctx.texImage2D.bind(ctx);
glImports["glTexSubImage2D"] = ctx.texSubImage2D.bind(ctx);
glImports["glCopyTexSubImage2D"] = ctx.copyTexSubImage2D.bind(ctx);
glImports["glTexStorage2D"] = glesVersIn >= 300 ? ctx.texStorage2D.bind(ctx) : unsupportedFunc(platfOpenGLName, "glTexStorage2D");
glImports["glPixelStorei"] = ctx.pixelStorei.bind(ctx);
@ -145,6 +145,7 @@ function setCurrentGLContext(ctx, glesVersIn, allowExts, glImports) {
glImports["glGetProgramInfoLog"] = ctx.getProgramInfoLog.bind(ctx);
glImports["glDrawArrays"] = ctx.drawArrays.bind(ctx);
glImports["glDrawElements"] = ctx.drawElements.bind(ctx);
glImports["glDrawRangeElements"] = glesVersIn >= 300 ? ctx.drawRangeElements.bind(ctx) : unsupportedFunc(platfOpenGLName, "glDrawRangeElements");
glImports["glBindAttribLocation"] = ctx.bindAttribLocation.bind(ctx);
glImports["glGetAttribLocation"] = ctx.getAttribLocation.bind(ctx);
glImports["glGetUniformLocation"] = ctx.getUniformLocation.bind(ctx);
@ -299,7 +300,6 @@ function setNoGLContext(glImports) {
setUnsupportedFunc(glImports, platfOpenGLName, "glDrawBuffers");
setUnsupportedFunc(glImports, platfOpenGLName, "glReadBuffer");
setUnsupportedFunc(glImports, platfOpenGLName, "glReadPixels");
setUnsupportedFunc(glImports, platfOpenGLName, "glReadPixels0");
setUnsupportedFunc(glImports, platfOpenGLName, "glPolygonOffset");
setUnsupportedFunc(glImports, platfOpenGLName, "glLineWidth");
setUnsupportedFunc(glImports, platfOpenGLName, "glGenBuffers");
@ -318,9 +318,7 @@ function setNoGLContext(glImports) {
setUnsupportedFunc(glImports, platfOpenGLName, "glDeleteQueries");
setUnsupportedFunc(glImports, platfOpenGLName, "glBindBuffer");
setUnsupportedFunc(glImports, platfOpenGLName, "glBufferData");
setUnsupportedFunc(glImports, platfOpenGLName, "glBufferData0");
setUnsupportedFunc(glImports, platfOpenGLName, "glBufferSubData");
setUnsupportedFunc(glImports, platfOpenGLName, "glBufferSubData0");
setUnsupportedFunc(glImports, platfOpenGLName, "glEnableVertexAttribArray");
setUnsupportedFunc(glImports, platfOpenGLName, "glDisableVertexAttribArray");
setUnsupportedFunc(glImports, platfOpenGLName, "glVertexAttribPointer");
@ -329,11 +327,8 @@ function setNoGLContext(glImports) {
setUnsupportedFunc(glImports, platfOpenGLName, "glTexParameterf");
setUnsupportedFunc(glImports, platfOpenGLName, "glTexParameteri");
setUnsupportedFunc(glImports, platfOpenGLName, "glTexImage3D");
setUnsupportedFunc(glImports, platfOpenGLName, "glTexImage3D0");
setUnsupportedFunc(glImports, platfOpenGLName, "glTexImage2D");
setUnsupportedFunc(glImports, platfOpenGLName, "glTexImage2D0");
setUnsupportedFunc(glImports, platfOpenGLName, "glTexSubImage2D");
setUnsupportedFunc(glImports, platfOpenGLName, "glTexSubImage2D0");
setUnsupportedFunc(glImports, platfOpenGLName, "glCopyTexSubImage2D");
setUnsupportedFunc(glImports, platfOpenGLName, "glTexStorage2D");
setUnsupportedFunc(glImports, platfOpenGLName, "glPixelStorei");
@ -350,6 +345,7 @@ function setNoGLContext(glImports) {
setUnsupportedFunc(glImports, platfOpenGLName, "glGetProgramInfoLog");
setUnsupportedFunc(glImports, platfOpenGLName, "glDrawArrays");
setUnsupportedFunc(glImports, platfOpenGLName, "glDrawElements");
setUnsupportedFunc(glImports, platfOpenGLName, "glDrawRangeElements");
setUnsupportedFunc(glImports, platfOpenGLName, "glBindAttribLocation");
setUnsupportedFunc(glImports, platfOpenGLName, "glGetAttribLocation");
setUnsupportedFunc(glImports, platfOpenGLName, "glGetUniformLocation");

View File

@ -121,19 +121,18 @@ function initializePlatfWebView(webViewImports) {
/**
* @param {string} ch
* @param {Uint8Array} bin
* @param {number} addr
* @param {number} length
*/
webViewImports["sendBinaryMessage"] = function(ch, bin) {
webViewImports["sendBinaryMessage"] = function(ch, addr, length) {
try {
var w;
if(currentIFrame != null && (w = currentIFrame.contentWindow) != null) {
const copiedArray = new Uint8Array(bin.length);
copiedArray.set(bin, 0);
w.postMessage({
"ver": 1,
"channel": ch,
"type": "binary",
"data": copiedArray.buffer
"data": heapArrayBuffer.slice(addr, addr + length)
}, "*");
}else {
eagError("Server tried to send the WebView a message, but the message channel is not open!");

View File

@ -57,15 +57,15 @@ function initializeServerPlatfSP(spImports) {
/**
* @param {string} channel
* @param {Uint8Array} arr
* @param {number} addr
* @param {number} length
*/
spImports["sendPacket"] = function(channel, arr) {
const copiedArray = new Uint8Array(arr.length);
copiedArray.set(arr, 0);
spImports["sendPacket"] = function(channel, addr, length) {
const copiedArray = heapArrayBuffer.slice(addr, addr + length);
postMessage({
"ch": channel,
"dat": copiedArray.buffer
}, [copiedArray.buffer]);
"dat": copiedArray
}, [copiedArray]);
};
spImports["getAvailablePackets"] = serverMessageQueue.getLength.bind(serverMessageQueue);