//
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// QueryGL.cpp: Implements the class methods for QueryGL.

#include "libANGLE/renderer/gl/QueryGL.h"

#include "common/debug.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/gl/ContextGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/renderergl_utils.h"

namespace
{

GLuint64 MergeQueryResults(gl::QueryType type, GLuint64 currentResult, GLuint64 newResult)
{
    switch (type)
    {
        case gl::QueryType::AnySamples:
        case gl::QueryType::AnySamplesConservative:
            return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE;

        case gl::QueryType::TransformFeedbackPrimitivesWritten:
            return currentResult + newResult;

        case gl::QueryType::TimeElapsed:
            return currentResult + newResult;

        case gl::QueryType::Timestamp:
            return newResult;

        case gl::QueryType::PrimitivesGenerated:
            return currentResult + newResult;

        default:
            UNREACHABLE();
            return 0;
    }
}

// Some drivers tend to hang when flushing pending queries.  Wait until this number of queries have
// added up before checking if results are ready.
constexpr uint32_t kPauseResumeFlushThreshold = 5;
}  // anonymous namespace

namespace rx
{

QueryGL::QueryGL(gl::QueryType type) : QueryImpl(type) {}

QueryGL::~QueryGL() {}

StandardQueryGL::StandardQueryGL(gl::QueryType type,
                                 const FunctionsGL *functions,
                                 StateManagerGL *stateManager)
    : QueryGL(type),
      mFunctions(functions),
      mStateManager(stateManager),
      mActiveQuery(0),
      mPendingQueries(),
      mResultSum(0)
{}

StandardQueryGL::~StandardQueryGL()
{
    clearInternalQueries();
}

void StandardQueryGL::clearInternalQueries()
{
    if (mActiveQuery != 0)
    {
        mStateManager->endQuery(mType, this, mActiveQuery);
        mFunctions->deleteQueries(1, &mActiveQuery);
        mActiveQuery = 0;
    }

    while (!mPendingQueries.empty())
    {
        GLuint id = mPendingQueries.front();
        mFunctions->deleteQueries(1, &id);
        mPendingQueries.pop_front();
    }
}

angle::Result StandardQueryGL::begin(const gl::Context *context)
{
    clearInternalQueries();
    mResultSum = 0;
    return resume(context);
}

angle::Result StandardQueryGL::end(const gl::Context *context)
{
    return pause(context);
}

angle::Result StandardQueryGL::queryCounter(const gl::Context *context)
{
    ASSERT(mType == gl::QueryType::Timestamp);

    // Directly create a query for the timestamp and add it to the pending query queue, as timestamp
    // queries do not have the traditional begin/end block and never need to be paused/resumed
    GLuint query;
    mFunctions->genQueries(1, &query);
    mFunctions->queryCounter(query, GL_TIMESTAMP);
    mPendingQueries.push_back(query);

    return angle::Result::Continue;
}

template <typename T>
angle::Result StandardQueryGL::getResultBase(const gl::Context *context, T *params)
{
    ASSERT(mActiveQuery == 0);

    ANGLE_TRY(flush(context, true));
    ASSERT(mPendingQueries.empty());
    *params = static_cast<T>(mResultSum);

    return angle::Result::Continue;
}

angle::Result StandardQueryGL::getResult(const gl::Context *context, GLint *params)
{
    return getResultBase(context, params);
}

angle::Result StandardQueryGL::getResult(const gl::Context *context, GLuint *params)
{
    return getResultBase(context, params);
}

angle::Result StandardQueryGL::getResult(const gl::Context *context, GLint64 *params)
{
    return getResultBase(context, params);
}

angle::Result StandardQueryGL::getResult(const gl::Context *context, GLuint64 *params)
{
    return getResultBase(context, params);
}

angle::Result StandardQueryGL::isResultAvailable(const gl::Context *context, bool *available)
{
    ASSERT(mActiveQuery == 0);

    ANGLE_TRY(flush(context, false));
    *available = mPendingQueries.empty();
    return angle::Result::Continue;
}

angle::Result StandardQueryGL::pause(const gl::Context *context)
{
    if (mActiveQuery != 0)
    {
        mStateManager->endQuery(mType, this, mActiveQuery);

        mPendingQueries.push_back(mActiveQuery);
        mActiveQuery = 0;
    }

    // Flush to make sure the pending queries don't add up too much.
    if (mPendingQueries.size() >= kPauseResumeFlushThreshold)
    {
        ANGLE_TRY(flush(context, false));
    }

    return angle::Result::Continue;
}

angle::Result StandardQueryGL::resume(const gl::Context *context)
{
    if (mActiveQuery == 0)
    {
        // Flush to make sure the pending queries don't add up too much.
        if (mPendingQueries.size() >= kPauseResumeFlushThreshold)
        {
            ANGLE_TRY(flush(context, false));
        }

        mFunctions->genQueries(1, &mActiveQuery);
        mStateManager->beginQuery(mType, this, mActiveQuery);

        ContextGL *contextGL = GetImplAs<ContextGL>(context);
        contextGL->markWorkSubmitted();
    }

    return angle::Result::Continue;
}

angle::Result StandardQueryGL::flush(const gl::Context *context, bool force)
{
    while (!mPendingQueries.empty())
    {
        GLuint id = mPendingQueries.front();
        if (!force)
        {
            GLuint resultAvailable = 0;
            mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT_AVAILABLE, &resultAvailable);
            if (resultAvailable == GL_FALSE)
            {
                return angle::Result::Continue;
            }
        }

        // Even though getQueryObjectui64v was introduced for timer queries, there is nothing in the
        // standard that says that it doesn't work for any other queries. It also passes on all the
        // trybots, so we use it if it is available
        if (mFunctions->getQueryObjectui64v != nullptr)
        {
            GLuint64 result = 0;
            mFunctions->getQueryObjectui64v(id, GL_QUERY_RESULT, &result);
            mResultSum = MergeQueryResults(mType, mResultSum, result);
        }
        else
        {
            GLuint result = 0;
            mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT, &result);
            mResultSum = MergeQueryResults(mType, mResultSum, static_cast<GLuint64>(result));
        }

