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

#include "include/core/SkCanvas.h"
#include "include/core/SkSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrImageInfo.h"
#include "src/gpu/GrSurfaceContext.h"
#include "src/gpu/GrSurfaceDrawContext.h"
#include "src/gpu/SkGr.h"
#include "tests/Test.h"

// using anonymous namespace because these functions are used as template params.
namespace {
/** convert 0..1 srgb value to 0..1 linear */
float srgb_to_linear(float srgb) {
    if (srgb <= 0.04045f) {
        return srgb / 12.92f;
    } else {
        return powf((srgb + 0.055f) / 1.055f, 2.4f);
    }
}

/** convert 0..1 linear value to 0..1 srgb */
float linear_to_srgb(float linear) {
    if (linear <= 0.0031308) {
        return linear * 12.92f;
    } else {
        return 1.055f * powf(linear, 1.f / 2.4f) - 0.055f;
    }
}
}  // namespace

/** tests a conversion with an error tolerance */
template <float (*CONVERT)(float)> static bool check_conversion(uint32_t input, uint32_t output,
                                                                float error) {
    // alpha should always be exactly preserved.
    if ((input & 0xff000000) != (output & 0xff000000)) {
        return false;
    }

    for (int c = 0; c < 3; ++c) {
        uint8_t inputComponent = (uint8_t) ((input & (0xff << (c*8))) >> (c*8));
        float lower = std::max(0.f, (float) inputComponent - error);
        float upper = std::min(255.f, (float) inputComponent + error);
        lower = CONVERT(lower / 255.f);
        upper = CONVERT(upper / 255.f);
        SkASSERT(lower >= 0.f && lower <= 255.f);
        SkASSERT(upper >= 0.f && upper <= 255.f);
        uint8_t outputComponent = (output & (0xff << (c*8))) >> (c*8);
        if (outputComponent < SkScalarFloorToInt(lower * 255.f) ||
            outputComponent > SkScalarCeilToInt(upper * 255.f)) {
            return false;
        }
    }
    return true;
}

/** tests a forward and backward conversion with an error tolerance */
template <float (*FORWARD)(float), float (*BACKWARD)(float)>
static bool check_double_conversion(uint32_t input, uint32_t output, float error) {
    // alpha should always be exactly preserved.
    if ((input & 0xff000000) != (output & 0xff000000)) {
        return false;
    }

    for (int c = 0; c < 3; ++c) {
        uint8_t inputComponent = (uint8_t) ((input & (0xff << (c*8))) >> (c*8));
        float lower = std::max(0.f, (float) inputComponent - error);
        float upper = std::min(255.f, (float) inputComponent + error);
        lower = FORWARD(lower / 255.f);
        upper = FORWARD(upper / 255.f);
        SkASSERT(lower >= 0.f && lower <= 255.f);
        SkASSERT(upper >= 0.f && upper <= 255.f);
        uint8_t upperComponent = SkScalarCeilToInt(upper * 255.f);
        uint8_t lowerComponent = SkScalarFloorToInt(lower * 255.f);
        lower = std::max(0.f, (float) lowerComponent - error);
        upper = std::min(255.f, (float) upperComponent + error);
        lower = BACKWARD(lowerComponent / 255.f);
        upper = BACKWARD(upperComponent / 255.f);
        SkASSERT(lower >= 0.f && lower <= 255.f);
        SkASSERT(upper >= 0.f && upper <= 255.f);
        upperComponent = SkScalarCeilToInt(upper * 255.f);
        lowerComponent = SkScalarFloorToInt(lower * 255.f);

        uint8_t outputComponent = (output & (0xff << (c*8))) >> (c*8);
        if (outputComponent < lowerComponent || outputComponent > upperComponent) {
            return false;
        }
    }
    return true;
}

static bool check_srgb_to_linear_conversion(uint32_t srgb, uint32_t linear, float error) {
    return check_conversion<srgb_to_linear>(srgb, linear, error);
}

static bool check_linear_to_srgb_conversion(uint32_t linear, uint32_t srgb, float error) {
    return check_conversion<linear_to_srgb>(linear, srgb, error);
}

static bool check_linear_to_srgb_to_linear_conversion(uint32_t input, uint32_t output, float error) {
    return check_double_conversion<linear_to_srgb, srgb_to_linear>(input, output, error);
}

static bool check_srgb_to_linear_to_srgb_conversion(uint32_t input, uint32_t output, float error) {
    return check_double_conversion<srgb_to_linear, linear_to_srgb>(input, output, error);
}

static bool check_no_conversion(uint32_t input, uint32_t output, float error) {
    // This is a bit of a hack to check identity transformations that may lose precision.
    return check_srgb_to_linear_to_srgb_conversion(input, output, error);
}

typedef bool (*CheckFn) (uint32_t orig, uint32_t actual, float error);

