vkAcquireNextImageKHR and vkQueuePresentKHR

The following changes will allow to present
to the screen. However, do not adjust the
size of the window.

Bug: b/124265819
Change-Id: Iaa42f458af9555e91d47238397112324ec080a67
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/26008
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Hernan Liatis <hliatis@google.com>
diff --git a/src/Vulkan/VkGetProcAddress.cpp b/src/Vulkan/VkGetProcAddress.cpp
index ea7eb7b..40b8f7e 100644
--- a/src/Vulkan/VkGetProcAddress.cpp
+++ b/src/Vulkan/VkGetProcAddress.cpp
@@ -251,6 +251,8 @@
 	MAKE_VULKAN_DEVICE_ENTRY(vkCreateSwapchainKHR),
 	MAKE_VULKAN_DEVICE_ENTRY(vkDestroySwapchainKHR),
 	MAKE_VULKAN_DEVICE_ENTRY(vkGetSwapchainImagesKHR),
+	MAKE_VULKAN_DEVICE_ENTRY(vkAcquireNextImageKHR),
+	MAKE_VULKAN_DEVICE_ENTRY(vkQueuePresentKHR),
 };
 #undef MAKE_VULKAN_DEVICE_ENTRY
 
diff --git a/src/Vulkan/VkQueue.cpp b/src/Vulkan/VkQueue.cpp
index 1a7f0fc..339eeed 100644
--- a/src/Vulkan/VkQueue.cpp
+++ b/src/Vulkan/VkQueue.cpp
@@ -17,6 +17,7 @@
 #include "VkQueue.hpp"
 #include "VkSemaphore.hpp"
 #include "Device/Renderer.hpp"
+#include "WSI/VkSwapchainKHR.hpp"
 
 namespace vk
 {
@@ -65,12 +66,20 @@
 	}
 }
 
-void Queue::waitIdle()

-{

-	// equivalent to submitting a fence to a queue and waiting

-	// with an infinite timeout for that fence to signal

-

-	// FIXME (b/117835459): implement once we have working fences

+void Queue::waitIdle()
+{
+	// equivalent to submitting a fence to a queue and waiting
+	// with an infinite timeout for that fence to signal
+
+	// FIXME (b/117835459): implement once we have working fences
+}
+
+void Queue::present(const VkPresentInfoKHR* presentInfo)
+{
+	for(uint32_t i = 0; i < presentInfo->swapchainCount; i++)
+	{
+		vk::Cast(presentInfo->pSwapchains[i])->present(presentInfo->pImageIndices[i]);
+	}
 }
 
 } // namespace vk
\ No newline at end of file
diff --git a/src/Vulkan/VkQueue.hpp b/src/Vulkan/VkQueue.hpp
index d38e3a0..5716fa8 100644
--- a/src/Vulkan/VkQueue.hpp
+++ b/src/Vulkan/VkQueue.hpp
@@ -43,6 +43,7 @@
 	void destroy();
 	void submit(uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence);
 	void waitIdle();
+	void present(const VkPresentInfoKHR* presentInfo);
 
 private:
 	sw::Context* context = nullptr;
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index a22a3ef..3896b53 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -2212,4 +2212,22 @@
 	return vk::Cast(swapchain)->getImages(pSwapchainImageCount, pSwapchainImages);
 }
 
+VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex)
+{
+	TRACE("(VkDevice device = 0x%X, VkSwapchainKHR swapchain = 0x%X, uint64_t timeout = 0x%X, VkSemaphore semaphore = 0x%X, VkFence fence = 0x%X, uint32_t* pImageIndex = 0x%X)",
+			device, swapchain, timeout, semaphore, fence, pImageIndex);
+
+	return vk::Cast(swapchain)->getNextImage(timeout, semaphore, fence, pImageIndex);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo)
+{
+	TRACE("(VkQueue queue = 0x%X, const VkPresentInfoKHR* pPresentInfo = 0x%X)",
+			queue, pPresentInfo);
+
+	vk::Cast(queue)->present(pPresentInfo);
+
+	return VK_SUCCESS;
+}
+
 }
diff --git a/src/WSI/VkSurfaceKHR.cpp b/src/WSI/VkSurfaceKHR.cpp
index 0fd3468..2877f8a 100644
--- a/src/WSI/VkSurfaceKHR.cpp
+++ b/src/WSI/VkSurfaceKHR.cpp
@@ -83,6 +83,4 @@
 	return VK_SUCCESS;
 }
 
-
-
 }
\ No newline at end of file
diff --git a/src/WSI/VkSurfaceKHR.hpp b/src/WSI/VkSurfaceKHR.hpp
index 4734097..0d2c2e2 100644
--- a/src/WSI/VkSurfaceKHR.hpp
+++ b/src/WSI/VkSurfaceKHR.hpp
@@ -45,6 +45,8 @@
 	uint32_t getPresentModeCount() const;
 	VkResult getPresentModes(uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes) const;
 
+	virtual void present(VkImage image, VkDeviceMemory imageData) = 0;
+
 private:
 	const std::vector<VkSurfaceFormatKHR> surfaceFormats =
 	{
diff --git a/src/WSI/VkSwapchainKHR.cpp b/src/WSI/VkSwapchainKHR.cpp
index c825f72..50487f1 100644
--- a/src/WSI/VkSwapchainKHR.cpp
+++ b/src/WSI/VkSwapchainKHR.cpp
@@ -146,4 +146,39 @@
 	return VK_SUCCESS;
 }
 
