WSI: Very basic XCB surface implementation.

Much like XlibSurfaceKHR, doesn't cope with any formats aside from 24-bit RGB.

Bug: b/124265819
Bug: b/139412276
Bug: b/139491466
Change-Id: I1146f6ff672a9016be04e6b4d595de40fa03346f
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/35149
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2588a2e..9a518af 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -71,6 +71,13 @@
 endif(CCACHE_FOUND)
 
 ###########################################################
+# Host libraries
+###########################################################
+
+find_library(X11 X11)
+find_library(XCB xcb)
+
+###########################################################
 # Options
 ###########################################################
 
@@ -1808,12 +1815,22 @@
         ${OPENGL_COMPILER_DIR}/ossource_posix.cpp
     )
 
-    list(APPEND VULKAN_LIST
-        ${SOURCE_DIR}/WSI/libX11.cpp
-        ${SOURCE_DIR}/WSI/libX11.hpp
-        ${SOURCE_DIR}/WSI/XlibSurfaceKHR.cpp
-        ${SOURCE_DIR}/WSI/XlibSurfaceKHR.hpp
-    )
+    if(X11)
+        list(APPEND VULKAN_LIST
+            ${SOURCE_DIR}/WSI/XlibSurfaceKHR.cpp
+            ${SOURCE_DIR}/WSI/XlibSurfaceKHR.hpp
+            ${SOURCE_DIR}/WSI/libX11.cpp
+            ${SOURCE_DIR}/WSI/libX11.hpp
+        )
+    endif(X11)
+
+    if(XCB)
+        list(APPEND VULKAN_LIST
+            ${SOURCE_DIR}/WSI/XcbSurfaceKHR.cpp
+            ${SOURCE_DIR}/WSI/XcbSurfaceKHR.hpp
+        )
+    endif(XCB)
+
 elseif(APPLE)
     list(APPEND SWIFTSHADER_LIST
         ${SOURCE_DIR}/Main/FrameBufferOSX.mm
@@ -1948,7 +1965,9 @@
         PREFIX ""
     )
     if(LINUX)
-        set_property(TARGET libEGL APPEND PROPERTY COMPILE_DEFINITIONS "USE_X11=1")
+        if(X11)
+            set_property(TARGET libEGL APPEND PROPERTY COMPILE_DEFINITIONS "USE_X11=1")
+        endif(X11)
     endif()
     if (ANDROID)
         set_target_properties(libEGL PROPERTIES SUFFIX "_swiftshader.so")
@@ -2033,8 +2052,14 @@
         set_property(TARGET libvk_swiftshader APPEND
                      PROPERTY COMPILE_DEFINITIONS "VK_USE_PLATFORM_WIN32_KHR")
     elseif(LINUX)
-        set_property(TARGET libvk_swiftshader APPEND
-                     PROPERTY COMPILE_DEFINITIONS "VK_USE_PLATFORM_XLIB_KHR")
+        if(X11)
+            set_property(TARGET libvk_swiftshader APPEND
+                        PROPERTY COMPILE_DEFINITIONS "VK_USE_PLATFORM_XLIB_KHR")
+        endif(X11)
+        if(XCB)
+            set_property(TARGET libvk_swiftshader APPEND
+                        PROPERTY COMPILE_DEFINITIONS "VK_USE_PLATFORM_XCB_KHR")
+        endif(XCB)
     elseif(APPLE)
         set_property(TARGET libvk_swiftshader APPEND
                      PROPERTY COMPILE_DEFINITIONS "VK_USE_PLATFORM_MACOS_MVK")
@@ -2090,7 +2115,7 @@
             COMPILE_OPTIONS "${SWIFTSHADER_COMPILE_OPTIONS}"
             COMPILE_DEFINITIONS "GL_GLEXT_PROTOTYPES"
         )
