/*
 * Copyright 2026 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/layout/StorageContext.h"

#include "include/private/SkAlign.h"
#include "include/private/SkAttributes.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/TextureProxy.h"
#include "src/gpu/graphite/TextureProxyView.h"
#include "src/gpu/graphite/buffer/BufferManager.h"
#include "src/gpu/graphite/draw/DrawContext.h"
#include "src/gpu/graphite/task/UploadTask.h"
#include "src/shaders/gradients/SkGradientBaseShader.h"

namespace skgpu::graphite {

namespace {

sk_sp<TextureProxy> create_texture_proxy(Recorder* recorder, int width, int height) {
    const Caps* caps = recorder->priv().caps();
    TextureInfo info = caps->getDefaultReadableTextureInfo(
            StorageContext::kTextureFormat,
            recorder->priv().isProtected());

    sk_sp<TextureProxy> proxy = TextureProxy::Make(caps,
                                                   recorder->priv().resourceProvider(),
                                                   SkISize::Make(width, height),
                                                   info,
                                                   Budgeted::kYes,
                                                   "StorageFallbackTexture");
    return proxy;
}

}  // anonymous namespace

StorageContext::StorageContext(const ResourceBindingRequirements& bindingReqs,
                               bool storageBufferSupport)
        : StorageContext(bindingReqs.fMaxFallbackTextureSize,
                         storageBufferSupport,
                         bindingReqs.fMaxStorageBufferBytes) {}

StorageContext::StorageContext(int maxFallbackTextureSize,
                               bool storageBufferSupport,
                               int maxStorageBufferBytes)
        : fRunningLCM(1)
        , fMaxFallbackTextureSize(maxFallbackTextureSize)
        , fMaxStorageBytes(storageBufferSupport
                                   ? maxStorageBufferBytes
                                   : maxFallbackTextureSize * maxFallbackTextureSize * kTexelBytes)
        , fStorageBufferSupport(storageBufferSupport) {
    SkASSERT(fMaxFallbackTextureSize > 0);
    SkASSERT(fMaxStorageBytes > 0);
}

StorageContext::~StorageContext() {
    this->resetCache();
}

void StorageContext::GradientCache::reset() {
    fLocalGradientOffsetCache.foreach([](const SkGradientBaseShader* shader, int*) {
        shader->unref();
    });
    fLocalGradientOffsetCache.reset();
    fGradientData.clear();
    fGradientDataSize = 0;
}

void StorageContext::resetCache() {
    fGradientCache.reset();
    fVertexData.clear();
    fRunningLCM = 1;
    SkDEBUGCODE(fFinalized = false;)
}

std::pair<float*, int> StorageContext::allocateGradientData(int numStops,
                                                            const SkGradientBaseShader* shader) {
    SkASSERT(!fFinalized);
    if (numStops < 1 || numStops > GradientCache::kMaxGradientStops) {
        return {nullptr, -1};
    }

    int* existingLocalOffset = fGradientCache.fLocalGradientOffsetCache.find(shader);
    if (existingLocalOffset) {
        return {nullptr, *existingLocalOffset};
    }

    int floatOffset = fGradientCache.fGradientData.size();
    const int floatCount = fStorageBufferSupport
            ? (numStops * 5)
            : (SkAlign4(numStops) + numStops * 4);
    SkASSERT(fStorageBufferSupport || SkIsAlign4(floatCount));
    const int maxStorageFloats = fMaxStorageBytes / static_cast<int>(sizeof(float));
    if (floatCount > maxStorageFloats || maxStorageFloats - floatCount < floatOffset) {
        return {nullptr, -1};
    }

    fGradientCache.fGradientData.resize(floatOffset + floatCount);
    float* dstData = SK_UNSAFE_TODO(fGradientCache.fGradientData.data() + floatOffset);
    SK_UNSAFE_TODO(memset(dstData, 0, floatCount * sizeof(float)));

    shader->ref();
    fGradientCache.fLocalGradientOffsetCache.set(shader, floatOffset);
    fGradientCache.fGradientDataSize = fGradientCache.fGradientData.size_bytes();

    return {dstData, floatOffset};
}

void StorageContext::recordAlignment(size_t stride, size_t align) {
    SkASSERT(stride > 0 && align > 0);
    SkASSERT(!fFinalized);
    if (!fStorageBufferSupport) {
        align = std::max<size_t>(align, kTexelBytes);
        stride = SkAlignTo<size_t>(stride, kTexelBytes);
    }
    uint32_t align32 = BufferAligner::LcmAlignment(SkTo<uint32_t>(align), SkTo<uint32_t>(stride));
    fRunningLCM = BufferAligner::LcmAlignment(fRunningLCM, align32);
}

uint32_t StorageContext::appendVertices(const void* data,
                                        size_t count,
                                        size_t stride,
                                        size_t align) {
    SkASSERT(data && count > 0 && stride > 0 && align > 0);

    size_t paddedStride = stride;
    size_t paddedAlign  = align;
    if (!fStorageBufferSupport) {
        paddedStride = SkAlignTo<size_t>(stride, kTexelBytes);
        paddedAlign  = std::max<size_t>(align, static_cast<size_t>(kTexelBytes));
    }

    uint32_t align32 = BufferAligner::LcmAlignment(SkTo<uint32_t>(paddedAlign),
                                                   SkTo<uint32_t>(paddedStride));
    SkASSERT(fRunningLCM % align32 == 0);

    uint32_t requiredBytes =
            BufferAligner::ValidateCountAndStride(count, paddedStride, /*headroom=*/0, align32);
    if (requiredBytes == 0) {
        return 0;
    }

    uint32_t alignedVertOffset = SkAlignNonPow2(static_cast<uint32_t>(fVertexData.size()), align32);
    const size_t maxStorageBytes = static_cast<size_t>(fMaxStorageBytes);
    size_t newVertBytes = static_cast<size_t>(alignedVertOffset) + requiredBytes;
    if (fGradientCache.fGradientDataSize > maxStorageBytes ||
        newVertBytes > maxStorageBytes - fGradientCache.fGradientDataSize) {
        return 0;
    }

    if (alignedVertOffset > static_cast<uint32_t>(fVertexData.size())) {
        int padBytes = alignedVertOffset - fVertexData.size();
        SK_UNSAFE_TODO(memset(fVertexData.append(padBytes), 0, padBytes));
    }

    char* dst = fVertexData.append(requiredBytes);

    // Because the fallback texture format is kRGBA32F (16 bytes per texel), the unpack shader
    // addresses instances by whole texels (index * nTexels). Pad each instance's stride to a
    // 16-byte texel boundary so subsequent instances align with the shader's texel indexing.
    if (stride == paddedStride) {
        SK_UNSAFE_TODO(memcpy(dst, data, requiredBytes));
    } else {
        const char* src = static_cast<const char*>(data);
        size_t diff = paddedStride - stride;
        for (size_t i = 0; i < count; ++i) {
            SK_UNSAFE_TODO(memcpy(dst, src, stride));
            SK_UNSAFE_TODO(memset(dst + stride, 0, diff));
            SK_UNSAFE_TODO(dst += paddedStride);
            SK_UNSAFE_TODO(src += stride);
        }
    }

    return SkTo<uint32_t>(fGradientCache.fGradientDataSize) + alignedVertOffset;
}

