/*
 * Copyright 2013 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/SkCanvas.h"
#include "include/core/SkData.h"
#include "include/core/SkOverdrawCanvas.h"
#include "include/core/SkPath.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRegion.h"
#include "include/core/SkSurface.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "src/core/SkAutoPixmapStorage.h"
#include "src/core/SkCanvasPriv.h"
#include "src/core/SkDevice.h"
#include "src/core/SkUtils.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrGpuResourcePriv.h"
#include "src/gpu/GrImageInfo.h"
#include "src/gpu/GrRenderTarget.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrSurfaceDrawContext.h"
#include "src/gpu/SkBaseGpuDevice.h"
#include "src/image/SkImage_Base.h"
#include "src/image/SkImage_Gpu.h"
#include "src/image/SkSurface_Gpu.h"
#include "tests/Test.h"
#include "tools/ToolUtils.h"
#include "tools/gpu/BackendSurfaceFactory.h"
#include "tools/gpu/ManagedBackendTexture.h"
#include "tools/gpu/ProxyUtils.h"

#include <functional>
#include <initializer_list>
#include <vector>

static void release_direct_surface_storage(void* pixels, void* context) {
    SkASSERT(pixels == context);
    sk_free(pixels);
}
static sk_sp<SkSurface> create_surface(SkAlphaType at = kPremul_SkAlphaType,
                                       SkImageInfo* requestedInfo = nullptr) {
    const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
    if (requestedInfo) {
        *requestedInfo = info;
    }
    return SkSurface::MakeRaster(info);
}
static sk_sp<SkSurface> create_direct_surface(SkAlphaType at = kPremul_SkAlphaType,
                                              SkImageInfo* requestedInfo = nullptr) {
    const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
    if (requestedInfo) {
        *requestedInfo = info;
    }
    const size_t rowBytes = info.minRowBytes();
    void* storage = sk_malloc_throw(info.computeByteSize(rowBytes));
    return SkSurface::MakeRasterDirectReleaseProc(info, storage, rowBytes,
                                                  release_direct_surface_storage,
                                                  storage);
}
static sk_sp<SkSurface> create_gpu_surface(GrRecordingContext* rContext,
                                           SkAlphaType at = kPremul_SkAlphaType,
                                           SkImageInfo* requestedInfo = nullptr) {
    const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
    if (requestedInfo) {
        *requestedInfo = info;
    }
    return SkSurface::MakeRenderTarget(rContext, SkBudgeted::kNo, info);
}
static sk_sp<SkSurface> create_gpu_scratch_surface(GrRecordingContext* rContext,
                                                   SkAlphaType at = kPremul_SkAlphaType,
                                                   SkImageInfo* requestedInfo = nullptr) {
    const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
    if (requestedInfo) {
        *requestedInfo = info;
    }
    return SkSurface::MakeRenderTarget(rContext, SkBudgeted::kYes, info);
}

DEF_TEST(SurfaceEmpty, reporter) {
    const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
    REPORTER_ASSERT(reporter, nullptr == SkSurface::MakeRaster(info));
    REPORTER_ASSERT(reporter, nullptr == SkSurface::MakeRasterDirect(info, nullptr, 0));

}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceEmpty_Gpu, reporter, ctxInfo) {
    const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
    REPORTER_ASSERT(reporter, nullptr ==
                    SkSurface::MakeRenderTarget(ctxInfo.directContext(), SkBudgeted::kNo, info));
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrContext_colorTypeSupportedAsSurface, reporter, ctxInfo) {
    auto context = ctxInfo.directContext();

    for (int ct = 0; ct < kLastEnum_SkColorType; ++ct) {
        static constexpr int kSize = 10;

        SkColorType colorType = static_cast<SkColorType>(ct);
        auto info = SkImageInfo::Make(kSize, kSize, colorType, kOpaque_SkAlphaType, nullptr);

        {
            bool can = context->colorTypeSupportedAsSurface(colorType);
            auto surf = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 1, nullptr);
            REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
                            colorType, can, SkToBool(surf));

            surf = sk_gpu_test::MakeBackendTextureSurface(context,
                                                          {kSize, kSize},
                                                          kTopLeft_GrSurfaceOrigin,
                                                          /*sample cnt*/ 1,
                                                          colorType);
            REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
                            colorType, can, SkToBool(surf));
        }

        // The MSAA test only makes sense if the colorType is renderable to begin with.
        if (context->colorTypeSupportedAsSurface(colorType)) {
            static constexpr int kSampleCnt = 2;

            bool can = context->maxSurfaceSampleCountForColorType(colorType) >= kSampleCnt;
            auto surf = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, kSampleCnt,
                                                    nullptr);
            REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
                            colorType, can, SkToBool(surf));

            surf = sk_gpu_test::MakeBackendTextureSurface(
                    context, {kSize, kSize}, kTopLeft_GrSurfaceOrigin, kSampleCnt, colorType);
            REPORTER_ASSERT(reporter, can == SkToBool(surf),
                            "colorTypeSupportedAsSurface:%d, surf:%d, ct:%d", can, SkToBool(surf),
                            colorType);
            // Ensure that the sample count stored on the resulting SkSurface is a valid value.
            if (surf) {
                auto rtp = SkCanvasPriv::TopDeviceTargetProxy(surf->getCanvas());
                int storedCnt = rtp->numSamples();
                const GrBackendFormat& format = rtp->backendFormat();
                int allowedCnt =
                        context->priv().caps()->getRenderTargetSampleCount(storedCnt, format);
                REPORTER_ASSERT(reporter, storedCnt == allowedCnt,
                                "Should store an allowed sample count (%d vs %d)", allowedCnt,
                                storedCnt);
            }
        }

        for (int sampleCnt : {1, 2}) {
            auto surf = sk_gpu_test::MakeBackendRenderTargetSurface(context,
                                                                    {16, 16},
                                                                    kTopLeft_GrSurfaceOrigin,
                                                                    sampleCnt,
                                                                    colorType);
            bool can = context->colorTypeSupportedAsSurface(colorType) &&
                       context->maxSurfaceSampleCountForColorType(colorType) >= sampleCnt;
            if (!surf && can && colorType == kBGRA_8888_SkColorType && sampleCnt > 1 &&
                context->backend() == GrBackendApi::kOpenGL) {
                // This is an execeptional case. On iOS GLES we support MSAA BGRA for internally-
                // created render targets by using a MSAA RGBA8 renderbuffer that resolves to a
                // BGRA8 texture. However, the GL_APPLE_texture_format_BGRA8888 extension does not
                // allow creation of BGRA8 renderbuffers and we don't support multisampled textures.
                // So this is expected to fail. As of 10/5/2020 it actually seems to work to create
                // a MSAA BGRA8 renderbuffer (at least in the simulator) but we don't want to rely
                // on this undocumented behavior.
                continue;
            }
            REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, sc: %d, can: %d, surf: %d",
                            colorType, sampleCnt, can, SkToBool(surf));
            if (surf) {
                auto rtp = SkCanvasPriv::TopDeviceTargetProxy(surf->getCanvas());
                int storedCnt = rtp->numSamples();
                const GrBackendFormat& backendFormat = rtp->backendFormat();
                int allowedCnt = context->priv().caps()->getRenderTargetSampleCount(storedCnt,
                                                                                    backendFormat);
                REPORTER_ASSERT(reporter, storedCnt == allowedCnt,
                                "Should store an allowed sample count (%d vs %d)", allowedCnt,
                                storedCnt);
            }
        }
    }
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrContext_maxSurfaceSamplesForColorType, reporter, ctxInfo) {
    auto context = ctxInfo.directContext();

    static constexpr int kSize = 10;

    for (int ct = 0; ct < kLastEnum_SkColorType; ++ct) {

        SkColorType colorType = static_cast<SkColorType>(ct);
        int maxSampleCnt = context->maxSurfaceSampleCountForColorType(colorType);
        if (!maxSampleCnt) {
            continue;
        }
        if (!context->colorTypeSupportedAsSurface(colorType)) {
            continue;
        }

        auto info = SkImageInfo::Make(kSize, kSize, colorType, kOpaque_SkAlphaType, nullptr);
        auto surf = sk_gpu_test::MakeBackendTextureSurface(
                context, info, kTopLeft_GrSurfaceOrigin, maxSampleCnt);
        if (!surf) {
            ERRORF(reporter, "Could not make surface of color type %d.", colorType);
            continue;
        }
        int sampleCnt =
            ((SkSurface_Gpu*)(surf.get()))->getDevice()->targetProxy()->numSamples();
        REPORTER_ASSERT(reporter, sampleCnt == maxSampleCnt, "Exected: %d, actual: %d",
                        maxSampleCnt, sampleCnt);
    }
}

