// Copyright (C) 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "RenderChannelImpl.h"

#include "RenderThread.h"
#include "aemu/base/synchronization/Lock.h"

#include <algorithm>
#include <utility>

#include <assert.h>
#include <string.h>

#define EMUGL_DEBUG_LEVEL 0
#include "host-common/debug.h"

namespace gfxstream {

using Buffer = RenderChannel::Buffer;
using IoResult = android::base::BufferQueueResult;
using State = RenderChannel::State;
using AutoLock = android::base::AutoLock;

// These constants correspond to the capacities of buffer queues
// used by each RenderChannelImpl instance. Benchmarking shows that
// it's important to have a large queue for guest -> host transfers,
// but a much smaller one works for host -> guest ones.
// Note: 32-bit Windows just doesn't have enough RAM to allocate optimal
// capacity.
#if defined(_WIN32) && !defined(_WIN64)
static constexpr size_t kGuestToHostQueueCapacity = 32U;
#else
static constexpr size_t kGuestToHostQueueCapacity = 1024U;
#endif
static constexpr size_t kHostToGuestQueueCapacity = 16U;

RenderChannelImpl::RenderChannelImpl(android::base::Stream* loadStream, uint32_t contextId)
    : mFromGuest(kGuestToHostQueueCapacity, mLock),
      mToGuest(kHostToGuestQueueCapacity, mLock) {
    if (loadStream) {
        mFromGuest.onLoadLocked(loadStream);
        mToGuest.onLoadLocked(loadStream);
        mState = (State)loadStream->getBe32();
        mWantedEvents = (State)loadStream->getBe32();
#ifndef NDEBUG
        // Make sure we're in a consistent state after loading.
        const auto state = mState;
        updateStateLocked();
        assert(state == mState);
#endif
    } else {
        updateStateLocked();
    }
    mRenderThread.reset(new RenderThread(this, loadStream, contextId));
    mRenderThread->start();
}

void RenderChannelImpl::setEventCallback(EventCallback&& callback) {
    mEventCallback = std::move(callback);
    notifyStateChangeLocked();
}

void RenderChannelImpl::setWantedEvents(State state) {
    D("state=%d", (int)state);
    AutoLock lock(mLock);
    mWantedEvents |= state;
    notifyStateChangeLocked();
}

RenderChannel::State RenderChannelImpl::state() const {
    AutoLock lock(mLock);
    return mState;
}

IoResult RenderChannelImpl::tryWrite(Buffer&& buffer) {
    D("buffer size=%d", (int)buffer.size());
    AutoLock lock(mLock);
    auto result = mFromGuest.tryPushLocked(std::move(buffer));
    updateStateLocked();
    DD("mFromGuest.tryPushLocked() returned %d, state %d", (int)result,
       (int)mState);
    return result;
}

void RenderChannelImpl::waitUntilWritable() {
    AutoLock lock(mLock);
    mFromGuest.waitUntilPushableLocked();
}

IoResult RenderChannelImpl::tryRead(Buffer* buffer) {
    D("enter");
    AutoLock lock(mLock);
    auto result = mToGuest.tryPopLocked(buffer);
    updateStateLocked();
    DD("mToGuest.tryPopLocked() returned %d, buffer size %d, state %d",
       (int)result, (int)buffer->size(), (int)mState);
    return result;
}

IoResult RenderChannelImpl::readBefore(Buffer* buffer, Duration waitUntilUs) {
    D("enter");
    AutoLock lock(mLock);
    auto result = mToGuest.popLockedBefore(buffer, waitUntilUs);
    updateStateLocked();
    DD("mToGuest.popLockedBefore() returned %d, buffer size %d, state %d",
       (int)result, (int)buffer->size(), (int)mState);
    return result;
}

void RenderChannelImpl::waitUntilReadable() {
    AutoLock lock(mLock);
    mToGuest.waitUntilPopableLocked();
}

void RenderChannelImpl::stop() {
    D("enter");
    AutoLock lock(mLock);
    mFromGuest.closeLocked();
    mToGuest.closeLocked();
    mEventCallback = [](State state) {};
}

bool RenderChannelImpl::writeToGuest(Buffer&& buffer) {
    D("buffer size=%d", (int)buffer.size());
    AutoLock lock(mLock);
    IoResult result = mToGuest.pushLocked(std::move(buffer));
    updateStateLocked();
    D("mToGuest.pushLocked() returned %d, state %d", (int)result, (int)mState);
    notifyStateChangeLocked();
    return result == IoResult::Ok;
}

IoResult RenderChannelImpl::readFromGuest(Buffer* buffer, bool blocking) {
    D("enter");
    AutoLock lock(mLock);
    IoResult result;
    if (blocking) {
        result = mFromGuest.popLocked(buffer);
    } else {
        result = mFromGuest.tryPopLocked(buffer);
    }
    updateStateLocked();
    DD("mFromGuest.%s() return %d, buffer size %d, state %d",
       blocking ? "popLocked" : "tryPopLocked", (int)result,
       (int)buffer->size(), (int)mState);
    notifyStateChangeLocked();
    return result;
}

void RenderChannelImpl::stopFromHost() {
    D("enter");

    AutoLock lock(mLock);
    mFromGuest.closeLocked();
    mToGuest.closeLocked();
    mState |= State::Stopped;
    notifyStateChangeLocked();
    mEventCallback = [](State state) {};
}

bool RenderChannelImpl::isStopped() const {
    AutoLock lock(mLock);
    return (mState & State::Stopped) != 0;
}

RenderThread* RenderChannelImpl::renderThread() const {
    return mRenderThread.get();
}

void RenderChannelImpl::pausePreSnapshot() {
    AutoLock lock(mLock);
    mFromGuest.setSnapshotModeLocked(true);
    mToGuest.setSnapshotModeLocked(true);
}

void RenderChannelImpl::resume() {
    AutoLock lock(mLock);
    mFromGuest.setSnapshotModeLocked(false);
    mToGuest.setSnapshotModeLocked(false);
}

RenderChannelImpl::~RenderChannelImpl() {
    // Make sure the render thread is stopped before the channel is gone.
    mRenderThread->wait();
}

void RenderChannelImpl::updateStateLocked() {
    State state = RenderChannel::State::Empty;

    if (mToGuest.canPopLocked()) {
        state |= State::CanRead;
    }
    if (mFromGuest.canPushLocked()) {
        state |= State::CanWrite;
    }
    if (mToGuest.isClosedLocked()) {
        state |= State::Stopped;
    }
    mState = state;
}

void RenderChannelImpl::notifyStateChangeLocked() {
    // Always report stop events, event if not explicitly asked for.
    State available = mState & (mWantedEvents | State::Stopped);
    if (available != 0) {
        D("callback with %d", (int)available);
        mWantedEvents &= ~mState;
        mEventCallback(available);
    }
}

void RenderChannelImpl::onSave(android::base::Stream* stream) {
    D("enter");
    AutoLock lock(mLock);
    mFromGuest.onSaveLocked(stream);
    mToGuest.onSaveLocked(stream);
    stream->putBe32(static_cast<uint32_t>(mState));
    stream->putBe32(static_cast<uint32_t>(mWantedEvents));
    lock.unlock();
    mRenderThread->save(stream);
}

}  // namespace gfxstream
