/*
 * 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/GpuTypes.h"
#include "include/gpu/ganesh/GrBackendSurface.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/GrTypes.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/core/SkColorData.h"
#include "src/gpu/SkBackingFit.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 = SkSurfaces::WrapBackendTexture(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, skgpu::Mipmapped::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 = SkSurfaces::WrapBackendTexture(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);
    dContext->flush(surface.get());
    dContext->submit();
    REPORTER_ASSERT(reporter, check_pixels(reporter, dContext, tex, info, SK_ColorRED));

    // Next try doing a GrDirectContext::flush without the surface 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.
    dContext->flush(surface.get());
    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);
    SkSurfaces::ResolveMSAA(surface);
    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).
    SkSurfaces::ResolveMSAA(surface);
    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);
    SkSurfaces::ResolveMSAA(surface);
    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
    dContext->flush(surface.get());

    auto otherSurface = SkSurfaces::RenderTarget(dContext, skgpu::Budgeted::kYes, info);
    REPORTER_ASSERT(reporter, otherSurface);
    otherSurface->getCanvas()->clear(SK_ColorRED);
    SkSurfaces::ResolveMSAA(surface);
    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);
    SkSurfaces::ResolveMSAA(otherSurface);
    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,
                                                               skgpu::Mipmapped::kYes,
                                                               SkBackingFit::kExact,
                                                               skgpu::Budgeted::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::ganesh::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,
                                                               skgpu::Mipmapped::kNo,
                                                               SkBackingFit::kExact,
                                                               skgpu::Budgeted::kYes,
                                                               GrProtected::kNo,
                                                               "testSrc");
            skgpu::ganesh::SurfaceContext mmSC(
                    dc, mmProxyView, {GrColorType::kRGBA_8888, kPremul_SkAlphaType, nullptr});
            mmSC.testCopy(src);
        }

        auto drawDst = skgpu::ganesh::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;
        }
    }
}