        mFunctions->deleteQueries(1, &id);

        mPendingQueries.pop_front();
    }

    return angle::Result::Continue;
}

class SyncProviderGL
{
  public:
    virtual ~SyncProviderGL() {}
    virtual angle::Result init(const gl::Context *context, gl::QueryType queryType)
    {
        return angle::Result::Continue;
    }
    virtual angle::Result flush(const gl::Context *context, bool force, bool *finished) = 0;
};

class SyncProviderGLSync : public SyncProviderGL
{
  public:
    SyncProviderGLSync(const FunctionsGL *functions) : mFunctions(functions), mSync(nullptr) {}

    ~SyncProviderGLSync() override { mFunctions->deleteSync(mSync); }

    angle::Result init(const gl::Context *context, gl::QueryType type) override
    {
        ContextGL *contextGL = GetImplAs<ContextGL>(context);
        mSync                = mFunctions->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
        ANGLE_CHECK(contextGL, mSync != 0, "glFenceSync failed to create a GLsync object.",
                    GL_OUT_OF_MEMORY);
        contextGL->markWorkSubmitted();
        return angle::Result::Continue;
    }

    angle::Result flush(const gl::Context *context, bool force, bool *finished) override
    {
        if (force)
        {
            mFunctions->clientWaitSync(mSync, 0, 0);
            *finished = true;
        }
        else
        {
            GLint value = 0;
            mFunctions->getSynciv(mSync, GL_SYNC_STATUS, 1, nullptr, &value);
            *finished = (value == GL_SIGNALED);
        }

        return angle::Result::Continue;
    }

  private:
    const FunctionsGL *mFunctions;
    GLsync mSync;
};

class SyncProviderGLQuery : public SyncProviderGL
{
  public:
    SyncProviderGLQuery(const FunctionsGL *functions) : mFunctions(functions), mQuery(0) {}

