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

// This is a GPU-backend specific test. It relies on static initializers to work

#include "include/core/SkAlphaType.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/core/SkTypes.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/ganesh/GrBackendSurface.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/GrTypes.h"
#include "include/private/base/SkAlign.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrColor.h"
#include "src/gpu/ganesh/GrDataUtils.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrGpu.h"
#include "src/gpu/ganesh/GrGpuBuffer.h"
#include "src/gpu/ganesh/GrImageInfo.h"
#include "src/gpu/ganesh/GrPixmap.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include "src/gpu/ganesh/GrTexture.h"
#include "src/gpu/ganesh/GrUtil.h"
#include "tests/CtsEnforcement.h"
#include "tests/Test.h"
#include "tests/ganesh/GaneshTestUtils.h"

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <functional>
#include <initializer_list>
#include <memory>

struct GrContextOptions;

using sk_gpu_test::GrContextFactory;

void fill_transfer_data(int left, int top, int width, int height, int rowBytes,
                        GrColorType dstType, char* dst) {
    size_t dstBpp = GrColorTypeBytesPerPixel(dstType);
    auto dstLocation = [dst, dstBpp, rowBytes](int x, int y) {
        return dst + y * rowBytes + x * dstBpp;
    };
    // build red-green gradient
    for (int j = top; j < top + height; ++j) {
        for (int i = left; i < left + width; ++i) {
            auto r = (unsigned int)(256.f*((i - left) / (float)width));
            auto g = (unsigned int)(256.f*((j - top) / (float)height));
            r -= (r >> 8);
            g -= (g >> 8);
            // set b and a channels to be inverse of r and g just to have interesting values to
            // test.
            uint32_t srcPixel = GrColorPackRGBA(r, g, 0xff - r, 0xff - g);
            GrImageInfo srcInfo(GrColorType::kRGBA_8888, kUnpremul_SkAlphaType, nullptr, 1, 1);
            GrImageInfo dstInfo(dstType, kUnpremul_SkAlphaType, nullptr, 1, 1);
            GrConvertPixels(GrPixmap(dstInfo, dstLocation(i, j), dstBpp),
                            GrPixmap(srcInfo,         &srcPixel,      4));
        }
    }
}

void determine_tolerances(GrColorType a, GrColorType b, float tolerances[4]) {
    std::fill_n(tolerances, 4, 0);

    auto descA = GrGetColorTypeDesc(a);
    auto descB = GrGetColorTypeDesc(b);
    // For each channel x set the tolerance to 1 / (2^min(bits_in_a, bits_in_b) - 1) unless
    // one color type is missing the channel. In that case leave it at 0. If the other color
    // has the channel then it better be exactly 1 for alpha or 0 for rgb.
    for (int i = 0; i < 4; ++i) {
        if (descA[i] != descB[i]) {
            auto m = std::min(descA[i], descB[i]);
            if (m) {
                tolerances[i] = 1.f / (m - 1);
            }
        }
    }
}

bool read_pixels_from_texture(GrTexture* texture, GrColorType colorType, char* dst,
                              float tolerances[4]) {
    auto* context = texture->getContext();
    auto* gpu = context->priv().getGpu();
    auto* caps = context->priv().caps();

    int w = texture->width();
    int h = texture->height();
    size_t rowBytes = GrColorTypeBytesPerPixel(colorType) * w;

    GrCaps::SupportedRead supportedRead =
            caps->supportedReadPixelsColorType(colorType, texture->backendFormat(), colorType);
    std::fill_n(tolerances, 4, 0);
    if (supportedRead.fColorType != colorType) {
        size_t tmpRowBytes = GrColorTypeBytesPerPixel(supportedRead.fColorType) * w;
        std::unique_ptr<char[]> tmpPixels(new char[tmpRowBytes * h]);
        if (!gpu->readPixels(texture,
                             SkIRect::MakeWH(w, h),
                             colorType,
                             supportedRead.fColorType,
                             tmpPixels.get(),
                             tmpRowBytes)) {
            return false;
        }
        GrImageInfo tmpInfo(supportedRead.fColorType, kUnpremul_SkAlphaType, nullptr, w, h);
        GrImageInfo dstInfo(colorType,                kUnpremul_SkAlphaType, nullptr, w, h);
        determine_tolerances(tmpInfo.colorType(), dstInfo.colorType(), tolerances);
        return GrConvertPixels(GrPixmap(dstInfo,             dst,    rowBytes),
                               GrPixmap(tmpInfo, tmpPixels.get(), tmpRowBytes));
    }
    return gpu->readPixels(texture,
                           SkIRect::MakeWH(w, h),
                           colorType,
                           supportedRead.fColorType,
                           dst,
                           rowBytes);
}

