/*
 * Copyright 2017 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/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.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/GrContextThreadSafeProxy.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/GrRecordingContext.h"
#include "include/gpu/ganesh/GrTypes.h"
#include "include/gpu/ganesh/SkImageGanesh.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "include/private/chromium/GrDeferredDisplayList.h"
#include "include/private/chromium/GrDeferredDisplayListRecorder.h"
#include "include/private/chromium/GrPromiseImageTexture.h"
#include "include/private/chromium/GrSurfaceCharacterization.h"
#include "include/private/chromium/SkImageChromium.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrDeferredDisplayListPriv.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/GrTextureProxy.h"
#include "tests/CtsEnforcement.h"
#include "tests/Test.h"
#include "tools/ganesh/ProxyUtils.h"
#include "tools/gpu/BackendSurfaceFactory.h"
#include "tools/gpu/ManagedBackendTexture.h"

#include <array>
#include <cstddef>
#include <initializer_list>
#include <memory>
#include <utility>

class SkImage;
struct GrContextOptions;

#ifdef SK_GL
#include "include/gpu/ganesh/gl/GrGLBackendSurface.h"
#include "include/gpu/ganesh/gl/GrGLTypes.h"
#include "src/gpu/ganesh/gl/GrGLDefines.h"
#endif

#ifdef SK_VULKAN
#include "include/gpu/ganesh/vk/GrVkBackendSurface.h"
#include "include/gpu/ganesh/vk/GrVkTypes.h"
#include "include/private/chromium/GrVkSecondaryCBDrawContext.h"
#include "src/gpu/ganesh/vk/GrVkCaps.h"
#include "tools/gpu/vk/VkTestHelper.h"
#include <vulkan/vulkan_core.h>
#endif

static bool is_compatible(const GrSurfaceCharacterization& gsc, const GrBackendTexture& backendTex) {
    if (!gsc.isValid() || !backendTex.isValid()) {
        return false;
    }

    if (gsc.backendFormat() != backendTex.getBackendFormat()) {
        return false;
    }

    if (gsc.usesGLFBO0()) {
        // It is a backend texture so can't be wrapping FBO0
        return false;
    }

    if (gsc.vulkanSecondaryCBCompatible()) {
        return false;
    }

    if (gsc.vkRTSupportsInputAttachment()) {
        if (backendTex.backend() != GrBackendApi::kVulkan) {
            return false;
        }
#ifdef SK_VULKAN
        GrVkImageInfo vkInfo;
        if (!GrBackendTextures::GetVkImageInfo(backendTex, &vkInfo)) {
            return false;
        }
        if (!SkToBool(vkInfo.fImageUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
            return false;
        }
#endif  // SK_VULKAN
    }

    if (gsc.isMipMapped() && !backendTex.hasMipmaps()) {
        // backend texture is allowed to have mipmaps even if the characterization doesn't require
        // them.
        return false;
    }

    if (gsc.width() != backendTex.width() || gsc.height() != backendTex.height()) {
        return false;
    }

    if (gsc.isProtected() != skgpu::Protected(backendTex.isProtected())) {
        return false;
    }

    return true;
}

class SurfaceParameters {
public:
    static const int kNumParams      = 12;
    static const int kFBO0Count      = 9;
    static const int kVkSCBCount     = 11;

    SurfaceParameters(GrRecordingContext* rContext)
            : fBackend(rContext->backend())
            , fCanBeProtected(false)
            , fWidth(64)
            , fHeight(64)
            , fOrigin(kTopLeft_GrSurfaceOrigin)
            , fColorType(kRGBA_8888_SkColorType)
            , fColorSpace(SkColorSpace::MakeSRGB())
            , fSampleCount(1)
            , fSurfaceProps(0x0, kUnknown_SkPixelGeometry)
            , fShouldCreateMipMaps(skgpu::Mipmapped::kYes)
            , fUsesGLFBO0(false)
            , fIsTextureable(true)
            , fIsProtected(skgpu::Protected::kNo)
            , fVkRTSupportsInputAttachment(false)
            , fForVulkanSecondaryCommandBuffer(false) {
        const GrCaps* caps = rContext->priv().caps();

        if (rContext->backend() == GrBackendApi::kOpenGL ||
            rContext->backend() == GrBackendApi::kVulkan) {
            fCanBeProtected = caps->supportsProtectedContent();
            if (fCanBeProtected) {
                fIsProtected = skgpu::Protected::kYes;
            }
        }

        if (!caps->mipmapSupport()) {
            fShouldCreateMipMaps = skgpu::Mipmapped::kNo;
        }
    }

    int sampleCount() const { return fSampleCount; }

    void setColorType(SkColorType ct) { fColorType = ct; }
    SkColorType colorType() const { return fColorType; }
    void setColorSpace(sk_sp<SkColorSpace> cs) { fColorSpace = std::move(cs); }
    void disableTextureability() {
        fIsTextureable = false;
        fShouldCreateMipMaps = skgpu::Mipmapped::kNo;
    }
    void setShouldCreateMipMaps(skgpu::Mipmapped shouldCreateMipMaps) {
        fShouldCreateMipMaps = shouldCreateMipMaps;
    }
    void setVkRTInputAttachmentSupport(bool inputSupport) {
        fVkRTSupportsInputAttachment = inputSupport;
    }
    void setForVulkanSecondaryCommandBuffer(bool forVkSCB) {
        fForVulkanSecondaryCommandBuffer = forVkSCB;
    }

    // Modify the SurfaceParameters in just one way. Returns false if the requested modification had
    // no effect.
    bool modify(int i) {
        bool changed = false;
        auto set = [&changed](auto& var, auto value) {
            if (var != value) {
                changed = true;
            }
            var = value;
        };
        switch (i) {
        case 0:
            set(fWidth, 63);
            break;
        case 1:
            set(fHeight, 63);
            break;
        case 2:
            set(fOrigin, kBottomLeft_GrSurfaceOrigin);
            break;
        case 3:
            set(fColorType, kRGBA_F16_SkColorType);
            break;
        case 4:
            // This just needs to be a colorSpace different from that returned by MakeSRGB().
            // In this case we just change the gamut.
            set(fColorSpace, SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
                                                   SkNamedGamut::kAdobeRGB));
            break;
        case 5:
            set(fSampleCount, 4);
            break;
        case 6:
            set(fSurfaceProps, SkSurfaceProps(0x0, kRGB_H_SkPixelGeometry));
            break;
        case 7:
            set(fSurfaceProps, SkSurfaceProps(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
                                              kUnknown_SkPixelGeometry));
            break;
        case 8:
            set(fShouldCreateMipMaps, skgpu::Mipmapped::kNo);
            break;
        case 9:
            if (GrBackendApi::kOpenGL == fBackend) {
                set(fUsesGLFBO0, true);
                set(fShouldCreateMipMaps,
                    skgpu::Mipmapped::kNo);  // needs to changed in tandem w/ textureability
                set(fIsTextureable, false);
            }
            break;
        case 10:
            set(fShouldCreateMipMaps,
                skgpu::Mipmapped::kNo);  // needs to changed in tandem w/ textureability
            set(fIsTextureable, false);
            break;
        case 11:
            if (GrBackendApi::kVulkan == fBackend) {
                set(fForVulkanSecondaryCommandBuffer, true);
                set(fUsesGLFBO0, false);
                set(fShouldCreateMipMaps,
                    skgpu::Mipmapped::kNo);  // needs to changed in tandem w/ textureability
                set(fIsTextureable, false);
                set(fVkRTSupportsInputAttachment, false);
            }
            break;
        }
        return changed;
    }

    GrSurfaceCharacterization createCharacterization(GrDirectContext* dContext) const {
        size_t maxResourceBytes = dContext->getResourceCacheLimit();

        if (!dContext->colorTypeSupportedAsSurface(fColorType)) {
            return GrSurfaceCharacterization();
        }

        // Note that Ganesh doesn't make use of the SkImageInfo's alphaType
        SkImageInfo ii = SkImageInfo::Make(fWidth, fHeight, fColorType,
                                           kPremul_SkAlphaType, fColorSpace);

        GrBackendFormat backendFormat = dContext->defaultBackendFormat(fColorType,
                                                                       GrRenderable::kYes);
        if (!backendFormat.isValid()) {
            return GrSurfaceCharacterization();
        }

        GrSurfaceCharacterization c = dContext->threadSafeProxy()->createCharacterization(
                                                maxResourceBytes, ii, backendFormat, fSampleCount,
                                                fOrigin, fSurfaceProps, fShouldCreateMipMaps,
                                                fUsesGLFBO0, fIsTextureable, fIsProtected,
                                                fVkRTSupportsInputAttachment,
                                                fForVulkanSecondaryCommandBuffer);
        return c;
    }

    // Create a DDL whose characterization captures the current settings
    sk_sp<GrDeferredDisplayList> createDDL(GrDirectContext* dContext) const {
        GrSurfaceCharacterization c = this->createCharacterization(dContext);
        SkAssertResult(c.isValid());

        GrDeferredDisplayListRecorder r(c);
        SkCanvas* canvas = r.getCanvas();
        if (!canvas) {
            return nullptr;
        }

        canvas->drawRect(SkRect::MakeXYWH(10, 10, 10, 10), SkPaint());
        return r.detach();
    }

    // Create the surface with the current set of parameters
    sk_sp<SkSurface> make(GrDirectContext* dContext) const {
        const GrSurfaceCharacterization c = this->createCharacterization(dContext);

#ifdef SK_GL
        if (fUsesGLFBO0) {
            if (GrBackendApi::kOpenGL != dContext->backend()) {
                return nullptr;
            }

            GrGLFramebufferInfo fboInfo;
            fboInfo.fFBOID = 0;
            fboInfo.fFormat = GR_GL_RGBA8;
            fboInfo.fProtected = fIsProtected;
            static constexpr int kStencilBits = 8;
            GrBackendRenderTarget backendRT =
                    GrBackendRenderTargets::MakeGL(fWidth, fHeight, 1, kStencilBits, fboInfo);

            if (!backendRT.isValid()) {
                return nullptr;
            }

            sk_sp<SkSurface> result = SkSurfaces::WrapBackendRenderTarget(
                    dContext, backendRT, fOrigin, fColorType, fColorSpace, &fSurfaceProps);
            SkASSERT(result->isCompatible(c));
            return result;
        }
#endif

        // We can't make SkSurfaces for vulkan secondary command buffers.
        if (fForVulkanSecondaryCommandBuffer) {
            return nullptr;
        }

        sk_sp<SkSurface> surface;
        if (fIsTextureable) {
            surface = sk_gpu_test::MakeBackendTextureSurface(dContext,
                                                             {fWidth, fHeight},
                                                             fOrigin,
                                                             fSampleCount,
                                                             fColorType,
                                                             fColorSpace,
                                                             fShouldCreateMipMaps,
                                                             fIsProtected,
                                                             &fSurfaceProps);
        } else {
            // Create a surface w/ the current parameters but make it non-textureable
            SkASSERT(fShouldCreateMipMaps == skgpu::Mipmapped::kNo);
            surface = sk_gpu_test::MakeBackendRenderTargetSurface(dContext,
                                                                  {fWidth, fHeight},
                                                                  fOrigin,
                                                                  fSampleCount,
                                                                  fColorType,
                                                                  fColorSpace,
                                                                  fIsProtected,
                                                                  &fSurfaceProps);
        }

        if (!surface) {
            SkASSERT(!c.isValid());
            return nullptr;
        }

        GrBackendTexture texture = SkSurfaces::GetBackendTexture(
                surface.get(), SkSurfaces::BackendHandleAccess::kFlushRead);
        if (texture.isValid()) {
            SkASSERT(is_compatible(c, texture));
        }

        SkASSERT(c.isValid());
        SkASSERT(surface->isCompatible(c));
        return surface;
    }

#ifdef SK_VULKAN
    sk_sp<GrVkSecondaryCBDrawContext> makeVkSCB(GrDirectContext* dContext) {
        const GrSurfaceCharacterization c = this->createCharacterization(dContext);
        SkImageInfo imageInfo = SkImageInfo::Make({fWidth, fHeight},
                                                  {fColorType, kPremul_SkAlphaType, fColorSpace});
        GrVkDrawableInfo vkInfo;
        // putting in a bunch of placeholder values here
        vkInfo.fSecondaryCommandBuffer = (VkCommandBuffer)1;
        vkInfo.fColorAttachmentIndex = 0;
        vkInfo.fCompatibleRenderPass = (VkRenderPass)1;
        vkInfo.fFormat = VK_FORMAT_R8G8B8A8_UNORM;
        vkInfo.fDrawBounds = nullptr;

        return GrVkSecondaryCBDrawContext::Make(dContext, imageInfo, vkInfo, &fSurfaceProps);
    }
#endif

private:
    GrBackendApi        fBackend;
    bool                fCanBeProtected;

    int                 fWidth;
    int                 fHeight;
    GrSurfaceOrigin     fOrigin;
    SkColorType         fColorType;
    sk_sp<SkColorSpace> fColorSpace;
    int                 fSampleCount;
    SkSurfaceProps      fSurfaceProps;
    skgpu::Mipmapped fShouldCreateMipMaps;
    bool                fUsesGLFBO0;
    bool                fIsTextureable;
    skgpu::Protected fIsProtected;
    bool                fVkRTSupportsInputAttachment;
    bool                fForVulkanSecondaryCommandBuffer;
};

// Test out operator== && operator!=
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(DDLOperatorEqTest,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kNever) {
    auto context = ctxInfo.directContext();

    for (int i = -1; i < SurfaceParameters::kNumParams; ++i) {
        SurfaceParameters params1(context);
        bool didModify1 = i >= 0 && params1.modify(i);

        GrSurfaceCharacterization char1 = params1.createCharacterization(context);
        if (!char1.isValid()) {
            continue;  // can happen on some platforms (ChromeOS)
        }

        for (int j = -1; j < SurfaceParameters::kNumParams; ++j) {
            SurfaceParameters params2(context);
            bool didModify2 = j >= 0 && params2.modify(j);

            GrSurfaceCharacterization char2 = params2.createCharacterization(context);
            if (!char2.isValid()) {
                continue;  // can happen on some platforms (ChromeOS)
            }

            if (i == j || (!didModify1 && !didModify2)) {
                REPORTER_ASSERT(reporter, char1 == char2);
            } else {
                REPORTER_ASSERT(reporter, char1 != char2);
            }
        }
    }

    {
        SurfaceParameters params(context);

        GrSurfaceCharacterization valid = params.createCharacterization(context);
        SkASSERT(valid.isValid());

        GrSurfaceCharacterization inval1, inval2;
        SkASSERT(!inval1.isValid() && !inval2.isValid());

        REPORTER_ASSERT(reporter, inval1 != inval2);
        REPORTER_ASSERT(reporter, valid != inval1);
        REPORTER_ASSERT(reporter, inval1 != valid);
    }
}

////////////////////////////////////////////////////////////////////////////////
// This tests GrSurfaceCharacterization/SkSurface compatibility
void DDLSurfaceCharacterizationTestImpl(GrDirectContext* dContext, skiatest::Reporter* reporter) {
    // Create a bitmap that we can readback into
    SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
                                              kPremul_SkAlphaType);
    SkBitmap bitmap;
    bitmap.allocPixels(imageInfo);

    sk_sp<GrDeferredDisplayList> ddl;

    // First, create a DDL using the stock SkSurface parameters
    {
        SurfaceParameters params(dContext);
        if (dContext->backend() == GrBackendApi::kVulkan) {
            params.setVkRTInputAttachmentSupport(true);
        }
        ddl = params.createDDL(dContext);
        SkAssertResult(ddl);

        // The DDL should draw into an SkSurface created with the same parameters
        sk_sp<SkSurface> s = params.make(dContext);
        if (!s) {
            return;
        }

        REPORTER_ASSERT(reporter, skgpu::ganesh::DrawDDL(s, ddl));
        s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);

        dContext->flush();
    }

    // Then, alter each parameter in turn and check that the DDL & surface are incompatible
    for (int i = 0; i < SurfaceParameters::kNumParams; ++i) {
        SurfaceParameters params(dContext);
        if (!params.modify(i)) {
            continue;
        }

        sk_sp<SkSurface> s = params.make(dContext);
        if (!s) {
            continue;
        }

        REPORTER_ASSERT(reporter, !skgpu::ganesh::DrawDDL(s, ddl),
                        "DDLSurfaceCharacterizationTest failed on parameter: %d\n", i);
        dContext->flush();
    }

    // Next test the compatibility of resource cache parameters
    {
        const SurfaceParameters params(dContext);

        sk_sp<SkSurface> s = params.make(dContext);

        size_t maxResourceBytes = dContext->getResourceCacheLimit();

        dContext->setResourceCacheLimit(maxResourceBytes/2);
        REPORTER_ASSERT(reporter, !skgpu::ganesh::DrawDDL(s, ddl));

        // DDL TODO: once proxies/ops can be de-instantiated we can re-enable these tests.
        // For now, DDLs are drawn once.
#if 0
        // resource limits >= those at characterization time are accepted
        context->setResourceCacheLimits(2*maxResourceCount, maxResourceBytes);
        REPORTER_ASSERT(reporter, skgpu::ganesh::DrawDDL(s, ddl));
        s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);

        context->setResourceCacheLimits(maxResourceCount, 2*maxResourceBytes);
        REPORTER_ASSERT(reporter, skgpu::ganesh::DrawDDL(s, ddl));
        s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);

        context->setResourceCacheLimits(maxResourceCount, maxResourceBytes);
        REPORTER_ASSERT(reporter, skgpu::ganesh::DrawDDL(s, ddl));
        s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
#endif

        dContext->flush();
    }

    // Test that the textureability of the DDL characterization can block a DDL draw
    {
        SurfaceParameters params(dContext);
        params.disableTextureability();

        sk_sp<SkSurface> s = params.make(dContext);
        if (s) {
            // bc the DDL was made w/ textureability
            REPORTER_ASSERT(reporter, !skgpu::ganesh::DrawDDL(s, ddl));

            dContext->flush();
        }
    }

    // Make sure non-GPU-backed surfaces fail characterization
    {
        SkImageInfo ii = SkImageInfo::MakeN32(64, 64, kOpaque_SkAlphaType);

        sk_sp<SkSurface> rasterSurface = SkSurfaces::Raster(ii);
        GrSurfaceCharacterization c;
        REPORTER_ASSERT(reporter, !rasterSurface->characterize(&c));
    }

    // Exercise the createResized method
    {
        SurfaceParameters params(dContext);

        sk_sp<SkSurface> s = params.make(dContext);
        if (!s) {
            return;
        }

        GrSurfaceCharacterization char0;
        SkAssertResult(s->characterize(&char0));

        // Too small
        GrSurfaceCharacterization char1 = char0.createResized(-1, -1);
        REPORTER_ASSERT(reporter, !char1.isValid());

        // Too large
        GrSurfaceCharacterization char2 = char0.createResized(1000000, 32);
        REPORTER_ASSERT(reporter, !char2.isValid());

        // Just right
        GrSurfaceCharacterization char3 = char0.createResized(32, 32);
        REPORTER_ASSERT(reporter, char3.isValid());
        REPORTER_ASSERT(reporter, 32 == char3.width());
        REPORTER_ASSERT(reporter, 32 == char3.height());
    }

    // Exercise the createColorSpace method
    {
        SurfaceParameters params(dContext);

        sk_sp<SkSurface> s = params.make(dContext);
        if (!s) {
            return;
        }

        GrSurfaceCharacterization char0;
        SkAssertResult(s->characterize(&char0));

        // The default params create an sRGB color space
        REPORTER_ASSERT(reporter, char0.colorSpace()->isSRGB());
        REPORTER_ASSERT(reporter, !char0.colorSpace()->gammaIsLinear());

        {
            sk_sp<SkColorSpace> newCS = SkColorSpace::MakeSRGBLinear();

            GrSurfaceCharacterization char1 = char0.createColorSpace(std::move(newCS));
            REPORTER_ASSERT(reporter, char1.isValid());
            REPORTER_ASSERT(reporter, !char1.colorSpace()->isSRGB());
            REPORTER_ASSERT(reporter, char1.colorSpace()->gammaIsLinear());
        }

        {
            GrSurfaceCharacterization char2 = char0.createColorSpace(nullptr);
            REPORTER_ASSERT(reporter, char2.isValid());
            REPORTER_ASSERT(reporter, !char2.colorSpace());
        }

        {
            sk_sp<SkColorSpace> newCS = SkColorSpace::MakeSRGBLinear();

            GrSurfaceCharacterization invalid;
            REPORTER_ASSERT(reporter, !invalid.isValid());
            GrSurfaceCharacterization stillInvalid = invalid.createColorSpace(std::move(newCS));
            REPORTER_ASSERT(reporter, !stillInvalid.isValid());
        }
    }

    // Exercise the createBackendFormat method
    {
        SurfaceParameters params(dContext);

        sk_sp<SkSurface> s = params.make(dContext);
        if (!s) {
            return;
        }

        GrSurfaceCharacterization char0;
        SkAssertResult(s->characterize(&char0));

        // The default params create a renderable RGBA8 surface
        auto originalBackendFormat = dContext->defaultBackendFormat(kRGBA_8888_SkColorType,
                                                                    GrRenderable::kYes);
        REPORTER_ASSERT(reporter, originalBackendFormat.isValid());
        REPORTER_ASSERT(reporter, char0.backendFormat() == originalBackendFormat);

        auto newBackendFormat = dContext->defaultBackendFormat(kRGB_565_SkColorType,
                                                               GrRenderable::kYes);

        if (newBackendFormat.isValid()) {
            GrSurfaceCharacterization char1 = char0.createBackendFormat(kRGB_565_SkColorType,
                                                                        newBackendFormat);
            REPORTER_ASSERT(reporter, char1.isValid());
            REPORTER_ASSERT(reporter, char1.backendFormat() == newBackendFormat);

            GrSurfaceCharacterization invalid;
            REPORTER_ASSERT(reporter, !invalid.isValid());
            auto stillInvalid = invalid.createBackendFormat(kRGB_565_SkColorType,
                                                            newBackendFormat);
            REPORTER_ASSERT(reporter, !stillInvalid.isValid());
        }
    }

    // Exercise the createFBO0 method
    if (dContext->backend() == GrBackendApi::kOpenGL) {
        SurfaceParameters params(dContext);
        // If the original characterization is textureable then we will fail trying to make an
        // FBO0 characterization
        params.disableTextureability();

        sk_sp<SkSurface> s = params.make(dContext);
        if (!s) {
            return;
        }

        GrSurfaceCharacterization char0;
        SkAssertResult(s->characterize(&char0));

        // The default params create a non-FBO0 surface
        REPORTER_ASSERT(reporter, !char0.usesGLFBO0());

        {
            GrSurfaceCharacterization char1 = char0.createFBO0(true);
            REPORTER_ASSERT(reporter, char1.isValid());
            REPORTER_ASSERT(reporter, char1.usesGLFBO0());
        }

        {
            GrSurfaceCharacterization invalid;
            REPORTER_ASSERT(reporter, !invalid.isValid());
            GrSurfaceCharacterization stillInvalid = invalid.createFBO0(true);
            REPORTER_ASSERT(reporter, !stillInvalid.isValid());
        }
    }
}

#ifdef SK_GL

// Test out the surface compatibility checks regarding FBO0-ness. This test constructs
// two parallel arrays of characterizations and surfaces in the order:
//    FBO0 w/ MSAA, FBO0 w/o MSAA, not-FBO0 w/ MSAA, not-FBO0 w/o MSAA
// and then tries all sixteen combinations to check the expected compatibility.
// Note: this is a GL-only test
DEF_GANESH_TEST_FOR_GL_CONTEXT(CharacterizationFBO0nessTest,
                               reporter,
                               ctxInfo,
                               CtsEnforcement::kApiLevel_T) {
    auto context = ctxInfo.directContext();
    const GrCaps* caps = context->priv().caps();
    sk_sp<GrContextThreadSafeProxy> proxy = context->threadSafeProxy();
    const size_t resourceCacheLimit = context->getResourceCacheLimit();

    GrBackendFormat format = GrBackendFormats::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_2D);

    int availableSamples = caps->getRenderTargetSampleCount(4, format);
    if (availableSamples <= 1) {
        // This context doesn't support MSAA for RGBA8
        return;
    }

    SkImageInfo ii = SkImageInfo::Make({ 128, 128 }, kRGBA_8888_SkColorType, kPremul_SkAlphaType);

    static constexpr int kStencilBits = 8;
    static constexpr bool kNotTextureable = false;
    const SkSurfaceProps surfaceProps(0x0, kRGB_H_SkPixelGeometry);

    // Rows are characterizations and columns are surfaces
    static constexpr std::array<std::array<bool, 4>, 4> kExpectedCompatibility = {{
                    //  FBO0 & MSAA, FBO0 & not-MSAA, not-FBO0 & MSAA, not-FBO0 & not-MSAA
/* FBO0 & MSAA     */ { true,        false,           false,           false },
/* FBO0 & not-MSAA */ { false,       true,            false,           true  },
/* not-FBO0 & MSAA */ { false,       false,           true,            false },
/* not-FBO0 & not- */ { false,       false,           false,           true  },
    }};

    std::array<GrSurfaceCharacterization, 4> characterizations;
    std::array<sk_sp<SkSurface>, 4> surfaces;

    int index = 0;
    for (bool isFBO0 : { true, false }) {
        for (int numSamples : { availableSamples, 1 }) {
            characterizations[index] = proxy->createCharacterization(resourceCacheLimit,
                                                                     ii,
                                                                     format,
                                                                     numSamples,
                                                                     kTopLeft_GrSurfaceOrigin,
                                                                     surfaceProps,
                                                                     skgpu::Mipmapped::kNo,
                                                                     isFBO0,
                                                                     kNotTextureable);
            SkASSERT(characterizations[index].sampleCount() == numSamples);
            SkASSERT(characterizations[index].usesGLFBO0() == isFBO0);

            GrGLFramebufferInfo fboInfo{ isFBO0 ? 0 : (GrGLuint) 1, GR_GL_RGBA8 };
            GrBackendRenderTarget backendRT =
                    GrBackendRenderTargets::MakeGL(128, 128, numSamples, kStencilBits, fboInfo);
            SkAssertResult(backendRT.isValid());

            surfaces[index] = SkSurfaces::WrapBackendRenderTarget(context,
                                                                  backendRT,
                                                                  kTopLeft_GrSurfaceOrigin,
                                                                  kRGBA_8888_SkColorType,
                                                                  nullptr,
                                                                  &surfaceProps);
            ++index;
        }
    }

    for (int c = 0; c < 4; ++c) {
        for (int s = 0; s < 4; ++s) {
            REPORTER_ASSERT(reporter,
                            kExpectedCompatibility[c][s] ==
                                                 surfaces[s]->isCompatible(characterizations[c]));
        }
    }
}
#endif