static void test_canvas_peek(skiatest::Reporter* reporter,
                             sk_sp<SkSurface>& surface,
                             const SkImageInfo& requestInfo,
                             bool expectPeekSuccess) {
    const SkColor color = SK_ColorRED;
    const SkPMColor pmcolor = SkPreMultiplyColor(color);
    surface->getCanvas()->clear(color);

    SkPixmap pmap;
    bool success = surface->getCanvas()->peekPixels(&pmap);
    REPORTER_ASSERT(reporter, expectPeekSuccess == success);

    SkPixmap pmap2;
    const void* addr2 = surface->peekPixels(&pmap2) ? pmap2.addr() : nullptr;

    if (success) {
        REPORTER_ASSERT(reporter, requestInfo == pmap.info());
        REPORTER_ASSERT(reporter, requestInfo.minRowBytes() <= pmap.rowBytes());
        REPORTER_ASSERT(reporter, pmcolor == *pmap.addr32());

        REPORTER_ASSERT(reporter, pmap.addr() == pmap2.addr());
        REPORTER_ASSERT(reporter, pmap.info() == pmap2.info());
        REPORTER_ASSERT(reporter, pmap.rowBytes() == pmap2.rowBytes());
    } else {
        REPORTER_ASSERT(reporter, nullptr == addr2);
    }
}
DEF_TEST(SurfaceCanvasPeek, reporter) {
    for (auto& surface_func : { &create_surface, &create_direct_surface }) {
        SkImageInfo requestInfo;
        auto surface(surface_func(kPremul_SkAlphaType, &requestInfo));
        test_canvas_peek(reporter, surface, requestInfo, true);
    }
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCanvasPeek_Gpu, reporter, ctxInfo) {
    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
        SkImageInfo requestInfo;
        auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, &requestInfo));
        test_canvas_peek(reporter, surface, requestInfo, false);
    }
}

static void test_snapshot_alphatype(skiatest::Reporter* reporter, const sk_sp<SkSurface>& surface,
                                    SkAlphaType expectedAlphaType) {
    REPORTER_ASSERT(reporter, surface);
    if (surface) {
        sk_sp<SkImage> image(surface->makeImageSnapshot());
        REPORTER_ASSERT(reporter, image);
        if (image) {
            REPORTER_ASSERT(reporter, image->alphaType() == expectedAlphaType);
        }
    }
}
DEF_TEST(SurfaceSnapshotAlphaType, reporter) {
    for (auto& surface_func : { &create_surface, &create_direct_surface }) {
        for (auto& at: { kOpaque_SkAlphaType, kPremul_SkAlphaType, kUnpremul_SkAlphaType }) {
            auto surface(surface_func(at, nullptr));
            test_snapshot_alphatype(reporter, surface, at);
        }
    }
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceSnapshotAlphaType_Gpu, reporter, ctxInfo) {
    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
        // GPU doesn't support creating unpremul surfaces, so only test opaque + premul
        for (auto& at : { kOpaque_SkAlphaType, kPremul_SkAlphaType }) {
            auto surface(surface_func(ctxInfo.directContext(), at, nullptr));
            test_snapshot_alphatype(reporter, surface, at);
        }
    }
}

static void test_backend_texture_access_copy_on_write(
    skiatest::Reporter* reporter, SkSurface* surface, SkSurface::BackendHandleAccess access) {
    GrBackendTexture tex1 = surface->getBackendTexture(access);
    sk_sp<SkImage> snap1(surface->makeImageSnapshot());

    GrBackendTexture tex2 = surface->getBackendTexture(access);
    sk_sp<SkImage> snap2(surface->makeImageSnapshot());

    // If the access mode triggers CoW, then the backend objects should reflect it.
    REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(tex1, tex2) == (snap1 == snap2));
}

