/*
 * 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 "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/GrContextOptions.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/GrTypes.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "include/gpu/ganesh/mock/GrMockTypes.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/GrDrawingManager.h"
#include "src/gpu/ganesh/GrFragmentProcessor.h"
#include "src/gpu/ganesh/GrOnFlushResourceProvider.h"
#include "src/gpu/ganesh/GrPaint.h"
#include "src/gpu/ganesh/GrProxyProvider.h"
#include "src/gpu/ganesh/GrRenderTargetProxy.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/ComparePixels.h"
#include "tests/CtsEnforcement.h"
#include "tests/Test.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;
        }
    }
}

namespace {
// A preFlush callback that fails the first N flushes, simulating an allocation failure in an
// onFlush callback (e.g. atlas instantiation under memory pressure).
class FailingPreFlushCallback : public GrOnFlushCallbackObject {
public:
    explicit FailingPreFlushCallback(int failCount) : fRemainingFailures(failCount) {}
    bool preFlush(GrOnFlushResourceProvider*) override {
        if (fRemainingFailures > 0) {
            --fRemainingFailures;
            return false;
        }
        return true;
    }
    bool retainOnFreeGpuResources() override { return true; }

private:
    int fRemainingFailures;
};
}  // namespace

// GrTextureResolveRenderTask::addProxy() optimistically marks a proxy's mipmaps clean / MSAA
// resolved at recording time. If the owning flush is dropped without executing render tasks
// (e.g., a preFlush callback or the resource allocator fails) the proxy must be re-dirtied so a
// later flush will record a new resolve.
DEF_GANESH_TEST(SurfaceResolveProxyStateAfterFailedFlush,
                reporter,
                /* options */,
                CtsEnforcement::kNever) {
    using ResolveFlags = GrSurfaceProxy::ResolveFlags;
    using Enable = GrContextOptions::Enable;
    using MipmapMode = GrSamplerState::MipmapMode;

    for (auto reduceOpsTaskSplitting : {Enable::kYes, Enable::kNo}) {
        for (int sampleCount : {1, 4}) {
            GrMockOptions mockOptions;
            mockOptions.fMipmapSupport = true;
            mockOptions.fConfigOptions[(int)GrColorType::kRGBA_8888].fRenderability =
                    GrMockOptions::ConfigOptions::Renderability::kMSAA;
            GrContextOptions ctxOptions;
            ctxOptions.fReduceOpsTaskSplitting = reduceOpsTaskSplitting;
            sk_sp<GrDirectContext> dContext = GrDirectContext::MakeMock(&mockOptions, ctxOptions);
            if (!dContext) {
                ERRORF(reporter, "could not create mock context");
                continue;
            }
            GrDrawingManager* drawingManager = dContext->priv().drawingManager();
            auto bef = dContext->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
                                                                        GrRenderable::kYes);

            sk_sp<GrSurfaceProxy> proxy =
                    dContext->priv().proxyProvider()->createProxy(bef,
                                                                  {64, 64},
                                                                  GrRenderable::kYes,
                                                                  sampleCount,
                                                                  skgpu::Mipmapped::kYes,
                                                                  SkBackingFit::kExact,
                                                                  skgpu::Budgeted::kYes,
                                                                  GrProtected::kNo,
                                                                  "ResolveProxyStateTest");
            if (!proxy) {
                ERRORF(reporter, "could not create proxy");
                continue;
            }
            GrTextureProxy* texProxy = proxy->asTextureProxy();
            GrRenderTargetProxy* rtProxy = proxy->asRenderTargetProxy();
            GrSurfaceProxyView proxyView{proxy,
                                         kTopLeft_GrSurfaceOrigin,
                                         skgpu::Swizzle::RGBA()};

            const bool testMSAA = sampleCount > 1;
            REPORTER_ASSERT(reporter, !testMSAA || proxy->requiresManualMSAAResolve());

            auto recordDirtyingDrawAndMipmappedDependency = [&]() {
                auto srcSDC =
                        skgpu::ganesh::SurfaceDrawContext::Make(dContext.get(),
                                                                GrColorType::kRGBA_8888,
                                                                proxy,
                                                                nullptr,
                                                                kTopLeft_GrSurfaceOrigin,
                                                                SkSurfaceProps{});
                srcSDC->fillWithFP(GrFragmentProcessor::MakeColor(SK_PMColor4fWHITE));

                auto dstSDC =
                        skgpu::ganesh::SurfaceDrawContext::Make(dContext.get(),
                                                                GrColorType::kRGBA_8888,
                                                                nullptr,
                                                                SkBackingFit::kExact,
                                                                {8, 8},
                                                                SkSurfaceProps{},
                                                                "ResolveProxyStateTestDst");
                auto te = GrTextureEffect::Make(
                        proxyView,
                        kPremul_SkAlphaType,
                        SkMatrix::I(),
                        GrSamplerState{SkFilterMode::kLinear, MipmapMode::kLinear},
                        *dContext->priv().caps());
                GrPaint paint;
                paint.setColorFragmentProcessor(std::move(te));
                dstSDC->drawRect(nullptr,
                                 std::move(paint),
                                 GrAA::kNo,
                                 SkMatrix::Scale(1/8.f, 1/8.f),
                                 SkRect::Make(proxy->dimensions()));
                return dstSDC;
            };

            // Record a flush whose preFlush callback fails. The resolve task records the proxy
            // as resolved/clean and is then discarded without executing.
            {
                FailingPreFlushCallback failCB(1);
                dContext->priv().addOnFlushCallbackObject(&failCB);

                auto dstSDC = recordDirtyingDrawAndMipmappedDependency();

                ResolveFlags expectedFlags = ResolveFlags::kMipMaps;
                if (testMSAA) {
                    expectedFlags |= ResolveFlags::kMSAA;
                }
                const GrTextureResolveRenderTask* resolveTask =
                        dstSDC->getOpsTask()->resolveTask();
                REPORTER_ASSERT(reporter,
                                resolveTask &&
                                        resolveTask->flagsForProxy(proxy) == expectedFlags);
                REPORTER_ASSERT(reporter, !texProxy->mipmapsAreDirty());
                REPORTER_ASSERT(reporter, !testMSAA || !rtProxy->isMSAADirty());

                dContext->flush();
                drawingManager->testingOnly_removeOnFlushCallbackObject(&failCB);
            }

            // The resolve never executed so the proxy must once again report dirty mips/MSAA.
            REPORTER_ASSERT(reporter, texProxy->mipmapsAreDirty());
            if (testMSAA) {
                REPORTER_ASSERT(reporter, rtProxy->isMSAADirty());
                REPORTER_ASSERT(reporter,
                                rtProxy->msaaDirtyRect() == SkIRect::MakeSize(proxy->dimensions()));
            }

            // A subsequent dependency must therefore record a new resolve task and the proxy
            // should be clean once that flush succeeds.
            {
                auto dstSDC = recordDirtyingDrawAndMipmappedDependency();
                REPORTER_ASSERT(reporter, dstSDC->getOpsTask()->resolveTask());
                dContext->flush();
            }
            REPORTER_ASSERT(reporter, !texProxy->mipmapsAreDirty());
            REPORTER_ASSERT(reporter, !testMSAA || !rtProxy->isMSAADirty());
        }
    }
}