void basic_transfer_to_test(skiatest::Reporter* reporter,
                            GrDirectContext* dContext,
                            GrColorType colorType,
                            GrRenderable renderable) {
    if (GrCaps::kNone_MapFlags == dContext->priv().caps()->mapBufferFlags()) {
        return;
    }

    auto* caps = dContext->priv().caps();

    auto backendFormat = caps->getDefaultBackendFormat(colorType, renderable);
    if (!backendFormat.isValid()) {
        return;
    }

    auto resourceProvider = dContext->priv().resourceProvider();
    GrGpu* gpu = dContext->priv().getGpu();

    static constexpr SkISize kTexDims = {16, 16};
    int srcBufferWidth = caps->transferPixelsToRowBytesSupport() ? 20 : 16;
    const int kBufferHeight = 16;

    sk_sp<GrTexture> tex = resourceProvider->createTexture(kTexDims,
                                                           backendFormat,
                                                           GrTextureType::k2D,
                                                           renderable,
                                                           1,
                                                           skgpu::Mipmapped::kNo,
                                                           skgpu::Budgeted::kNo,
                                                           GrProtected::kNo,
                                                           /*label=*/{});
    if (!tex) {
        ERRORF(reporter, "Could not create texture");
        return;
    }

    // We validate the results using GrGpu::readPixels, so exit if this is not supported.
    // TODO: Do this through SurfaceContext once it works for all color types or support
    // kCopyToTexture2D here.
    if (GrCaps::SurfaceReadPixelsSupport::kSupported !=
        caps->surfaceSupportsReadPixels(tex.get())) {
        return;
    }
    // GL requires a texture to be framebuffer bindable to call glReadPixels. However, we have not
    // incorporated that test into surfaceSupportsReadPixels(). TODO: Remove this once we handle
    // drawing to a bindable format.
    if (!caps->isFormatAsColorTypeRenderable(colorType, tex->backendFormat())) {
        return;
    }

    // The caps tell us what color type we are allowed to upload and read back from this texture,
    // either of which may differ from 'colorType'.
    GrCaps::SupportedWrite allowedSrc =
            caps->supportedWritePixelsColorType(colorType, tex->backendFormat(), colorType);
    if (!allowedSrc.fOffsetAlignmentForTransferBuffer) {
        return;
    }
    size_t srcRowBytes = SkAlignTo(GrColorTypeBytesPerPixel(allowedSrc.fColorType) * srcBufferWidth,
                                   caps->transferBufferRowBytesAlignment());

    std::unique_ptr<char[]> srcData(new char[kTexDims.fHeight * srcRowBytes]);

    fill_transfer_data(0, 0, kTexDims.fWidth, kTexDims.fHeight, srcRowBytes,
                       allowedSrc.fColorType, srcData.get());

    // create and fill transfer buffer
    size_t size = srcRowBytes * kBufferHeight;
    sk_sp<GrGpuBuffer> buffer = resourceProvider->createBuffer(size,
                                                               GrGpuBufferType::kXferCpuToGpu,
                                                               kDynamic_GrAccessPattern,
                                                               GrResourceProvider::ZeroInit::kNo);
    if (!buffer) {
        return;
    }
    void* data = buffer->map();
    if (!buffer) {
        ERRORF(reporter, "Could not map buffer");
        return;
    }
    memcpy(data, srcData.get(), size);
    buffer->unmap();

    //////////////////////////
    // transfer full data

    bool result;
    result = gpu->transferPixelsTo(tex.get(),
                                   SkIRect::MakeSize(kTexDims),
                                   colorType,
                                   allowedSrc.fColorType,
                                   buffer,
                                   0,
                                   srcRowBytes);
    REPORTER_ASSERT(reporter, result);

    size_t dstRowBytes = GrColorTypeBytesPerPixel(colorType) * kTexDims.fWidth;
    std::unique_ptr<char[]> dstBuffer(new char[dstRowBytes * kTexDims.fHeight]());

    float compareTolerances[4] = {};
    result = read_pixels_from_texture(tex.get(), colorType, dstBuffer.get(), compareTolerances);
    if (!result) {
        ERRORF(reporter, "Could not read pixels from texture, color type: %d",
               static_cast<int>(colorType));
        return;
    }

    auto error = std::function<ComparePixmapsErrorReporter>(
            [reporter, colorType](int x, int y, const float diffs[4]) {
                ERRORF(reporter,
                       "Error at (%d %d) in transfer, color type: %s, diffs: (%f, %f, %f, %f)",
                       x, y, GrColorTypeToStr(colorType),
                       diffs[0], diffs[1], diffs[2], diffs[3]);
            });
    GrImageInfo srcInfo(allowedSrc.fColorType, kUnpremul_SkAlphaType, nullptr, tex->dimensions());
    GrImageInfo dstInfo(            colorType, kUnpremul_SkAlphaType, nullptr, tex->dimensions());
    CompareGaneshPixels(GrCPixmap(srcInfo,   srcData.get(), srcRowBytes),
                        GrCPixmap(dstInfo, dstBuffer.get(), dstRowBytes),
                        compareTolerances,
                        error);

    //////////////////////////
    // transfer partial data

    // We're relying on this cap to write partial texture data
    if (!caps->transferPixelsToRowBytesSupport()) {
        return;
    }
    // We keep a 1 to 1 correspondence between pixels in the buffer and the entire texture. We
    // update the contents of a sub-rect of the buffer and push that rect to the texture. We start
    // with a left sub-rect inset of 2 but may adjust that so we can fulfill the transfer buffer
    // offset alignment requirement.
    int left = 2;
    int top = 10;
    const int width = 10;
    const int height = 2;
    size_t offset = top * srcRowBytes + left * GrColorTypeBytesPerPixel(allowedSrc.fColorType);
    while (offset % allowedSrc.fOffsetAlignmentForTransferBuffer) {
        offset += GrColorTypeBytesPerPixel(allowedSrc.fColorType);
        ++left;
        // In most cases we assume that the required alignment is 1 or a small multiple of the bpp,
        // which it is for color types across all current backends except Direct3D. To correct for
        // Direct3D's large alignment requirement we may adjust the top location as well.
        if (left + width > tex->width()) {
            left = 0;
            ++top;
            offset = top * srcRowBytes;
        }
        SkASSERT(left + width <= tex->width());
        SkASSERT(top + height <= tex->height());
    }

    // change color of subrectangle
    fill_transfer_data(left, top, width, height, srcRowBytes, allowedSrc.fColorType,
                       srcData.get());
    data = buffer->map();
    memcpy(data, srcData.get(), size);
    buffer->unmap();

    result = gpu->transferPixelsTo(tex.get(),
                                   SkIRect::MakeXYWH(left, top, width, height),
                                   colorType,
                                   allowedSrc.fColorType,
                                   buffer,
                                   offset,
                                   srcRowBytes);
    if (!result) {
        ERRORF(reporter, "Could not transfer pixels to texture, color type: %d",
               static_cast<int>(colorType));
        return;
    }

    result = read_pixels_from_texture(tex.get(), colorType, dstBuffer.get(), compareTolerances);
    if (!result) {
        ERRORF(reporter, "Could not read pixels from texture, color type: %d",
               static_cast<int>(colorType));
        return;
    }
    CompareGaneshPixels(GrCPixmap(srcInfo,   srcData.get(), srcRowBytes),
                        GrCPixmap(dstInfo, dstBuffer.get(), dstRowBytes),
                        compareTolerances,
                        error);
}