static void test_backend_rendertarget_access_copy_on_write(
    skiatest::Reporter* reporter, SkSurface* surface, SkSurface::BackendHandleAccess access) {
    GrBackendRenderTarget rt1 = surface->getBackendRenderTarget(access);
    sk_sp<SkImage> snap1(surface->makeImageSnapshot());

    GrBackendRenderTarget rt2 = surface->getBackendRenderTarget(access);
    sk_sp<SkImage> snap2(surface->makeImageSnapshot());

    // If the access mode triggers CoW, then the backend objects should reflect it.
    REPORTER_ASSERT(reporter, GrBackendRenderTarget::TestingOnly_Equals(rt1, rt2) ==
                              (snap1 == snap2));
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendSurfaceAccessCopyOnWrite_Gpu, reporter, ctxInfo) {
    const SkSurface::BackendHandleAccess accessModes[] = {
        SkSurface::kFlushRead_BackendHandleAccess,
        SkSurface::kFlushWrite_BackendHandleAccess,
        SkSurface::kDiscardWrite_BackendHandleAccess,
    };

    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
        for (auto& accessMode : accessModes) {
            {
                auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
                test_backend_texture_access_copy_on_write(reporter, surface.get(), accessMode);
            }
            {
                auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
                test_backend_rendertarget_access_copy_on_write(reporter, surface.get(), accessMode);
            }
        }
    }
}

template<typename Type, Type(SkSurface::*func)(SkSurface::BackendHandleAccess)>
static void test_backend_unique_id(skiatest::Reporter* reporter, SkSurface* surface) {
    sk_sp<SkImage> image0(surface->makeImageSnapshot());

    Type obj = (surface->*func)(SkSurface::kFlushRead_BackendHandleAccess);
    REPORTER_ASSERT(reporter, obj.isValid());
    sk_sp<SkImage> image1(surface->makeImageSnapshot());
    // just read access should not affect the snapshot
    REPORTER_ASSERT(reporter, image0->uniqueID() == image1->uniqueID());

    obj = (surface->*func)(SkSurface::kFlushWrite_BackendHandleAccess);
    REPORTER_ASSERT(reporter, obj.isValid());
    sk_sp<SkImage> image2(surface->makeImageSnapshot());
    // expect a new image, since we claimed we would write
    REPORTER_ASSERT(reporter, image0->uniqueID() != image2->uniqueID());

    obj = (surface->*func)(SkSurface::kDiscardWrite_BackendHandleAccess);
    REPORTER_ASSERT(reporter, obj.isValid());
    sk_sp<SkImage> image3(surface->makeImageSnapshot());
    // expect a new(er) image, since we claimed we would write
    REPORTER_ASSERT(reporter, image0->uniqueID() != image3->uniqueID());
    REPORTER_ASSERT(reporter, image2->uniqueID() != image3->uniqueID());
}

// No CPU test.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessIDs_Gpu, reporter, ctxInfo) {
    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
        {
            auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
            test_backend_unique_id<GrBackendTexture, &SkSurface::getBackendTexture>(reporter,
                                                                                    surface.get());
        }
        {
            auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
            test_backend_unique_id<GrBackendRenderTarget, &SkSurface::getBackendRenderTarget>(
                                                                reporter, surface.get());
        }
    }
}

// No CPU test.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceAbandonPostFlush_Gpu, reporter, ctxInfo) {
    auto direct = ctxInfo.directContext();
    sk_sp<SkSurface> surface = create_gpu_surface(direct, kPremul_SkAlphaType, nullptr);
    if (!surface) {
        return;
    }
    // This flush can put command buffer refs on the GrGpuResource for the surface.
    surface->flush();
    direct->abandonContext();
    // We pass the test if we don't hit any asserts or crashes when the ref on the surface goes away
    // after we abanonded the context. One thing specifically this checks is to make sure we're
    // correctly handling the mix of normal refs and command buffer refs, and correctly deleting
    // the object at the right time.
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendAccessAbandoned_Gpu, reporter, ctxInfo) {
    auto dContext = ctxInfo.directContext();
    sk_sp<SkSurface> surface = create_gpu_surface(dContext, kPremul_SkAlphaType, nullptr);
    if (!surface) {
        return;
    }

    GrBackendRenderTarget beRT =
            surface->getBackendRenderTarget(SkSurface::kFlushRead_BackendHandleAccess);
    REPORTER_ASSERT(reporter, beRT.isValid());
    GrBackendTexture beTex =
            surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess);
    REPORTER_ASSERT(reporter, beTex.isValid());

    surface->flush();
    dContext->abandonContext();

    // After abandoning the context none of the backend surfaces should be valid.
    beRT = surface->getBackendRenderTarget(SkSurface::kFlushRead_BackendHandleAccess);
    REPORTER_ASSERT(reporter, !beRT.isValid());
    beTex = surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess);
    REPORTER_ASSERT(reporter, !beTex.isValid());
}

// Verify that the right canvas commands trigger a copy on write.
static void test_copy_on_write(skiatest::Reporter* reporter, SkSurface* surface) {
    SkCanvas* canvas = surface->getCanvas();

    const SkRect testRect =
        SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
                         SkIntToScalar(4), SkIntToScalar(5));
    SkPath testPath;
    testPath.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
                                      SkIntToScalar(2), SkIntToScalar(1)));

    const SkIRect testIRect = SkIRect::MakeXYWH(0, 0, 2, 1);

    SkRegion testRegion;
    testRegion.setRect(testIRect);


    const SkColor testColor = 0x01020304;
    const SkPaint testPaint;
    const SkPoint testPoints[3] = {
        {SkIntToScalar(0), SkIntToScalar(0)},
        {SkIntToScalar(2), SkIntToScalar(1)},
        {SkIntToScalar(0), SkIntToScalar(2)}
    };
    const size_t testPointCount = 3;

    SkBitmap testBitmap;
    testBitmap.allocN32Pixels(10, 10);
    testBitmap.eraseColor(0);

    SkRRect testRRect;
    testRRect.setRectXY(testRect, SK_Scalar1, SK_Scalar1);

    SkString testText("Hello World");

