blob: 6ec298883693c6bd3b525cdd658137288e382623 [file] [log] [blame]
Brian Salomond63638b2021-03-05 14:00:07 -05001/*
2 * Copyright 2021 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "include/core/SkDeferredDisplayListRecorder.h"
9#include "include/core/SkImageInfo.h"
10#include "include/gpu/GrDirectContext.h"
11#include "include/gpu/GrTypes.h"
12#include "src/core/SkAutoPixmapStorage.h"
13#include "src/core/SkCanvasPriv.h"
14#include "src/gpu/GrDirectContextPriv.h"
15#include "src/gpu/GrProxyProvider.h"
16#include "src/gpu/GrSurfaceDrawContext.h"
17#include "src/gpu/GrSurfaceProxy.h"
18#include "tests/Test.h"
19#include "tests/TestUtils.h"
20#include "tools/gpu/BackendSurfaceFactory.h"
21#include "tools/gpu/ProxyUtils.h"
22
23DEF_GPUTEST_FOR_ALL_CONTEXTS(WrappedSurfaceCopyOnWrite, reporter, ctxInfo) {
24 GrDirectContext* dContext = ctxInfo.directContext();
25
26 auto makeDirectBackendSurface = [&]() {
27 auto info = SkImageInfo::Make({10, 10}, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
28 return sk_gpu_test::MakeBackendTextureSurface(dContext,
29 info,
30 kTopLeft_GrSurfaceOrigin,
31 /*sample count*/ 1);
32 };
33
34 auto imageProxyID = [&](const sk_sp<SkImage>& img) {
35 return sk_gpu_test::GetTextureImageProxy(img.get(), dContext)->uniqueID();
36 };
37
38 auto surfaceProxyID = [&](const sk_sp<SkSurface>& surf) {
Robert Phillipsfa8af0a2021-06-03 11:58:43 -040039 GrRenderTargetProxy* rtp = SkCanvasPriv::TopDeviceTargetProxy(surf->getCanvas());
40 return rtp->uniqueID();
Brian Salomond63638b2021-03-05 14:00:07 -050041 };
42
43 sk_sp<SkSurface> surf = makeDirectBackendSurface();
44 surf->getCanvas()->clear(SkColor4f{1, 0, 0, 1});
45 sk_sp<SkImage> img = surf->makeImageSnapshot();
46 // Initially they share
47 REPORTER_ASSERT(reporter, surfaceProxyID(surf) == imageProxyID(img));
48 // Using the image on the direct context shouldn't affect sharing.
49 sk_sp<SkSurface> surf2 = makeDirectBackendSurface();
50 surf2->getCanvas()->drawImage(img, 0, 0);
51 REPORTER_ASSERT(reporter, surfaceProxyID(surf) == imageProxyID(img));
52 // Modifying the original surface should trigger using the copy proxy.
53 surf->getCanvas()->clear({0, 0, 1, 1});
54 REPORTER_ASSERT(reporter, surfaceProxyID(surf) != imageProxyID(img));
55 // Image caching on surface should mean another snapshot gives us the same image.
56 GrSurfaceProxy::UniqueID imageID = imageProxyID(img);
57 img = surf->makeImageSnapshot();
58 REPORTER_ASSERT(reporter, imageProxyID(img) != imageID);
59
60 SkSurfaceCharacterization characterization;
61 REPORTER_ASSERT(reporter, surf->characterize(&characterization));
62 SkDeferredDisplayListRecorder recorder(characterization);
63
64 // Using an image from a direct context on a recording context should trigger using the copy.
65 surf = makeDirectBackendSurface();
66 img = surf->makeImageSnapshot();
67 REPORTER_ASSERT(reporter, surfaceProxyID(surf) == imageProxyID(img));
68 recorder.getCanvas()->drawImage(img, 0, 0);
69 REPORTER_ASSERT(reporter, surfaceProxyID(surf) != imageProxyID(img));
70
71 // Same as above but if the surface goes out of scope first we keep using the original
72 surf = makeDirectBackendSurface();
73 img = surf->makeImageSnapshot();
74 GrSurfaceProxy::UniqueID surfID = surfaceProxyID(surf);
75 REPORTER_ASSERT(reporter, surfaceProxyID(surf) == imageProxyID(img));
76 surf.reset();
77 recorder.getCanvas()->drawImage(img, 0, 0);
78 REPORTER_ASSERT(reporter, surfID == imageProxyID(img));
79}
80
81// Make sure GrCopyRenderTasks's skip actually skips the copy.
82DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkipCopyTaskTest, reporter, ctxInfo) {
83 GrDirectContext* dContext = ctxInfo.directContext();
84
85 auto dst = GrSurfaceDrawContext::Make(dContext,
86 GrColorType::kRGBA_8888,
87 /*color space*/ nullptr,
88 SkBackingFit::kExact,
Chris Daltonf5b87f92021-04-19 17:27:09 -060089 {10, 10},
90 SkSurfaceProps());
Brian Salomond63638b2021-03-05 14:00:07 -050091 dst->clear(SkPMColor4f{1, 0, 0, 1});
92
93 auto src = GrSurfaceDrawContext::Make(dContext,
94 GrColorType::kRGBA_8888,
95 /*color space*/ nullptr,
96 SkBackingFit::kExact,
Chris Daltonf5b87f92021-04-19 17:27:09 -060097 {10, 10},
98 SkSurfaceProps());
Brian Salomond63638b2021-03-05 14:00:07 -050099 src->clear(SkPMColor4f{0, 0, 1, 1});
100
101 sk_sp<GrRenderTask> task =
102 dContext->priv().drawingManager()->newCopyRenderTask(src->asSurfaceProxyRef(),
103 SkIRect::MakeWH(10, 10),
104 dst->asSurfaceProxyRef(),
105 {0, 0},
106 kTopLeft_GrSurfaceOrigin);
107
108 if (!task) {
109 ERRORF(reporter, "Couldn't make a copy task.");
110 return;
111 }
112
Adlai Hollere9ea4142021-04-27 14:31:56 -0400113 task->makeSkippable();
Brian Salomond63638b2021-03-05 14:00:07 -0500114
115 SkAutoPixmapStorage pixels;
116 pixels.alloc(SkImageInfo::Make({10, 10}, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
117 dst->readPixels(dContext, pixels, {0, 0});
118 float kTol[4] = {};
119 std::function<ComparePixmapsErrorReporter> errorReporter(
120 [&](int x, int y, const float diffs[4]) {
121 ERRORF(reporter, "Expected {1, 0, 0, 1}. diff {%f, %f, %f, %f}",
122 diffs[0], diffs[1], diffs[2], diffs[3]);
123 });
124 CheckSolidPixels(SkColor4f{1, 0, 0, 1}, pixels, kTol, errorReporter);
125}
126
127// Make sure GrOpsTask are skippable
128DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkipOpsTaskTest, reporter, ctxInfo) {
129 GrDirectContext* dContext = ctxInfo.directContext();
130
131 auto dst = GrSurfaceDrawContext::Make(dContext,
132 GrColorType::kRGBA_8888,
133 /*color space*/ nullptr,
134 SkBackingFit::kExact,
Chris Daltonf5b87f92021-04-19 17:27:09 -0600135 {10, 10},
136 SkSurfaceProps());
Brian Salomond63638b2021-03-05 14:00:07 -0500137 dst->clear(SkPMColor4f{1, 0, 0, 1});
138 dContext->flush();
139
140 dst->clear(SkPMColor4f{0, 0, 1, 1});
141 sk_sp<GrRenderTask> task = sk_ref_sp(dst->getOpsTask());
142
143 // GrDrawingManager maintains an "active ops task" and doesn't like having it closed behind
144 // its back. temp exists just to replace dst's ops task as the active one.
145 auto temp = GrSurfaceDrawContext::Make(dContext,
146 GrColorType::kRGBA_8888,
147 /*color space*/ nullptr,
148 SkBackingFit::kExact,
Chris Daltonf5b87f92021-04-19 17:27:09 -0600149 {10, 10},
150 SkSurfaceProps());
Brian Salomond63638b2021-03-05 14:00:07 -0500151 temp->clear(SkPMColor4f{0, 0, 0, 0});
152
153 GrSurfaceProxyView readView = dst->readSurfaceView();
Adlai Hollere9ea4142021-04-27 14:31:56 -0400154 task->makeSkippable();
Brian Salomond63638b2021-03-05 14:00:07 -0500155
156 SkAutoPixmapStorage pixels;
157 pixels.alloc(SkImageInfo::Make({10, 10}, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
158 dst->readPixels(dContext, pixels, {0, 0});
159 float kTol[4] = {};
160 std::function<ComparePixmapsErrorReporter> errorReporter(
161 [&](int x, int y, const float diffs[4]) {
162 ERRORF(reporter, "Expected {1, 0, 0, 1}. diff {%f, %f, %f, %f}",
163 diffs[0], diffs[1], diffs[2], diffs[3]);
164 });
165 CheckSolidPixels(SkColor4f{1, 0, 0, 1}, pixels, kTol, errorReporter);
166}