void StorageContext::finalizePrecachedStorageData() {
    fGradientCache.fGradientDataSize =
            SkAlignNonPow2<size_t>(fGradientCache.fGradientData.size_bytes(), fRunningLCM);
    SkDEBUGCODE(fFinalized = true;)
}

std::optional<StorageContextResult> StorageContext::finalize(Recorder* recorder,
                                                             DrawContext* drawContext) {
    SkASSERT(recorder);
    SkASSERT(fFinalized);
    SkDEBUGCODE(fFinalized = false;)

    std::optional<StorageContextResult> result;
    if (!this->isEmpty()) {
        if (fStorageBufferSupport) {
            if (BindBufferInfo info = this->finalizeStorageBuffer(recorder)) {
                result = info;
            }
        } else {
            if (sk_sp<TextureProxy> proxy = this->finalizeTexture(recorder, drawContext)) {
                result = std::move(proxy);
            }
        }
    }

    // Vertex data and LCM alignment are per-DrawPass, whereas the gradient cache persists across
    // internal DrawPass flushes until Recorder::snap() calls resetCache().
    fVertexData.clear();
    fRunningLCM = 1;
    fGradientCache.fGradientDataSize = fGradientCache.fGradientData.size_bytes();

    return result;
}

BindBufferInfo StorageContext::finalizeStorageBuffer(Recorder* recorder) {
    DrawBufferManager* bufferMgr = recorder->priv().drawBufferManager();
    SkASSERT(bufferMgr);

    size_t totalBytes = fGradientCache.fGradientDataSize + fVertexData.size_bytes();
    if (totalBytes == 0 || totalBytes > static_cast<size_t>(fMaxStorageBytes)) {
        return {};
    }

    BindBufferInfo result;
    auto [writer, bufferInfo, _] = bufferMgr->getMappedStorageBuffer(totalBytes, /*stride=*/1);
    if (writer) {
        if (!fGradientCache.isEmpty()) {
            writer.write(fGradientCache.fGradientData.data(),
                         fGradientCache.fGradientData.size_bytes());
            if (fGradientCache.fGradientDataSize > fGradientCache.fGradientData.size_bytes()) {
                writer.zeroBytes(fGradientCache.fGradientDataSize -
                                 fGradientCache.fGradientData.size_bytes());
            }
        }
        if (!fVertexData.empty()) {
            writer.write(fVertexData.data(), fVertexData.size_bytes());
        }

        result = bufferInfo;
    }

    return result;
}