#define EXPECT_COPY_ON_WRITE(command)                               \
    {                                                               \
        sk_sp<SkImage> imageBefore = surface->makeImageSnapshot();  \
        sk_sp<SkImage> aur_before(imageBefore);  /*NOLINT*/         \
        canvas-> command ;                                          \
        sk_sp<SkImage> imageAfter = surface->makeImageSnapshot();   \
        sk_sp<SkImage> aur_after(imageAfter);  /*NOLINT*/           \
        REPORTER_ASSERT(reporter, imageBefore != imageAfter);       \
    }

    EXPECT_COPY_ON_WRITE(clear(testColor))
    EXPECT_COPY_ON_WRITE(drawPaint(testPaint))
    EXPECT_COPY_ON_WRITE(drawPoints(SkCanvas::kPoints_PointMode, testPointCount, testPoints, \
        testPaint))
    EXPECT_COPY_ON_WRITE(drawOval(testRect, testPaint))
    EXPECT_COPY_ON_WRITE(drawRect(testRect, testPaint))
    EXPECT_COPY_ON_WRITE(drawRRect(testRRect, testPaint))
    EXPECT_COPY_ON_WRITE(drawPath(testPath, testPaint))
    EXPECT_COPY_ON_WRITE(drawImage(testBitmap.asImage(), 0, 0))
    EXPECT_COPY_ON_WRITE(drawImageRect(testBitmap.asImage(), testRect, SkSamplingOptions()))
    EXPECT_COPY_ON_WRITE(drawString(testText, 0, 1, SkFont(), testPaint))
}
DEF_TEST(SurfaceCopyOnWrite, reporter) {
    test_copy_on_write(reporter, create_surface().get());
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCopyOnWrite_Gpu, reporter, ctxInfo) {
    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
        auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
        test_copy_on_write(reporter, surface.get());
    }
}

static void test_writable_after_snapshot_release(skiatest::Reporter* reporter,
                                                 SkSurface* surface) {
    // This test succeeds by not triggering an assertion.
    // The test verifies that the surface remains writable (usable) after
    // acquiring and releasing a snapshot without triggering a copy on write.
    SkCanvas* canvas = surface->getCanvas();
    canvas->clear(1);
    surface->makeImageSnapshot();  // Create and destroy SkImage
    canvas->clear(2);  // Must not assert internally
}
DEF_TEST(SurfaceWriteableAfterSnapshotRelease, reporter) {
    test_writable_after_snapshot_release(reporter, create_surface().get());
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceWriteableAfterSnapshotRelease_Gpu, reporter, ctxInfo) {
    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
        auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
        test_writable_after_snapshot_release(reporter, surface.get());
    }
}

static void test_crbug263329(skiatest::Reporter* reporter,
                             SkSurface* surface1,
                             SkSurface* surface2) {
    // This is a regression test for crbug.com/263329
    // Bug was caused by onCopyOnWrite releasing the old surface texture
    // back to the scratch texture pool even though the texture is used
    // by and active SkImage_Gpu.
    SkCanvas* canvas1 = surface1->getCanvas();
    SkCanvas* canvas2 = surface2->getCanvas();
    canvas1->clear(1);
    sk_sp<SkImage> image1(surface1->makeImageSnapshot());
    // Trigger copy on write, new backing is a scratch texture
    canvas1->clear(2);
    sk_sp<SkImage> image2(surface1->makeImageSnapshot());
    // Trigger copy on write, old backing should not be returned to scratch
    // pool because it is held by image2
    canvas1->clear(3);

    canvas2->clear(4);
    sk_sp<SkImage> image3(surface2->makeImageSnapshot());
    // Trigger copy on write on surface2. The new backing store should not
    // be recycling a texture that is held by an existing image.
    canvas2->clear(5);
    sk_sp<SkImage> image4(surface2->makeImageSnapshot());

    auto imageProxy = [ctx = surface1->recordingContext()](SkImage* img) {
        GrTextureProxy* proxy = sk_gpu_test::GetTextureImageProxy(img, ctx);
        SkASSERT(proxy);
        return proxy;
    };

    REPORTER_ASSERT(reporter, imageProxy(image4.get()) != imageProxy(image3.get()));
    // The following assertion checks crbug.com/263329
    REPORTER_ASSERT(reporter, imageProxy(image4.get()) != imageProxy(image2.get()));
    REPORTER_ASSERT(reporter, imageProxy(image4.get()) != imageProxy(image1.get()));
    REPORTER_ASSERT(reporter, imageProxy(image3.get()) != imageProxy(image2.get()));
    REPORTER_ASSERT(reporter, imageProxy(image3.get()) != imageProxy(image1.get()));
    REPORTER_ASSERT(reporter, imageProxy(image2.get()) != imageProxy(image1.get()));
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCRBug263329_Gpu, reporter, ctxInfo) {
    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
        auto surface1(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
        auto surface2(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
        test_crbug263329(reporter, surface1.get(), surface2.get());
    }
}

DEF_TEST(SurfaceGetTexture, reporter) {
    auto surface(create_surface());
    sk_sp<SkImage> image(surface->makeImageSnapshot());
    REPORTER_ASSERT(reporter, !as_IB(image)->isTextureBacked());
    surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
    REPORTER_ASSERT(reporter, !as_IB(image)->isTextureBacked());
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfacepeekTexture_Gpu, reporter, ctxInfo) {
    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
        auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
        sk_sp<SkImage> image(surface->makeImageSnapshot());

        REPORTER_ASSERT(reporter, as_IB(image)->isTextureBacked());
        GrBackendTexture backendTex = image->getBackendTexture(false);
        REPORTER_ASSERT(reporter, backendTex.isValid());
        surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
        REPORTER_ASSERT(reporter, as_IB(image)->isTextureBacked());
        GrBackendTexture backendTex2 = image->getBackendTexture(false);
        REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(backendTex, backendTex2));
    }
}

static SkBudgeted is_budgeted(const sk_sp<SkSurface>& surf) {
    SkSurface_Gpu* gsurf = (SkSurface_Gpu*)surf.get();

    GrRenderTargetProxy* proxy = gsurf->getDevice()->targetProxy();
    return proxy->isBudgeted();
}

