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

#include "include/core/SkAlphaType.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkColorType.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkSurface.h"
#include "include/core/SkSurfaceProps.h"
#include "include/core/SkTypes.h"
#include "include/core/SkVertices.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/ganesh/GrBackendSurface.h"
#include "include/gpu/ganesh/GrContextOptions.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/GrTypes.h"
#include "include/gpu/ganesh/SkImageGanesh.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/core/SkBlendModePriv.h"
#include "src/core/SkColorData.h"
#include "src/gpu/SkBackingFit.h"
#include "src/gpu/ganesh/GrPaint.h"
#include "src/gpu/ganesh/GrPixmap.h"
#include "src/gpu/ganesh/GrXferProcessor.h"
#include "src/gpu/ganesh/SurfaceDrawContext.h"
#include "tests/CtsEnforcement.h"
#include "tests/Test.h"
#include "tools/gpu/ContextType.h"

#include <cstdint>
#include <cstring>
#include <memory>
#include <utility>

namespace {

static SkSurfaceProps kDMSAAProps(SkSurfaceProps::kDynamicMSAA_Flag, kUnknown_SkPixelGeometry);
static SkSurfaceProps kBasicProps(0, kUnknown_SkPixelGeometry);
constexpr static SkPMColor4f kTransYellow = {.5f,.5f,.0f,.5f};
constexpr static SkPMColor4f kTransCyan = {.0f,.5f,.5f,.5f};
constexpr static int kWidth=10, kHeight=10;

}

static void draw_paint_with_aa(skgpu::ganesh::SurfaceDrawContext* sdc,
                               const SkPMColor4f& color,
                               SkBlendMode blendMode) {
    GrPaint paint;
    paint.setColor4f(color);
    paint.setXPFactory(GrXPFactory::FromBlendMode(blendMode));
    sdc->drawRect(nullptr, std::move(paint), GrAA::kYes, SkMatrix::I(),
                  SkRect::MakeIWH(kWidth, kHeight), nullptr);
}

static void draw_paint_with_dmsaa(skgpu::ganesh::SurfaceDrawContext* sdc,
                                  const SkPMColor4f& color,
                                  SkBlendMode blendMode) {
    // drawVertices should always trigger dmsaa, but draw something non-rectangular just to be 100%
    // certain.
    static const SkPoint kVertices[3] = {{-.5f,-.5f}, {kWidth * 2.1f, 0}, {0, kHeight * 2.1f}};
    SkVertices::Builder builder(SkVertices::kTriangles_VertexMode, 3, 0, 0);
    memcpy(builder.positions(), kVertices, sizeof(kVertices));
    auto vertices = builder.detach();

    GrPaint paint;
    paint.setColor4f(color);
    paint.setXPFactory(GrXPFactory::FromBlendMode(blendMode));
    sdc->drawVertices(nullptr, std::move(paint), SkMatrix::I(), vertices);
}

static bool fuzzy_equals(const float a[4], const SkPMColor4f& b) {
    constexpr static float kTolerance = 2.5f / 256;
    for (int i = 0; i < 4; ++i) {
        if (!SkScalarNearlyEqual(a[i], b.vec()[i], kTolerance)) {
            return false;
        }
    }
    return true;
}

static void check_sdc_color(skiatest::Reporter* reporter,
                            skgpu::ganesh::SurfaceDrawContext* sdc,
                            GrDirectContext* ctx,
                            const SkPMColor4f& color) {
    auto info = SkImageInfo::Make(kWidth, kHeight, kRGBA_F32_SkColorType, kPremul_SkAlphaType);
    GrPixmap pixmap = GrPixmap::Allocate(info);
    sdc->readPixels(ctx, pixmap, {0, 0});
    auto pix = static_cast<const float*>(pixmap.addr());
    for (int y = 0; y < kHeight; ++y) {
        for (int x = 0; x < kWidth; ++x) {
            if (!fuzzy_equals(pix, color)) {
                ERRORF(reporter, "SDC color mismatch.\n"
                                 "Got      [%0.3f, %0.3f, %0.3f, %0.3f]\n"
                                 "Expected [%0.3f, %0.3f, %0.3f, %0.3f]",
                       pix[0], pix[1], pix[2], pix[3], color.fR, color.fG, color.fB, color.fA);
                return;
            }
            pix += 4;
        }
    }
}

