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

#include "tests/Test.h"

#include "include/core/SkBitmap.h"
#include "include/core/SkTileMode.h"
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/Image.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/Surface.h"
#include "src/gpu/graphite/Surface_Graphite.h"
#include "src/shaders/SkImageShader.h"
#include "tools/ToolUtils.h"

namespace skgpu::graphite {

namespace {

constexpr SkColor4f kRectColor = SkColors::kRed;
constexpr SkColor4f kBgColor = SkColors::kTransparent;

struct Expectation {
    SkPoint pos;
    SkColor4f color;
};

void test_draw(skiatest::Reporter* reporter,
               Context* context,
               SkISize canvasSize,
               SkISize imageSize,
               SkRect srcRect,
               SkRect dstRect,
               SkTileMode tileMode,
               SkSamplingOptions samplingOptions,
               std::vector<Expectation> expectations) {
    std::unique_ptr<Recorder> recorder = context->makeRecorder();
    REPORTER_ASSERT(reporter, recorder);
    sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(
            recorder.get(),
            SkImageInfo::Make(canvasSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
    SkCanvas* canvas = surface->getCanvas();

    SkBitmap bitmap;
    bitmap.allocPixels(SkImageInfo::Make(imageSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType),
                       0);
    bitmap.eraseColor(kRectColor);
    bitmap.setImmutable();
    sk_sp<SkImage> image = SkImages::TextureFromImage(recorder.get(), bitmap.asImage(),
                                                      {/*fMipmapped=*/false});

    SkPaint p;
    SkMatrix srcToDst = SkMatrix::RectToRectOrIdentity(srcRect, dstRect);
    p.setShader(SkImageShader::MakeSubset(
            std::move(image), srcRect, tileMode, tileMode, samplingOptions, &srcToDst));
    canvas->drawRect(dstRect, p);

    SkPixmap pm;

    SkBitmap result;
    result.allocPixels(SkImageInfo::Make(canvasSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
    bool peekPixelsSuccess = result.peekPixels(&pm);
    REPORTER_ASSERT(reporter, peekPixelsSuccess);

    bool readPixelsSuccess = surface->readPixels(pm, 0, 0);
    REPORTER_ASSERT(reporter, readPixelsSuccess);

    for (const Expectation& e : expectations) {
        SkColor4f a = e.color;
        SkColor4f b = pm.getColor4f(e.pos.fX, e.pos.fY);
        REPORTER_ASSERT(reporter,
                        a == b,
                        "At position {%.1f, %.1f}, "
                        "expected {%.1f, %.1f, %.1f, %.1f}, "
                        "found {%.1f, %.1f, %.1f, %.1f}",
                        e.pos.fX, e.pos.fY,
                        a.fR, a.fG, a.fB, a.fA,
                        b.fR, b.fG, b.fB, b.fA);
    }
}

}  // anonymous namespace

DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(ImageShaderTest, reporter, context,
                                         CtsEnforcement::kApiLevel_202404) {
    // Test that a subset bound covering less than half of a pixel causes that pixel not to be
    // drawn when using decal tiling and nearest-neighbor filtering. In this case we have a subset
    // that covers 3/4 the pixel column at y=1, all of the y=2 column, and 1/4 the y=3 column.
    test_draw(reporter,
              context,
              /*canvasSize=*/SkISize::Make(100, 100),
              /*imageSize=*/SkISize::Make(4, 4),
              /*srcRect=*/SkRect::MakeLTRB(1.25, 0.0f, 3.25f, 2.0f),
              /*dstRect=*/SkRect::MakeLTRB(0, 0, 80, 80),
              SkTileMode::kDecal,
              SkSamplingOptions(),

              // Pixel that should sample the image at y=1, since that's where the subset starts.
              {{{0, 40}, kRectColor},
               // Pixel that would sample the image at y=3, but the subset bound at y=3.25 prevents
               // us from sampling the image.
               {{75, 40}, kBgColor}});
}

}  // namespace skgpu::graphite