#ifdef SK_VULKAN
DEF_GANESH_TEST_FOR_VULKAN_CONTEXT(CharacterizationVkSCBnessTest,
                                   reporter,
                                   ctxInfo,
                                   CtsEnforcement::kApiLevel_T) {
    auto dContext = ctxInfo.directContext();

    SurfaceParameters params(dContext);
    params.modify(SurfaceParameters::kVkSCBCount);
    GrSurfaceCharacterization characterization = params.createCharacterization(dContext);
    REPORTER_ASSERT(reporter, characterization.isValid());

    sk_sp<GrDeferredDisplayList> ddl = params.createDDL(dContext);
    REPORTER_ASSERT(reporter, ddl.get());

    sk_sp<GrVkSecondaryCBDrawContext> scbDrawContext = params.makeVkSCB(dContext);
    REPORTER_ASSERT(reporter, scbDrawContext->isCompatible(characterization));

    scbDrawContext->releaseResources();
}
#endif

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(DDLSurfaceCharacterizationTest,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kNever) {
    auto context = ctxInfo.directContext();

    DDLSurfaceCharacterizationTestImpl(context, reporter);
}

#if defined(SK_VULKAN)
DEF_GANESH_TEST(VkProtectedContext_DDLSurfaceCharacterizationTest,
                reporter,
                ctxInfo,
                CtsEnforcement::kNever) {
    std::unique_ptr<VkTestHelper> helper = VkTestHelper::Make(skiatest::TestType::kGanesh,
                                                              /* isProtected= */ true);
    if (!helper) {
        return;
    }

    REPORTER_ASSERT(reporter, helper->isValid());

    DDLSurfaceCharacterizationTestImpl(helper->directContext(), reporter);
}
#endif

