/*
* Copyright (C) 2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "CVDisplayLink.h"

#include "CVDisplayLinkClient.h"
#include <QuartzCore/CABase.h>
#include <wtf/RefPtr.h>

namespace WKQCA {

inline CVDisplayLink::CVDisplayLink(CVDisplayLinkClient* client)
    : m_client(client)
    , m_wakeupEvent(::CreateEventW(0, FALSE, FALSE, 0))
{
    ASSERT_ARG(client, client);
}

CVDisplayLink::~CVDisplayLink()
{
    stop();
    ::CloseHandle(m_wakeupEvent);
}

RefPtr<CVDisplayLink> CVDisplayLink::create(CVDisplayLinkClient* client)
{
    return adoptRef(new CVDisplayLink(client));
}

void CVDisplayLink::start()
{
    if (m_isRunning) {
        ASSERT(m_ioThread);
        return;
    }

    ASSERT(!m_ioThread);

    m_isRunning = true;

    ref(); // Adopted in runIOThread.
    m_ioThread = Thread::create("WKQCA: CVDisplayLink", [this] {
        runIOThread();
    });
}

void CVDisplayLink::stop()
{
    if (!m_isRunning) {
        ASSERT(!m_ioThread);
        return;
    }

    ASSERT(m_ioThread);

    m_isRunning = false;

    // Unpause the thread so it will exit.
    setPaused(false);

    DWORD result = m_ioThread->waitForCompletion();
    m_ioThread = nullptr;

    switch (result) {
    case WAIT_OBJECT_0:
        // The thread's HANDLE was signaled, so the thread has exited.
        break;
    case WAIT_FAILED:
        LOG_ERROR("waitForCompletion failed with error code %u", ::GetLastError());
        break;
    default:
        ASSERT_WITH_MESSAGE(false, "waitForCompletion returned unexpected result %u", result);
        break;
    }
}

void CVDisplayLink::setPaused(bool paused)
{
    if (m_isPaused == paused)
        return;

    m_isPaused = paused;

    if (m_isPaused)
        return;

    // Since we were paused until right now, the IO thread, if it has been started, is currently
    // waiting forever inside ::WaitForSingleObject. We need to wake it up so it can continue
    // running. If it hasn't been started, signaling this event is harmless.
    ::SetEvent(m_wakeupEvent);
}

void CVDisplayLink::runIOThread()
{
    RefPtr<CVDisplayLink> link = adoptRef(this);
    ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST);

    while (m_isRunning) {
        // When we're not paused, we want to wait for as short a time as possible. MSDN says that
        // passing a timeout of 0 causes ::WaitForSingleObject to return immediately without
        // entering the wait state at all, which wouldn't give other threads a chance to acquire any
        // mutexes our client acquires beneath displayLinkReachedCAMediaTime. So we pass a timeout
        // of 1 instead. (Passing a timeout of 0 does seem to cause this function to enter the wait
        // state at least sometimes on Windows XP, despite what MSDN says, but not on Windows 7.)
        DWORD result = ::WaitForSingleObject(m_wakeupEvent, m_isPaused ? INFINITE : 1);
        switch (result) {
        case WAIT_TIMEOUT:
            // It must be time to render.
            m_client->displayLinkReachedCAMediaTime(this, CACurrentMediaTime());
            break;
        case WAIT_OBJECT_0:
            // Someone wanted to wake us up.
            break;
        case WAIT_FAILED:
            LOG_ERROR("::WaitForSingleObject failed with error code %u", ::GetLastError());
            break;
        default:
            ASSERT_WITH_MESSAGE(false, "::WaitForSingleObject returned unexpected result %u", result);
            break;
        }
    }
}

} // namespace WKQCA
