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

#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrGpu.h"
#include "src/gpu/ganesh/GrGpuBuffer.h"

GrGpuBuffer::GrGpuBuffer(GrGpu* gpu, size_t sizeInBytes, GrGpuBufferType type,
                         GrAccessPattern pattern,
                         std::string_view label)
        : GrGpuResource(gpu, label)
        , fMapPtr(nullptr)
        , fSizeInBytes(sizeInBytes)
        , fAccessPattern(pattern)
        , fIntendedType(type) {}

void* GrGpuBuffer::map() {
    if (this->wasDestroyed()) {
        return nullptr;
    }
    if (!fMapPtr) {
        this->onMap(this->mapType());
    }
    return fMapPtr;
}

void GrGpuBuffer::unmap() {
    if (this->wasDestroyed()) {
        return;
    }
    SkASSERT(fMapPtr);
    this->onUnmap(this->mapType());
    fMapPtr = nullptr;
}

bool GrGpuBuffer::isMapped() const { return SkToBool(fMapPtr); }

bool GrGpuBuffer::clearToZero() {
    SkASSERT(!this->isMapped());

    if (this->wasDestroyed()) {
        return false;
    }

    if (this->intendedType()  == GrGpuBufferType::kXferGpuToCpu) {
        return false;
    }

    return this->onClearToZero();
}

bool GrGpuBuffer::updateData(const void* src, size_t offset, size_t size, bool preserve) {
    SkASSERT(!this->isMapped());
    SkASSERT(size > 0 && offset + size <= fSizeInBytes);
    SkASSERT(src);

    if (this->wasDestroyed()) {
        return false;
    }

    if (preserve) {
        size_t a = this->getGpu()->caps()->bufferUpdateDataPreserveAlignment();
        if (SkAlignTo(offset, a) != offset || SkAlignTo(size, a) != size) {
            return false;
        }
    }

    if (this->intendedType() == GrGpuBufferType::kXferGpuToCpu) {
        return false;
    }

    return this->onUpdateData(src, offset, size, preserve);
}

void GrGpuBuffer::ComputeScratchKeyForDynamicBuffer(size_t size,
                                                    GrGpuBufferType intendedType,
                                                    skgpu::ScratchKey* key) {
    static const skgpu::ScratchKey::ResourceType kType = skgpu::ScratchKey::GenerateResourceType();
    skgpu::ScratchKey::Builder builder(key, kType, 1 + (sizeof(size_t) + 3) / 4);
    builder[0] = SkToU32(intendedType);
    builder[1] = (uint32_t)size;
    if (sizeof(size_t) > 4) {
        builder[2] = (uint32_t)((uint64_t)size >> 32);
    }
}

void GrGpuBuffer::computeScratchKey(skgpu::ScratchKey* key) const {
    if (SkIsPow2(fSizeInBytes) && kDynamic_GrAccessPattern == fAccessPattern) {
        ComputeScratchKeyForDynamicBuffer(fSizeInBytes, fIntendedType, key);
    }
}