// Test that a DDL created w/o textureability can be replayed into both a textureable and
// non-textureable destination. Note that DDLSurfaceCharacterizationTest tests that a
// textureable DDL cannot be played into a non-textureable destination but can be replayed
// into a textureable destination.
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(DDLNonTextureabilityTest,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kNever) {
    auto context = ctxInfo.directContext();

    // Create a bitmap that we can readback into
    SkImageInfo imageInfo = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType,
                                              kPremul_SkAlphaType);
    SkBitmap bitmap;
    bitmap.allocPixels(imageInfo);

    for (bool textureability : { true, false }) {
        sk_sp<GrDeferredDisplayList> ddl;

        // First, create a DDL w/o textureability (and thus no mipmaps). TODO: once we have
        // reusable DDLs, move this outside of the loop.
        {
            SurfaceParameters params(context);
            params.disableTextureability();
            if (context->backend() == GrBackendApi::kVulkan) {
                params.setVkRTInputAttachmentSupport(true);
            }

            ddl = params.createDDL(context);
            SkAssertResult(ddl);
        }

        // Then verify it can draw into either flavor of destination
        SurfaceParameters params(context);
        if (!textureability) {
            params.disableTextureability();
        }
        if (context->backend() == GrBackendApi::kVulkan) {
            params.setVkRTInputAttachmentSupport(true);
        }

        sk_sp<SkSurface> s = params.make(context);
        if (!s) {
            continue;
        }

        REPORTER_ASSERT(reporter, skgpu::ganesh::DrawDDL(s, ddl));
        s->readPixels(imageInfo, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);

        context->flush();
    }
}

