blob: fd474211f4e249cb6e0aeadb743a290254c7440c [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"
19#include "src/gpu/GrRenderTargetContext.h"
20#include "src/gpu/GrSemaphore.h"
21#include "src/gpu/GrSurfaceProxyPriv.h"
22#include "src/gpu/GrTexturePriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040023#include "src/gpu/GrTextureProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "src/gpu/SkGpuDevice.h"
25#include "src/image/SkImage_Base.h"
26#include "src/image/SkSurface_Gpu.h"
27#include "tests/Test.h"
Greg Daniel177e6952017-10-12 12:27:11 -040028
Greg Daniel45d63032017-10-30 13:41:26 -040029static constexpr int kSize = 8;
30
Greg Daniel177e6952017-10-12 12:27:11 -040031// Test that the correct mip map states are on the GrTextures when wrapping GrBackendTextures in
32// SkImages and SkSurfaces
33DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest, reporter, ctxInfo) {
34 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -050035 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel261b8aa2017-10-23 09:37:36 -040036 return;
37 }
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050038
Greg Daniel177e6952017-10-12 12:27:11 -040039 for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040040 for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
Robert Phillips9b16f812019-05-17 10:01:21 -040041 // createBackendTexture currently doesn't support uploading data to mip maps
Greg Daniel177e6952017-10-12 12:27:11 -040042 // so we don't send any. However, we pretend there is data for the checks below which is
43 // fine since we are never actually using these textures for any work on the gpu.
Robert Phillips4bdd36f2019-06-04 11:03:06 -040044 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -040045 kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -040046 SkColors::kTransparent, mipMapped, renderable, GrProtected::kNo);
Greg Daniel177e6952017-10-12 12:27:11 -040047
Robert Phillipse0070c02017-11-13 12:47:24 -050048 sk_sp<GrTextureProxy> proxy;
Greg Daniel177e6952017-10-12 12:27:11 -040049 sk_sp<SkImage> image;
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040050 if (GrRenderable::kYes == renderable) {
Greg Daniel177e6952017-10-12 12:27:11 -040051 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(
52 context,
53 backendTex,
54 kTopLeft_GrSurfaceOrigin,
55 0,
Greg Danielfaa095e2017-12-19 13:15:02 -050056 kRGBA_8888_SkColorType,
Greg Daniel177e6952017-10-12 12:27:11 -040057 nullptr,
58 nullptr);
59
60 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
Robert Phillipse0070c02017-11-13 12:47:24 -050061 proxy = device->accessRenderTargetContext()->asTextureProxyRef();
Greg Daniel177e6952017-10-12 12:27:11 -040062 } else {
63 image = SkImage::MakeFromTexture(context, backendTex,
64 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -050065 kRGBA_8888_SkColorType,
66 kPremul_SkAlphaType, nullptr,
67 nullptr, nullptr);
Robert Phillips6603a172019-03-05 12:35:44 -050068 proxy = as_IB(image)->asTextureProxyRef(context);
Greg Daniel177e6952017-10-12 12:27:11 -040069 }
70 REPORTER_ASSERT(reporter, proxy);
71 if (!proxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -040072 context->deleteBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040073 return;
74 }
75
Brian Salomonfd98c2c2018-07-31 17:25:29 -040076 REPORTER_ASSERT(reporter, proxy->isInstantiated());
Greg Daniel177e6952017-10-12 12:27:11 -040077
Brian Salomonfd98c2c2018-07-31 17:25:29 -040078 GrTexture* texture = proxy->peekTexture();
Greg Daniel177e6952017-10-12 12:27:11 -040079 REPORTER_ASSERT(reporter, texture);
80 if (!texture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -040081 context->deleteBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040082 return;
83 }
84
85 if (GrMipMapped::kYes == mipMapped) {
Greg Daniele252f082017-10-23 16:05:23 -040086 REPORTER_ASSERT(reporter, GrMipMapped::kYes == texture->texturePriv().mipMapped());
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040087 if (GrRenderable::kYes == renderable) {
Greg Daniel177e6952017-10-12 12:27:11 -040088 REPORTER_ASSERT(reporter, texture->texturePriv().mipMapsAreDirty());
89 } else {
90 REPORTER_ASSERT(reporter, !texture->texturePriv().mipMapsAreDirty());
91 }
92 } else {
Greg Daniele252f082017-10-23 16:05:23 -040093 REPORTER_ASSERT(reporter, GrMipMapped::kNo == texture->texturePriv().mipMapped());
Greg Daniel177e6952017-10-12 12:27:11 -040094 }
Robert Phillips5c7a25b2019-05-20 08:38:07 -040095 context->deleteBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040096 }
97 }
98}
99
Greg Daniel261b8aa2017-10-23 09:37:36 -0400100// Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator
101// based on if we will use mips in the draw and the mip status of the GrBackendTexture.
102DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400103 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500104 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400105 return;
106 }
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500107
Greg Daniel261b8aa2017-10-23 09:37:36 -0400108 for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
109 for (auto willUseMips : {false, true}) {
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400110 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400111 kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400112 SkColors::kTransparent, mipMapped, GrRenderable::kNo, GrProtected::kNo);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400113
Greg Daniel261b8aa2017-10-23 09:37:36 -0400114 sk_sp<SkImage> image = SkImage::MakeFromTexture(context, backendTex,
115 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -0500116 kRGBA_8888_SkColorType,
117 kPremul_SkAlphaType, nullptr,
118 nullptr, nullptr);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400119
120 GrTextureProxy* proxy = as_IB(image)->peekProxy();
121 REPORTER_ASSERT(reporter, proxy);
122 if (!proxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400123 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400124 return;
125 }
126
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400127 REPORTER_ASSERT(reporter, proxy->isInstantiated());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400128
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400129 sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400130 REPORTER_ASSERT(reporter, texture);
131 if (!texture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400132 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400133 return;
134 }
135
136 std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make(
Brian Osman052ef692018-03-27 09:56:31 -0400137 texture, kTopLeft_GrSurfaceOrigin, nullptr, kRGBA_8888_SkColorType,
138 kPremul_SkAlphaType, nullptr);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400139 REPORTER_ASSERT(reporter, imageGen);
140 if (!imageGen) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400141 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400142 return;
143 }
144
145 SkIPoint origin = SkIPoint::Make(0,0);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400146 SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
147 kPremul_SkAlphaType);
148 sk_sp<GrTextureProxy> genProxy = imageGen->generateTexture(context, imageInfo,
Brian Osmanc87cfb62018-07-11 09:08:46 -0400149 origin, willUseMips);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400150
151 REPORTER_ASSERT(reporter, genProxy);
152 if (!genProxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400153 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400154 return;
155 }
156
Brian Salomonbeb7f522019-08-30 16:19:42 -0400157 if (genProxy->isLazy()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500158 genProxy->priv().doLazyInstantiation(context->priv().resourceProvider());
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400159 } else if (!genProxy->isInstantiated()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500160 genProxy->instantiate(context->priv().resourceProvider());
Greg Daniele728f672018-01-17 10:52:04 -0500161 }
162
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400163 REPORTER_ASSERT(reporter, genProxy->isInstantiated());
164 if (!genProxy->isInstantiated()) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400165 context->deleteBackendTexture(backendTex);
Greg Danielbddcc952018-01-24 13:22:24 -0500166 return;
167 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400168
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400169 GrTexture* genTexture = genProxy->peekTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400170 REPORTER_ASSERT(reporter, genTexture);
171 if (!genTexture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400172 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400173 return;
174 }
175
Robert Phillipsb67821d2017-12-13 15:00:45 -0500176 GrBackendTexture genBackendTex = genTexture->getBackendTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400177
Greg Danielbdf12ad2018-10-12 09:31:11 -0400178 if (GrBackendApi::kOpenGL == genBackendTex.backend()) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400179 GrGLTextureInfo genTexInfo;
180 GrGLTextureInfo origTexInfo;
181 if (genBackendTex.getGLTextureInfo(&genTexInfo) &&
182 backendTex.getGLTextureInfo(&origTexInfo)) {
183 if (willUseMips && GrMipMapped::kNo == mipMapped) {
184 // We did a copy so the texture IDs should be different
185 REPORTER_ASSERT(reporter, origTexInfo.fID != genTexInfo.fID);
186 } else {
187 REPORTER_ASSERT(reporter, origTexInfo.fID == genTexInfo.fID);
188 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400189 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400190 ERRORF(reporter, "Failed to get GrGLTextureInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400191 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400192#ifdef SK_VULKAN
Greg Danielbdf12ad2018-10-12 09:31:11 -0400193 } else if (GrBackendApi::kVulkan == genBackendTex.backend()) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400194 GrVkImageInfo genImageInfo;
195 GrVkImageInfo origImageInfo;
196 if (genBackendTex.getVkImageInfo(&genImageInfo) &&
197 backendTex.getVkImageInfo(&origImageInfo)) {
198 if (willUseMips && GrMipMapped::kNo == mipMapped) {
199 // We did a copy so the texture IDs should be different
200 REPORTER_ASSERT(reporter, origImageInfo.fImage != genImageInfo.fImage);
201 } else {
202 REPORTER_ASSERT(reporter, origImageInfo.fImage == genImageInfo.fImage);
203 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400204 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400205 ERRORF(reporter, "Failed to get GrVkImageInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400206 }
207#endif
Jim Van Verth9896a0d2019-04-10 15:11:12 -0400208#ifdef SK_METAL
209 } else if (GrBackendApi::kMetal == genBackendTex.backend()) {
210 GrMtlTextureInfo genImageInfo;
211 GrMtlTextureInfo origImageInfo;
212 if (genBackendTex.getMtlTextureInfo(&genImageInfo) &&
213 backendTex.getMtlTextureInfo(&origImageInfo)) {
214 if (willUseMips && GrMipMapped::kNo == mipMapped) {
215 // We did a copy so the texture IDs should be different
216 REPORTER_ASSERT(reporter, origImageInfo.fTexture != genImageInfo.fTexture);
217 } else {
218 REPORTER_ASSERT(reporter, origImageInfo.fTexture == genImageInfo.fTexture);
219 }
220 } else {
221 ERRORF(reporter, "Failed to get GrMtlTextureInfo");
222 }
223#endif
Greg Daniel261b8aa2017-10-23 09:37:36 -0400224 } else {
225 REPORTER_ASSERT(reporter, false);
226 }
227
228 // Must make sure the uses of the backend texture have finished (we possibly have a
Greg Daniel26b50a42018-03-08 09:49:58 -0500229 // queued up copy) before we delete the backend texture.
230 context->flush();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400231
Robert Phillips9b16f812019-05-17 10:01:21 -0400232 context->priv().getGpu()->testingOnly_flushGpuAndSync();
233
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400234 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400235 }
236 }
237}
238
Greg Daniel45d63032017-10-30 13:41:26 -0400239// Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the
240// resource we took the snapshot of.
241DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) {
242 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500243 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel45d63032017-10-30 13:41:26 -0400244 return;
245 }
246
Robert Phillips9da87e02019-02-04 13:26:26 -0500247 auto resourceProvider = context->priv().resourceProvider();
Robert Phillips6be756b2018-01-16 15:07:54 -0500248
Greg Daniel45d63032017-10-30 13:41:26 -0400249 for (auto willUseMips : {false, true}) {
250 for (auto isWrapped : {false, true}) {
251 GrMipMapped mipMapped = willUseMips ? GrMipMapped::kYes : GrMipMapped::kNo;
252 sk_sp<SkSurface> surface;
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400253 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400254 kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400255 SkColors::kTransparent, mipMapped, GrRenderable::kYes, GrProtected::kNo);
Greg Daniel45d63032017-10-30 13:41:26 -0400256 if (isWrapped) {
Greg Daniel45d63032017-10-30 13:41:26 -0400257 surface = SkSurface::MakeFromBackendTexture(context,
258 backendTex,
259 kTopLeft_GrSurfaceOrigin,
260 0,
Greg Danielfaa095e2017-12-19 13:15:02 -0500261 kRGBA_8888_SkColorType,
Greg Daniel45d63032017-10-30 13:41:26 -0400262 nullptr,
263 nullptr);
264 } else {
265 SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
266 kPremul_SkAlphaType);
267 surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
268 kTopLeft_GrSurfaceOrigin, nullptr,
269 willUseMips);
270 }
271 REPORTER_ASSERT(reporter, surface);
272 if (!surface) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400273 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400274 }
275 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
276 GrTextureProxy* texProxy = device->accessRenderTargetContext()->asTextureProxy();
277 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
278
Robert Phillips6be756b2018-01-16 15:07:54 -0500279 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400280 GrTexture* texture = texProxy->peekTexture();
Greg Daniel45d63032017-10-30 13:41:26 -0400281 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
282
283 sk_sp<SkImage> image = surface->makeImageSnapshot();
284 REPORTER_ASSERT(reporter, image);
285 if (!image) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400286 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400287 }
288 texProxy = as_IB(image)->peekProxy();
289 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
290
Robert Phillips6be756b2018-01-16 15:07:54 -0500291 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400292 texture = texProxy->peekTexture();
Greg Daniel45d63032017-10-30 13:41:26 -0400293 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
294
295 // Must flush the context to make sure all the cmds (copies, etc.) from above are sent
296 // to the gpu before we delete the backendHandle.
297 context->flush();
Robert Phillips9b16f812019-05-17 10:01:21 -0400298 context->priv().getGpu()->testingOnly_flushGpuAndSync();
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400299 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400300 }
301 }
302}
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400303
304// Test that we don't create a mip mapped texture if the size is 1x1 even if the filter mode is set
305// to use mips. This test passes by not crashing or hitting asserts in code.
306DEF_GPUTEST_FOR_RENDERING_CONTEXTS(Gr1x1TextureMipMappedTest, reporter, ctxInfo) {
307 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500308 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400309 return;
310 }
311
312 // Make surface to draw into
313 SkImageInfo info = SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType);
314 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info);
315
316 // Make 1x1 raster bitmap
317 SkBitmap bmp;
318 bmp.allocN32Pixels(1, 1);
319 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(bmp.getPixels());
320 *pixel = 0;
321
322 sk_sp<SkImage> bmpImage = SkImage::MakeFromBitmap(bmp);
323
324 // Make sure we scale so we don't optimize out the use of mips.
325 surface->getCanvas()->scale(0.5f, 0.5f);
326
327 SkPaint paint;
328 // This should upload the image to a non mipped GrTextureProxy.
329 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
330 surface->flush();
331
332 // Now set the filter quality to high so we use mip maps. We should find the non mipped texture
333 // in the cache for the SkImage. Since the texture is 1x1 we should just use that texture
334 // instead of trying to do a copy to a mipped texture.
335 paint.setFilterQuality(kHigh_SkFilterQuality);
336 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
337 surface->flush();
338}
339
Chris Dalton3d770272019-08-14 09:24:37 -0600340// Create a new render target and draw 'mipmapProxy' into it using the provided 'filter'.
Brian Salomonbf6b9792019-08-21 09:38:10 -0400341static std::unique_ptr<GrRenderTargetContext> draw_mipmap_into_new_render_target(
Chris Dalton3d770272019-08-14 09:24:37 -0600342 GrDrawingManager* drawingManager, GrProxyProvider* proxyProvider, GrColorType colorType,
343 sk_sp<GrTextureProxy> mipmapProxy, GrSamplerState::Filter filter) {
344 GrSurfaceDesc desc;
345 desc.fWidth = 1;
346 desc.fHeight = 1;
347 desc.fConfig = mipmapProxy->config();
348 sk_sp<GrSurfaceProxy> renderTarget = proxyProvider->createProxy(
349 mipmapProxy->backendFormat(), desc, GrRenderable::kYes, 1, kTopLeft_GrSurfaceOrigin,
Brian Salomonbeb7f522019-08-30 16:19:42 -0400350 GrMipMapped::kNo, SkBackingFit::kApprox, SkBudgeted::kYes, GrProtected::kNo);
Brian Salomonbf6b9792019-08-21 09:38:10 -0400351 auto rtc = drawingManager->makeRenderTargetContext(
Chris Dalton3d770272019-08-14 09:24:37 -0600352 std::move(renderTarget), colorType, nullptr, nullptr, true);
353 rtc->drawTexture(GrNoClip(), mipmapProxy, filter, SkBlendMode::kSrcOver, {1,1,1,1},
354 SkRect::MakeWH(4, 4), SkRect::MakeWH(1,1), GrAA::kYes, GrQuadAAFlags::kAll,
355 SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), nullptr);
356 return rtc;
357}
358
Greg Danielf41b2bd2019-08-22 16:19:24 -0400359// Test that two opsTasks using the same mipmaps both depend on the same GrTextureResolveRenderTask.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600360DEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) {
361 using CanClearFullscreen = GrRenderTargetContext::CanClearFullscreen;
362 using Enable = GrContextOptions::Enable;
363 using Filter = GrSamplerState::Filter;
364
365 for (auto enableSortingAndReduction : {Enable::kYes, Enable::kNo}) {
366 GrMockOptions mockOptions;
367 mockOptions.fMipMapSupport = true;
368 GrContextOptions ctxOptions;
Greg Daniel93138742019-08-22 17:15:39 -0400369 ctxOptions.fReduceOpsTaskSplitting = enableSortingAndReduction;
Chris Dalton30eea6c2019-08-21 10:22:50 -0600370 sk_sp<GrContext> context = GrContext::MakeMock(&mockOptions, ctxOptions);
371 if (!context) {
Greg Danielf41b2bd2019-08-22 16:19:24 -0400372 ERRORF(reporter, "could not create mock context with fReduceOpsTaskSplitting %s.",
Chris Dalton30eea6c2019-08-21 10:22:50 -0600373 (Enable::kYes == enableSortingAndReduction) ? "enabled" : "disabled");
374 continue;
375 }
376
377 SkASSERT(context->priv().caps()->mipMapSupport());
378
379 GrBackendFormat format = context->defaultBackendFormat(
380 kRGBA_8888_SkColorType, GrRenderable::kYes);
381 GrPixelConfig config = kRGBA_8888_GrPixelConfig;
382 GrColorType colorType = GrColorType::kRGBA_8888;
383
384 GrDrawingManager* drawingManager = context->priv().drawingManager();
385 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
386
387 // Create a mipmapped render target.
388 GrSurfaceDesc desc;
389 desc.fWidth = 4;
390 desc.fHeight = 4;
391 desc.fConfig = config;
Brian Salomonbeb7f522019-08-30 16:19:42 -0400392 sk_sp<GrTextureProxy> mipmapProxy = proxyProvider->createProxy(
393 format, desc, GrRenderable::kYes, 1, kTopLeft_GrSurfaceOrigin, GrMipMapped::kYes,
394 SkBackingFit::kExact, SkBudgeted::kYes, GrProtected::kNo);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600395
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600396 // Mark the mipmaps clean to ensure things still work properly when they won't be marked
397 // dirty again until GrRenderTask::makeClosed().
398 mipmapProxy->markMipMapsClean();
399
Chris Dalton30eea6c2019-08-21 10:22:50 -0600400 // Render something to dirty the mips.
401 auto mipmapRTC = drawingManager->makeRenderTargetContext(
402 mipmapProxy, colorType, nullptr, nullptr, true);
403 mipmapRTC->clear(nullptr, {.1f,.2f,.3f,.4f}, CanClearFullscreen::kYes);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600404 REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask());
Greg Danielf41b2bd2019-08-22 16:19:24 -0400405 // mipmapProxy's last render task should now just be the opsTask containing the clear.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600406 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400407 mipmapRTC->testingOnly_PeekLastOpsTask() == mipmapProxy->getLastRenderTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600408
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600409 // Mipmaps don't get marked dirty until makeClosed().
410 REPORTER_ASSERT(reporter, !mipmapProxy->mipMapsAreDirty());
411
Chris Dalton30eea6c2019-08-21 10:22:50 -0600412 // Draw the dirty mipmap texture into a render target.
413 auto rtc1 = draw_mipmap_into_new_render_target(
414 drawingManager, proxyProvider, colorType, mipmapProxy, Filter::kMipMap);
415
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600416 // Mipmaps should have gotten marked dirty during makeClosed, then marked clean again as
417 // soon as a GrTextureResolveRenderTask was inserted. The way we know they were resolved is
Greg Danielf41b2bd2019-08-22 16:19:24 -0400418 // if mipmapProxy->getLastRenderTask() has switched from the opsTask that drew to it, to the
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600419 // task that resolved its mips.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600420 GrRenderTask* initialMipmapRegenTask = mipmapProxy->getLastRenderTask();
421 REPORTER_ASSERT(reporter, initialMipmapRegenTask);
422 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400423 initialMipmapRegenTask != mipmapRTC->testingOnly_PeekLastOpsTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600424 REPORTER_ASSERT(reporter, !mipmapProxy->mipMapsAreDirty());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600425
426 // Draw the now-clean mipmap texture into a second target.
427 auto rtc2 = draw_mipmap_into_new_render_target(
428 drawingManager, proxyProvider, colorType, mipmapProxy, Filter::kMipMap);
429
430 // Make sure the mipmap texture still has the same regen task.
431 REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask() == initialMipmapRegenTask);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600432 SkASSERT(!mipmapProxy->mipMapsAreDirty());
433
434 // Reset everything so we can go again, this time with the first draw not mipmapped.
435 context->flush();
436
Chris Daltone2a903e2019-09-18 13:41:50 -0600437 // Mip regen tasks don't get added as dependencies until makeClosed().
438 REPORTER_ASSERT(reporter,
439 rtc1->testingOnly_PeekLastOpsTask()->dependsOn(initialMipmapRegenTask));
440 REPORTER_ASSERT(reporter,
441 rtc2->testingOnly_PeekLastOpsTask()->dependsOn(initialMipmapRegenTask));
442
Chris Dalton30eea6c2019-08-21 10:22:50 -0600443 // Render something to dirty the mips.
444 mipmapRTC->clear(nullptr, {.1f,.2f,.3f,.4f}, CanClearFullscreen::kYes);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600445 REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask());
Greg Danielf41b2bd2019-08-22 16:19:24 -0400446 // mipmapProxy's last render task should now just be the opsTask containing the clear.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600447 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400448 mipmapRTC->testingOnly_PeekLastOpsTask() == mipmapProxy->getLastRenderTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600449
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600450 // Mipmaps don't get marked dirty until makeClosed().
451 REPORTER_ASSERT(reporter, !mipmapProxy->mipMapsAreDirty());
452
Chris Dalton30eea6c2019-08-21 10:22:50 -0600453 // Draw the dirty mipmap texture into a render target, but don't do mipmap filtering.
454 rtc1 = draw_mipmap_into_new_render_target(
455 drawingManager, proxyProvider, colorType, mipmapProxy, Filter::kBilerp);
456
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600457 // Mipmaps should have gotten marked dirty during makeClosed() when adding the dependency.
458 // Since the last draw did not use mips, they will not have been regenerated and should
459 // therefore still be dirty.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600460 REPORTER_ASSERT(reporter, mipmapProxy->mipMapsAreDirty());
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600461
462 // Since mips weren't regenerated, the last render task shouldn't have changed.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600463 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400464 mipmapRTC->testingOnly_PeekLastOpsTask() == mipmapProxy->getLastRenderTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600465
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600466 // Draw the stil-dirty mipmap texture into a second target with mipmap filtering.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600467 rtc2 = draw_mipmap_into_new_render_target(
468 drawingManager, proxyProvider, colorType, mipmapProxy, Filter::kMipMap);
469
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600470 // Make sure the mipmap texture now has a new last render task that regenerates the mips,
471 // and that the mipmaps are now clean.
Chris Daltone2a903e2019-09-18 13:41:50 -0600472 auto mipRegenTask2 = mipmapProxy->getLastRenderTask();
473 REPORTER_ASSERT(reporter, mipRegenTask2);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600474 REPORTER_ASSERT(reporter,
Chris Daltone2a903e2019-09-18 13:41:50 -0600475 mipmapRTC->testingOnly_PeekLastOpsTask() != mipRegenTask2);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600476 SkASSERT(!mipmapProxy->mipMapsAreDirty());
Chris Daltone2a903e2019-09-18 13:41:50 -0600477
478 // Mip regen tasks don't get added as dependencies until makeClosed().
479 context->flush();
480 REPORTER_ASSERT(reporter, rtc2->testingOnly_PeekLastOpsTask()->dependsOn(mipRegenTask2));
Chris Dalton3d770272019-08-14 09:24:37 -0600481 }
Chris Dalton3d770272019-08-14 09:24:37 -0600482}