-        target_link_libraries(OGLES2HelloAPI dl X11 libEGL libGLESv2)   # Explicitly link our "lib*" targets, not the platform provided "EGL" and "GLESv2"
+        target_link_libraries(OGLES2HelloAPI dl ${X11} libEGL libGLESv2)   # Explicitly link our "lib*" targets, not the platform provided "EGL" and "GLESv2"
     elseif(APPLE)
         add_executable(OGLES2HelloAPI MACOSX_BUNDLE
             ${HELLO2_DIR}/OGLES2HelloAPI_OSX.mm
diff --git a/src/Vulkan/VkGetProcAddress.cpp b/src/Vulkan/VkGetProcAddress.cpp
index 06a8cc9..2f90548 100644
--- a/src/Vulkan/VkGetProcAddress.cpp
+++ b/src/Vulkan/VkGetProcAddress.cpp
@@ -89,6 +89,11 @@
 	MAKE_VULKAN_INSTANCE_ENTRY(vkGetPhysicalDeviceSurfacePresentModesKHR),
 	MAKE_VULKAN_INSTANCE_ENTRY(vkGetPhysicalDevicePresentRectanglesKHR),
 #endif
+#ifdef VK_USE_PLATFORM_XCB_KHR
+	// VK_KHR_Xcb_surface
+	MAKE_VULKAN_INSTANCE_ENTRY(vkCreateXcbSurfaceKHR),
+	MAKE_VULKAN_INSTANCE_ENTRY(vkGetPhysicalDeviceXcbPresentationSupportKHR),
+#endif
 #ifdef VK_USE_PLATFORM_XLIB_KHR
 	// VK_KHR_xlib_surface
 	MAKE_VULKAN_INSTANCE_ENTRY(vkCreateXlibSurfaceKHR),
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index e4d7698..7b1bd95 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -46,6 +46,10 @@
 #include "WSI/MacOSSurfaceMVK.h"
 #endif
 
+#ifdef VK_USE_PLATFORM_XCB_KHR
+#include "WSI/XcbSurfaceKHR.hpp"
+#endif
+
 #ifdef VK_USE_PLATFORM_XLIB_KHR
 #include "WSI/XlibSurfaceKHR.hpp"
 #endif
@@ -166,6 +170,9 @@
 #ifndef __ANDROID__
 	{ VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION },
 #endif
+#ifdef VK_USE_PLATFORM_XCB_KHR
+	{ VK_KHR_XCB_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_SPEC_VERSION },
+#endif
 #ifdef VK_USE_PLATFORM_XLIB_KHR
 	{ VK_KHR_XLIB_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_SPEC_VERSION },
 #endif
@@ -2657,6 +2664,24 @@
 	vk::Cast(device)->getDescriptorSetLayoutSupport(pCreateInfo, pSupport);
 }
 
