Fix resizing issues

In summary, this change associates a 1:1
correspondance between a VkImage and XImage.
This will fix resize issues as well as prepare
to implement createInfo->oldSwapchain.

Bug: b/124265819
Change-Id: I42e8e1e7b5c9a5b64820156603dca10e2ab828ca
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/26368
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Hernan Liatis <hliatis@google.com>
diff --git a/src/WSI/VkSurfaceKHR.hpp b/src/WSI/VkSurfaceKHR.hpp
index 0d2c2e2..f17cbbd 100644
--- a/src/WSI/VkSurfaceKHR.hpp
+++ b/src/WSI/VkSurfaceKHR.hpp
@@ -22,6 +22,21 @@
 namespace vk
 {
 
+enum PresentImageStatus
+{
+	NONEXISTENT, //  Image wasn't made
+	AVAILABLE,
+	DRAWING,
+	PRESENTING,
+};
+
+struct PresentImage
+{
+	VkImage image;
+	VkDeviceMemory imageMemory;
+	PresentImageStatus imageStatus;
+};
+
 class SurfaceKHR
 {
 public:
@@ -45,7 +60,9 @@
 	uint32_t getPresentModeCount() const;
 	VkResult getPresentModes(uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes) const;
 
-	virtual void present(VkImage image, VkDeviceMemory imageData) = 0;
+	virtual void attachImage(PresentImage* image) = 0;
+	virtual void detachImage(PresentImage* image) = 0;
+	virtual void present(PresentImage* image) = 0;
 
 private:
 	const std::vector<VkSurfaceFormatKHR> surfaceFormats =
diff --git a/src/WSI/VkSwapchainKHR.cpp b/src/WSI/VkSwapchainKHR.cpp
index 50487f1..bd1672e 100644
--- a/src/WSI/VkSwapchainKHR.cpp
+++ b/src/WSI/VkSwapchainKHR.cpp
@@ -36,6 +36,7 @@
 	{
 		if (currentImage.imageStatus != NONEXISTENT)
 		{
+			vk::Cast(createInfo.surface)->detachImage(&currentImage);
 			vk::destroy(currentImage.imageMemory, pAllocator);
 			vk::destroy(currentImage.image, pAllocator);
 
@@ -116,6 +117,8 @@
 		vkBindImageMemory(device, currentImage.image, currentImage.imageMemory, 0);
 
 		currentImage.imageStatus = AVAILABLE;
+
+		vk::Cast(createInfo.surface)->attachImage(&currentImage);
 	}
 
 	return VK_SUCCESS;
@@ -177,7 +180,7 @@
 {
 	auto & image = images[index];
 	image.imageStatus = PRESENTING;
-	vk::Cast(createInfo.surface)->present(image.image, image.imageMemory);
+	vk::Cast(createInfo.surface)->present(&image);
 	image.imageStatus = AVAILABLE;
 }
 
diff --git a/src/WSI/VkSwapchainKHR.hpp b/src/WSI/VkSwapchainKHR.hpp
index 4c9a926..7cd06d6 100644
--- a/src/WSI/VkSwapchainKHR.hpp
+++ b/src/WSI/VkSwapchainKHR.hpp
@@ -18,27 +18,13 @@
 
 #include "Vulkan/VkObject.hpp"
 #include "Vulkan/VkImage.hpp"
+#include "VkSurfaceKHR.hpp"
 
 #include <vector>
 
 namespace vk
 {
 
-enum PresentImageStatus
-{
-	NONEXISTENT, //  Image wasn't made
-	AVAILABLE,
-	DRAWING,
-	PRESENTING,
-};
-
-struct PresentImage
-{
-	VkImage image;
-	VkDeviceMemory imageMemory;
-	PresentImageStatus imageStatus;
-};
-
 class SwapchainKHR : public Object<SwapchainKHR, VkSwapchainKHR>
 {
 public:
diff --git a/src/WSI/XlibSurfaceKHR.cpp b/src/WSI/XlibSurfaceKHR.cpp
index 18b10ce..3bf3022 100644
--- a/src/WSI/XlibSurfaceKHR.cpp
+++ b/src/WSI/XlibSurfaceKHR.cpp
@@ -27,24 +27,12 @@
 	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);
-
+	visual = match ? xVisual.visual : libX11->XDefaultVisual(pDisplay, screen);
 }
 
 void XlibSurfaceKHR::destroySurface(const VkAllocationCallbacks *pAllocator)
 {
-	if(xImage)
-	{
-		XDestroyImage(xImage);
-	}
+
 }
 
 size_t XlibSurfaceKHR::ComputeRequiredAllocationSize(const VkXlibSurfaceCreateInfoKHR *pCreateInfo)
@@ -65,16 +53,46 @@
 	pSurfaceCapabilities->maxImageExtent = extent;
 }
 
-void XlibSurfaceKHR::present(VkImage image, VkDeviceMemory imageData)
+void XlibSurfaceKHR::attachImage(PresentImage* image)
 {
-	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);
+	VkExtent3D extent = vk::Cast(image->image)->getMipLevelExtent(0);
 
-	xImage->data = nullptr;
+	int bytes_per_line = vk::Cast(image->image)->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
+	char* buffer = static_cast<char*>(vk::Cast(image->imageMemory)->getOffsetPointer(0));
+
+	XImage* xImage = libX11->XCreateImage(pDisplay, visual, attr.depth, ZPixmap, 0, buffer, extent.width, extent.height, 32, bytes_per_line);
+
+	imageMap[image] = xImage;
+}
+
+void XlibSurfaceKHR::detachImage(PresentImage* image)
+{
+	auto it = imageMap.find(image);
+	if(it != imageMap.end())
+	{
+		XImage* xImage = it->second;
+		xImage->data = nullptr; // the XImage does not actually own the buffer
+		XDestroyImage(xImage);
+		imageMap.erase(image);
+	}
+}
+
+void XlibSurfaceKHR::present(PresentImage* image)
+{
+	auto it = imageMap.find(image);
+	if(it != imageMap.end())
+	{
+		XImage* xImage = it->second;
+
+		if(xImage->data)
+		{
+			VkExtent3D extent = vk::Cast(image->image)->getMipLevelExtent(0);
+			libX11->XPutImage(pDisplay, window, gc, xImage, 0, 0, 0, 0, extent.width, extent.height);
+		}
+	}
 }
 
 }