DEF_GANESH_TEST_FOR_CONTEXTS(DMSAA_preserve_contents,
                             &skgpu::IsRenderingContext,
                             reporter,
                             ctxInfo,
                             nullptr,
                             CtsEnforcement::kApiLevel_T) {
    auto dContext = ctxInfo.directContext();
    auto sdc = skgpu::ganesh::SurfaceDrawContext::Make(dContext,
                                                       GrColorType::kRGBA_8888,
                                                       nullptr,
                                                       SkBackingFit::kApprox,
                                                       {kWidth, kHeight},
                                                       kDMSAAProps,
                                                       /*label=*/{});

    // Initialize the texture and dmsaa attachment with transparent.
    draw_paint_with_dmsaa(sdc.get(), SK_PMColor4fTRANSPARENT, SkBlendMode::kSrc);
    check_sdc_color(reporter, sdc.get(), dContext, SK_PMColor4fTRANSPARENT);

    // Clear the main texture to yellow.
    sdc->clear(kTransYellow);

    // Close the opsTask by doing a readback.
    check_sdc_color(reporter, sdc.get(), dContext, kTransYellow);

    // Now the DMSAA attachment is clear and the texture is yellow. Blend cyan into the DMSAA
    // attachment. This will fail if the yellow from the main texture doesn't get copied into the
    // DMSAA attachment before the renderPass.
    draw_paint_with_dmsaa(sdc.get(), kTransCyan, SkBlendMode::kSrcOver);
    SkPMColor4f dstColor = SkBlendMode_Apply(SkBlendMode::kSrcOver, kTransCyan, kTransYellow);

    check_sdc_color(reporter, sdc.get(), dContext, dstColor);
}

static void require_dst_reads(GrContextOptions* options) {
    options->fSuppressAdvancedBlendEquations = true;
    options->fSuppressFramebufferFetch = true;
}

DEF_GANESH_TEST_FOR_CONTEXTS(DMSAA_dst_read,
                             &skgpu::IsRenderingContext,
                             reporter,
                             ctxInfo,
                             require_dst_reads,
                             CtsEnforcement::kApiLevel_T) {
    auto dContext = ctxInfo.directContext();
    auto sdc = skgpu::ganesh::SurfaceDrawContext::Make(dContext,
                                                       GrColorType::kRGBA_8888,
                                                       nullptr,
                                                       SkBackingFit::kApprox,
                                                       {kWidth, kHeight},
                                                       kDMSAAProps,
                                                       /*label=*/{});

    // Initialize the texture and dmsaa attachment with transparent.
    draw_paint_with_dmsaa(sdc.get(), SK_PMColor4fTRANSPARENT, SkBlendMode::kSrc);
    check_sdc_color(reporter, sdc.get(), dContext, SK_PMColor4fTRANSPARENT);

    sdc->clear(SK_PMColor4fWHITE);
    SkPMColor4f dstColor = SK_PMColor4fWHITE;

    draw_paint_with_dmsaa(sdc.get(), kTransYellow, SkBlendMode::kDarken);
    dstColor = SkBlendMode_Apply(SkBlendMode::kDarken, kTransYellow, dstColor);

    draw_paint_with_dmsaa(sdc.get(), kTransCyan, SkBlendMode::kDarken);
    dstColor = SkBlendMode_Apply(SkBlendMode::kDarken, kTransCyan, dstColor);

    check_sdc_color(reporter, sdc.get(), dContext, dstColor);
}