+#ifdef VK_USE_PLATFORM_XCB_KHR
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface)
+{
+	TRACE("(VkInstance instance = %p, VkXcbSurfaceCreateInfoKHR* pCreateInfo = %p, VkAllocationCallbacks* pAllocator = %p, VkSurface* pSurface = %p)",
+			instance, pCreateInfo, pAllocator, pSurface);
+
+	return vk::XcbSurfaceKHR::Create(pAllocator, pCreateInfo, pSurface);
+}
+
+VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id)
+{
+	TRACE("(VkPhysicalDevice physicalDevice = %p, uint32_t queueFamilyIndex = %d, xcb_connection_t* connection = %p, xcb_visualid_t visual_id = %d)",
+		physicalDevice, int(queueFamilyIndex), connection, int(visual_id));
+
+	return VK_TRUE;
+}
+#endif
+
 #ifdef VK_USE_PLATFORM_XLIB_KHR
 VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface)
 {
diff --git a/src/WSI/XcbSurfaceKHR.cpp b/src/WSI/XcbSurfaceKHR.cpp
new file mode 100644
index 0000000..81fe40e
--- /dev/null
+++ b/src/WSI/XcbSurfaceKHR.cpp
@@ -0,0 +1,172 @@
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "XcbSurfaceKHR.hpp"
+
+#include "Vulkan/VkDeviceMemory.hpp"
+#include "Vulkan/VkImage.hpp"
+
+#include "System/SharedLibrary.hpp"
+
+#include <memory>
+
+namespace
+{
+
+template <typename FPTR>
+void getFuncAddress(void *lib, const char *name, FPTR *out)
+{
+	*out = reinterpret_cast<FPTR>(getProcAddress(lib, name));
+}
+
+struct LibXcbExports
+{
+	LibXcbExports(void *lib)
+	{
+		getFuncAddress(lib, "xcb_create_gc", &xcb_create_gc);
+		getFuncAddress(lib, "xcb_flush", &xcb_flush);
+		getFuncAddress(lib, "xcb_free_gc", &xcb_free_gc);
+		getFuncAddress(lib, "xcb_generate_id", &xcb_generate_id);
+		getFuncAddress(lib, "xcb_get_geometry", &xcb_get_geometry);
+		getFuncAddress(lib, "xcb_get_geometry_reply", &xcb_get_geometry_reply);
+		getFuncAddress(lib, "xcb_put_image", &xcb_put_image);
+	}
+
+	xcb_void_cookie_t (*xcb_create_gc)(xcb_connection_t *c, xcb_gcontext_t cid, xcb_drawable_t drawable, uint32_t value_mask, const void *value_list);
+	int (*xcb_flush)(xcb_connection_t *c);
+	xcb_void_cookie_t (*xcb_free_gc)(xcb_connection_t *c, xcb_gcontext_t gc);
+	uint32_t (*xcb_generate_id)(xcb_connection_t *c);
+	xcb_get_geometry_cookie_t (*xcb_get_geometry)(xcb_connection_t *c, xcb_drawable_t drawable);
+	xcb_get_geometry_reply_t* (*xcb_get_geometry_reply)(xcb_connection_t *c, xcb_get_geometry_cookie_t cookie, xcb_generic_error_t **e);
+	xcb_void_cookie_t (*xcb_put_image)(xcb_connection_t *c, uint8_t format, xcb_drawable_t drawable, xcb_gcontext_t gc, uint16_t width,uint16_t height, int16_t dst_x, int16_t dst_y, uint8_t left_pad, uint8_t depth, uint32_t data_len, const uint8_t* data);
+};
+
+class LibXcb
+{
+public:
+	operator bool()
+	{
+		return loadExports();
+	}
+
+	LibXcbExports *operator->()
+	{
+		return loadExports();
+	}
+
+private:
+	LibXcbExports *loadExports()
+	{
+		static auto exports = []
+		{
+			if (getProcAddress(RTLD_DEFAULT, "xcb_create_gc"))
+			{
+				return std::unique_ptr<LibXcbExports>(new LibXcbExports(RTLD_DEFAULT));
+			}
+
+			if (auto lib = loadLibrary("libXcb.so"))
+			{
+				return std::unique_ptr<LibXcbExports>(new LibXcbExports(lib));
+			}
+
+			return std::unique_ptr<LibXcbExports>();
+		}();
+
+		return exports.get();
+	}
+};
+
+LibXcb libXcb;
+
+} // anonymous namespace
+
+namespace vk {
+
+XcbSurfaceKHR::XcbSurfaceKHR(const VkXcbSurfaceCreateInfoKHR *pCreateInfo, void *mem) :
+	connection(pCreateInfo->connection),
+	window(pCreateInfo->window)
+{
+}
+
+void XcbSurfaceKHR::destroySurface(const VkAllocationCallbacks *pAllocator)
+{
+
+}
+
+size_t XcbSurfaceKHR::ComputeRequiredAllocationSize(const VkXcbSurfaceCreateInfoKHR *pCreateInfo)
+{
+	return 0;
+}
+
+void XcbSurfaceKHR::getSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) const
+{
+	SurfaceKHR::getSurfaceCapabilities(pSurfaceCapabilities);
+
+	auto geom = libXcb->xcb_get_geometry_reply(connection, libXcb->xcb_get_geometry(connection, window), nullptr);
+	VkExtent2D extent = {static_cast<uint32_t>(geom->width), static_cast<uint32_t>(geom->height)};
+	free(geom);
+
+	pSurfaceCapabilities->currentExtent = extent;
+	pSurfaceCapabilities->minImageExtent = extent;
+	pSurfaceCapabilities->maxImageExtent = extent;
+}
+
+void XcbSurfaceKHR::attachImage(PresentImage* image)
+{
+ 	auto gc = libXcb->xcb_generate_id(connection);
+
+	uint32_t values[2] = {0, 0xffffffff};
+ 	libXcb->xcb_create_gc(connection, gc, window, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, values);
+
+	graphicsContexts[image] = gc;
+}
+
+void XcbSurfaceKHR::detachImage(PresentImage* image)
+{
+	auto it = graphicsContexts.find(image);
+	if(it != graphicsContexts.end())
+	{
+		libXcb->xcb_free_gc(connection, it->second);
+		graphicsContexts.erase(image);
+	}
+}
+
+void XcbSurfaceKHR::present(PresentImage* image)
+{
+	auto it = graphicsContexts.find(image);
+	if(it != graphicsContexts.end())
+	{
+		// TODO: Convert image if not RGB888.
+		VkExtent3D extent = image->getImage()->getMipLevelExtent(VK_IMAGE_ASPECT_COLOR_BIT, 0);
+		int stride = image->getImage()->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
+		auto buffer = reinterpret_cast<uint8_t*>(image->getImageMemory()->getOffsetPointer(0));
+		size_t bufferSize = extent.height * stride;
+		constexpr int depth = 24; // TODO: Actually use window display depth.
+
+		libXcb->xcb_put_image(
+			connection,
+			XCB_IMAGE_FORMAT_Z_PIXMAP,
+			window,
+			it->second,
+			extent.width,
+			extent.height,
+			0, 0,       // dst x, y
+			0,          // left_pad
+			depth,
+			bufferSize, // data_len
+			buffer      // data
+		);
+
+		libXcb->xcb_flush(connection);
+	}
+}
+
+}
\ No newline at end of file
diff --git a/src/WSI/XcbSurfaceKHR.hpp b/src/WSI/XcbSurfaceKHR.hpp
new file mode 100644
index 0000000..dacd382
--- /dev/null
+++ b/src/WSI/XcbSurfaceKHR.hpp
@@ -0,0 +1,48 @@
+// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SWIFTSHADER_XCBSURFACEKHR_HPP
+#define SWIFTSHADER_XCBSURFACEKHR_HPP
+
+#include "Vulkan/VkObject.hpp"
+#include "VkSurfaceKHR.hpp"
+#include <xcb/xcb.h>
+#include "vulkan/vulkan_xcb.h"
+
+#include <unordered_map>
+
+namespace vk {
+
+class XcbSurfaceKHR : public SurfaceKHR, public ObjectBase<XcbSurfaceKHR, VkSurfaceKHR> {
+public:
+	XcbSurfaceKHR(const VkXcbSurfaceCreateInfoKHR *pCreateInfo, void *mem);
+
+	void destroySurface(const VkAllocationCallbacks *pAllocator) override;
+
+	static size_t ComputeRequiredAllocationSize(const VkXcbSurfaceCreateInfoKHR *pCreateInfo);
+
+	void getSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) const override;
+
+	virtual void attachImage(PresentImage* image) override;
+	virtual void detachImage(PresentImage* image) override;
+	void present(PresentImage* image) override;
+
+private:
+	xcb_connection_t* connection;
+	xcb_window_t window;
+	std::unordered_map<PresentImage*, uint32_t> graphicsContexts;
+};
+
+}
+#endif //SWIFTSHADER_XCBSURFACEKHR_HPP
diff --git a/src/WSI/XlibSurfaceKHR.cpp b/src/WSI/XlibSurfaceKHR.cpp
index a193c23..0ebca02 100644
--- a/src/WSI/XlibSurfaceKHR.cpp
+++ b/src/WSI/XlibSurfaceKHR.cpp
@@ -17,8 +17,6 @@
 #include "Vulkan/VkDeviceMemory.hpp"
 #include "Vulkan/VkImage.hpp"
 
