// Copyright 2026 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "src/dawn/native/BufferTextureCopyOversizedRow.h"

#include <cstdint>

#include "src/dawn/common/Constants.h"
#include "src/dawn/common/Math.h"
#include "src/dawn/native/Buffer.h"
#include "src/dawn/native/CommandAllocator.h"
#include "src/dawn/native/Texture.h"

namespace dawn::native {

namespace {

// Intel GPUs store a buffer<->texture copy's bytes per row and texels per row in two separate
// hardware register fields: bytes per row is 18 bits and texels per row is 14 bits. The two must
// be checked independently: bytesPerRow == texelsPerRow * bytesPerBlock, so a format with a small
// bytesPerBlock (e.g. R8Unorm, 1 byte/texel) can push texelsPerRow past 2^14 while bytesPerRow is
// still nowhere near 2^18. See crbug.com/481934465.
// These thresholds also cover the larger row pitch overflow / wrap-around limits on ARM Mali
// (2^28 bytes, crbug.com/569161611), ImgTec PowerVR (2^28 bytes, crbug.com/529867799),
// Qualcomm Adreno (2^28 bytes, crbug.com/380487895), and NVIDIA (2^31 bytes, crbug.com/583083283).
constexpr uint64_t kMaxBytesPerRow = 1u << 18;
constexpr uint64_t kMaxTexelsPerRow = 1u << 14;

// Multi-slice copies also step across images by `bytesPerImage = bytesPerRow * rowsPerImage`.
// ARM Mali GLES wraps signed 32-bit bit strides at 2^28 bytes (256 MiB), and drivers that compute
// byte strides in signed 32-bit integers (e.g. NVIDIA Vulkan, crbug.com/583083283) wrap at 2 GiB.
constexpr uint64_t kMaxBytesPerImage = 1ull << 28;

// Splits {bufferCopy, textureCopy, copySize} into one sub-copy per unpadded row, in row-major
// order, invoking `func(bufferOffset, origin)` for each one. `bufferOffset` is the real
// (unclamped) offset of the row in the buffer; `origin` is the texture origin of this row (the
// rest of the TextureCopy is unchanged from the original, unsplit copy).
template <typename Func>
void SplitBufferTextureCopyByRow(const BufferCopy& bufferCopy,
                                 const TextureCopy& textureCopy,
                                 const BlockExtent3D& copySize,
                                 const TypedTexelBlockInfo& blockInfo,
                                 Func&& func) {
    DAWN_CHECK(!copySize.IsEmpty());
    const BlockOrigin3D origin = blockInfo.ToBlock(textureCopy.origin);
    const uint64_t bytesPerRow = blockInfo.ToBytes(bufferCopy.blocksPerRow);

    for (BlockCount z{0u}; z < copySize.depthOrArrayLayers; z += BlockCount{1u}) {
        // Buffer offset of the first row of this layer.
        const uint64_t layerOffset =
            bufferCopy.offset +
            blockInfo.ToBytes(z * bufferCopy.rowsPerImage * bufferCopy.blocksPerRow);
        for (BlockCount y{0u}; y < copySize.height; y += BlockCount{1u}) {
            // Advance from the layer's first row by y rows of (possibly padded) bytes per row.
            func(layerOffset + static_cast<uint64_t>(y) * bytesPerRow,
                 blockInfo.ToTexel(BlockOrigin3D{origin.x, origin.y + y, origin.z + z}));
        }
    }
}

}  // namespace

bool NeedsBufferTextureCopySplitForOversizedRow(const BufferCopy& bufferCopy,
                                                const BlockExtent3D& copySize,
                                                const TypedTexelBlockInfo& blockInfo) {
    const bool exceedsMaxBytesPerRow =
        blockInfo.ToBytes(bufferCopy.blocksPerRow) >= kMaxBytesPerRow;
    const bool exceedsMaxTexelsPerRow =
        static_cast<uint64_t>(blockInfo.ToTexelWidth(bufferCopy.blocksPerRow)) >= kMaxTexelsPerRow;
    const bool exceedsMaxBytesPerImage =
        copySize.depthOrArrayLayers > BlockCount{1u} &&
        blockInfo.ToBytes(bufferCopy.blocksPerRow * bufferCopy.rowsPerImage) >= kMaxBytesPerImage;
    return exceedsMaxBytesPerRow || exceedsMaxTexelsPerRow || exceedsMaxBytesPerImage;
}

void SplitCopyTextureToBufferForOversizedRow(CommandAllocator* allocator,
                                             const BufferCopy& bufferCopy,
                                             const TextureCopy& textureCopy,
                                             const BlockExtent3D& copySize,
                                             const TypedTexelBlockInfo& blockInfo) {
    const BlockCount blocksPerRow = blockInfo.BytesToBlocks(
        Align(blockInfo.ToBytes(copySize.width), uint64_t{kTextureBytesPerRowAlignment}));
    SplitBufferTextureCopyByRow(
        bufferCopy, textureCopy, copySize, blockInfo,
        [&](uint64_t bufferOffset, const TexelOrigin3D& origin) {
            CopyTextureToBufferCmd* cmd =
                allocator->Allocate<CopyTextureToBufferCmd>(Command::CopyTextureToBuffer);
            cmd->source = textureCopy;
            cmd->source.origin = origin;
            cmd->destination.buffer = bufferCopy.buffer;
            cmd->destination.offset = bufferOffset;
            cmd->destination.blocksPerRow = blocksPerRow;
            cmd->destination.rowsPerImage = BlockCount{1u};
            cmd->copySize =
                blockInfo.ToTexel(BlockExtent3D{copySize.width, BlockCount{1u}, BlockCount{1u}});
        });
}

void SplitCopyBufferToTextureForOversizedRow(CommandAllocator* allocator,
                                             const BufferCopy& bufferCopy,
                                             const TextureCopy& textureCopy,
                                             const BlockExtent3D& copySize,
                                             const TypedTexelBlockInfo& blockInfo) {
    const BlockCount blocksPerRow = blockInfo.BytesToBlocks(
        Align(blockInfo.ToBytes(copySize.width), uint64_t{kTextureBytesPerRowAlignment}));
    SplitBufferTextureCopyByRow(
        bufferCopy, textureCopy, copySize, blockInfo,
        [&](uint64_t bufferOffset, const TexelOrigin3D& origin) {
            CopyBufferToTextureCmd* cmd =
                allocator->Allocate<CopyBufferToTextureCmd>(Command::CopyBufferToTexture);
            cmd->source.buffer = bufferCopy.buffer;
            cmd->source.offset = bufferOffset;
            cmd->source.blocksPerRow = blocksPerRow;
            cmd->source.rowsPerImage = BlockCount{1u};
            cmd->destination = textureCopy;
            cmd->destination.origin = origin;
            cmd->copySize =
                blockInfo.ToTexel(BlockExtent3D{copySize.width, BlockCount{1u}, BlockCount{1u}});
        });
}

}  // namespace dawn::native
