/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/graphite/CommandBuffer.h"

#include "src/core/SkTraceEvent.h"
#include "src/gpu/RefCntedCallback.h"
#include "src/gpu/graphite/Buffer.h"
#include "src/gpu/graphite/ComputePipeline.h"
#include "src/gpu/graphite/GraphicsPipeline.h"
#include "src/gpu/graphite/Log.h"
#include "src/gpu/graphite/Sampler.h"
#include "src/gpu/graphite/Texture.h"
#include "src/gpu/graphite/TextureProxy.h"

namespace skgpu::graphite {

CommandBuffer::CommandBuffer() {}

CommandBuffer::~CommandBuffer() {
    this->releaseResources();
}

void CommandBuffer::releaseResources() {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);

    fTrackedUsageResources.clear();
    fCommandBufferResources.clear();
}

void CommandBuffer::resetCommandBuffer() {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);

    this->releaseResources();
    this->onResetCommandBuffer();
    fBuffersToAsyncMap.clear();
}

void CommandBuffer::trackResource(sk_sp<Resource> resource) {
    fTrackedUsageResources.push_back(std::move(resource));
}

void CommandBuffer::trackCommandBufferResource(sk_sp<Resource> resource) {
    fCommandBufferResources.push_back(std::move(resource));
}

void CommandBuffer::addFinishedProc(sk_sp<RefCntedCallback> finishedProc) {
    fFinishedProcs.push_back(std::move(finishedProc));
}

void CommandBuffer::callFinishedProcs(bool success) {
    if (!success) {
        for (int i = 0; i < fFinishedProcs.size(); ++i) {
            fFinishedProcs[i]->setFailureResult();
        }
    }
    fFinishedProcs.clear();
}

void CommandBuffer::addBuffersToAsyncMapOnSubmit(SkSpan<const sk_sp<Buffer>> buffers) {
    for (size_t i = 0; i < buffers.size(); ++i) {
        SkASSERT(buffers[i]);
        fBuffersToAsyncMap.push_back(buffers[i]);
    }
}

SkSpan<const sk_sp<Buffer>> CommandBuffer::buffersToAsyncMapOnSubmit() const {
    return fBuffersToAsyncMap;
}

bool CommandBuffer::addRenderPass(const RenderPassDesc& renderPassDesc,
                                  sk_sp<Texture> colorTexture,
                                  sk_sp<Texture> resolveTexture,
                                  sk_sp<Texture> depthStencilTexture,
                                  SkRect viewport,
                                  const DrawPassList& drawPasses) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);

    fRenderPassSize = colorTexture->dimensions();
    if (!this->onAddRenderPass(renderPassDesc,
                               colorTexture.get(),
                               resolveTexture.get(),
                               depthStencilTexture.get(),
                               viewport,
                               drawPasses)) {
        return false;
    }

    if (colorTexture) {
        this->trackCommandBufferResource(std::move(colorTexture));
    }
    if (resolveTexture) {
        this->trackCommandBufferResource(std::move(resolveTexture));
    }
    if (depthStencilTexture) {
        this->trackCommandBufferResource(std::move(depthStencilTexture));
    }
    // We just assume if you are adding a render pass that the render pass will actually do work. In
    // theory we could have a discard load that doesn't submit any draws, clears, etc. But hopefully
    // something so trivial would be caught before getting here.
    SkDEBUGCODE(fHasWork = true;)

    return true;
}

bool CommandBuffer::addComputePass(const DispatchGroupList& dispatchGroups) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);

    if (!this->onAddComputePass(dispatchGroups)) {
        return false;
    }

    SkDEBUGCODE(fHasWork = true;)

    return true;
}

bool CommandBuffer::copyBufferToBuffer(const Buffer* srcBuffer,
                                       size_t srcOffset,
                                       sk_sp<Buffer> dstBuffer,
                                       size_t dstOffset,
                                       size_t size) {
    SkASSERT(srcBuffer);
    SkASSERT(dstBuffer);

    if (!this->onCopyBufferToBuffer(srcBuffer, srcOffset, dstBuffer.get(), dstOffset, size)) {
        return false;
    }

    this->trackResource(std::move(dstBuffer));

    SkDEBUGCODE(fHasWork = true;)

    return true;
}

bool CommandBuffer::copyTextureToBuffer(sk_sp<Texture> texture,
                                        SkIRect srcRect,
                                        sk_sp<Buffer> buffer,
                                        size_t bufferOffset,
                                        size_t bufferRowBytes) {
    SkASSERT(texture);
    SkASSERT(buffer);

    if (!this->onCopyTextureToBuffer(texture.get(), srcRect, buffer.get(), bufferOffset,
                                     bufferRowBytes)) {
        return false;
    }

    this->trackCommandBufferResource(std::move(texture));
    this->trackResource(std::move(buffer));

    SkDEBUGCODE(fHasWork = true;)

    return true;
}

bool CommandBuffer::copyBufferToTexture(const Buffer* buffer,
                                        sk_sp<Texture> texture,
                                        const BufferTextureCopyData* copyData,
                                        int count) {
    SkASSERT(buffer);
    SkASSERT(texture);
    SkASSERT(count > 0 && copyData);

    if (!this->onCopyBufferToTexture(buffer, texture.get(), copyData, count)) {
        return false;
    }

    this->trackCommandBufferResource(std::move(texture));

    SkDEBUGCODE(fHasWork = true;)

    return true;
}

bool CommandBuffer::copyTextureToTexture(sk_sp<Texture> src,
                                         SkIRect srcRect,
                                         sk_sp<Texture> dst,
                                         SkIPoint dstPoint,
                                         int mipLevel) {
    SkASSERT(src);
    SkASSERT(dst);
    if (src->textureInfo().isProtected() == Protected::kYes &&
        dst->textureInfo().isProtected() != Protected::kYes) {
        SKGPU_LOG_E("Can't copy from protected memory to non-protected");
        return false;
    }

    if (!this->onCopyTextureToTexture(src.get(), srcRect, dst.get(), dstPoint, mipLevel)) {
        return false;
    }

    this->trackCommandBufferResource(std::move(src));
    this->trackCommandBufferResource(std::move(dst));

    SkDEBUGCODE(fHasWork = true;)

    return true;
}

bool CommandBuffer::synchronizeBufferToCpu(sk_sp<Buffer> buffer) {
    SkASSERT(buffer);

    bool didResultInWork = false;
    if (!this->onSynchronizeBufferToCpu(buffer.get(), &didResultInWork)) {
        return false;
    }

    if (didResultInWork) {
        this->trackResource(std::move(buffer));
        SkDEBUGCODE(fHasWork = true;)
    }

    return true;
}

bool CommandBuffer::clearBuffer(const Buffer* buffer, size_t offset, size_t size) {
    SkASSERT(buffer);

    if (!this->onClearBuffer(buffer, offset, size)) {
        return false;
    }

    SkDEBUGCODE(fHasWork = true;)

    return true;
}

} // namespace skgpu::graphite