-#include <string.h>
-
 namespace vk {
 
 XlibSurfaceKHR::XlibSurfaceKHR(const VkXlibSurfaceCreateInfoKHR *pCreateInfo, void *mem) :
diff --git a/src/WSI/XlibSurfaceKHR.hpp b/src/WSI/XlibSurfaceKHR.hpp
index 0dcb5e4..f580836 100644
--- a/src/WSI/XlibSurfaceKHR.hpp
+++ b/src/WSI/XlibSurfaceKHR.hpp
@@ -20,7 +20,7 @@
 #include "VkSurfaceKHR.hpp"
 #include "vulkan/vulkan_xlib.h"
 
-#include <map>
+#include <unordered_map>
 
 namespace vk {
 
@@ -43,7 +43,7 @@
 	const Window window;
 	GC gc;
 	Visual *visual = nullptr;
-	std::map<PresentImage*, XImage*> imageMap;
+	std::unordered_map<PresentImage*, XImage*> imageMap;
 };
 
 }
diff --git a/src/WSI/libX11.cpp b/src/WSI/libX11.cpp
index 5cca9f8..74e9dd1 100644
--- a/src/WSI/libX11.cpp
+++ b/src/WSI/libX11.cpp
@@ -18,30 +18,40 @@
 
 #define Bool int
 