static void test_make_render_target(skiatest::Reporter* reporter,
                                    GrDirectContext* dContext,
                                    const SurfaceParameters& params) {
    {
        const GrSurfaceCharacterization c = params.createCharacterization(dContext);

        if (!c.isValid()) {
            sk_sp<SkSurface> tmp = params.make(dContext);
            // If we couldn't characterize the surface we shouldn't be able to create it either
            REPORTER_ASSERT(reporter, !tmp);
            return;
        }
    }

    const GrSurfaceCharacterization c = params.createCharacterization(dContext);
    {
        sk_sp<SkSurface> s = params.make(dContext);
        REPORTER_ASSERT(reporter, s);
        if (!s) {
            REPORTER_ASSERT(reporter, !c.isValid());
            return;
        }

        REPORTER_ASSERT(reporter, c.isValid());
        GrBackendTexture backend =
                SkSurfaces::GetBackendTexture(s.get(), SkSurfaces::BackendHandleAccess::kFlushRead);
        if (backend.isValid()) {
            REPORTER_ASSERT(reporter, is_compatible(c, backend));
        }
        REPORTER_ASSERT(reporter, s->isCompatible(c));
        // Note that we're leaving 'backend' live here
    }

    // Make an SkSurface from scratch
    {
        sk_sp<SkSurface> s = SkSurfaces::RenderTarget(dContext, c, skgpu::Budgeted::kYes);
        REPORTER_ASSERT(reporter, s);
        REPORTER_ASSERT(reporter, s->isCompatible(c));
    }
}