+VkResult SwapchainKHR::getNextImage(uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex)
+{
+	for(uint32_t i = 0; i < getImageCount(); i++)
+	{
+		PresentImage& currentImage = images[i];
+		if(currentImage.imageStatus == AVAILABLE)
+		{
+			currentImage.imageStatus = DRAWING;
+			*pImageIndex = i;
+
+			if(semaphore)
+			{
+				vk::Cast(semaphore)->signal();
+			}
+
+			if(fence)
+			{
+				vk::Cast(fence)->signal();
+			}
+
+			return VK_SUCCESS;
+		}
+	}
+
+	return VK_NOT_READY;
+}
+
+void SwapchainKHR::present(uint32_t index)
+{
+	auto & image = images[index];
+	image.imageStatus = PRESENTING;
+	vk::Cast(createInfo.surface)->present(image.image, image.imageMemory);
+	image.imageStatus = AVAILABLE;
+}
+
 }
\ No newline at end of file
diff --git a/src/WSI/VkSwapchainKHR.hpp b/src/WSI/VkSwapchainKHR.hpp
index 5be2584..4c9a926 100644
--- a/src/WSI/VkSwapchainKHR.hpp
+++ b/src/WSI/VkSwapchainKHR.hpp
@@ -54,6 +54,10 @@
 	uint32_t getImageCount() const;
 	VkResult getImages(uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) const;
 
+	VkResult getNextImage(uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex);
+
+	void present(uint32_t index);
+
 private:
 	VkSwapchainCreateInfoKHR createInfo;
 	std::vector<PresentImage> images;
diff --git a/src/WSI/XlibSurfaceKHR.cpp b/src/WSI/XlibSurfaceKHR.cpp
index 9dd7575..18b10ce 100644
--- a/src/WSI/XlibSurfaceKHR.cpp
+++ b/src/WSI/XlibSurfaceKHR.cpp
@@ -11,23 +11,49 @@
 
 #include "XlibSurfaceKHR.hpp"
 
+#include "Vulkan/VkDeviceMemory.hpp"
+
+#include <string.h>
+
 namespace vk {
 
 XlibSurfaceKHR::XlibSurfaceKHR(const VkXlibSurfaceCreateInfoKHR *pCreateInfo, void *mem) :
 		pDisplay(pCreateInfo->dpy),
-		window(pCreateInfo->window) {
+		window(pCreateInfo->window)
+{
+	int screen = DefaultScreen(pDisplay);
+	gc = libX11->XDefaultGC(pDisplay, screen);
+
+	XVisualInfo xVisual;
+	Status status = libX11->XMatchVisualInfo(pDisplay, screen, 32, TrueColor, &xVisual);
+	bool match = (status != 0 && xVisual.blue_mask ==0xFF);
+	Visual *visual = match ? xVisual.visual : libX11->XDefaultVisual(pDisplay, screen);
+
+	XWindowAttributes attr;
+	libX11->XGetWindowAttributes(pDisplay, window, &attr);
+
+	int bytes_per_line = attr.width * 4;
+	int bytes_per_image = attr.height * bytes_per_line;
+
+	xImage = libX11->XCreateImage(pDisplay, visual, attr.depth, ZPixmap, 0, nullptr, attr.width, attr.height, 32, bytes_per_line);
 
 }
 
-void XlibSurfaceKHR::destroySurface(const VkAllocationCallbacks *pAllocator) {
-
+void XlibSurfaceKHR::destroySurface(const VkAllocationCallbacks *pAllocator)
+{
+	if(xImage)
+	{
+		XDestroyImage(xImage);
+	}
 }
 
-size_t XlibSurfaceKHR::ComputeRequiredAllocationSize(const VkXlibSurfaceCreateInfoKHR *pCreateInfo) {
+size_t XlibSurfaceKHR::ComputeRequiredAllocationSize(const VkXlibSurfaceCreateInfoKHR *pCreateInfo)
+{
 	return 0;
 }
 
-void XlibSurfaceKHR::getSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) const {
+void XlibSurfaceKHR::getSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) const
+{
 	SurfaceKHR::getSurfaceCapabilities(pSurfaceCapabilities);
 
 	XWindowAttributes attr;
@@ -39,4 +65,16 @@
 	pSurfaceCapabilities->maxImageExtent = extent;
 }
 
+void XlibSurfaceKHR::present(VkImage image, VkDeviceMemory imageData)
+{
+	xImage->data = static_cast<char*>(vk::Cast(imageData)->getOffsetPointer(0));
+
+	XWindowAttributes attr;
+	libX11->XGetWindowAttributes(pDisplay, window, &attr);
+
+	libX11->XPutImage(pDisplay, window, gc, xImage, 0, 0, 0, 0, attr.width, attr.height);
+
+	xImage->data = nullptr;
+}
+
 }
\ No newline at end of file
diff --git a/src/WSI/XlibSurfaceKHR.hpp b/src/WSI/XlibSurfaceKHR.hpp
index 56540fe..1f49e1e 100644
--- a/src/WSI/XlibSurfaceKHR.hpp
+++ b/src/WSI/XlibSurfaceKHR.hpp
@@ -33,10 +33,13 @@
 
 	void getSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) const override;
 
+	void present(VkImage image, VkDeviceMemory imageData) override;
+
 private:
 	Display *pDisplay;
 	Window window;
-
+	GC gc;
+	XImage *xImage = nullptr;
 };
 
 }