/*
 * MVKSwapchain.h
 *
 * Copyright (c) 2014-2019 The Brenwill Workshop Ltd. (http://www.brenwill.com)
 *
 * 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.
 */

#pragma once

#include "MVKDevice.h"
#include "MVKVector.h"

class MVKSwapchainImage;
class MVKWatermark;

@class MVKBlockObserver;


#pragma mark MVKSwapchain

/** Represents a Vulkan swapchain. */
class MVKSwapchain : public MVKVulkanAPIDeviceObject {

public:

	/** Returns the Vulkan type of this object. */
	VkObjectType getVkObjectType() override { return VK_OBJECT_TYPE_SWAPCHAIN_KHR; }

	/** Returns the debug report object type of this object. */
	VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT; }

	/** Returns the number of images in this swapchain. */
	uint32_t getImageCount();

	/** Returns the image at the specified index. */
	MVKSwapchainImage* getImage(uint32_t index);

	/**
	 * Returns the array of presentable images associated with this swapchain.
	 *
	 * If pSwapchainImages is null, the value of pCount is updated with the number of
	 * presentable images associated with this swapchain.
	 *
	 * If pSwapchainImages is not null, then pCount images are copied into the array.
	 * If the number of available images is less than pCount, the value of pCount is
	 * updated to indicate the number of images actually returned in the array.
	 *
	 * Returns VK_SUCCESS if successful. Returns VK_INCOMPLETE if the number of supported
	 * images is larger than pCount. Returns other values if an error occurs.
	 */
	VkResult getImages(uint32_t* pCount, VkImage* pSwapchainImages);

	/** Returns the index of the next swapchain image. */
	VkResult acquireNextImageKHR(uint64_t timeout,
								 VkSemaphore semaphore,
								 VkFence fence,
								 uint32_t deviceMask,
								 uint32_t* pImageIndex);

	/** Returns whether the surface size has changed since the last time this function was called. */
	bool getHasSurfaceSizeChanged();

	/** Returns whether the parent surface is now lost and this swapchain must be recreated. */
	bool getIsSurfaceLost() { return _surfaceLost; }

	/** Returns the specified performance stats structure. */
	const MVKSwapchainPerformance* getPerformanceStatistics() { return &_performanceStatistics; }


#pragma mark Metal

	/** 
	 * Returns the next Metal drawable available to provide backing for 
	 * an image in this swapchain. The returned object is autoreleased.
	 *
	 * This function may block until the next drawable is available, 
	 * and may return nil if no drawable is available at all.
	 */
	id<CAMetalDrawable> getNextCAMetalDrawable();


#pragma mark Construction
	
	MVKSwapchain(MVKDevice* device, const VkSwapchainCreateInfoKHR* pCreateInfo);

	~MVKSwapchain() override;

protected:
	friend class MVKSwapchainImage;

	void propogateDebugName() override;
	void initCAMetalLayer(const VkSwapchainCreateInfoKHR* pCreateInfo, uint32_t imgCnt);
	void initSurfaceImages(const VkSwapchainCreateInfoKHR* pCreateInfo, uint32_t imgCnt);
    void initFrameIntervalTracking();
	void releaseUndisplayedSurfaces();
	uint64_t getNextAcquisitionID();
    void willPresentSurface(id<MTLTexture> mtlTexture, id<MTLCommandBuffer> mtlCmdBuff);
    void renderWatermark(id<MTLTexture> mtlTexture, id<MTLCommandBuffer> mtlCmdBuff);
    void markFrameInterval();

	CAMetalLayer* _mtlLayer;
    MVKWatermark* _licenseWatermark;
	MVKVectorInline<MVKSwapchainImage*, kMVKMaxSwapchainImageCount> _surfaceImages;
	std::atomic<uint64_t> _currentAcquisitionID;
    CGSize _mtlLayerOrigDrawSize;
    MVKSwapchainPerformance _performanceStatistics;
    uint64_t _lastFrameTime;
    double _averageFrameIntervalFilterAlpha;
    uint32_t _currentPerfLogFrameCount;
    std::atomic<bool> _surfaceLost;
    MVKBlockObserver* _layerObserver;
};

