#ifndef SURFACEINTEROP_H
#define SURFACEINTEROP_H

#include <memory>
#include "NVPixelFormatEx.h"
#ifdef SDK_SIMPLE_INCLUDE
#include "../YCKitExport.h"
#include "../common.h"
#else
#include "YCKit/YCKitExport.h"
#include "YCKSdwan/common.h"
#endif

/*!
 * \brief The SurfaceType enum
 * HostMemorySurface:
 * Map the decoded frame to host memory
 * GLTextureSurface:
 * Map the decoded frame as an OpenGL texture
 * SourceSurface:
 * get the original surface from decoder, for example VASurfaceID for va-api, CUdeviceptr for CUDA and IDirect3DSurface9* for DXVA.
 * Zero copy mode is required.
 * UserSurface:
 * Do your own magic mapping with it
 */
enum SurfaceType {
    HostMemorySurface,
    GLTextureSurface,
    SourceSurface,
    UserSurface = 0xffff
};

class DLL_DECL VideoSurfaceInterop
{
public:
	virtual ~VideoSurfaceInterop() {}
	/*!
	 * \brief map
	 * currently is used to map a frame from hardware decoder to opengl texture, host memory.
	 * \param type currently only support GLTextureSurface and HostMemorySurface for some decoders
	 * \param fmt
	 *   HostMemorySurface: must be a packed rgb format
	 * \param handle address of real handle. handle value can be modified in map() and the caller (VideoShader for example) should manage the changes.
	 *   GLTextureSurface: usually opengl texture. maybe other objects for some decoders in the feature
	 *   HostMemorySurface: a VideoFrame ptr
	 * \param plane
	 * \return Null if not supported or failed. handle if success.
	 */
	virtual void* map(SurfaceType type, const NVPixelFormatEx& fmt, void* handle = 0, int plane = 0) {
		UNUSED(type);
		UNUSED(fmt);
		UNUSED(handle);
		UNUSED(plane);
		return 0;
	}
	// TODO: SurfaceType. unmap is currenty used by opengl rendering
	virtual void unmap(void* handle) { UNUSED(handle); }
	//virtual void unmap(void* handle, SurfaceType type) { UNUSED(handle);} //for SourceSurfaceType
	/*!
	 * \brief createHandle
	 * It is used by opengl renderer to create a texture when rendering frame from VDA/VideoToolbox decoder
	 * VideoSurfaceInterop does not have the ownership. VideoShader does
	 * \return NULL if not used for opengl rendering. handle if create here
	 */
	virtual void* createHandle(void* handle, SurfaceType type, const NVPixelFormatEx &fmt, int plane, int planeWidth, int planeHeight) {
		UNUSED(handle);
		UNUSED(type);
		UNUSED(fmt);
		UNUSED(plane);
		UNUSED(planeWidth);
		UNUSED(planeHeight);
		return 0;
	}

    virtual bool CopyTo(uint8_t* data[4], int strides[4]) = 0;
    virtual bool CopyTo(void* textures[4]) = 0;

	//if set, only hardware decode used, cannot share hardware surface.
	virtual void set_hardware_surface_share_failed() { surface_map_failed = true; }
	virtual bool is_hardware_surface_share_failed() const { return surface_map_failed; }
	virtual void set_display_closing_in_uithread(bool closing) {display_closing = closing;}

    virtual bool is_need_release_in_uithread() = 0;

protected:
	bool surface_map_failed = false;
	bool display_closing = false;
};





#endif // SURFACEINTEROP_H
