/*
 * 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/GrBackendSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/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 "tests/CtsEnforcement.h"
#include "tests/Test.h"
#include "tests/TestUtils.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,
                                                           GrMipmapped::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());
    ComparePixels(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;
    }
    ComparePixels(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,
                                                           GrMipmapped::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) {
        gpu->submitToGpu(true);
    }

    // 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);
    ComparePixels(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) {
        gpu->submitToGpu(true);
    }

    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);
    ComparePixels(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::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::kGray_8,
                     GrColorType::kAlpha_F16,
                     GrColorType::kRGBA_F16,
                     GrColorType::kRGBA_F16_Clamped,
                     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::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::kGray_8,
                     GrColorType::kAlpha_F16,
                     GrColorType::kRGBA_F16,
                     GrColorType::kRGBA_F16_Clamped,
                     GrColorType::kRGBA_F32,
                     GrColorType::kRG_1616,
                     GrColorType::kRGBA_16161616,
                     GrColorType::kRG_F16,
             }) {
            basic_transfer_from_test(reporter, ctxInfo, colorType, renderable);
        }
    }
}
