blob: 7a24853bc8997df0e1feb35b046192e028416dc1 [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);
149 sk_sp<GrTextureProxy> genProxy = imageGen->generateTexture(context, imageInfo,
Brian Osmanc87cfb62018-07-11 09:08:46 -0400150 origin, willUseMips);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400151
152 REPORTER_ASSERT(reporter, genProxy);
153 if (!genProxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400154 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400155 return;
156 }
157
Brian Salomonbeb7f522019-08-30 16:19:42 -0400158 if (genProxy->isLazy()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500159 genProxy->priv().doLazyInstantiation(context->priv().resourceProvider());
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400160 } else if (!genProxy->isInstantiated()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500161 genProxy->instantiate(context->priv().resourceProvider());
Greg Daniele728f672018-01-17 10:52:04 -0500162 }
163
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400164 REPORTER_ASSERT(reporter, genProxy->isInstantiated());
165 if (!genProxy->isInstantiated()) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400166 context->deleteBackendTexture(backendTex);
Greg Danielbddcc952018-01-24 13:22:24 -0500167 return;
168 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400169
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400170 GrTexture* genTexture = genProxy->peekTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400171 REPORTER_ASSERT(reporter, genTexture);
172 if (!genTexture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400173 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400174 return;
175 }
176
Robert Phillipsb67821d2017-12-13 15:00:45 -0500177 GrBackendTexture genBackendTex = genTexture->getBackendTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400178
Greg Danielbdf12ad2018-10-12 09:31:11 -0400179 if (GrBackendApi::kOpenGL == genBackendTex.backend()) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400180 GrGLTextureInfo genTexInfo;
181 GrGLTextureInfo origTexInfo;
182 if (genBackendTex.getGLTextureInfo(&genTexInfo) &&
183 backendTex.getGLTextureInfo(&origTexInfo)) {
184 if (willUseMips && GrMipMapped::kNo == mipMapped) {
185 // We did a copy so the texture IDs should be different
186 REPORTER_ASSERT(reporter, origTexInfo.fID != genTexInfo.fID);
187 } else {
188 REPORTER_ASSERT(reporter, origTexInfo.fID == genTexInfo.fID);
189 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400190 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400191 ERRORF(reporter, "Failed to get GrGLTextureInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400192 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400193#ifdef SK_VULKAN
Greg Danielbdf12ad2018-10-12 09:31:11 -0400194 } else if (GrBackendApi::kVulkan == genBackendTex.backend()) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400195 GrVkImageInfo genImageInfo;
196 GrVkImageInfo origImageInfo;
197 if (genBackendTex.getVkImageInfo(&genImageInfo) &&
198 backendTex.getVkImageInfo(&origImageInfo)) {
199 if (willUseMips && GrMipMapped::kNo == mipMapped) {
200 // We did a copy so the texture IDs should be different
201 REPORTER_ASSERT(reporter, origImageInfo.fImage != genImageInfo.fImage);
202 } else {
203 REPORTER_ASSERT(reporter, origImageInfo.fImage == genImageInfo.fImage);
204 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400205 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400206 ERRORF(reporter, "Failed to get GrVkImageInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400207 }
208#endif
Jim Van Verth9896a0d2019-04-10 15:11:12 -0400209#ifdef SK_METAL
210 } else if (GrBackendApi::kMetal == genBackendTex.backend()) {
211 GrMtlTextureInfo genImageInfo;
212 GrMtlTextureInfo origImageInfo;
213 if (genBackendTex.getMtlTextureInfo(&genImageInfo) &&
214 backendTex.getMtlTextureInfo(&origImageInfo)) {
215 if (willUseMips && GrMipMapped::kNo == mipMapped) {
216 // We did a copy so the texture IDs should be different
217 REPORTER_ASSERT(reporter, origImageInfo.fTexture != genImageInfo.fTexture);
218 } else {
219 REPORTER_ASSERT(reporter, origImageInfo.fTexture == genImageInfo.fTexture);
220 }
221 } else {
222 ERRORF(reporter, "Failed to get GrMtlTextureInfo");
223 }
224#endif
Greg Daniel261b8aa2017-10-23 09:37:36 -0400225 } else {
226 REPORTER_ASSERT(reporter, false);
227 }
228
229 // Must make sure the uses of the backend texture have finished (we possibly have a
Greg Daniel26b50a42018-03-08 09:49:58 -0500230 // queued up copy) before we delete the backend texture.
231 context->flush();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400232
Robert Phillips9b16f812019-05-17 10:01:21 -0400233 context->priv().getGpu()->testingOnly_flushGpuAndSync();
234
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400235 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400236 }
237 }
238}
239
Greg Daniel45d63032017-10-30 13:41:26 -0400240// Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the
241// resource we took the snapshot of.
242DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) {
243 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500244 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel45d63032017-10-30 13:41:26 -0400245 return;
246 }
247
Robert Phillips9da87e02019-02-04 13:26:26 -0500248 auto resourceProvider = context->priv().resourceProvider();
Robert Phillips6be756b2018-01-16 15:07:54 -0500249
Greg Daniel45d63032017-10-30 13:41:26 -0400250 for (auto willUseMips : {false, true}) {
251 for (auto isWrapped : {false, true}) {
252 GrMipMapped mipMapped = willUseMips ? GrMipMapped::kYes : GrMipMapped::kNo;
253 sk_sp<SkSurface> surface;
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400254 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400255 kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400256 SkColors::kTransparent, mipMapped, GrRenderable::kYes, GrProtected::kNo);
Greg Daniel45d63032017-10-30 13:41:26 -0400257 if (isWrapped) {
Greg Daniel45d63032017-10-30 13:41:26 -0400258 surface = SkSurface::MakeFromBackendTexture(context,
259 backendTex,
260 kTopLeft_GrSurfaceOrigin,
261 0,
Greg Danielfaa095e2017-12-19 13:15:02 -0500262 kRGBA_8888_SkColorType,
Greg Daniel45d63032017-10-30 13:41:26 -0400263 nullptr,
264 nullptr);
265 } else {
266 SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
267 kPremul_SkAlphaType);
268 surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
269 kTopLeft_GrSurfaceOrigin, nullptr,
270 willUseMips);
271 }
272 REPORTER_ASSERT(reporter, surface);
273 if (!surface) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400274 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400275 }
276 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
277 GrTextureProxy* texProxy = device->accessRenderTargetContext()->asTextureProxy();
278 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
279
Robert Phillips6be756b2018-01-16 15:07:54 -0500280 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400281 GrTexture* texture = texProxy->peekTexture();
Greg Daniel45d63032017-10-30 13:41:26 -0400282 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
283
284 sk_sp<SkImage> image = surface->makeImageSnapshot();
285 REPORTER_ASSERT(reporter, image);
286 if (!image) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400287 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400288 }
289 texProxy = as_IB(image)->peekProxy();
290 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
291
Robert Phillips6be756b2018-01-16 15:07:54 -0500292 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400293 texture = texProxy->peekTexture();
Greg Daniel45d63032017-10-30 13:41:26 -0400294 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
295
296 // Must flush the context to make sure all the cmds (copies, etc.) from above are sent
297 // to the gpu before we delete the backendHandle.
298 context->flush();
Robert Phillips9b16f812019-05-17 10:01:21 -0400299 context->priv().getGpu()->testingOnly_flushGpuAndSync();
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400300 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400301 }
302 }
303}
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400304
305// Test that we don't create a mip mapped texture if the size is 1x1 even if the filter mode is set
306// to use mips. This test passes by not crashing or hitting asserts in code.
307DEF_GPUTEST_FOR_RENDERING_CONTEXTS(Gr1x1TextureMipMappedTest, reporter, ctxInfo) {
308 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500309 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400310 return;
311 }
312
313 // Make surface to draw into
314 SkImageInfo info = SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType);
315 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info);
316
317 // Make 1x1 raster bitmap
318 SkBitmap bmp;
319 bmp.allocN32Pixels(1, 1);
320 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(bmp.getPixels());
321 *pixel = 0;
322
323 sk_sp<SkImage> bmpImage = SkImage::MakeFromBitmap(bmp);
324
325 // Make sure we scale so we don't optimize out the use of mips.
326 surface->getCanvas()->scale(0.5f, 0.5f);
327
328 SkPaint paint;
329 // This should upload the image to a non mipped GrTextureProxy.
330 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
331 surface->flush();
332
333 // Now set the filter quality to high so we use mip maps. We should find the non mipped texture
334 // in the cache for the SkImage. Since the texture is 1x1 we should just use that texture
335 // instead of trying to do a copy to a mipped texture.
336 paint.setFilterQuality(kHigh_SkFilterQuality);
337 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
338 surface->flush();
339}
340
Greg Daniel40903af2020-01-30 14:55:05 -0500341// Create a new render target and draw 'mipmapView' into it using the provided 'filter'.
Brian Salomonbf6b9792019-08-21 09:38:10 -0400342static std::unique_ptr<GrRenderTargetContext> draw_mipmap_into_new_render_target(
Greg Danielba0ff782020-01-07 15:42:57 -0500343 GrRecordingContext* context, GrProxyProvider* proxyProvider, GrColorType colorType,
Greg Daniel40903af2020-01-30 14:55:05 -0500344 SkAlphaType alphaType, GrSurfaceProxyView mipmapView, GrSamplerState::Filter filter) {
Chris Dalton3d770272019-08-14 09:24:37 -0600345 GrSurfaceDesc desc;
346 desc.fWidth = 1;
347 desc.fHeight = 1;
Chris Dalton3d770272019-08-14 09:24:37 -0600348 sk_sp<GrSurfaceProxy> renderTarget = proxyProvider->createProxy(
Greg Daniel40903af2020-01-30 14:55:05 -0500349 mipmapView.proxy()->backendFormat(), desc, mipmapView.swizzle(), GrRenderable::kYes, 1,
350 mipmapView.origin(), GrMipMapped::kNo, SkBackingFit::kApprox, SkBudgeted::kYes,
Greg Daniel47c20e82020-01-21 14:29:57 -0500351 GrProtected::kNo);
Greg Danielba0ff782020-01-07 15:42:57 -0500352
353 auto rtc = GrRenderTargetContext::Make(
354 context, colorType, nullptr, std::move(renderTarget), kTopLeft_GrSurfaceOrigin,
355 nullptr);
356
Greg Daniel40903af2020-01-30 14:55:05 -0500357 rtc->drawTexture(GrNoClip(), std::move(mipmapView), alphaType, filter, SkBlendMode::kSrcOver,
Greg Danielc594e622019-10-15 14:01:49 -0400358 {1,1,1,1}, SkRect::MakeWH(4, 4), SkRect::MakeWH(1,1), GrAA::kYes,
Brian Salomonfc118442019-11-22 19:09:27 -0500359 GrQuadAAFlags::kAll, SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(),
360 nullptr);
Chris Dalton3d770272019-08-14 09:24:37 -0600361 return rtc;
362}
363
Greg Danielf41b2bd2019-08-22 16:19:24 -0400364// Test that two opsTasks using the same mipmaps both depend on the same GrTextureResolveRenderTask.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600365DEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) {
366 using CanClearFullscreen = GrRenderTargetContext::CanClearFullscreen;
367 using Enable = GrContextOptions::Enable;
368 using Filter = GrSamplerState::Filter;
369
370 for (auto enableSortingAndReduction : {Enable::kYes, Enable::kNo}) {
371 GrMockOptions mockOptions;
372 mockOptions.fMipMapSupport = true;
373 GrContextOptions ctxOptions;
Greg Daniel93138742019-08-22 17:15:39 -0400374 ctxOptions.fReduceOpsTaskSplitting = enableSortingAndReduction;
Chris Dalton30eea6c2019-08-21 10:22:50 -0600375 sk_sp<GrContext> context = GrContext::MakeMock(&mockOptions, ctxOptions);
376 if (!context) {
Greg Danielf41b2bd2019-08-22 16:19:24 -0400377 ERRORF(reporter, "could not create mock context with fReduceOpsTaskSplitting %s.",
Chris Dalton30eea6c2019-08-21 10:22:50 -0600378 (Enable::kYes == enableSortingAndReduction) ? "enabled" : "disabled");
379 continue;
380 }
381
382 SkASSERT(context->priv().caps()->mipMapSupport());
383
384 GrBackendFormat format = context->defaultBackendFormat(
385 kRGBA_8888_SkColorType, GrRenderable::kYes);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600386 GrColorType colorType = GrColorType::kRGBA_8888;
Brian Salomonfc118442019-11-22 19:09:27 -0500387 SkAlphaType alphaType = kPremul_SkAlphaType;
Chris Dalton30eea6c2019-08-21 10:22:50 -0600388
Chris Dalton30eea6c2019-08-21 10:22:50 -0600389 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
390
391 // Create a mipmapped render target.
392 GrSurfaceDesc desc;
393 desc.fWidth = 4;
394 desc.fHeight = 4;
Greg Daniel47c20e82020-01-21 14:29:57 -0500395
396 GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(format, colorType);
397
Brian Salomonbeb7f522019-08-30 16:19:42 -0400398 sk_sp<GrTextureProxy> mipmapProxy = proxyProvider->createProxy(
Greg Daniel47c20e82020-01-21 14:29:57 -0500399 format, desc, swizzle, GrRenderable::kYes, 1, kTopLeft_GrSurfaceOrigin,
400 GrMipMapped::kYes, SkBackingFit::kExact, SkBudgeted::kYes, GrProtected::kNo);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600401
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600402 // Mark the mipmaps clean to ensure things still work properly when they won't be marked
403 // dirty again until GrRenderTask::makeClosed().
404 mipmapProxy->markMipMapsClean();
405
Greg Danielba0ff782020-01-07 15:42:57 -0500406 auto mipmapRTC = GrRenderTargetContext::Make(
407 context.get(), colorType, nullptr, mipmapProxy, kTopLeft_GrSurfaceOrigin, nullptr);
408
Chris Dalton30eea6c2019-08-21 10:22:50 -0600409 mipmapRTC->clear(nullptr, {.1f,.2f,.3f,.4f}, CanClearFullscreen::kYes);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600410 REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask());
Greg Danielf41b2bd2019-08-22 16:19:24 -0400411 // mipmapProxy's last render task should now just be the opsTask containing the clear.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600412 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400413 mipmapRTC->testingOnly_PeekLastOpsTask() == mipmapProxy->getLastRenderTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600414
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600415 // Mipmaps don't get marked dirty until makeClosed().
416 REPORTER_ASSERT(reporter, !mipmapProxy->mipMapsAreDirty());
417
Greg Daniel40903af2020-01-30 14:55:05 -0500418 GrSurfaceProxyView mipmapView(mipmapProxy, kTopLeft_GrSurfaceOrigin, swizzle);
419
Chris Dalton30eea6c2019-08-21 10:22:50 -0600420 // Draw the dirty mipmap texture into a render target.
Greg Danielba0ff782020-01-07 15:42:57 -0500421 auto rtc1 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
Greg Daniel40903af2020-01-30 14:55:05 -0500422 alphaType, mipmapView, Filter::kMipMap);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600423
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600424 // Mipmaps should have gotten marked dirty during makeClosed, then marked clean again as
425 // soon as a GrTextureResolveRenderTask was inserted. The way we know they were resolved is
Greg Danielf41b2bd2019-08-22 16:19:24 -0400426 // if mipmapProxy->getLastRenderTask() has switched from the opsTask that drew to it, to the
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600427 // task that resolved its mips.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600428 GrRenderTask* initialMipmapRegenTask = mipmapProxy->getLastRenderTask();
429 REPORTER_ASSERT(reporter, initialMipmapRegenTask);
430 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400431 initialMipmapRegenTask != mipmapRTC->testingOnly_PeekLastOpsTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600432 REPORTER_ASSERT(reporter, !mipmapProxy->mipMapsAreDirty());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600433
434 // Draw the now-clean mipmap texture into a second target.
Greg Danielba0ff782020-01-07 15:42:57 -0500435 auto rtc2 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
Greg Daniel40903af2020-01-30 14:55:05 -0500436 alphaType, mipmapView, Filter::kMipMap);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600437
438 // Make sure the mipmap texture still has the same regen task.
439 REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask() == initialMipmapRegenTask);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600440 SkASSERT(!mipmapProxy->mipMapsAreDirty());
441
442 // Reset everything so we can go again, this time with the first draw not mipmapped.
443 context->flush();
444
Chris Daltone2a903e2019-09-18 13:41:50 -0600445 // Mip regen tasks don't get added as dependencies until makeClosed().
446 REPORTER_ASSERT(reporter,
447 rtc1->testingOnly_PeekLastOpsTask()->dependsOn(initialMipmapRegenTask));
448 REPORTER_ASSERT(reporter,
449 rtc2->testingOnly_PeekLastOpsTask()->dependsOn(initialMipmapRegenTask));
450
Chris Dalton30eea6c2019-08-21 10:22:50 -0600451 // Render something to dirty the mips.
452 mipmapRTC->clear(nullptr, {.1f,.2f,.3f,.4f}, CanClearFullscreen::kYes);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600453 REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask());
Greg Danielf41b2bd2019-08-22 16:19:24 -0400454 // mipmapProxy's last render task should now just be the opsTask containing the clear.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600455 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400456 mipmapRTC->testingOnly_PeekLastOpsTask() == mipmapProxy->getLastRenderTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600457
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600458 // Mipmaps don't get marked dirty until makeClosed().
459 REPORTER_ASSERT(reporter, !mipmapProxy->mipMapsAreDirty());
460
Chris Dalton30eea6c2019-08-21 10:22:50 -0600461 // Draw the dirty mipmap texture into a render target, but don't do mipmap filtering.
Greg Danielba0ff782020-01-07 15:42:57 -0500462 rtc1 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
Greg Daniel40903af2020-01-30 14:55:05 -0500463 alphaType, mipmapView, Filter::kBilerp);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600464
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600465 // Mipmaps should have gotten marked dirty during makeClosed() when adding the dependency.
466 // Since the last draw did not use mips, they will not have been regenerated and should
467 // therefore still be dirty.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600468 REPORTER_ASSERT(reporter, mipmapProxy->mipMapsAreDirty());
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600469
470 // Since mips weren't regenerated, the last render task shouldn't have changed.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600471 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400472 mipmapRTC->testingOnly_PeekLastOpsTask() == mipmapProxy->getLastRenderTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600473
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600474 // Draw the stil-dirty mipmap texture into a second target with mipmap filtering.
Greg Danielba0ff782020-01-07 15:42:57 -0500475 rtc2 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
Greg Daniel40903af2020-01-30 14:55:05 -0500476 alphaType, std::move(mipmapView),
477 Filter::kMipMap);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600478
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600479 // Make sure the mipmap texture now has a new last render task that regenerates the mips,
480 // and that the mipmaps are now clean.
Chris Daltone2a903e2019-09-18 13:41:50 -0600481 auto mipRegenTask2 = mipmapProxy->getLastRenderTask();
482 REPORTER_ASSERT(reporter, mipRegenTask2);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600483 REPORTER_ASSERT(reporter,
Chris Daltone2a903e2019-09-18 13:41:50 -0600484 mipmapRTC->testingOnly_PeekLastOpsTask() != mipRegenTask2);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600485 SkASSERT(!mipmapProxy->mipMapsAreDirty());
Chris Daltone2a903e2019-09-18 13:41:50 -0600486
487 // Mip regen tasks don't get added as dependencies until makeClosed().
488 context->flush();
489 REPORTER_ASSERT(reporter, rtc2->testingOnly_PeekLastOpsTask()->dependsOn(mipRegenTask2));
Chris Dalton3d770272019-08-14 09:24:37 -0600490 }
Chris Dalton3d770272019-08-14 09:24:37 -0600491}