DEF_GANESH_TEST_FOR_CONTEXTS(DMSAA_aa_dst_read_after_dmsaa,
                             &skgpu::IsRenderingContext,
                             reporter,
                             ctxInfo,
                             require_dst_reads,
                             CtsEnforcement::kApiLevel_T) {
    auto dContext = ctxInfo.directContext();
    auto sdc = skgpu::ganesh::SurfaceDrawContext::Make(dContext,
                                                       GrColorType::kRGBA_8888,
                                                       nullptr,
                                                       SkBackingFit::kApprox,
                                                       {kWidth, kHeight},
                                                       kDMSAAProps,
                                                       /*label=*/{});

    // Initialize the texture and dmsaa attachment with transparent.
    draw_paint_with_dmsaa(sdc.get(), SK_PMColor4fTRANSPARENT, SkBlendMode::kSrc);
    check_sdc_color(reporter, sdc.get(), dContext, SK_PMColor4fTRANSPARENT);

    sdc->clear(SK_PMColor4fWHITE);
    SkPMColor4f dstColor = SK_PMColor4fWHITE;

    draw_paint_with_dmsaa(sdc.get(), kTransYellow, SkBlendMode::kDarken);
    dstColor = SkBlendMode_Apply(SkBlendMode::kDarken, kTransYellow, dstColor);

    // Draw with aa after dmsaa. This should break up the render pass and issue a texture barrier.
    draw_paint_with_aa(sdc.get(), kTransCyan, SkBlendMode::kDarken);
    dstColor = SkBlendMode_Apply(SkBlendMode::kDarken, kTransCyan, dstColor);

    check_sdc_color(reporter, sdc.get(), dContext, dstColor);
}

DEF_GANESH_TEST_FOR_CONTEXTS(DMSAA_dst_read_with_existing_barrier,
                             &skgpu::IsRenderingContext,
                             reporter,
                             ctxInfo,
                             require_dst_reads,
                             CtsEnforcement::kApiLevel_T) {
    auto dContext = ctxInfo.directContext();
    auto sdc = skgpu::ganesh::SurfaceDrawContext::Make(dContext,
                                                       GrColorType::kRGBA_8888,
                                                       nullptr,
                                                       SkBackingFit::kApprox,
                                                       {kWidth, kHeight},
                                                       kDMSAAProps,
                                                       /*label=*/{});

    // Initialize the texture and dmsaa attachment with transparent.
    draw_paint_with_dmsaa(sdc.get(), SK_PMColor4fTRANSPARENT, SkBlendMode::kSrc);
    check_sdc_color(reporter, sdc.get(), dContext, SK_PMColor4fTRANSPARENT);

    sdc->clear(SK_PMColor4fWHITE);
    SkPMColor4f dstColor = SK_PMColor4fWHITE;

    // Blend to the texture (not the dmsaa attachment) with a dst read. This creates a texture
    // barrier.
    draw_paint_with_aa(sdc.get(), kTransYellow, SkBlendMode::kDarken);
    dstColor = SkBlendMode_Apply(SkBlendMode::kDarken, kTransYellow, dstColor);

    // Blend to the msaa attachment _without_ a dst read. This ensures we respect the prior texture
    // barrier by splitting the opsTask.
    draw_paint_with_dmsaa(sdc.get(), kTransCyan, SkBlendMode::kSrcOver);
    dstColor = SkBlendMode_Apply(SkBlendMode::kSrcOver, kTransCyan, dstColor);

    check_sdc_color(reporter, sdc.get(), dContext, dstColor);
}

