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