// 
// Notice Regarding Standards.  AMD does not provide a license or sublicense to
// any Intellectual Property Rights relating to any standards, including but not
// limited to any audio and/or video codec technologies such as MPEG-2, MPEG-4;
// AVC/H.264; HEVC/H.265; AAC decode/FFMPEG; AAC encode/FFMPEG; VC-1; and MP3
// (collectively, the "Media Technologies"). For clarity, you will pay any
// royalties due for such third party technologies, which may include the Media
// Technologies that are owed as a result of AMD providing the Software to you.
// 
// MIT license 
// 
// Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif

#include "../../../include/core/Context.h"
#include "../../../common/InterfaceImpl.h"
#include "../../../common/PropertyStorageImpl.h"
#include "public/include/components/DisplayCapture.h"

#define USE_DUPLICATEOUTPUT1

#include <d3d11_1.h>
#ifdef USE_DUPLICATEOUTPUT1
// Requires Windows SDK 10.0.10586
#include <dxgi1_5.h>
#include <dxgi1_6.h>
#else
#include <dxgi1_2.h>
#endif
#include <atlbase.h>


namespace amf
{
    class AMFDDAPISourceImpl : public
        AMFInterfaceImpl< AMFInterface >,
        public amf::AMFSurfaceObserver
    {
    public:
        AMFDDAPISourceImpl(AMFContext* pContext);
        ~AMFDDAPISourceImpl();

        AMF_RESULT                      InitDisplayCapture(uint32_t displayMonitorIndex, amf_pts frameDuration, bool bEnableDirtyRects);
        AMF_RESULT                      TerminateDisplayCapture();

        AMF_RESULT                      AcquireSurface(bool bCopyOutputSurface, amf::AMFSurface **pSurface);

        AMFSize                         GetResolution();

        AMFRect                         GetDesktopRect();
        AMF_ROTATION_ENUM               GetRotation();
        void                            SetMode(AMF_DISPLAYCAPTURE_MODE_ENUM mode);

        // AMFSurfaceObserver interface
        virtual void        AMF_STD_CALL OnSurfaceDataRelease(AMFSurface* pSurface);

    private:
        // Utility methods
        AMF_RESULT                      GetHDRInformation(AMFSurface* pSurface);
        AMF_RESULT                      GetNewDuplicator();

        // When we are done with a texture, we push it onto a free list
        // We must track the AMF surfaces in case Terminate() is called
        // before the surface is released
        amf_list< AMFSurface* >                 m_freeCopySurfaces;

        AMFContextPtr                           m_pContext;
        AMFComputePtr                           m_pCompute;

        mutable AMFCriticalSection              m_sync;

        ATL::CComPtr<IDXGIOutputDuplication>    m_displayDuplicator;

        ATL::CComQIPtr<ID3D11Device1>           m_deviceAMF;
        ATL::CComPtr<IDXGIAdapter>              m_dxgiAdapter;
        ATL::CComPtr<ID3D11DeviceContext>       m_contextAMF;
        ATL::CComPtr < ID3D11Texture2D >        m_acquiredTextureAMF;

        volatile bool                           m_bAcquired;
        DXGI_OUTPUT_DESC                        m_outputDescription;


        uint32_t                                m_displayMonitorIndex;
        amf_pts                                 m_frameDuration; // in 100 of nanosec
        amf_pts                                 m_lastPts;

        amf_int64                               m_iFrameCount;

#ifdef USE_DUPLICATEOUTPUT1
        ATL::CComPtr<IDXGIOutput5>              m_dxgiOutput5;
#else
        ATL::CComPtr<IDXGIOutput1>              m_dxgiOutput1;
#endif
        amf_vector<RECT>                        m_DirtyRects;
        amf_vector<DXGI_OUTDUPL_MOVE_RECT>      m_MoveRects;

        bool                                    m_bEnableDirtyRects;
        AMF_DISPLAYCAPTURE_MODE_ENUM            m_eCaptureMode;
    };
    typedef AMFInterfacePtr_T<AMFDDAPISourceImpl>    AMFDDAPISourceImplPtr;
} //namespace amf
