Statically allocate function pointer tables for libX11

This avoids the use of dynamically allocated memory, managed by a
shared_ptr<>, which required exit-time deallocation.

Bug: b/203541908
Change-Id: I27b2373f986583b05b1d9303a7701aa1c83a90d1
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/60089
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Sean Risser <srisser@google.com>
diff --git a/src/WSI/libX11.cpp b/src/WSI/libX11.cpp
index 5d72c4f..42e2267 100644
--- a/src/WSI/libX11.cpp
+++ b/src/WSI/libX11.cpp
@@ -51,34 +51,24 @@
 
 LibX11exports *LibX11::loadExports()
 {
-	static void *libX11 = nullptr;
-	static void *libXext = nullptr;
-	static std::unique_ptr<LibX11exports> libX11exports = nullptr;
-
-	if(!libX11)
-	{
+	static LibX11exports exports = [] {
 		if(getProcAddress(RTLD_DEFAULT, "XOpenDisplay"))  // Search the global scope for pre-loaded X11 library.
 		{
-			libX11exports = std::make_unique<LibX11exports>(RTLD_DEFAULT, RTLD_DEFAULT);
-			libX11 = (void *)-1;  // No need to load it.
+			return LibX11exports(RTLD_DEFAULT, RTLD_DEFAULT);
 		}
-		else
+
+		void *libX11 = loadLibrary("libX11.so");
+
+		if(libX11)
 		{
-			libX11 = loadLibrary("libX11.so");
-
-			if(libX11)
-			{
-				libXext = loadLibrary("libXext.so");
-				libX11exports = std::make_unique<LibX11exports>(libX11, libXext);
-			}
-			else
-			{
-				libX11 = (void *)-1;  // Don't attempt loading more than once.
-			}
+			void *libXext = loadLibrary("libXext.so");
+			return LibX11exports(libX11, libXext);
 		}
-	}
 
-	return libX11exports.get();
+		return LibX11exports();
+	}();
+
+	return exports.XOpenDisplay ? &exports : nullptr;
 }
 
 LibX11 libX11;
diff --git a/src/WSI/libX11.hpp b/src/WSI/libX11.hpp
index b40bc6c..ef354c9 100644
--- a/src/WSI/libX11.hpp
+++ b/src/WSI/libX11.hpp
@@ -22,31 +22,32 @@
 
 struct LibX11exports
 {
+	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);
+	Display *(*XOpenDisplay)(char *display_name) = nullptr;
+	Status (*XGetWindowAttributes)(Display *display, Window w, XWindowAttributes *window_attributes_return) = nullptr;
+	Screen *(*XDefaultScreenOfDisplay)(Display *display) = nullptr;
+	int (*XWidthOfScreen)(Screen *screen) = nullptr;
+	int (*XHeightOfScreen)(Screen *screen) = nullptr;
+	int (*XPlanesOfScreen)(Screen *screen) = nullptr;
 	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);
-	int (*XDrawString)(Display *display, Drawable d, GC gc, int x, int y, char *string, int length);
+	(Display *display, int screen_number) = nullptr;
+	int (*XDefaultDepth)(Display *display, int screen_number) = nullptr;
+	Status (*XMatchVisualInfo)(Display *display, int screen, int depth, int screen_class, XVisualInfo *vinfo_return) = nullptr;
+	Visual *(*XDefaultVisual)(Display *display, int screen_number) = nullptr;
+	int (*(*XSetErrorHandler)(int (*handler)(Display *, XErrorEvent *)))(Display *, XErrorEvent *) = nullptr;
+	int (*XSync)(Display *display, Bool discard) = nullptr;
+	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) = nullptr;
+	int (*XCloseDisplay)(Display *display) = nullptr;
+	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) = nullptr;
+	int (*XDrawString)(Display *display, Drawable d, GC gc, int x, int y, char *string, int length) = nullptr;
 
-	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);
+	Bool (*XShmQueryExtension)(Display *display) = nullptr;
+	XImage *(*XShmCreateImage)(Display *display, Visual *visual, unsigned int depth, int format, char *data, XShmSegmentInfo *shminfo, unsigned int width, unsigned int height) = nullptr;
+	Bool (*XShmAttach)(Display *display, XShmSegmentInfo *shminfo) = nullptr;
+	Bool (*XShmDetach)(Display *display, XShmSegmentInfo *shminfo) = nullptr;
+	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) = nullptr;
 };
 
 class LibX11