+namespace {
+
+template <typename FPTR>
+void getFuncAddress(void *lib, const char *name, FPTR *out)
+{
+	*out = reinterpret_cast<FPTR>(getProcAddress(lib, name));
+}
+
+} // anonymous namespace
+
 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");
-	XDrawString = (int (*)(Display*, Drawable, GC, int, int, char*, int))getProcAddress(libX11, "XDrawString");
+	getFuncAddress(libX11, "XOpenDisplay", &XOpenDisplay);
+	getFuncAddress(libX11, "XGetWindowAttributes", &XGetWindowAttributes);
+	getFuncAddress(libX11, "XDefaultScreenOfDisplay", &XDefaultScreenOfDisplay);
+	getFuncAddress(libX11, "XWidthOfScreen", &XWidthOfScreen);
+	getFuncAddress(libX11, "XHeightOfScreen", &XHeightOfScreen);
+	getFuncAddress(libX11, "XPlanesOfScreen", &XPlanesOfScreen);
+	getFuncAddress(libX11, "XDefaultGC", &XDefaultGC);
+	getFuncAddress(libX11, "XDefaultDepth", &XDefaultDepth);
+	getFuncAddress(libX11, "XMatchVisualInfo", &XMatchVisualInfo);
+	getFuncAddress(libX11, "XDefaultVisual", &XDefaultVisual);
+	getFuncAddress(libX11, "XSetErrorHandler", &XSetErrorHandler);
+	getFuncAddress(libX11, "XSync", &XSync);
+	getFuncAddress(libX11, "XCreateImage", &XCreateImage);
+	getFuncAddress(libX11, "XCloseDisplay", &XCloseDisplay);
+	getFuncAddress(libX11, "XPutImage", &XPutImage);
+	getFuncAddress(libX11, "XDrawString", &XDrawString);
 
-	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");
+	getFuncAddress(libXext, "XShmQueryExtension", &XShmQueryExtension);
+	getFuncAddress(libXext, "XShmCreateImage", &XShmCreateImage);
+	getFuncAddress(libXext, "XShmAttach", &XShmAttach);
+	getFuncAddress(libXext, "XShmDetach", &XShmDetach);
+	getFuncAddress(libXext, "XShmPutImage", &XShmPutImage);
 }
 
 LibX11exports *LibX11::operator->()