void basic_transfer_from_test(skiatest::Reporter* reporter, const sk_gpu_test::ContextInfo& ctxInfo,
                              GrColorType colorType, GrRenderable renderable) {
    auto context = ctxInfo.directContext();
    auto caps = context->priv().caps();
    if (GrCaps::kNone_MapFlags == caps->mapBufferFlags()) {
        return;
    }

    auto resourceProvider = context->priv().resourceProvider();
    GrGpu* gpu = context->priv().getGpu();

    static constexpr SkISize kTexDims = {16, 16};

    // We'll do a full texture read into the buffer followed by a partial read. These values
    // describe the partial read subrect.
    const int kPartialLeft = 2;
    const int kPartialTop = 10;
    const int kPartialWidth = 10;
    const int kPartialHeight = 2;

    // create texture
    auto format = context->priv().caps()->getDefaultBackendFormat(colorType, renderable);
    if (!format.isValid()) {
        return;
    }

    size_t textureDataBpp = GrColorTypeBytesPerPixel(colorType);
    size_t textureDataRowBytes = kTexDims.fWidth * textureDataBpp;
    std::unique_ptr<char[]> textureData(new char[kTexDims.fHeight * textureDataRowBytes]);
    fill_transfer_data(0, 0, kTexDims.fWidth, kTexDims.fHeight, textureDataRowBytes, colorType,
                       textureData.get());
    GrMipLevel data;
    data.fPixels = textureData.get();
    data.fRowBytes = textureDataRowBytes;
    sk_sp<GrTexture> tex = resourceProvider->createTexture(kTexDims,
                                                           format,
                                                           GrTextureType::k2D,
                                                           colorType,
                                                           renderable,
                                                           1,
                                                           skgpu::Budgeted::kNo,
                                                           skgpu::Mipmapped::kNo,
                                                           GrProtected::kNo,
                                                           &data,
                                                           /*label=*/{});
    if (!tex) {
        return;
    }

    if (GrCaps::SurfaceReadPixelsSupport::kSupported !=
        caps->surfaceSupportsReadPixels(tex.get())) {
        return;
    }
    // GL requires a texture to be framebuffer bindable to call glReadPixels. However, we have not
    // incorporated that test into surfaceSupportsReadPixels(). TODO: Remove this once we handle
    // drawing to a bindable format.
    if (!caps->isFormatAsColorTypeRenderable(colorType, tex->backendFormat())) {
        return;
    }

    // Create the transfer buffer.
    auto allowedRead =
            caps->supportedReadPixelsColorType(colorType, tex->backendFormat(), colorType);
    if (!allowedRead.fOffsetAlignmentForTransferBuffer) {
        return;
    }
    GrImageInfo readInfo(allowedRead.fColorType, kUnpremul_SkAlphaType, nullptr, kTexDims);

    size_t bpp = GrColorTypeBytesPerPixel(allowedRead.fColorType);
    size_t fullBufferRowBytes = SkAlignTo(kTexDims.fWidth * bpp,
                                          caps->transferBufferRowBytesAlignment());
    size_t partialBufferRowBytes = SkAlignTo(kPartialWidth * bpp,
                                             caps->transferBufferRowBytesAlignment());
    size_t offsetAlignment = allowedRead.fOffsetAlignmentForTransferBuffer;
    SkASSERT(offsetAlignment);

    size_t bufferSize = fullBufferRowBytes * kTexDims.fHeight;
    // Arbitrary starting offset for the partial read.
    static constexpr size_t kStartingOffset = 11;
    size_t partialReadOffset = kStartingOffset +
                               (offsetAlignment - kStartingOffset%offsetAlignment)%offsetAlignment;
    bufferSize = std::max(bufferSize,
                          partialReadOffset + partialBufferRowBytes * kPartialHeight);

    sk_sp<GrGpuBuffer> buffer = resourceProvider->createBuffer(bufferSize,
                                                               GrGpuBufferType::kXferGpuToCpu,
                                                               kDynamic_GrAccessPattern,
                                                               GrResourceProvider::ZeroInit::kNo);
    REPORTER_ASSERT(reporter, buffer);
    if (!buffer) {
        return;
    }

    int expectedTransferCnt = 0;
    gpu->stats()->reset();

    //////////////////////////
    // transfer full data
    bool result = gpu->transferPixelsFrom(tex.get(),
                                          SkIRect::MakeSize(kTexDims),
                                          colorType,
                                          allowedRead.fColorType,
                                          buffer,
                                          0);
    if (!result) {
        ERRORF(reporter, "transferPixelsFrom failed.");
        return;
    }
    ++expectedTransferCnt;

    if (context->priv().caps()->mapBufferFlags() & GrCaps::kAsyncRead_MapFlag) {
        GrSubmitInfo info;
        info.fSync = GrSyncCpu::kYes;

        gpu->submitToGpu(info);
    }

    // Copy the transfer buffer contents to a temporary so we can manipulate it.
    const auto* map = reinterpret_cast<const char*>(buffer->map());
    REPORTER_ASSERT(reporter, map);
    if (!map) {
        ERRORF(reporter, "Failed to map transfer buffer.");
        return;
    }
    std::unique_ptr<char[]> transferData(new char[kTexDims.fHeight * fullBufferRowBytes]);
    memcpy(transferData.get(), map, fullBufferRowBytes * kTexDims.fHeight);
    buffer->unmap();

    GrImageInfo transferInfo(allowedRead.fColorType, kUnpremul_SkAlphaType, nullptr, kTexDims);

    float tol[4];
    determine_tolerances(allowedRead.fColorType, colorType, tol);
    auto error = std::function<ComparePixmapsErrorReporter>(
            [reporter, colorType](int x, int y, const float diffs[4]) {
                ERRORF(reporter,
                       "Error at (%d %d) in transfer, color type: %s, diffs: (%f, %f, %f, %f)",
                       x, y, GrColorTypeToStr(colorType),
                       diffs[0], diffs[1], diffs[2], diffs[3]);
            });
    GrImageInfo textureDataInfo(colorType, kUnpremul_SkAlphaType, nullptr, kTexDims);
    CompareGaneshPixels(GrCPixmap(textureDataInfo,  textureData.get(), textureDataRowBytes),
                        GrCPixmap(   transferInfo, transferData.get(),  fullBufferRowBytes),
                        tol,
                        error);

    ///////////////////////
    // Now test a partial read at an offset into the buffer.
    result = gpu->transferPixelsFrom(
            tex.get(),
            SkIRect::MakeXYWH(kPartialLeft, kPartialTop, kPartialWidth, kPartialHeight),
            colorType,
            allowedRead.fColorType,
            buffer,
            partialReadOffset);
    if (!result) {
        ERRORF(reporter, "transferPixelsFrom failed.");
        return;
    }
    ++expectedTransferCnt;

    if (context->priv().caps()->mapBufferFlags() & GrCaps::kAsyncRead_MapFlag) {
        GrSubmitInfo info;
        info.fSync = GrSyncCpu::kYes;

        gpu->submitToGpu(info);
    }

    map = reinterpret_cast<const char*>(buffer->map());
    REPORTER_ASSERT(reporter, map);
    if (!map) {
        ERRORF(reporter, "Failed to map transfer buffer.");
        return;
    }
    const char* bufferStart = reinterpret_cast<const char*>(map) + partialReadOffset;
    memcpy(transferData.get(), bufferStart, partialBufferRowBytes * kTexDims.fHeight);
    buffer->unmap();

    transferInfo = transferInfo.makeWH(kPartialWidth, kPartialHeight);
    const char* textureDataStart =
            textureData.get() + textureDataRowBytes * kPartialTop + textureDataBpp * kPartialLeft;
    textureDataInfo = textureDataInfo.makeWH(kPartialWidth, kPartialHeight);
    CompareGaneshPixels(GrCPixmap(textureDataInfo,   textureDataStart,   textureDataRowBytes),
                        GrCPixmap(transferInfo   , transferData.get(), partialBufferRowBytes),
                        tol,
                        error);
#if GR_GPU_STATS
    REPORTER_ASSERT(reporter, gpu->stats()->transfersFromSurface() == expectedTransferCnt);
#else
    (void)expectedTransferCnt;
#endif
}

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(TransferPixelsToTextureTest,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kApiLevel_T) {
    if (!ctxInfo.directContext()->priv().caps()->transferFromBufferToTextureSupport()) {
        return;
    }
    for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
        for (auto colorType : {
                     GrColorType::kAlpha_8,
                     GrColorType::kBGR_565,
                     GrColorType::kRGB_565,
                     GrColorType::kABGR_4444,
                     GrColorType::kRGBA_8888,
                     GrColorType::kRGBA_8888_SRGB,
                     GrColorType::kRGB_888x,
                     GrColorType::kRG_88,
                     GrColorType::kBGRA_8888,
                     GrColorType::kRGBA_1010102,
                     GrColorType::kBGRA_1010102,
                     GrColorType::kRGB_101010x,
                     GrColorType::kRGBA_10x6,
                     GrColorType::kGray_8,
                     GrColorType::kAlpha_F16,
                     GrColorType::kRGBA_F16,
                     GrColorType::kRGBA_F16_Clamped,
                     GrColorType::kRGB_F16F16F16x,
                     GrColorType::kRGBA_F32,
                     GrColorType::kAlpha_16,
                     GrColorType::kRG_1616,
                     GrColorType::kRGBA_16161616,
                     GrColorType::kRG_F16,
             }) {
            basic_transfer_to_test(reporter, ctxInfo.directContext(), colorType, renderable);
        }
    }
}

