This commit is contained in:
TheBrokenRail 2024-06-08 03:09:55 -04:00
parent 4e2437dbd6
commit c60428c600
7 changed files with 163 additions and 79 deletions

@ -1 +1 @@
Subproject commit b2cf446e9dd5593c388c1f244c527741070f7a26 Subproject commit 027e58ee9bdcfef285c16e731c8db218082b9639

View File

@ -29,7 +29,7 @@ static void setup_environment(const options_t &options) {
bind_to_env("_MCPI_ONLY_GENERATE", options.only_generate); bind_to_env("_MCPI_ONLY_GENERATE", options.only_generate);
#endif #endif
#ifdef MCPI_USE_NATIVE_TRAMPOLINE #ifdef MCPI_USE_NATIVE_TRAMPOLINE
bind_to_env(TRAMPOLINE_USE_PTRACE_ENV, options.use_ptrace_trampoline); bind_to_env(TRAMPOLINE_USE_PIPES_ENV, !options.use_ptrace_trampoline);
#endif #endif
// GTK Dark Mode // GTK Dark Mode

View File

@ -20,7 +20,7 @@ if(BUILD_NATIVE_COMPONENTS)
elseif(BUILD_ARM_COMPONENTS) elseif(BUILD_ARM_COMPONENTS)
# Guest Component # Guest Component
add_library(media-layer-core SHARED src/guest/guest.cpp ${MEDIA_LAYER_TRAMPOLINE_SRC} $<TARGET_OBJECTS:media-layer-extras>) add_library(media-layer-core SHARED src/guest/guest.cpp ${MEDIA_LAYER_TRAMPOLINE_SRC} $<TARGET_OBJECTS:media-layer-extras>)
target_link_libraries(media-layer-core PUBLIC media-layer-headers PRIVATE reborn-util PRIVATE trampoline-headers) target_link_libraries(media-layer-core PUBLIC media-layer-headers PRIVATE reborn-util PRIVATE trampoline-headers PRIVATE rt)
target_compile_definitions(media-layer-core PRIVATE -DMEDIA_LAYER_TRAMPOLINE_GUEST) target_compile_definitions(media-layer-core PRIVATE -DMEDIA_LAYER_TRAMPOLINE_GUEST)
# Install # Install
if(MCPI_USE_MEDIA_LAYER_TRAMPOLINE) if(MCPI_USE_MEDIA_LAYER_TRAMPOLINE)

View File

@ -21,25 +21,100 @@ CALL(11, glFogfv, void, (GLenum pname, const GLfloat *params))
#endif #endif
} }
// 'pointer' Is Only Supported As An Integer, Not As An Actual Pointer // Track GL State
struct gl_array_state_t {
bool enabled = false;
GLint size = 0;
GLenum type = 0;
GLsizei stride = 0;
uint32_t pointer = 0;
bool operator==(const gl_array_state_t &other) const {
return enabled == other.enabled && size == other.size && type == other.type && stride == other.stride && pointer == other.pointer;
}
bool operator!=(const gl_array_state_t &other) const {
return !operator==(other);
}
};
struct gl_state_t {
GLuint bound_array_buffer = 0;
GLuint bound_texture = 0;
gl_array_state_t vertex_array;
gl_array_state_t color_array;
gl_array_state_t tex_coord_array;
// Update State
static typeof(glVertexPointer) *get_array_pointer_function(const GLenum array) {
switch (array) {
case GL_VERTEX_ARRAY: {
return glVertexPointer;
}
case GL_COLOR_ARRAY: {
return glColorPointer;
}
case GL_TEXTURE_COORD_ARRAY: {
return glTexCoordPointer;
}
default: {
ERR("Unsupported Array Type: %i", array);
}
}
}
gl_array_state_t &get_array_state(const GLenum array) {
switch (array) {
case GL_VERTEX_ARRAY: {
return vertex_array;
}
case GL_COLOR_ARRAY: {
return color_array;
}
case GL_TEXTURE_COORD_ARRAY: {
return tex_coord_array;
}
default: {
ERR("Unsupported Array Function");
}
}
}
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
#define CALL_GL_POINTER(unique_id, name) \ void enable_disable_array(const GLenum array, const bool value) {
CALL(unique_id, name, void, (GLint size, GLenum type, GLsizei stride, const void *pointer)) \ get_array_state(array).enabled = value;
trampoline(size, type, stride, uint32_t(pointer)); \
} }
#else #else
#define CALL_GL_POINTER(unique_id, name) \ void send_array_to_driver(GLenum array) {
CALL(unique_id, name, unused, unused) \ gl_array_state_t state = get_array_state(array);
GLint size = args.next<GLint>(); \ if (state.enabled) {
GLenum type = args.next<GLenum>(); \ glEnableClientState(array);
GLsizei stride = args.next<GLsizei>(); \ } else {
const void *pointer = (const void *) (uint64_t) args.next<uint32_t>(); \ glDisableClientState(array);
func(size, type, stride, pointer); \ }
return 0; \ typeof(glVertexPointer) *func = get_array_pointer_function(array);
func(state.size, state.type, state.stride, (const void *) uintptr_t(state.pointer));
}
void send_arrays_to_driver() {
send_array_to_driver(GL_VERTEX_ARRAY);
send_array_to_driver(GL_COLOR_ARRAY);
send_array_to_driver(GL_TEXTURE_COORD_ARRAY);
} }
#endif #endif
};
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
static gl_state_t gl_state;
#endif
CALL_GL_POINTER(12, glVertexPointer) // 'pointer' Is Only Supported As An Integer, Not As An Actual Pointer
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
#define CALL_GL_POINTER(name, array) \
void name(GLint size, GLenum type, GLsizei stride, const void *pointer) { \
gl_array_state_t &state = gl_state.get_array_state(array); \
state.size = size; \
state.type = type; \
state.stride = stride; \
state.pointer = uint32_t(pointer); \
}
#else
#define CALL_GL_POINTER(name, array)
#endif
CALL_GL_POINTER(glVertexPointer, GL_VERTEX_ARRAY)
CALL(13, glLineWidth, void, (GLfloat width)) CALL(13, glLineWidth, void, (GLfloat width))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
@ -63,8 +138,12 @@ CALL(14, glBlendFunc, void, (GLenum sfactor, GLenum dfactor))
CALL(15, glDrawArrays, void, (GLenum mode, GLint first, GLsizei count)) CALL(15, glDrawArrays, void, (GLenum mode, GLint first, GLsizei count))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
trampoline(mode, first, count); trampoline(gl_state, mode, first, count);
#else #else
gl_state_t gl_state = args.next<gl_state_t>();
glBindBuffer(GL_ARRAY_BUFFER, gl_state.bound_array_buffer);
glBindTexture(GL_TEXTURE_2D, gl_state.bound_texture);
gl_state.send_arrays_to_driver();
GLenum mode = args.next<GLenum>(); GLenum mode = args.next<GLenum>();
GLint first = args.next<GLint>(); GLint first = args.next<GLint>();
GLsizei count = args.next<GLsizei>(); GLsizei count = args.next<GLsizei>();
@ -97,8 +176,9 @@ CALL(17, glClear, void, (GLbitfield mask))
CALL(18, glBufferData, void, (GLenum target, GLsizeiptr size, const void *data, GLenum usage)) CALL(18, glBufferData, void, (GLenum target, GLsizeiptr size, const void *data, GLenum usage))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
trampoline(target, copy_array(size, (unsigned char *) data), usage); trampoline(gl_state.bound_array_buffer, target, copy_array(size, (unsigned char *) data), usage);
#else #else
glBindBuffer(GL_ARRAY_BUFFER, args.next<GLuint>());
GLenum target = args.next<GLenum>(); GLenum target = args.next<GLenum>();
uint32_t size; uint32_t size;
const unsigned char *data = args.next_arr<unsigned char>(&size); const unsigned char *data = args.next_arr<unsigned char>(&size);
@ -139,7 +219,7 @@ CALL(21, glMatrixMode, void, (GLenum mode))
#endif #endif
} }
CALL_GL_POINTER(22, glColorPointer) CALL_GL_POINTER(glColorPointer, GL_COLOR_ARRAY)
CALL(23, glScissor, void, (GLint x, GLint y, GLsizei width, GLsizei height)) CALL(23, glScissor, void, (GLint x, GLint y, GLsizei width, GLsizei height))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
@ -156,8 +236,9 @@ CALL(23, glScissor, void, (GLint x, GLint y, GLsizei width, GLsizei height))
CALL(24, glTexParameteri, void, (GLenum target, GLenum pname, GLint param)) CALL(24, glTexParameteri, void, (GLenum target, GLenum pname, GLint param))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
trampoline(target, pname, param); trampoline(gl_state.bound_texture, target, pname, param);
#else #else
glBindTexture(GL_TEXTURE_2D, args.next<GLuint>());
GLenum target = args.next<GLenum>(); GLenum target = args.next<GLenum>();
GLenum pname = args.next<GLenum>(); GLenum pname = args.next<GLenum>();
GLint param = args.next<GLint>(); GLint param = args.next<GLint>();
@ -204,8 +285,9 @@ static int get_texture_size(const GLsizei width, const GLsizei height, const GLe
CALL(25, glTexImage2D, void, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels)) CALL(25, glTexImage2D, void, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
trampoline(target, level, internalformat, width, height, border, format, type, copy_array(get_texture_size(width, height, format, type, true), (const unsigned char *) pixels)); trampoline(gl_state.bound_texture, target, level, internalformat, width, height, border, format, type, copy_array(get_texture_size(width, height, format, type, true), (const unsigned char *) pixels));
#else #else
glBindTexture(GL_TEXTURE_2D, args.next<GLuint>());
GLenum target = args.next<GLenum>(); GLenum target = args.next<GLenum>();
GLint level = args.next<GLint>(); GLint level = args.next<GLint>();
GLint internalformat = args.next<GLint>(); GLint internalformat = args.next<GLint>();
@ -229,14 +311,11 @@ CALL(26, glEnable, void, (GLenum cap))
#endif #endif
} }
CALL(27, glEnableClientState, void, (GLenum array))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
trampoline(array); void glEnableClientState(const GLenum array) {
#else gl_state.enable_disable_array(array, true);
func(args.next<GLenum>());
return 0;
#endif
} }
#endif
CALL(28, glPolygonOffset, void, (GLfloat factor, GLfloat units)) CALL(28, glPolygonOffset, void, (GLfloat factor, GLfloat units))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
@ -249,16 +328,13 @@ CALL(28, glPolygonOffset, void, (GLfloat factor, GLfloat units))
#endif #endif
} }
CALL_GL_POINTER(41, glTexCoordPointer) CALL_GL_POINTER(glTexCoordPointer, GL_TEXTURE_COORD_ARRAY)
CALL(29, glDisableClientState, void, (GLenum array))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
trampoline(array); void glDisableClientState(const GLenum array) {
#else gl_state.enable_disable_array(array, false);
func(args.next<GLenum>());
return 0;
#endif
} }
#endif
CALL(30, glDepthRangef, void, (GLclampf near, GLclampf far)) CALL(30, glDepthRangef, void, (GLclampf near, GLclampf far))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
@ -280,16 +356,15 @@ CALL(31, glDepthFunc, void, (GLenum func))
#endif #endif
} }
CALL(32, glBindBuffer, void, (GLenum target, GLuint buffer))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
trampoline(target, buffer); void glBindBuffer(const GLenum target, const GLuint buffer) {
#else if (target == GL_ARRAY_BUFFER) {
GLenum target = args.next<GLenum>(); gl_state.bound_array_buffer = buffer;
GLenum buffer = args.next<GLenum>(); } else {
func(target, buffer); ERR("Unsupported Buffer Binding: %u", target);
return 0;
#endif
} }
}
#endif
CALL(33, glClearColor, void, (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)) CALL(33, glClearColor, void, (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
@ -403,8 +478,9 @@ CALL(43, glColorMask, void, (GLboolean red, GLboolean green, GLboolean blue, GLb
CALL(44, glTexSubImage2D, void, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)) CALL(44, glTexSubImage2D, void, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
trampoline(target, level, xoffset, yoffset, width, height, format, type, copy_array(get_texture_size(width, height, format, type, true), (const unsigned char *) pixels)); trampoline(gl_state.bound_texture, target, level, xoffset, yoffset, width, height, format, type, copy_array(get_texture_size(width, height, format, type, true), (const unsigned char *) pixels));
#else #else
glBindTexture(GL_TEXTURE_2D, args.next<GLuint>());
GLenum target = args.next<GLenum>(); GLenum target = args.next<GLenum>();
GLint level = args.next<GLint>(); GLint level = args.next<GLint>();
GLint xoffset = args.next<GLint>(); GLint xoffset = args.next<GLint>();
@ -485,16 +561,15 @@ CALL(48, glGetFloatv, void, (GLenum pname, GLfloat *params))
#endif #endif
} }
CALL(49, glBindTexture, void, (GLenum target, GLuint texture))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
trampoline(target, texture); void glBindTexture(const GLenum target, const GLuint texture) {
#else if (target == GL_TEXTURE_2D) {
GLenum target = args.next<GLenum>(); gl_state.bound_texture = texture;
GLuint texture = args.next<GLuint>(); } else {
func(target, texture); ERR("Unsupported Texture Binding: %u", target);
return 0;
#endif
} }
}
#endif
CALL(50, glTranslatef, void, (GLfloat x, GLfloat y, GLfloat z)) CALL(50, glTranslatef, void, (GLfloat x, GLfloat y, GLfloat z))
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST

View File

@ -1,6 +1,7 @@
#include <unistd.h> #include <unistd.h>
#include <libreborn/libreborn.h> #include <libreborn/libreborn.h>
#include <string> #include <string>
#include <sys/mman.h>
#include "guest.h" #include "guest.h"
@ -16,8 +17,7 @@ static uint32_t trampoline_syscall(const uint32_t id, const uint32_t length, con
return *(uint32_t *) args; return *(uint32_t *) args;
} }
// Pipe Method // Pipe Method (Native Trampoline Only)
#ifdef MCPI_USE_NATIVE_TRAMPOLINE
static int get_pipe(const char *env) { static int get_pipe(const char *env) {
const char *value = getenv(env); const char *value = getenv(env);
if (value == nullptr) { if (value == nullptr) {
@ -26,7 +26,7 @@ static int get_pipe(const char *env) {
std::string str = value; std::string str = value;
return std::stoi(str); return std::stoi(str);
} }
static uint32_t trampoline_pipe(const uint32_t id, const uint32_t length, const unsigned char *args) { static uint32_t trampoline_pipe(const uint32_t id) {
// Get Pipes // Get Pipes
static int arguments_pipe = -1; static int arguments_pipe = -1;
static int return_value_pipe = -1; static int return_value_pipe = -1;
@ -34,13 +34,8 @@ static uint32_t trampoline_pipe(const uint32_t id, const uint32_t length, const
arguments_pipe = get_pipe(TRAMPOLINE_ARGUMENTS_PIPE_ENV); arguments_pipe = get_pipe(TRAMPOLINE_ARGUMENTS_PIPE_ENV);
return_value_pipe = get_pipe(TRAMPOLINE_RETURN_VALUE_PIPE_ENV); return_value_pipe = get_pipe(TRAMPOLINE_RETURN_VALUE_PIPE_ENV);
} }
// Write Arguments // Write ID
trampoline_pipe_arguments data = { if (write(arguments_pipe, &id, sizeof(uint32_t)) != sizeof(uint32_t)) {
.id = id,
.length = length,
.args_addr = uint32_t(args)
};
if (write(arguments_pipe, &data, sizeof(trampoline_pipe_arguments)) != sizeof(trampoline_pipe_arguments)) {
ERR("Unable To Write Trampoline Command"); ERR("Unable To Write Trampoline Command");
} }
// Return // Return
@ -50,29 +45,42 @@ static uint32_t trampoline_pipe(const uint32_t id, const uint32_t length, const
} }
return ret; return ret;
} }
#else
static uint32_t trampoline_pipe(__attribute__((unused)) const uint32_t id, __attribute__((unused)) const uint32_t length, __attribute__((unused)) const unsigned char *args) {
IMPOSSIBLE();
}
#endif
// Main Function // Main Function
uint32_t _raw_trampoline(const uint32_t id, const uint32_t length, const unsigned char *args) { uint32_t _raw_trampoline(const uint32_t id, const uint32_t length, const unsigned char *args) {
// Configure Method // Configure Method
static int use_syscall = -1; static int use_syscall = -1;
if (use_syscall == -1) { if (use_syscall == -1) {
use_syscall = use_syscall = getenv(TRAMPOLINE_USE_PIPES_ENV) == nullptr;
#ifdef MCPI_USE_NATIVE_TRAMPOLINE
getenv(TRAMPOLINE_USE_PTRACE_ENV) != nullptr
#else
1
#endif
;
} }
// Use Correct Method // Use Correct Method
if (use_syscall) { if (use_syscall) {
return trampoline_syscall(id, length, args); return trampoline_syscall(id, length, args);
} else { } else {
return trampoline_pipe(id, length, args); return trampoline_pipe(id);
} }
} }
// Arguments Memory
unsigned char *get_arguments_memory() {
static unsigned char fallback[MAX_TRAMPOLINE_ARGS_SIZE];
// Find Result
static unsigned char *ret = nullptr;
if (ret == nullptr) {
ret = fallback;
// Try Shared Memory
const char *shared_memory_name = getenv(TRAMPOLINE_SHARED_MEMORY_ENV);
if (shared_memory_name != nullptr) {
int fd = shm_open(shared_memory_name, O_RDWR, 0600);
if (fd == -1) {
ERR("Unable To Open Shared Memory: %s", strerror(errno));
}
ret = (unsigned char *) mmap(nullptr, MAX_TRAMPOLINE_ARGS_SIZE, PROT_WRITE, MAP_SHARED, fd, 0);
if (ret == MAP_FAILED) {
ERR("Unable To Map Shared Memory: %s", strerror(errno));
}
}
}
// Return
return ret;
}

View File

@ -5,11 +5,12 @@
#include "../common/common.h" #include "../common/common.h"
// Trampoline Function // Trampoline Function
unsigned char *get_arguments_memory();
uint32_t _raw_trampoline(uint32_t id, uint32_t length, const unsigned char *args); uint32_t _raw_trampoline(uint32_t id, uint32_t length, const unsigned char *args);
// Compile Trampoline Arguments // Compile Trampoline Arguments
template <typename T> template <typename T>
void _handle_trampoline_arg(unsigned char *&out, const T arg) { void _handle_trampoline_arg(unsigned char *&out, const T &arg) {
block_pointer(T); block_pointer(T);
*(T *) out = arg; *(T *) out = arg;
out += sizeof(T); out += sizeof(T);
@ -33,7 +34,7 @@ struct copy_array {
const void *data; const void *data;
}; };
template <> template <>
inline void _handle_trampoline_arg<copy_array>(unsigned char *&out, const copy_array arg) { inline void _handle_trampoline_arg<copy_array>(unsigned char *&out, const copy_array &arg) {
*(uint32_t *) out = arg.size; *(uint32_t *) out = arg.size;
out += sizeof(uint32_t); out += sizeof(uint32_t);
if (arg.size > 0) { if (arg.size > 0) {
@ -45,7 +46,7 @@ inline void _handle_trampoline_arg<copy_array>(unsigned char *&out, const copy_a
__attribute__((unused)) static void _add_to_trampoline_args(__attribute__((unused)) unsigned char *&out) { __attribute__((unused)) static void _add_to_trampoline_args(__attribute__((unused)) unsigned char *&out) {
} }
template <typename T, typename... Args> template <typename T, typename... Args>
void _add_to_trampoline_args(unsigned char *&out, T first, Args... args) { void _add_to_trampoline_args(unsigned char *&out, const T &first, const Args... args) {
_handle_trampoline_arg(out, first); _handle_trampoline_arg(out, first);
_add_to_trampoline_args(out, args...); _add_to_trampoline_args(out, args...);
} }
@ -53,7 +54,7 @@ void _add_to_trampoline_args(unsigned char *&out, T first, Args... args) {
// Main Trampoline Function // Main Trampoline Function
template <typename... Args> template <typename... Args>
unsigned int _trampoline(unsigned int id, Args... args) { unsigned int _trampoline(unsigned int id, Args... args) {
static unsigned char out[MAX_TRAMPOLINE_ARGS_SIZE]; static unsigned char *out = get_arguments_memory();
unsigned char *end = out; unsigned char *end = out;
_add_to_trampoline_args(end, args...); _add_to_trampoline_args(end, args...);
const uint32_t length = end - out; const uint32_t length = end - out;

View File

@ -87,7 +87,7 @@ CALL(8, media_swap_buffers, void, ())
CALL(9, media_cleanup, void, ()) CALL(9, media_cleanup, void, ())
#ifdef MEDIA_LAYER_TRAMPOLINE_GUEST #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST
trampoline(); trampoline(false);
#else #else
func(); func();
return 0; return 0;