//
// 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.
//

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

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

#include "common/debug.h"
#include "libANGLE/Context.h"
#include "libANGLE/State.h"
#include "libANGLE/renderer/gl/BufferGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/ProgramExecutableGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/renderergl_utils.h"

namespace rx
{

TransformFeedbackGL::TransformFeedbackGL(const gl::TransformFeedbackState &state,
                                         const FunctionsGL *functions,
                                         StateManagerGL *stateManager)
    : TransformFeedbackImpl(state),
      mFunctions(functions),
      mStateManager(stateManager),
      mTransformFeedbackID(0),
      mIsActive(false),
      mIsPaused(false),
      mActiveProgram(0)
{
    mFunctions->genTransformFeedbacks(1, &mTransformFeedbackID);
}

TransformFeedbackGL::~TransformFeedbackGL()
{
    mStateManager->deleteTransformFeedback(mTransformFeedbackID);
    mTransformFeedbackID = 0;
}

angle::Result TransformFeedbackGL::begin(const gl::Context *context,
                                         gl::PrimitiveMode primitiveMode)
{
    const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
    ASSERT(executable);

    const ProgramExecutableGL *executableGL = GetImplAs<ProgramExecutableGL>(executable);
    mActiveProgram                          = executableGL->getProgramID();
    mStateManager->onTransformFeedbackStateChange();
    return angle::Result::Continue;
}

angle::Result TransformFeedbackGL::end(const gl::Context *context)
{
    mStateManager->onTransformFeedbackStateChange();

    // Immediately end the transform feedback so that the results are visible.
    syncActiveState(context, false, gl::PrimitiveMode::InvalidEnum);
    return angle::Result::Continue;
}

angle::Result TransformFeedbackGL::pause(const gl::Context *context)
{
    mStateManager->onTransformFeedbackStateChange();

    syncPausedState(true);
    return angle::Result::Continue;
}

angle::Result TransformFeedbackGL::resume(const gl::Context *context)
{
    mStateManager->onTransformFeedbackStateChange();
    return angle::Result::Continue;
}

angle::Result TransformFeedbackGL::bindIndexedBuffer(
    const gl::Context *context,
    size_t index,
    const gl::OffsetBindingPointer<gl::Buffer> &binding)
{
    const angle::FeaturesGL &features = GetFeaturesGL(context);

    // Directly bind buffer (not through the StateManager methods) because the buffer bindings are
    // tracked per transform feedback object
    mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
    if (binding.get() != nullptr)
    {
        const BufferGL *bufferGL = GetImplAs<BufferGL>(binding.get());

        if (features.bindTransformFeedbackBufferBeforeBindBufferRange.enabled)
        {
            // Generic binding will be overwritten by the bindRange/bindBase below.
            ANGLE_GL_TRY(context, mFunctions->bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER,
                                                         bufferGL->getBufferID()));
        }

        if (binding.getSize() != 0)
        {
            ANGLE_GL_TRY(context,
                         mFunctions->bindBufferRange(
                             GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index),
                             bufferGL->getBufferID(), binding.getOffset(), binding.getSize()));
        }
        else
        {
            ANGLE_GL_TRY(context, mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,
                                                             static_cast<GLuint>(index),
                                                             bufferGL->getBufferID()));
        }
    }
    else
    {
        ANGLE_GL_TRY(context, mFunctions->bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER,
                                                         static_cast<GLuint>(index), 0));
    }
    return angle::Result::Continue;
}

GLuint TransformFeedbackGL::getTransformFeedbackID() const
{
    return mTransformFeedbackID;
}

void TransformFeedbackGL::syncActiveState(const gl::Context *context,
                                          bool active,
                                          gl::PrimitiveMode primitiveMode) const
{
    if (mIsActive != active)
    {
        mIsActive = active;
        mIsPaused = false;

        mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
        if (mIsActive)
        {
            ASSERT(primitiveMode != gl::PrimitiveMode::InvalidEnum);
            mStateManager->useProgram(mActiveProgram);
            mFunctions->beginTransformFeedback(gl::ToGLenum(primitiveMode));
        }
        else
        {
            // Implementations disagree about what should happen if a different program is bound
            // when calling EndTransformFeedback. We avoid the ambiguity by always re-binding the
            // program associated with this transform feedback.
            GLuint previousProgram = mStateManager->getProgramID();
            mStateManager->useProgram(mActiveProgram);
            mFunctions->endTransformFeedback();
            // Restore the current program if we changed it.
            mStateManager->useProgram(previousProgram);
        }
    }
}

void TransformFeedbackGL::syncPausedState(bool paused) const
{
    if (mIsActive && mIsPaused != paused)
    {
        mIsPaused = paused;

        mStateManager->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedbackID);
        if (mIsPaused)
        {
            // If we're transitioning from active to paused, the currently bound program must be the
            // one associated with this transform feedback.
            ASSERT(mStateManager->getProgramID() == mActiveProgram);
            mFunctions->pauseTransformFeedback();
        }
        else
        {
            // When transitioning to resumed, make sure the program associated with this transform
            // feedback is set
            mStateManager->useProgram(mActiveProgram);
            mFunctions->resumeTransformFeedback();
        }
    }
}
}  // namespace rx