static SkBudgeted is_budgeted(SkImage* image, GrRecordingContext* rc) {
    return sk_gpu_test::GetTextureImageProxy(image, rc)->isBudgeted();
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBudget, reporter, ctxInfo) {
    SkImageInfo info = SkImageInfo::MakeN32Premul(8,8);
    GrDirectContext* dContext = ctxInfo.directContext();
    for (auto budgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) {
        auto surface(SkSurface::MakeRenderTarget(dContext, budgeted, info));
        SkASSERT(surface);
        REPORTER_ASSERT(reporter, budgeted == is_budgeted(surface));

        sk_sp<SkImage> image(surface->makeImageSnapshot());

        // Initially the image shares a texture with the surface, and the
        // the budgets should always match.
        REPORTER_ASSERT(reporter, budgeted == is_budgeted(surface));
        REPORTER_ASSERT(reporter, budgeted == is_budgeted(image.get(), dContext));

        // Now trigger copy-on-write
        surface->getCanvas()->clear(SK_ColorBLUE);

        // They don't share a texture anymore but the budgets should still match.
        REPORTER_ASSERT(reporter, budgeted == is_budgeted(surface));
        REPORTER_ASSERT(reporter, budgeted == is_budgeted(image.get(), dContext));
    }
}

static void test_no_canvas1(skiatest::Reporter* reporter,
                            SkSurface* surface,
                            SkSurface::ContentChangeMode mode) {
    // Test passes by not asserting
    surface->notifyContentWillChange(mode);
}
static void test_no_canvas2(skiatest::Reporter* reporter,
                            SkSurface* surface,
                            SkSurface::ContentChangeMode mode) {
    // Verifies the robustness of SkSurface for handling use cases where calls
    // are made before a canvas is created.
    sk_sp<SkImage> image1 = surface->makeImageSnapshot();
    sk_sp<SkImage> aur_image1(image1);  // NOLINT(performance-unnecessary-copy-initialization)
    surface->notifyContentWillChange(mode);
    sk_sp<SkImage> image2 = surface->makeImageSnapshot();
    sk_sp<SkImage> aur_image2(image2);  // NOLINT(performance-unnecessary-copy-initialization)
    REPORTER_ASSERT(reporter, image1 != image2);
}
DEF_TEST(SurfaceNoCanvas, reporter) {
    SkSurface::ContentChangeMode modes[] =
            { SkSurface::kDiscard_ContentChangeMode, SkSurface::kRetain_ContentChangeMode};
    for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) {
        for (auto& mode : modes) {
            test_func(reporter, create_surface().get(), mode);
        }
    }
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceNoCanvas_Gpu, reporter, ctxInfo) {
    SkSurface::ContentChangeMode modes[] =
            { SkSurface::kDiscard_ContentChangeMode, SkSurface::kRetain_ContentChangeMode};
    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
        for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) {
            for (auto& mode : modes) {
                auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
                test_func(reporter, surface.get(), mode);
            }
        }
    }
}

static void check_rowbytes_remain_consistent(SkSurface* surface, skiatest::Reporter* reporter) {
    SkPixmap surfacePM;
    REPORTER_ASSERT(reporter, surface->peekPixels(&surfacePM));

    sk_sp<SkImage> image(surface->makeImageSnapshot());
    SkPixmap pm;
    REPORTER_ASSERT(reporter, image->peekPixels(&pm));

    REPORTER_ASSERT(reporter, surfacePM.rowBytes() == pm.rowBytes());

    // trigger a copy-on-write
    surface->getCanvas()->drawPaint(SkPaint());
    sk_sp<SkImage> image2(surface->makeImageSnapshot());
    REPORTER_ASSERT(reporter, image->uniqueID() != image2->uniqueID());

    SkPixmap pm2;
    REPORTER_ASSERT(reporter, image2->peekPixels(&pm2));
    REPORTER_ASSERT(reporter, pm2.rowBytes() == pm.rowBytes());
}

DEF_TEST(surface_rowbytes, reporter) {
    const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);

    auto surf0(SkSurface::MakeRaster(info));
    check_rowbytes_remain_consistent(surf0.get(), reporter);

    // specify a larger rowbytes
    auto surf1(SkSurface::MakeRaster(info, 500, nullptr));
    check_rowbytes_remain_consistent(surf1.get(), reporter);

    // Try some illegal rowByte values
    auto s = SkSurface::MakeRaster(info, 396, nullptr);    // needs to be at least 400
    REPORTER_ASSERT(reporter, nullptr == s);
    s = SkSurface::MakeRaster(info, std::numeric_limits<size_t>::max(), nullptr);
    REPORTER_ASSERT(reporter, nullptr == s);
}

DEF_TEST(surface_raster_zeroinitialized, reporter) {
    sk_sp<SkSurface> s(SkSurface::MakeRasterN32Premul(100, 100));
    SkPixmap pixmap;
    REPORTER_ASSERT(reporter, s->peekPixels(&pixmap));

    for (int i = 0; i < pixmap.info().width(); ++i) {
        for (int j = 0; j < pixmap.info().height(); ++j) {
            REPORTER_ASSERT(reporter, *pixmap.addr32(i, j) == 0);
        }
    }
}

static sk_sp<SkSurface> create_gpu_surface_backend_texture(GrDirectContext* dContext,
                                                           int sampleCnt,
                                                           const SkColor4f& color) {
    // On Pixel and Pixel2XL's with Adreno 530 and 540s, setting width and height to 10s reliably
    // triggers what appears to be a driver race condition where the 10x10 surface from the
    // OverdrawSurface_gpu test is reused(?) for this surface created by the SurfacePartialDraw_gpu
    // test.
    //
    // Immediately after creation of this surface, readback shows the correct initial solid color.
    // However, sometime before content is rendered into the upper half of the surface, the driver
    // presumably cleans up the OverdrawSurface_gpu's memory which corrupts this color buffer. The
    // top half of the surface is fine after the partially-covering rectangle is drawn, but the
    // untouched bottom half contains random pixel values that trigger asserts in the
    // SurfacePartialDraw_gpu test for no longer matching the initial color. Running the
    // SurfacePartialDraw_gpu test without the OverdrawSurface_gpu test completes successfully.
    //
    // Requesting a much larger backend texture size seems to prevent it from reusing the same
    // memory and avoids the issue.
#if defined(SK_BUILD_FOR_SKQP)
    const int kWidth = 10;
    const int kHeight = 10;
#else
    const int kWidth = 100;
    const int kHeight = 100;
#endif

    auto surf = sk_gpu_test::MakeBackendTextureSurface(dContext,
                                                       {kWidth, kHeight},
                                                       kTopLeft_GrSurfaceOrigin,
                                                       sampleCnt,
                                                       kRGBA_8888_SkColorType);
    if (!surf) {
        return nullptr;
    }
    surf->getCanvas()->clear(color);
    return surf;
}

