// 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 shmQuery = libXCB->xcb_get_extension_data(connection, libXCB->xcb_shm_id);
	if(shmQuery->present)
	{
		auto shmCookie = libXCB->xcb_shm_query_version(connection);
		if(auto *reply = libXCB->xcb_shm_query_version_reply(connection, shmCookie, nullptr))
		{
			mitSHM = reply && reply->shared_pixmaps;
			free(reply);
		}
	}

	auto geomCookie = libXCB->xcb_get_geometry(connection, window);
	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