diff --git a/Dockerfile.client b/Dockerfile.client index b7aaa64..27d0b5d 100644 --- a/Dockerfile.client +++ b/Dockerfile.client @@ -8,7 +8,6 @@ RUN \ apt-get install -y libglvnd-dev:armhf libsdl1.2-dev:armhf libx11-dev:armhf build-essential zlib1g-dev:armhf git cmake curl gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libfreeimage-dev:armhf libglfw3-dev:armhf xinput:armhf libxfixes-dev:armhf RUN ln -s /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2 /usr/lib/libGLESv2.so -RUN ln -s /usr/lib/arm-linux-gnueabihf/libEGL.so.1 /usr/lib/libEGL.so ADD ./build /app/build diff --git a/Dockerfile.server b/Dockerfile.server index e0d52fb..2c83a65 100644 --- a/Dockerfile.server +++ b/Dockerfile.server @@ -1,7 +1,3 @@ FROM thebrokenrail/minecraft-pi:client ENV MCPI_MODE=server - -RUN apt-get install -y xvfb - -ENTRYPOINT xvfb-run ./launcher diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index a9a6593..fe9f992 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -4,6 +4,7 @@ project(core) add_compile_options(-Wall -Wextra -Werror) -add_library(bcm_host SHARED src/bcm_host.c) +add_library(bcm_host SHARED src/stubs/bcm_host.c) +add_library(EGL SHARED src/stubs/EGL.c) add_executable(launcher src/launcher.c) diff --git a/core/src/stubs/EGL.c b/core/src/stubs/EGL.c new file mode 100644 index 0000000..af7cf52 --- /dev/null +++ b/core/src/stubs/EGL.c @@ -0,0 +1,37 @@ +#include + +// EGL/SDL Is Replaced With GLFW + +EGLDisplay eglGetDisplay(__attribute__((unused)) NativeDisplayType native_display) { + return 0; +} +EGLBoolean eglInitialize(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLint *major, __attribute__((unused)) EGLint *minor) { + return EGL_TRUE; +} +EGLBoolean eglChooseConfig(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLint const *attrib_list, __attribute__((unused)) EGLConfig *configs, __attribute__((unused)) EGLint config_size, __attribute__((unused)) EGLint *num_config) { + return EGL_TRUE; +} +EGLBoolean eglBindAPI(__attribute__((unused)) EGLenum api) { + return EGL_TRUE; +} +EGLContext eglCreateContext(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) EGLContext share_context, __attribute__((unused)) EGLint const *attrib_list) { + return 0; +} +EGLSurface eglCreateWindowSurface(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) NativeWindowType native_window, __attribute__((unused)) EGLint const *attrib_list) { + return 0; +} +EGLBoolean eglMakeCurrent(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface draw, __attribute__((unused)) EGLSurface read, __attribute__((unused)) EGLContext context) { + return EGL_TRUE; +} +EGLBoolean eglDestroySurface(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface) { + return EGL_TRUE; +} +EGLBoolean eglDestroyContext(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLContext context) { + return EGL_TRUE; +} +EGLBoolean eglTerminate(__attribute__((unused)) EGLDisplay display) { + return EGL_TRUE; +} +EGLBoolean eglSwapBuffers(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface) { + return EGL_TRUE; +} \ No newline at end of file diff --git a/core/src/bcm_host.c b/core/src/stubs/bcm_host.c similarity index 100% rename from core/src/bcm_host.c rename to core/src/stubs/bcm_host.c diff --git a/mods/CMakeLists.txt b/mods/CMakeLists.txt index 2606216..d5044b4 100644 --- a/mods/CMakeLists.txt +++ b/mods/CMakeLists.txt @@ -22,7 +22,7 @@ target_link_libraries(extra core dl server) find_package(glfw3 3.3 REQUIRED) add_library(compat SHARED src/compat.c) -target_link_libraries(compat core extra SDL EGL GLESv1_CM GLESv2 X11 dl freeimage glfw Xfixes) +target_link_libraries(compat core extra SDL GLESv1_CM GLESv2 X11 dl freeimage glfw Xfixes) # Force GLESv1 Link target_link_options(compat PRIVATE "-Wl,--no-as-needed") diff --git a/mods/src/compat.c b/mods/src/compat.c index e1b30a0..f2e6a27 100644 --- a/mods/src/compat.c +++ b/mods/src/compat.c @@ -14,7 +14,6 @@ #include #include -#include #include #include @@ -182,47 +181,41 @@ static void glfw_scroll(__attribute__((unused)) GLFWwindow *window, __attribute_ HOOK(SDL_WM_SetCaption, void, (const char *title, __attribute__((unused)) const char *icon)) { FreeImage_Initialise(0); - glfwSetErrorCallback(glfw_error); + // Don't Enable GLFW In Server Mode + if (!is_server) { + glfwSetErrorCallback(glfw_error); - if (!glfwInit()) { - fprintf(stderr, "Unable To Initialize GLFW\n"); - exit(1); - } + if (!glfwInit()) { + fprintf(stderr, "Unable To Initialize GLFW\n"); + exit(1); + } - if (is_server) { - // Don't Show Window In Server Mode - glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - } else { // Create OpenGL ES 1.1 Context glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - } - glfw_window = glfwCreateWindow(840, 480, title, NULL, NULL); - if (!glfw_window) { - fprintf(stderr, "Unable To Create GLFW Window\n"); - exit(1); - } + glfw_window = glfwCreateWindow(840, 480, title, NULL, NULL); + if (!glfw_window) { + fprintf(stderr, "Unable To Create GLFW Window\n"); + exit(1); + } - if (!is_server) { // Don't Process Events In Server Mode glfwSetKeyCallback(glfw_window, glfw_key); glfwSetCharCallback(glfw_window, glfw_char); glfwSetCursorPosCallback(glfw_window, glfw_motion); glfwSetMouseButtonCallback(glfw_window, glfw_click); glfwSetScrollCallback(glfw_window, glfw_scroll); - } - store_x11_window(); + store_x11_window(); - if (!is_server) { glfwMakeContextCurrent(glfw_window); } } +#include HOOK(eglSwapBuffers, EGLBoolean, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface)) { if (!is_server) { // Don't Swap Buffers In A Context-Less Window @@ -321,8 +314,8 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) { // Process GLFW Events glfwPollEvents(); - // Close Window - if (glfwWindowShouldClose(glfw_window)) { + // Close Window (Ignore In Server Mode) + if (!is_server && glfwWindowShouldClose(glfw_window)) { SDL_Event event; event.type = SDL_QUIT; SDL_PushEvent(&event); @@ -361,8 +354,11 @@ HOOK(SDL_Quit, void, ()) { ensure_SDL_Quit(); (*real_SDL_Quit)(); - glfwDestroyWindow(glfw_window); - glfwTerminate(); + // GLFW Is Disabled In Server Mode + if (!is_server) { + glfwDestroyWindow(glfw_window); + glfwTerminate(); + } } static SDL_GrabMode fake_grab_mode = SDL_GRAB_OFF; @@ -370,7 +366,7 @@ static SDL_GrabMode fake_grab_mode = SDL_GRAB_OFF; // Fix SDL Cursor Visibility/Grabbing HOOK(SDL_WM_GrabInput, SDL_GrabMode, (SDL_GrabMode mode)) { if (is_server) { - // Don't Grab Input In Server/Headless Mode + // Don't Grab Input In Server Mode if (mode != SDL_GRAB_QUERY) { fake_grab_mode = mode; } @@ -410,54 +406,56 @@ HOOK(SDL_SetVideoMode, SDL_Surface *, (__attribute__((unused)) int width, __attr } HOOK(XTranslateCoordinates, int, (Display *display, Window src_w, Window dest_w, int src_x, int src_y, int *dest_x_return, int *dest_y_return, Window *child_return)) { - ensure_XTranslateCoordinates(); - if (window_loaded) { - return (*real_XTranslateCoordinates)(x11_display, x11_window, x11_root_window, src_x, src_y, dest_x_return, dest_y_return, child_return); + if (!is_server) { + ensure_XTranslateCoordinates(); + if (window_loaded) { + return (*real_XTranslateCoordinates)(x11_display, x11_window, x11_root_window, src_x, src_y, dest_x_return, dest_y_return, child_return); + } else { + return (*real_XTranslateCoordinates)(display, src_w, dest_w, src_x, src_y, dest_x_return, dest_y_return, child_return); + } } else { - return (*real_XTranslateCoordinates)(display, src_w, dest_w, src_x, src_y, dest_x_return, dest_y_return, child_return); + // No X11 + *dest_x_return = src_x; + *dest_y_return = src_y; + return 1; } } HOOK(XGetWindowAttributes, int, (Display *display, Window w, XWindowAttributes *window_attributes_return)) { - ensure_XGetWindowAttributes(); - if (window_loaded) { - return (*real_XGetWindowAttributes)(x11_display, x11_window, window_attributes_return); + if (!is_server) { + ensure_XGetWindowAttributes(); + if (window_loaded) { + return (*real_XGetWindowAttributes)(x11_display, x11_window, window_attributes_return); + } else { + return (*real_XGetWindowAttributes)(display, w, window_attributes_return); + } } else { - return (*real_XGetWindowAttributes)(display, w, window_attributes_return); + // No X11 + XWindowAttributes attributes; + attributes.x = 0; + attributes.y = 0; + attributes.width = 640; + attributes.height = 480; + *window_attributes_return = attributes; + return 1; } } -// EGL Stubs - -HOOK(eglGetDisplay, EGLDisplay, (__attribute__((unused)) NativeDisplayType native_display)) { - return 0; +static void x11_nop() { + // NOP } -HOOK(eglInitialize, EGLBoolean, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLint *major, __attribute__((unused)) EGLint *minor)) { - return EGL_TRUE; -} -HOOK(eglChooseConfig, EGLBoolean, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLint const *attrib_list, __attribute__((unused)) EGLConfig *configs, __attribute__((unused)) EGLint config_size, __attribute__((unused)) EGLint *num_config)) { - return EGL_TRUE; -} -HOOK(eglBindAPI, EGLBoolean, (__attribute__((unused)) EGLenum api)) { - return EGL_TRUE; -} -HOOK(eglCreateContext, EGLContext, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) EGLContext share_context, __attribute__((unused)) EGLint const *attrib_list)) { - return 0; -} -HOOK(eglCreateWindowSurface, EGLSurface, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) NativeWindowType native_window, __attribute__((unused)) EGLint const *attrib_list)) { - return 0; -} -HOOK(eglMakeCurrent, EGLBoolean, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface draw, __attribute__((unused)) EGLSurface read, __attribute__((unused)) EGLContext context)) { - return EGL_TRUE; -} -HOOK(eglDestroySurface, EGLBoolean, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface)) { - return EGL_TRUE; -} -HOOK(eglDestroyContext, EGLBoolean, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLContext context)) { - return EGL_TRUE; -} -HOOK(eglTerminate, EGLBoolean, (__attribute__((unused)) EGLDisplay display)) { - return EGL_TRUE; +HOOK(SDL_GetWMInfo, int, (SDL_SysWMinfo *info)) { + if (!is_server) { + ensure_SDL_GetWMInfo(); + return (*real_SDL_GetWMInfo)(info); + } else { + // Return Fake Lock Functions In Server Mode Since X11 Is Disabled + SDL_SysWMinfo ret; + ret.info.x11.lock_func = x11_nop; + ret.info.x11.unlock_func = x11_nop; + *info = ret; + return 1; + } } #include @@ -466,10 +464,14 @@ HOOK(eglTerminate, EGLBoolean, (__attribute__((unused)) EGLDisplay display)) { __attribute__((constructor)) static void init() { int mode = extra_get_mode(); if (mode != 1) { + // Force Software Rendering When Not In Native Mode setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1); } if (mode == 0) { + // Use VirGL When In VirGL Mode setenv("GALLIUM_DRIVER", "virpipe", 1); } is_server = mode == 2; + // Disable X11 When In Server Mode + setenv("SDL_VIDEODRIVER", is_server ? "dummy" : "x11", 1); }