void read_and_check_pixels(skiatest::Reporter* reporter,
                           GrDirectContext* dContext,
                           GrSurfaceContext* sContext,
                           uint32_t* origData,
                           const SkImageInfo& dstInfo, CheckFn checker, float error,
                           const char* subtestName) {
    auto [w, h] = dstInfo.dimensions();
    GrPixmap readPM = GrPixmap::Allocate(dstInfo);
    memset(readPM.addr(), 0, sizeof(uint32_t)*w*h);

    if (!sContext->readPixels(dContext, readPM, {0, 0})) {
        ERRORF(reporter, "Could not read pixels for %s.", subtestName);
        return;
    }

    for (int j = 0; j < h; ++j) {
        for (int i = 0; i < w; ++i) {
            uint32_t orig = origData[j * w + i];
            uint32_t read = static_cast<uint32_t*>(readPM.addr())[j * w + i];

            if (!checker(orig, read, error)) {
                ERRORF(reporter, "Original 0x%08x, read back as 0x%08x in %s at %d, %d).", orig,
                       read, subtestName, i, j);
                return;
            }
        }
    }
}

namespace {
enum class Encoding {
    kUntagged,
    kLinear,
    kSRGB,
};
}  // namespace

static sk_sp<SkColorSpace> encoding_as_color_space(Encoding encoding) {
    switch (encoding) {
        case Encoding::kUntagged: return nullptr;
        case Encoding::kLinear:   return SkColorSpace::MakeSRGBLinear();
        case Encoding::kSRGB:     return SkColorSpace::MakeSRGB();
    }
    return nullptr;
}

static const char* encoding_as_str(Encoding encoding) {
    switch (encoding) {
        case Encoding::kUntagged: return "untagged";
        case Encoding::kLinear:   return "linear";
        case Encoding::kSRGB:     return "sRGB";
    }
    return nullptr;
}

static constexpr int kW = 255;
static constexpr int kH = 255;

static std::unique_ptr<uint32_t[]> make_data() {
    std::unique_ptr<uint32_t[]> data(new uint32_t[kW * kH]);
    for (int j = 0; j < kH; ++j) {
        for (int i = 0; i < kW; ++i) {
            data[j * kW + i] = (0xFF << 24) | (i << 16) | (i << 8) | i;
        }
    }
    return data;
}

static std::unique_ptr<GrSurfaceContext> make_surface_context(Encoding contextEncoding,
                                                              GrRecordingContext* rContext,
                                                              skiatest::Reporter* reporter) {
    auto surfaceContext = GrSurfaceDrawContext::Make(
            rContext, GrColorType::kRGBA_8888, encoding_as_color_space(contextEncoding),
            SkBackingFit::kExact, {kW, kH}, SkSurfaceProps(), 1, GrMipmapped::kNo, GrProtected::kNo,
            kBottomLeft_GrSurfaceOrigin, SkBudgeted::kNo);
    if (!surfaceContext) {
        ERRORF(reporter, "Could not create %s surface context.", encoding_as_str(contextEncoding));
    }
    return std::move(surfaceContext);
}

static void test_write_read(Encoding contextEncoding, Encoding writeEncoding, Encoding readEncoding,
                            float error, CheckFn check, GrDirectContext* dContext,
                            skiatest::Reporter* reporter) {
    auto surfaceContext = make_surface_context(contextEncoding, dContext, reporter);
    if (!surfaceContext) {
        return;
    }
    auto writeII = SkImageInfo::Make(kW, kH, kRGBA_8888_SkColorType, kPremul_SkAlphaType,
                                     encoding_as_color_space(writeEncoding));
    auto data = make_data();
    GrCPixmap dataPM(writeII, data.get(), kW*sizeof(uint32_t));
    if (!surfaceContext->writePixels(dContext, dataPM, {0, 0})) {
        ERRORF(reporter, "Could not write %s to %s surface context.",
               encoding_as_str(writeEncoding), encoding_as_str(contextEncoding));
        return;
    }

    auto readII = SkImageInfo::Make(kW, kH, kRGBA_8888_SkColorType, kPremul_SkAlphaType,
                                    encoding_as_color_space(readEncoding));
    SkString testName;
    testName.printf("write %s data to a %s context and read as %s.", encoding_as_str(writeEncoding),
                    encoding_as_str(contextEncoding), encoding_as_str(readEncoding));
    read_and_check_pixels(reporter, dContext, surfaceContext.get(), data.get(), readII, check,
                          error, testName.c_str());
}

