1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC 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/SkDeferredDisplayListRecorder.h" 9cb93a386Sopenharmony_ci#include "include/core/SkImageInfo.h" 10cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 11cb93a386Sopenharmony_ci#include "include/gpu/GrTypes.h" 12cb93a386Sopenharmony_ci#include "src/core/SkAutoPixmapStorage.h" 13cb93a386Sopenharmony_ci#include "src/core/SkCanvasPriv.h" 14cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrProxyProvider.h" 16cb93a386Sopenharmony_ci#include "src/gpu/GrSurfaceProxy.h" 17cb93a386Sopenharmony_ci#include "src/gpu/SurfaceFillContext.h" 18cb93a386Sopenharmony_ci#include "tests/Test.h" 19cb93a386Sopenharmony_ci#include "tests/TestUtils.h" 20cb93a386Sopenharmony_ci#include "tools/gpu/BackendSurfaceFactory.h" 21cb93a386Sopenharmony_ci#include "tools/gpu/ProxyUtils.h" 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_ALL_CONTEXTS(WrappedSurfaceCopyOnWrite, reporter, ctxInfo) { 24cb93a386Sopenharmony_ci GrDirectContext* dContext = ctxInfo.directContext(); 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ci auto makeDirectBackendSurface = [&]() { 27cb93a386Sopenharmony_ci auto info = SkImageInfo::Make({10, 10}, kRGBA_8888_SkColorType, kPremul_SkAlphaType); 28cb93a386Sopenharmony_ci return sk_gpu_test::MakeBackendTextureSurface(dContext, 29cb93a386Sopenharmony_ci info, 30cb93a386Sopenharmony_ci kTopLeft_GrSurfaceOrigin, 31cb93a386Sopenharmony_ci /*sample count*/ 1); 32cb93a386Sopenharmony_ci }; 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci auto imageProxyID = [&](const sk_sp<SkImage>& img) { 35cb93a386Sopenharmony_ci return sk_gpu_test::GetTextureImageProxy(img.get(), dContext)->uniqueID(); 36cb93a386Sopenharmony_ci }; 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci auto surfaceProxyID = [&](const sk_sp<SkSurface>& surf) { 39cb93a386Sopenharmony_ci GrRenderTargetProxy* rtp = SkCanvasPriv::TopDeviceTargetProxy(surf->getCanvas()); 40cb93a386Sopenharmony_ci return rtp->uniqueID(); 41cb93a386Sopenharmony_ci }; 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ci sk_sp<SkSurface> surf = makeDirectBackendSurface(); 44cb93a386Sopenharmony_ci surf->getCanvas()->clear(SkColor4f{1, 0, 0, 1}); 45cb93a386Sopenharmony_ci sk_sp<SkImage> img = surf->makeImageSnapshot(); 46cb93a386Sopenharmony_ci // Initially they share 47cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, surfaceProxyID(surf) == imageProxyID(img)); 48cb93a386Sopenharmony_ci // Using the image on the direct context shouldn't affect sharing. 49cb93a386Sopenharmony_ci sk_sp<SkSurface> surf2 = makeDirectBackendSurface(); 50cb93a386Sopenharmony_ci surf2->getCanvas()->drawImage(img, 0, 0); 51cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, surfaceProxyID(surf) == imageProxyID(img)); 52cb93a386Sopenharmony_ci // Modifying the original surface should trigger using the copy proxy. 53cb93a386Sopenharmony_ci surf->getCanvas()->clear({0, 0, 1, 1}); 54cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, surfaceProxyID(surf) != imageProxyID(img)); 55cb93a386Sopenharmony_ci // Image caching on surface should mean another snapshot gives us the same image. 56cb93a386Sopenharmony_ci GrSurfaceProxy::UniqueID imageID = imageProxyID(img); 57cb93a386Sopenharmony_ci img = surf->makeImageSnapshot(); 58cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, imageProxyID(img) != imageID); 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci SkSurfaceCharacterization characterization; 61cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, surf->characterize(&characterization)); 62cb93a386Sopenharmony_ci SkDeferredDisplayListRecorder recorder(characterization); 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ci // Using an image from a direct context on a recording context should trigger using the copy. 65cb93a386Sopenharmony_ci surf = makeDirectBackendSurface(); 66cb93a386Sopenharmony_ci img = surf->makeImageSnapshot(); 67cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, surfaceProxyID(surf) == imageProxyID(img)); 68cb93a386Sopenharmony_ci recorder.getCanvas()->drawImage(img, 0, 0); 69cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, surfaceProxyID(surf) != imageProxyID(img)); 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci // Same as above but if the surface goes out of scope first we keep using the original 72cb93a386Sopenharmony_ci surf = makeDirectBackendSurface(); 73cb93a386Sopenharmony_ci img = surf->makeImageSnapshot(); 74cb93a386Sopenharmony_ci GrSurfaceProxy::UniqueID surfID = surfaceProxyID(surf); 75cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, surfaceProxyID(surf) == imageProxyID(img)); 76cb93a386Sopenharmony_ci surf.reset(); 77cb93a386Sopenharmony_ci recorder.getCanvas()->drawImage(img, 0, 0); 78cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, surfID == imageProxyID(img)); 79cb93a386Sopenharmony_ci} 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci// Make sure GrCopyRenderTasks's skip actually skips the copy. 82cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkipCopyTaskTest, reporter, ctxInfo) { 83cb93a386Sopenharmony_ci GrDirectContext* dContext = ctxInfo.directContext(); 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ci GrImageInfo info(GrColorType::kRGBA_8888, 86cb93a386Sopenharmony_ci kPremul_SkAlphaType, 87cb93a386Sopenharmony_ci /*color space*/ nullptr, 88cb93a386Sopenharmony_ci 10, 10); 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_ci auto dstSC = CreateSurfaceContext(dContext, 91cb93a386Sopenharmony_ci info, 92cb93a386Sopenharmony_ci SkBackingFit::kExact, 93cb93a386Sopenharmony_ci kBottomLeft_GrSurfaceOrigin, 94cb93a386Sopenharmony_ci GrRenderable::kYes); 95cb93a386Sopenharmony_ci dstSC->asFillContext()->clear(SkPMColor4f{1, 0, 0, 1}); 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_ci auto srcSC = CreateSurfaceContext(dContext, 98cb93a386Sopenharmony_ci info, 99cb93a386Sopenharmony_ci SkBackingFit::kExact, 100cb93a386Sopenharmony_ci kBottomLeft_GrSurfaceOrigin, 101cb93a386Sopenharmony_ci GrRenderable::kYes); 102cb93a386Sopenharmony_ci srcSC->asFillContext()->clear(SkPMColor4f{0, 0, 1, 1}); 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ci sk_sp<GrRenderTask> task = 105cb93a386Sopenharmony_ci dContext->priv().drawingManager()->newCopyRenderTask(srcSC->asSurfaceProxyRef(), 106cb93a386Sopenharmony_ci SkIRect::MakeWH(10, 10), 107cb93a386Sopenharmony_ci dstSC->asSurfaceProxyRef(), 108cb93a386Sopenharmony_ci {0, 0}, 109cb93a386Sopenharmony_ci kTopLeft_GrSurfaceOrigin); 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_ci if (!task) { 112cb93a386Sopenharmony_ci ERRORF(reporter, "Couldn't make a copy task."); 113cb93a386Sopenharmony_ci return; 114cb93a386Sopenharmony_ci } 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ci task->makeSkippable(); 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ci SkAutoPixmapStorage pixels; 119cb93a386Sopenharmony_ci pixels.alloc(SkImageInfo::Make({10, 10}, kRGBA_8888_SkColorType, kPremul_SkAlphaType)); 120cb93a386Sopenharmony_ci dstSC->readPixels(dContext, pixels, {0, 0}); 121cb93a386Sopenharmony_ci float kTol[4] = {}; 122cb93a386Sopenharmony_ci std::function<ComparePixmapsErrorReporter> errorReporter( 123cb93a386Sopenharmony_ci [&](int x, int y, const float diffs[4]) { 124cb93a386Sopenharmony_ci ERRORF(reporter, "Expected {1, 0, 0, 1}. diff {%f, %f, %f, %f}", 125cb93a386Sopenharmony_ci diffs[0], diffs[1], diffs[2], diffs[3]); 126cb93a386Sopenharmony_ci }); 127cb93a386Sopenharmony_ci CheckSolidPixels(SkColor4f{1, 0, 0, 1}, pixels, kTol, errorReporter); 128cb93a386Sopenharmony_ci} 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ci#if SK_GPU_V1 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_ci// Make sure OpsTask are skippable 133cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkipOpsTaskTest, reporter, ctxInfo) { 134cb93a386Sopenharmony_ci GrDirectContext* dContext = ctxInfo.directContext(); 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci GrImageInfo ii(GrColorType::kRGBA_8888, kPremul_SkAlphaType, /*color space*/ nullptr, 10, 10); 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ci auto dst = dContext->priv().makeSFC(ii, SkBackingFit::kExact); 139cb93a386Sopenharmony_ci dst->clear(SkPMColor4f{1, 0, 0, 1}); 140cb93a386Sopenharmony_ci dContext->flush(); 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ci dst->clear(SkPMColor4f{0, 0, 1, 1}); 143cb93a386Sopenharmony_ci sk_sp<GrRenderTask> task = dst->refRenderTask(); 144cb93a386Sopenharmony_ci 145cb93a386Sopenharmony_ci // GrDrawingManager maintains an "active ops task" and doesn't like having it closed behind 146cb93a386Sopenharmony_ci // its back. temp exists just to replace dst's ops task as the active one. 147cb93a386Sopenharmony_ci auto temp = dContext->priv().makeSFC(ii, SkBackingFit::kExact); 148cb93a386Sopenharmony_ci temp->clear(SkPMColor4f{0, 0, 0, 0}); 149cb93a386Sopenharmony_ci 150cb93a386Sopenharmony_ci GrSurfaceProxyView readView = dst->readSurfaceView(); 151cb93a386Sopenharmony_ci task->makeSkippable(); 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_ci SkAutoPixmapStorage pixels; 154cb93a386Sopenharmony_ci pixels.alloc(SkImageInfo::Make({10, 10}, kRGBA_8888_SkColorType, kPremul_SkAlphaType)); 155cb93a386Sopenharmony_ci dst->readPixels(dContext, pixels, {0, 0}); 156cb93a386Sopenharmony_ci float kTol[4] = {}; 157cb93a386Sopenharmony_ci std::function<ComparePixmapsErrorReporter> errorReporter( 158cb93a386Sopenharmony_ci [&](int x, int y, const float diffs[4]) { 159cb93a386Sopenharmony_ci ERRORF(reporter, "Expected {1, 0, 0, 1}. diff {%f, %f, %f, %f}", 160cb93a386Sopenharmony_ci diffs[0], diffs[1], diffs[2], diffs[3]); 161cb93a386Sopenharmony_ci }); 162cb93a386Sopenharmony_ci CheckSolidPixels(SkColor4f{1, 0, 0, 1}, pixels, kTol, errorReporter); 163cb93a386Sopenharmony_ci} 164cb93a386Sopenharmony_ci#endif // SK_GPU_V1 165