1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2013 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
9cb93a386Sopenharmony_ci#include "include/core/SkData.h"
10cb93a386Sopenharmony_ci#include "include/core/SkOverdrawCanvas.h"
11cb93a386Sopenharmony_ci#include "include/core/SkPath.h"
12cb93a386Sopenharmony_ci#include "include/core/SkRRect.h"
13cb93a386Sopenharmony_ci#include "include/core/SkRegion.h"
14cb93a386Sopenharmony_ci#include "include/core/SkSurface.h"
15cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSurface.h"
16cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
17cb93a386Sopenharmony_ci#include "src/core/SkAutoPixmapStorage.h"
18cb93a386Sopenharmony_ci#include "src/core/SkCanvasPriv.h"
19cb93a386Sopenharmony_ci#include "src/core/SkDevice.h"
20cb93a386Sopenharmony_ci#include "src/core/SkUtils.h"
21cb93a386Sopenharmony_ci#include "src/gpu/BaseDevice.h"
22cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
23cb93a386Sopenharmony_ci#include "src/gpu/GrGpu.h"
24cb93a386Sopenharmony_ci#include "src/gpu/GrGpuResourcePriv.h"
25cb93a386Sopenharmony_ci#include "src/gpu/GrImageInfo.h"
26cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTarget.h"
27cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h"
28cb93a386Sopenharmony_ci#include "src/gpu/SurfaceFillContext.h"
29cb93a386Sopenharmony_ci#include "src/image/SkImage_Base.h"
30cb93a386Sopenharmony_ci#include "src/image/SkImage_Gpu.h"
31cb93a386Sopenharmony_ci#include "src/image/SkSurface_Gpu.h"
32cb93a386Sopenharmony_ci#include "tests/Test.h"
33cb93a386Sopenharmony_ci#include "tools/ToolUtils.h"
34cb93a386Sopenharmony_ci#include "tools/gpu/BackendSurfaceFactory.h"
35cb93a386Sopenharmony_ci#include "tools/gpu/ManagedBackendTexture.h"
36cb93a386Sopenharmony_ci#include "tools/gpu/ProxyUtils.h"
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_ci#include <functional>
39cb93a386Sopenharmony_ci#include <initializer_list>
40cb93a386Sopenharmony_ci#include <vector>
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_cistatic void release_direct_surface_storage(void* pixels, void* context) {
43cb93a386Sopenharmony_ci    SkASSERT(pixels == context);
44cb93a386Sopenharmony_ci    sk_free(pixels);
45cb93a386Sopenharmony_ci}
46cb93a386Sopenharmony_cistatic sk_sp<SkSurface> create_surface(SkAlphaType at = kPremul_SkAlphaType,
47cb93a386Sopenharmony_ci                                       SkImageInfo* requestedInfo = nullptr) {
48cb93a386Sopenharmony_ci    const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
49cb93a386Sopenharmony_ci    if (requestedInfo) {
50cb93a386Sopenharmony_ci        *requestedInfo = info;
51cb93a386Sopenharmony_ci    }
52cb93a386Sopenharmony_ci    return SkSurface::MakeRaster(info);
53cb93a386Sopenharmony_ci}
54cb93a386Sopenharmony_cistatic sk_sp<SkSurface> create_direct_surface(SkAlphaType at = kPremul_SkAlphaType,
55cb93a386Sopenharmony_ci                                              SkImageInfo* requestedInfo = nullptr) {
56cb93a386Sopenharmony_ci    const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
57cb93a386Sopenharmony_ci    if (requestedInfo) {
58cb93a386Sopenharmony_ci        *requestedInfo = info;
59cb93a386Sopenharmony_ci    }
60cb93a386Sopenharmony_ci    const size_t rowBytes = info.minRowBytes();
61cb93a386Sopenharmony_ci    void* storage = sk_malloc_throw(info.computeByteSize(rowBytes));
62cb93a386Sopenharmony_ci    return SkSurface::MakeRasterDirectReleaseProc(info, storage, rowBytes,
63cb93a386Sopenharmony_ci                                                  release_direct_surface_storage,
64cb93a386Sopenharmony_ci                                                  storage);
65cb93a386Sopenharmony_ci}
66cb93a386Sopenharmony_cistatic sk_sp<SkSurface> create_gpu_surface(GrRecordingContext* rContext,
67cb93a386Sopenharmony_ci                                           SkAlphaType at = kPremul_SkAlphaType,
68cb93a386Sopenharmony_ci                                           SkImageInfo* requestedInfo = nullptr) {
69cb93a386Sopenharmony_ci    const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
70cb93a386Sopenharmony_ci    if (requestedInfo) {
71cb93a386Sopenharmony_ci        *requestedInfo = info;
72cb93a386Sopenharmony_ci    }
73cb93a386Sopenharmony_ci    return SkSurface::MakeRenderTarget(rContext, SkBudgeted::kNo, info);
74cb93a386Sopenharmony_ci}
75cb93a386Sopenharmony_cistatic sk_sp<SkSurface> create_gpu_scratch_surface(GrRecordingContext* rContext,
76cb93a386Sopenharmony_ci                                                   SkAlphaType at = kPremul_SkAlphaType,
77cb93a386Sopenharmony_ci                                                   SkImageInfo* requestedInfo = nullptr) {
78cb93a386Sopenharmony_ci    const SkImageInfo info = SkImageInfo::MakeN32(10, 10, at);
79cb93a386Sopenharmony_ci    if (requestedInfo) {
80cb93a386Sopenharmony_ci        *requestedInfo = info;
81cb93a386Sopenharmony_ci    }
82cb93a386Sopenharmony_ci    return SkSurface::MakeRenderTarget(rContext, SkBudgeted::kYes, info);
83cb93a386Sopenharmony_ci}
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_ciDEF_TEST(SurfaceEmpty, reporter) {
86cb93a386Sopenharmony_ci    const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
87cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, nullptr == SkSurface::MakeRaster(info));
88cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, nullptr == SkSurface::MakeRasterDirect(info, nullptr, 0));
89cb93a386Sopenharmony_ci
90cb93a386Sopenharmony_ci}
91cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceEmpty_Gpu, reporter, ctxInfo) {
92cb93a386Sopenharmony_ci    const SkImageInfo info = SkImageInfo::Make(0, 0, kN32_SkColorType, kPremul_SkAlphaType);
93cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, nullptr ==
94cb93a386Sopenharmony_ci                    SkSurface::MakeRenderTarget(ctxInfo.directContext(), SkBudgeted::kNo, info));
95cb93a386Sopenharmony_ci}
96cb93a386Sopenharmony_ci
97cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrContext_colorTypeSupportedAsSurface, reporter, ctxInfo) {
98cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_ci    for (int ct = 0; ct < kLastEnum_SkColorType; ++ct) {
101cb93a386Sopenharmony_ci        static constexpr int kSize = 10;
102cb93a386Sopenharmony_ci
103cb93a386Sopenharmony_ci        SkColorType colorType = static_cast<SkColorType>(ct);
104cb93a386Sopenharmony_ci        auto info = SkImageInfo::Make(kSize, kSize, colorType, kOpaque_SkAlphaType, nullptr);
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ci        {
107cb93a386Sopenharmony_ci            bool can = context->colorTypeSupportedAsSurface(colorType);
108cb93a386Sopenharmony_ci            auto surf = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 1, nullptr);
109cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
110cb93a386Sopenharmony_ci                            colorType, can, SkToBool(surf));
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ci            surf = sk_gpu_test::MakeBackendTextureSurface(context,
113cb93a386Sopenharmony_ci                                                          {kSize, kSize},
114cb93a386Sopenharmony_ci                                                          kTopLeft_GrSurfaceOrigin,
115cb93a386Sopenharmony_ci                                                          /*sample cnt*/ 1,
116cb93a386Sopenharmony_ci                                                          colorType);
117cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
118cb93a386Sopenharmony_ci                            colorType, can, SkToBool(surf));
119cb93a386Sopenharmony_ci        }
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_ci        // The MSAA test only makes sense if the colorType is renderable to begin with.
122cb93a386Sopenharmony_ci        if (context->colorTypeSupportedAsSurface(colorType)) {
123cb93a386Sopenharmony_ci            static constexpr int kSampleCnt = 2;
124cb93a386Sopenharmony_ci
125cb93a386Sopenharmony_ci            bool can = context->maxSurfaceSampleCountForColorType(colorType) >= kSampleCnt;
126cb93a386Sopenharmony_ci            auto surf = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, kSampleCnt,
127cb93a386Sopenharmony_ci                                                    nullptr);
128cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, can: %d, surf: %d",
129cb93a386Sopenharmony_ci                            colorType, can, SkToBool(surf));
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_ci            surf = sk_gpu_test::MakeBackendTextureSurface(
132cb93a386Sopenharmony_ci                    context, {kSize, kSize}, kTopLeft_GrSurfaceOrigin, kSampleCnt, colorType);
133cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, can == SkToBool(surf),
134cb93a386Sopenharmony_ci                            "colorTypeSupportedAsSurface:%d, surf:%d, ct:%d", can, SkToBool(surf),
135cb93a386Sopenharmony_ci                            colorType);
136cb93a386Sopenharmony_ci            // Ensure that the sample count stored on the resulting SkSurface is a valid value.
137cb93a386Sopenharmony_ci            if (surf) {
138cb93a386Sopenharmony_ci                auto rtp = SkCanvasPriv::TopDeviceTargetProxy(surf->getCanvas());
139cb93a386Sopenharmony_ci                int storedCnt = rtp->numSamples();
140cb93a386Sopenharmony_ci                const GrBackendFormat& format = rtp->backendFormat();
141cb93a386Sopenharmony_ci                int allowedCnt =
142cb93a386Sopenharmony_ci                        context->priv().caps()->getRenderTargetSampleCount(storedCnt, format);
143cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, storedCnt == allowedCnt,
144cb93a386Sopenharmony_ci                                "Should store an allowed sample count (%d vs %d)", allowedCnt,
145cb93a386Sopenharmony_ci                                storedCnt);
146cb93a386Sopenharmony_ci            }
147cb93a386Sopenharmony_ci        }
148cb93a386Sopenharmony_ci
149cb93a386Sopenharmony_ci        for (int sampleCnt : {1, 2}) {
150cb93a386Sopenharmony_ci            auto surf = sk_gpu_test::MakeBackendRenderTargetSurface(context,
151cb93a386Sopenharmony_ci                                                                    {16, 16},
152cb93a386Sopenharmony_ci                                                                    kTopLeft_GrSurfaceOrigin,
153cb93a386Sopenharmony_ci                                                                    sampleCnt,
154cb93a386Sopenharmony_ci                                                                    colorType);
155cb93a386Sopenharmony_ci            bool can = context->colorTypeSupportedAsSurface(colorType) &&
156cb93a386Sopenharmony_ci                       context->maxSurfaceSampleCountForColorType(colorType) >= sampleCnt;
157cb93a386Sopenharmony_ci            if (!surf && can && colorType == kBGRA_8888_SkColorType && sampleCnt > 1 &&
158cb93a386Sopenharmony_ci                context->backend() == GrBackendApi::kOpenGL) {
159cb93a386Sopenharmony_ci                // This is an execeptional case. On iOS GLES we support MSAA BGRA for internally-
160cb93a386Sopenharmony_ci                // created render targets by using a MSAA RGBA8 renderbuffer that resolves to a
161cb93a386Sopenharmony_ci                // BGRA8 texture. However, the GL_APPLE_texture_format_BGRA8888 extension does not
162cb93a386Sopenharmony_ci                // allow creation of BGRA8 renderbuffers and we don't support multisampled textures.
163cb93a386Sopenharmony_ci                // So this is expected to fail. As of 10/5/2020 it actually seems to work to create
164cb93a386Sopenharmony_ci                // a MSAA BGRA8 renderbuffer (at least in the simulator) but we don't want to rely
165cb93a386Sopenharmony_ci                // on this undocumented behavior.
166cb93a386Sopenharmony_ci                continue;
167cb93a386Sopenharmony_ci            }
168cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, can == SkToBool(surf), "ct: %d, sc: %d, can: %d, surf: %d",
169cb93a386Sopenharmony_ci                            colorType, sampleCnt, can, SkToBool(surf));
170cb93a386Sopenharmony_ci            if (surf) {
171cb93a386Sopenharmony_ci                auto rtp = SkCanvasPriv::TopDeviceTargetProxy(surf->getCanvas());
172cb93a386Sopenharmony_ci                int storedCnt = rtp->numSamples();
173cb93a386Sopenharmony_ci                const GrBackendFormat& backendFormat = rtp->backendFormat();
174cb93a386Sopenharmony_ci                int allowedCnt = context->priv().caps()->getRenderTargetSampleCount(storedCnt,
175cb93a386Sopenharmony_ci                                                                                    backendFormat);
176cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, storedCnt == allowedCnt,
177cb93a386Sopenharmony_ci                                "Should store an allowed sample count (%d vs %d)", allowedCnt,
178cb93a386Sopenharmony_ci                                storedCnt);
179cb93a386Sopenharmony_ci            }
180cb93a386Sopenharmony_ci        }
181cb93a386Sopenharmony_ci    }
182cb93a386Sopenharmony_ci}
183cb93a386Sopenharmony_ci
184cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrContext_maxSurfaceSamplesForColorType, reporter, ctxInfo) {
185cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
186cb93a386Sopenharmony_ci
187cb93a386Sopenharmony_ci    static constexpr int kSize = 10;
188cb93a386Sopenharmony_ci
189cb93a386Sopenharmony_ci    for (int ct = 0; ct < kLastEnum_SkColorType; ++ct) {
190cb93a386Sopenharmony_ci
191cb93a386Sopenharmony_ci        SkColorType colorType = static_cast<SkColorType>(ct);
192cb93a386Sopenharmony_ci        int maxSampleCnt = context->maxSurfaceSampleCountForColorType(colorType);
193cb93a386Sopenharmony_ci        if (!maxSampleCnt) {
194cb93a386Sopenharmony_ci            continue;
195cb93a386Sopenharmony_ci        }
196cb93a386Sopenharmony_ci        if (!context->colorTypeSupportedAsSurface(colorType)) {
197cb93a386Sopenharmony_ci            continue;
198cb93a386Sopenharmony_ci        }
199cb93a386Sopenharmony_ci
200cb93a386Sopenharmony_ci        auto info = SkImageInfo::Make(kSize, kSize, colorType, kOpaque_SkAlphaType, nullptr);
201cb93a386Sopenharmony_ci        auto surf = sk_gpu_test::MakeBackendTextureSurface(
202cb93a386Sopenharmony_ci                context, info, kTopLeft_GrSurfaceOrigin, maxSampleCnt);
203cb93a386Sopenharmony_ci        if (!surf) {
204cb93a386Sopenharmony_ci            ERRORF(reporter, "Could not make surface of color type %d.", colorType);
205cb93a386Sopenharmony_ci            continue;
206cb93a386Sopenharmony_ci        }
207cb93a386Sopenharmony_ci        int sampleCnt =
208cb93a386Sopenharmony_ci            ((SkSurface_Gpu*)(surf.get()))->getDevice()->targetProxy()->numSamples();
209cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, sampleCnt == maxSampleCnt, "Exected: %d, actual: %d",
210cb93a386Sopenharmony_ci                        maxSampleCnt, sampleCnt);
211cb93a386Sopenharmony_ci    }
212cb93a386Sopenharmony_ci}
213cb93a386Sopenharmony_ci
214cb93a386Sopenharmony_cistatic void test_canvas_peek(skiatest::Reporter* reporter,
215cb93a386Sopenharmony_ci                             sk_sp<SkSurface>& surface,
216cb93a386Sopenharmony_ci                             const SkImageInfo& requestInfo,
217cb93a386Sopenharmony_ci                             bool expectPeekSuccess) {
218cb93a386Sopenharmony_ci    const SkColor color = SK_ColorRED;
219cb93a386Sopenharmony_ci    const SkPMColor pmcolor = SkPreMultiplyColor(color);
220cb93a386Sopenharmony_ci    surface->getCanvas()->clear(color);
221cb93a386Sopenharmony_ci
222cb93a386Sopenharmony_ci    SkPixmap pmap;
223cb93a386Sopenharmony_ci    bool success = surface->getCanvas()->peekPixels(&pmap);
224cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, expectPeekSuccess == success);
225cb93a386Sopenharmony_ci
226cb93a386Sopenharmony_ci    SkPixmap pmap2;
227cb93a386Sopenharmony_ci    const void* addr2 = surface->peekPixels(&pmap2) ? pmap2.addr() : nullptr;
228cb93a386Sopenharmony_ci
229cb93a386Sopenharmony_ci    if (success) {
230cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, requestInfo == pmap.info());
231cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, requestInfo.minRowBytes() <= pmap.rowBytes());
232cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, pmcolor == *pmap.addr32());
233cb93a386Sopenharmony_ci
234cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, pmap.addr() == pmap2.addr());
235cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, pmap.info() == pmap2.info());
236cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, pmap.rowBytes() == pmap2.rowBytes());
237cb93a386Sopenharmony_ci    } else {
238cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, nullptr == addr2);
239cb93a386Sopenharmony_ci    }
240cb93a386Sopenharmony_ci}
241cb93a386Sopenharmony_ciDEF_TEST(SurfaceCanvasPeek, reporter) {
242cb93a386Sopenharmony_ci    for (auto& surface_func : { &create_surface, &create_direct_surface }) {
243cb93a386Sopenharmony_ci        SkImageInfo requestInfo;
244cb93a386Sopenharmony_ci        auto surface(surface_func(kPremul_SkAlphaType, &requestInfo));
245cb93a386Sopenharmony_ci        test_canvas_peek(reporter, surface, requestInfo, true);
246cb93a386Sopenharmony_ci    }
247cb93a386Sopenharmony_ci}
248cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCanvasPeek_Gpu, reporter, ctxInfo) {
249cb93a386Sopenharmony_ci    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
250cb93a386Sopenharmony_ci        SkImageInfo requestInfo;
251cb93a386Sopenharmony_ci        auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, &requestInfo));
252cb93a386Sopenharmony_ci        test_canvas_peek(reporter, surface, requestInfo, false);
253cb93a386Sopenharmony_ci    }
254cb93a386Sopenharmony_ci}
255cb93a386Sopenharmony_ci
256cb93a386Sopenharmony_cistatic void test_snapshot_alphatype(skiatest::Reporter* reporter, const sk_sp<SkSurface>& surface,
257cb93a386Sopenharmony_ci                                    SkAlphaType expectedAlphaType) {
258cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, surface);
259cb93a386Sopenharmony_ci    if (surface) {
260cb93a386Sopenharmony_ci        sk_sp<SkImage> image(surface->makeImageSnapshot());
261cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, image);
262cb93a386Sopenharmony_ci        if (image) {
263cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, image->alphaType() == expectedAlphaType);
264cb93a386Sopenharmony_ci        }
265cb93a386Sopenharmony_ci    }
266cb93a386Sopenharmony_ci}
267cb93a386Sopenharmony_ciDEF_TEST(SurfaceSnapshotAlphaType, reporter) {
268cb93a386Sopenharmony_ci    for (auto& surface_func : { &create_surface, &create_direct_surface }) {
269cb93a386Sopenharmony_ci        for (auto& at: { kOpaque_SkAlphaType, kPremul_SkAlphaType, kUnpremul_SkAlphaType }) {
270cb93a386Sopenharmony_ci            auto surface(surface_func(at, nullptr));
271cb93a386Sopenharmony_ci            test_snapshot_alphatype(reporter, surface, at);
272cb93a386Sopenharmony_ci        }
273cb93a386Sopenharmony_ci    }
274cb93a386Sopenharmony_ci}
275cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceSnapshotAlphaType_Gpu, reporter, ctxInfo) {
276cb93a386Sopenharmony_ci    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
277cb93a386Sopenharmony_ci        // GPU doesn't support creating unpremul surfaces, so only test opaque + premul
278cb93a386Sopenharmony_ci        for (auto& at : { kOpaque_SkAlphaType, kPremul_SkAlphaType }) {
279cb93a386Sopenharmony_ci            auto surface(surface_func(ctxInfo.directContext(), at, nullptr));
280cb93a386Sopenharmony_ci            test_snapshot_alphatype(reporter, surface, at);
281cb93a386Sopenharmony_ci        }
282cb93a386Sopenharmony_ci    }
283cb93a386Sopenharmony_ci}
284cb93a386Sopenharmony_ci
285cb93a386Sopenharmony_cistatic void test_backend_texture_access_copy_on_write(
286cb93a386Sopenharmony_ci    skiatest::Reporter* reporter, SkSurface* surface, SkSurface::BackendHandleAccess access) {
287cb93a386Sopenharmony_ci    GrBackendTexture tex1 = surface->getBackendTexture(access);
288cb93a386Sopenharmony_ci    sk_sp<SkImage> snap1(surface->makeImageSnapshot());
289cb93a386Sopenharmony_ci
290cb93a386Sopenharmony_ci    GrBackendTexture tex2 = surface->getBackendTexture(access);
291cb93a386Sopenharmony_ci    sk_sp<SkImage> snap2(surface->makeImageSnapshot());
292cb93a386Sopenharmony_ci
293cb93a386Sopenharmony_ci    // If the access mode triggers CoW, then the backend objects should reflect it.
294cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(tex1, tex2) == (snap1 == snap2));
295cb93a386Sopenharmony_ci}
296cb93a386Sopenharmony_ci
297cb93a386Sopenharmony_cistatic void test_backend_rendertarget_access_copy_on_write(
298cb93a386Sopenharmony_ci    skiatest::Reporter* reporter, SkSurface* surface, SkSurface::BackendHandleAccess access) {
299cb93a386Sopenharmony_ci    GrBackendRenderTarget rt1 = surface->getBackendRenderTarget(access);
300cb93a386Sopenharmony_ci    sk_sp<SkImage> snap1(surface->makeImageSnapshot());
301cb93a386Sopenharmony_ci
302cb93a386Sopenharmony_ci    GrBackendRenderTarget rt2 = surface->getBackendRenderTarget(access);
303cb93a386Sopenharmony_ci    sk_sp<SkImage> snap2(surface->makeImageSnapshot());
304cb93a386Sopenharmony_ci
305cb93a386Sopenharmony_ci    // If the access mode triggers CoW, then the backend objects should reflect it.
306cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, GrBackendRenderTarget::TestingOnly_Equals(rt1, rt2) ==
307cb93a386Sopenharmony_ci                              (snap1 == snap2));
308cb93a386Sopenharmony_ci}
309cb93a386Sopenharmony_ci
310cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendSurfaceAccessCopyOnWrite_Gpu, reporter, ctxInfo) {
311cb93a386Sopenharmony_ci    const SkSurface::BackendHandleAccess accessModes[] = {
312cb93a386Sopenharmony_ci        SkSurface::kFlushRead_BackendHandleAccess,
313cb93a386Sopenharmony_ci        SkSurface::kFlushWrite_BackendHandleAccess,
314cb93a386Sopenharmony_ci        SkSurface::kDiscardWrite_BackendHandleAccess,
315cb93a386Sopenharmony_ci    };
316cb93a386Sopenharmony_ci
317cb93a386Sopenharmony_ci    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
318cb93a386Sopenharmony_ci        for (auto& accessMode : accessModes) {
319cb93a386Sopenharmony_ci            {
320cb93a386Sopenharmony_ci                auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
321cb93a386Sopenharmony_ci                test_backend_texture_access_copy_on_write(reporter, surface.get(), accessMode);
322cb93a386Sopenharmony_ci            }
323cb93a386Sopenharmony_ci            {
324cb93a386Sopenharmony_ci                auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
325cb93a386Sopenharmony_ci                test_backend_rendertarget_access_copy_on_write(reporter, surface.get(), accessMode);
326cb93a386Sopenharmony_ci            }
327cb93a386Sopenharmony_ci        }
328cb93a386Sopenharmony_ci    }
329cb93a386Sopenharmony_ci}
330cb93a386Sopenharmony_ci
331cb93a386Sopenharmony_citemplate<typename Type, Type(SkSurface::*func)(SkSurface::BackendHandleAccess)>
332cb93a386Sopenharmony_cistatic void test_backend_unique_id(skiatest::Reporter* reporter, SkSurface* surface) {
333cb93a386Sopenharmony_ci    sk_sp<SkImage> image0(surface->makeImageSnapshot());
334cb93a386Sopenharmony_ci
335cb93a386Sopenharmony_ci    Type obj = (surface->*func)(SkSurface::kFlushRead_BackendHandleAccess);
336cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, obj.isValid());
337cb93a386Sopenharmony_ci    sk_sp<SkImage> image1(surface->makeImageSnapshot());
338cb93a386Sopenharmony_ci    // just read access should not affect the snapshot
339cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, image0->uniqueID() == image1->uniqueID());
340cb93a386Sopenharmony_ci
341cb93a386Sopenharmony_ci    obj = (surface->*func)(SkSurface::kFlushWrite_BackendHandleAccess);
342cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, obj.isValid());
343cb93a386Sopenharmony_ci    sk_sp<SkImage> image2(surface->makeImageSnapshot());
344cb93a386Sopenharmony_ci    // expect a new image, since we claimed we would write
345cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, image0->uniqueID() != image2->uniqueID());
346cb93a386Sopenharmony_ci
347cb93a386Sopenharmony_ci    obj = (surface->*func)(SkSurface::kDiscardWrite_BackendHandleAccess);
348cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, obj.isValid());
349cb93a386Sopenharmony_ci    sk_sp<SkImage> image3(surface->makeImageSnapshot());
350cb93a386Sopenharmony_ci    // expect a new(er) image, since we claimed we would write
351cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, image0->uniqueID() != image3->uniqueID());
352cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, image2->uniqueID() != image3->uniqueID());
353cb93a386Sopenharmony_ci}
354cb93a386Sopenharmony_ci
355cb93a386Sopenharmony_ci// No CPU test.
356cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendHandleAccessIDs_Gpu, reporter, ctxInfo) {
357cb93a386Sopenharmony_ci    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
358cb93a386Sopenharmony_ci        {
359cb93a386Sopenharmony_ci            auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
360cb93a386Sopenharmony_ci            test_backend_unique_id<GrBackendTexture, &SkSurface::getBackendTexture>(reporter,
361cb93a386Sopenharmony_ci                                                                                    surface.get());
362cb93a386Sopenharmony_ci        }
363cb93a386Sopenharmony_ci        {
364cb93a386Sopenharmony_ci            auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
365cb93a386Sopenharmony_ci            test_backend_unique_id<GrBackendRenderTarget, &SkSurface::getBackendRenderTarget>(
366cb93a386Sopenharmony_ci                                                                reporter, surface.get());
367cb93a386Sopenharmony_ci        }
368cb93a386Sopenharmony_ci    }
369cb93a386Sopenharmony_ci}
370cb93a386Sopenharmony_ci
371cb93a386Sopenharmony_ci// No CPU test.
372cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceAbandonPostFlush_Gpu, reporter, ctxInfo) {
373cb93a386Sopenharmony_ci    auto direct = ctxInfo.directContext();
374cb93a386Sopenharmony_ci    sk_sp<SkSurface> surface = create_gpu_surface(direct, kPremul_SkAlphaType, nullptr);
375cb93a386Sopenharmony_ci    if (!surface) {
376cb93a386Sopenharmony_ci        return;
377cb93a386Sopenharmony_ci    }
378cb93a386Sopenharmony_ci    // This flush can put command buffer refs on the GrGpuResource for the surface.
379cb93a386Sopenharmony_ci    surface->flush();
380cb93a386Sopenharmony_ci    direct->abandonContext();
381cb93a386Sopenharmony_ci    // We pass the test if we don't hit any asserts or crashes when the ref on the surface goes away
382cb93a386Sopenharmony_ci    // after we abanonded the context. One thing specifically this checks is to make sure we're
383cb93a386Sopenharmony_ci    // correctly handling the mix of normal refs and command buffer refs, and correctly deleting
384cb93a386Sopenharmony_ci    // the object at the right time.
385cb93a386Sopenharmony_ci}
386cb93a386Sopenharmony_ci
387cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBackendAccessAbandoned_Gpu, reporter, ctxInfo) {
388cb93a386Sopenharmony_ci    auto dContext = ctxInfo.directContext();
389cb93a386Sopenharmony_ci    sk_sp<SkSurface> surface = create_gpu_surface(dContext, kPremul_SkAlphaType, nullptr);
390cb93a386Sopenharmony_ci    if (!surface) {
391cb93a386Sopenharmony_ci        return;
392cb93a386Sopenharmony_ci    }
393cb93a386Sopenharmony_ci
394cb93a386Sopenharmony_ci    GrBackendRenderTarget beRT =
395cb93a386Sopenharmony_ci            surface->getBackendRenderTarget(SkSurface::kFlushRead_BackendHandleAccess);
396cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, beRT.isValid());
397cb93a386Sopenharmony_ci    GrBackendTexture beTex =
398cb93a386Sopenharmony_ci            surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess);
399cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, beTex.isValid());
400cb93a386Sopenharmony_ci
401cb93a386Sopenharmony_ci    surface->flush();
402cb93a386Sopenharmony_ci    dContext->abandonContext();
403cb93a386Sopenharmony_ci
404cb93a386Sopenharmony_ci    // After abandoning the context none of the backend surfaces should be valid.
405cb93a386Sopenharmony_ci    beRT = surface->getBackendRenderTarget(SkSurface::kFlushRead_BackendHandleAccess);
406cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !beRT.isValid());
407cb93a386Sopenharmony_ci    beTex = surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess);
408cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !beTex.isValid());
409cb93a386Sopenharmony_ci}
410cb93a386Sopenharmony_ci
411cb93a386Sopenharmony_ci// Verify that the right canvas commands trigger a copy on write.
412cb93a386Sopenharmony_cistatic void test_copy_on_write(skiatest::Reporter* reporter, SkSurface* surface) {
413cb93a386Sopenharmony_ci    SkCanvas* canvas = surface->getCanvas();
414cb93a386Sopenharmony_ci
415cb93a386Sopenharmony_ci    const SkRect testRect =
416cb93a386Sopenharmony_ci        SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
417cb93a386Sopenharmony_ci                         SkIntToScalar(4), SkIntToScalar(5));
418cb93a386Sopenharmony_ci    SkPath testPath;
419cb93a386Sopenharmony_ci    testPath.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
420cb93a386Sopenharmony_ci                                      SkIntToScalar(2), SkIntToScalar(1)));
421cb93a386Sopenharmony_ci
422cb93a386Sopenharmony_ci    const SkIRect testIRect = SkIRect::MakeXYWH(0, 0, 2, 1);
423cb93a386Sopenharmony_ci
424cb93a386Sopenharmony_ci    SkRegion testRegion;
425cb93a386Sopenharmony_ci    testRegion.setRect(testIRect);
426cb93a386Sopenharmony_ci
427cb93a386Sopenharmony_ci
428cb93a386Sopenharmony_ci    const SkColor testColor = 0x01020304;
429cb93a386Sopenharmony_ci    const SkPaint testPaint;
430cb93a386Sopenharmony_ci    const SkPoint testPoints[3] = {
431cb93a386Sopenharmony_ci        {SkIntToScalar(0), SkIntToScalar(0)},
432cb93a386Sopenharmony_ci        {SkIntToScalar(2), SkIntToScalar(1)},
433cb93a386Sopenharmony_ci        {SkIntToScalar(0), SkIntToScalar(2)}
434cb93a386Sopenharmony_ci    };
435cb93a386Sopenharmony_ci    const size_t testPointCount = 3;
436cb93a386Sopenharmony_ci
437cb93a386Sopenharmony_ci    SkBitmap testBitmap;
438cb93a386Sopenharmony_ci    testBitmap.allocN32Pixels(10, 10);
439cb93a386Sopenharmony_ci    testBitmap.eraseColor(0);
440cb93a386Sopenharmony_ci
441cb93a386Sopenharmony_ci    SkRRect testRRect;
442cb93a386Sopenharmony_ci    testRRect.setRectXY(testRect, SK_Scalar1, SK_Scalar1);
443cb93a386Sopenharmony_ci
444cb93a386Sopenharmony_ci    SkString testText("Hello World");
445cb93a386Sopenharmony_ci
446cb93a386Sopenharmony_ci#define EXPECT_COPY_ON_WRITE(command)                               \
447cb93a386Sopenharmony_ci    {                                                               \
448cb93a386Sopenharmony_ci        sk_sp<SkImage> imageBefore = surface->makeImageSnapshot();  \
449cb93a386Sopenharmony_ci        sk_sp<SkImage> aur_before(imageBefore);  /*NOLINT*/         \
450cb93a386Sopenharmony_ci        canvas-> command ;                                          \
451cb93a386Sopenharmony_ci        sk_sp<SkImage> imageAfter = surface->makeImageSnapshot();   \
452cb93a386Sopenharmony_ci        sk_sp<SkImage> aur_after(imageAfter);  /*NOLINT*/           \
453cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, imageBefore != imageAfter);       \
454cb93a386Sopenharmony_ci    }
455cb93a386Sopenharmony_ci
456cb93a386Sopenharmony_ci    EXPECT_COPY_ON_WRITE(clear(testColor))
457cb93a386Sopenharmony_ci    EXPECT_COPY_ON_WRITE(drawPaint(testPaint))
458cb93a386Sopenharmony_ci    EXPECT_COPY_ON_WRITE(drawPoints(SkCanvas::kPoints_PointMode, testPointCount, testPoints, \
459cb93a386Sopenharmony_ci        testPaint))
460cb93a386Sopenharmony_ci    EXPECT_COPY_ON_WRITE(drawOval(testRect, testPaint))
461cb93a386Sopenharmony_ci    EXPECT_COPY_ON_WRITE(drawRect(testRect, testPaint))
462cb93a386Sopenharmony_ci    EXPECT_COPY_ON_WRITE(drawRRect(testRRect, testPaint))
463cb93a386Sopenharmony_ci    EXPECT_COPY_ON_WRITE(drawPath(testPath, testPaint))
464cb93a386Sopenharmony_ci    EXPECT_COPY_ON_WRITE(drawImage(testBitmap.asImage(), 0, 0))
465cb93a386Sopenharmony_ci    EXPECT_COPY_ON_WRITE(drawImageRect(testBitmap.asImage(), testRect, SkSamplingOptions()))
466cb93a386Sopenharmony_ci    EXPECT_COPY_ON_WRITE(drawString(testText, 0, 1, SkFont(), testPaint))
467cb93a386Sopenharmony_ci}
468cb93a386Sopenharmony_ciDEF_TEST(SurfaceCopyOnWrite, reporter) {
469cb93a386Sopenharmony_ci    test_copy_on_write(reporter, create_surface().get());
470cb93a386Sopenharmony_ci}
471cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCopyOnWrite_Gpu, reporter, ctxInfo) {
472cb93a386Sopenharmony_ci    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
473cb93a386Sopenharmony_ci        auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
474cb93a386Sopenharmony_ci        test_copy_on_write(reporter, surface.get());
475cb93a386Sopenharmony_ci    }
476cb93a386Sopenharmony_ci}
477cb93a386Sopenharmony_ci
478cb93a386Sopenharmony_cistatic void test_writable_after_snapshot_release(skiatest::Reporter* reporter,
479cb93a386Sopenharmony_ci                                                 SkSurface* surface) {
480cb93a386Sopenharmony_ci    // This test succeeds by not triggering an assertion.
481cb93a386Sopenharmony_ci    // The test verifies that the surface remains writable (usable) after
482cb93a386Sopenharmony_ci    // acquiring and releasing a snapshot without triggering a copy on write.
483cb93a386Sopenharmony_ci    SkCanvas* canvas = surface->getCanvas();
484cb93a386Sopenharmony_ci    canvas->clear(1);
485cb93a386Sopenharmony_ci    surface->makeImageSnapshot();  // Create and destroy SkImage
486cb93a386Sopenharmony_ci    canvas->clear(2);  // Must not assert internally
487cb93a386Sopenharmony_ci}
488cb93a386Sopenharmony_ciDEF_TEST(SurfaceWriteableAfterSnapshotRelease, reporter) {
489cb93a386Sopenharmony_ci    test_writable_after_snapshot_release(reporter, create_surface().get());
490cb93a386Sopenharmony_ci}
491cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceWriteableAfterSnapshotRelease_Gpu, reporter, ctxInfo) {
492cb93a386Sopenharmony_ci    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
493cb93a386Sopenharmony_ci        auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
494cb93a386Sopenharmony_ci        test_writable_after_snapshot_release(reporter, surface.get());
495cb93a386Sopenharmony_ci    }
496cb93a386Sopenharmony_ci}
497cb93a386Sopenharmony_ci
498cb93a386Sopenharmony_cistatic void test_crbug263329(skiatest::Reporter* reporter,
499cb93a386Sopenharmony_ci                             SkSurface* surface1,
500cb93a386Sopenharmony_ci                             SkSurface* surface2) {
501cb93a386Sopenharmony_ci    // This is a regression test for crbug.com/263329
502cb93a386Sopenharmony_ci    // Bug was caused by onCopyOnWrite releasing the old surface texture
503cb93a386Sopenharmony_ci    // back to the scratch texture pool even though the texture is used
504cb93a386Sopenharmony_ci    // by and active SkImage_Gpu.
505cb93a386Sopenharmony_ci    SkCanvas* canvas1 = surface1->getCanvas();
506cb93a386Sopenharmony_ci    SkCanvas* canvas2 = surface2->getCanvas();
507cb93a386Sopenharmony_ci    canvas1->clear(1);
508cb93a386Sopenharmony_ci    sk_sp<SkImage> image1(surface1->makeImageSnapshot());
509cb93a386Sopenharmony_ci    // Trigger copy on write, new backing is a scratch texture
510cb93a386Sopenharmony_ci    canvas1->clear(2);
511cb93a386Sopenharmony_ci    sk_sp<SkImage> image2(surface1->makeImageSnapshot());
512cb93a386Sopenharmony_ci    // Trigger copy on write, old backing should not be returned to scratch
513cb93a386Sopenharmony_ci    // pool because it is held by image2
514cb93a386Sopenharmony_ci    canvas1->clear(3);
515cb93a386Sopenharmony_ci
516cb93a386Sopenharmony_ci    canvas2->clear(4);
517cb93a386Sopenharmony_ci    sk_sp<SkImage> image3(surface2->makeImageSnapshot());
518cb93a386Sopenharmony_ci    // Trigger copy on write on surface2. The new backing store should not
519cb93a386Sopenharmony_ci    // be recycling a texture that is held by an existing image.
520cb93a386Sopenharmony_ci    canvas2->clear(5);
521cb93a386Sopenharmony_ci    sk_sp<SkImage> image4(surface2->makeImageSnapshot());
522cb93a386Sopenharmony_ci
523cb93a386Sopenharmony_ci    auto imageProxy = [ctx = surface1->recordingContext()](SkImage* img) {
524cb93a386Sopenharmony_ci        GrTextureProxy* proxy = sk_gpu_test::GetTextureImageProxy(img, ctx);
525cb93a386Sopenharmony_ci        SkASSERT(proxy);
526cb93a386Sopenharmony_ci        return proxy;
527cb93a386Sopenharmony_ci    };
528cb93a386Sopenharmony_ci
529cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, imageProxy(image4.get()) != imageProxy(image3.get()));
530cb93a386Sopenharmony_ci    // The following assertion checks crbug.com/263329
531cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, imageProxy(image4.get()) != imageProxy(image2.get()));
532cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, imageProxy(image4.get()) != imageProxy(image1.get()));
533cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, imageProxy(image3.get()) != imageProxy(image2.get()));
534cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, imageProxy(image3.get()) != imageProxy(image1.get()));
535cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, imageProxy(image2.get()) != imageProxy(image1.get()));
536cb93a386Sopenharmony_ci}
537cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceCRBug263329_Gpu, reporter, ctxInfo) {
538cb93a386Sopenharmony_ci    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
539cb93a386Sopenharmony_ci        auto surface1(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
540cb93a386Sopenharmony_ci        auto surface2(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
541cb93a386Sopenharmony_ci        test_crbug263329(reporter, surface1.get(), surface2.get());
542cb93a386Sopenharmony_ci    }
543cb93a386Sopenharmony_ci}
544cb93a386Sopenharmony_ci
545cb93a386Sopenharmony_ciDEF_TEST(SurfaceGetTexture, reporter) {
546cb93a386Sopenharmony_ci    auto surface(create_surface());
547cb93a386Sopenharmony_ci    sk_sp<SkImage> image(surface->makeImageSnapshot());
548cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !as_IB(image)->isTextureBacked());
549cb93a386Sopenharmony_ci    surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
550cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !as_IB(image)->isTextureBacked());
551cb93a386Sopenharmony_ci}
552cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfacepeekTexture_Gpu, reporter, ctxInfo) {
553cb93a386Sopenharmony_ci    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
554cb93a386Sopenharmony_ci        auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
555cb93a386Sopenharmony_ci        sk_sp<SkImage> image(surface->makeImageSnapshot());
556cb93a386Sopenharmony_ci
557cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, as_IB(image)->isTextureBacked());
558cb93a386Sopenharmony_ci        GrBackendTexture backendTex = image->getBackendTexture(false);
559cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, backendTex.isValid());
560cb93a386Sopenharmony_ci        surface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
561cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, as_IB(image)->isTextureBacked());
562cb93a386Sopenharmony_ci        GrBackendTexture backendTex2 = image->getBackendTexture(false);
563cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(backendTex, backendTex2));
564cb93a386Sopenharmony_ci    }
565cb93a386Sopenharmony_ci}
566cb93a386Sopenharmony_ci
567cb93a386Sopenharmony_cistatic SkBudgeted is_budgeted(const sk_sp<SkSurface>& surf) {
568cb93a386Sopenharmony_ci    SkSurface_Gpu* gsurf = (SkSurface_Gpu*)surf.get();
569cb93a386Sopenharmony_ci
570cb93a386Sopenharmony_ci    GrRenderTargetProxy* proxy = gsurf->getDevice()->targetProxy();
571cb93a386Sopenharmony_ci    return proxy->isBudgeted();
572cb93a386Sopenharmony_ci}
573cb93a386Sopenharmony_ci
574cb93a386Sopenharmony_cistatic SkBudgeted is_budgeted(SkImage* image, GrRecordingContext* rc) {
575cb93a386Sopenharmony_ci    return sk_gpu_test::GetTextureImageProxy(image, rc)->isBudgeted();
576cb93a386Sopenharmony_ci}
577cb93a386Sopenharmony_ci
578cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceBudget, reporter, ctxInfo) {
579cb93a386Sopenharmony_ci    SkImageInfo info = SkImageInfo::MakeN32Premul(8,8);
580cb93a386Sopenharmony_ci    GrDirectContext* dContext = ctxInfo.directContext();
581cb93a386Sopenharmony_ci    for (auto budgeted : { SkBudgeted::kNo, SkBudgeted::kYes }) {
582cb93a386Sopenharmony_ci        auto surface(SkSurface::MakeRenderTarget(dContext, budgeted, info));
583cb93a386Sopenharmony_ci        SkASSERT(surface);
584cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, budgeted == is_budgeted(surface));
585cb93a386Sopenharmony_ci
586cb93a386Sopenharmony_ci        sk_sp<SkImage> image(surface->makeImageSnapshot());
587cb93a386Sopenharmony_ci
588cb93a386Sopenharmony_ci        // Initially the image shares a texture with the surface, and the
589cb93a386Sopenharmony_ci        // the budgets should always match.
590cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, budgeted == is_budgeted(surface));
591cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, budgeted == is_budgeted(image.get(), dContext));
592cb93a386Sopenharmony_ci
593cb93a386Sopenharmony_ci        // Now trigger copy-on-write
594cb93a386Sopenharmony_ci        surface->getCanvas()->clear(SK_ColorBLUE);
595cb93a386Sopenharmony_ci
596cb93a386Sopenharmony_ci        // They don't share a texture anymore but the budgets should still match.
597cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, budgeted == is_budgeted(surface));
598cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, budgeted == is_budgeted(image.get(), dContext));
599cb93a386Sopenharmony_ci    }
600cb93a386Sopenharmony_ci}
601cb93a386Sopenharmony_ci
602cb93a386Sopenharmony_cistatic void test_no_canvas1(skiatest::Reporter* reporter,
603cb93a386Sopenharmony_ci                            SkSurface* surface,
604cb93a386Sopenharmony_ci                            SkSurface::ContentChangeMode mode) {
605cb93a386Sopenharmony_ci    // Test passes by not asserting
606cb93a386Sopenharmony_ci    surface->notifyContentWillChange(mode);
607cb93a386Sopenharmony_ci}
608cb93a386Sopenharmony_cistatic void test_no_canvas2(skiatest::Reporter* reporter,
609cb93a386Sopenharmony_ci                            SkSurface* surface,
610cb93a386Sopenharmony_ci                            SkSurface::ContentChangeMode mode) {
611cb93a386Sopenharmony_ci    // Verifies the robustness of SkSurface for handling use cases where calls
612cb93a386Sopenharmony_ci    // are made before a canvas is created.
613cb93a386Sopenharmony_ci    sk_sp<SkImage> image1 = surface->makeImageSnapshot();
614cb93a386Sopenharmony_ci    sk_sp<SkImage> aur_image1(image1);  // NOLINT(performance-unnecessary-copy-initialization)
615cb93a386Sopenharmony_ci    surface->notifyContentWillChange(mode);
616cb93a386Sopenharmony_ci    sk_sp<SkImage> image2 = surface->makeImageSnapshot();
617cb93a386Sopenharmony_ci    sk_sp<SkImage> aur_image2(image2);  // NOLINT(performance-unnecessary-copy-initialization)
618cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, image1 != image2);
619cb93a386Sopenharmony_ci}
620cb93a386Sopenharmony_ciDEF_TEST(SurfaceNoCanvas, reporter) {
621cb93a386Sopenharmony_ci    SkSurface::ContentChangeMode modes[] =
622cb93a386Sopenharmony_ci            { SkSurface::kDiscard_ContentChangeMode, SkSurface::kRetain_ContentChangeMode};
623cb93a386Sopenharmony_ci    for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) {
624cb93a386Sopenharmony_ci        for (auto& mode : modes) {
625cb93a386Sopenharmony_ci            test_func(reporter, create_surface().get(), mode);
626cb93a386Sopenharmony_ci        }
627cb93a386Sopenharmony_ci    }
628cb93a386Sopenharmony_ci}
629cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceNoCanvas_Gpu, reporter, ctxInfo) {
630cb93a386Sopenharmony_ci    SkSurface::ContentChangeMode modes[] =
631cb93a386Sopenharmony_ci            { SkSurface::kDiscard_ContentChangeMode, SkSurface::kRetain_ContentChangeMode};
632cb93a386Sopenharmony_ci    for (auto& surface_func : { &create_gpu_surface, &create_gpu_scratch_surface }) {
633cb93a386Sopenharmony_ci        for (auto& test_func : { &test_no_canvas1, &test_no_canvas2 }) {
634cb93a386Sopenharmony_ci            for (auto& mode : modes) {
635cb93a386Sopenharmony_ci                auto surface(surface_func(ctxInfo.directContext(), kPremul_SkAlphaType, nullptr));
636cb93a386Sopenharmony_ci                test_func(reporter, surface.get(), mode);
637cb93a386Sopenharmony_ci            }
638cb93a386Sopenharmony_ci        }
639cb93a386Sopenharmony_ci    }
640cb93a386Sopenharmony_ci}
641cb93a386Sopenharmony_ci
642cb93a386Sopenharmony_cistatic void check_rowbytes_remain_consistent(SkSurface* surface, skiatest::Reporter* reporter) {
643cb93a386Sopenharmony_ci    SkPixmap surfacePM;
644cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, surface->peekPixels(&surfacePM));
645cb93a386Sopenharmony_ci
646cb93a386Sopenharmony_ci    sk_sp<SkImage> image(surface->makeImageSnapshot());
647cb93a386Sopenharmony_ci    SkPixmap pm;
648cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, image->peekPixels(&pm));
649cb93a386Sopenharmony_ci
650cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, surfacePM.rowBytes() == pm.rowBytes());
651cb93a386Sopenharmony_ci
652cb93a386Sopenharmony_ci    // trigger a copy-on-write
653cb93a386Sopenharmony_ci    surface->getCanvas()->drawPaint(SkPaint());
654cb93a386Sopenharmony_ci    sk_sp<SkImage> image2(surface->makeImageSnapshot());
655cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, image->uniqueID() != image2->uniqueID());
656cb93a386Sopenharmony_ci
657cb93a386Sopenharmony_ci    SkPixmap pm2;
658cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, image2->peekPixels(&pm2));
659cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, pm2.rowBytes() == pm.rowBytes());
660cb93a386Sopenharmony_ci}
661cb93a386Sopenharmony_ci
662cb93a386Sopenharmony_ciDEF_TEST(surface_rowbytes, reporter) {
663cb93a386Sopenharmony_ci    const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
664cb93a386Sopenharmony_ci
665cb93a386Sopenharmony_ci    auto surf0(SkSurface::MakeRaster(info));
666cb93a386Sopenharmony_ci    check_rowbytes_remain_consistent(surf0.get(), reporter);
667cb93a386Sopenharmony_ci
668cb93a386Sopenharmony_ci    // specify a larger rowbytes
669cb93a386Sopenharmony_ci    auto surf1(SkSurface::MakeRaster(info, 500, nullptr));
670cb93a386Sopenharmony_ci    check_rowbytes_remain_consistent(surf1.get(), reporter);
671cb93a386Sopenharmony_ci
672cb93a386Sopenharmony_ci    // Try some illegal rowByte values
673cb93a386Sopenharmony_ci    auto s = SkSurface::MakeRaster(info, 396, nullptr);    // needs to be at least 400
674cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, nullptr == s);
675cb93a386Sopenharmony_ci    s = SkSurface::MakeRaster(info, std::numeric_limits<size_t>::max(), nullptr);
676cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, nullptr == s);
677cb93a386Sopenharmony_ci}
678cb93a386Sopenharmony_ci
679cb93a386Sopenharmony_ciDEF_TEST(surface_raster_zeroinitialized, reporter) {
680cb93a386Sopenharmony_ci    sk_sp<SkSurface> s(SkSurface::MakeRasterN32Premul(100, 100));
681cb93a386Sopenharmony_ci    SkPixmap pixmap;
682cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, s->peekPixels(&pixmap));
683cb93a386Sopenharmony_ci
684cb93a386Sopenharmony_ci    for (int i = 0; i < pixmap.info().width(); ++i) {
685cb93a386Sopenharmony_ci        for (int j = 0; j < pixmap.info().height(); ++j) {
686cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, *pixmap.addr32(i, j) == 0);
687cb93a386Sopenharmony_ci        }
688cb93a386Sopenharmony_ci    }
689cb93a386Sopenharmony_ci}
690cb93a386Sopenharmony_ci
691cb93a386Sopenharmony_cistatic sk_sp<SkSurface> create_gpu_surface_backend_texture(GrDirectContext* dContext,
692cb93a386Sopenharmony_ci                                                           int sampleCnt,
693cb93a386Sopenharmony_ci                                                           const SkColor4f& color) {
694cb93a386Sopenharmony_ci    // On Pixel and Pixel2XL's with Adreno 530 and 540s, setting width and height to 10s reliably
695cb93a386Sopenharmony_ci    // triggers what appears to be a driver race condition where the 10x10 surface from the
696cb93a386Sopenharmony_ci    // OverdrawSurface_gpu test is reused(?) for this surface created by the SurfacePartialDraw_gpu
697cb93a386Sopenharmony_ci    // test.
698cb93a386Sopenharmony_ci    //
699cb93a386Sopenharmony_ci    // Immediately after creation of this surface, readback shows the correct initial solid color.
700cb93a386Sopenharmony_ci    // However, sometime before content is rendered into the upper half of the surface, the driver
701cb93a386Sopenharmony_ci    // presumably cleans up the OverdrawSurface_gpu's memory which corrupts this color buffer. The
702cb93a386Sopenharmony_ci    // top half of the surface is fine after the partially-covering rectangle is drawn, but the
703cb93a386Sopenharmony_ci    // untouched bottom half contains random pixel values that trigger asserts in the
704cb93a386Sopenharmony_ci    // SurfacePartialDraw_gpu test for no longer matching the initial color. Running the
705cb93a386Sopenharmony_ci    // SurfacePartialDraw_gpu test without the OverdrawSurface_gpu test completes successfully.
706cb93a386Sopenharmony_ci    //
707cb93a386Sopenharmony_ci    // Requesting a much larger backend texture size seems to prevent it from reusing the same
708cb93a386Sopenharmony_ci    // memory and avoids the issue.
709cb93a386Sopenharmony_ci#if defined(SK_BUILD_FOR_SKQP)
710cb93a386Sopenharmony_ci    const int kWidth = 10;
711cb93a386Sopenharmony_ci    const int kHeight = 10;
712cb93a386Sopenharmony_ci#else
713cb93a386Sopenharmony_ci    const int kWidth = 100;
714cb93a386Sopenharmony_ci    const int kHeight = 100;
715cb93a386Sopenharmony_ci#endif
716cb93a386Sopenharmony_ci
717cb93a386Sopenharmony_ci    auto surf = sk_gpu_test::MakeBackendTextureSurface(dContext,
718cb93a386Sopenharmony_ci                                                       {kWidth, kHeight},
719cb93a386Sopenharmony_ci                                                       kTopLeft_GrSurfaceOrigin,
720cb93a386Sopenharmony_ci                                                       sampleCnt,
721cb93a386Sopenharmony_ci                                                       kRGBA_8888_SkColorType);
722cb93a386Sopenharmony_ci    if (!surf) {
723cb93a386Sopenharmony_ci        return nullptr;
724cb93a386Sopenharmony_ci    }
725cb93a386Sopenharmony_ci    surf->getCanvas()->clear(color);
726cb93a386Sopenharmony_ci    return surf;
727cb93a386Sopenharmony_ci}
728cb93a386Sopenharmony_ci
729cb93a386Sopenharmony_cistatic bool supports_readpixels(const GrCaps* caps, SkSurface* surface) {
730cb93a386Sopenharmony_ci    auto surfaceGpu = static_cast<SkSurface_Gpu*>(surface);
731cb93a386Sopenharmony_ci    GrRenderTarget* rt = surfaceGpu->getDevice()->targetProxy()->peekRenderTarget();
732cb93a386Sopenharmony_ci    if (!rt) {
733cb93a386Sopenharmony_ci        return false;
734cb93a386Sopenharmony_ci    }
735cb93a386Sopenharmony_ci    return caps->surfaceSupportsReadPixels(rt) == GrCaps::SurfaceReadPixelsSupport::kSupported;
736cb93a386Sopenharmony_ci}
737cb93a386Sopenharmony_ci
738cb93a386Sopenharmony_cistatic sk_sp<SkSurface> create_gpu_surface_backend_render_target(GrDirectContext* dContext,
739cb93a386Sopenharmony_ci                                                                 int sampleCnt,
740cb93a386Sopenharmony_ci                                                                 const SkColor4f& color) {
741cb93a386Sopenharmony_ci    const int kWidth = 10;
742cb93a386Sopenharmony_ci    const int kHeight = 10;
743cb93a386Sopenharmony_ci
744cb93a386Sopenharmony_ci    auto surf = sk_gpu_test::MakeBackendRenderTargetSurface(dContext,
745cb93a386Sopenharmony_ci                                                            {kWidth, kHeight},
746cb93a386Sopenharmony_ci                                                            kTopLeft_GrSurfaceOrigin,
747cb93a386Sopenharmony_ci                                                            sampleCnt,
748cb93a386Sopenharmony_ci                                                            kRGBA_8888_SkColorType);
749cb93a386Sopenharmony_ci    if (!surf) {
750cb93a386Sopenharmony_ci        return nullptr;
751cb93a386Sopenharmony_ci    }
752cb93a386Sopenharmony_ci    surf->getCanvas()->clear(color);
753cb93a386Sopenharmony_ci    return surf;
754cb93a386Sopenharmony_ci}
755cb93a386Sopenharmony_ci
756cb93a386Sopenharmony_cistatic void test_surface_context_clear(skiatest::Reporter* reporter,
757cb93a386Sopenharmony_ci                                       GrDirectContext* dContext,
758cb93a386Sopenharmony_ci                                       skgpu::SurfaceContext* surfaceContext,
759cb93a386Sopenharmony_ci                                       uint32_t expectedValue) {
760cb93a386Sopenharmony_ci    int w = surfaceContext->width();
761cb93a386Sopenharmony_ci    int h = surfaceContext->height();
762cb93a386Sopenharmony_ci
763cb93a386Sopenharmony_ci    SkImageInfo ii = SkImageInfo::Make(w, h, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
764cb93a386Sopenharmony_ci
765cb93a386Sopenharmony_ci    SkAutoPixmapStorage readback;
766cb93a386Sopenharmony_ci    readback.alloc(ii);
767cb93a386Sopenharmony_ci
768cb93a386Sopenharmony_ci    readback.erase(~expectedValue);
769cb93a386Sopenharmony_ci    surfaceContext->readPixels(dContext, readback, {0, 0});
770cb93a386Sopenharmony_ci    for (int y = 0; y < h; ++y) {
771cb93a386Sopenharmony_ci        for (int x = 0; x < w; ++x) {
772cb93a386Sopenharmony_ci            uint32_t pixel = readback.addr32()[y * w + x];
773cb93a386Sopenharmony_ci            if (pixel != expectedValue) {
774cb93a386Sopenharmony_ci                SkString msg;
775cb93a386Sopenharmony_ci                if (expectedValue) {
776cb93a386Sopenharmony_ci                    msg = "SkSurface should have left render target unmodified";
777cb93a386Sopenharmony_ci                } else {
778cb93a386Sopenharmony_ci                    msg = "SkSurface should have cleared the render target";
779cb93a386Sopenharmony_ci                }
780cb93a386Sopenharmony_ci                ERRORF(reporter,
781cb93a386Sopenharmony_ci                       "%s but read 0x%08x (instead of 0x%08x) at %x,%d", msg.c_str(), pixel,
782cb93a386Sopenharmony_ci                       expectedValue, x, y);
783cb93a386Sopenharmony_ci                return;
784cb93a386Sopenharmony_ci            }
785cb93a386Sopenharmony_ci        }
786cb93a386Sopenharmony_ci    }
787cb93a386Sopenharmony_ci}
788cb93a386Sopenharmony_ci
789cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceClear_Gpu, reporter, ctxInfo) {
790cb93a386Sopenharmony_ci    auto dContext = ctxInfo.directContext();
791cb93a386Sopenharmony_ci    // Snaps an image from a surface and then makes a SurfaceContext from the image's texture.
792cb93a386Sopenharmony_ci    auto makeImageSurfaceContext = [dContext](SkSurface* surface) {
793cb93a386Sopenharmony_ci        sk_sp<SkImage> i(surface->makeImageSnapshot());
794cb93a386Sopenharmony_ci        auto gpuImage = static_cast<SkImage_Gpu*>(as_IB(i));
795cb93a386Sopenharmony_ci        auto [view, ct] = gpuImage->asView(dContext, GrMipmapped::kNo);
796cb93a386Sopenharmony_ci        GrColorInfo colorInfo(ct, i->alphaType(), i->refColorSpace());
797cb93a386Sopenharmony_ci        return dContext->priv().makeSC(view, std::move(colorInfo));
798cb93a386Sopenharmony_ci    };
799cb93a386Sopenharmony_ci
800cb93a386Sopenharmony_ci    // Test that non-wrapped RTs are created clear.
801cb93a386Sopenharmony_ci    for (auto& surface_func : {&create_gpu_surface, &create_gpu_scratch_surface}) {
802cb93a386Sopenharmony_ci        auto surface = surface_func(dContext, kPremul_SkAlphaType, nullptr);
803cb93a386Sopenharmony_ci        if (!surface) {
804cb93a386Sopenharmony_ci            ERRORF(reporter, "Could not create GPU SkSurface.");
805cb93a386Sopenharmony_ci            return;
806cb93a386Sopenharmony_ci        }
807cb93a386Sopenharmony_ci        auto sfc = SkCanvasPriv::TopDeviceSurfaceFillContext(surface->getCanvas());
808cb93a386Sopenharmony_ci        if (!sfc) {
809cb93a386Sopenharmony_ci            ERRORF(reporter, "Could access surface context of GPU SkSurface.");
810cb93a386Sopenharmony_ci            return;
811cb93a386Sopenharmony_ci        }
812cb93a386Sopenharmony_ci        test_surface_context_clear(reporter, dContext, sfc, 0x0);
813cb93a386Sopenharmony_ci        auto imageSurfaceCtx = makeImageSurfaceContext(surface.get());
814cb93a386Sopenharmony_ci        test_surface_context_clear(reporter, dContext, imageSurfaceCtx.get(), 0x0);
815cb93a386Sopenharmony_ci    }
816cb93a386Sopenharmony_ci
817cb93a386Sopenharmony_ci    // Wrapped RTs are *not* supposed to clear (to allow client to partially update a surface).
818cb93a386Sopenharmony_ci    const SkColor4f kOrigColor{.67f, .67f, .67f, 1};
819cb93a386Sopenharmony_ci    for (auto& surfaceFunc :
820cb93a386Sopenharmony_ci         {&create_gpu_surface_backend_texture, &create_gpu_surface_backend_render_target}) {
821cb93a386Sopenharmony_ci        auto surface = surfaceFunc(dContext, 1, kOrigColor);
822cb93a386Sopenharmony_ci        if (!surface) {
823cb93a386Sopenharmony_ci            ERRORF(reporter, "Could not create GPU SkSurface.");
824cb93a386Sopenharmony_ci            return;
825cb93a386Sopenharmony_ci        }
826cb93a386Sopenharmony_ci        auto sfc = SkCanvasPriv::TopDeviceSurfaceFillContext(surface->getCanvas());
827cb93a386Sopenharmony_ci        if (!sfc) {
828cb93a386Sopenharmony_ci            ERRORF(reporter, "Could access surface context of GPU SkSurface.");
829cb93a386Sopenharmony_ci            return;
830cb93a386Sopenharmony_ci        }
831cb93a386Sopenharmony_ci        test_surface_context_clear(reporter, dContext, sfc, kOrigColor.toSkColor());
832cb93a386Sopenharmony_ci        auto imageSurfaceCtx = makeImageSurfaceContext(surface.get());
833cb93a386Sopenharmony_ci        test_surface_context_clear(reporter, dContext, imageSurfaceCtx.get(),
834cb93a386Sopenharmony_ci                                   kOrigColor.toSkColor());
835cb93a386Sopenharmony_ci    }
836cb93a386Sopenharmony_ci}
837cb93a386Sopenharmony_ci
838cb93a386Sopenharmony_cistatic void test_surface_draw_partially(
839cb93a386Sopenharmony_ci    skiatest::Reporter* reporter, sk_sp<SkSurface> surface, SkColor origColor) {
840cb93a386Sopenharmony_ci    const int kW = surface->width();
841cb93a386Sopenharmony_ci    const int kH = surface->height();
842cb93a386Sopenharmony_ci    SkPaint paint;
843cb93a386Sopenharmony_ci    const SkColor kRectColor = ~origColor | 0xFF000000;
844cb93a386Sopenharmony_ci    paint.setColor(kRectColor);
845cb93a386Sopenharmony_ci    surface->getCanvas()->drawRect(SkRect::MakeIWH(kW, kH/2), paint);
846cb93a386Sopenharmony_ci
847cb93a386Sopenharmony_ci    // Read back RGBA to avoid format conversions that may not be supported on all platforms.
848cb93a386Sopenharmony_ci    SkImageInfo readInfo = SkImageInfo::Make(kW, kH, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
849cb93a386Sopenharmony_ci
850cb93a386Sopenharmony_ci    SkAutoPixmapStorage readback;
851cb93a386Sopenharmony_ci    readback.alloc(readInfo);
852cb93a386Sopenharmony_ci
853cb93a386Sopenharmony_ci    readback.erase(~origColor);
854cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, surface->readPixels(readback.info(), readback.writable_addr(),
855cb93a386Sopenharmony_ci                                                  readback.rowBytes(), 0, 0));
856cb93a386Sopenharmony_ci    bool stop = false;
857cb93a386Sopenharmony_ci
858cb93a386Sopenharmony_ci    SkPMColor origColorPM = SkPackARGB_as_RGBA(SkColorGetA(origColor),
859cb93a386Sopenharmony_ci                                               SkColorGetR(origColor),
860cb93a386Sopenharmony_ci                                               SkColorGetG(origColor),
861cb93a386Sopenharmony_ci                                               SkColorGetB(origColor));
862cb93a386Sopenharmony_ci    SkPMColor rectColorPM = SkPackARGB_as_RGBA(SkColorGetA(kRectColor),
863cb93a386Sopenharmony_ci                                               SkColorGetR(kRectColor),
864cb93a386Sopenharmony_ci                                               SkColorGetG(kRectColor),
865cb93a386Sopenharmony_ci                                               SkColorGetB(kRectColor));
866cb93a386Sopenharmony_ci
867cb93a386Sopenharmony_ci    for (int y = 0; y < kH/2 && !stop; ++y) {
868cb93a386Sopenharmony_ci       for (int x = 0; x < kW && !stop; ++x) {
869cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, rectColorPM == readback.addr32()[x + y * kW]);
870cb93a386Sopenharmony_ci            if (rectColorPM != readback.addr32()[x + y * kW]) {
871cb93a386Sopenharmony_ci                SkDebugf("--- got [%x] expected [%x], x = %d, y = %d\n",
872cb93a386Sopenharmony_ci                         readback.addr32()[x + y * kW], rectColorPM, x, y);
873cb93a386Sopenharmony_ci                stop = true;
874cb93a386Sopenharmony_ci            }
875cb93a386Sopenharmony_ci        }
876cb93a386Sopenharmony_ci    }
877cb93a386Sopenharmony_ci    stop = false;
878cb93a386Sopenharmony_ci    for (int y = kH/2; y < kH && !stop; ++y) {
879cb93a386Sopenharmony_ci        for (int x = 0; x < kW && !stop; ++x) {
880cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, origColorPM == readback.addr32()[x + y * kW]);
881cb93a386Sopenharmony_ci            if (origColorPM != readback.addr32()[x + y * kW]) {
882cb93a386Sopenharmony_ci                SkDebugf("--- got [%x] expected [%x], x = %d, y = %d\n",
883cb93a386Sopenharmony_ci                         readback.addr32()[x + y * kW], origColorPM, x, y);
884cb93a386Sopenharmony_ci                stop = true;
885cb93a386Sopenharmony_ci            }
886cb93a386Sopenharmony_ci        }
887cb93a386Sopenharmony_ci    }
888cb93a386Sopenharmony_ci}
889cb93a386Sopenharmony_ci
890cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfacePartialDraw_Gpu, reporter, ctxInfo) {
891cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
892cb93a386Sopenharmony_ci
893cb93a386Sopenharmony_ci    static const SkColor4f kOrigColor { 0.667f, 0.733f, 0.8f, 1 };
894cb93a386Sopenharmony_ci
895cb93a386Sopenharmony_ci    for (auto& surfaceFunc :
896cb93a386Sopenharmony_ci         {&create_gpu_surface_backend_texture, &create_gpu_surface_backend_render_target}) {
897cb93a386Sopenharmony_ci        // Validate that we can draw to the canvas and that the original texture color is
898cb93a386Sopenharmony_ci        // preserved in pixels that aren't rendered to via the surface.
899cb93a386Sopenharmony_ci        // This works only for non-multisampled case.
900cb93a386Sopenharmony_ci        auto surface = surfaceFunc(context, 1, kOrigColor);
901cb93a386Sopenharmony_ci        if (surface && supports_readpixels(context->priv().caps(), surface.get())) {
902cb93a386Sopenharmony_ci            test_surface_draw_partially(reporter, surface, kOrigColor.toSkColor());
903cb93a386Sopenharmony_ci        }
904cb93a386Sopenharmony_ci    }
905cb93a386Sopenharmony_ci}
906cb93a386Sopenharmony_ci
907cb93a386Sopenharmony_cistruct ReleaseChecker {
908cb93a386Sopenharmony_ci    ReleaseChecker() : fReleaseCount(0) {}
909cb93a386Sopenharmony_ci    int fReleaseCount;
910cb93a386Sopenharmony_ci    static void Release(void* self) {
911cb93a386Sopenharmony_ci        static_cast<ReleaseChecker*>(self)->fReleaseCount++;
912cb93a386Sopenharmony_ci    }
913cb93a386Sopenharmony_ci};
914cb93a386Sopenharmony_ci
915cb93a386Sopenharmony_ci
916cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SurfaceWrappedWithRelease_Gpu, reporter, ctxInfo) {
917cb93a386Sopenharmony_ci    const int kWidth = 10;
918cb93a386Sopenharmony_ci    const int kHeight = 10;
919cb93a386Sopenharmony_ci
920cb93a386Sopenharmony_ci    auto ctx = ctxInfo.directContext();
921cb93a386Sopenharmony_ci    GrGpu* gpu = ctx->priv().getGpu();
922cb93a386Sopenharmony_ci
923cb93a386Sopenharmony_ci    for (bool useTexture : {false, true}) {
924cb93a386Sopenharmony_ci        sk_sp<sk_gpu_test::ManagedBackendTexture> mbet;
925cb93a386Sopenharmony_ci        GrBackendRenderTarget backendRT;
926cb93a386Sopenharmony_ci        sk_sp<SkSurface> surface;
927cb93a386Sopenharmony_ci
928cb93a386Sopenharmony_ci        ReleaseChecker releaseChecker;
929cb93a386Sopenharmony_ci        GrSurfaceOrigin texOrigin = kBottomLeft_GrSurfaceOrigin;
930cb93a386Sopenharmony_ci
931cb93a386Sopenharmony_ci        if (useTexture) {
932cb93a386Sopenharmony_ci            SkImageInfo ii = SkImageInfo::Make(kWidth, kHeight, SkColorType::kRGBA_8888_SkColorType,
933cb93a386Sopenharmony_ci                                               kPremul_SkAlphaType);
934cb93a386Sopenharmony_ci            mbet = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(ctx, ii, GrMipmapped::kNo,
935cb93a386Sopenharmony_ci                                                                    GrRenderable::kYes);
936cb93a386Sopenharmony_ci            if (!mbet) {
937cb93a386Sopenharmony_ci                continue;
938cb93a386Sopenharmony_ci            }
939cb93a386Sopenharmony_ci
940cb93a386Sopenharmony_ci            surface = SkSurface::MakeFromBackendTexture(
941cb93a386Sopenharmony_ci                    ctx,
942cb93a386Sopenharmony_ci                    mbet->texture(),
943cb93a386Sopenharmony_ci                    texOrigin,
944cb93a386Sopenharmony_ci                    /*sample count*/ 1,
945cb93a386Sopenharmony_ci                    kRGBA_8888_SkColorType,
946cb93a386Sopenharmony_ci                    /*color space*/ nullptr,
947cb93a386Sopenharmony_ci                    /*surface props*/ nullptr,
948cb93a386Sopenharmony_ci                    sk_gpu_test::ManagedBackendTexture::ReleaseProc,
949cb93a386Sopenharmony_ci                    mbet->releaseContext(ReleaseChecker::Release, &releaseChecker));
950cb93a386Sopenharmony_ci        } else {
951cb93a386Sopenharmony_ci            backendRT = gpu->createTestingOnlyBackendRenderTarget({kWidth, kHeight},
952cb93a386Sopenharmony_ci                                                                  GrColorType::kRGBA_8888);
953cb93a386Sopenharmony_ci            if (!backendRT.isValid()) {
954cb93a386Sopenharmony_ci                continue;
955cb93a386Sopenharmony_ci            }
956cb93a386Sopenharmony_ci            surface = SkSurface::MakeFromBackendRenderTarget(ctx, backendRT, texOrigin,
957cb93a386Sopenharmony_ci                                                             kRGBA_8888_SkColorType,
958cb93a386Sopenharmony_ci                                                             nullptr, nullptr,
959cb93a386Sopenharmony_ci                                                             ReleaseChecker::Release,
960cb93a386Sopenharmony_ci                                                             &releaseChecker);
961cb93a386Sopenharmony_ci        }
962cb93a386Sopenharmony_ci        if (!surface) {
963cb93a386Sopenharmony_ci            ERRORF(reporter, "Failed to create surface");
964cb93a386Sopenharmony_ci            continue;
965cb93a386Sopenharmony_ci        }
966cb93a386Sopenharmony_ci
967cb93a386Sopenharmony_ci        surface->getCanvas()->clear(SK_ColorRED);
968cb93a386Sopenharmony_ci        surface->flush();
969cb93a386Sopenharmony_ci        ctx->submit(true);
970cb93a386Sopenharmony_ci
971cb93a386Sopenharmony_ci        // Now exercise the release proc
972cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, 0 == releaseChecker.fReleaseCount);
973cb93a386Sopenharmony_ci        surface.reset(nullptr); // force a release of the surface
974cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, 1 == releaseChecker.fReleaseCount);
975cb93a386Sopenharmony_ci
976cb93a386Sopenharmony_ci        if (!useTexture) {
977cb93a386Sopenharmony_ci            gpu->deleteTestingOnlyBackendRenderTarget(backendRT);
978cb93a386Sopenharmony_ci        }
979cb93a386Sopenharmony_ci    }
980cb93a386Sopenharmony_ci}
981cb93a386Sopenharmony_ci
982cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(SurfaceAttachStencil_Gpu, reporter, ctxInfo) {
983cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
984cb93a386Sopenharmony_ci    const GrCaps* caps = context->priv().caps();
985cb93a386Sopenharmony_ci
986cb93a386Sopenharmony_ci    if (caps->avoidStencilBuffers()) {
987cb93a386Sopenharmony_ci        return;
988cb93a386Sopenharmony_ci    }
989cb93a386Sopenharmony_ci
990cb93a386Sopenharmony_ci    static const SkColor4f kOrigColor { 0.667f, 0.733f, 0.8f, 1 };
991cb93a386Sopenharmony_ci
992cb93a386Sopenharmony_ci    auto resourceProvider = context->priv().resourceProvider();
993cb93a386Sopenharmony_ci
994cb93a386Sopenharmony_ci    for (auto& surfaceFunc :
995cb93a386Sopenharmony_ci         {&create_gpu_surface_backend_texture, &create_gpu_surface_backend_render_target}) {
996cb93a386Sopenharmony_ci        for (int sampleCnt : {1, 4, 8}) {
997cb93a386Sopenharmony_ci            auto surface = surfaceFunc(context, sampleCnt, kOrigColor);
998cb93a386Sopenharmony_ci
999cb93a386Sopenharmony_ci            if (!surface && sampleCnt > 1) {
1000cb93a386Sopenharmony_ci                // Certain platforms don't support MSAA, skip these.
1001cb93a386Sopenharmony_ci                continue;
1002cb93a386Sopenharmony_ci            }
1003cb93a386Sopenharmony_ci
1004cb93a386Sopenharmony_ci            // Validate that we can attach a stencil buffer to an SkSurface created by either of
1005cb93a386Sopenharmony_ci            // our surface functions.
1006cb93a386Sopenharmony_ci            auto rtp = SkCanvasPriv::TopDeviceTargetProxy(surface->getCanvas());
1007cb93a386Sopenharmony_ci            GrRenderTarget* rt = rtp->peekRenderTarget();
1008cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter,
1009cb93a386Sopenharmony_ci                            resourceProvider->attachStencilAttachment(rt, rt->numSamples() > 1));
1010cb93a386Sopenharmony_ci        }
1011cb93a386Sopenharmony_ci    }
1012cb93a386Sopenharmony_ci}
1013cb93a386Sopenharmony_ci
1014cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReplaceSurfaceBackendTexture, reporter, ctxInfo) {
1015cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
1016cb93a386Sopenharmony_ci
1017cb93a386Sopenharmony_ci    for (int sampleCnt : {1, 2}) {
1018cb93a386Sopenharmony_ci        auto ii = SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
1019cb93a386Sopenharmony_ci        auto mbet1 = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(
1020cb93a386Sopenharmony_ci                context, ii, GrMipmapped::kNo, GrRenderable::kYes);
1021cb93a386Sopenharmony_ci        if (!mbet1) {
1022cb93a386Sopenharmony_ci            continue;
1023cb93a386Sopenharmony_ci        }
1024cb93a386Sopenharmony_ci        auto mbet2 = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(
1025cb93a386Sopenharmony_ci                context, ii, GrMipmapped::kNo, GrRenderable::kYes);
1026cb93a386Sopenharmony_ci        if (!mbet2) {
1027cb93a386Sopenharmony_ci            ERRORF(reporter, "Expected to be able to make second texture");
1028cb93a386Sopenharmony_ci            continue;
1029cb93a386Sopenharmony_ci        }
1030cb93a386Sopenharmony_ci        auto ii2 = ii.makeWH(8, 8);
1031cb93a386Sopenharmony_ci        auto mbet3 = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(
1032cb93a386Sopenharmony_ci                context, ii2, GrMipmapped::kNo, GrRenderable::kYes);
1033cb93a386Sopenharmony_ci        GrBackendTexture backendTexture3;
1034cb93a386Sopenharmony_ci        if (!mbet3) {
1035cb93a386Sopenharmony_ci            ERRORF(reporter, "Couldn't create different sized texture.");
1036cb93a386Sopenharmony_ci            continue;
1037cb93a386Sopenharmony_ci        }
1038cb93a386Sopenharmony_ci
1039cb93a386Sopenharmony_ci        auto surf = SkSurface::MakeFromBackendTexture(
1040cb93a386Sopenharmony_ci                context, mbet1->texture(), kTopLeft_GrSurfaceOrigin, sampleCnt,
1041cb93a386Sopenharmony_ci                kRGBA_8888_SkColorType, ii.refColorSpace(), nullptr);
1042cb93a386Sopenharmony_ci        if (!surf) {
1043cb93a386Sopenharmony_ci            continue;
1044cb93a386Sopenharmony_ci        }
1045cb93a386Sopenharmony_ci        surf->getCanvas()->clear(SK_ColorBLUE);
1046cb93a386Sopenharmony_ci        // Change matrix, layer, and clip state before swapping out the backing texture.
1047cb93a386Sopenharmony_ci        surf->getCanvas()->translate(5, 5);
1048cb93a386Sopenharmony_ci        surf->getCanvas()->saveLayer(nullptr, nullptr);
1049cb93a386Sopenharmony_ci        surf->getCanvas()->clipRect(SkRect::MakeXYWH(0, 0, 1, 1));
1050cb93a386Sopenharmony_ci        // switch origin while we're at it.
1051cb93a386Sopenharmony_ci        bool replaced = surf->replaceBackendTexture(mbet2->texture(), kBottomLeft_GrSurfaceOrigin);
1052cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, replaced);
1053cb93a386Sopenharmony_ci        SkPaint paint;
1054cb93a386Sopenharmony_ci        paint.setColor(SK_ColorRED);
1055cb93a386Sopenharmony_ci        surf->getCanvas()->drawRect(SkRect::MakeWH(5, 5), paint);
1056cb93a386Sopenharmony_ci        surf->getCanvas()->restore();
1057cb93a386Sopenharmony_ci
1058cb93a386Sopenharmony_ci        // Check that the replacement texture got the right color values.
1059cb93a386Sopenharmony_ci        SkAutoPixmapStorage pm;
1060cb93a386Sopenharmony_ci        pm.alloc(ii);
1061cb93a386Sopenharmony_ci        bool bad = !surf->readPixels(pm, 0, 0);
1062cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !bad, "Could not read surface.");
1063cb93a386Sopenharmony_ci        for (int y = 0; y < ii.height() && !bad; ++y) {
1064cb93a386Sopenharmony_ci            for (int x = 0; x < ii.width() && !bad; ++x) {
1065cb93a386Sopenharmony_ci                auto expected = (x == 5 && y == 5) ? 0xFF0000FF : 0xFFFF0000;
1066cb93a386Sopenharmony_ci                auto found = *pm.addr32(x, y);
1067cb93a386Sopenharmony_ci                if (found != expected) {
1068cb93a386Sopenharmony_ci                    bad = true;
1069cb93a386Sopenharmony_ci                    ERRORF(reporter, "Expected color 0x%08x, found color 0x%08x at %d, %d.",
1070cb93a386Sopenharmony_ci                           expected, found, x, y);
1071cb93a386Sopenharmony_ci                }
1072cb93a386Sopenharmony_ci            }
1073cb93a386Sopenharmony_ci        }
1074cb93a386Sopenharmony_ci        // The original texture should still be all blue.
1075cb93a386Sopenharmony_ci        surf = SkSurface::MakeFromBackendTexture(
1076cb93a386Sopenharmony_ci                context, mbet1->texture(), kBottomLeft_GrSurfaceOrigin, sampleCnt,
1077cb93a386Sopenharmony_ci                kRGBA_8888_SkColorType, ii.refColorSpace(), nullptr);
1078cb93a386Sopenharmony_ci        if (!surf) {
1079cb93a386Sopenharmony_ci            ERRORF(reporter, "Could not create second surface.");
1080cb93a386Sopenharmony_ci            continue;
1081cb93a386Sopenharmony_ci        }
1082cb93a386Sopenharmony_ci        bad = !surf->readPixels(pm, 0, 0);
1083cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !bad, "Could not read second surface.");
1084cb93a386Sopenharmony_ci        for (int y = 0; y < ii.height() && !bad; ++y) {
1085cb93a386Sopenharmony_ci            for (int x = 0; x < ii.width() && !bad; ++x) {
1086cb93a386Sopenharmony_ci                auto expected = 0xFFFF0000;
1087cb93a386Sopenharmony_ci                auto found = *pm.addr32(x, y);
1088cb93a386Sopenharmony_ci                if (found != expected) {
1089cb93a386Sopenharmony_ci                    bad = true;
1090cb93a386Sopenharmony_ci                    ERRORF(reporter, "Expected color 0x%08x, found color 0x%08x at %d, %d.",
1091cb93a386Sopenharmony_ci                           expected, found, x, y);
1092cb93a386Sopenharmony_ci                }
1093cb93a386Sopenharmony_ci            }
1094cb93a386Sopenharmony_ci        }
1095cb93a386Sopenharmony_ci
1096cb93a386Sopenharmony_ci        // Can't replace with the same texture
1097cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter,
1098cb93a386Sopenharmony_ci                        !surf->replaceBackendTexture(mbet1->texture(), kTopLeft_GrSurfaceOrigin));
1099cb93a386Sopenharmony_ci        // Can't replace with invalid texture
1100cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !surf->replaceBackendTexture({}, kTopLeft_GrSurfaceOrigin));
1101cb93a386Sopenharmony_ci        // Can't replace with different size texture.
1102cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter,
1103cb93a386Sopenharmony_ci                        !surf->replaceBackendTexture(mbet3->texture(), kTopLeft_GrSurfaceOrigin));
1104cb93a386Sopenharmony_ci        // Can't replace texture of non-wrapped SkSurface.
1105cb93a386Sopenharmony_ci        surf = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, ii, sampleCnt, nullptr);
1106cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, surf);
1107cb93a386Sopenharmony_ci        if (surf) {
1108cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, !surf->replaceBackendTexture(mbet1->texture(),
1109cb93a386Sopenharmony_ci                                                                   kTopLeft_GrSurfaceOrigin));
1110cb93a386Sopenharmony_ci        }
1111cb93a386Sopenharmony_ci    }
1112cb93a386Sopenharmony_ci}
1113cb93a386Sopenharmony_ci
1114cb93a386Sopenharmony_cistatic void test_overdraw_surface(skiatest::Reporter* r, SkSurface* surface) {
1115cb93a386Sopenharmony_ci    SkOverdrawCanvas canvas(surface->getCanvas());
1116cb93a386Sopenharmony_ci    canvas.drawPaint(SkPaint());
1117cb93a386Sopenharmony_ci    sk_sp<SkImage> image = surface->makeImageSnapshot();
1118cb93a386Sopenharmony_ci
1119cb93a386Sopenharmony_ci    SkBitmap bitmap;
1120cb93a386Sopenharmony_ci    image->asLegacyBitmap(&bitmap);
1121cb93a386Sopenharmony_ci    for (int y = 0; y < 10; y++) {
1122cb93a386Sopenharmony_ci        for (int x = 0; x < 10; x++) {
1123cb93a386Sopenharmony_ci            REPORTER_ASSERT(r, 1 == SkGetPackedA32(*bitmap.getAddr32(x, y)));
1124cb93a386Sopenharmony_ci        }
1125cb93a386Sopenharmony_ci    }
1126cb93a386Sopenharmony_ci}
1127cb93a386Sopenharmony_ci
1128cb93a386Sopenharmony_ciDEF_TEST(OverdrawSurface_Raster, r) {
1129cb93a386Sopenharmony_ci    sk_sp<SkSurface> surface = create_surface();
1130cb93a386Sopenharmony_ci    test_overdraw_surface(r, surface.get());
1131cb93a386Sopenharmony_ci}
1132cb93a386Sopenharmony_ci
1133cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(OverdrawSurface_Gpu, r, ctxInfo) {
1134cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
1135cb93a386Sopenharmony_ci    sk_sp<SkSurface> surface = create_gpu_surface(context);
1136cb93a386Sopenharmony_ci    test_overdraw_surface(r, surface.get());
1137cb93a386Sopenharmony_ci}
1138cb93a386Sopenharmony_ci
1139cb93a386Sopenharmony_ciDEF_TEST(Surface_null, r) {
1140cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, SkSurface::MakeNull(0, 0) == nullptr);
1141cb93a386Sopenharmony_ci
1142cb93a386Sopenharmony_ci    const int w = 37;
1143cb93a386Sopenharmony_ci    const int h = 1000;
1144cb93a386Sopenharmony_ci    auto surf = SkSurface::MakeNull(w, h);
1145cb93a386Sopenharmony_ci    auto canvas = surf->getCanvas();
1146cb93a386Sopenharmony_ci
1147cb93a386Sopenharmony_ci    canvas->drawPaint(SkPaint());   // should not crash, but don't expect anything to draw
1148cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, surf->makeImageSnapshot() == nullptr);
1149cb93a386Sopenharmony_ci}
1150cb93a386Sopenharmony_ci
1151cb93a386Sopenharmony_ci// assert: if a given imageinfo is valid for a surface, then it must be valid for an image
1152cb93a386Sopenharmony_ci//         (so the snapshot can succeed)
1153cb93a386Sopenharmony_ciDEF_TEST(surface_image_unity, reporter) {
1154cb93a386Sopenharmony_ci    auto do_test = [reporter](const SkImageInfo& info) {
1155cb93a386Sopenharmony_ci        size_t rowBytes = info.minRowBytes();
1156cb93a386Sopenharmony_ci        auto surf = SkSurface::MakeRaster(info, rowBytes, nullptr);
1157cb93a386Sopenharmony_ci        if (surf) {
1158cb93a386Sopenharmony_ci            auto img = surf->makeImageSnapshot();
1159cb93a386Sopenharmony_ci            if (!img && false) {    // change to true to document the differences
1160cb93a386Sopenharmony_ci                SkDebugf("image failed: [%08X %08X] %14s %s\n",
1161cb93a386Sopenharmony_ci                         info.width(),
1162cb93a386Sopenharmony_ci                         info.height(),
1163cb93a386Sopenharmony_ci                         ToolUtils::colortype_name(info.colorType()),
1164cb93a386Sopenharmony_ci                         ToolUtils::alphatype_name(info.alphaType()));
1165cb93a386Sopenharmony_ci                return;
1166cb93a386Sopenharmony_ci            }
1167cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, img != nullptr);
1168cb93a386Sopenharmony_ci
1169cb93a386Sopenharmony_ci            char tempPixel = 0;    // just need a valid address (not a valid size)
1170cb93a386Sopenharmony_ci            SkPixmap pmap = { info, &tempPixel, rowBytes };
1171cb93a386Sopenharmony_ci            img = SkImage::MakeFromRaster(pmap, nullptr, nullptr);
1172cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, img != nullptr);
1173cb93a386Sopenharmony_ci        }
1174cb93a386Sopenharmony_ci    };
1175cb93a386Sopenharmony_ci
1176cb93a386Sopenharmony_ci    const int32_t sizes[] = { -1, 0, 1, 1 << 18 };
1177cb93a386Sopenharmony_ci    for (int cti = 0; cti <= kLastEnum_SkColorType; ++cti) {
1178cb93a386Sopenharmony_ci        SkColorType ct = static_cast<SkColorType>(cti);
1179cb93a386Sopenharmony_ci        for (int ati = 0; ati <= kLastEnum_SkAlphaType; ++ati) {
1180cb93a386Sopenharmony_ci            SkAlphaType at = static_cast<SkAlphaType>(ati);
1181cb93a386Sopenharmony_ci            for (int32_t size : sizes) {
1182cb93a386Sopenharmony_ci                do_test(SkImageInfo::Make(1, size, ct, at));
1183cb93a386Sopenharmony_ci                do_test(SkImageInfo::Make(size, 1, ct, at));
1184cb93a386Sopenharmony_ci            }
1185cb93a386Sopenharmony_ci        }
1186cb93a386Sopenharmony_ci    }
1187cb93a386Sopenharmony_ci}
1188