// TODO (thomsmit): Currently UploadSource holds its own copy of the data. Create an alternative
// path for uploading which allows writing to the mapped gpu buffer directly.
sk_sp<TextureProxy> StorageContext::finalizeTexture(Recorder* recorder, DrawContext* drawContext) {
    SkASSERT(drawContext);
    size_t gradSize = fGradientCache.fGradientDataSize;
    size_t vertSize = fVertexData.size_bytes();
    size_t totalBytes = gradSize + vertSize;
    if (totalBytes == 0 || totalBytes > static_cast<size_t>(fMaxStorageBytes)) {
        return nullptr;
    }

    int totalTexels = (totalBytes + kTexelBytes - 1) / kTexelBytes;
    int width = std::min(totalTexels, fMaxFallbackTextureSize);
    int height = (totalTexels + fMaxFallbackTextureSize - 1) / fMaxFallbackTextureSize;
    if (height > fMaxFallbackTextureSize) {
        return nullptr;
    }

    int atlasRowBytes = width * kTexelBytes;
    size_t paddedBytes = static_cast<size_t>(height) * atlasRowBytes;
    SkTDArray<char> uploadBuffer;
    uploadBuffer.resize(paddedBytes);
    SK_UNSAFE_TODO(memset(uploadBuffer.data(), 0, paddedBytes));

    if (gradSize > 0) {
        SK_UNSAFE_TODO(memcpy(uploadBuffer.data(),
                              fGradientCache.fGradientData.data(),
                              fGradientCache.fGradientData.size_bytes()));
    }

    if (!fVertexData.empty()) {
        SK_UNSAFE_TODO(memcpy(
                uploadBuffer.data() + gradSize, fVertexData.data(), fVertexData.size_bytes()));
    }

    sk_sp<TextureProxy> proxy = create_texture_proxy(recorder, width, height);
    if (!proxy) {
        return nullptr;
    }

    MipLevel level;
    level.fPixels = uploadBuffer.data();
    level.fRowBytes = atlasRowBytes;
    SkIRect dstRect = SkIRect::MakeWH(width, height);

    Swizzle readSwizzle = ReadSwizzleForColorType(StorageContext::kColorType, proxy->format());
    TextureProxyView proxyView(std::move(proxy), readSwizzle);

    SkColorInfo colorInfo(StorageContext::kColorType, kPremul_SkAlphaType, nullptr);
    UploadSource source = UploadSource::Make(recorder->priv().caps(),
                                             proxyView,
                                             colorInfo,
                                             colorInfo,
                                             SkSpan<const MipLevel>(&level, 1),
                                             dstRect);

    UploadInstance uploadInstance = UploadInstance::Make(recorder, source, nullptr);
    if (!uploadInstance.isValid()) {
        return nullptr;
    }

    sk_sp<Task> uploadTask = UploadTask::Make(std::move(uploadInstance));
    if (!uploadTask) {
        return nullptr;
    }
    drawContext->recordDependency(std::move(uploadTask));

    return proxyView.refProxy();
}

}  // namespace skgpu::graphite