static bool supports_readpixels(const GrCaps* caps, SkSurface* surface) {
    auto surfaceGpu = static_cast<SkSurface_Gpu*>(surface);
    GrRenderTarget* rt = surfaceGpu->getDevice()->targetProxy()->peekRenderTarget();
    if (!rt) {
        return false;
    }
    return caps->surfaceSupportsReadPixels(rt) == GrCaps::SurfaceReadPixelsSupport::kSupported;
}

static sk_sp<SkSurface> create_gpu_surface_backend_render_target(GrDirectContext* dContext,
                                                                 int sampleCnt,
                                                                 const SkColor4f& color) {
    const int kWidth = 10;
    const int kHeight = 10;

    auto surf = sk_gpu_test::MakeBackendRenderTargetSurface(dContext,
                                                            {kWidth, kHeight},
                                                            kTopLeft_GrSurfaceOrigin,
                                                            sampleCnt,
                                                            kRGBA_8888_SkColorType);
    if (!surf) {
        return nullptr;
    }
    surf->getCanvas()->clear(color);
    return surf;
}

static void test_surface_context_clear(skiatest::Reporter* reporter,
                                       GrDirectContext* dContext,
                                       GrSurfaceContext* surfaceContext, uint32_t expectedValue) {
    int w = surfaceContext->width();
    int h = surfaceContext->height();

    SkImageInfo ii = SkImageInfo::Make(w, h, kRGBA_8888_SkColorType, kPremul_SkAlphaType);

    SkAutoPixmapStorage readback;
    readback.alloc(ii);

    readback.erase(~expectedValue);
    surfaceContext->readPixels(dContext, readback, {0, 0});
    for (int y = 0; y < h; ++y) {
        for (int x = 0; x < w; ++x) {
            uint32_t pixel = readback.addr32()[y * w + x];
            if (pixel != expectedValue) {
                SkString msg;
                if (expectedValue) {
                    msg = "SkSurface should have left render target unmodified";
                } else {
                    msg = "SkSurface should have cleared the render target";
                }
                ERRORF(reporter,
                       "%s but read 0x%08x (instead of 0x%08x) at %x,%d", msg.c_str(), pixel,
                       expectedValue, x, y);
                return;
            }
        }
    }
}

DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceClear_Gpu, reporter, ctxInfo) {
    auto dContext = ctxInfo.directContext();
    // Snaps an image from a surface and then makes a GrSurfaceContext from the image's texture.
    auto makeImageSurfaceContext = [dContext](SkSurface* surface) {
        sk_sp<SkImage> i(surface->makeImageSnapshot());
        auto gpuImage = static_cast<SkImage_Gpu*>(as_IB(i));
        auto [view, ct] = gpuImage->asView(dContext, GrMipmapped::kNo);
        GrColorInfo colorInfo(ct, i->alphaType(), i->refColorSpace());
        return GrSurfaceContext::Make(dContext, view, std::move(colorInfo));
    };

    // Test that non-wrapped RTs are created clear.
    for (auto& surface_func : {&create_gpu_surface, &create_gpu_scratch_surface}) {
        auto surface = surface_func(dContext, kPremul_SkAlphaType, nullptr);
        if (!surface) {
            ERRORF(reporter, "Could not create GPU SkSurface.");
            return;
        }
        auto sdc = SkCanvasPriv::TopDeviceSurfaceDrawContext(surface->getCanvas());
        if (!sdc) {
            ERRORF(reporter, "Could access surface context of GPU SkSurface.");
            return;
        }
        test_surface_context_clear(reporter, dContext, sdc, 0x0);
        auto imageSurfaceCtx = makeImageSurfaceContext(surface.get());
        test_surface_context_clear(reporter, dContext, imageSurfaceCtx.get(), 0x0);
    }

    // Wrapped RTs are *not* supposed to clear (to allow client to partially update a surface).
    const SkColor4f kOrigColor{.67f, .67f, .67f, 1};
    for (auto& surfaceFunc :
         {&create_gpu_surface_backend_texture, &create_gpu_surface_backend_render_target}) {
        auto surface = surfaceFunc(dContext, 1, kOrigColor);
        if (!surface) {
            ERRORF(reporter, "Could not create GPU SkSurface.");
            return;
        }
        auto sdc = SkCanvasPriv::TopDeviceSurfaceDrawContext(surface->getCanvas());
        if (!sdc) {
            ERRORF(reporter, "Could access surface context of GPU SkSurface.");
            return;
        }
        test_surface_context_clear(reporter, dContext, sdc, kOrigColor.toSkColor());
        auto imageSurfaceCtx = makeImageSurfaceContext(surface.get());
        test_surface_context_clear(reporter, dContext, imageSurfaceCtx.get(),
                                   kOrigColor.toSkColor());
    }
}

static void test_surface_draw_partially(
    skiatest::Reporter* reporter, sk_sp<SkSurface> surface, SkColor origColor) {
    const int kW = surface->width();
    const int kH = surface->height();
    SkPaint paint;
    const SkColor kRectColor = ~origColor | 0xFF000000;
    paint.setColor(kRectColor);
    surface->getCanvas()->drawRect(SkRect::MakeIWH(kW, kH/2), paint);

    // Read back RGBA to avoid format conversions that may not be supported on all platforms.
    SkImageInfo readInfo = SkImageInfo::Make(kW, kH, kRGBA_8888_SkColorType, kPremul_SkAlphaType);

    SkAutoPixmapStorage readback;
    readback.alloc(readInfo);

    readback.erase(~origColor);
    REPORTER_ASSERT(reporter, surface->readPixels(readback.info(), readback.writable_addr(),
                                                  readback.rowBytes(), 0, 0));
    bool stop = false;

    SkPMColor origColorPM = SkPackARGB_as_RGBA(SkColorGetA(origColor),
                                               SkColorGetR(origColor),
                                               SkColorGetG(origColor),
                                               SkColorGetB(origColor));
    SkPMColor rectColorPM = SkPackARGB_as_RGBA(SkColorGetA(kRectColor),
                                               SkColorGetR(kRectColor),
                                               SkColorGetG(kRectColor),
                                               SkColorGetB(kRectColor));

    for (int y = 0; y < kH/2 && !stop; ++y) {
       for (int x = 0; x < kW && !stop; ++x) {
            REPORTER_ASSERT(reporter, rectColorPM == readback.addr32()[x + y * kW]);
            if (rectColorPM != readback.addr32()[x + y * kW]) {
                SkDebugf("--- got [%x] expected [%x], x = %d, y = %d\n",
                         readback.addr32()[x + y * kW], rectColorPM, x, y);
                stop = true;
            }
        }
    }
    stop = false;
    for (int y = kH/2; y < kH && !stop; ++y) {
        for (int x = 0; x < kW && !stop; ++x) {
            REPORTER_ASSERT(reporter, origColorPM == readback.addr32()[x + y * kW]);
            if (origColorPM != readback.addr32()[x + y * kW]) {
                SkDebugf("--- got [%x] expected [%x], x = %d, y = %d\n",
                         readback.addr32()[x + y * kW], origColorPM, x, y);
                stop = true;
            }
        }
    }
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfacePartialDraw_Gpu, reporter, ctxInfo) {
    auto context = ctxInfo.directContext();

    static const SkColor4f kOrigColor { 0.667f, 0.733f, 0.8f, 1 };

    for (auto& surfaceFunc :
         {&create_gpu_surface_backend_texture, &create_gpu_surface_backend_render_target}) {
        // Validate that we can draw to the canvas and that the original texture color is
        // preserved in pixels that aren't rendered to via the surface.
        // This works only for non-multisampled case.
        auto surface = surfaceFunc(context, 1, kOrigColor);
        if (surface && supports_readpixels(context->priv().caps(), surface.get())) {
            test_surface_draw_partially(reporter, surface, kOrigColor.toSkColor());
        }
    }
}

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


DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceWrappedWithRelease_Gpu, reporter, ctxInfo) {
    const int kWidth = 10;
    const int kHeight = 10;

    auto ctx = ctxInfo.directContext();
    GrGpu* gpu = ctx->priv().getGpu();

    for (bool useTexture : {false, true}) {
        sk_sp<sk_gpu_test::ManagedBackendTexture> mbet;
        GrBackendRenderTarget backendRT;
        sk_sp<SkSurface> surface;

        ReleaseChecker releaseChecker;
        GrSurfaceOrigin texOrigin = kBottomLeft_GrSurfaceOrigin;

        if (useTexture) {
            SkImageInfo ii = SkImageInfo::Make(kWidth, kHeight, SkColorType::kRGBA_8888_SkColorType,
                                               kPremul_SkAlphaType);
            mbet = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(ctx, ii, GrMipmapped::kNo,
                                                                    GrRenderable::kYes);
            if (!mbet) {
                continue;
            }

            surface = SkSurface::MakeFromBackendTexture(
                    ctx,
                    mbet->texture(),
                    texOrigin,
                    /*sample count*/ 1,
                    kRGBA_8888_SkColorType,
                    /*color space*/ nullptr,
                    /*surface props*/ nullptr,
                    sk_gpu_test::ManagedBackendTexture::ReleaseProc,
                    mbet->releaseContext(ReleaseChecker::Release, &releaseChecker));
        } else {
            backendRT = gpu->createTestingOnlyBackendRenderTarget({kWidth, kHeight},
                                                                  GrColorType::kRGBA_8888);
            if (!backendRT.isValid()) {
                continue;
            }
            surface = SkSurface::MakeFromBackendRenderTarget(ctx, backendRT, texOrigin,
                                                             kRGBA_8888_SkColorType,
                                                             nullptr, nullptr,
                                                             ReleaseChecker::Release,
                                                             &releaseChecker);
        }
        if (!surface) {
            ERRORF(reporter, "Failed to create surface");
            continue;
        }

        surface->getCanvas()->clear(SK_ColorRED);
        surface->flush();
        ctx->submit(true);

        // Now exercise the release proc
        REPORTER_ASSERT(reporter, 0 == releaseChecker.fReleaseCount);
        surface.reset(nullptr); // force a release of the surface
        REPORTER_ASSERT(reporter, 1 == releaseChecker.fReleaseCount);

        if (!useTexture) {
            gpu->deleteTestingOnlyBackendRenderTarget(backendRT);
        }
    }
}

DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceAttachStencil_Gpu, reporter, ctxInfo) {
    auto context = ctxInfo.directContext();
    const GrCaps* caps = context->priv().caps();

    if (caps->avoidStencilBuffers()) {
        return;
    }

    static const SkColor4f kOrigColor { 0.667f, 0.733f, 0.8f, 1 };

    auto resourceProvider = context->priv().resourceProvider();

    for (auto& surfaceFunc :
         {&create_gpu_surface_backend_texture, &create_gpu_surface_backend_render_target}) {
        for (int sampleCnt : {1, 4, 8}) {
            auto surface = surfaceFunc(context, sampleCnt, kOrigColor);

            if (!surface && sampleCnt > 1) {
                // Certain platforms don't support MSAA, skip these.
                continue;
            }

            // Validate that we can attach a stencil buffer to an SkSurface created by either of
            // our surface functions.
            auto rtp = SkCanvasPriv::TopDeviceTargetProxy(surface->getCanvas());
            GrRenderTarget* rt = rtp->peekRenderTarget();
            REPORTER_ASSERT(reporter,
                            resourceProvider->attachStencilAttachment(rt, rt->numSamples() > 1));
        }
    }
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReplaceSurfaceBackendTexture, reporter, ctxInfo) {
    auto context = ctxInfo.directContext();

    for (int sampleCnt : {1, 2}) {
        auto ii = SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
        auto mbet1 = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(
                context, ii, GrMipmapped::kNo, GrRenderable::kYes);
        if (!mbet1) {
            continue;
        }
        auto mbet2 = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(
                context, ii, GrMipmapped::kNo, GrRenderable::kYes);
        if (!mbet2) {
            ERRORF(reporter, "Expected to be able to make second texture");
            continue;
        }
        auto ii2 = ii.makeWH(8, 8);
        auto mbet3 = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(
                context, ii2, GrMipmapped::kNo, GrRenderable::kYes);
        GrBackendTexture backendTexture3;
        if (!mbet3) {
            ERRORF(reporter, "Couldn't create different sized texture.");
            continue;
        }

        auto surf = SkSurface::MakeFromBackendTexture(
                context, mbet1->texture(), kTopLeft_GrSurfaceOrigin, sampleCnt,
                kRGBA_8888_SkColorType, ii.refColorSpace(), nullptr);
        if (!surf) {
            continue;
        }
        surf->getCanvas()->clear(SK_ColorBLUE);
        // Change matrix, layer, and clip state before swapping out the backing texture.
        surf->getCanvas()->translate(5, 5);
        surf->getCanvas()->saveLayer(nullptr, nullptr);
        surf->getCanvas()->clipRect(SkRect::MakeXYWH(0, 0, 1, 1));
        // switch origin while we're at it.
        bool replaced = surf->replaceBackendTexture(mbet2->texture(), kBottomLeft_GrSurfaceOrigin);
        REPORTER_ASSERT(reporter, replaced);
        SkPaint paint;
        paint.setColor(SK_ColorRED);
        surf->getCanvas()->drawRect(SkRect::MakeWH(5, 5), paint);
        surf->getCanvas()->restore();

        // Check that the replacement texture got the right color values.
        SkAutoPixmapStorage pm;
        pm.alloc(ii);
        bool bad = !surf->readPixels(pm, 0, 0);
        REPORTER_ASSERT(reporter, !bad, "Could not read surface.");
        for (int y = 0; y < ii.height() && !bad; ++y) {
            for (int x = 0; x < ii.width() && !bad; ++x) {
                auto expected = (x == 5 && y == 5) ? 0xFF0000FF : 0xFFFF0000;
                auto found = *pm.addr32(x, y);
                if (found != expected) {
                    bad = true;
                    ERRORF(reporter, "Expected color 0x%08x, found color 0x%08x at %d, %d.",
                           expected, found, x, y);
                }
            }
        }
        // The original texture should still be all blue.
        surf = SkSurface::MakeFromBackendTexture(
                context, mbet1->texture(), kBottomLeft_GrSurfaceOrigin, sampleCnt,
                kRGBA_8888_SkColorType, ii.refColorSpace(), nullptr);
        if (!surf) {
            ERRORF(reporter, "Could not create second surface.");
            continue;
        }
        bad = !surf->readPixels(pm, 0, 0);
        REPORTER_ASSERT(reporter, !bad, "Could not read second surface.");
        for (int y = 0; y < ii.height() && !bad; ++y) {
            for (int x = 0; x < ii.width() && !bad; ++x) {
                auto expected = 0xFFFF0000;
                auto found = *pm.addr32(x, y);
                if (found != expected) {
                    bad = true;
                    ERRORF(reporter, "Expected color 0x%08x, found color 0x%08x at %d, %d.",
                           expected, found, x, y);
                }
            }
        }

        // Can't replace with the same texture
        REPORTER_ASSERT(reporter,
                        !surf->replaceBackendTexture(mbet1->texture(), kTopLeft_GrSurfaceOrigin));
        // Can't replace with invalid texture
        REPORTER_ASSERT(reporter, !surf->replaceBackendTexture({}, kTopLeft_GrSurfaceOrigin));
        // Can't replace with different size texture.
        REPORTER_ASSERT(reporter,
                        !surf->replaceBackendTexture(mbet3->texture(), kTopLeft_GrSurfaceOrigin));
        // Can't replace texture of non-wrapped SkSurface.
        surf = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, ii, sampleCnt, nullptr);
        REPORTER_ASSERT(reporter, surf);
        if (surf) {
            REPORTER_ASSERT(reporter, !surf->replaceBackendTexture(mbet1->texture(),
                                                                   kTopLeft_GrSurfaceOrigin));
        }
    }
}

static void test_overdraw_surface(skiatest::Reporter* r, SkSurface* surface) {
    SkOverdrawCanvas canvas(surface->getCanvas());
    canvas.drawPaint(SkPaint());
    sk_sp<SkImage> image = surface->makeImageSnapshot();

    SkBitmap bitmap;
    image->asLegacyBitmap(&bitmap);
    for (int y = 0; y < 10; y++) {
        for (int x = 0; x < 10; x++) {
            REPORTER_ASSERT(r, 1 == SkGetPackedA32(*bitmap.getAddr32(x, y)));
        }
    }
}

DEF_TEST(OverdrawSurface_Raster, r) {
    sk_sp<SkSurface> surface = create_surface();
    test_overdraw_surface(r, surface.get());
}

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(OverdrawSurface_Gpu, r, ctxInfo) {
    auto context = ctxInfo.directContext();
    sk_sp<SkSurface> surface = create_gpu_surface(context);
    test_overdraw_surface(r, surface.get());
}

DEF_TEST(Surface_null, r) {
    REPORTER_ASSERT(r, SkSurface::MakeNull(0, 0) == nullptr);

    const int w = 37;
    const int h = 1000;
    auto surf = SkSurface::MakeNull(w, h);
    auto canvas = surf->getCanvas();

    canvas->drawPaint(SkPaint());   // should not crash, but don't expect anything to draw
    REPORTER_ASSERT(r, surf->makeImageSnapshot() == nullptr);
}

// assert: if a given imageinfo is valid for a surface, then it must be valid for an image
//         (so the snapshot can succeed)
DEF_TEST(surface_image_unity, reporter) {
    auto do_test = [reporter](const SkImageInfo& info) {
        size_t rowBytes = info.minRowBytes();
        auto surf = SkSurface::MakeRaster(info, rowBytes, nullptr);
        if (surf) {
            auto img = surf->makeImageSnapshot();
            if (!img && false) {    // change to true to document the differences
                SkDebugf("image failed: [%08X %08X] %14s %s\n",
                         info.width(),
                         info.height(),
                         ToolUtils::colortype_name(info.colorType()),
                         ToolUtils::alphatype_name(info.alphaType()));
                return;
            }
            REPORTER_ASSERT(reporter, img != nullptr);

            char tempPixel = 0;    // just need a valid address (not a valid size)
            SkPixmap pmap = { info, &tempPixel, rowBytes };
            img = SkImage::MakeFromRaster(pmap, nullptr, nullptr);
            REPORTER_ASSERT(reporter, img != nullptr);
        }
    };

    const int32_t sizes[] = { -1, 0, 1, 1 << 18 };
    for (int cti = 0; cti <= kLastEnum_SkColorType; ++cti) {
        SkColorType ct = static_cast<SkColorType>(cti);
        for (int ati = 0; ati <= kLastEnum_SkAlphaType; ++ati) {
            SkAlphaType at = static_cast<SkAlphaType>(ati);
            for (int32_t size : sizes) {
                do_test(SkImageInfo::Make(1, size, ct, at));
                do_test(SkImageInfo::Make(size, 1, ct, at));
            }
        }
    }
}
