/*
 * 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 "include/core/SkRect.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkSize.h"
#include "include/core/SkTileMode.h"
#include "include/gpu/graphite/TextureInfo.h"
#include "include/private/base/SkDebug.h"
#include "src/core/SkTraceEvent.h"
#include "src/gpu/RefCntedCallback.h"
#include "src/gpu/graphite/Buffer.h"
#include "src/gpu/graphite/DrawPass.h"
#include "src/gpu/graphite/Log.h"
#include "src/gpu/graphite/RenderPassDesc.h"
#include "src/gpu/graphite/Resource.h"
#include "src/gpu/graphite/ResourceProvider.h"
#include "src/gpu/graphite/ResourceTypes.h"
#include "src/gpu/graphite/Sampler.h"  // IWYU pragma: keep
#include "src/gpu/graphite/Texture.h"

#if defined(SK_DEBUG)
#include "src/gpu/graphite/SharedContext.h"
#endif

#include <algorithm>
#include <atomic>
#include <cstdint>

namespace skgpu::graphite {

CommandBuffer::CommandBuffer(Protected isProtected) : fIsProtected(isProtected) {}

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

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

    fCommandBufferResources.clear();
}

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

    // The dst copy texture and sampler are kept alive by the tracked resources, so reset these
    // before we release their refs. Assuming we don't go idle and free lots of resources, we'll
    // get the same cached sampler the next time we need a dst copy.
    fDstCopy = {nullptr, nullptr};
    this->releaseResources();
    this->onResetCommandBuffer();
    fBuffersToAsyncMap.clear();
}

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

#if defined(SK_DEBUG)
bool CommandBuffer::isResourceTracked(const Resource* resource) {
    for (const gr_cb<Resource>& trackedResource : fCommandBufferResources) {
        if (trackedResource.get() == resource)
            return true;
    }

    // If not tracked on this CommandBuffer then tracked globally?
    const auto* globalCache =
        this->resourceProvider()->sharedContext()->globalCache();
    return globalCache->isResourceTracked(resource);
}
#endif

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();
        }
    } else {
        if (auto stats = this->gpuStats()) {
            for (int i = 0; i < fFinishedProcs.size(); ++i) {
                if (fFinishedProcs[i]->receivesGpuStats()) {
                    fFinishedProcs[i]->setStats(*stats);
                }
            }
        }
    }
    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,
                                  const Texture* dstCopy,
                                  SkIRect dstReadBounds,
                                  SkIPoint resolveOffset,
                                  SkISize viewportDims,
                                  const DrawPassList& drawPasses) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    SkASSERT(!dstCopy || this->isResourceTracked(dstCopy));

    fRenderAreaBounds = SkIRect::MakeEmpty();
    for (const auto& drawPass : drawPasses) {
        fRenderAreaBounds.join(drawPass->bounds());
    }
    if (renderPassDesc.fColorAttachment.fLoadOp == LoadOp::kClear) {
        fRenderAreaBounds.join(fRenderTargetBounds);
    }
    fRenderAreaBounds.offset(fReplayTranslation.x(), fReplayTranslation.y());
    if (!fRenderAreaBounds.intersect(fRenderTargetBounds)) {
        // The entire RenderPass is offscreen given the replay translation so skip adding the pass
        // at all
        return true;
    }

    dstReadBounds.offset(fReplayTranslation);
    if (!dstReadBounds.intersect(fRenderTargetBounds)) {
        // The draws within the RenderPass that would sample from the dstCopy have been translated
        // off screen. Set the bounds to empty and let the GPU clipping do its job.
        dstReadBounds = SkIRect::MakeEmpty();
    }
    // Save the dstCopy texture so that it can be embedded into texture bind commands later on.
    // Stash the texture's full dimensions on the rect so we can calculate normalized coords later.
    fDstCopy.first = dstCopy;
    fDstReadBounds = dstCopy ? SkIRect::MakePtSize(dstReadBounds.topLeft(), dstCopy->dimensions())
                             : SkIRect::MakeEmpty();
    if (dstCopy && !fDstCopy.second) {
        // Only lookup the sampler the first time we require a dstCopy. The texture can change
        // on subsequent passes but it will always use the same nearest neighbor sampling.
        sk_sp<Sampler> nearestNeighbor = this->resourceProvider()->findOrCreateCompatibleSampler(
                {SkFilterMode::kNearest, SkTileMode::kClamp});
        fDstCopy.second = nearestNeighbor.get();
        this->trackResource(std::move(nearestNeighbor));
    }

    // We don't intersect the viewport with the render pass bounds or target size because it just
    // defines a linear transform, which we don't want to change just because a portion of it maps
    // to a region that gets clipped.
    SkIRect viewport = SkIRect::MakePtSize(fReplayTranslation, viewportDims);
    if (!this->onAddRenderPass(renderPassDesc,
                               colorTexture.get(),
                               resolveTexture.get(),
                               depthStencilTexture.get(),
                               resolveOffset,
                               viewport,
                               drawPasses)) {
        return false;
    }

    if (colorTexture) {
        this->trackResource(std::move(colorTexture));
    }
    if (resolveTexture) {
        this->trackResource(std::move(resolveTexture));
    }
    if (depthStencilTexture) {
        this->trackResource(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(DispatchGroupSpan 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(this->isResourceTracked(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->trackResource(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(this->isResourceTracked(buffer));
    SkASSERT(texture);
    SkASSERT(count > 0 && copyData);

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

    this->trackResource(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->trackResource(std::move(src));
    this->trackResource(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);
    SkASSERT(this->isResourceTracked(buffer));

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

    SkDEBUGCODE(fHasWork = true;)

    return true;
}

bool CommandBuffer::setReplayTranslationAndClip(const SkIVector& translation,
                                                const SkIRect& clip,
                                                const SkIRect& renderTargetBounds) {
    fReplayTranslation = translation;
    fRenderTargetBounds = renderTargetBounds;

    // If a replay clip is defined, we intersect it with the render target bounds.
    if (!clip.isEmpty()) {
        if (!fRenderTargetBounds.intersect(clip.makeOffset(translation))) {
            return false;
        }
    }

    return true;
}

} // namespace skgpu::graphite