// Directly read back 'tex' and return the first pixel color.
static bool read_backing_pixel(GrDirectContext* dContext,
                               const GrBackendTexture& tex,
                               const SkImageInfo& info,
                               SkColor* outPixel) {
    sk_sp<SkSurface> reader = SkSurfaces::WrapBackendTexture(dContext,
                                                             tex,
                                                             kTopLeft_GrSurfaceOrigin,
                                                             /*sampleCnt=*/1,
                                                             kRGBA_8888_SkColorType,
                                                             nullptr,
                                                             nullptr);
    if (!reader) {
        return false;
    }
    SkBitmap bm;
    bm.allocPixels(info);
    if (!reader->readPixels(bm, 0, 0)) {
        return false;
    }
    *outPixel = bm.getColor(0, 0);
    return true;
}

// This test wraps a backend texture as an MSAA render target twice. The first wrap establishes a
// known baseline color in the single-sample texture via a *successful* flush. The second wrap
// creates a *fresh, never-written* MSAA color attachment (on GL a new renderbuffer, on Vulkan a
// scratch/new GrVkImage), records a draw, forces the flush to fail via a failing preFlush
// callback, and then reads back the single-sample texture. The read-back must not show the
// uninitialized MSAA attachment contents; if it does, resolve_and_mipmap() ran despite the failed
// flush and copied uninitialized GPU memory into the client-visible texture.
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SurfaceResolveAfterFailedFlush,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kNever) {
    auto dContext = ctxInfo.directContext();
    const GrCaps* caps = dContext->priv().caps();

    // Only meaningful on backends that require an explicit resolve of a persistent MSAA attachment.
    if (caps->msaaResolvesAutomatically() || caps->preferDiscardableMSAAAttachment()) {
        return;
    }

    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;
    }
    const GrBackendTexture& tex = managedTex->texture();

    constexpr SkColor kBaseline = SK_ColorBLUE;   // known content of the single-sample texture
    constexpr SkColor kIntended = SK_ColorGREEN;  // what the failed flush *would* have drawn

    // 1. Wrap once and successfully draw kBaseline so the single-sample texture holds known bytes.
    {
        sk_sp<SkSurface> surface = SkSurfaces::WrapBackendTexture(dContext,
                                                                  tex,
                                                                  kTopLeft_GrSurfaceOrigin,
                                                                  /*sampleCnt=*/4,
                                                                  kRGBA_8888_SkColorType,
                                                                  nullptr,
                                                                  nullptr);
        if (!surface) {
            return;  // MSAA=4 unsupported on this config.
        }
        surface->getCanvas()->clear(kBaseline);
        dContext->flush(surface.get());
        dContext->submit(GrSyncCpu::kYes);
    }
    // Ensure the second wrap below allocates a *fresh* MSAA attachment rather than recycling the
    // one from the wrap above (whose contents would coincidentally match kBaseline).
    dContext->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);

    SkColor pixel = 0;
    REPORTER_ASSERT(reporter, read_backing_pixel(dContext, tex, info, &pixel));
    REPORTER_ASSERT(reporter, pixel == kBaseline,
                    "baseline flush failed to resolve, got 0x%x", pixel);

    // 2. Re-wrap: this creates a *new* persistent MSAA color attachment that has never been
    //    written by any render pass in this test.
    sk_sp<SkSurface> surface = SkSurfaces::WrapBackendTexture(dContext,
                                                              tex,
                                                              kTopLeft_GrSurfaceOrigin,
                                                              /*sampleCnt=*/4,
                                                              kRGBA_8888_SkColorType,
                                                              nullptr,
                                                              nullptr);
    if (!surface) {
        return;
    }

    // 3. Record a full-surface draw so OpsTask::onMakeClosed() returns kTargetDirty and
    //    markMSAADirty() is called during closeAllTasks(). Force the flush to fail.
    FailingPreFlushCallback failCB(1);
    dContext->priv().addOnFlushCallbackObject(&failCB);

    surface->getCanvas()->clear(kIntended);
    GrSemaphoresSubmitted result = dContext->flush(surface.get(), GrFlushInfo{});
    dContext->submit(GrSyncCpu::kYes);

    GrDrawingManager* drawingManager = dContext->priv().drawingManager();
    drawingManager->testingOnly_removeOnFlushCallbackObject(&failCB);

    REPORTER_ASSERT(reporter, result == GrSemaphoresSubmitted::kNo,
                    "expected flush to report semaphores not submitted");

    // 4. Read back the single-sample backing texture.
    REPORTER_ASSERT(reporter, read_backing_pixel(dContext, tex, info, &pixel));

    // The recorded draw never executed, so kIntended should not appear.
    REPORTER_ASSERT(reporter, pixel != kIntended,
                    "flush failed but draw, somehow, occurred (got 0x%x)", pixel);

    // Since the flush failed the MSAA resolve step should not have occurred and the contents
    // of the backend texture should have remained at 'kBaseline'.
    REPORTER_ASSERT(reporter, pixel == kBaseline,
                    "Invalid resolve after a failed flush: expected 0x%x, actual 0x%x",
                    kBaseline, pixel);
}
