/*
 * 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 "experimental/graphite/src/CommandBuffer.h"

#include "experimental/graphite/src/GraphicsPipeline.h"
#include "src/core/SkTraceEvent.h"

#include "experimental/graphite/src/Buffer.h"
#include "experimental/graphite/src/Sampler.h"
#include "experimental/graphite/src/Texture.h"
#include "experimental/graphite/src/TextureProxy.h"

namespace skgpu {

CommandBuffer::CommandBuffer() {}

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

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

    fTrackedResources.reset();
}

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

bool CommandBuffer::beginRenderPass(const RenderPassDesc& renderPassDesc,
                                    sk_sp<Texture> colorTexture,
                                    sk_sp<Texture> resolveTexture,
                                    sk_sp<Texture> depthStencilTexture) {
    if (!this->onBeginRenderPass(renderPassDesc, colorTexture.get(), resolveTexture.get(),
                                 depthStencilTexture.get())) {
        return false;
    }

    if (colorTexture) {
        this->trackResource(std::move(colorTexture));
    }
    if (resolveTexture) {
        this->trackResource(std::move(resolveTexture));
    }
    if (depthStencilTexture) {
        this->trackResource(std::move(depthStencilTexture));
    }
#ifdef SK_DEBUG
    if (renderPassDesc.fColorAttachment.fLoadOp == LoadOp::kClear &&
        (renderPassDesc.fColorAttachment.fStoreOp == StoreOp::kStore ||
         renderPassDesc.fColorResolveAttachment.fStoreOp == StoreOp::kStore)) {
        fHasWork = true;
    }
#endif

    return true;
}

void CommandBuffer::bindGraphicsPipeline(sk_sp<GraphicsPipeline> graphicsPipeline) {
    this->onBindGraphicsPipeline(graphicsPipeline.get());
    this->trackResource(std::move(graphicsPipeline));
}

void CommandBuffer::bindUniformBuffer(UniformSlot slot,
                                      sk_sp<Buffer> uniformBuffer,
                                      size_t offset) {
    this->onBindUniformBuffer(slot, uniformBuffer.get(), offset);
    this->trackResource(std::move(uniformBuffer));
}

void CommandBuffer::bindVertexBuffers(sk_sp<Buffer> vertexBuffer, size_t vertexOffset,
                                      sk_sp<Buffer> instanceBuffer, size_t instanceOffset) {
    this->onBindVertexBuffers(vertexBuffer.get(), vertexOffset,
                              instanceBuffer.get(), instanceOffset);
    if (vertexBuffer) {
        this->trackResource(std::move(vertexBuffer));
    }
    if (instanceBuffer) {
        this->trackResource(std::move(instanceBuffer));
    }
}

void CommandBuffer::bindIndexBuffer(sk_sp<Buffer> indexBuffer, size_t bufferOffset) {
    this->onBindIndexBuffer(indexBuffer.get(), bufferOffset);
    if (indexBuffer) {
        this->trackResource(std::move(indexBuffer));
    }
}

void CommandBuffer::bindDrawBuffers(BindBufferInfo vertices,
                                    BindBufferInfo instances,
                                    BindBufferInfo indices) {
    this->bindVertexBuffers(sk_ref_sp(vertices.fBuffer), vertices.fOffset,
                            sk_ref_sp(instances.fBuffer), instances.fOffset);
    this->bindIndexBuffer(sk_ref_sp(indices.fBuffer), indices.fOffset);
}

void CommandBuffer::bindTextures(const TextureBindEntry* entries, int count) {
    this->onBindTextures(entries, count);
    for (int i = 0; i < count; ++i) {
        SkASSERT(entries[i].fTexture);
        this->trackResource(entries[i].fTexture);
    }
}

void CommandBuffer::bindSamplers(const SamplerBindEntry* entries, int count) {
    this->onBindSamplers(entries, count);
    for (int i = 0; i < count; ++i) {
        SkASSERT(entries[i].fSampler);
        this->trackResource(entries[i].fSampler);
    }
}

static bool check_max_blit_width(int widthInPixels) {
    if (widthInPixels > 32767) {
        SkASSERT(false); // surfaces should not be this wide anyway
        return false;
    }
    return true;
}

bool CommandBuffer::copyTextureToBuffer(sk_sp<skgpu::Texture> texture,
                                        SkIRect srcRect,
                                        sk_sp<skgpu::Buffer> buffer,
                                        size_t bufferOffset,
                                        size_t bufferRowBytes) {
    if (!check_max_blit_width(srcRect.width())) {
        return false;
    }

    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;
}

} // namespace skgpu