////////////////////////////////////////////////////////////////////////////////
// This tests the SkSurfaces::RenderTarget variants that take a GrSurfaceCharacterization.
// In particular, the SkSurface, backendTexture and GrSurfaceCharacterization
// should always be compatible.
void DDLMakeRenderTargetTestImpl(GrDirectContext* dContext, skiatest::Reporter* reporter) {
    for (int i = -1; i < SurfaceParameters::kNumParams; ++i) {
        if (i == SurfaceParameters::kFBO0Count || i == SurfaceParameters::kVkSCBCount) {
            // MakeRenderTarget doesn't support FBO0 or vulkan secondary command buffers
            continue;
        }

        SurfaceParameters params(dContext);
        if (i >= 0 && !params.modify(i)) {
            continue;
        }

        test_make_render_target(reporter, dContext, params);
    }
}

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(DDLMakeRenderTargetTest,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kNever) {
    auto context = ctxInfo.directContext();

    DDLMakeRenderTargetTestImpl(context, reporter);
}

#if defined(SK_VULKAN)

DEF_GANESH_TEST(VkProtectedContext_DDLMakeRenderTargetTest,
                reporter,
                ctxInfo,
                CtsEnforcement::kNever) {
    std::unique_ptr<VkTestHelper> helper = VkTestHelper::Make(skiatest::TestType::kGanesh,
                                                              /* isProtected= */ true);
    if (!helper) {
        return;
    }
    REPORTER_ASSERT(reporter, helper->isValid());

    DDLMakeRenderTargetTestImpl(helper->directContext(), reporter);
}
#endif

