Compare commits

...

3 Commits

Author SHA1 Message Date
0061edb3b2 2.3.12
All checks were successful
minecraft-pi-reborn/pipeline/head This commit looks good
2022-06-04 14:36:47 -04:00
baeeceeaac Slightly Faster 2022-06-04 14:34:15 -04:00
211bf265ff Optimizations & Fixes 2022-06-03 22:25:22 -04:00
13 changed files with 236 additions and 105 deletions

View File

@ -1 +1 @@
2.3.11
2.3.12

View File

@ -1,5 +1,9 @@
# Changelog
**2.3.12**
* Media Layer Proxy Optimizations
* Bug Fixes
**2.3.11**
* ``--version`` Command Line Option
* TPS Measured In Benchmark & Server

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

After

Width:  |  Height:  |  Size: 154 KiB

View File

@ -254,6 +254,7 @@ void bootstrap(int argc, char *argv[]) {
}
// Fix MCPI Dependencies
char new_mcpi_exe_path[] = MCPI_PATCHED_DIR "/XXXXXX";
{
// Log
DEBUG("Patching ELF Dependencies...");
@ -273,7 +274,7 @@ void bootstrap(int argc, char *argv[]) {
#endif
// Patch
patch_mcpi_elf_dependencies(resolved_path, linker);
patch_mcpi_elf_dependencies(resolved_path, new_mcpi_exe_path, linker);
// Free Linker Path
if (linker != NULL) {
@ -281,7 +282,7 @@ void bootstrap(int argc, char *argv[]) {
}
// Verify
if (!starts_with(getenv("MCPI_EXECUTABLE_PATH"), "/tmp")) {
if (!starts_with(new_mcpi_exe_path, MCPI_PATCHED_DIR)) {
IMPOSSIBLE();
}
}
@ -391,7 +392,7 @@ void bootstrap(int argc, char *argv[]) {
new_args[argv_start + argc] = NULL;
// Set Executable Argument
new_args[argv_start] = getenv("MCPI_EXECUTABLE_PATH");
new_args[argv_start] = new_mcpi_exe_path;
// Non-ARM Systems Need QEMU
#ifndef __ARM_ARCH

View File

@ -8,23 +8,21 @@
#include "patchelf.h"
// Duplicate MCPI Executable Into /tmp
#define TMP_DIR "/tmp/.minecraft-pi-patched"
static void duplicate_mcpi_executable(const char *original_path) {
static void duplicate_mcpi_executable(const char *original_path, char *new_path) {
// Ensure Temporary Directory
{
// Check If It Exists
struct stat tmp_stat;
int exists = stat(TMP_DIR, &tmp_stat) != 0 ? 0 : S_ISDIR(tmp_stat.st_mode);
int exists = stat(MCPI_PATCHED_DIR, &tmp_stat) != 0 ? 0 : S_ISDIR(tmp_stat.st_mode);
if (!exists) {
// Doesn't Exist
if (mkdir(TMP_DIR, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
if (mkdir(MCPI_PATCHED_DIR, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
ERR("Unable To Create Temporary Folder: %s", strerror(errno));
}
}
}
// Generate New File
char new_path[] = TMP_DIR "/XXXXXX";
int new_file_fd = mkstemp(new_path);
if (new_file_fd == -1) {
ERR("Unable To Create Temporary File: %s", strerror(errno));
@ -33,7 +31,6 @@ static void duplicate_mcpi_executable(const char *original_path) {
if (new_file == NULL) {
ERR("Unable To Open Temporary File: %s", strerror(errno));
}
set_and_print_env("MCPI_EXECUTABLE_PATH", new_path);
// Copy Original File
{
@ -76,7 +73,7 @@ static void duplicate_mcpi_executable(const char *original_path) {
"--remove-needed", "libX11.so.6", \
"--remove-needed", "libEGL.so", \
"--replace-needed", "libGLESv2.so", "libGLESv1_CM.so.1", \
exe, \
new_path, \
NULL \
}; \
int _macro_return_code = 0; \
@ -86,12 +83,9 @@ static void duplicate_mcpi_executable(const char *original_path) {
} \
_macro_return_code; \
})
void patch_mcpi_elf_dependencies(const char *original_path, const char *linker) {
void patch_mcpi_elf_dependencies(const char *original_path, char *new_path, const char *linker) {
// Duplicate MCPI executable into /tmp so it can be modified.
duplicate_mcpi_executable(original_path);
// Get Path
char *exe = getenv("MCPI_EXECUTABLE_PATH");
duplicate_mcpi_executable(original_path, new_path);
// Run patchelf
int return_code;
@ -107,8 +101,8 @@ void patch_mcpi_elf_dependencies(const char *original_path, const char *linker)
}
// Fix Permissions
if (chmod(exe, S_IRUSR | S_IXUSR) != 0) {
ERR("Unable To Set File Permissions: %s: %s", exe, strerror(errno));
if (chmod(new_path, S_IRUSR | S_IXUSR) != 0) {
ERR("Unable To Set File Permissions: %s: %s", new_path, strerror(errno));
}
}

View File

@ -4,7 +4,9 @@
extern "C" {
#endif
void patch_mcpi_elf_dependencies(const char *original_path, const char *linker);
#define MCPI_PATCHED_DIR "/tmp/.minecraft-pi-patched"
void patch_mcpi_elf_dependencies(const char *original_path, char *new_path, const char *linker);
char *patch_get_interpreter(const char *file);
#ifdef __cplusplus

View File

@ -6,6 +6,7 @@ extern "C" {
#define GL_FALSE 0
#define GL_ARRAY_BUFFER_BINDING 0x8894
#define GL_ARRAY_BUFFER 0x8892
#define GL_TEXTURE_BINDING_2D 0x8069
#define GL_UNSIGNED_BYTE 0x1401
#define GL_FLOAT 0x1406

View File

@ -39,6 +39,21 @@ CALL(11, glFogfv, void, (GLenum pname, const GLfloat *params)) {
#if defined(MEDIA_LAYER_PROXY_SERVER)
#define CALL_GL_POINTER(unique_id, name) \
CALL(unique_id, name, void, (GLint size, GLenum type, GLsizei stride, const void *pointer)) { \
/* Check */ \
static int last_set = 0; \
static GLint last_size; \
static GLenum last_type; \
static GLsizei last_stride; \
static const void *last_pointer; \
if (last_set && last_size == size && last_type == type && last_stride == stride && last_pointer == pointer) { \
return; \
} else { \
last_set = 1; \
last_size = size; \
last_type = type; \
last_stride = stride; \
last_pointer = pointer; \
} \
/* Lock Proxy */ \
start_proxy_call(); \
\
@ -107,6 +122,31 @@ CALL(14, glBlendFunc, void, (GLenum sfactor, GLenum dfactor)) {
#endif
}
// Track Bindings
#if defined(MEDIA_LAYER_PROXY_SERVER)
static GLuint bound_buffer = 0;
static GLuint bound_texture = 0;
static unsigned char vertex_array_enabled = 0;
static unsigned char color_array_enabled = 0;
static unsigned char tex_coord_array_enabled = 0;
static unsigned char *get_array_enabled_pointer(GLenum array) {
switch (array) {
case GL_VERTEX_ARRAY: {
return &vertex_array_enabled;
}
case GL_COLOR_ARRAY: {
return &color_array_enabled;
}
case GL_TEXTURE_COORD_ARRAY: {
return &tex_coord_array_enabled;
}
default: {
ERR("Unsupported Array Pointer: %i", array);
}
}
}
#endif
CALL(15, glDrawArrays, void, (GLenum mode, GLint first, GLsizei count)) {
#if defined(MEDIA_LAYER_PROXY_SERVER)
// Lock Proxy
@ -116,6 +156,13 @@ CALL(15, glDrawArrays, void, (GLenum mode, GLint first, GLsizei count)) {
write_int((uint32_t) mode);
write_int((uint32_t) first);
write_int((uint32_t) count);
write_int(bound_buffer);
write_int(bound_texture);
if (!vertex_array_enabled) {
IMPOSSIBLE();
}
write_byte(color_array_enabled);
write_byte(tex_coord_array_enabled);
// Release Proxy
end_proxy_call();
@ -123,7 +170,17 @@ CALL(15, glDrawArrays, void, (GLenum mode, GLint first, GLsizei count)) {
GLenum mode = (GLenum) read_int();
GLint first = (GLint) read_int();
GLsizei count = (GLsizei) read_int();
GLuint bound_buffer = (GLuint) read_int();
GLuint bound_texture = (GLuint) read_int();
unsigned char color_array_enabled = read_byte();
unsigned char tex_coord_array_enabled = read_byte();
// Run
glBindBuffer(GL_ARRAY_BUFFER, bound_buffer);
glBindTexture(GL_TEXTURE_2D, bound_texture);
glEnableClientState(GL_VERTEX_ARRAY);
#define set_array_enabled(condition, enum) condition ? glEnableClientState(enum) : glDisableClientState(enum);
set_array_enabled(color_array_enabled, GL_COLOR_ARRAY);
set_array_enabled(tex_coord_array_enabled, GL_TEXTURE_COORD_ARRAY);
glDrawArrays(mode, first, count);
#endif
}
@ -187,6 +244,7 @@ CALL(18, glBufferData, void, (GLenum target, GLsizeiptr size, const void *data,
write_int((uint32_t) target);
write_int((uint32_t) size);
write_int((uint32_t) usage);
write_int(bound_buffer);
// Write Data
unsigned char is_null = data == NULL;
write_byte(is_null);
@ -200,6 +258,7 @@ CALL(18, glBufferData, void, (GLenum target, GLsizeiptr size, const void *data,
GLenum target = (GLenum) read_int();
GLsizeiptr size = (GLsizeiptr) read_int();
GLenum usage = (GLenum) read_int();
GLuint bound_buffer = (GLuint) read_int();
// Load Data
void *data = NULL;
unsigned char is_null = read_byte();
@ -223,6 +282,7 @@ CALL(18, glBufferData, void, (GLenum target, GLsizeiptr size, const void *data,
safe_read(data, (size_t) size);
}
// Run
glBindBuffer(GL_ARRAY_BUFFER, bound_buffer);
glBufferData(target, size, data, usage);
#endif
}
@ -316,6 +376,7 @@ CALL(24, glTexParameteri, void, (GLenum target, GLenum pname, GLint param)) {
write_int((uint32_t) target);
write_int((uint32_t) pname);
write_int((uint32_t) param);
write_int(bound_texture);
// Release Proxy
end_proxy_call();
@ -323,7 +384,9 @@ CALL(24, glTexParameteri, void, (GLenum target, GLenum pname, GLint param)) {
GLenum target = (GLenum) read_int();
GLenum pname = (GLenum) read_int();
GLint param = (GLint) read_int();
GLuint bound_texture = (GLuint) read_int();
// Run
glBindTexture(GL_TEXTURE_2D, bound_texture);
glTexParameteri(target, pname, param);
#endif
}
@ -383,6 +446,7 @@ CALL(25, glTexImage2D, void, (GLenum target, GLint level, GLint internalformat,
write_int((uint32_t) border);
write_int((uint32_t) format);
write_int((uint32_t) type);
write_int(bound_texture);
write_byte(is_null);
if (!is_null) {
safe_write((void *) pixels, (size_t) size);
@ -399,6 +463,7 @@ CALL(25, glTexImage2D, void, (GLenum target, GLint level, GLint internalformat,
GLint border = (GLint) read_int();
GLenum format = (GLenum) read_int();
GLenum type = (GLenum) read_int();
GLuint bound_texture = (GLuint) read_int();
unsigned char is_null = read_byte();
void *pixels = NULL;
if (!is_null) {
@ -408,6 +473,7 @@ CALL(25, glTexImage2D, void, (GLenum target, GLint level, GLint internalformat,
safe_read(pixels, (size_t) size);
}
// Run
glBindTexture(GL_TEXTURE_2D, bound_texture);
glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
// Free
if (!is_null) {
@ -433,22 +499,17 @@ CALL(26, glEnable, void, (GLenum cap)) {
#endif
}
CALL(27, glEnableClientState, void, (GLenum array)) {
#if defined(MEDIA_LAYER_PROXY_SERVER)
// Lock Proxy
start_proxy_call();
// Arguments
write_int((uint32_t) array);
// Release Proxy
end_proxy_call();
#else
GLenum array = (GLenum) read_int();
// Run
glEnableClientState(array);
#endif
void glEnableClientState(GLenum array) {
// Set
unsigned char *enabled = get_array_enabled_pointer(array);
if (*enabled) {
return;
} else {
*enabled = 1;
}
}
#endif
CALL(28, glPolygonOffset, void, (GLfloat factor, GLfloat units)) {
#if defined(MEDIA_LAYER_PROXY_SERVER)
@ -469,22 +530,17 @@ CALL(28, glPolygonOffset, void, (GLfloat factor, GLfloat units)) {
#endif
}
CALL(29, glDisableClientState, void, (GLenum array)) {
#if defined(MEDIA_LAYER_PROXY_SERVER)
// Lock Proxy
start_proxy_call();
// Arguments
write_int((uint32_t) array);
// Release Proxy
end_proxy_call();
#else
GLenum array = (GLenum) read_int();
// Run
glDisableClientState(array);
#endif
void glDisableClientState(GLenum array) {
// Set
unsigned char *enabled = get_array_enabled_pointer(array);
if (!*enabled) {
return;
} else {
*enabled = 0;
}
}
#endif
CALL(30, glDepthRangef, void, (GLclampf near, GLclampf far)) {
#if defined(MEDIA_LAYER_PROXY_SERVER)
@ -522,24 +578,16 @@ CALL(31, glDepthFunc, void, (GLenum func)) {
#endif
}
CALL(32, glBindBuffer, void, (GLenum target, GLuint buffer)) {
#if defined(MEDIA_LAYER_PROXY_SERVER)
// Lock Proxy
start_proxy_call();
// Arguments
write_int((uint32_t) target);
write_int((uint32_t) buffer);
// Release Proxy
end_proxy_call();
#else
GLenum target = (GLenum) read_int();
GLuint buffer = (GLuint) read_int();
// Run
glBindBuffer(target, buffer);
#endif
void glBindBuffer(GLenum target, GLuint buffer) {
// Set
if (target == GL_ARRAY_BUFFER) {
bound_buffer = buffer;
} else {
PROXY_ERR("Unsupported Buffer Binding: %u", target);
}
}
#endif
CALL(33, glClearColor, void, (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)) {
#if defined(MEDIA_LAYER_PROXY_SERVER)
@ -748,6 +796,7 @@ CALL(44, glTexSubImage2D, void, (GLenum target, GLint level, GLint xoffset, GLin
write_int((uint32_t) height);
write_int((uint32_t) format);
write_int((uint32_t) type);
write_int(bound_texture);
write_byte(is_null);
if (!is_null) {
safe_write((void *) pixels, (size_t) size);
@ -764,6 +813,7 @@ CALL(44, glTexSubImage2D, void, (GLenum target, GLint level, GLint xoffset, GLin
GLsizei height = (GLsizei) read_int();
GLenum format = (GLenum) read_int();
GLenum type = (GLenum) read_int();
GLuint bound_texture = (GLuint) read_int();
unsigned char is_null = read_byte();
void *pixels = NULL;
if (!is_null) {
@ -773,6 +823,7 @@ CALL(44, glTexSubImage2D, void, (GLenum target, GLint level, GLint xoffset, GLin
safe_read(pixels, (size_t) size);
}
// Run
glBindTexture(GL_TEXTURE_2D, bound_texture);
glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
// Free
if (!is_null) {
@ -887,24 +938,16 @@ CALL(48, glGetFloatv, void, (GLenum pname, GLfloat *params)) {
#endif
}
CALL(49, glBindTexture, void, (GLenum target, GLuint texture)) {
#if defined(MEDIA_LAYER_PROXY_SERVER)
// Lock Proxy
start_proxy_call();
// Arguments
write_int((uint32_t) target);
write_int((uint32_t) texture);
// Release Proxy
end_proxy_call();
#else
GLenum target = (GLenum) read_int();
GLuint texture = (GLuint) read_int();
// Run
glBindTexture(target, texture);
#endif
void glBindTexture(GLenum target, GLuint texture) {
// Set
if (target == GL_TEXTURE_2D) {
bound_texture = texture;
} else {
PROXY_ERR("Unsupported Texture Binding: %u", target);
}
}
#endif
CALL(50, glTranslatef, void, (GLfloat x, GLfloat y, GLfloat z)) {
#if defined(MEDIA_LAYER_PROXY_SERVER)

View File

@ -9,18 +9,15 @@
#include "../common/common.h"
// Store Handlers
__attribute__((const)) static std::vector<proxy_handler_t> &get_handlers() {
static std::vector<proxy_handler_t> handlers;
return handlers;
}
static std::vector<proxy_handler_t> handlers;
void _add_handler(unsigned char unique_id, proxy_handler_t handler) {
if (get_handlers().size() > unique_id && get_handlers()[unique_id] != NULL) {
if (handlers.size() > unique_id && handlers[unique_id] != NULL) {
PROXY_ERR("Duplicate ID: %i", (int) unique_id);
}
if (get_handlers().size() <= unique_id) {
get_handlers().resize(unique_id + 1);
if (handlers.size() <= unique_id) {
handlers.resize(unique_id + 1);
}
get_handlers()[unique_id] = handler;
handlers[unique_id] = handler;
}
// Store Parent PID
@ -48,10 +45,7 @@ static void exit_handler(__attribute__((unused)) int signal_id) {
// Main
int main(int argc, char *argv[]) {
// Install Signal Handlers
struct sigaction act_sigint;
memset((void *) &act_sigint, 0, sizeof (struct sigaction));
act_sigint.sa_handler = &exit_handler;
sigaction(SIGINT, &act_sigint, NULL);
signal(SIGINT, SIG_IGN);
struct sigaction act_sigterm;
memset((void *) &act_sigterm, 0, sizeof (struct sigaction));
act_sigterm.sa_handler = &exit_handler;
@ -84,9 +78,9 @@ int main(int argc, char *argv[]) {
int running = is_connection_open();
while (running && !exit_requested) {
unsigned char unique_id = read_byte();
if (get_handlers().size() > unique_id && get_handlers()[unique_id] != NULL) {
if (handlers.size() > unique_id && handlers[unique_id] != NULL) {
// Run Method
get_handlers()[unique_id]();
handlers[unique_id]();
// Check If Connection Is Still Open
if (!is_connection_open()) {
// Exit

View File

@ -1,6 +1,8 @@
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <sys/ioctl.h>
#include "common.h"
@ -12,23 +14,76 @@
PROXY_ERR("Attempting To Access Closed Connection"); \
} \
}
// Buffer Reads
static void *_read_cache = NULL;
__attribute__((destructor)) static void _free_read_cache() {
if (_read_cache != NULL) {
free(_read_cache);
}
}
static size_t _read_cache_size = 0;
static size_t _read_cache_actual_size = 0;
static size_t _read_cache_position = 0;
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
void safe_read(void *buf, size_t len) {
// Check Data
if (buf == NULL) {
PROXY_ERR("Attempting To Read Into NULL Buffer");
}
// Setup
size_t to_read = len;
// Copy From Read Buffer
if (_read_cache != NULL && _read_cache_size > 0) {
char *read_cache = (void *) (((unsigned char *) _read_cache) + _read_cache_position);
size_t read_cache_size = _read_cache_size - _read_cache_position;
if (read_cache_size > 0) {
size_t to_copy = min(to_read, read_cache_size);
memcpy(buf, read_cache, to_copy);
to_read -= to_copy;
_read_cache_position += to_copy;
}
}
// Check If Done
if (to_read < 1) {
return;
}
if (_read_cache_position < _read_cache_size) {
IMPOSSIBLE();
}
// Flush Write Cache
flush_write_cache();
// Read
size_t to_read = len;
while (to_read > 0) {
// Read Remaining Data
size_t to_read_to_cache = 0;
while (to_read_to_cache < 1) {
int bytes_available;
if (ioctl(get_connection_read(), FIONREAD, &bytes_available) == -1) {
bytes_available = 0;
}
to_read_to_cache = max((size_t) bytes_available, to_read);
}
// Resize Buffer
_read_cache_position = 0;
_read_cache_size = to_read_to_cache;
if (_read_cache == NULL) {
_read_cache_actual_size = _read_cache_size;
_read_cache = malloc(_read_cache_actual_size);
} else if (_read_cache_size > _read_cache_actual_size) {
_read_cache_actual_size = _read_cache_size;
_read_cache = realloc(_read_cache, _read_cache_actual_size);
}
ALLOC_CHECK(_read_cache);
// Read Into Buffer
while (to_read_to_cache > 0) {
CHECK_CONNECTION();
ssize_t x = read(get_connection_read(), (void *) (((unsigned char *) buf) + (len - to_read)), to_read);
ssize_t x = read(get_connection_read(), (void *) (((unsigned char *) _read_cache) + (_read_cache_size - to_read_to_cache)), to_read_to_cache);
if (x == -1 && errno != EINTR) {
PROXY_ERR("Failed Reading Data To Connection: %s", strerror(errno));
}
to_read -= x;
to_read_to_cache -= x;
}
// Copy Remaining Data
safe_read((void *) (((unsigned char *) buf) + (len - to_read)), to_read);
}
// Buffer Writes
static void *_write_cache = NULL;

View File

@ -86,6 +86,34 @@ static void start_media_layer_proxy_client(int read, int write) {
update_client_state(1, 0);
}
// Maximize Pipe Buffer Size
static void maximize_pipe_fd_size(int fd) {
// Read Maximum Pipe Size
std::ifstream max_size_file("/proc/sys/fs/pipe-max-size");
if (!max_size_file.good()) {
PROXY_ERR("%s", "Unable To Open Maximum Pipe Size File");
}
// Read One Line
int max_size;
std::string line;
if (std::getline(max_size_file, line) && line.size() > 0) {
max_size = std::stoi(line);
} else {
PROXY_ERR("%s", "Unable To Read Maximum Pipe Size File");
}
// Close
max_size_file.close();
// Set Maximum Pipe Size
errno = 0;
if (fcntl(fd, F_SETPIPE_SZ, max_size) < max_size) {
PROXY_ERR("Unable To Set Maximum Pipe Size: %s", errno != 0 ? strerror(errno) : "Unknown Error");
}
}
static void maximize_pipe_size(int pipe[2]) {
maximize_pipe_fd_size(pipe[0]);
maximize_pipe_fd_size(pipe[1]);
}
// Start Server
static int loaded = 0;
__attribute__((constructor)) void media_ensure_loaded() {
@ -98,8 +126,10 @@ __attribute__((constructor)) void media_ensure_loaded() {
// Create Connection
int server_to_client_pipe[2];
safe_pipe2(server_to_client_pipe, 0);
maximize_pipe_size(server_to_client_pipe);
int client_to_server_pipe[2];
safe_pipe2(client_to_server_pipe, 0);
maximize_pipe_size(client_to_server_pipe);
// Set Connection
set_connection(client_to_server_pipe[0], server_to_client_pipe[1]);

View File

@ -133,13 +133,18 @@ void init_compat() {
__attribute__((destructor)) static void cleanup_temporary() {
// Cleanup Executable
{
const char *exe = getenv("MCPI_EXECUTABLE_PATH");
// Check If Executable Is Temporary
if (exe != NULL && starts_with(exe, "/tmp")) {
// Cleanup Temporary File
if (unlink(exe) != 0) {
ERR("Unable To Cleanup Temporary File: %s", strerror(errno));
char *exe = realpath("/proc/self/exe", NULL);
// Check If Successful
if (exe != NULL) {
// Check If Executable Is Temporary
if (starts_with(exe, "/tmp")) {
// Cleanup Temporary File
if (unlink(exe) != 0) {
ERR("Unable To Cleanup Temporary File: %s", strerror(errno));
}
}
// Free
free(exe);
}
}
}

View File

@ -38,6 +38,7 @@ if (mode === 'client') {
'libgtk-3-0',
'libglib2.0-0',
'libgdk-pixbuf2.0-0',
'librsvg2-common',
'shared-mime-info',
'libfreeimage3',
'libopenal1'
@ -59,7 +60,8 @@ const packageExclusions = [
'librest-*',
'libcups2',
'libcolord2',
'libmount1'
'libmount1',
'libwayland-*'
];
// APT