Manually load X11 and resolve its symbols when needed. This removes the static dependency on X11 on Linux, allowing for headless rendering on systems without it. Bug 20104157 Change-Id: I463c8b3340c3ad16cd0f0d1d0f8804ee31012dd0 Reviewed-on: https://swiftshader-review.googlesource.com/2832 Reviewed-by: Nicolas Capens <capn@google.com> Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/Main/FrameBufferX11.cpp b/src/Main/FrameBufferX11.cpp index 7fb97e4..f0d3c50 100644 --- a/src/Main/FrameBufferX11.cpp +++ b/src/Main/FrameBufferX11.cpp
@@ -15,9 +15,11 @@ #include "FrameBufferX11.hpp" +#include "libX11.hpp" + #include <sys/ipc.h> #include <sys/shm.h> -#include <string.h> +#include <string.h> #include <assert.h> namespace sw @@ -43,31 +45,31 @@ { if(!x_display) { - x_display = XOpenDisplay(0); + x_display = libX11->XOpenDisplay(0); } int screen = DefaultScreen(x_display); - x_gc = XDefaultGC(x_display, screen); - int depth = XDefaultDepth(x_display, screen); - - Status status = XMatchVisualInfo(x_display, screen, 32, TrueColor, &x_visual); - bool match = (status != 0 && x_visual.blue_mask == 0xFF); // Prefer X8R8G8B8 - Visual *visual = match ? x_visual.visual : XDefaultVisual(x_display, screen); + x_gc = libX11->XDefaultGC(x_display, screen); + int depth = libX11->XDefaultDepth(x_display, screen); - mit_shm = (XShmQueryExtension(x_display) == True); + Status status = libX11->XMatchVisualInfo(x_display, screen, 32, TrueColor, &x_visual); + bool match = (status != 0 && x_visual.blue_mask == 0xFF); // Prefer X8R8G8B8 + Visual *visual = match ? x_visual.visual : libX11->XDefaultVisual(x_display, screen); + + mit_shm = (libX11->XShmQueryExtension && libX11->XShmQueryExtension(x_display) == True); if(mit_shm) { - x_image = XShmCreateImage(x_display, visual, depth, ZPixmap, 0, &shminfo, width, height); + x_image = libX11->XShmCreateImage(x_display, visual, depth, ZPixmap, 0, &shminfo, width, height); shminfo.shmid = shmget(IPC_PRIVATE, x_image->bytes_per_line * x_image->height, IPC_CREAT | SHM_R | SHM_W); shminfo.shmaddr = x_image->data = buffer = (char*)shmat(shminfo.shmid, 0, 0); shminfo.readOnly = False; - PreviousXErrorHandler = XSetErrorHandler(XShmErrorHandler); - XShmAttach(x_display, &shminfo); // May produce a BadAccess error - XSync(x_display, False); - XSetErrorHandler(PreviousXErrorHandler); + PreviousXErrorHandler = libX11->XSetErrorHandler(XShmErrorHandler); + libX11->XShmAttach(x_display, &shminfo); // May produce a BadAccess error + libX11->XSync(x_display, False); + libX11->XSetErrorHandler(PreviousXErrorHandler); if(shmBadAccess) { @@ -84,7 +86,7 @@ if(!mit_shm) { buffer = new char[width * height * 4]; - x_image = XCreateImage(x_display, visual, depth, ZPixmap, 0, buffer, width, height, 32, width * 4); + x_image = libX11->XCreateImage(x_display, visual, depth, ZPixmap, 0, buffer, width, height, 32, width * 4); } } @@ -100,7 +102,7 @@ } else { - XShmDetach(x_display, &shminfo); + libX11->XShmDetach(x_display, &shminfo); XDestroyImage(x_image); shmdt(shminfo.shmaddr); shmctl(shminfo.shmid, IPC_RMID, 0); @@ -108,7 +110,7 @@ if(ownX11) { - XCloseDisplay(x_display); + libX11->XCloseDisplay(x_display); } } @@ -131,14 +133,14 @@ if(!mit_shm) { - XPutImage(x_display, x_window, x_gc, x_image, 0, 0, 0, 0, width, height); + libX11->XPutImage(x_display, x_window, x_gc, x_image, 0, 0, 0, 0, width, height); } else { - XShmPutImage(x_display, x_window, x_gc, x_image, 0, 0, 0, 0, width, height, False); + libX11->XShmPutImage(x_display, x_window, x_gc, x_image, 0, 0, 0, 0, width, height, False); } - XSync(x_display, False); + libX11->XSync(x_display, False); } }
diff --git a/src/Main/libX11.cpp b/src/Main/libX11.cpp new file mode 100644 index 0000000..ebd76ff --- /dev/null +++ b/src/Main/libX11.cpp
@@ -0,0 +1,48 @@ +#include "libX11.hpp" + +#include "Common/SharedLibrary.hpp" + +#define Bool int + +LibX11exports::LibX11exports(void *libX11, void *libXext) +{ + XOpenDisplay = (Display *(*)(char*))getProcAddress(libX11, "XOpenDisplay"); + XGetWindowAttributes = (Status (*)(Display*, Window, XWindowAttributes*))getProcAddress(libX11, "XGetWindowAttributes"); + XDefaultScreenOfDisplay = (Screen *(*)(Display*))getProcAddress(libX11, "XDefaultScreenOfDisplay"); + XWidthOfScreen = (int (*)(Screen*))getProcAddress(libX11, "XWidthOfScreen"); + XHeightOfScreen = (int (*)(Screen*))getProcAddress(libX11, "XHeightOfScreen"); + XPlanesOfScreen = (int (*)(Screen*))getProcAddress(libX11, "XPlanesOfScreen"); + XDefaultGC = (GC (*)(Display*, int))getProcAddress(libX11, "XDefaultGC"); + XDefaultDepth = (int (*)(Display*, int))getProcAddress(libX11, "XDefaultDepth"); + XMatchVisualInfo = (Status (*)(Display*, int, int, int, XVisualInfo*))getProcAddress(libX11, "XMatchVisualInfo"); + XDefaultVisual = (Visual *(*)(Display*, int screen_number))getProcAddress(libX11, "XDefaultVisual"); + XSetErrorHandler = (int (*(*)(int (*)(Display*, XErrorEvent*)))(Display*, XErrorEvent*))getProcAddress(libX11, "XSetErrorHandler"); + XSync = (int (*)(Display*, Bool))getProcAddress(libX11, "XSync"); + XCreateImage = (XImage *(*)(Display*, Visual*, unsigned int, int, int, char*, unsigned int, unsigned int, int, int))getProcAddress(libX11, "XCreateImage"); + XCloseDisplay = (int (*)(Display*))getProcAddress(libX11, "XCloseDisplay"); + XPutImage = (int (*)(Display*, Drawable, GC, XImage*, int, int, int, int, unsigned int, unsigned int))getProcAddress(libX11, "XPutImage"); + + XShmQueryExtension = (Bool (*)(Display*))getProcAddress(libXext, "XShmQueryExtension"); + XShmCreateImage = (XImage *(*)(Display*, Visual*, unsigned int, int, char*, XShmSegmentInfo*, unsigned int, unsigned int))getProcAddress(libXext, "XShmCreateImage"); + XShmAttach = (Bool (*)(Display*, XShmSegmentInfo*))getProcAddress(libXext, "XShmAttach"); + XShmDetach = (Bool (*)(Display*, XShmSegmentInfo*))getProcAddress(libXext, "XShmDetach"); + XShmPutImage = (int (*)(Display*, Drawable, GC, XImage*, int, int, int, int, unsigned int, unsigned int, bool))getProcAddress(libXext, "XShmPutImage"); +} + +LibX11exports *LibX11::operator->() +{ + static void *libX11 = nullptr; + static void *libXext = nullptr; + static LibX11exports *libX11exports = nullptr; + + if(!libX11) + { + libX11 = loadLibrary("libX11.so"); + libXext = loadLibrary("libXext.so"); + libX11exports = new LibX11exports(libX11, libXext); + } + + return libX11exports; +} + +LibX11 libX11;
diff --git a/src/Main/libX11.hpp b/src/Main/libX11.hpp new file mode 100644 index 0000000..eb5f6fc --- /dev/null +++ b/src/Main/libX11.hpp
@@ -0,0 +1,46 @@ +#ifndef libX11_hpp +#define libX11_hpp + +#define Bool int +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/extensions/XShm.h> + +struct LibX11exports +{ + LibX11exports(void *libX11, void *libXext); + + Display *(*XOpenDisplay)(char *display_name); + Status (*XGetWindowAttributes)(Display *display, Window w, XWindowAttributes *window_attributes_return); + Screen *(*XDefaultScreenOfDisplay)(Display *display); + int (*XWidthOfScreen)(Screen *screen); + int (*XHeightOfScreen)(Screen *screen); + int (*XPlanesOfScreen)(Screen *screen); + GC (*XDefaultGC)(Display *display, int screen_number); + int (*XDefaultDepth)(Display *display, int screen_number); + Status (*XMatchVisualInfo)(Display *display, int screen, int depth, int screen_class, XVisualInfo *vinfo_return); + Visual *(*XDefaultVisual)(Display *display, int screen_number); + int (*(*XSetErrorHandler)(int (*handler)(Display*, XErrorEvent*)))(Display*, XErrorEvent*); + int (*XSync)(Display *display, Bool discard); + XImage *(*XCreateImage)(Display *display, Visual *visual, unsigned int depth, int format, int offset, char *data, unsigned int width, unsigned int height, int bitmap_pad, int bytes_per_line); + int (*XCloseDisplay)(Display *display); + int (*XPutImage)(Display *display, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height); + + Bool (*XShmQueryExtension)(Display *display); + XImage *(*XShmCreateImage)(Display *display, Visual *visual, unsigned int depth, int format, char *data, XShmSegmentInfo *shminfo, unsigned int width, unsigned int height); + Bool (*XShmAttach)(Display *display, XShmSegmentInfo *shminfo); + Bool (*XShmDetach)(Display *display, XShmSegmentInfo *shminfo); + int (*XShmPutImage)(Display *display, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height, bool send_event); +}; + +#undef Bool + +class LibX11 +{ +public: + LibX11exports *operator->(); +}; + +extern LibX11 libX11; + +#endif // libX11_hpp
diff --git a/src/OpenGL/libEGL/Display.cpp b/src/OpenGL/libEGL/Display.cpp index cbd4d27..8d99bc7 100644 --- a/src/OpenGL/libEGL/Display.cpp +++ b/src/OpenGL/libEGL/Display.cpp
@@ -20,6 +20,10 @@ #include "libEGL/Context.hpp" #include "common/debug.h" +#if defined(__unix__) && !defined(__ANDROID__) +#include "Main/libX11.hpp" +#endif + #ifdef __ANDROID__ #include <system/window.h> #include <GceFrameBufferConfig.h> @@ -49,7 +53,14 @@ if(platform == EGL_PLATFORM_X11_EXT) { #if defined(__unix__) - displayId = XOpenDisplay(NULL); + if(libX11->XOpenDisplay) + { + displayId = libX11->XOpenDisplay(NULL); + } + else + { + return error(EGL_BAD_PARAMETER, (egl::Display*)EGL_NO_DISPLAY); + } #else return error(EGL_BAD_PARAMETER, (egl::Display*)EGL_NO_DISPLAY); #endif @@ -507,7 +518,7 @@ if(platform == EGL_PLATFORM_X11_EXT) { XWindowAttributes windowAttributes; - Status status = XGetWindowAttributes(displayId, window, &windowAttributes); + Status status = libX11->XGetWindowAttributes(displayId, window, &windowAttributes); return status == True; } @@ -573,10 +584,10 @@ #else if(platform == EGL_PLATFORM_X11_EXT) { - Screen *screen = XDefaultScreenOfDisplay(displayId); - displayMode.width = XWidthOfScreen(screen); - displayMode.height = XHeightOfScreen(screen); - unsigned int bpp = XPlanesOfScreen(screen); + Screen *screen = libX11->XDefaultScreenOfDisplay(displayId); + displayMode.width = libX11->XWidthOfScreen(screen); + displayMode.height = libX11->XHeightOfScreen(screen); + unsigned int bpp = libX11->XPlanesOfScreen(screen); switch(bpp) {
diff --git a/src/OpenGL/libEGL/Surface.cpp b/src/OpenGL/libEGL/Surface.cpp index 0770848..1a36a93 100644 --- a/src/OpenGL/libEGL/Surface.cpp +++ b/src/OpenGL/libEGL/Surface.cpp
@@ -23,6 +23,10 @@ #include "common/debug.h" #include "Main/FrameBuffer.hpp" +#if defined(__unix__) && !defined(__ANDROID__) +#include "Main/libX11.hpp" +#endif + #if defined(_WIN32) #include <tchar.h> #endif @@ -82,7 +86,7 @@ } void Surface::deleteResources() -{ +{ if(mDepthStencil) { mDepthStencil->release(); @@ -122,8 +126,8 @@ return reset(ANativeWindow_getWidth(mWindow), ANativeWindow_getHeight(mWindow)); #else XWindowAttributes windowAttributes; - XGetWindowAttributes(mDisplay->getNativeDisplay(), mWindow, &windowAttributes); - + libX11->XGetWindowAttributes(mDisplay->getNativeDisplay(), mWindow, &windowAttributes); + return reset(windowAttributes.width, windowAttributes.height); #endif } @@ -219,7 +223,7 @@ { return; } - + mSwapInterval = interval; mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval()); mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval()); @@ -302,7 +306,7 @@ int clientHeight = ANativeWindow_getHeight(mWindow); #else XWindowAttributes windowAttributes; - XGetWindowAttributes(mDisplay->getNativeDisplay(), mWindow, &windowAttributes); + libX11->XGetWindowAttributes(mDisplay->getNativeDisplay(), mWindow, &windowAttributes); int clientWidth = windowAttributes.width; int clientHeight = windowAttributes.height;
diff --git a/src/OpenGL/libEGL/libEGL.cbp b/src/OpenGL/libEGL/libEGL.cbp index 92a43c1..ee5fa97 100644 --- a/src/OpenGL/libEGL/libEGL.cbp +++ b/src/OpenGL/libEGL/libEGL.cbp
@@ -107,10 +107,13 @@ <Linker> <Add option="-Wl,--version-script=./exports.map" /> <Add option="-Wl,--hash-style=both" /> + <Add option="-Wl,--no-undefined" /> <Add library="pthread" /> - <Add library="X11" /> + <Add library="dl" /> </Linker> <Unit filename="../../Common/SharedLibrary.hpp" /> + <Unit filename="../../Main/libX11.cpp" /> + <Unit filename="../../Main/libX11.hpp" /> <Unit filename="../common/Object.cpp" /> <Unit filename="../common/Object.hpp" /> <Unit filename="../common/debug.cpp" />
diff --git a/src/OpenGL/libGLES_CM/libGLES_CM.cbp b/src/OpenGL/libGLES_CM/libGLES_CM.cbp index ce1178b..7041a83 100644 --- a/src/OpenGL/libGLES_CM/libGLES_CM.cbp +++ b/src/OpenGL/libGLES_CM/libGLES_CM.cbp
@@ -131,9 +131,9 @@ <Linker> <Add option="-Wl,--version-script=./exports.map" /> <Add option="-Wl,--hash-style=both" /> + <Add option="-Wl,--no-undefined" /> <Add library="pthread" /> - <Add library="X11" /> - <Add library="Xext" /> + <Add library="dl" /> </Linker> <Unit filename="../../Common/CPUID.cpp" /> <Unit filename="../../Common/CPUID.hpp" /> @@ -174,6 +174,8 @@ <Unit filename="../../Main/SwiftConfig.hpp" /> <Unit filename="../../Main/crc.cpp" /> <Unit filename="../../Main/crc.h" /> + <Unit filename="../../Main/libX11.cpp" /> + <Unit filename="../../Main/libX11.hpp" /> <Unit filename="../../Main/serialcommon.h" /> <Unit filename="../../Main/serialvalid.cpp" /> <Unit filename="../../Main/serialvalid.h" /> @@ -247,6 +249,8 @@ <Unit filename="../../Shader/VertexRoutine.hpp" /> <Unit filename="../../Shader/VertexShader.cpp" /> <Unit filename="../../Shader/VertexShader.hpp" /> + <Unit filename="../common/MatrixStack.cpp" /> + <Unit filename="../common/MatrixStack.hpp" /> <Unit filename="../common/NameSpace.cpp" /> <Unit filename="../common/NameSpace.hpp" /> <Unit filename="../common/Object.cpp" /> @@ -272,8 +276,6 @@ <Unit filename="Image.hpp" /> <Unit filename="IndexDataManager.cpp" /> <Unit filename="IndexDataManager.h" /> - <Unit filename="../common/MatrixStack.cpp" /> - <Unit filename="../common/MatrixStack.hpp" /> <Unit filename="Renderbuffer.cpp" /> <Unit filename="Renderbuffer.h" /> <Unit filename="ResourceManager.cpp" />
diff --git a/src/OpenGL/libGLESv2/libGLESv2.cbp b/src/OpenGL/libGLESv2/libGLESv2.cbp index 6f08551..4615472 100644 --- a/src/OpenGL/libGLESv2/libGLESv2.cbp +++ b/src/OpenGL/libGLESv2/libGLESv2.cbp
@@ -131,9 +131,9 @@ <Linker> <Add option="-Wl,--version-script=./exports.map" /> <Add option="-Wl,--hash-style=both" /> + <Add option="-Wl,--no-undefined" /> <Add library="pthread" /> - <Add library="X11" /> - <Add library="Xext" /> + <Add library="dl" /> </Linker> <Unit filename="../../Common/CPUID.cpp" /> <Unit filename="../../Common/CPUID.hpp" /> @@ -174,6 +174,8 @@ <Unit filename="../../Main/SwiftConfig.hpp" /> <Unit filename="../../Main/crc.cpp" /> <Unit filename="../../Main/crc.h" /> + <Unit filename="../../Main/libX11.cpp" /> + <Unit filename="../../Main/libX11.hpp" /> <Unit filename="../../Main/serialcommon.h" /> <Unit filename="../../Main/serialvalid.cpp" /> <Unit filename="../../Main/serialvalid.h" />
diff --git a/src/Radiance/libRAD/libRAD.cbp b/src/Radiance/libRAD/libRAD.cbp index 47be418..4017d4e 100644 --- a/src/Radiance/libRAD/libRAD.cbp +++ b/src/Radiance/libRAD/libRAD.cbp
@@ -153,6 +153,8 @@ <Unit filename="../../Main/SwiftConfig.hpp" /> <Unit filename="../../Main/crc.cpp" /> <Unit filename="../../Main/crc.h" /> + <Unit filename="../../Main/libX11.cpp" /> + <Unit filename="../../Main/libX11.hpp" /> <Unit filename="../../Main/serialcommon.h" /> <Unit filename="../../Main/serialvalid.cpp" /> <Unit filename="../../Main/serialvalid.h" />