////////////////////////////////////////////////////////////////////////////////
static constexpr int kSize = 8;

struct TextureReleaseChecker {
    TextureReleaseChecker() : fReleaseCount(0) {}
    int fReleaseCount;
    static void Release(void* self) {
        static_cast<TextureReleaseChecker*>(self)->fReleaseCount++;
    }
};

enum class DDLStage { kMakeImage, kDrawImage, kDetach, kDrawDDL };

// This tests the ability to create and use wrapped textures in a DDL world
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(DDLWrapBackendTest,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kNever) {
    auto dContext = ctxInfo.directContext();

    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(dContext,
                                                                    kSize,
                                                                    kSize,
                                                                    kRGBA_8888_SkColorType,
                                                                    skgpu::Mipmapped::kNo,
                                                                    GrRenderable::kNo,
                                                                    skgpu::Protected::kNo);
    if (!mbet) {
        return;
    }

    SurfaceParameters params(dContext);

    sk_sp<SkSurface> s = params.make(dContext);
    if (!s) {
        return;
    }

    GrSurfaceCharacterization c;
    SkAssertResult(s->characterize(&c));

    GrDeferredDisplayListRecorder recorder(c);

    SkCanvas* canvas = recorder.getCanvas();
    SkASSERT(canvas);

    auto rContext = canvas->recordingContext();
    if (!rContext) {
        return;
    }

    // Wrapped Backend Textures are not supported in DDL
    TextureReleaseChecker releaseChecker;
    sk_sp<SkImage> image = SkImages::BorrowTextureFrom(
            rContext,
            mbet->texture(),
            kTopLeft_GrSurfaceOrigin,
            kRGBA_8888_SkColorType,
            kPremul_SkAlphaType,
            nullptr,
            sk_gpu_test::ManagedBackendTexture::ReleaseProc,
            mbet->releaseContext(TextureReleaseChecker::Release, &releaseChecker));
    REPORTER_ASSERT(reporter, !image);
}

