blob: 8d15582e8dbf0f63bf8d23fab4ad71604ee2aba8 [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);
Greg Danielfebdedf2020-02-05 17:06:27 -050069 const GrSurfaceProxyView* view = as_IB(image)->view(context);
70 REPORTER_ASSERT(reporter, view);
71 if (!view) {
72 context->deleteBackendTexture(backendTex);
73 return;
74 }
75 proxy = view->asTextureProxyRef();
Greg Daniel177e6952017-10-12 12:27:11 -040076 }
77 REPORTER_ASSERT(reporter, proxy);
78 if (!proxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -040079 context->deleteBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040080 return;
81 }
82
Brian Salomonfd98c2c2018-07-31 17:25:29 -040083 REPORTER_ASSERT(reporter, proxy->isInstantiated());
Greg Daniel177e6952017-10-12 12:27:11 -040084
Brian Salomonfd98c2c2018-07-31 17:25:29 -040085 GrTexture* texture = proxy->peekTexture();
Greg Daniel177e6952017-10-12 12:27:11 -040086 REPORTER_ASSERT(reporter, texture);
87 if (!texture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -040088 context->deleteBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040089 return;
90 }
91
92 if (GrMipMapped::kYes == mipMapped) {
Greg Daniele252f082017-10-23 16:05:23 -040093 REPORTER_ASSERT(reporter, GrMipMapped::kYes == texture->texturePriv().mipMapped());
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040094 if (GrRenderable::kYes == renderable) {
Greg Daniel177e6952017-10-12 12:27:11 -040095 REPORTER_ASSERT(reporter, texture->texturePriv().mipMapsAreDirty());
96 } else {
97 REPORTER_ASSERT(reporter, !texture->texturePriv().mipMapsAreDirty());
98 }
99 } else {
Greg Daniele252f082017-10-23 16:05:23 -0400100 REPORTER_ASSERT(reporter, GrMipMapped::kNo == texture->texturePriv().mipMapped());
Greg Daniel177e6952017-10-12 12:27:11 -0400101 }
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400102 context->deleteBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -0400103 }
104 }
105}
106
Greg Daniel261b8aa2017-10-23 09:37:36 -0400107// Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator
108// based on if we will use mips in the draw and the mip status of the GrBackendTexture.
109DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400110 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500111 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400112 return;
113 }
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500114
Greg Daniel261b8aa2017-10-23 09:37:36 -0400115 for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
116 for (auto willUseMips : {false, true}) {
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400117 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400118 kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400119 SkColors::kTransparent, mipMapped, GrRenderable::kNo, GrProtected::kNo);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400120
Greg Daniel261b8aa2017-10-23 09:37:36 -0400121 sk_sp<SkImage> image = SkImage::MakeFromTexture(context, backendTex,
122 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -0500123 kRGBA_8888_SkColorType,
124 kPremul_SkAlphaType, nullptr,
125 nullptr, nullptr);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400126
127 GrTextureProxy* proxy = as_IB(image)->peekProxy();
128 REPORTER_ASSERT(reporter, proxy);
129 if (!proxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400130 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400131 return;
132 }
133
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400134 REPORTER_ASSERT(reporter, proxy->isInstantiated());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400135
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400136 sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400137 REPORTER_ASSERT(reporter, texture);
138 if (!texture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400139 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400140 return;
141 }
142
143 std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make(
Brian Osman052ef692018-03-27 09:56:31 -0400144 texture, kTopLeft_GrSurfaceOrigin, nullptr, kRGBA_8888_SkColorType,
145 kPremul_SkAlphaType, nullptr);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400146 REPORTER_ASSERT(reporter, imageGen);
147 if (!imageGen) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400148 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400149 return;
150 }
151
152 SkIPoint origin = SkIPoint::Make(0,0);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400153 SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
154 kPremul_SkAlphaType);
Greg Danielcc104db2020-02-03 14:17:08 -0500155 GrSurfaceProxyView genView = imageGen->generateTexture(context, imageInfo, origin,
156 willUseMips);
157 GrSurfaceProxy* genProxy = genView.proxy();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400158
159 REPORTER_ASSERT(reporter, genProxy);
160 if (!genProxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400161 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400162 return;
163 }
164
Brian Salomonbeb7f522019-08-30 16:19:42 -0400165 if (genProxy->isLazy()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500166 genProxy->priv().doLazyInstantiation(context->priv().resourceProvider());
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400167 } else if (!genProxy->isInstantiated()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500168 genProxy->instantiate(context->priv().resourceProvider());
Greg Daniele728f672018-01-17 10:52:04 -0500169 }
170
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400171 REPORTER_ASSERT(reporter, genProxy->isInstantiated());
172 if (!genProxy->isInstantiated()) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400173 context->deleteBackendTexture(backendTex);
Greg Danielbddcc952018-01-24 13:22:24 -0500174 return;
175 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400176
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400177 GrTexture* genTexture = genProxy->peekTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400178 REPORTER_ASSERT(reporter, genTexture);
179 if (!genTexture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400180 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400181 return;
182 }
183
Robert Phillipsb67821d2017-12-13 15:00:45 -0500184 GrBackendTexture genBackendTex = genTexture->getBackendTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400185
Greg Danielbdf12ad2018-10-12 09:31:11 -0400186 if (GrBackendApi::kOpenGL == genBackendTex.backend()) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400187 GrGLTextureInfo genTexInfo;
188 GrGLTextureInfo origTexInfo;
189 if (genBackendTex.getGLTextureInfo(&genTexInfo) &&
190 backendTex.getGLTextureInfo(&origTexInfo)) {
191 if (willUseMips && GrMipMapped::kNo == mipMapped) {
192 // We did a copy so the texture IDs should be different
193 REPORTER_ASSERT(reporter, origTexInfo.fID != genTexInfo.fID);
194 } else {
195 REPORTER_ASSERT(reporter, origTexInfo.fID == genTexInfo.fID);
196 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400197 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400198 ERRORF(reporter, "Failed to get GrGLTextureInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400199 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400200#ifdef SK_VULKAN
Greg Danielbdf12ad2018-10-12 09:31:11 -0400201 } else if (GrBackendApi::kVulkan == genBackendTex.backend()) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400202 GrVkImageInfo genImageInfo;
203 GrVkImageInfo origImageInfo;
204 if (genBackendTex.getVkImageInfo(&genImageInfo) &&
205 backendTex.getVkImageInfo(&origImageInfo)) {
206 if (willUseMips && GrMipMapped::kNo == mipMapped) {
207 // We did a copy so the texture IDs should be different
208 REPORTER_ASSERT(reporter, origImageInfo.fImage != genImageInfo.fImage);
209 } else {
210 REPORTER_ASSERT(reporter, origImageInfo.fImage == genImageInfo.fImage);
211 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400212 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400213 ERRORF(reporter, "Failed to get GrVkImageInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400214 }
215#endif
Jim Van Verth9896a0d2019-04-10 15:11:12 -0400216#ifdef SK_METAL
217 } else if (GrBackendApi::kMetal == genBackendTex.backend()) {
218 GrMtlTextureInfo genImageInfo;
219 GrMtlTextureInfo origImageInfo;
220 if (genBackendTex.getMtlTextureInfo(&genImageInfo) &&
221 backendTex.getMtlTextureInfo(&origImageInfo)) {
222 if (willUseMips && GrMipMapped::kNo == mipMapped) {
223 // We did a copy so the texture IDs should be different
224 REPORTER_ASSERT(reporter, origImageInfo.fTexture != genImageInfo.fTexture);
225 } else {
226 REPORTER_ASSERT(reporter, origImageInfo.fTexture == genImageInfo.fTexture);
227 }
228 } else {
229 ERRORF(reporter, "Failed to get GrMtlTextureInfo");
230 }
231#endif
Greg Daniel261b8aa2017-10-23 09:37:36 -0400232 } else {
233 REPORTER_ASSERT(reporter, false);
234 }
235
236 // Must make sure the uses of the backend texture have finished (we possibly have a
Greg Daniel26b50a42018-03-08 09:49:58 -0500237 // queued up copy) before we delete the backend texture.
238 context->flush();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400239
Robert Phillips9b16f812019-05-17 10:01:21 -0400240 context->priv().getGpu()->testingOnly_flushGpuAndSync();
241
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400242 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400243 }
244 }
245}
246
Greg Daniel45d63032017-10-30 13:41:26 -0400247// Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the
248// resource we took the snapshot of.
249DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) {
250 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500251 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel45d63032017-10-30 13:41:26 -0400252 return;
253 }
254
Robert Phillips9da87e02019-02-04 13:26:26 -0500255 auto resourceProvider = context->priv().resourceProvider();
Robert Phillips6be756b2018-01-16 15:07:54 -0500256
Greg Daniel45d63032017-10-30 13:41:26 -0400257 for (auto willUseMips : {false, true}) {
258 for (auto isWrapped : {false, true}) {
259 GrMipMapped mipMapped = willUseMips ? GrMipMapped::kYes : GrMipMapped::kNo;
260 sk_sp<SkSurface> surface;
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400261 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400262 kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400263 SkColors::kTransparent, mipMapped, GrRenderable::kYes, GrProtected::kNo);
Greg Daniel45d63032017-10-30 13:41:26 -0400264 if (isWrapped) {
Greg Daniel45d63032017-10-30 13:41:26 -0400265 surface = SkSurface::MakeFromBackendTexture(context,
266 backendTex,
267 kTopLeft_GrSurfaceOrigin,
268 0,
Greg Danielfaa095e2017-12-19 13:15:02 -0500269 kRGBA_8888_SkColorType,
Greg Daniel45d63032017-10-30 13:41:26 -0400270 nullptr,
271 nullptr);
272 } else {
273 SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
274 kPremul_SkAlphaType);
275 surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
276 kTopLeft_GrSurfaceOrigin, nullptr,
277 willUseMips);
278 }
279 REPORTER_ASSERT(reporter, surface);
280 if (!surface) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400281 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400282 }
283 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
284 GrTextureProxy* texProxy = device->accessRenderTargetContext()->asTextureProxy();
285 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
286
Robert Phillips6be756b2018-01-16 15:07:54 -0500287 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400288 GrTexture* texture = texProxy->peekTexture();
Greg Daniel45d63032017-10-30 13:41:26 -0400289 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
290
291 sk_sp<SkImage> image = surface->makeImageSnapshot();
292 REPORTER_ASSERT(reporter, image);
293 if (!image) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400294 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400295 }
296 texProxy = as_IB(image)->peekProxy();
297 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
298
Robert Phillips6be756b2018-01-16 15:07:54 -0500299 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400300 texture = texProxy->peekTexture();
Greg Daniel45d63032017-10-30 13:41:26 -0400301 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
302
303 // Must flush the context to make sure all the cmds (copies, etc.) from above are sent
304 // to the gpu before we delete the backendHandle.
305 context->flush();
Robert Phillips9b16f812019-05-17 10:01:21 -0400306 context->priv().getGpu()->testingOnly_flushGpuAndSync();
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400307 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400308 }
309 }
310}
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400311
312// Test that we don't create a mip mapped texture if the size is 1x1 even if the filter mode is set
313// to use mips. This test passes by not crashing or hitting asserts in code.
314DEF_GPUTEST_FOR_RENDERING_CONTEXTS(Gr1x1TextureMipMappedTest, reporter, ctxInfo) {
315 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500316 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400317 return;
318 }
319
320 // Make surface to draw into
321 SkImageInfo info = SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType);
322 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info);
323
324 // Make 1x1 raster bitmap
325 SkBitmap bmp;
326 bmp.allocN32Pixels(1, 1);
327 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(bmp.getPixels());
328 *pixel = 0;
329
330 sk_sp<SkImage> bmpImage = SkImage::MakeFromBitmap(bmp);
331
332 // Make sure we scale so we don't optimize out the use of mips.
333 surface->getCanvas()->scale(0.5f, 0.5f);
334
335 SkPaint paint;
336 // This should upload the image to a non mipped GrTextureProxy.
337 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
338 surface->flush();
339
340 // Now set the filter quality to high so we use mip maps. We should find the non mipped texture
341 // in the cache for the SkImage. Since the texture is 1x1 we should just use that texture
342 // instead of trying to do a copy to a mipped texture.
343 paint.setFilterQuality(kHigh_SkFilterQuality);
344 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
345 surface->flush();
346}
347
Greg Daniel40903af2020-01-30 14:55:05 -0500348// Create a new render target and draw 'mipmapView' into it using the provided 'filter'.
Brian Salomonbf6b9792019-08-21 09:38:10 -0400349static std::unique_ptr<GrRenderTargetContext> draw_mipmap_into_new_render_target(
Greg Danielba0ff782020-01-07 15:42:57 -0500350 GrRecordingContext* context, GrProxyProvider* proxyProvider, GrColorType colorType,
Greg Daniel40903af2020-01-30 14:55:05 -0500351 SkAlphaType alphaType, GrSurfaceProxyView mipmapView, GrSamplerState::Filter filter) {
Chris Dalton3d770272019-08-14 09:24:37 -0600352 GrSurfaceDesc desc;
353 desc.fWidth = 1;
354 desc.fHeight = 1;
Chris Dalton3d770272019-08-14 09:24:37 -0600355 sk_sp<GrSurfaceProxy> renderTarget = proxyProvider->createProxy(
Greg Daniel40903af2020-01-30 14:55:05 -0500356 mipmapView.proxy()->backendFormat(), desc, mipmapView.swizzle(), GrRenderable::kYes, 1,
357 mipmapView.origin(), GrMipMapped::kNo, SkBackingFit::kApprox, SkBudgeted::kYes,
Greg Daniel47c20e82020-01-21 14:29:57 -0500358 GrProtected::kNo);
Greg Danielba0ff782020-01-07 15:42:57 -0500359
360 auto rtc = GrRenderTargetContext::Make(
361 context, colorType, nullptr, std::move(renderTarget), kTopLeft_GrSurfaceOrigin,
362 nullptr);
363
Greg Daniel40903af2020-01-30 14:55:05 -0500364 rtc->drawTexture(GrNoClip(), std::move(mipmapView), alphaType, filter, SkBlendMode::kSrcOver,
Greg Danielc594e622019-10-15 14:01:49 -0400365 {1,1,1,1}, SkRect::MakeWH(4, 4), SkRect::MakeWH(1,1), GrAA::kYes,
Brian Salomonfc118442019-11-22 19:09:27 -0500366 GrQuadAAFlags::kAll, SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(),
367 nullptr);
Chris Dalton3d770272019-08-14 09:24:37 -0600368 return rtc;
369}
370
Greg Danielf41b2bd2019-08-22 16:19:24 -0400371// Test that two opsTasks using the same mipmaps both depend on the same GrTextureResolveRenderTask.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600372DEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) {
373 using CanClearFullscreen = GrRenderTargetContext::CanClearFullscreen;
374 using Enable = GrContextOptions::Enable;
375 using Filter = GrSamplerState::Filter;
376
377 for (auto enableSortingAndReduction : {Enable::kYes, Enable::kNo}) {
378 GrMockOptions mockOptions;
379 mockOptions.fMipMapSupport = true;
380 GrContextOptions ctxOptions;
Greg Daniel93138742019-08-22 17:15:39 -0400381 ctxOptions.fReduceOpsTaskSplitting = enableSortingAndReduction;
Chris Dalton30eea6c2019-08-21 10:22:50 -0600382 sk_sp<GrContext> context = GrContext::MakeMock(&mockOptions, ctxOptions);
383 if (!context) {
Greg Danielf41b2bd2019-08-22 16:19:24 -0400384 ERRORF(reporter, "could not create mock context with fReduceOpsTaskSplitting %s.",
Chris Dalton30eea6c2019-08-21 10:22:50 -0600385 (Enable::kYes == enableSortingAndReduction) ? "enabled" : "disabled");
386 continue;
387 }
388
389 SkASSERT(context->priv().caps()->mipMapSupport());
390
391 GrBackendFormat format = context->defaultBackendFormat(
392 kRGBA_8888_SkColorType, GrRenderable::kYes);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600393 GrColorType colorType = GrColorType::kRGBA_8888;
Brian Salomonfc118442019-11-22 19:09:27 -0500394 SkAlphaType alphaType = kPremul_SkAlphaType;
Chris Dalton30eea6c2019-08-21 10:22:50 -0600395
Chris Dalton30eea6c2019-08-21 10:22:50 -0600396 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
397
398 // Create a mipmapped render target.
399 GrSurfaceDesc desc;
400 desc.fWidth = 4;
401 desc.fHeight = 4;
Greg Daniel47c20e82020-01-21 14:29:57 -0500402
403 GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(format, colorType);
404
Brian Salomonbeb7f522019-08-30 16:19:42 -0400405 sk_sp<GrTextureProxy> mipmapProxy = proxyProvider->createProxy(
Greg Daniel47c20e82020-01-21 14:29:57 -0500406 format, desc, swizzle, GrRenderable::kYes, 1, kTopLeft_GrSurfaceOrigin,
407 GrMipMapped::kYes, SkBackingFit::kExact, SkBudgeted::kYes, GrProtected::kNo);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600408
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600409 // Mark the mipmaps clean to ensure things still work properly when they won't be marked
410 // dirty again until GrRenderTask::makeClosed().
411 mipmapProxy->markMipMapsClean();
412
Greg Danielba0ff782020-01-07 15:42:57 -0500413 auto mipmapRTC = GrRenderTargetContext::Make(
414 context.get(), colorType, nullptr, mipmapProxy, kTopLeft_GrSurfaceOrigin, nullptr);
415
Chris Dalton30eea6c2019-08-21 10:22:50 -0600416 mipmapRTC->clear(nullptr, {.1f,.2f,.3f,.4f}, CanClearFullscreen::kYes);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600417 REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask());
Greg Danielf41b2bd2019-08-22 16:19:24 -0400418 // mipmapProxy's last render task should now just be the opsTask containing the clear.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600419 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400420 mipmapRTC->testingOnly_PeekLastOpsTask() == mipmapProxy->getLastRenderTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600421
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600422 // Mipmaps don't get marked dirty until makeClosed().
423 REPORTER_ASSERT(reporter, !mipmapProxy->mipMapsAreDirty());
424
Greg Daniel40903af2020-01-30 14:55:05 -0500425 GrSurfaceProxyView mipmapView(mipmapProxy, kTopLeft_GrSurfaceOrigin, swizzle);
426
Chris Dalton30eea6c2019-08-21 10:22:50 -0600427 // Draw the dirty mipmap texture into a render target.
Greg Danielba0ff782020-01-07 15:42:57 -0500428 auto rtc1 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
Greg Daniel40903af2020-01-30 14:55:05 -0500429 alphaType, mipmapView, Filter::kMipMap);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600430
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600431 // Mipmaps should have gotten marked dirty during makeClosed, then marked clean again as
432 // soon as a GrTextureResolveRenderTask was inserted. The way we know they were resolved is
Greg Danielf41b2bd2019-08-22 16:19:24 -0400433 // if mipmapProxy->getLastRenderTask() has switched from the opsTask that drew to it, to the
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600434 // task that resolved its mips.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600435 GrRenderTask* initialMipmapRegenTask = mipmapProxy->getLastRenderTask();
436 REPORTER_ASSERT(reporter, initialMipmapRegenTask);
437 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400438 initialMipmapRegenTask != mipmapRTC->testingOnly_PeekLastOpsTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600439 REPORTER_ASSERT(reporter, !mipmapProxy->mipMapsAreDirty());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600440
441 // Draw the now-clean mipmap texture into a second target.
Greg Danielba0ff782020-01-07 15:42:57 -0500442 auto rtc2 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
Greg Daniel40903af2020-01-30 14:55:05 -0500443 alphaType, mipmapView, Filter::kMipMap);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600444
445 // Make sure the mipmap texture still has the same regen task.
446 REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask() == initialMipmapRegenTask);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600447 SkASSERT(!mipmapProxy->mipMapsAreDirty());
448
449 // Reset everything so we can go again, this time with the first draw not mipmapped.
450 context->flush();
451
Chris Daltone2a903e2019-09-18 13:41:50 -0600452 // Mip regen tasks don't get added as dependencies until makeClosed().
453 REPORTER_ASSERT(reporter,
454 rtc1->testingOnly_PeekLastOpsTask()->dependsOn(initialMipmapRegenTask));
455 REPORTER_ASSERT(reporter,
456 rtc2->testingOnly_PeekLastOpsTask()->dependsOn(initialMipmapRegenTask));
457
Chris Dalton30eea6c2019-08-21 10:22:50 -0600458 // Render something to dirty the mips.
459 mipmapRTC->clear(nullptr, {.1f,.2f,.3f,.4f}, CanClearFullscreen::kYes);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600460 REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask());
Greg Danielf41b2bd2019-08-22 16:19:24 -0400461 // mipmapProxy's last render task should now just be the opsTask containing the clear.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600462 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400463 mipmapRTC->testingOnly_PeekLastOpsTask() == mipmapProxy->getLastRenderTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600464
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600465 // Mipmaps don't get marked dirty until makeClosed().
466 REPORTER_ASSERT(reporter, !mipmapProxy->mipMapsAreDirty());
467
Chris Dalton30eea6c2019-08-21 10:22:50 -0600468 // Draw the dirty mipmap texture into a render target, but don't do mipmap filtering.
Greg Danielba0ff782020-01-07 15:42:57 -0500469 rtc1 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
Greg Daniel40903af2020-01-30 14:55:05 -0500470 alphaType, mipmapView, Filter::kBilerp);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600471
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600472 // Mipmaps should have gotten marked dirty during makeClosed() when adding the dependency.
473 // Since the last draw did not use mips, they will not have been regenerated and should
474 // therefore still be dirty.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600475 REPORTER_ASSERT(reporter, mipmapProxy->mipMapsAreDirty());
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600476
477 // Since mips weren't regenerated, the last render task shouldn't have changed.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600478 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400479 mipmapRTC->testingOnly_PeekLastOpsTask() == mipmapProxy->getLastRenderTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600480
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600481 // Draw the stil-dirty mipmap texture into a second target with mipmap filtering.
Greg Danielba0ff782020-01-07 15:42:57 -0500482 rtc2 = draw_mipmap_into_new_render_target(context.get(), proxyProvider, colorType,
Greg Daniel40903af2020-01-30 14:55:05 -0500483 alphaType, std::move(mipmapView),
484 Filter::kMipMap);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600485
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600486 // Make sure the mipmap texture now has a new last render task that regenerates the mips,
487 // and that the mipmaps are now clean.
Chris Daltone2a903e2019-09-18 13:41:50 -0600488 auto mipRegenTask2 = mipmapProxy->getLastRenderTask();
489 REPORTER_ASSERT(reporter, mipRegenTask2);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600490 REPORTER_ASSERT(reporter,
Chris Daltone2a903e2019-09-18 13:41:50 -0600491 mipmapRTC->testingOnly_PeekLastOpsTask() != mipRegenTask2);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600492 SkASSERT(!mipmapProxy->mipMapsAreDirty());
Chris Daltone2a903e2019-09-18 13:41:50 -0600493
494 // Mip regen tasks don't get added as dependencies until makeClosed().
495 context->flush();
496 REPORTER_ASSERT(reporter, rtc2->testingOnly_PeekLastOpsTask()->dependsOn(mipRegenTask2));
Chris Dalton3d770272019-08-14 09:24:37 -0600497 }
Chris Dalton3d770272019-08-14 09:24:37 -0600498}