\ No newline at end of file
diff --git a/src/WSI/XlibSurfaceKHR.hpp b/src/WSI/XlibSurfaceKHR.hpp
index 1f49e1e..bafd973 100644
--- a/src/WSI/XlibSurfaceKHR.hpp
+++ b/src/WSI/XlibSurfaceKHR.hpp
@@ -16,9 +16,12 @@
 #define SWIFTSHADER_XLIBSURFACEKHR_HPP
 
 #include "Vulkan/VkObject.hpp"
+#include "Vulkan/VkImage.hpp"
 #include "libX11.hpp"
 #include "VkSurfaceKHR.hpp"
 
+#include <map>
+
 namespace vk {
 
 class XlibSurfaceKHR : public SurfaceKHR, public ObjectBase<XlibSurfaceKHR, VkSurfaceKHR> {
@@ -33,13 +36,16 @@
 
 	void getSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) const override;
 
-	void present(VkImage image, VkDeviceMemory imageData) override;
+	virtual void attachImage(PresentImage* image) override;
+	virtual void detachImage(PresentImage* image) override;
+	void present(PresentImage* image) override;
 
 private:
 	Display *pDisplay;
 	Window window;
 	GC gc;
-	XImage *xImage = nullptr;
+	Visual *visual = nullptr;
+	std::map<PresentImage*, XImage*> imageMap;
 };
 
 }