diff --git a/dependencies/trampoline/src b/dependencies/trampoline/src index b2cf446e9d..027e58ee9b 160000 --- a/dependencies/trampoline/src +++ b/dependencies/trampoline/src @@ -1 +1 @@ -Subproject commit b2cf446e9dd5593c388c1f244c527741070f7a26 +Subproject commit 027e58ee9bdcfef285c16e731c8db218082b9639 diff --git a/launcher/src/main.cpp b/launcher/src/main.cpp index b12d85fcba..fedad17692 100644 --- a/launcher/src/main.cpp +++ b/launcher/src/main.cpp @@ -29,7 +29,7 @@ static void setup_environment(const options_t &options) { bind_to_env("_MCPI_ONLY_GENERATE", options.only_generate); #endif #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 // GTK Dark Mode diff --git a/media-layer/trampoline/CMakeLists.txt b/media-layer/trampoline/CMakeLists.txt index a8d8083532..3dd5bbd4b4 100644 --- a/media-layer/trampoline/CMakeLists.txt +++ b/media-layer/trampoline/CMakeLists.txt @@ -20,7 +20,7 @@ if(BUILD_NATIVE_COMPONENTS) elseif(BUILD_ARM_COMPONENTS) # Guest Component add_library(media-layer-core SHARED src/guest/guest.cpp ${MEDIA_LAYER_TRAMPOLINE_SRC} $) - 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) # Install if(MCPI_USE_MEDIA_LAYER_TRAMPOLINE) diff --git a/media-layer/trampoline/src/GLESv1_CM.cpp b/media-layer/trampoline/src/GLESv1_CM.cpp index 1c88c277a1..49dd09f75b 100644 --- a/media-layer/trampoline/src/GLESv1_CM.cpp +++ b/media-layer/trampoline/src/GLESv1_CM.cpp @@ -21,25 +21,100 @@ CALL(11, glFogfv, void, (GLenum pname, const GLfloat *params)) #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 -#define CALL_GL_POINTER(unique_id, name) \ - CALL(unique_id, name, void, (GLint size, GLenum type, GLsizei stride, const void *pointer)) \ - trampoline(size, type, stride, uint32_t(pointer)); \ + void enable_disable_array(const GLenum array, const bool value) { + get_array_state(array).enabled = value; } #else -#define CALL_GL_POINTER(unique_id, name) \ - CALL(unique_id, name, unused, unused) \ - GLint size = args.next(); \ - GLenum type = args.next(); \ - GLsizei stride = args.next(); \ - const void *pointer = (const void *) (uint64_t) args.next(); \ - func(size, type, stride, pointer); \ - return 0; \ + void send_array_to_driver(GLenum array) { + gl_array_state_t state = get_array_state(array); + if (state.enabled) { + glEnableClientState(array); + } else { + glDisableClientState(array); + } + 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 +}; +#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)) #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)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST - trampoline(mode, first, count); + trampoline(gl_state, mode, first, count); #else + gl_state_t gl_state = args.next(); + 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(); GLint first = args.next(); GLsizei count = args.next(); @@ -97,8 +176,9 @@ CALL(17, glClear, void, (GLbitfield mask)) CALL(18, glBufferData, void, (GLenum target, GLsizeiptr size, const void *data, GLenum usage)) #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 + glBindBuffer(GL_ARRAY_BUFFER, args.next()); GLenum target = args.next(); uint32_t size; const unsigned char *data = args.next_arr(&size); @@ -139,7 +219,7 @@ CALL(21, glMatrixMode, void, (GLenum mode)) #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)) #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)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST - trampoline(target, pname, param); + trampoline(gl_state.bound_texture, target, pname, param); #else + glBindTexture(GL_TEXTURE_2D, args.next()); GLenum target = args.next(); GLenum pname = args.next(); GLint param = args.next(); @@ -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)) #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 + glBindTexture(GL_TEXTURE_2D, args.next()); GLenum target = args.next(); GLint level = args.next(); GLint internalformat = args.next(); @@ -229,14 +311,11 @@ CALL(26, glEnable, void, (GLenum cap)) #endif } -CALL(27, glEnableClientState, void, (GLenum array)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST - trampoline(array); -#else - func(args.next()); - return 0; -#endif +void glEnableClientState(const GLenum array) { + gl_state.enable_disable_array(array, true); } +#endif CALL(28, glPolygonOffset, void, (GLfloat factor, GLfloat units)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST @@ -249,16 +328,13 @@ CALL(28, glPolygonOffset, void, (GLfloat factor, GLfloat units)) #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 - trampoline(array); -#else - func(args.next()); - return 0; -#endif +void glDisableClientState(const GLenum array) { + gl_state.enable_disable_array(array, false); } +#endif CALL(30, glDepthRangef, void, (GLclampf near, GLclampf far)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST @@ -280,16 +356,15 @@ CALL(31, glDepthFunc, void, (GLenum func)) #endif } -CALL(32, glBindBuffer, void, (GLenum target, GLuint buffer)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST - trampoline(target, buffer); -#else - GLenum target = args.next(); - GLenum buffer = args.next(); - func(target, buffer); - return 0; -#endif +void glBindBuffer(const GLenum target, const GLuint buffer) { + if (target == GL_ARRAY_BUFFER) { + gl_state.bound_array_buffer = buffer; + } else { + ERR("Unsupported Buffer Binding: %u", target); + } } +#endif CALL(33, glClearColor, void, (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)) #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)) #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 + glBindTexture(GL_TEXTURE_2D, args.next()); GLenum target = args.next(); GLint level = args.next(); GLint xoffset = args.next(); @@ -485,16 +561,15 @@ CALL(48, glGetFloatv, void, (GLenum pname, GLfloat *params)) #endif } -CALL(49, glBindTexture, void, (GLenum target, GLuint texture)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST - trampoline(target, texture); -#else - GLenum target = args.next(); - GLuint texture = args.next(); - func(target, texture); - return 0; -#endif +void glBindTexture(const GLenum target, const GLuint texture) { + if (target == GL_TEXTURE_2D) { + gl_state.bound_texture = texture; + } else { + ERR("Unsupported Texture Binding: %u", target); + } } +#endif CALL(50, glTranslatef, void, (GLfloat x, GLfloat y, GLfloat z)) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST diff --git a/media-layer/trampoline/src/guest/guest.cpp b/media-layer/trampoline/src/guest/guest.cpp index dfdf783fae..d699e269e3 100644 --- a/media-layer/trampoline/src/guest/guest.cpp +++ b/media-layer/trampoline/src/guest/guest.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #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; } -// Pipe Method -#ifdef MCPI_USE_NATIVE_TRAMPOLINE +// Pipe Method (Native Trampoline Only) static int get_pipe(const char *env) { const char *value = getenv(env); if (value == nullptr) { @@ -26,7 +26,7 @@ static int get_pipe(const char *env) { std::string str = value; 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 static int arguments_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); return_value_pipe = get_pipe(TRAMPOLINE_RETURN_VALUE_PIPE_ENV); } - // Write Arguments - trampoline_pipe_arguments data = { - .id = id, - .length = length, - .args_addr = uint32_t(args) - }; - if (write(arguments_pipe, &data, sizeof(trampoline_pipe_arguments)) != sizeof(trampoline_pipe_arguments)) { + // Write ID + if (write(arguments_pipe, &id, sizeof(uint32_t)) != sizeof(uint32_t)) { ERR("Unable To Write Trampoline Command"); } // Return @@ -50,29 +45,42 @@ static uint32_t trampoline_pipe(const uint32_t id, const uint32_t length, const } 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 uint32_t _raw_trampoline(const uint32_t id, const uint32_t length, const unsigned char *args) { // Configure Method static int use_syscall = -1; if (use_syscall == -1) { - use_syscall = -#ifdef MCPI_USE_NATIVE_TRAMPOLINE - getenv(TRAMPOLINE_USE_PTRACE_ENV) != nullptr -#else - 1 -#endif - ; + use_syscall = getenv(TRAMPOLINE_USE_PIPES_ENV) == nullptr; } // Use Correct Method if (use_syscall) { return trampoline_syscall(id, length, args); } 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; } \ No newline at end of file diff --git a/media-layer/trampoline/src/guest/guest.h b/media-layer/trampoline/src/guest/guest.h index 7a36c9516b..fa9d22b436 100644 --- a/media-layer/trampoline/src/guest/guest.h +++ b/media-layer/trampoline/src/guest/guest.h @@ -5,11 +5,12 @@ #include "../common/common.h" // Trampoline Function +unsigned char *get_arguments_memory(); uint32_t _raw_trampoline(uint32_t id, uint32_t length, const unsigned char *args); // Compile Trampoline Arguments template -void _handle_trampoline_arg(unsigned char *&out, const T arg) { +void _handle_trampoline_arg(unsigned char *&out, const T &arg) { block_pointer(T); *(T *) out = arg; out += sizeof(T); @@ -33,7 +34,7 @@ struct copy_array { const void *data; }; template <> -inline void _handle_trampoline_arg(unsigned char *&out, const copy_array arg) { +inline void _handle_trampoline_arg(unsigned char *&out, const copy_array &arg) { *(uint32_t *) out = arg.size; out += sizeof(uint32_t); if (arg.size > 0) { @@ -45,7 +46,7 @@ inline void _handle_trampoline_arg(unsigned char *&out, const copy_a __attribute__((unused)) static void _add_to_trampoline_args(__attribute__((unused)) unsigned char *&out) { } template -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); _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 template 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; _add_to_trampoline_args(end, args...); const uint32_t length = end - out; diff --git a/media-layer/trampoline/src/media-layer-core.cpp b/media-layer/trampoline/src/media-layer-core.cpp index 513377a4a6..c70c072b46 100644 --- a/media-layer/trampoline/src/media-layer-core.cpp +++ b/media-layer/trampoline/src/media-layer-core.cpp @@ -87,7 +87,7 @@ CALL(8, media_swap_buffers, void, ()) CALL(9, media_cleanup, void, ()) #ifdef MEDIA_LAYER_TRAMPOLINE_GUEST - trampoline(); + trampoline(false); #else func(); return 0;