/*
 * 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/BaseDevice.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/SurfaceFillContext.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,
                                       skgpu::SurfaceContext* 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 SurfaceContext 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 dContext->priv().makeSC(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 sfc = SkCanvasPriv::TopDeviceSurfaceFillContext(surface->getCanvas());
        if (!sfc) {
            ERRORF(reporter, "Could access surface context of GPU SkSurface.");
            return;
        }
        test_surface_context_clear(reporter, dContext, sfc, 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 sfc = SkCanvasPriv::TopDeviceSurfaceFillContext(surface->getCanvas());
        if (!sfc) {
            ERRORF(reporter, "Could access surface context of GPU SkSurface.");
            return;
        }
        test_surface_context_clear(reporter, dContext, sfc, 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));
            }
        }
    }
}