    angle::Result init(const gl::Context *context, gl::QueryType type) override
    {
        StateManagerGL *stateManager = GetStateManagerGL(context);

        mFunctions->genQueries(1, &mQuery);
        ANGLE_TRY(stateManager->pauseQuery(context, type));
        mFunctions->beginQuery(ToGLenum(type), mQuery);
        mFunctions->endQuery(ToGLenum(type));
        return stateManager->resumeQuery(context, type);
    }

    ~SyncProviderGLQuery() override { mFunctions->deleteQueries(1, &mQuery); }

    angle::Result flush(const gl::Context *context, bool force, bool *finished) override
    {
        if (force)
        {
            GLint result = 0;
            mFunctions->getQueryObjectiv(mQuery, GL_QUERY_RESULT, &result);
            *finished = true;
        }
        else
        {
            GLint available = 0;
            mFunctions->getQueryObjectiv(mQuery, GL_QUERY_RESULT_AVAILABLE, &available);
            *finished = (available == GL_TRUE);
        }

        return angle::Result::Continue;
    }

  private:
    const FunctionsGL *mFunctions;
    GLuint mQuery;
};

SyncQueryGL::SyncQueryGL(gl::QueryType type, const FunctionsGL *functions)
    : QueryGL(type), mFunctions(functions), mSyncProvider(nullptr), mFinished(false)
{
    ASSERT(IsSupported(mFunctions));
    ASSERT(type == gl::QueryType::CommandsCompleted);
}

SyncQueryGL::~SyncQueryGL() {}

bool SyncQueryGL::IsSupported(const FunctionsGL *functions)
{
    return nativegl::SupportsFenceSync(functions) || nativegl::SupportsOcclusionQueries(functions);
}

angle::Result SyncQueryGL::begin(const gl::Context *context)
{
    return angle::Result::Continue;
}

angle::Result SyncQueryGL::end(const gl::Context *context)
{
    if (nativegl::SupportsFenceSync(mFunctions))
    {
        mSyncProvider.reset(new SyncProviderGLSync(mFunctions));
    }
    else if (nativegl::SupportsOcclusionQueries(mFunctions))
    {
        mSyncProvider.reset(new SyncProviderGLQuery(mFunctions));
    }
    else
    {
        ANGLE_GL_UNREACHABLE(GetImplAs<ContextGL>(context));
    }
    ANGLE_TRY(mSyncProvider->init(context, gl::QueryType::AnySamples));
    return angle::Result::Continue;
}

angle::Result SyncQueryGL::queryCounter(const gl::Context *context)
{
    UNREACHABLE();
    return angle::Result::Continue;
}

angle::Result SyncQueryGL::getResult(const gl::Context *context, GLint *params)
{
    return getResultBase(context, params);
}

angle::Result SyncQueryGL::getResult(const gl::Context *context, GLuint *params)
{
    return getResultBase(context, params);
}

angle::Result SyncQueryGL::getResult(const gl::Context *context, GLint64 *params)
{
    return getResultBase(context, params);
}

angle::Result SyncQueryGL::getResult(const gl::Context *context, GLuint64 *params)
{
    return getResultBase(context, params);
}

angle::Result SyncQueryGL::isResultAvailable(const gl::Context *context, bool *available)
{
    ANGLE_TRY(flush(context, false));
    *available = mFinished;
    return angle::Result::Continue;
}

angle::Result SyncQueryGL::pause(const gl::Context *context)
{
    return angle::Result::Continue;
}

angle::Result SyncQueryGL::resume(const gl::Context *context)
{
    return angle::Result::Continue;
}

angle::Result SyncQueryGL::flush(const gl::Context *context, bool force)
{
    if (mSyncProvider == nullptr)
    {
        ASSERT(mFinished);
        return angle::Result::Continue;
    }

    ANGLE_TRY(mSyncProvider->flush(context, force, &mFinished));
    if (mFinished)
    {
        mSyncProvider.reset();
    }

    return angle::Result::Continue;
}

template <typename T>
angle::Result SyncQueryGL::getResultBase(const gl::Context *context, T *params)
{
    ANGLE_TRY(flush(context, true));
    *params = static_cast<T>(mFinished ? GL_TRUE : GL_FALSE);
    return angle::Result::Continue;
}
}  // namespace rx
