// Copyright 2019 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/RenderBundle.h"

#include <utility>

#include "dawn/common/BitSetIterator.h"
#include "dawn/native/Commands.h"
#include "dawn/native/Device.h"
#include "dawn/native/ObjectType_autogen.h"
#include "dawn/native/RenderBundleEncoder.h"

namespace dawn::native {

    RenderBundleBase::RenderBundleBase(RenderBundleEncoder* encoder,
                                       const RenderBundleDescriptor* descriptor,
                                       Ref<AttachmentState> attachmentState,
                                       bool depthReadOnly,
                                       bool stencilReadOnly,
                                       RenderPassResourceUsage resourceUsage,
                                       IndirectDrawMetadata indirectDrawMetadata)
        : ApiObjectBase(encoder->GetDevice(), kLabelNotImplemented),
          mCommands(encoder->AcquireCommands()),
          mIndirectDrawMetadata(std::move(indirectDrawMetadata)),
          mAttachmentState(std::move(attachmentState)),
          mDepthReadOnly(depthReadOnly),
          mStencilReadOnly(stencilReadOnly),
          mResourceUsage(std::move(resourceUsage)) {
        TrackInDevice();
    }

    void RenderBundleBase::DestroyImpl() {
        FreeCommands(&mCommands);

        // Remove reference to the attachment state so that we don't have lingering references to
        // it preventing it from being uncached in the device.
        mAttachmentState = nullptr;
    }

    // static
    RenderBundleBase* RenderBundleBase::MakeError(DeviceBase* device) {
        return new RenderBundleBase(device, ObjectBase::kError);
    }

    RenderBundleBase::RenderBundleBase(DeviceBase* device, ErrorTag errorTag)
        : ApiObjectBase(device, errorTag), mIndirectDrawMetadata(device->GetLimits()) {
    }

    ObjectType RenderBundleBase::GetType() const {
        return ObjectType::RenderBundle;
    }

    CommandIterator* RenderBundleBase::GetCommands() {
        return &mCommands;
    }

    const AttachmentState* RenderBundleBase::GetAttachmentState() const {
        ASSERT(!IsError());
        return mAttachmentState.Get();
    }

    bool RenderBundleBase::IsDepthReadOnly() const {
        ASSERT(!IsError());
        return mDepthReadOnly;
    }

    bool RenderBundleBase::IsStencilReadOnly() const {
        ASSERT(!IsError());
        return mStencilReadOnly;
    }

    const RenderPassResourceUsage& RenderBundleBase::GetResourceUsage() const {
        ASSERT(!IsError());
        return mResourceUsage;
    }

    const IndirectDrawMetadata& RenderBundleBase::GetIndirectDrawMetadata() {
        return mIndirectDrawMetadata;
    }

}  // namespace dawn::native
