// Copyright 2020 The Dawn Authors
//
// 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 "dawn_native/metal/CommandRecordingContext.h"

#include "common/Assert.h"

namespace dawn_native { namespace metal {

    CommandRecordingContext::CommandRecordingContext() = default;

    CommandRecordingContext::~CommandRecordingContext() {
        // Commands must be acquired.
        ASSERT(mCommands == nullptr);
    }

    id<MTLCommandBuffer> CommandRecordingContext::GetCommands() {
        return mCommands.Get();
    }

    void CommandRecordingContext::MarkUsed() {
        mUsed = true;
    }
    bool CommandRecordingContext::WasUsed() const {
        return mUsed;
    }

    MaybeError CommandRecordingContext::PrepareNextCommandBuffer(id<MTLCommandQueue> queue) {
        ASSERT(mCommands == nil);
        ASSERT(!mUsed);

        // The MTLCommandBuffer will be autoreleased by default.
        // The autorelease pool may drain before the command buffer is submitted. Retain so it stays
        // alive.
        mCommands = AcquireNSPRef([[queue commandBuffer] retain]);
        if (mCommands == nil) {
            return DAWN_INTERNAL_ERROR("Failed to allocate an MTLCommandBuffer");
        }

        return {};
    }

    NSPRef<id<MTLCommandBuffer>> CommandRecordingContext::AcquireCommands() {
        // A blit encoder can be left open from WriteBuffer, make sure we close it.
        if (mCommands != nullptr) {
            EndBlit();
        }

        ASSERT(!mInEncoder);
        mUsed = false;
        return std::move(mCommands);
    }

    id<MTLBlitCommandEncoder> CommandRecordingContext::EnsureBlit() {
        ASSERT(mCommands != nullptr);

        if (mBlit == nullptr) {
            ASSERT(!mInEncoder);
            mInEncoder = true;

            // The encoder is created autoreleased. Retain it to avoid the autoreleasepool from
            // draining from under us.
            mBlit.Acquire([[*mCommands blitCommandEncoder] retain]);
        }
        return mBlit.Get();
    }

    void CommandRecordingContext::EndBlit() {
        ASSERT(mCommands != nullptr);

        if (mBlit != nullptr) {
            [*mBlit endEncoding];
            mBlit = nullptr;
            mInEncoder = false;
        }
    }

    id<MTLComputeCommandEncoder> CommandRecordingContext::BeginCompute() {
        ASSERT(mCommands != nullptr);
        ASSERT(mCompute == nullptr);
        ASSERT(!mInEncoder);

        mInEncoder = true;
        // The encoder is created autoreleased. Retain it to avoid the autoreleasepool from
        // draining from under us.
        mCompute.Acquire([[*mCommands computeCommandEncoder] retain]);
        return mCompute.Get();
    }

    void CommandRecordingContext::EndCompute() {
        ASSERT(mCommands != nullptr);
        ASSERT(mCompute != nullptr);

        [*mCompute endEncoding];
        mCompute = nullptr;
        mInEncoder = false;
    }

    id<MTLRenderCommandEncoder> CommandRecordingContext::BeginRender(
        MTLRenderPassDescriptor* descriptor) {
        ASSERT(mCommands != nullptr);
        ASSERT(mRender == nullptr);
        ASSERT(!mInEncoder);

        mInEncoder = true;
        // The encoder is created autoreleased. Retain it to avoid the autoreleasepool from
        // draining from under us.
        mRender.Acquire([[*mCommands renderCommandEncoderWithDescriptor:descriptor] retain]);
        return mRender.Get();
    }

    void CommandRecordingContext::EndRender() {
        ASSERT(mCommands != nullptr);
        ASSERT(mRender != nullptr);

        [*mRender endEncoding];
        mRender = nullptr;
        mInEncoder = false;
    }

}}  // namespace dawn_native::metal