////////////////////////////////////////////////////////////////////////////////
// Test out the behavior of an invalid DDLRecorder
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(DDLInvalidRecorder,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kNever) {
    auto dContext = ctxInfo.directContext();

    {
        SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
        sk_sp<SkSurface> s = SkSurfaces::RenderTarget(dContext, skgpu::Budgeted::kNo, ii);

        GrSurfaceCharacterization characterization;
        SkAssertResult(s->characterize(&characterization));

        // never calling getCanvas means the backing surface is never allocated
        GrDeferredDisplayListRecorder recorder(characterization);
    }

    {
        GrSurfaceCharacterization invalid;

        GrDeferredDisplayListRecorder recorder(invalid);

        const GrSurfaceCharacterization c = recorder.characterization();
        REPORTER_ASSERT(reporter, !c.isValid());
        REPORTER_ASSERT(reporter, !recorder.getCanvas());
        REPORTER_ASSERT(reporter, !recorder.detach());
    }
}

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(DDLCreateCharacterizationFailures,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kNever) {
    using namespace skgpu;

    auto dContext = ctxInfo.directContext();
    size_t maxResourceBytes = dContext->getResourceCacheLimit();
    auto proxy = dContext->threadSafeProxy().get();

    Protected isProtected = Protected(dContext->priv().caps()->supportsProtectedContent());

    auto check_create_fails = [proxy, reporter, maxResourceBytes](
                                      const GrBackendFormat& backendFormat,
                                      int width,
                                      int height,
                                      SkColorType ct,
                                      bool willUseGLFBO0,
                                      bool isTextureable,
                                      Protected prot,
                                      bool vkRTSupportsInputAttachment,
                                      bool forVulkanSecondaryCommandBuffer) {
        const SkSurfaceProps surfaceProps(0x0, kRGB_H_SkPixelGeometry);

        SkImageInfo ii = SkImageInfo::Make(width, height, ct,
                                           kPremul_SkAlphaType, nullptr);

        GrSurfaceCharacterization c =
                proxy->createCharacterization(maxResourceBytes,
                                              ii,
                                              backendFormat,
                                              1,
                                              kBottomLeft_GrSurfaceOrigin,
                                              surfaceProps,
                                              Mipmapped::kNo,
                                              willUseGLFBO0,
                                              isTextureable,
                                              prot,
                                              vkRTSupportsInputAttachment,
                                              forVulkanSecondaryCommandBuffer);
        REPORTER_ASSERT(reporter, !c.isValid());
    };

    GrBackendFormat goodBackendFormat = dContext->defaultBackendFormat(kRGBA_8888_SkColorType,
                                                                       GrRenderable::kYes);
    SkASSERT(goodBackendFormat.isValid());

    GrBackendFormat badBackendFormat;
    SkASSERT(!badBackendFormat.isValid());

    SkColorType kGoodCT = kRGBA_8888_SkColorType;
    SkColorType kBadCT = kUnknown_SkColorType;

    static const bool kIsTextureable = true;
    static const bool kIsNotTextureable = false;

    static const bool kGoodUseFBO0 = false;
    static const bool kBadUseFBO0 = true;

    static const bool kGoodVkInputAttachment = false;
    static const bool kBadVkInputAttachment = true;

    static const bool kGoodForVkSCB = false;
    static const bool kBadForVkSCB = true;

    int goodWidth = 64;
    int goodHeight = 64;
    int badWidths[] = { 0, 1048576 };
    int badHeights[] = { 0, 1048576 };


    // In each of the check_create_fails calls there is one bad parameter that should cause the
    // creation of the characterization to fail.
    check_create_fails(goodBackendFormat, goodWidth, badHeights[0], kGoodCT, kGoodUseFBO0,
                       kIsTextureable, isProtected, kGoodVkInputAttachment, kGoodForVkSCB);
    check_create_fails(goodBackendFormat, goodWidth, badHeights[1], kGoodCT, kGoodUseFBO0,
                       kIsTextureable, isProtected, kGoodVkInputAttachment, kGoodForVkSCB);
    check_create_fails(goodBackendFormat, badWidths[0], goodHeight, kGoodCT, kGoodUseFBO0,
                       kIsTextureable, isProtected, kGoodVkInputAttachment, kGoodForVkSCB);
    check_create_fails(goodBackendFormat, badWidths[1], goodHeight, kGoodCT, kGoodUseFBO0,
                       kIsTextureable, isProtected, kGoodVkInputAttachment, kGoodForVkSCB);
    check_create_fails(badBackendFormat, goodWidth, goodHeight, kGoodCT, kGoodUseFBO0,
                       kIsTextureable, isProtected, kGoodVkInputAttachment, kGoodForVkSCB);
    check_create_fails(goodBackendFormat, goodWidth, goodHeight, kBadCT, kGoodUseFBO0,
                       kIsTextureable, isProtected, kGoodVkInputAttachment, kGoodForVkSCB);
    // This fails because we always try to make a characterization that is textureable and we can't
    // have UseFBO0 be true and textureable.
    check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kBadUseFBO0,
                       kIsTextureable, isProtected, kGoodVkInputAttachment, kGoodForVkSCB);
    if (dContext->backend() == GrBackendApi::kVulkan) {
        // The following fails because forVulkanSecondaryCommandBuffer is true and
        // isTextureable is true. This is not a legal combination.
        check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kGoodUseFBO0,
                           kIsTextureable, isProtected, kGoodVkInputAttachment, kBadForVkSCB);
        // The following fails because forVulkanSecondaryCommandBuffer is true and
        // vkRTSupportsInputAttachment is true. This is not a legal combination.
        check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kGoodUseFBO0,
                           kIsNotTextureable, isProtected, kBadVkInputAttachment,
                           kBadForVkSCB);
        // The following fails because forVulkanSecondaryCommandBuffer is true and
        // willUseGLFBO0 is true. This is not a legal combination.
        check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kBadUseFBO0,
                           kIsNotTextureable, isProtected, kGoodVkInputAttachment,
                           kBadForVkSCB);
    } else {
        // The following set vulkan only flags on non vulkan backends.
        check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kGoodUseFBO0,
                           kIsTextureable, isProtected, kBadVkInputAttachment, kGoodForVkSCB);
        check_create_fails(goodBackendFormat, goodWidth, goodHeight, kGoodCT, kGoodUseFBO0,
                           kIsNotTextureable, isProtected, kGoodVkInputAttachment,
                           kBadForVkSCB);
    }
}

////////////////////////////////////////////////////////////////////////////////
// Test that flushing a DDL via SkSurface::flush works

struct FulfillInfo {
    sk_sp<GrPromiseImageTexture> fTex;
    bool fFulfilled = false;
    bool fReleased  = false;
};

static sk_sp<GrPromiseImageTexture> tracking_fulfill_proc(void* context) {
    FulfillInfo* info = (FulfillInfo*) context;
    info->fFulfilled = true;
    return info->fTex;
}

