blob: a7b8fd84369bafc90226a02e7703a0509f23fc59 [file] [log] [blame]
Greg Daniel177e6952017-10-12 12:27:11 -04001/*
2 * Copyright 2017 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkTypes.h"
Greg Daniel177e6952017-10-12 12:27:11 -04009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkCanvas.h"
11#include "include/core/SkPoint.h"
12#include "include/core/SkSurface.h"
13#include "include/gpu/GrBackendSurface.h"
14#include "include/gpu/GrContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/gpu/GrBackendTextureImageGenerator.h"
16#include "src/gpu/GrContextPriv.h"
Chris Dalton3d770272019-08-14 09:24:37 -060017#include "src/gpu/GrDrawingManager.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/gpu/GrGpu.h"
Greg Daniel47c20e82020-01-21 14:29:57 -050019#include "src/gpu/GrRecordingContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/gpu/GrRenderTargetContext.h"
21#include "src/gpu/GrSemaphore.h"
22#include "src/gpu/GrSurfaceProxyPriv.h"
23#include "src/gpu/GrTexturePriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040024#include "src/gpu/GrTextureProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "src/gpu/SkGpuDevice.h"
26#include "src/image/SkImage_Base.h"
27#include "src/image/SkSurface_Gpu.h"
28#include "tests/Test.h"
Greg Daniel177e6952017-10-12 12:27:11 -040029
Greg Daniel45d63032017-10-30 13:41:26 -040030static constexpr int kSize = 8;
31
Greg Daniel177e6952017-10-12 12:27:11 -040032// Test that the correct mip map states are on the GrTextures when wrapping GrBackendTextures in
33// SkImages and SkSurfaces
34DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest, reporter, ctxInfo) {
35 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -050036 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel261b8aa2017-10-23 09:37:36 -040037 return;
38 }
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050039
Greg Daniel177e6952017-10-12 12:27:11 -040040 for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040041 for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
Robert Phillips9b16f812019-05-17 10:01:21 -040042 // createBackendTexture currently doesn't support uploading data to mip maps
Greg Daniel177e6952017-10-12 12:27:11 -040043 // so we don't send any. However, we pretend there is data for the checks below which is
44 // fine since we are never actually using these textures for any work on the gpu.
Robert Phillips4bdd36f2019-06-04 11:03:06 -040045 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -040046 kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -040047 SkColors::kTransparent, mipMapped, renderable, GrProtected::kNo);
Greg Daniel177e6952017-10-12 12:27:11 -040048
Robert Phillipse0070c02017-11-13 12:47:24 -050049 sk_sp<GrTextureProxy> proxy;
Greg Daniel177e6952017-10-12 12:27:11 -040050 sk_sp<SkImage> image;
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040051 if (GrRenderable::kYes == renderable) {
Greg Daniel177e6952017-10-12 12:27:11 -040052 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(
53 context,
54 backendTex,
55 kTopLeft_GrSurfaceOrigin,
56 0,
Greg Danielfaa095e2017-12-19 13:15:02 -050057 kRGBA_8888_SkColorType,
Greg Daniel177e6952017-10-12 12:27:11 -040058 nullptr,
59 nullptr);
60
61 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
Robert Phillipse0070c02017-11-13 12:47:24 -050062 proxy = device->accessRenderTargetContext()->asTextureProxyRef();
Greg Daniel177e6952017-10-12 12:27:11 -040063 } else {
64 image = SkImage::MakeFromTexture(context, backendTex,
65 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -050066 kRGBA_8888_SkColorType,
67 kPremul_SkAlphaType, nullptr,
68 nullptr, nullptr);
Robert Phillips6603a172019-03-05 12:35:44 -050069 proxy = as_IB(image)->asTextureProxyRef(context);
Greg Daniel177e6952017-10-12 12:27:11 -040070 }
71 REPORTER_ASSERT(reporter, proxy);
72 if (!proxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -040073 context->deleteBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040074 return;
75 }
76
Brian Salomonfd98c2c2018-07-31 17:25:29 -040077 REPORTER_ASSERT(reporter, proxy->isInstantiated());
Greg Daniel177e6952017-10-12 12:27:11 -040078
Brian Salomonfd98c2c2018-07-31 17:25:29 -040079 GrTexture* texture = proxy->peekTexture();
Greg Daniel177e6952017-10-12 12:27:11 -040080 REPORTER_ASSERT(reporter, texture);
81 if (!texture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -040082 context->deleteBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040083 return;
84 }
85
86 if (GrMipMapped::kYes == mipMapped) {
Greg Daniele252f082017-10-23 16:05:23 -040087 REPORTER_ASSERT(reporter, GrMipMapped::kYes == texture->texturePriv().mipMapped());
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040088 if (GrRenderable::kYes == renderable) {
Greg Daniel177e6952017-10-12 12:27:11 -040089 REPORTER_ASSERT(reporter, texture->texturePriv().mipMapsAreDirty());
90 } else {
91 REPORTER_ASSERT(reporter, !texture->texturePriv().mipMapsAreDirty());
92 }
93 } else {
Greg Daniele252f082017-10-23 16:05:23 -040094 REPORTER_ASSERT(reporter, GrMipMapped::kNo == texture->texturePriv().mipMapped());
Greg Daniel177e6952017-10-12 12:27:11 -040095 }
Robert Phillips5c7a25b2019-05-20 08:38:07 -040096 context->deleteBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040097 }
98 }
99}
100
Greg Daniel261b8aa2017-10-23 09:37:36 -0400101// Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator
102// based on if we will use mips in the draw and the mip status of the GrBackendTexture.
103DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400104 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500105 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400106 return;
107 }
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500108
Greg Daniel261b8aa2017-10-23 09:37:36 -0400109 for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
110 for (auto willUseMips : {false, true}) {
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400111 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400112 kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400113 SkColors::kTransparent, mipMapped, GrRenderable::kNo, GrProtected::kNo);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400114
Greg Daniel261b8aa2017-10-23 09:37:36 -0400115 sk_sp<SkImage> image = SkImage::MakeFromTexture(context, backendTex,
116 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -0500117 kRGBA_8888_SkColorType,
118 kPremul_SkAlphaType, nullptr,
119 nullptr, nullptr);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400120
121 GrTextureProxy* proxy = as_IB(image)->peekProxy();
122 REPORTER_ASSERT(reporter, proxy);
123 if (!proxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400124 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400125 return;
126 }
127
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400128 REPORTER_ASSERT(reporter, proxy->isInstantiated());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400129
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400130 sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400131 REPORTER_ASSERT(reporter, texture);
132 if (!texture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400133 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400134 return;
135 }
136
137 std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make(
Brian Osman052ef692018-03-27 09:56:31 -0400138 texture, kTopLeft_GrSurfaceOrigin, nullptr, kRGBA_8888_SkColorType,
139 kPremul_SkAlphaType, nullptr);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400140 REPORTER_ASSERT(reporter, imageGen);
141 if (!imageGen) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400142 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400143 return;
144 }
145
146 SkIPoint origin = SkIPoint::Make(0,0);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400147 SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
148 kPremul_SkAlphaType);
Greg Danielcc104db2020-02-03 14:17:08 -0500149 GrSurfaceProxyView genView = imageGen->generateTexture(context, imageInfo, origin,
150 willUseMips);
151 GrSurfaceProxy* genProxy = genView.proxy();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400152
153 REPORTER_ASSERT(reporter, genProxy);
154 if (!genProxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400155 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400156 return;
157 }
158
Brian Salomonbeb7f522019-08-30 16:19:42 -0400159 if (genProxy->isLazy()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500160 genProxy->priv().doLazyInstantiation(context->priv().resourceProvider());
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400161 } else if (!genProxy->isInstantiated()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500162 genProxy->instantiate(context->priv().resourceProvider());
Greg Daniele728f672018-01-17 10:52:04 -0500163 }
164
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400165 REPORTER_ASSERT(reporter, genProxy->isInstantiated());
166 if (!genProxy->isInstantiated()) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400167 context->deleteBackendTexture(backendTex);
Greg Danielbddcc952018-01-24 13:22:24 -0500168 return;
169 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400170
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400171 GrTexture* genTexture = genProxy->peekTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400172 REPORTER_ASSERT(reporter, genTexture);
173 if (!genTexture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400174 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400175 return;
176 }
177
Robert Phillipsb67821d2017-12-13 15:00:45 -0500178 GrBackendTexture genBackendTex = genTexture->getBackendTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400179
Greg Danielbdf12ad2018-10-12 09:31:11 -0400180 if (GrBackendApi::kOpenGL == genBackendTex.backend()) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400181 GrGLTextureInfo genTexInfo;
182 GrGLTextureInfo origTexInfo;
183 if (genBackendTex.getGLTextureInfo(&genTexInfo) &&
184 backendTex.getGLTextureInfo(&origTexInfo)) {
185 if (willUseMips && GrMipMapped::kNo == mipMapped) {
186 // We did a copy so the texture IDs should be different
187 REPORTER_ASSERT(reporter, origTexInfo.fID != genTexInfo.fID);
188 } else {
189 REPORTER_ASSERT(reporter, origTexInfo.fID == genTexInfo.fID);
190 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400191 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400192 ERRORF(reporter, "Failed to get GrGLTextureInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400193 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400194#ifdef SK_VULKAN
Greg Danielbdf12ad2018-10-12 09:31:11 -0400195 } else if (GrBackendApi::kVulkan == genBackendTex.backend()) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400196 GrVkImageInfo genImageInfo;
197 GrVkImageInfo origImageInfo;
198 if (genBackendTex.getVkImageInfo(&genImageInfo) &&
199 backendTex.getVkImageInfo(&origImageInfo)) {
200 if (willUseMips && GrMipMapped::kNo == mipMapped) {
201 // We did a copy so the texture IDs should be different
202 REPORTER_ASSERT(reporter, origImageInfo.fImage != genImageInfo.fImage);
203 } else {
204 REPORTER_ASSERT(reporter, origImageInfo.fImage == genImageInfo.fImage);
205 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400206 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400207 ERRORF(reporter, "Failed to get GrVkImageInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400208 }
209#endif
Jim Van Verth9896a0d2019-04-10 15:11:12 -0400210#ifdef SK_METAL
211 } else if (GrBackendApi::kMetal == genBackendTex.backend()) {
212 GrMtlTextureInfo genImageInfo;
213 GrMtlTextureInfo origImageInfo;
214 if (genBackendTex.getMtlTextureInfo(&genImageInfo) &&
215 backendTex.getMtlTextureInfo(&origImageInfo)) {
216 if (willUseMips && GrMipMapped::kNo == mipMapped) {
217 // We did a copy so the texture IDs should be different
218 REPORTER_ASSERT(reporter, origImageInfo.fTexture != genImageInfo.fTexture);
219 } else {
220 REPORTER_ASSERT(reporter, origImageInfo.fTexture == genImageInfo.fTexture);
221 }
222 } else {
223 ERRORF(reporter, "Failed to get GrMtlTextureInfo");
224 }
225#endif
Greg Daniel261b8aa2017-10-23 09:37:36 -0400226 } else {
227 REPORTER_ASSERT(reporter, false);
228 }
229
230 // Must make sure the uses of the backend texture have finished (we possibly have a
Greg Daniel26b50a42018-03-08 09:49:58 -0500231 // queued up copy) before we delete the backend texture.
232 context->flush();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400233
Robert Phillips9b16f812019-05-17 10:01:21 -0400234 context->priv().getGpu()->testingOnly_flushGpuAndSync();
235
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400236 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400237 }
238 }
239}
240
Greg Daniel45d63032017-10-30 13:41:26 -0400241// Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the
242// resource we took the snapshot of.
243DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) {
244 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500245 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel45d63032017-10-30 13:41:26 -0400246 return;
247 }
248
Robert Phillips9da87e02019-02-04 13:26:26 -0500249 auto resourceProvider = context->priv().resourceProvider();
Robert Phillips6be756b2018-01-16 15:07:54 -0500250
Greg Daniel45d63032017-10-30 13:41:26 -0400251 for (auto willUseMips : {false, true}) {
252 for (auto isWrapped : {false, true}) {
253 GrMipMapped mipMapped = willUseMips ? GrMipMapped::kYes : GrMipMapped::kNo;
254 sk_sp<SkSurface> surface;
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400255 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400256 kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400257 SkColors::kTransparent, mipMapped, GrRenderable::kYes, GrProtected::kNo);
Greg Daniel45d63032017-10-30 13:41:26 -0400258 if (isWrapped) {
Greg Daniel45d63032017-10-30 13:41:26 -0400259 surface = SkSurface::MakeFromBackendTexture(context,
260 backendTex,
261 kTopLeft_GrSurfaceOrigin,
262 0,
Greg Danielfaa095e2017-12-19 13:15:02 -0500263 kRGBA_8888_SkColorType,
Greg Daniel45d63032017-10-30 13:41:26 -0400264 nullptr,
265 nullptr);
266 } else {
267 SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
268 kPremul_SkAlphaType);
269 surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
270 kTopLeft_GrSurfaceOrigin, nullptr,
271 willUseMips);
272 }
273 REPORTER_ASSERT(reporter, surface);
274 if (!surface) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400275 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400276 }
277 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
278 GrTextureProxy* texProxy = device->accessRenderTargetContext()->asTextureProxy();
279 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
280
Robert Phillips6be756b2018-01-16 15:07:54 -0500281 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400282 GrTexture* texture = texProxy->peekTexture();
Greg Daniel45d63032017-10-30 13:41:26 -0400283 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
284
285 sk_sp<SkImage> image = surface->makeImageSnapshot();
286 REPORTER_ASSERT(reporter, image);
287 if (!image) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400288 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400289 }
290 texProxy = as_IB(image)->peekProxy();
291 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
292
Robert Phillips6be756b2018-01-16 15:07:54 -0500293 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400294 texture = texProxy->peekTexture();
Greg Daniel45d63032017-10-30 13:41:26 -0400295 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
296
297 // Must flush the context to make sure all the cmds (copies, etc.) from above are sent
298 // to the gpu before we delete the backendHandle.
299 context->flush();
Robert Phillips9b16f812019-05-17 10:01:21 -0400300 context->priv().getGpu()->testingOnly_flushGpuAndSync();
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400301 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400302 }
303 }
304}
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400305
306// Test that we don't create a mip mapped texture if the size is 1x1 even if the filter mode is set
307// to use mips. This test passes by not crashing or hitting asserts in code.
308DEF_GPUTEST_FOR_RENDERING_CONTEXTS(Gr1x1TextureMipMappedTest, reporter, ctxInfo) {
309 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500310 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400311 return;
312 }
313
314 // Make surface to draw into
315 SkImageInfo info = SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType);
316 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info);
317
318 // Make 1x1 raster bitmap
319 SkBitmap bmp;
320 bmp.allocN32Pixels(1, 1);
321 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(bmp.getPixels());
322 *pixel = 0;
323
324 sk_sp<SkImage> bmpImage = SkImage::MakeFromBitmap(bmp);
325
326 // Make sure we scale so we don't optimize out the use of mips.
327 surface->getCanvas()->scale(0.5f, 0.5f);
328
329 SkPaint paint;
330 // This should upload the image to a non mipped GrTextureProxy.
331 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
332 surface->flush();
333
334 // Now set the filter quality to high so we use mip maps. We should find the non mipped texture
335 // in the cache for the SkImage. Since the texture is 1x1 we should just use that texture
336 // instead of trying to do a copy to a mipped texture.
337 paint.setFilterQuality(kHigh_SkFilterQuality);
338 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
339 surface->flush();
340}
341
Greg Daniel40903af2020-01-30 14:55:05 -0500342// Create a new render target and draw 'mipmapView' into it using the provided 'filter'.
Brian Salomonbf6b9792019-08-21 09:38:10 -0400343static std::unique_ptr<GrRenderTargetContext> draw_mipmap_into_new_render_target(
Greg Danielba0ff782020-01-07 15:42:57 -0500344 GrRecordingContext* context, GrProxyProvider* proxyProvider, GrColorType colorType,
Greg Daniel40903af2020-01-30 14:55:05 -0500345 SkAlphaType alphaType, GrSurfaceProxyView mipmapView, GrSamplerState::Filter filter) {
Chris Dalton3d770272019-08-14 09:24:37 -0600346 GrSurfaceDesc desc;
347 desc.fWidth = 1;
348 desc.fHeight = 1;
Chris Dalton3d770272019-08-14 09:24:37 -0600349 sk_sp<GrSurfaceProxy> renderTarget = proxyProvider->createProxy(
Greg Daniel40903af2020-01-30 14:55:05 -0500350 mipmapView.proxy()->backendFormat(), desc, mipmapView.swizzle(), GrRenderable::kYes, 1,
351 mipmapView.origin(), GrMipMapped::kNo, SkBackingFit::kApprox, SkBudgeted::kYes,
Greg Daniel47c20e82020-01-21 14:29:57 -0500352 GrProtected::kNo);
Greg Danielba0ff782020-01-07 15:42:57 -0500353
354 auto rtc = GrRenderTargetContext::Make(
355 context, colorType, nullptr, std::move(renderTarget), kTopLeft_GrSurfaceOrigin,
356 nullptr);
357
Greg Daniel40903af2020-01-30 14:55:05 -0500358 rtc->drawTexture(GrNoClip(), std::move(mipmapView), alphaType, filter, SkBlendMode::kSrcOver,
Greg Danielc594e622019-10-15 14:01:49 -0400359 {1,1,1,1}, SkRect::MakeWH(4, 4), SkRect::MakeWH(1,1), GrAA::kYes,
Brian Salomonfc118442019-11-22 19:09:27 -0500360 GrQuadAAFlags::kAll, SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(),
361 nullptr);
Chris Dalton3d770272019-08-14 09:24:37 -0600362 return rtc;
363}
364
Greg Danielf41b2bd2019-08-22 16:19:24 -0400365// Test that two opsTasks using the same mipmaps both depend on the same GrTextureResolveRenderTask.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600366DEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) {
367 using CanClearFullscreen = GrRenderTargetContext::CanClearFullscreen;
368 using Enable = GrContextOptions::Enable;
369 using Filter = GrSamplerState::Filter;
370
371 for (auto enableSortingAndReduction : {Enable::kYes, Enable::kNo}) {
372 GrMockOptions mockOptions;
373 mockOptions.fMipMapSupport = true;
374 GrContextOptions ctxOptions;
Greg Daniel93138742019-08-22 17:15:39 -0400375 ctxOptions.fReduceOpsTaskSplitting = enableSortingAndReduction;
Chris Dalton30eea6c2019-08-21 10:22:50 -0600376 sk_sp<GrContext> context = GrContext::MakeMock(&mockOptions, ctxOptions);
377 if (!context) {
Greg Danielf41b2bd2019-08-22 16:19:24 -0400378 ERRORF(reporter, "could not create mock context with fReduceOpsTaskSplitting %s.",
Chris Dalton30eea6c2019-08-21 10:22:50 -0600379 (Enable::kYes == enableSortingAndReduction) ? "enabled" : "disabled");
380 continue;
381 }
382
383 SkASSERT(context->priv().caps()->mipMapSupport());
384
385 GrBackendFormat format = context->defaultBackendFormat(
386 kRGBA_8888_SkColorType, GrRenderable::kYes);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600387 GrColorType colorType = GrColorType::kRGBA_8888;
Brian Salomonfc118442019-11-22 19:09:27 -0500388 SkAlphaType alphaType = kPremul_SkAlphaType;
Chris Dalton30eea6c2019-08-21 10:22:50 -0600389
Chris Dalton30eea6c2019-08-21 10:22:50 -0600390 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
391
392 // Create a mipmapped render target.
393 GrSurfaceDesc desc;
394 desc.fWidth = 4;
395 desc.fHeight = 4;
Greg Daniel47c20e82020-01-21 14:29:57 -0500396
397 GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(format, colorType);
398
Brian Salomonbeb7f522019-08-30 16:19:42 -0400399 sk_sp<GrTextureProxy> mipmapProxy = proxyProvider->createProxy(
Greg Daniel47c20e82020-01-21 14:29:57 -0500400 format, desc, swizzle, GrRenderable::kYes, 1, kTopLeft_GrSurfaceOrigin,
401 GrMipMapped::kYes, SkBackingFit::kExact, SkBudgeted::kYes, GrProtected::kNo);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600402
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600403 // Mark the mipmaps clean to ensure things still work properly when they won't be marked
404 // dirty again until GrRenderTask::makeClosed().
405 mipmapProxy->markMipMapsClean();
406
Greg Danielba0ff782020-01-07 15:42:57 -0500407 auto mipmapRTC = GrRenderTargetContext::Make(
408 context.get(), colorType, nullptr, mipmapProxy, kTopLeft_GrSurfaceOrigin, nullptr);
409
Chris Dalton30eea6c2019-08-21 10:22:50 -0600410 mipmapRTC->clear(nullptr, {.1f,.2f,.3f,.4f}, CanClearFullscreen::kYes);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600411 REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask());
Greg Danielf41b2bd2019-08-22 16:19:24 -0400412 // mipmapProxy's last render task should now just be the opsTask containing the clear.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600413 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400414 mipmapRTC->testingOnly_PeekLastOpsTask() == mipmapProxy->getLastRenderTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600415
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600416 // Mipmaps don't get marked dirty until makeClosed().
417 REPORTER_ASSERT(reporter, !mipmapProxy->mipMapsAreDirty());
418
Greg Daniel40903af2020-01-30 14:55:05 -0500419 GrSurfaceProxyView mipmapView(mipmapProxy, kTopLeft_GrSurfaceOrigin, swizzle);
420
Chris Dalton30eea6c2019-08-21 10:22:50 -0600421 // Draw the dirty mipmap texture into a render target.
Greg Danielba0ff782020-01-07 15:42:57 -0500422 auto rtc1 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
Greg Daniel40903af2020-01-30 14:55:05 -0500423 alphaType, mipmapView, Filter::kMipMap);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600424
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600425 // Mipmaps should have gotten marked dirty during makeClosed, then marked clean again as
426 // soon as a GrTextureResolveRenderTask was inserted. The way we know they were resolved is
Greg Danielf41b2bd2019-08-22 16:19:24 -0400427 // if mipmapProxy->getLastRenderTask() has switched from the opsTask that drew to it, to the
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600428 // task that resolved its mips.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600429 GrRenderTask* initialMipmapRegenTask = mipmapProxy->getLastRenderTask();
430 REPORTER_ASSERT(reporter, initialMipmapRegenTask);
431 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400432 initialMipmapRegenTask != mipmapRTC->testingOnly_PeekLastOpsTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600433 REPORTER_ASSERT(reporter, !mipmapProxy->mipMapsAreDirty());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600434
435 // Draw the now-clean mipmap texture into a second target.
Greg Danielba0ff782020-01-07 15:42:57 -0500436 auto rtc2 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
Greg Daniel40903af2020-01-30 14:55:05 -0500437 alphaType, mipmapView, Filter::kMipMap);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600438
439 // Make sure the mipmap texture still has the same regen task.
440 REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask() == initialMipmapRegenTask);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600441 SkASSERT(!mipmapProxy->mipMapsAreDirty());
442
443 // Reset everything so we can go again, this time with the first draw not mipmapped.
444 context->flush();
445
Chris Daltone2a903e2019-09-18 13:41:50 -0600446 // Mip regen tasks don't get added as dependencies until makeClosed().
447 REPORTER_ASSERT(reporter,
448 rtc1->testingOnly_PeekLastOpsTask()->dependsOn(initialMipmapRegenTask));
449 REPORTER_ASSERT(reporter,
450 rtc2->testingOnly_PeekLastOpsTask()->dependsOn(initialMipmapRegenTask));
451
Chris Dalton30eea6c2019-08-21 10:22:50 -0600452 // Render something to dirty the mips.
453 mipmapRTC->clear(nullptr, {.1f,.2f,.3f,.4f}, CanClearFullscreen::kYes);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600454 REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask());
Greg Danielf41b2bd2019-08-22 16:19:24 -0400455 // mipmapProxy's last render task should now just be the opsTask containing the clear.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600456 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400457 mipmapRTC->testingOnly_PeekLastOpsTask() == mipmapProxy->getLastRenderTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600458
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600459 // Mipmaps don't get marked dirty until makeClosed().
460 REPORTER_ASSERT(reporter, !mipmapProxy->mipMapsAreDirty());
461
Chris Dalton30eea6c2019-08-21 10:22:50 -0600462 // Draw the dirty mipmap texture into a render target, but don't do mipmap filtering.
Greg Danielba0ff782020-01-07 15:42:57 -0500463 rtc1 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
Greg Daniel40903af2020-01-30 14:55:05 -0500464 alphaType, mipmapView, Filter::kBilerp);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600465
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600466 // Mipmaps should have gotten marked dirty during makeClosed() when adding the dependency.
467 // Since the last draw did not use mips, they will not have been regenerated and should
468 // therefore still be dirty.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600469 REPORTER_ASSERT(reporter, mipmapProxy->mipMapsAreDirty());
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600470
471 // Since mips weren't regenerated, the last render task shouldn't have changed.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600472 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400473 mipmapRTC->testingOnly_PeekLastOpsTask() == mipmapProxy->getLastRenderTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600474
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600475 // Draw the stil-dirty mipmap texture into a second target with mipmap filtering.
Greg Danielba0ff782020-01-07 15:42:57 -0500476 rtc2 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
Greg Daniel40903af2020-01-30 14:55:05 -0500477 alphaType, std::move(mipmapView),
478 Filter::kMipMap);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600479
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600480 // Make sure the mipmap texture now has a new last render task that regenerates the mips,
481 // and that the mipmaps are now clean.
Chris Daltone2a903e2019-09-18 13:41:50 -0600482 auto mipRegenTask2 = mipmapProxy->getLastRenderTask();
483 REPORTER_ASSERT(reporter, mipRegenTask2);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600484 REPORTER_ASSERT(reporter,
Chris Daltone2a903e2019-09-18 13:41:50 -0600485 mipmapRTC->testingOnly_PeekLastOpsTask() != mipRegenTask2);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600486 SkASSERT(!mipmapProxy->mipMapsAreDirty());
Chris Daltone2a903e2019-09-18 13:41:50 -0600487
488 // Mip regen tasks don't get added as dependencies until makeClosed().
489 context->flush();
490 REPORTER_ASSERT(reporter, rtc2->testingOnly_PeekLastOpsTask()->dependsOn(mipRegenTask2));
Chris Dalton3d770272019-08-14 09:24:37 -0600491 }
Chris Dalton3d770272019-08-14 09:24:37 -0600492}