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->()