static void tracking_release_proc(void* context) {
    FulfillInfo* info = (FulfillInfo*) context;
    info->fReleased = true;
}

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(DDLSkSurfaceFlush,
                                       reporter,
                                       ctxInfo,
                                       CtsEnforcement::kNever) {
    using namespace skgpu;

    auto context = ctxInfo.directContext();

    Protected isProtected = Protected(context->priv().caps()->supportsProtectedContent());

    SkImageInfo ii = SkImageInfo::Make(32, 32, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
    sk_sp<SkSurface> s = SkSurfaces::RenderTarget(context, Budgeted::kNo, ii);

    GrSurfaceCharacterization characterization;
    SkAssertResult(s->characterize(&characterization));

    auto mbet = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(context, ii,
                                                                 Mipmapped::kNo,
                                                                 Renderable::kNo,
                                                                 isProtected);
    if (!mbet) {
        ERRORF(reporter, "Could not make texture.");
        return;
    }

    FulfillInfo fulfillInfo;
    fulfillInfo.fTex = GrPromiseImageTexture::Make(mbet->texture());

    sk_sp<GrDeferredDisplayList> ddl;

    {
        GrDeferredDisplayListRecorder recorder(characterization);

        GrBackendFormat format = context->defaultBackendFormat(kRGBA_8888_SkColorType,
                                                               GrRenderable::kNo);
        SkASSERT(format.isValid());

        SkCanvas* canvas = recorder.getCanvas();

        sk_sp<SkImage> promiseImage =
                SkImages::PromiseTextureFrom(canvas->recordingContext()->threadSafeProxy(),
                                             format,
                                             SkISize::Make(32, 32),
                                             skgpu::Mipmapped::kNo,
                                             kTopLeft_GrSurfaceOrigin,
                                             kRGBA_8888_SkColorType,
                                             kPremul_SkAlphaType,
                                             nullptr,
                                             tracking_fulfill_proc,
                                             tracking_release_proc,
                                             &fulfillInfo);

        canvas->clear(SK_ColorRED);
        canvas->drawImage(promiseImage, 0, 0);
        ddl = recorder.detach();
    }

    context->flushAndSubmit();

    REPORTER_ASSERT(reporter, skgpu::ganesh::DrawDDL(s, ddl));

    GrFlushInfo flushInfo;
    context->flush(s.get(), SkSurfaces::BackendSurfaceAccess::kPresent, flushInfo);
    context->submit(GrSyncCpu::kNo);

    REPORTER_ASSERT(reporter, fulfillInfo.fFulfilled);

    // In order to receive the done callback with the low-level APIs we need to re-flush
    context->flush(s.get());
    context->submit(GrSyncCpu::kYes);

    REPORTER_ASSERT(reporter, fulfillInfo.fReleased);

    REPORTER_ASSERT(reporter, fulfillInfo.fTex->unique());
    fulfillInfo.fTex.reset();
}

////////////////////////////////////////////////////////////////////////////////
// Ensure that reusing a single DDLRecorder to create multiple DDLs works cleanly
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(DDLMultipleDDLs, reporter, ctxInfo, CtsEnforcement::kNever) {
    auto context = ctxInfo.directContext();

    SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
    sk_sp<SkSurface> s = SkSurfaces::RenderTarget(context, skgpu::Budgeted::kNo, ii);

    SkBitmap bitmap;
    bitmap.allocPixels(ii);

    GrSurfaceCharacterization characterization;
    SkAssertResult(s->characterize(&characterization));

    GrDeferredDisplayListRecorder recorder(characterization);

    SkCanvas* canvas1 = recorder.getCanvas();

    canvas1->clear(SK_ColorRED);

    canvas1->save();
    canvas1->clipRect(SkRect::MakeXYWH(8, 8, 16, 16));

    sk_sp<GrDeferredDisplayList> ddl1 = recorder.detach();

    SkCanvas* canvas2 = recorder.getCanvas();

    SkPaint p;
    p.setColor(SK_ColorGREEN);
    canvas2->drawRect(SkRect::MakeWH(32, 32), p);

    sk_sp<GrDeferredDisplayList> ddl2 = recorder.detach();

    REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData());
    REPORTER_ASSERT(reporter, ddl2->priv().lazyProxyData());

    // The lazy proxy data being different ensures that the SkSurface, SkCanvas and backing-
    // lazy proxy are all different between the two DDLs
    REPORTER_ASSERT(reporter, ddl1->priv().lazyProxyData() != ddl2->priv().lazyProxyData());

    skgpu::ganesh::DrawDDL(s, ddl1);
    skgpu::ganesh::DrawDDL(s, ddl2);

    // Make sure the clipRect from DDL1 didn't percolate into DDL2
    s->readPixels(ii, bitmap.getPixels(), bitmap.rowBytes(), 0, 0);
    for (int y = 0; y < 32; ++y) {
        for (int x = 0; x < 32; ++x) {
            REPORTER_ASSERT(reporter, bitmap.getColor(x, y) == SK_ColorGREEN);
            if (bitmap.getColor(x, y) != SK_ColorGREEN) {
                return; // we only really need to report the error once
            }
        }
    }
}

#ifdef SK_GL

static sk_sp<GrPromiseImageTexture> noop_fulfill_proc(void*) {
    SkASSERT(0);
    return nullptr;
}

////////////////////////////////////////////////////////////////////////////////
// Check that the texture-specific flags (i.e., for external & rectangle textures) work
// for promise images. As such, this is a GL-only test.
DEF_GANESH_TEST_FOR_GL_CONTEXT(DDLTextureFlagsTest, reporter, ctxInfo, CtsEnforcement::kNever) {
    auto context = ctxInfo.directContext();

    SkImageInfo ii = SkImageInfo::MakeN32Premul(32, 32);
    sk_sp<SkSurface> s = SkSurfaces::RenderTarget(context, skgpu::Budgeted::kNo, ii);

    GrSurfaceCharacterization characterization;
    SkAssertResult(s->characterize(&characterization));

    GrDeferredDisplayListRecorder recorder(characterization);

    for (GrGLenum target : { GR_GL_TEXTURE_EXTERNAL, GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_2D } ) {
        for (auto mipmapped : {skgpu::Mipmapped::kNo, skgpu::Mipmapped::kYes}) {
            GrBackendFormat format = GrBackendFormats::MakeGL(GR_GL_RGBA8, target);

            sk_sp<SkImage> image = SkImages::PromiseTextureFrom(
                    recorder.getCanvas()->recordingContext()->threadSafeProxy(),
                    format,
                    SkISize::Make(32, 32),
                    mipmapped,
                    kTopLeft_GrSurfaceOrigin,
                    kRGBA_8888_SkColorType,
                    kPremul_SkAlphaType,
                    /*color space*/ nullptr,
                    noop_fulfill_proc,
                    /*release proc*/ nullptr,
                    /*context*/ nullptr);
            if (GR_GL_TEXTURE_2D != target && mipmapped == skgpu::Mipmapped::kYes) {
                REPORTER_ASSERT(reporter, !image);
                continue;
            }
            if (!context->priv().caps()->isFormatTexturable(format, format.textureType())) {
                REPORTER_ASSERT(reporter, !image);
                continue;
            }
            REPORTER_ASSERT(reporter, image);

            GrTextureProxy* backingProxy = sk_gpu_test::GetTextureImageProxy(image.get(), context);

            REPORTER_ASSERT(reporter, backingProxy->mipmapped() == mipmapped);
            if (GR_GL_TEXTURE_2D == target) {
                REPORTER_ASSERT(reporter, !backingProxy->hasRestrictedSampling());
            } else {
                REPORTER_ASSERT(reporter, backingProxy->hasRestrictedSampling());
            }
        }
    }
}
#endif  // SK_GL

////////////////////////////////////////////////////////////////////////////////
// Test colorType and pixelConfig compatibility.
DEF_GANESH_TEST_FOR_GL_CONTEXT(DDLCompatibilityTest, reporter, ctxInfo, CtsEnforcement::kNever) {
    auto context = ctxInfo.directContext();

    for (int ct = 0; ct <= kLastEnum_SkColorType; ++ct) {
        SkColorType colorType = static_cast<SkColorType>(ct);

        SurfaceParameters params(context);
        params.setColorType(colorType);
        params.setColorSpace(nullptr);

        test_make_render_target(reporter, context, params);
    }
}
