// 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 "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::make_unique<LibXcbExports>(RTLD_DEFAULT);
			}

			if(auto lib = loadLibrary("libxcb.so.1"))
			{
				return std::make_unique<LibXcbExports>(lib);
			}

			return std::unique_ptr<LibXcbExports>();
		}();

		return exports.get();
	}
};

LibXcb libXcb;

VkExtent2D getWindowSize(xcb_connection_t *connection, xcb_window_t window)
{
	VkExtent2D windowExtent = { 0, 0 };
	xcb_generic_error_t *error = nullptr;
	auto geom = libXcb->xcb_get_geometry_reply(connection, libXcb->xcb_get_geometry(connection, window), &error);
	if(error)
	{
		free(error);
	}
	else
	{
		windowExtent.width = static_cast<uint32_t>(geom->width);
		windowExtent.height = static_cast<uint32_t>(geom->height);
	}
	free(geom);
	return windowExtent;
}

}  // 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;
}

VkResult XcbSurfaceKHR::getSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) const
{
	setCommonSurfaceCapabilities(pSurfaceCapabilities);

	VkExtent2D extent = getWindowSize(connection, window);

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

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(it);
	}
}

VkResult XcbSurfaceKHR::present(PresentImage *image)
{
	auto it = graphicsContexts.find(image);
	if(it != graphicsContexts.end())
	{
		VkExtent2D windowExtent = getWindowSize(connection, window);
		const VkExtent3D &extent = image->getImage()->getExtent();

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

		// TODO: Convert image if not RGB888.
		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);
	}

	return VK_SUCCESS;
}

}  // namespace vk