/*
 * Copyright 2022 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/SkAlphaType.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkColorType.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkSurface.h"
#include "include/core/SkSurfaceProps.h"
#include "include/core/SkTypes.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/GrTypes.h"
#include "include/private/SkColorData.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/gpu/Swizzle.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrFragmentProcessor.h"
#include "src/gpu/ganesh/GrPaint.h"
#include "src/gpu/ganesh/GrProxyProvider.h"
#include "src/gpu/ganesh/GrSamplerState.h"
#include "src/gpu/ganesh/GrSurfaceProxy.h"
#include "src/gpu/ganesh/GrSurfaceProxyView.h"
#include "src/gpu/ganesh/GrTextureProxy.h"
#include "src/gpu/ganesh/GrTextureResolveRenderTask.h"
#include "src/gpu/ganesh/SurfaceContext.h"
#include "src/gpu/ganesh/SurfaceDrawContext.h"
#include "src/gpu/ganesh/effects/GrTextureEffect.h"
#include "src/gpu/ganesh/ops/OpsTask.h"
#include "tests/CtsEnforcement.h"
#include "tests/Test.h"
#include "tests/TestUtils.h"
#include "tools/gpu/FenceSync.h"
#include "tools/gpu/ManagedBackendTexture.h"

#include <functional>
#include <initializer_list>
#include <memory>
#include <utility>

struct GrContextOptions;

using namespace sk_gpu_test;

bool check_pixels(skiatest::Reporter* reporter,
                  GrDirectContext* dContext,
                  const GrBackendTexture& tex,
                  const SkImageInfo& info,
                  SkColor expectedColor) {
    // We have to do the readback of the backend texture wrapped in a different Skia surface than
    // the one used in the main body of the test or else the readPixels call will trigger resolves
    // itself.
    sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(dContext,
                                                                 tex,
                                                                 kTopLeft_GrSurfaceOrigin,
                                                                 /*sampleCnt=*/4,
                                                                 kRGBA_8888_SkColorType,
                                                                 nullptr, nullptr);
    SkBitmap actual;
    actual.allocPixels(info);
    if (!surface->readPixels(actual, 0, 0)) {
        return false;
    }

    SkBitmap expected;
    expected.allocPixels(info);
    SkCanvas tmp(expected);
    tmp.clear(expectedColor);
    expected.setImmutable();

    const float tols[4] = { 0.0f, 0.0f, 0.0f, 0.0f };

    auto error = std::function<ComparePixmapsErrorReporter>(
        [reporter](int x, int y, const float diffs[4]) {
            SkASSERT(x >= 0 && y >= 0);
            ERRORF(reporter, "mismatch at %d, %d (%f, %f, %f %f)",
                   x, y, diffs[0], diffs[1], diffs[2], diffs[3]);
        });

    return ComparePixels(expected.pixmap(), actual.pixmap(), tols, error);
}

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SurfaceResolveTest,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kApiLevel_T) {
    auto dContext = ctxInfo.directContext();

    SkImageInfo info = SkImageInfo::Make(8, 8, kRGBA_8888_SkColorType, kPremul_SkAlphaType);

    auto managedTex = ManagedBackendTexture::MakeFromInfo(dContext,
                                                          info,
                                                          GrMipmapped::kNo,
                                                          GrRenderable::kYes);
    if (!managedTex) {
        return;
    }
    auto tex = managedTex->texture();
    // Wrap the backend surface but tell it rendering with MSAA so that the wrapped texture is the
    // resolve.
    sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(dContext,
                                                                 tex,
                                                                 kTopLeft_GrSurfaceOrigin,
                                                                 /*sampleCnt=*/4,
                                                                 kRGBA_8888_SkColorType,
                                                                 nullptr, nullptr);

    if (!surface) {
        return;
    }

    const GrCaps* caps = dContext->priv().caps();
    // In metal and vulkan if we prefer discardable msaa attachments we will also auto resolve. The
    // GrBackendTexture and SkSurface are set up in a way that is compatible with discardable msaa
    // for both backends.
    bool autoResolves = caps->msaaResolvesAutomatically() ||
                        caps->preferDiscardableMSAAAttachment();

    // First do a simple test where we clear the surface than flush with SkSurface::flush. This
    // should trigger the resolve and the texture should have the correct data.
    surface->getCanvas()->clear(SK_ColorRED);
    surface->flush();
    dContext->submit();
    REPORTER_ASSERT(reporter, check_pixels(reporter, dContext, tex, info, SK_ColorRED));

    // Next try doing a GrDirectContext::flush which will not trigger a resolve on gpus without
    // automatic msaa resolves.
    surface->getCanvas()->clear(SK_ColorBLUE);
    dContext->flush();
    dContext->submit();
    if (autoResolves) {
        REPORTER_ASSERT(reporter, check_pixels(reporter, dContext, tex, info, SK_ColorBLUE));
    } else {
        REPORTER_ASSERT(reporter, check_pixels(reporter, dContext, tex, info, SK_ColorRED));
    }

    // Now doing a surface flush (even without any queued up normal work) should still resolve the
    // surface.
    surface->flush();
    dContext->submit();
    REPORTER_ASSERT(reporter, check_pixels(reporter, dContext, tex, info, SK_ColorBLUE));

    // Test using SkSurface::resolve with a GrDirectContext::flush
    surface->getCanvas()->clear(SK_ColorRED);
    surface->resolveMSAA();
    dContext->flush();
    dContext->submit();
    REPORTER_ASSERT(reporter, check_pixels(reporter, dContext, tex, info, SK_ColorRED));

    // Calling resolve again should cause no issues as it is a no-op (there is an assert in the
    // resolve op that the surface's msaa is dirty, we shouldn't hit that assert).
    surface->resolveMSAA();
    dContext->flush();
    dContext->submit();
    REPORTER_ASSERT(reporter, check_pixels(reporter, dContext, tex, info, SK_ColorRED));

    // Try resolving in the middle of draw calls. Non automatic resolve gpus should only see the
    // results of the first draw.
    surface->getCanvas()->clear(SK_ColorGREEN);
    surface->resolveMSAA();
    surface->getCanvas()->clear(SK_ColorBLUE);
    dContext->flush();
    dContext->submit();
    if (autoResolves) {
        REPORTER_ASSERT(reporter, check_pixels(reporter, dContext, tex, info, SK_ColorBLUE));
    } else {
        REPORTER_ASSERT(reporter, check_pixels(reporter, dContext, tex, info, SK_ColorGREEN));
    }

    // Test that a resolve between draws to a different surface doesn't cause the OpsTasks for that
    // surface to be split. Fails if we hit validation asserts in GrDrawingManager.
    // First clear out dirty msaa from previous test
    surface->flush();

    auto otherSurface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kYes, info);
    REPORTER_ASSERT(reporter, otherSurface);
    otherSurface->getCanvas()->clear(SK_ColorRED);
    surface->resolveMSAA();
    otherSurface->getCanvas()->clear(SK_ColorBLUE);
    dContext->flush();
    dContext->submit();

    // Make sure resolving a non-msaa surface doesn't trigger a resolve call. We'll hit an assert
    // that the msaa is not dirty if it does.
    REPORTER_ASSERT(reporter, otherSurface);
    otherSurface->getCanvas()->clear(SK_ColorRED);
    otherSurface->resolveMSAA();
    dContext->flush();
    dContext->submit();
}

