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" />