// Test all combinations of writePixels/readPixels where the surface context/write source/read dst
// are sRGB, linear, or untagged RGBA_8888.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SRGBReadWritePixels, reporter, ctxInfo) {
    auto context = ctxInfo.directContext();
    if (!context->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888_SRGB,
                                                         GrRenderable::kNo).isValid()) {
        return;
    }
    // We allow more error on GPUs with lower precision shader variables.
    float error = context->priv().caps()->shaderCaps()->halfIs32Bits() ? 0.5f : 1.2f;
    // For the all-sRGB case, we allow a small error only for devices that have
    // precision variation because the sRGB data gets converted to linear and back in
    // the shader.
    float smallError = context->priv().caps()->shaderCaps()->halfIs32Bits() ? 0.0f : 1.f;

    ///////////////////////////////////////////////////////////////////////////////////////////////
    // Write sRGB data to a sRGB context - no conversion on the write.

    // back to sRGB - no conversion.
    test_write_read(Encoding::kSRGB, Encoding::kSRGB, Encoding::kSRGB, smallError,
                    check_no_conversion, context, reporter);
    // Reading back to untagged should be a pass through with no conversion.
    test_write_read(Encoding::kSRGB, Encoding::kSRGB, Encoding::kUntagged, error,
                    check_no_conversion, context, reporter);

    // Converts back to linear
    test_write_read(Encoding::kSRGB, Encoding::kSRGB, Encoding::kLinear, error,
                    check_srgb_to_linear_conversion, context, reporter);

    // Untagged source data should be interpreted as sRGB.
    test_write_read(Encoding::kSRGB, Encoding::kUntagged, Encoding::kSRGB, smallError,
                    check_no_conversion, context, reporter);

    ///////////////////////////////////////////////////////////////////////////////////////////////
    // Write linear data to a sRGB context. It gets converted to sRGB on write. The reads
    // are all the same as the above cases where the original data was untagged.
    test_write_read(Encoding::kSRGB, Encoding::kLinear, Encoding::kSRGB, error,
                    check_linear_to_srgb_conversion, context, reporter);
    // When the dst buffer is untagged there should be no conversion on the read.
    test_write_read(Encoding::kSRGB, Encoding::kLinear, Encoding::kUntagged, error,
                    check_linear_to_srgb_conversion, context, reporter);
    test_write_read(Encoding::kSRGB, Encoding::kLinear, Encoding::kLinear, error,
                    check_linear_to_srgb_to_linear_conversion, context, reporter);

    ///////////////////////////////////////////////////////////////////////////////////////////////
    // Write data to an untagged context. The write does no conversion no matter what encoding the
    // src data has.
    for (auto writeEncoding : {Encoding::kSRGB, Encoding::kUntagged, Encoding::kLinear}) {
        // The read from untagged to sRGB also does no conversion.
        test_write_read(Encoding::kUntagged, writeEncoding, Encoding::kSRGB, error,
                        check_no_conversion, context, reporter);
        // Reading untagged back as untagged should do no conversion.
        test_write_read(Encoding::kUntagged, writeEncoding, Encoding::kUntagged, error,
                        check_no_conversion, context, reporter);
        // Reading untagged back as linear does convert (context is source, so treated as sRGB),
        // dst is tagged.
        test_write_read(Encoding::kUntagged, writeEncoding, Encoding::kLinear, error,
                        check_srgb_to_linear_conversion, context, reporter);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////
    // Write sRGB data to a linear context - converts to sRGB on the write.

    // converts back to sRGB on read.
    test_write_read(Encoding::kLinear, Encoding::kSRGB, Encoding::kSRGB, error,
                    check_srgb_to_linear_to_srgb_conversion, context, reporter);
    // Reading untagged data from linear currently does no conversion.
    test_write_read(Encoding::kLinear, Encoding::kSRGB, Encoding::kUntagged, error,
                    check_srgb_to_linear_conversion, context, reporter);
    // Stays linear when read.
    test_write_read(Encoding::kLinear, Encoding::kSRGB, Encoding::kLinear, error,
                    check_srgb_to_linear_conversion, context, reporter);

    // Untagged source data should be interpreted as sRGB.
    test_write_read(Encoding::kLinear, Encoding::kUntagged, Encoding::kSRGB, error,
                    check_srgb_to_linear_to_srgb_conversion, context, reporter);

    ///////////////////////////////////////////////////////////////////////////////////////////////
    // Write linear data to a linear context. Does no conversion.

    // Reading to sRGB does a conversion.
    test_write_read(Encoding::kLinear, Encoding::kLinear, Encoding::kSRGB, error,
                    check_linear_to_srgb_conversion, context, reporter);
    // Reading to untagged does no conversion.
    test_write_read(Encoding::kLinear, Encoding::kLinear, Encoding::kUntagged, error,
                    check_no_conversion, context, reporter);
    // Stays linear when read.
    test_write_read(Encoding::kLinear, Encoding::kLinear, Encoding::kLinear, error,
                    check_no_conversion, context, reporter);
}
