mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2025-09-11 05:35:45 -04:00
Feat[renderer]: Add LTW renderer (#6477)
* Feat[launcher]: start introducing the Tinywrapper renderer * Feat[launcher]: add renderer, add compatibility checks * Chore[ltw]: update to latest * Style[code]: code cosmetic changes * Legal[ltw]: make LTW optional * Fix[ltw]: fix actions, add forgotten file * Workflow[ltw]: disallow forks, allow building on error
This commit is contained in:
parent
ed89b44d3b
commit
b28fc4a1f4
12
.github/workflows/android.yml
vendored
12
.github/workflows/android.yml
vendored
@ -26,6 +26,18 @@ jobs:
|
|||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
java-version: '8'
|
java-version: '8'
|
||||||
|
|
||||||
|
- name: Get LTW
|
||||||
|
uses: dawidd6/action-download-artifact@v2
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
github_token: ${{secrets.LTW_CLONER_SECRET}}
|
||||||
|
repo: PojavLauncherTeam/BigTinyWrapper
|
||||||
|
workflow: android.yml
|
||||||
|
workflow_conclusion: success
|
||||||
|
name: output-aar
|
||||||
|
path: app_pojavlauncher/libs
|
||||||
|
allow_forks: false
|
||||||
|
|
||||||
- name: Get JRE 8
|
- name: Get JRE 8
|
||||||
uses: dawidd6/action-download-artifact@v2
|
uses: dawidd6/action-download-artifact@v2
|
||||||
with:
|
with:
|
||||||
|
@ -227,5 +227,5 @@ dependencies {
|
|||||||
|
|
||||||
// implementation 'net.sourceforge.streamsupport:streamsupport-cfuture:1.7.0'
|
// implementation 'net.sourceforge.streamsupport:streamsupport-cfuture:1.7.0'
|
||||||
|
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,11 @@ import android.database.Cursor;
|
|||||||
import android.hardware.Sensor;
|
import android.hardware.Sensor;
|
||||||
import android.hardware.SensorManager;
|
import android.hardware.SensorManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.opengl.EGL14;
|
||||||
|
import android.opengl.EGLConfig;
|
||||||
|
import android.opengl.EGLContext;
|
||||||
|
import android.opengl.EGLDisplay;
|
||||||
|
import android.opengl.GLES30;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
@ -68,6 +73,7 @@ import net.kdt.pojavlaunch.utils.DownloadUtils;
|
|||||||
import net.kdt.pojavlaunch.utils.FileUtils;
|
import net.kdt.pojavlaunch.utils.FileUtils;
|
||||||
import net.kdt.pojavlaunch.utils.JREUtils;
|
import net.kdt.pojavlaunch.utils.JREUtils;
|
||||||
import net.kdt.pojavlaunch.utils.JSONUtils;
|
import net.kdt.pojavlaunch.utils.JSONUtils;
|
||||||
|
import net.kdt.pojavlaunch.utils.MCOptionUtils;
|
||||||
import net.kdt.pojavlaunch.utils.OldVersionsUtils;
|
import net.kdt.pojavlaunch.utils.OldVersionsUtils;
|
||||||
import net.kdt.pojavlaunch.value.DependentLibrary;
|
import net.kdt.pojavlaunch.value.DependentLibrary;
|
||||||
import net.kdt.pojavlaunch.value.MinecraftAccount;
|
import net.kdt.pojavlaunch.value.MinecraftAccount;
|
||||||
@ -178,6 +184,97 @@ public final class Tools {
|
|||||||
NATIVE_LIB_DIR = ctx.getApplicationInfo().nativeLibraryDir;
|
NATIVE_LIB_DIR = ctx.getApplicationInfo().nativeLibraryDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optimization mods based on Sodium can mitigate the render distance issue. Check if Sodium
|
||||||
|
* or its derivative is currently installed to skip the render distance check.
|
||||||
|
* @param gameDir current game directory
|
||||||
|
* @return whether sodium or a sodium-based mod is installed
|
||||||
|
*/
|
||||||
|
private static boolean hasSodium(File gameDir) {
|
||||||
|
File modsDir = new File(gameDir, "mods");
|
||||||
|
File[] mods = modsDir.listFiles(file -> file.isFile() && file.getName().endsWith(".jar"));
|
||||||
|
if(mods == null) return false;
|
||||||
|
for(File file : mods) {
|
||||||
|
String name = file.getName();
|
||||||
|
if(name.contains("sodium") ||
|
||||||
|
name.contains("embeddium") ||
|
||||||
|
name.contains("rubidium")) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize OpenGL and do checks to see if the GPU of the device is affected by the render
|
||||||
|
* distance issue.
|
||||||
|
|
||||||
|
* Currently only checks whether the user has an Adreno GPU capable of OpenGL ES 3
|
||||||
|
* and surfaceless rendering installed.
|
||||||
|
|
||||||
|
* This issue is caused by a very severe limit on the amount of GL buffer names that could be allocated
|
||||||
|
* by the Adreno properietary GLES driver.
|
||||||
|
|
||||||
|
* @return whether the GPU is affected by the Large Thin Wrapper render distance issue on vanilla
|
||||||
|
*/
|
||||||
|
private static boolean affectedByRenderDistanceIssue() {
|
||||||
|
EGLDisplay eglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
|
||||||
|
if(eglDisplay == EGL14.EGL_NO_DISPLAY || !EGL14.eglInitialize(eglDisplay, null, 0, null, 0)) return false;
|
||||||
|
int[] egl_attributes = new int[] {
|
||||||
|
EGL14.EGL_BLUE_SIZE, 8,
|
||||||
|
EGL14.EGL_GREEN_SIZE, 8,
|
||||||
|
EGL14.EGL_RED_SIZE, 8,
|
||||||
|
EGL14.EGL_ALPHA_SIZE, 8,
|
||||||
|
EGL14.EGL_DEPTH_SIZE, 24,
|
||||||
|
EGL14.EGL_SURFACE_TYPE, EGL14.EGL_PBUFFER_BIT,
|
||||||
|
EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
|
||||||
|
EGL14.EGL_NONE
|
||||||
|
};
|
||||||
|
EGLConfig[] config = new EGLConfig[1];
|
||||||
|
int[] num_configs = new int[]{0};
|
||||||
|
if(!EGL14.eglChooseConfig(eglDisplay, egl_attributes, 0, config, 0, 1, num_configs, 0) || num_configs[0] == 0) {
|
||||||
|
EGL14.eglTerminate(eglDisplay);
|
||||||
|
Log.e("CheckVendor", "Failed to choose an EGL config");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int[] egl_context_attributes = new int[] { EGL14.EGL_CONTEXT_CLIENT_VERSION, 3, EGL14.EGL_NONE };
|
||||||
|
EGLContext context = EGL14.eglCreateContext(eglDisplay, config[0], EGL14.EGL_NO_CONTEXT, egl_context_attributes, 0);
|
||||||
|
if(context == EGL14.EGL_NO_CONTEXT) {
|
||||||
|
Log.e("CheckVendor", "Failed to create a context");
|
||||||
|
EGL14.eglTerminate(eglDisplay);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!EGL14.eglMakeCurrent(eglDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, context)) {
|
||||||
|
Log.e("CheckVendor", "Failed to make context current");
|
||||||
|
EGL14.eglDestroyContext(eglDisplay, context);
|
||||||
|
EGL14.eglTerminate(eglDisplay);
|
||||||
|
}
|
||||||
|
boolean is_adreno = GLES30.glGetString(GLES30.GL_VENDOR).equals("Qualcomm") &&
|
||||||
|
GLES30.glGetString(GLES30.GL_RENDERER).contains("Adreno");
|
||||||
|
Log.e("CheckVendor", "Running Adreno graphics: "+is_adreno);
|
||||||
|
EGL14.eglMakeCurrent(eglDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
|
||||||
|
EGL14.eglDestroyContext(eglDisplay, context);
|
||||||
|
EGL14.eglTerminate(eglDisplay);
|
||||||
|
return is_adreno;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean checkRenderDistance(File gamedir) {
|
||||||
|
if(!"opengles3_ltw".equals(Tools.LOCAL_RENDERER)) return false;
|
||||||
|
if(!affectedByRenderDistanceIssue()) return false;
|
||||||
|
if(hasSodium(gamedir)) return false;
|
||||||
|
|
||||||
|
int renderDistance;
|
||||||
|
try {
|
||||||
|
MCOptionUtils.load();
|
||||||
|
String renderDistanceString = MCOptionUtils.get("renderDistance");
|
||||||
|
renderDistance = Integer.parseInt(renderDistanceString);
|
||||||
|
}catch (Exception e) {
|
||||||
|
Log.e("Tools", "Failed to check render distance", e);
|
||||||
|
renderDistance = 12; // Assume Minecraft's default render distance
|
||||||
|
}
|
||||||
|
// 7 is the render distance "magic number" above which MC creates too many buffers
|
||||||
|
// for Adreno's OpenGL ES implementation
|
||||||
|
return renderDistance > 7;
|
||||||
|
}
|
||||||
|
|
||||||
public static void launchMinecraft(final AppCompatActivity activity, MinecraftAccount minecraftAccount,
|
public static void launchMinecraft(final AppCompatActivity activity, MinecraftAccount minecraftAccount,
|
||||||
MinecraftProfile minecraftProfile, String versionId, int versionJavaRequirement) throws Throwable {
|
MinecraftProfile minecraftProfile, String versionId, int versionJavaRequirement) throws Throwable {
|
||||||
int freeDeviceMemory = getFreeDeviceMemory(activity);
|
int freeDeviceMemory = getFreeDeviceMemory(activity);
|
||||||
@ -203,10 +300,27 @@ public final class Tools {
|
|||||||
// to start after the activity is shown again
|
// to start after the activity is shown again
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Runtime runtime = MultiRTUtils.forceReread(Tools.pickRuntime(minecraftProfile, versionJavaRequirement));
|
|
||||||
JMinecraftVersionList.Version versionInfo = Tools.getVersionInfo(versionId);
|
|
||||||
LauncherProfiles.load();
|
LauncherProfiles.load();
|
||||||
File gamedir = Tools.getGameDirPath(minecraftProfile);
|
File gamedir = Tools.getGameDirPath(minecraftProfile);
|
||||||
|
if(checkRenderDistance(gamedir)) {
|
||||||
|
LifecycleAwareAlertDialog.DialogCreator dialogCreator = ((alertDialog, dialogBuilder) ->
|
||||||
|
dialogBuilder.setMessage(activity.getString(R.string.ltw_render_distance_warning_msg))
|
||||||
|
.setPositiveButton(android.R.string.ok, (d, w)->{}));
|
||||||
|
if(LifecycleAwareAlertDialog.haltOnDialog(activity.getLifecycle(), activity, dialogCreator)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If the code goes here, it means that the user clicked "OK". Fix the render distance.
|
||||||
|
try {
|
||||||
|
MCOptionUtils.set("renderDistance", "7");
|
||||||
|
MCOptionUtils.save();
|
||||||
|
}catch (Exception e) {
|
||||||
|
Log.e("Tools", "Failed to fix render distance setting", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Runtime runtime = MultiRTUtils.forceReread(Tools.pickRuntime(minecraftProfile, versionJavaRequirement));
|
||||||
|
JMinecraftVersionList.Version versionInfo = Tools.getVersionInfo(versionId);
|
||||||
|
|
||||||
|
|
||||||
// Pre-process specific files
|
// Pre-process specific files
|
||||||
@ -1271,12 +1385,16 @@ public final class Tools {
|
|||||||
boolean deviceHasVulkan = checkVulkanSupport(context.getPackageManager());
|
boolean deviceHasVulkan = checkVulkanSupport(context.getPackageManager());
|
||||||
// Currently, only 32-bit x86 does not have the Zink binary
|
// Currently, only 32-bit x86 does not have the Zink binary
|
||||||
boolean deviceHasZinkBinary = !(Architecture.is32BitsDevice() && Architecture.isx86Device());
|
boolean deviceHasZinkBinary = !(Architecture.is32BitsDevice() && Architecture.isx86Device());
|
||||||
|
boolean deviceHasOpenGLES3 = JREUtils.getDetectedVersion() >= 3;
|
||||||
|
// LTW is an optional proprietary dependency
|
||||||
|
boolean appHasLtw = new File(Tools.NATIVE_LIB_DIR, "libltw.so").exists();
|
||||||
List<String> rendererIds = new ArrayList<>(defaultRenderers.length);
|
List<String> rendererIds = new ArrayList<>(defaultRenderers.length);
|
||||||
List<String> rendererNames = new ArrayList<>(defaultRendererNames.length);
|
List<String> rendererNames = new ArrayList<>(defaultRendererNames.length);
|
||||||
for(int i = 0; i < defaultRenderers.length; i++) {
|
for(int i = 0; i < defaultRenderers.length; i++) {
|
||||||
String rendererId = defaultRenderers[i];
|
String rendererId = defaultRenderers[i];
|
||||||
if(rendererId.contains("vulkan") && !deviceHasVulkan) continue;
|
if(rendererId.contains("vulkan") && !deviceHasVulkan) continue;
|
||||||
if(rendererId.contains("zink") && !deviceHasZinkBinary) continue;
|
if(rendererId.contains("zink") && !deviceHasZinkBinary) continue;
|
||||||
|
if(rendererId.contains("ltw") && (!deviceHasOpenGLES3 || !appHasLtw)) continue;
|
||||||
rendererIds.add(rendererId);
|
rendererIds.add(rendererId);
|
||||||
rendererNames.add(defaultRendererNames[i]);
|
rendererNames.add(defaultRendererNames[i]);
|
||||||
}
|
}
|
||||||
|
@ -220,9 +220,9 @@ public class JREUtils {
|
|||||||
|
|
||||||
if(LOCAL_RENDERER != null) {
|
if(LOCAL_RENDERER != null) {
|
||||||
envMap.put("POJAV_RENDERER", LOCAL_RENDERER);
|
envMap.put("POJAV_RENDERER", LOCAL_RENDERER);
|
||||||
if(LOCAL_RENDERER.equals("opengles3_desktopgl_angle_vulkan")) {
|
if(LOCAL_RENDERER.equals("opengles3_ltw")) {
|
||||||
envMap.put("LIBGL_ES", "3");
|
envMap.put("LIBGL_ES", "3");
|
||||||
envMap.put("POJAVEXEC_EGL","libEGL_angle.so"); // Use ANGLE EGL
|
envMap.put("POJAVEXEC_EGL","libltw.so"); // Use ANGLE EGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(LauncherPreferences.PREF_BIG_CORE_AFFINITY) envMap.put("POJAV_BIG_CORE_AFFINITY", "1");
|
if(LauncherPreferences.PREF_BIG_CORE_AFFINITY) envMap.put("POJAV_BIG_CORE_AFFINITY", "1");
|
||||||
@ -464,7 +464,7 @@ public class JREUtils {
|
|||||||
case "opengles3":
|
case "opengles3":
|
||||||
renderLibrary = "libgl4es_114.so"; break;
|
renderLibrary = "libgl4es_114.so"; break;
|
||||||
case "vulkan_zink": renderLibrary = "libOSMesa.so"; break;
|
case "vulkan_zink": renderLibrary = "libOSMesa.so"; break;
|
||||||
case "opengles3_desktopgl_angle_vulkan" : renderLibrary = "libtinywrapper.so"; break;
|
case "opengles3_ltw" : renderLibrary = "libltw.so"; break;
|
||||||
default:
|
default:
|
||||||
Log.w("RENDER_LIBRARY", "No renderer selected, defaulting to opengles2");
|
Log.w("RENDER_LIBRARY", "No renderer selected, defaulting to opengles2");
|
||||||
renderLibrary = "libgl4es_114.so";
|
renderLibrary = "libgl4es_114.so";
|
||||||
|
@ -8,18 +8,6 @@ HERE_PATH := $(LOCAL_PATH)
|
|||||||
|
|
||||||
LOCAL_PATH := $(HERE_PATH)
|
LOCAL_PATH := $(HERE_PATH)
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := angle_gles2
|
|
||||||
LOCAL_SRC_FILES := tinywrapper/angle-gles/$(TARGET_ARCH_ABI)/libGLESv2_angle.so
|
|
||||||
include $(PREBUILT_SHARED_LIBRARY)
|
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := tinywrapper
|
|
||||||
LOCAL_SHARED_LIBRARIES := angle_gles2
|
|
||||||
LOCAL_SRC_FILES := tinywrapper/main.c tinywrapper/string_utils.c
|
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/tinywrapper
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
|
||||||
|
|
||||||
$(call import-module,prefab/bytehook)
|
$(call import-module,prefab/bytehook)
|
||||||
LOCAL_PATH := $(HERE_PATH)
|
LOCAL_PATH := $(HERE_PATH)
|
||||||
|
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,201 +0,0 @@
|
|||||||
//#import <Foundation/Foundation.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <dlfcn.h>
|
|
||||||
|
|
||||||
#include "GL/gl.h"
|
|
||||||
#include "GLES3/gl32.h"
|
|
||||||
#include "string_utils.h"
|
|
||||||
|
|
||||||
#define LOOKUP_FUNC(func) \
|
|
||||||
if (!gles_##func) { \
|
|
||||||
gles_##func = dlsym(RTLD_NEXT, #func); \
|
|
||||||
} if (!gles_##func) { \
|
|
||||||
gles_##func = dlsym(RTLD_DEFAULT, #func); \
|
|
||||||
}
|
|
||||||
|
|
||||||
int proxy_width, proxy_height, proxy_intformat, maxTextureSize;
|
|
||||||
|
|
||||||
void glBindFragDataLocationEXT(GLuint program, GLuint colorNumber, const char * name);
|
|
||||||
|
|
||||||
void(*gles_glGetTexLevelParameteriv)(GLenum target, GLint level, GLenum pname, GLint *params);
|
|
||||||
void(*gles_glShaderSource)(GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length);
|
|
||||||
void(*gles_glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *data);
|
|
||||||
|
|
||||||
void glBindFragDataLocation(GLuint program, GLuint colorNumber, const char * name) {
|
|
||||||
glBindFragDataLocationEXT(program, colorNumber, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glClearDepth(GLdouble depth) {
|
|
||||||
glClearDepthf(depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *glMapBuffer(GLenum target, GLenum access) {
|
|
||||||
// Use: GL_EXT_map_buffer_range
|
|
||||||
|
|
||||||
GLenum access_range;
|
|
||||||
GLint length;
|
|
||||||
|
|
||||||
switch (target) {
|
|
||||||
// GL 4.2
|
|
||||||
case GL_ATOMIC_COUNTER_BUFFER:
|
|
||||||
|
|
||||||
// GL 4.3
|
|
||||||
case GL_DISPATCH_INDIRECT_BUFFER:
|
|
||||||
case GL_SHADER_STORAGE_BUFFER :
|
|
||||||
|
|
||||||
// GL 4.4
|
|
||||||
case GL_QUERY_BUFFER:
|
|
||||||
printf("ERROR: glMapBuffer unsupported target=0x%x", target);
|
|
||||||
break; // not supported for now
|
|
||||||
|
|
||||||
case GL_DRAW_INDIRECT_BUFFER:
|
|
||||||
case GL_TEXTURE_BUFFER:
|
|
||||||
printf("ERROR: glMapBuffer unimplemented target=0x%x", target);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (access) {
|
|
||||||
case GL_READ_ONLY:
|
|
||||||
access_range = GL_MAP_READ_BIT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GL_WRITE_ONLY:
|
|
||||||
access_range = GL_MAP_WRITE_BIT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GL_READ_WRITE:
|
|
||||||
access_range = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);
|
|
||||||
return glMapBufferRange(target, 0, length, access_range);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glShaderSource(GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length) {
|
|
||||||
LOOKUP_FUNC(glShaderSource)
|
|
||||||
|
|
||||||
// DBG(printf("glShaderSource(%d, %d, %p, %p)\n", shader, count, string, length);)
|
|
||||||
char *source = NULL;
|
|
||||||
char *converted;
|
|
||||||
|
|
||||||
// get the size of the shader sources and than concatenate in a single string
|
|
||||||
int l = 0;
|
|
||||||
for (int i=0; i<count; i++) l+=(length && length[i] >= 0)?length[i]:strlen(string[i]);
|
|
||||||
if (source) free(source);
|
|
||||||
source = calloc(1, l+1);
|
|
||||||
if(length) {
|
|
||||||
for (int i=0; i<count; i++) {
|
|
||||||
if(length[i] >= 0)
|
|
||||||
strncat(source, string[i], length[i]);
|
|
||||||
else
|
|
||||||
strcat(source, string[i]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i=0; i<count; i++)
|
|
||||||
strcat(source, string[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *source2 = strchr(source, '#');
|
|
||||||
if (!source2) {
|
|
||||||
source2 = source;
|
|
||||||
}
|
|
||||||
// are there #version?
|
|
||||||
if (!strncmp(source2, "#version ", 9)) {
|
|
||||||
converted = strdup(source2);
|
|
||||||
if (converted[9] == '1') {
|
|
||||||
if (converted[10] - '0' < 2) {
|
|
||||||
// 100, 110 -> 120
|
|
||||||
converted[10] = '2';
|
|
||||||
} else if (converted[10] - '0' < 6) {
|
|
||||||
// 130, 140, 150 -> 330
|
|
||||||
converted[9] = converted[10] = '3';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// remove "core", is it safe?
|
|
||||||
if (!strncmp(&converted[13], "core", 4)) {
|
|
||||||
strncpy(&converted[13], "\n//c", 4);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
converted = calloc(1, strlen(source) + 13);
|
|
||||||
strcpy(converted, "#version 120\n");
|
|
||||||
strcpy(&converted[13], strdup(source));
|
|
||||||
}
|
|
||||||
|
|
||||||
int convertedLen = strlen(converted);
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
// patch OptiFine 1.17.x
|
|
||||||
if (FindString(converted, "\nuniform mat4 textureMatrix = mat4(1.0);")) {
|
|
||||||
InplaceReplace(converted, &convertedLen, "\nuniform mat4 textureMatrix = mat4(1.0);", "\n#define textureMatrix mat4(1.0)");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// some needed exts
|
|
||||||
const char* extensions =
|
|
||||||
"#extension GL_EXT_blend_func_extended : enable\n"
|
|
||||||
// For OptiFine (see patch above)
|
|
||||||
"#extension GL_EXT_shader_non_constant_global_initializers : enable\n";
|
|
||||||
converted = InplaceInsert(GetLine(converted, 1), extensions, converted, &convertedLen);
|
|
||||||
|
|
||||||
gles_glShaderSource(shader, 1, (const GLchar * const*)((converted)?(&converted):(&source)), NULL);
|
|
||||||
|
|
||||||
free(source);
|
|
||||||
free(converted);
|
|
||||||
}
|
|
||||||
|
|
||||||
int isProxyTexture(GLenum target) {
|
|
||||||
switch (target) {
|
|
||||||
case GL_PROXY_TEXTURE_1D:
|
|
||||||
case GL_PROXY_TEXTURE_2D:
|
|
||||||
case GL_PROXY_TEXTURE_3D:
|
|
||||||
case GL_PROXY_TEXTURE_RECTANGLE_ARB:
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int inline nlevel(int size, int level) {
|
|
||||||
if(size) {
|
|
||||||
size>>=level;
|
|
||||||
if(!size) size=1;
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) {
|
|
||||||
LOOKUP_FUNC(glGetTexLevelParameteriv)
|
|
||||||
// NSLog("glGetTexLevelParameteriv(%x, %d, %x, %p)", target, level, pname, params);
|
|
||||||
if (isProxyTexture(target)) {
|
|
||||||
switch (pname) {
|
|
||||||
case GL_TEXTURE_WIDTH:
|
|
||||||
(*params) = nlevel(proxy_width,level);
|
|
||||||
break;
|
|
||||||
case GL_TEXTURE_HEIGHT:
|
|
||||||
(*params) = nlevel(proxy_height,level);
|
|
||||||
break;
|
|
||||||
case GL_TEXTURE_INTERNAL_FORMAT:
|
|
||||||
(*params) = proxy_intformat;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gles_glGetTexLevelParameteriv(target, level, pname, params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *data) {
|
|
||||||
LOOKUP_FUNC(glTexImage2D)
|
|
||||||
if (isProxyTexture(target)) {
|
|
||||||
if (!maxTextureSize) {
|
|
||||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
|
|
||||||
// maxTextureSize = 16384;
|
|
||||||
// NSLog(@"Maximum texture size: %d", maxTextureSize);
|
|
||||||
}
|
|
||||||
proxy_width = ((width<<level)>maxTextureSize)?0:width;
|
|
||||||
proxy_height = ((height<<level)>maxTextureSize)?0:height;
|
|
||||||
proxy_intformat = internalformat;
|
|
||||||
// swizzle_internalformat((GLenum *) &internalformat, format, type);
|
|
||||||
} else {
|
|
||||||
gles_glTexImage2D(target, level, internalformat, width, height, border, format, type, data);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,234 +0,0 @@
|
|||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "string_utils.h"
|
|
||||||
|
|
||||||
const char* AllSeparators = " \t\n\r.,;()[]{}-<>+*/%&\\\"'^$=!:?";
|
|
||||||
|
|
||||||
char* ResizeIfNeeded(char* pBuffer, int *size, int addsize);
|
|
||||||
|
|
||||||
char* InplaceReplace(char* pBuffer, int* size, const char* S, const char* D)
|
|
||||||
{
|
|
||||||
int lS = strlen(S), lD = strlen(D);
|
|
||||||
pBuffer = ResizeIfNeeded(pBuffer, size, (lD-lS)*CountString(pBuffer, S));
|
|
||||||
char* p = pBuffer;
|
|
||||||
while((p = strstr(p, S)))
|
|
||||||
{
|
|
||||||
// found an occurence of S
|
|
||||||
// check if good to replace, strchr also found '\0' :)
|
|
||||||
if(strchr(AllSeparators, p[lS])!=NULL && (p==pBuffer || strchr(AllSeparators, p[-1])!=NULL)) {
|
|
||||||
// move out rest of string
|
|
||||||
memmove(p+lD, p+lS, strlen(p)-lS+1);
|
|
||||||
// replace
|
|
||||||
memcpy(p, D, strlen(D));
|
|
||||||
// next
|
|
||||||
p+=lD;
|
|
||||||
} else p+=lS;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* InplaceInsert(char* pBuffer, const char* S, char* master, int* size)
|
|
||||||
{
|
|
||||||
char* m = ResizeIfNeeded(master, size, strlen(S));
|
|
||||||
if(m!=master) {
|
|
||||||
pBuffer += (m-master);
|
|
||||||
master = m;
|
|
||||||
}
|
|
||||||
char* p = pBuffer;
|
|
||||||
int lS = strlen(S), ll = strlen(pBuffer);
|
|
||||||
memmove(p+lS, p, ll+1);
|
|
||||||
memcpy(p, S, lS);
|
|
||||||
|
|
||||||
return master;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* GetLine(char* pBuffer, int num)
|
|
||||||
{
|
|
||||||
char *p = pBuffer;
|
|
||||||
while(num-- && (p=strstr(p, "\n"))) p+=strlen("\n");
|
|
||||||
return (p)?p:pBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CountLine(const char* pBuffer)
|
|
||||||
{
|
|
||||||
int n=0;
|
|
||||||
const char* p = pBuffer;
|
|
||||||
while((p=strstr(p, "\n"))) {
|
|
||||||
p+=strlen("\n");
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetLineFor(const char* pBuffer, const char* S)
|
|
||||||
{
|
|
||||||
int n=0;
|
|
||||||
const char* p = pBuffer;
|
|
||||||
const char* end = FindString(pBuffer, S);
|
|
||||||
if(!end)
|
|
||||||
return 0;
|
|
||||||
while((p=strstr(p, "\n"))) {
|
|
||||||
p+=strlen("\n");
|
|
||||||
n++;
|
|
||||||
if(p>=end)
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CountString(const char* pBuffer, const char* S)
|
|
||||||
{
|
|
||||||
const char* p = pBuffer;
|
|
||||||
int lS = strlen(S);
|
|
||||||
int n = 0;
|
|
||||||
while((p = strstr(p, S)))
|
|
||||||
{
|
|
||||||
// found an occurence of S
|
|
||||||
// check if good to count, strchr also found '\0' :)
|
|
||||||
if(strchr(AllSeparators, p[lS])!=NULL && (p==pBuffer || strchr(AllSeparators, p[-1])!=NULL))
|
|
||||||
n++;
|
|
||||||
p+=lS;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* FindString(const char* pBuffer, const char* S)
|
|
||||||
{
|
|
||||||
const char* p = pBuffer;
|
|
||||||
int lS = strlen(S);
|
|
||||||
while((p = strstr(p, S)))
|
|
||||||
{
|
|
||||||
// found an occurence of S
|
|
||||||
// check if good to count, strchr also found '\0' :)
|
|
||||||
if(strchr(AllSeparators, p[lS])!=NULL && (p==pBuffer || strchr(AllSeparators, p[-1])!=NULL))
|
|
||||||
return p;
|
|
||||||
p+=lS;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* FindStringNC(char* pBuffer, const char* S)
|
|
||||||
{
|
|
||||||
char* p = pBuffer;
|
|
||||||
int lS = strlen(S);
|
|
||||||
while((p = strstr(p, S)))
|
|
||||||
{
|
|
||||||
// found an occurence of S
|
|
||||||
// check if good to count, strchr also found '\0' :)
|
|
||||||
if(strchr(AllSeparators, p[lS])!=NULL && (p==pBuffer || strchr(AllSeparators, p[-1])!=NULL))
|
|
||||||
return p;
|
|
||||||
p+=lS;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* ResizeIfNeeded(char* pBuffer, int *size, int addsize) {
|
|
||||||
char* p = pBuffer;
|
|
||||||
int newsize = strlen(pBuffer)+addsize+1;
|
|
||||||
if (newsize>*size) {
|
|
||||||
newsize += 100;
|
|
||||||
p = (char*)realloc(pBuffer, newsize);
|
|
||||||
*size=newsize;
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* Append(char* pBuffer, int* size, const char* S) {
|
|
||||||
char* p =pBuffer;
|
|
||||||
p = ResizeIfNeeded(pBuffer, size, strlen(S));
|
|
||||||
strcat(p, S);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
int isBlank(char c) {
|
|
||||||
switch(c) {
|
|
||||||
case ' ':
|
|
||||||
case '\t':
|
|
||||||
case '\n':
|
|
||||||
case '\r':
|
|
||||||
case ':':
|
|
||||||
case ',':
|
|
||||||
case ';':
|
|
||||||
case '/':
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
char* StrNext(char *pBuffer, const char* S) {
|
|
||||||
if(!pBuffer) return NULL;
|
|
||||||
char *p = strstr(pBuffer, S);
|
|
||||||
return (p)?p:(p+strlen(S));
|
|
||||||
}
|
|
||||||
|
|
||||||
char* NextStr(char* pBuffer) {
|
|
||||||
if(!pBuffer) return NULL;
|
|
||||||
while(isBlank(*pBuffer))
|
|
||||||
++pBuffer;
|
|
||||||
return pBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* NextBlank(char* pBuffer) {
|
|
||||||
if(!pBuffer) return NULL;
|
|
||||||
while(!isBlank(*pBuffer))
|
|
||||||
++pBuffer;
|
|
||||||
return pBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* NextLine(char* pBuffer) {
|
|
||||||
if(!pBuffer) return NULL;
|
|
||||||
while(*pBuffer && *pBuffer!='\n')
|
|
||||||
++pBuffer;
|
|
||||||
return pBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* GetNextStr(char* pBuffer) {
|
|
||||||
static char buff[100] = {0};
|
|
||||||
buff[0] = '\0';
|
|
||||||
if(!pBuffer) return NULL;
|
|
||||||
char* p1 = NextStr(pBuffer);
|
|
||||||
if(!p1) return buff;
|
|
||||||
char* p2 = NextBlank(p1);
|
|
||||||
if(!p2) return buff;
|
|
||||||
int i=0;
|
|
||||||
while(p1!=p2 && i<99)
|
|
||||||
buff[i++] = *(p1++);
|
|
||||||
buff[i] = '\0';
|
|
||||||
return buff;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CountStringSimple(char* pBuffer, const char* S)
|
|
||||||
{
|
|
||||||
char* p = pBuffer;
|
|
||||||
int lS = strlen(S);
|
|
||||||
int n = 0;
|
|
||||||
while((p = strstr(p, S)))
|
|
||||||
{
|
|
||||||
// found an occurence of S
|
|
||||||
n++;
|
|
||||||
p+=lS;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* InplaceReplaceSimple(char* pBuffer, int* size, const char* S, const char* D)
|
|
||||||
{
|
|
||||||
int lS = strlen(S), lD = strlen(D);
|
|
||||||
pBuffer = ResizeIfNeeded(pBuffer, size, (lD-lS)*CountStringSimple(pBuffer, S));
|
|
||||||
char* p = pBuffer;
|
|
||||||
while((p = strstr(p, S)))
|
|
||||||
{
|
|
||||||
// found an occurence of S
|
|
||||||
// move out rest of string
|
|
||||||
memmove(p+lD, p+lS, strlen(p)-lS+1);
|
|
||||||
// replace
|
|
||||||
memcpy(p, D, strlen(D));
|
|
||||||
// next
|
|
||||||
p+=lD;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pBuffer;
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
#ifndef _GL4ES_STRING_UTILS_H_
|
|
||||||
#define _GL4ES_STRING_UTILS_H_
|
|
||||||
|
|
||||||
extern const char* AllSeparators;
|
|
||||||
|
|
||||||
const char* FindString(const char* pBuffer, const char* S);
|
|
||||||
char* FindStringNC(char* pBuffer, const char* S);
|
|
||||||
int CountString(const char* pBuffer, const char* S);
|
|
||||||
char* ResizeIfNeeded(char* pBuffer, int *size, int addsize);
|
|
||||||
char* InplaceReplace(char* pBuffer, int* size, const char* S, const char* D);
|
|
||||||
char* Append(char* pBuffer, int* size, const char* S);
|
|
||||||
char* InplaceInsert(char* pBuffer, const char* S, char* master, int* size);
|
|
||||||
char* GetLine(char* pBuffer, int num);
|
|
||||||
int CountLine(const char* pBuffer);
|
|
||||||
int GetLineFor(const char* pBuffer, const char* S); // get the line number for 1st occurent of S in pBuffer
|
|
||||||
char* StrNext(char *pBuffer, const char* S); // mostly as strstr, but go after the substring if found
|
|
||||||
//"blank" (space, tab, cr, lf,":", ",", ";", ".", "/")
|
|
||||||
char* NextStr(char* pBuffer); // go to next non "blank"
|
|
||||||
char* NextBlank(char* pBuffer); // go to next "blank"
|
|
||||||
char* NextLine(char* pBuffer); // go to next new line (crlf not included)
|
|
||||||
|
|
||||||
const char* GetNextStr(char* pBuffer); // get a (static) copy of next str (until next separator), can be a simple number or separator also
|
|
||||||
|
|
||||||
// those function don't try to be smart with separators...
|
|
||||||
int CountStringSimple(char* pBuffer, const char* S);
|
|
||||||
char* InplaceReplaceSimple(char* pBuffer, int* size, const char* S, const char* D);
|
|
||||||
|
|
||||||
|
|
||||||
#endif // _GL4ES_STRING_UTILS_H_
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -3,7 +3,7 @@
|
|||||||
<string-array name="renderer">
|
<string-array name="renderer">
|
||||||
<item name="1">@string/mcl_setting_renderer_gles2_4</item>
|
<item name="1">@string/mcl_setting_renderer_gles2_4</item>
|
||||||
<item name="2">@string/mcl_setting_renderer_vulkan_zink</item>
|
<item name="2">@string/mcl_setting_renderer_vulkan_zink</item>
|
||||||
<item name="3">@string/mcl_setting_renderer_angle</item>
|
<item name="3">@string/mcl_setting_renderer_ltw</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="menu_customcontrol">
|
<string-array name="menu_customcontrol">
|
||||||
@ -36,7 +36,7 @@
|
|||||||
<string-array name="renderer_values">
|
<string-array name="renderer_values">
|
||||||
<item>opengles2</item> <!-- gl4es_extra 1.1.4 with OpenGL ES 2/"3" -->
|
<item>opengles2</item> <!-- gl4es_extra 1.1.4 with OpenGL ES 2/"3" -->
|
||||||
<item>vulkan_zink</item> <!-- virglrenderer with OpenGL ES 3 -->
|
<item>vulkan_zink</item> <!-- virglrenderer with OpenGL ES 3 -->
|
||||||
<item>opengles3_desktopgl_angle_vulkan</item>
|
<item>opengles3_ltw</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="download_source_names">
|
<string-array name="download_source_names">
|
||||||
<item>@string/global_default</item>
|
<item>@string/global_default</item>
|
||||||
|
@ -66,7 +66,7 @@
|
|||||||
<string name="mcl_setting_category_renderer">Renderer</string>
|
<string name="mcl_setting_category_renderer">Renderer</string>
|
||||||
<string name="mcl_setting_renderer_gles2_4">Holy GL4ES - (all versions, fast)</string>
|
<string name="mcl_setting_renderer_gles2_4">Holy GL4ES - (all versions, fast)</string>
|
||||||
<string name="mcl_setting_renderer_vulkan_zink">Zink (Vulkan) - (all versions, mid)</string>
|
<string name="mcl_setting_renderer_vulkan_zink">Zink (Vulkan) - (all versions, mid)</string>
|
||||||
<string name="mcl_setting_renderer_angle">ANGLE (Vulkan) - (1.17+ only, mid)</string>
|
<string name="mcl_setting_renderer_ltw">LTW (OpenGL ES 3) - 1.17+ only</string>
|
||||||
<string name="mcl_setting_veroption_release">Release</string>
|
<string name="mcl_setting_veroption_release">Release</string>
|
||||||
<string name="mcl_setting_veroption_snapshot">Snapshot</string>
|
<string name="mcl_setting_veroption_snapshot">Snapshot</string>
|
||||||
<string name="mcl_setting_veroption_oldalpha">Old-alpha</string>
|
<string name="mcl_setting_veroption_oldalpha">Old-alpha</string>
|
||||||
@ -418,6 +418,7 @@
|
|||||||
<string name="preference_remap_controller_title">Change controller key bindings</string>
|
<string name="preference_remap_controller_title">Change controller key bindings</string>
|
||||||
<string name="preference_remap_controller_description">Allows you to modify the keyboard keys bound to each controller button</string>
|
<string name="preference_remap_controller_description">Allows you to modify the keyboard keys bound to each controller button</string>
|
||||||
<string name="mcl_button_discord">Discord</string>
|
<string name="mcl_button_discord">Discord</string>
|
||||||
|
<string name="ltw_render_distance_warning_msg">Your GPU is not capable of rendering above 7 render distance without Sodium or other similar mods. The render distance will be automatically reduced when you click "OK".</string>
|
||||||
<string name="mcl_button_open_directory">Open game directory</string>
|
<string name="mcl_button_open_directory">Open game directory</string>
|
||||||
<string name="discord_invite" translatable="false">https://discord.com/invite/aenk3EUvER</string>
|
<string name="discord_invite" translatable="false">https://discord.com/invite/aenk3EUvER</string>
|
||||||
<string name="local_login_bad_username_title">Unsuitable username</string>
|
<string name="local_login_bad_username_title">Unsuitable username</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user