// This test is used to test for crbug.com/1241134. The bug appears on Adreno5xx devices with OS
// PQ3A. It does not repro on the earlier PPR1 version since the extend blend func extension was not
// present on the older driver.
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(DMSAA_dual_source_blend_disable,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kApiLevel_T) {
    SkISize surfaceDims = {100, 100};
    SkISize texDims = {50, 50};
    auto context = ctxInfo.directContext();

    auto sourceTexture = context->createBackendTexture(texDims.width(),
                                                       texDims.height(),
                                                       kRGBA_8888_SkColorType,
                                                       SkColors::kBlue,
                                                       skgpu::Mipmapped::kNo,
                                                       GrRenderable::kYes,
                                                       GrProtected::kNo);

    auto sourceImage = SkImages::BorrowTextureFrom(context,
                                                   sourceTexture,
                                                   kTopLeft_GrSurfaceOrigin,
                                                   kRGBA_8888_SkColorType,
                                                   kPremul_SkAlphaType,
                                                   nullptr);

    auto texture1 = context->createBackendTexture(surfaceDims.width(),
                                                  surfaceDims.height(),
                                                  kRGBA_8888_SkColorType,
                                                  SkColors::kRed,
                                                  skgpu::Mipmapped::kNo,
                                                  GrRenderable::kYes,
                                                  GrProtected::kNo);

    auto texture2 = context->createBackendTexture(surfaceDims.width(),
                                                  surfaceDims.height(),
                                                  kRGBA_8888_SkColorType,
                                                  SkColors::kYellow,
                                                  skgpu::Mipmapped::kNo,
                                                  GrRenderable::kYes,
                                                  GrProtected::kNo);

    SkPaint paint;
    paint.setBlendMode(SkBlendMode::kSrc);

    SkRect srcRect = SkRect::MakeIWH(texDims.width(), texDims.height());
    SkRect dstRect = SkRect::MakeXYWH(texDims.width()/2, texDims.height()/2,
                                      texDims.width(), texDims.height());

    // First we do an image draw to a DMSAA surface with kSrc blend mode. This will trigger us to
    // use dual source blending if supported.
    // Note: The draw here doesn't actually use the dmsaa multisampled buffer. However, by using
    // a dmsaa surface it forces us to use the FillRRectOp instead of the normal FillQuad path. It
    // is unclear why, but using the FillRRectOp is required to repro the bug.
    {
        auto surface = SkSurfaces::WrapBackendTexture(context,
                                                      texture1,
                                                      kTopLeft_GrSurfaceOrigin,
                                                      1,
                                                      kRGBA_8888_SkColorType,
                                                      nullptr,
                                                      &kDMSAAProps);

        surface->getCanvas()->drawImageRect(sourceImage,
                                            srcRect,
                                            dstRect,
                                            SkSamplingOptions(),
                                            &paint,
                                            SkCanvas::kStrict_SrcRectConstraint);
        // Make sure there isn't any batching
        context->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
    }

    // Next we do an image draw to a different surface that doesn't have the dmsaa flag. This will
    // trigger use to disable blending. However, when the bug is present the driver still seems to
    // try and use a "src2" blend value and ends up just writing the original dst color of yellow.
    {
        auto surface = SkSurfaces::WrapBackendTexture(context,
                                                      texture2,
                                                      kTopLeft_GrSurfaceOrigin,
                                                      1,
                                                      kRGBA_8888_SkColorType,
                                                      nullptr,
                                                      &kBasicProps);

        surface->getCanvas()->drawImageRect(sourceImage,
                                            srcRect,
                                            dstRect,
                                            SkSamplingOptions(),
                                            &paint,
                                            SkCanvas::kStrict_SrcRectConstraint);
        context->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
    }

    {
        auto readImage = SkImages::BorrowTextureFrom(context,
                                                     texture2,
                                                     kTopLeft_GrSurfaceOrigin,
                                                     kRGBA_8888_SkColorType,
                                                     kPremul_SkAlphaType,
                                                     nullptr);
        SkImageInfo dstIInfo = SkImageInfo::Make(texDims.width(),
                                                 texDims.height(),
                                                 kRGBA_8888_SkColorType,
                                                 kPremul_SkAlphaType,
                                                 nullptr);

        SkBitmap bitmap;
        bitmap.allocPixels(dstIInfo);

        bool success = readImage->readPixels(context, bitmap.pixmap(), dstRect.fLeft, dstRect.fTop);
        if (!success) {
            ERRORF(reporter, "Failed to read pixels");
            return;
        }
        auto pix = static_cast<const uint32_t*>(bitmap.getAddr(0, 0));
        for (int x = 0; x < 50; ++x) {
            for (int y = 0; y < 50; ++y) {
                uint32_t pixColor = pix[x + y * 50];
                if (pixColor != 0xFFFF0000) {
                    ERRORF(reporter, "Didn't get a blue pixel at %d, %d. Got 0x%8X",
                           x, y, pixColor);
                    continue;
                }
            }
        }
    }
    sourceImage.reset();
    // Need to make sure the gpu is fully finished before deleting the textures
    context->flushAndSubmit(GrSyncCpu::kYes);
    context->deleteBackendTexture(sourceTexture);
    context->deleteBackendTexture(texture1);
    context->deleteBackendTexture(texture2);
}
