// 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.

#include "XcbSurfaceKHR.hpp"

#include "libXCB.hpp"
#include "Vulkan/VkDeviceMemory.hpp"
#include "Vulkan/VkImage.hpp"

#include <sys/ipc.h>
#include <sys/shm.h>

#include <memory>

namespace vk {

bool getWindowSizeAndDepth(xcb_connection_t *connection, xcb_window_t window, VkExtent2D *windowExtent, int *depth)
{
	auto cookie = libXCB->xcb_get_geometry(connection, window);
	if(auto *geom = libXCB->xcb_get_geometry_reply(connection, cookie, nullptr))
	{
		windowExtent->width = static_cast<uint32_t>(geom->width);
		windowExtent->height = static_cast<uint32_t>(geom->height);
		*depth = static_cast<int>(geom->depth);
		free(geom);
		return true;
	}
	return false;
}

bool XcbSurfaceKHR::isSupported()
{
	return libXCB.isPresent();
}

XcbSurfaceKHR::XcbSurfaceKHR(const VkXcbSurfaceCreateInfoKHR *pCreateInfo, void *mem)
	: connection(pCreateInfo->connection)
	, window(pCreateInfo->window)
{
	ASSERT(isSupported());

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

	auto shmCookie = libXCB->xcb_shm_query_version(connection);
	auto geomCookie = libXCB->xcb_get_geometry(connection, window);

	if (auto *reply = libXCB->xcb_shm_query_version_reply(connection, shmCookie, nullptr))
	{
		mitSHM = reply && reply->shared_pixmaps;
		free(reply);
	}

	if (auto *reply = libXCB->xcb_get_geometry_reply(connection, geomCookie, nullptr))
	{
		windowDepth = reply->depth;
		free(reply);
	}
	else
	{
		surfaceLost = true;
	}
}

void XcbSurfaceKHR::destroySurface(const VkAllocationCallbacks *pAllocator)
{
	libXCB->xcb_free_gc(connection, gc);
}

size_t XcbSurfaceKHR::ComputeRequiredAllocationSize(const VkXcbSurfaceCreateInfoKHR *pCreateInfo)
{
	return 0;
}

VkResult XcbSurfaceKHR::getSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) const
{
	if (surfaceLost)
	{
		return VK_ERROR_SURFACE_LOST_KHR;
	}

	setCommonSurfaceCapabilities(pSurfaceCapabilities);

	VkExtent2D extent;
	int depth;
	if(!getWindowSizeAndDepth(connection, window, &extent, &depth))
	{
		surfaceLost = true;
		return VK_ERROR_SURFACE_LOST_KHR;
	}

	pSurfaceCapabilities->currentExtent = extent;
	pSurfaceCapabilities->minImageExtent = extent;
	pSurfaceCapabilities->maxImageExtent = extent;
	return VK_SUCCESS;
}

void* XcbSurfaceKHR::allocateImageMemory(PresentImage *image, const VkMemoryAllocateInfo &allocateInfo)
{
	if (!mitSHM)
		return nullptr;

	SHMPixmap& pixmap = pixmaps[image];
	int shmid = shmget(IPC_PRIVATE, allocateInfo.allocationSize, IPC_CREAT | SHM_R | SHM_W);
	pixmap.shmaddr = shmat(shmid, 0, 0);
	pixmap.shmseg = libXCB->xcb_generate_id(connection);
	libXCB->xcb_shm_attach(connection, pixmap.shmseg, shmid, false);
	shmctl(shmid, IPC_RMID, 0);

	int stride = image->getImage()->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
	int bytesPerPixel = static_cast<int>(image->getImage()->getFormat(VK_IMAGE_ASPECT_COLOR_BIT).bytes());
	int width = stride / bytesPerPixel;
	int height = allocateInfo.allocationSize / stride;

	pixmap.pixmap = libXCB->xcb_generate_id(connection);
	libXCB->xcb_shm_create_pixmap(
		connection,
		pixmap.pixmap,
		window,
		width, height,
		windowDepth,
		pixmap.shmseg,
		0);

	return pixmap.shmaddr;
}

void XcbSurfaceKHR::releaseImageMemory(PresentImage *image)
{
	if (mitSHM)
	{
		auto it = pixmaps.find(image);
		assert(it != pixmaps.end());
		libXCB->xcb_shm_detach(connection, it->second.shmseg);
		shmdt(it->second.shmaddr);
		libXCB->xcb_free_pixmap(connection, it->second.pixmap);
		pixmaps.erase(it);
	}
}

void XcbSurfaceKHR::attachImage(PresentImage *image)
{
}

void XcbSurfaceKHR::detachImage(PresentImage *image)
{
}

VkResult XcbSurfaceKHR::present(PresentImage *image)
{
	VkExtent2D windowExtent;
	int depth;
	// TODO(penghuang): getWindowSizeAndDepth() call needs a sync IPC, try to remove it.
	if(surfaceLost || !getWindowSizeAndDepth(connection, window, &windowExtent, &depth))
	{
		surfaceLost = true;
		return VK_ERROR_SURFACE_LOST_KHR;
	}

	const VkExtent3D &extent = image->getImage()->getExtent();

	if(windowExtent.width != extent.width || windowExtent.height != extent.height)
	{
		return VK_ERROR_OUT_OF_DATE_KHR;
	}

	if (!mitSHM) {
		// TODO: Convert image if not RGB888.
		int stride = image->getImage()->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
		int bytesPerPixel = static_cast<int>(image->getImage()->getFormat(VK_IMAGE_ASPECT_COLOR_BIT).bytes());
		int width = stride / bytesPerPixel;
		auto buffer = reinterpret_cast<uint8_t *>(image->getImageMemory()->getOffsetPointer(0));
		size_t bufferSize = extent.height * stride;
		libXCB->xcb_put_image(
			connection,
			XCB_IMAGE_FORMAT_Z_PIXMAP,
			window,
			gc,
			width,
			extent.height,
			0, 0,  // dst x, y
			0,     // left_pad
			depth,
			bufferSize,  // data_len
			buffer       // data
		);
	}
	else
	{
		auto it = pixmaps.find(image);
		assert(it != pixmaps.end());
		libXCB->xcb_copy_area(
			connection,
			it->second.pixmap,
			window,
			gc,
			0, 0,  // src x, y
			0, 0,  // dst x, y
			extent.width,
			extent.height);
	}
	libXCB->xcb_flush(connection);

	return VK_SUCCESS;
}

}  // namespace vk