// This test comes from crbug.com/1355807 and crbug.com/1365578. The underlying issue was:
//  * We would do a non-mipmapped draw of a proxy. This proxy would add a dependency from the ops
//    task to the proxy's last render task, which was a copy task targetting the proxy.
//  * We would do a mipmapped draw of the same proxy to the same ops task.
//    GrRenderTask::addDependency would detect the pre-existing dependency and early out before
//    adding the proxy to a resolve task.
// We also test the case where the first draw should add a MSAA resolve and the second draw should
// add a mipmap resolve.
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(NonmippedDrawBeforeMippedDraw,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kNever) {
    using ResolveFlags = GrSurfaceProxy::ResolveFlags;
    auto dc = ctxInfo.directContext();

    if (!dc->priv().caps()->mipmapSupport()) {
        return;
    }

    for (int sampleCount : {1, 4}) {
        GrRenderable renderable = sampleCount > 1 ? GrRenderable::kYes : GrRenderable::kNo;

        auto bef = dc->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888, renderable);
        if (sampleCount > 1) {
            if (dc->priv().caps()->msaaResolvesAutomatically()) {
                // MSAA won't add a resolve task.
                continue;
            }
            sampleCount = dc->priv().caps()->getRenderTargetSampleCount(sampleCount, bef);
            if (!sampleCount) {
                continue;
            }
        }

        // Create a mipmapped proxy
        auto mmProxy = dc->priv().proxyProvider()->createProxy(bef,
                                                               {64, 64},
                                                               renderable,
                                                               sampleCount,
                                                               GrMipmapped::kYes,
                                                               SkBackingFit::kExact,
                                                               SkBudgeted::kYes,
                                                               GrProtected::kNo,
                                                               "test MM Proxy");
        GrSurfaceProxyView mmProxyView{mmProxy,
                                       kBottomLeft_GrSurfaceOrigin,
                                       skgpu::Swizzle::RGBA()};

        if (sampleCount > 1) {
            // Make sure MSAA surface needs a resolve by drawing to it. This also adds a last
            // render task to the proxy.
            auto drawContext = skgpu::v1::SurfaceDrawContext::Make(dc,
                                                                   GrColorType::kRGBA_8888,
                                                                   mmProxy,
                                                                   nullptr,
                                                                   kBottomLeft_GrSurfaceOrigin,
                                                                   SkSurfaceProps{});
            drawContext->fillWithFP(GrFragmentProcessor::MakeColor(SK_PMColor4fWHITE));
        } else {
            // Use a copy, as in the original bug, to dirty the mipmap status and also install
            // a last render task on the proxy.
            auto src = dc->priv().proxyProvider()->createProxy(bef,
                                                               {64, 64},
                                                               GrRenderable::kNo,
                                                               1,
                                                               GrMipmapped::kNo,
                                                               SkBackingFit::kExact,
                                                               SkBudgeted::kYes,
                                                               GrProtected::kNo,
                                                               "testSrc");
            skgpu::v1::SurfaceContext mmSC(dc,
                                           mmProxyView,
                                           {GrColorType::kRGBA_8888, kPremul_SkAlphaType, nullptr});
            mmSC.testCopy(src);
        }

        auto drawDst = skgpu::v1::SurfaceDrawContext::Make(dc,
                                                           GrColorType::kRGBA_8888,
                                                           nullptr,
                                                           SkBackingFit::kExact,
                                                           {8, 8},
                                                           SkSurfaceProps{},
                                                           "testDrawDst");

        // Do a non-mipmapped draw from the mipmapped texture. This should add a dependency on the
        // copy task recorded above. If the src texture is also multisampled this should record a
        // msaa-only resolve.
        {
            auto te = GrTextureEffect::Make(
                    mmProxyView,
                    kPremul_SkAlphaType,
                    SkMatrix::I(),
                    GrSamplerState{SkFilterMode::kLinear, SkMipmapMode::kNone},
                    *dc->priv().caps());

            GrPaint paint;
            paint.setColorFragmentProcessor(std::move(te));

            drawDst->drawRect(nullptr,
                              std::move(paint),
                              GrAA::kNo,
                              SkMatrix::Scale(1/8.f, 1/8.f),
                              SkRect::Make(mmProxy->dimensions()));
            if (sampleCount > 1) {
                const GrTextureResolveRenderTask* resolveTask =
                        drawDst->getOpsTask()->resolveTask();
                if (!resolveTask) {
                    ERRORF(reporter, "No resolve task after drawing MSAA proxy");
                    return;
                }
                if (resolveTask->flagsForProxy(mmProxy) != ResolveFlags::kMSAA) {
                    ERRORF(reporter, "Expected resolve flags to be kMSAA");
                    return;
                }
            }
        }

        // Now do a mipmapped draw from the same texture. Ensure that even though we have a
        // dependency on the copy task we still ensure that a resolve is recorded.
        {
            auto te = GrTextureEffect::Make(
                    mmProxyView,
                    kPremul_SkAlphaType,
                    SkMatrix::I(),
                    GrSamplerState{SkFilterMode::kLinear, SkMipmapMode::kLinear},
                    *dc->priv().caps());

            GrPaint paint;
            paint.setColorFragmentProcessor(std::move(te));

            drawDst->drawRect(nullptr,
                              std::move(paint),
                              GrAA::kNo,
                              SkMatrix::Scale(1/8.f, 1/8.f),
                              SkRect::Make(mmProxy->dimensions()));
        }
        const GrTextureResolveRenderTask* resolveTask = drawDst->getOpsTask()->resolveTask();
        if (!resolveTask) {
            ERRORF(reporter, "No resolve task after drawing mip mapped proxy");
            return;
        }

        ResolveFlags expectedFlags = GrSurfaceProxy::ResolveFlags::kMipMaps;
        const char* expectedStr = "kMipMaps";
        if (sampleCount > 1) {
            expectedFlags |= GrSurfaceProxy::ResolveFlags::kMSAA;
            expectedStr = "kMipMaps|kMSAA";
        }
        if (resolveTask->flagsForProxy(mmProxy) != expectedFlags) {
            ERRORF(reporter, "Expected resolve flags to be %s", expectedStr);
            return;
        }
    }
}