// TODO(bsalomon): Metal
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(TransferPixelsFromTextureTest,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kApiLevel_T) {
    if (!ctxInfo.directContext()->priv().caps()->transferFromSurfaceToBufferSupport()) {
        return;
    }
    for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
        for (auto colorType : {
                     GrColorType::kAlpha_8,
                     GrColorType::kAlpha_16,
                     GrColorType::kBGR_565,
                     GrColorType::kRGB_565,
                     GrColorType::kABGR_4444,
                     GrColorType::kRGBA_8888,
                     GrColorType::kRGBA_8888_SRGB,
                     GrColorType::kRGB_888x,
                     GrColorType::kRG_88,
                     GrColorType::kBGRA_8888,
                     GrColorType::kRGBA_1010102,
                     GrColorType::kBGRA_1010102,
                     GrColorType::kRGB_101010x,
                     GrColorType::kRGBA_10x6,
                     GrColorType::kGray_8,
                     GrColorType::kAlpha_F16,
                     GrColorType::kRGBA_F16,
                     GrColorType::kRGBA_F16_Clamped,
                     GrColorType::kRGB_F16F16F16x,
                     GrColorType::kRGBA_F32,
                     GrColorType::kRG_1616,
                     GrColorType::kRGBA_16161616,
                     GrColorType::kRG_F16,
             }) {
            basic_transfer_from_test(reporter, ctxInfo, colorType, renderable);
        }
    }
}
