blob: 7eed68f0a138b3dddaa1ff43d465b61ef7f45c21 [file] [log] [blame]
Greg Daniela8d92112018-03-09 12:05:04 -05001/*
2 * Copyright 2018 Google Inc.
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 "Test.h"
9
Greg Daniela8d92112018-03-09 12:05:04 -050010#include "GrBackendSurface.h"
11#include "GrContextPriv.h"
12#include "GrGpu.h"
Greg Daniela8d92112018-03-09 12:05:04 -050013#include "SkDeferredDisplayListRecorder.h"
14#include "SkImage_Gpu.h"
15
16using namespace sk_gpu_test;
17
18struct PromiseTextureChecker {
19 explicit PromiseTextureChecker(const GrBackendTexture& tex)
20 : fTexture(tex)
21 , fFulfillCount(0)
Greg Daniel7278d682018-03-16 14:57:21 -040022 , fReleaseCount(0)
23 , fDoneCount(0) {}
Greg Daniela8d92112018-03-09 12:05:04 -050024 GrBackendTexture fTexture;
25 int fFulfillCount;
26 int fReleaseCount;
Greg Daniel7278d682018-03-16 14:57:21 -040027 int fDoneCount;
Greg Daniela8d92112018-03-09 12:05:04 -050028 static void Fulfill(void* self, GrBackendTexture* outTexture) {
29 static_cast<PromiseTextureChecker*>(self)->fFulfillCount++;
30 *outTexture = static_cast<PromiseTextureChecker*>(self)->fTexture;
31 }
32 static void Release(void* self) {
33 static_cast<PromiseTextureChecker*>(self)->fReleaseCount++;
34 }
Greg Daniel7278d682018-03-16 14:57:21 -040035 static void Done(void* self) {
36 static_cast<PromiseTextureChecker*>(self)->fDoneCount++;
37 }
Greg Daniela8d92112018-03-09 12:05:04 -050038};
39
40// Because Vulkan may delay when it actually calls the ReleaseProcs depending on when command
41// buffers finish their work, we need some slight wiggle room in what values we expect for fulfill
42// and release counts.
43static bool check_fulfill_and_release_cnts(const PromiseTextureChecker& promiseChecker,
44 bool countsMustBeEqual,
45 int expectedFulfillCnt,
46 int expectedReleaseCnt,
47 bool expectedRequired,
Greg Daniel7278d682018-03-16 14:57:21 -040048 int expectedDoneCnt,
Greg Daniela8d92112018-03-09 12:05:04 -050049 skiatest::Reporter* reporter) {
50 bool result = true;
51 int countDiff = promiseChecker.fFulfillCount - promiseChecker.fReleaseCount;
52 // FulfillCount should always equal ReleaseCount or be at most one higher
53 if (countDiff != 0) {
54 if (countsMustBeEqual) {
55 result = false;
56 REPORTER_ASSERT(reporter, 0 == countDiff);
57 } else if (countDiff != 1) {
58 result = false;
59 REPORTER_ASSERT(reporter, 0 == countDiff || 1 == countDiff);
60 }
61 }
62
63 int fulfillDiff = expectedFulfillCnt - promiseChecker.fFulfillCount;
64 REPORTER_ASSERT(reporter, fulfillDiff >= 0);
65 if (fulfillDiff != 0) {
66 if (expectedRequired) {
67 result = false;
68 REPORTER_ASSERT(reporter, expectedFulfillCnt == promiseChecker.fFulfillCount);
69 } else if (fulfillDiff > 1) {
70 result = false;
71 REPORTER_ASSERT(reporter, fulfillDiff <= 1);
72 }
73 }
74
75 int releaseDiff = expectedReleaseCnt - promiseChecker.fReleaseCount;
76 REPORTER_ASSERT(reporter, releaseDiff >= 0);
77 if (releaseDiff != 0) {
78 if (expectedRequired) {
79 result = false;
80 REPORTER_ASSERT(reporter, expectedReleaseCnt == promiseChecker.fReleaseCount);
81 } else if (releaseDiff > 1) {
82 result = false;
83 REPORTER_ASSERT(reporter, releaseDiff <= 1);
84 }
85 }
86
Greg Daniel7278d682018-03-16 14:57:21 -040087 if (expectedDoneCnt != promiseChecker.fDoneCount) {
88 result = false;
89 REPORTER_ASSERT(reporter, expectedDoneCnt == promiseChecker.fDoneCount);
90 }
91
Greg Daniela8d92112018-03-09 12:05:04 -050092 return result;
93}
94
95DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTest, reporter, ctxInfo) {
96 const int kWidth = 10;
97 const int kHeight = 10;
Greg Daniela8d92112018-03-09 12:05:04 -050098
99 GrContext* ctx = ctxInfo.grContext();
100 GrGpu* gpu = ctx->contextPriv().getGpu();
101
Greg Daniel7278d682018-03-16 14:57:21 -0400102 for (bool releaseImageEarly : {true, false}) {
103 GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
Robert Phillips646f6372018-09-25 09:31:10 -0400104 nullptr, kWidth, kHeight, GrColorType::kRGBA_8888, true, GrMipMapped::kNo);
Greg Daniel7278d682018-03-16 14:57:21 -0400105 REPORTER_ASSERT(reporter, backendTex.isValid());
Greg Daniela8d92112018-03-09 12:05:04 -0500106
Timothy Liang036fdfe2018-06-28 15:50:36 -0400107 GrBackendFormat backendFormat = gpu->caps()->createFormatFromBackendTexture(backendTex);
Greg Daniel7278d682018-03-16 14:57:21 -0400108 REPORTER_ASSERT(reporter, backendFormat.isValid());
Greg Daniela8d92112018-03-09 12:05:04 -0500109
Greg Daniel7278d682018-03-16 14:57:21 -0400110 PromiseTextureChecker promiseChecker(backendTex);
111 GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
112 sk_sp<SkImage> refImg(
113 SkImage_Gpu::MakePromiseTexture(ctx, backendFormat, kWidth, kHeight,
114 GrMipMapped::kNo, texOrigin,
115 kRGBA_8888_SkColorType, kPremul_SkAlphaType,
116 nullptr,
117 PromiseTextureChecker::Fulfill,
118 PromiseTextureChecker::Release,
119 PromiseTextureChecker::Done,
120 &promiseChecker));
Greg Daniela8d92112018-03-09 12:05:04 -0500121
Greg Daniel7278d682018-03-16 14:57:21 -0400122 SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
123 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
124 SkCanvas* canvas = surface->getCanvas();
Greg Daniela8d92112018-03-09 12:05:04 -0500125
Greg Daniel7278d682018-03-16 14:57:21 -0400126 int expectedFulfillCnt = 0;
127 int expectedReleaseCnt = 0;
128 int expectedDoneCnt = 0;
Greg Daniela8d92112018-03-09 12:05:04 -0500129
Greg Daniel7278d682018-03-16 14:57:21 -0400130 canvas->drawImage(refImg, 0, 0);
131 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
132 true,
133 expectedFulfillCnt,
134 expectedReleaseCnt,
135 true,
136 expectedDoneCnt,
137 reporter));
Greg Daniela8d92112018-03-09 12:05:04 -0500138
Greg Daniel7278d682018-03-16 14:57:21 -0400139 bool isVulkan = kVulkan_GrBackend == ctx->contextPriv().getBackend();
140 canvas->flush();
141 expectedFulfillCnt++;
142 expectedReleaseCnt++;
143 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
144 !isVulkan,
145 expectedFulfillCnt,
146 expectedReleaseCnt,
147 !isVulkan,
148 expectedDoneCnt,
149 reporter));
Greg Daniela8d92112018-03-09 12:05:04 -0500150
Greg Daniel7278d682018-03-16 14:57:21 -0400151 gpu->testingOnly_flushGpuAndSync();
152 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
153 true,
154 expectedFulfillCnt,
155 expectedReleaseCnt,
156 true,
157 expectedDoneCnt,
158 reporter));
Greg Daniela8d92112018-03-09 12:05:04 -0500159
Greg Daniel7278d682018-03-16 14:57:21 -0400160 canvas->drawImage(refImg, 0, 0);
161 canvas->drawImage(refImg, 0, 0);
Greg Daniela8d92112018-03-09 12:05:04 -0500162
Greg Daniel7278d682018-03-16 14:57:21 -0400163 canvas->flush();
164 expectedFulfillCnt++;
165 expectedReleaseCnt++;
Greg Daniela8d92112018-03-09 12:05:04 -0500166
Greg Daniel7278d682018-03-16 14:57:21 -0400167 gpu->testingOnly_flushGpuAndSync();
168 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
169 true,
170 expectedFulfillCnt,
171 expectedReleaseCnt,
172 true,
173 expectedDoneCnt,
174 reporter));
Greg Daniela8d92112018-03-09 12:05:04 -0500175
Greg Daniel7278d682018-03-16 14:57:21 -0400176 // Now test code path on Vulkan where we released the texture, but the GPU isn't done with
177 // resource yet and we do another draw. We should only call fulfill on the first draw and
178 // use the cached GrBackendTexture on the second. Release should only be called after the
179 // second draw is finished.
180 canvas->drawImage(refImg, 0, 0);
181 canvas->flush();
182 expectedFulfillCnt++;
183 expectedReleaseCnt++;
184 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
185 !isVulkan,
186 expectedFulfillCnt,
187 expectedReleaseCnt,
188 !isVulkan,
189 expectedDoneCnt,
190 reporter));
Greg Daniela8d92112018-03-09 12:05:04 -0500191
Greg Daniel7278d682018-03-16 14:57:21 -0400192 canvas->drawImage(refImg, 0, 0);
Greg Daniela8d92112018-03-09 12:05:04 -0500193
Greg Daniel7278d682018-03-16 14:57:21 -0400194 if (releaseImageEarly) {
195 refImg.reset();
196 }
Greg Daniela8d92112018-03-09 12:05:04 -0500197
Greg Daniel7278d682018-03-16 14:57:21 -0400198 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
199 !isVulkan,
200 expectedFulfillCnt,
201 expectedReleaseCnt,
202 !isVulkan,
203 expectedDoneCnt,
204 reporter));
Greg Daniela8d92112018-03-09 12:05:04 -0500205
Greg Daniel7278d682018-03-16 14:57:21 -0400206 canvas->flush();
207 expectedFulfillCnt++;
Greg Daniela8d92112018-03-09 12:05:04 -0500208
Greg Daniel7278d682018-03-16 14:57:21 -0400209 gpu->testingOnly_flushGpuAndSync();
210 expectedReleaseCnt++;
211 if (releaseImageEarly) {
212 expectedDoneCnt++;
213 }
214 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
215 true,
216 expectedFulfillCnt,
217 expectedReleaseCnt,
218 !isVulkan,
219 expectedDoneCnt,
220 reporter));
221 expectedFulfillCnt = promiseChecker.fFulfillCount;
222 expectedReleaseCnt = promiseChecker.fReleaseCount;
223
224 if (!releaseImageEarly) {
225 refImg.reset();
226 expectedDoneCnt++;
227 }
228
229 REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
230 true,
231 expectedFulfillCnt,
232 expectedReleaseCnt,
233 true,
234 expectedDoneCnt,
235 reporter));
236
237 gpu->deleteTestingOnlyBackendTexture(backendTex);
238 }
Greg Daniela8d92112018-03-09 12:05:04 -0500239}