blob: 7c1b03374ee74f1304e404c8fa5f409cf673df7e [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"
Robert Phillips6d344c32020-07-06 10:56:46 -040014#include "include/gpu/GrDirectContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/gpu/GrBackendTextureImageGenerator.h"
Adlai Hollera0693042020-10-14 11:23:11 -040016#include "src/gpu/GrDirectContextPriv.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"
Robert Phillipse19babf2020-04-06 13:57:30 -040019#include "src/gpu/GrProxyProvider.h"
Greg Daniel47c20e82020-01-21 14:29:57 -050020#include "src/gpu/GrRecordingContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "src/gpu/GrSemaphore.h"
Brian Salomoneebe7352020-12-09 16:37:04 -050022#include "src/gpu/GrSurfaceDrawContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "src/gpu/GrSurfaceProxyPriv.h"
Brian Salomon4cfae3b2020-07-23 10:33:24 -040024#include "src/gpu/GrTexture.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040025#include "src/gpu/GrTextureProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "src/gpu/SkGpuDevice.h"
27#include "src/image/SkImage_Base.h"
28#include "src/image/SkSurface_Gpu.h"
29#include "tests/Test.h"
Greg Danielc1ad77c2020-05-06 11:40:03 -040030#include "tests/TestUtils.h"
Brian Salomon72050802020-10-12 20:45:06 -040031#include "tools/gpu/BackendSurfaceFactory.h"
32#include "tools/gpu/BackendTextureImageFactory.h"
33#include "tools/gpu/ManagedBackendTexture.h"
Greg Daniel177e6952017-10-12 12:27:11 -040034
Greg Daniel45d63032017-10-30 13:41:26 -040035static constexpr int kSize = 8;
36
Greg Daniel177e6952017-10-12 12:27:11 -040037// Test that the correct mip map states are on the GrTextures when wrapping GrBackendTextures in
38// SkImages and SkSurfaces
39DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest, reporter, ctxInfo) {
Adlai Holler14dc7912020-08-11 15:48:49 +000040 auto dContext = ctxInfo.directContext();
41 if (!dContext->priv().caps()->mipmapSupport()) {
Greg Daniel261b8aa2017-10-23 09:37:36 -040042 return;
43 }
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050044
Brian Salomon7e67dca2020-07-21 09:27:25 -040045 for (auto mipMapped : {GrMipmapped::kNo, GrMipmapped::kYes}) {
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040046 for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
Robert Phillips9b16f812019-05-17 10:01:21 -040047 // createBackendTexture currently doesn't support uploading data to mip maps
Greg Daniel177e6952017-10-12 12:27:11 -040048 // so we don't send any. However, we pretend there is data for the checks below which is
49 // fine since we are never actually using these textures for any work on the gpu.
Brian Salomon72050802020-10-12 20:45:06 -040050 auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithData(dContext,
51 kSize,
52 kSize,
53 kRGBA_8888_SkColorType,
54 SkColors::kTransparent,
55 mipMapped,
56 renderable,
57 GrProtected::kNo);
Brian Salomon88d7e622020-11-05 11:11:20 -050058 if (!mbet) {
59 ERRORF(reporter, "Could not make texture.");
60 return;
61 }
Greg Daniel177e6952017-10-12 12:27:11 -040062
Robert Phillipse0070c02017-11-13 12:47:24 -050063 sk_sp<GrTextureProxy> proxy;
Greg Daniel177e6952017-10-12 12:27:11 -040064 sk_sp<SkImage> image;
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040065 if (GrRenderable::kYes == renderable) {
Greg Daniel177e6952017-10-12 12:27:11 -040066 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(
Brian Salomon72050802020-10-12 20:45:06 -040067 dContext,
68 mbet->texture(),
69 kTopLeft_GrSurfaceOrigin,
70 0,
71 kRGBA_8888_SkColorType,
72 /*color space*/ nullptr,
73 /*surface props*/ nullptr,
74 sk_gpu_test::ManagedBackendTexture::ReleaseProc,
75 mbet->releaseContext());
Greg Daniel177e6952017-10-12 12:27:11 -040076
77 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
Brian Salomon8f7d9532020-12-23 09:16:59 -050078 proxy = device->surfaceDrawContext()->asTextureProxyRef();
Greg Daniel177e6952017-10-12 12:27:11 -040079 } else {
Brian Salomon72050802020-10-12 20:45:06 -040080 image = SkImage::MakeFromTexture(dContext,
81 mbet->texture(),
Greg Daniel177e6952017-10-12 12:27:11 -040082 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -050083 kRGBA_8888_SkColorType,
Brian Salomon72050802020-10-12 20:45:06 -040084 kPremul_SkAlphaType,
85 /* color space */ nullptr,
86 sk_gpu_test::ManagedBackendTexture::ReleaseProc,
87 mbet->releaseContext());
Adlai Holler14dc7912020-08-11 15:48:49 +000088 const GrSurfaceProxyView* view = as_IB(image)->view(dContext);
Greg Danielfebdedf2020-02-05 17:06:27 -050089 REPORTER_ASSERT(reporter, view);
90 if (!view) {
Brian Salomon72050802020-10-12 20:45:06 -040091 continue;
Greg Danielfebdedf2020-02-05 17:06:27 -050092 }
93 proxy = view->asTextureProxyRef();
Greg Daniel177e6952017-10-12 12:27:11 -040094 }
95 REPORTER_ASSERT(reporter, proxy);
96 if (!proxy) {
Brian Salomon72050802020-10-12 20:45:06 -040097 continue;
Greg Daniel177e6952017-10-12 12:27:11 -040098 }
99
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400100 REPORTER_ASSERT(reporter, proxy->isInstantiated());
Greg Daniel177e6952017-10-12 12:27:11 -0400101
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400102 GrTexture* texture = proxy->peekTexture();
Greg Daniel177e6952017-10-12 12:27:11 -0400103 REPORTER_ASSERT(reporter, texture);
104 if (!texture) {
Brian Salomon72050802020-10-12 20:45:06 -0400105 continue;
Greg Daniel177e6952017-10-12 12:27:11 -0400106 }
107
Brian Salomon7e67dca2020-07-21 09:27:25 -0400108 if (GrMipmapped::kYes == mipMapped) {
Brian Salomon4cfae3b2020-07-23 10:33:24 -0400109 REPORTER_ASSERT(reporter, GrMipmapped::kYes == texture->mipmapped());
Robert Phillips9dbcdcc2019-05-13 10:40:06 -0400110 if (GrRenderable::kYes == renderable) {
Brian Salomon4cfae3b2020-07-23 10:33:24 -0400111 REPORTER_ASSERT(reporter, texture->mipmapsAreDirty());
Greg Daniel177e6952017-10-12 12:27:11 -0400112 } else {
Brian Salomon4cfae3b2020-07-23 10:33:24 -0400113 REPORTER_ASSERT(reporter, !texture->mipmapsAreDirty());
Greg Daniel177e6952017-10-12 12:27:11 -0400114 }
115 } else {
Brian Salomon4cfae3b2020-07-23 10:33:24 -0400116 REPORTER_ASSERT(reporter, GrMipmapped::kNo == texture->mipmapped());
Greg Daniel177e6952017-10-12 12:27:11 -0400117 }
Greg Daniel177e6952017-10-12 12:27:11 -0400118 }
119 }
120}
121
Greg Daniel261b8aa2017-10-23 09:37:36 -0400122// Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator
123// based on if we will use mips in the draw and the mip status of the GrBackendTexture.
124DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) {
Adlai Holler14dc7912020-08-11 15:48:49 +0000125 auto dContext = ctxInfo.directContext();
126 if (!dContext->priv().caps()->mipmapSupport()) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400127 return;
128 }
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500129
Brian Salomon7e67dca2020-07-21 09:27:25 -0400130 for (auto betMipMapped : {GrMipmapped::kNo, GrMipmapped::kYes}) {
131 for (auto requestMipMapped : {GrMipmapped::kNo, GrMipmapped::kYes}) {
Brian Salomon72050802020-10-12 20:45:06 -0400132 auto ii =
133 SkImageInfo::Make({kSize, kSize}, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
134 sk_sp<SkImage> image = sk_gpu_test::MakeBackendTextureImage(
135 dContext, ii, SkColors::kTransparent, betMipMapped);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400136
137 GrTextureProxy* proxy = as_IB(image)->peekProxy();
138 REPORTER_ASSERT(reporter, proxy);
139 if (!proxy) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400140 return;
141 }
142
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400143 REPORTER_ASSERT(reporter, proxy->isInstantiated());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400144
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400145 sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400146 REPORTER_ASSERT(reporter, texture);
147 if (!texture) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400148 return;
149 }
150
151 std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make(
Brian Osman052ef692018-03-27 09:56:31 -0400152 texture, kTopLeft_GrSurfaceOrigin, nullptr, kRGBA_8888_SkColorType,
153 kPremul_SkAlphaType, nullptr);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400154 REPORTER_ASSERT(reporter, imageGen);
155 if (!imageGen) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400156 return;
157 }
158
159 SkIPoint origin = SkIPoint::Make(0,0);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400160 SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
161 kPremul_SkAlphaType);
Brian Salomonbc074a62020-03-18 10:06:13 -0400162 GrSurfaceProxyView genView = imageGen->generateTexture(
Adlai Holler14dc7912020-08-11 15:48:49 +0000163 dContext, imageInfo, origin, requestMipMapped, GrImageTexGenPolicy::kDraw);
Greg Danielcc104db2020-02-03 14:17:08 -0500164 GrSurfaceProxy* genProxy = genView.proxy();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400165
166 REPORTER_ASSERT(reporter, genProxy);
167 if (!genProxy) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400168 return;
169 }
170
Brian Salomonbeb7f522019-08-30 16:19:42 -0400171 if (genProxy->isLazy()) {
Adlai Holler14dc7912020-08-11 15:48:49 +0000172 genProxy->priv().doLazyInstantiation(dContext->priv().resourceProvider());
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400173 } else if (!genProxy->isInstantiated()) {
Adlai Holler14dc7912020-08-11 15:48:49 +0000174 genProxy->instantiate(dContext->priv().resourceProvider());
Greg Daniele728f672018-01-17 10:52:04 -0500175 }
176
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400177 REPORTER_ASSERT(reporter, genProxy->isInstantiated());
178 if (!genProxy->isInstantiated()) {
Greg Danielbddcc952018-01-24 13:22:24 -0500179 return;
180 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400181
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400182 GrTexture* genTexture = genProxy->peekTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400183 REPORTER_ASSERT(reporter, genTexture);
184 if (!genTexture) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400185 return;
186 }
187
Brian Salomon72050802020-10-12 20:45:06 -0400188 GrBackendTexture backendTex = texture->getBackendTexture();
Robert Phillipsb67821d2017-12-13 15:00:45 -0500189 GrBackendTexture genBackendTex = genTexture->getBackendTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400190
Greg Danielbdf12ad2018-10-12 09:31:11 -0400191 if (GrBackendApi::kOpenGL == genBackendTex.backend()) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400192 GrGLTextureInfo genTexInfo;
193 GrGLTextureInfo origTexInfo;
194 if (genBackendTex.getGLTextureInfo(&genTexInfo) &&
195 backendTex.getGLTextureInfo(&origTexInfo)) {
Brian Salomon7e67dca2020-07-21 09:27:25 -0400196 if (requestMipMapped == GrMipmapped::kYes && betMipMapped == GrMipmapped::kNo) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400197 // We did a copy so the texture IDs should be different
198 REPORTER_ASSERT(reporter, origTexInfo.fID != genTexInfo.fID);
199 } else {
200 REPORTER_ASSERT(reporter, origTexInfo.fID == genTexInfo.fID);
201 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400202 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400203 ERRORF(reporter, "Failed to get GrGLTextureInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400204 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400205#ifdef SK_VULKAN
Greg Danielbdf12ad2018-10-12 09:31:11 -0400206 } else if (GrBackendApi::kVulkan == genBackendTex.backend()) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400207 GrVkImageInfo genImageInfo;
208 GrVkImageInfo origImageInfo;
209 if (genBackendTex.getVkImageInfo(&genImageInfo) &&
210 backendTex.getVkImageInfo(&origImageInfo)) {
Brian Salomon7e67dca2020-07-21 09:27:25 -0400211 if (requestMipMapped == GrMipmapped::kYes && betMipMapped == GrMipmapped::kNo) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400212 // We did a copy so the texture IDs should be different
213 REPORTER_ASSERT(reporter, origImageInfo.fImage != genImageInfo.fImage);
214 } else {
215 REPORTER_ASSERT(reporter, origImageInfo.fImage == genImageInfo.fImage);
216 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400217 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400218 ERRORF(reporter, "Failed to get GrVkImageInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400219 }
220#endif
Jim Van Verth9896a0d2019-04-10 15:11:12 -0400221#ifdef SK_METAL
222 } else if (GrBackendApi::kMetal == genBackendTex.backend()) {
223 GrMtlTextureInfo genImageInfo;
224 GrMtlTextureInfo origImageInfo;
225 if (genBackendTex.getMtlTextureInfo(&genImageInfo) &&
226 backendTex.getMtlTextureInfo(&origImageInfo)) {
Brian Salomon7e67dca2020-07-21 09:27:25 -0400227 if (requestMipMapped == GrMipmapped::kYes && betMipMapped == GrMipmapped::kNo) {
Jim Van Verth9896a0d2019-04-10 15:11:12 -0400228 // We did a copy so the texture IDs should be different
229 REPORTER_ASSERT(reporter, origImageInfo.fTexture != genImageInfo.fTexture);
230 } else {
231 REPORTER_ASSERT(reporter, origImageInfo.fTexture == genImageInfo.fTexture);
232 }
233 } else {
234 ERRORF(reporter, "Failed to get GrMtlTextureInfo");
235 }
236#endif
Stephen Whitee895cdc2020-10-08 13:43:40 -0400237#ifdef SK_DAWN
238 } else if (GrBackendApi::kDawn == genBackendTex.backend()) {
239 GrDawnTextureInfo genImageInfo;
240 GrDawnTextureInfo origImageInfo;
241 if (genBackendTex.getDawnTextureInfo(&genImageInfo) &&
242 backendTex.getDawnTextureInfo(&origImageInfo)) {
243 if (requestMipMapped == GrMipmapped::kYes && betMipMapped == GrMipmapped::kNo) {
244 // We did a copy so the texture IDs should be different
245 REPORTER_ASSERT(reporter,
246 origImageInfo.fTexture.Get() != genImageInfo.fTexture.Get());
247 } else {
248 REPORTER_ASSERT(reporter,
249 origImageInfo.fTexture.Get() == genImageInfo.fTexture.Get());
250 }
251 } else {
252 ERRORF(reporter, "Failed to get GrDawnTextureInfo");
253 }
254#endif
Greg Daniel261b8aa2017-10-23 09:37:36 -0400255 } else {
256 REPORTER_ASSERT(reporter, false);
257 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400258 }
259 }
260}
261
Greg Daniel45d63032017-10-30 13:41:26 -0400262// Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the
263// resource we took the snapshot of.
264DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) {
Adlai Holler14dc7912020-08-11 15:48:49 +0000265 auto dContext = ctxInfo.directContext();
266 if (!dContext->priv().caps()->mipmapSupport()) {
Greg Daniel45d63032017-10-30 13:41:26 -0400267 return;
268 }
269
Adlai Holler14dc7912020-08-11 15:48:49 +0000270 auto resourceProvider = dContext->priv().resourceProvider();
Robert Phillips6be756b2018-01-16 15:07:54 -0500271
Greg Daniel45d63032017-10-30 13:41:26 -0400272 for (auto willUseMips : {false, true}) {
273 for (auto isWrapped : {false, true}) {
Brian Salomon7e67dca2020-07-21 09:27:25 -0400274 GrMipmapped mipMapped = willUseMips ? GrMipmapped::kYes : GrMipmapped::kNo;
Greg Daniel45d63032017-10-30 13:41:26 -0400275 sk_sp<SkSurface> surface;
Brian Salomon72050802020-10-12 20:45:06 -0400276 SkImageInfo info =
277 SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
Greg Daniel45d63032017-10-30 13:41:26 -0400278 if (isWrapped) {
Brian Salomon72050802020-10-12 20:45:06 -0400279 surface = sk_gpu_test::MakeBackendTextureSurface(dContext,
280 info,
281 kTopLeft_GrSurfaceOrigin,
282 /* sample count */ 1,
283 mipMapped);
Greg Daniel45d63032017-10-30 13:41:26 -0400284 } else {
Brian Salomon72050802020-10-12 20:45:06 -0400285 surface = SkSurface::MakeRenderTarget(dContext,
286 SkBudgeted::kYes,
287 info,
288 /* sample count */ 1,
289 kTopLeft_GrSurfaceOrigin,
290 nullptr,
Greg Daniel45d63032017-10-30 13:41:26 -0400291 willUseMips);
292 }
293 REPORTER_ASSERT(reporter, surface);
Greg Daniel45d63032017-10-30 13:41:26 -0400294 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
Brian Salomon8f7d9532020-12-23 09:16:59 -0500295 GrTextureProxy* texProxy = device->surfaceDrawContext()->asTextureProxy();
Brian Salomon8c82a872020-07-21 12:09:58 -0400296 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipmapped());
Greg Daniel45d63032017-10-30 13:41:26 -0400297
Robert Phillips6be756b2018-01-16 15:07:54 -0500298 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400299 GrTexture* texture = texProxy->peekTexture();
Brian Salomon4cfae3b2020-07-23 10:33:24 -0400300 REPORTER_ASSERT(reporter, mipMapped == texture->mipmapped());
Greg Daniel45d63032017-10-30 13:41:26 -0400301
302 sk_sp<SkImage> image = surface->makeImageSnapshot();
303 REPORTER_ASSERT(reporter, image);
Greg Daniel45d63032017-10-30 13:41:26 -0400304 texProxy = as_IB(image)->peekProxy();
Brian Salomon8c82a872020-07-21 12:09:58 -0400305 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipmapped());
Greg Daniel45d63032017-10-30 13:41:26 -0400306
Robert Phillips6be756b2018-01-16 15:07:54 -0500307 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400308 texture = texProxy->peekTexture();
Brian Salomon4cfae3b2020-07-23 10:33:24 -0400309 REPORTER_ASSERT(reporter, mipMapped == texture->mipmapped());
Greg Daniel45d63032017-10-30 13:41:26 -0400310 }
311 }
312}
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400313
314// Test that we don't create a mip mapped texture if the size is 1x1 even if the filter mode is set
315// to use mips. This test passes by not crashing or hitting asserts in code.
316DEF_GPUTEST_FOR_RENDERING_CONTEXTS(Gr1x1TextureMipMappedTest, reporter, ctxInfo) {
Adlai Holler14dc7912020-08-11 15:48:49 +0000317 auto dContext = ctxInfo.directContext();
318 if (!dContext->priv().caps()->mipmapSupport()) {
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400319 return;
320 }
321
322 // Make surface to draw into
323 SkImageInfo info = SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType);
Adlai Holler14dc7912020-08-11 15:48:49 +0000324 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, info);
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400325
326 // Make 1x1 raster bitmap
327 SkBitmap bmp;
328 bmp.allocN32Pixels(1, 1);
329 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(bmp.getPixels());
330 *pixel = 0;
331
Mike Reeddc607e32020-12-23 11:50:36 -0500332 sk_sp<SkImage> bmpImage = bmp.asImage();
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400333
334 // Make sure we scale so we don't optimize out the use of mips.
335 surface->getCanvas()->scale(0.5f, 0.5f);
336
337 SkPaint paint;
338 // This should upload the image to a non mipped GrTextureProxy.
339 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400340 surface->flushAndSubmit();
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400341
342 // Now set the filter quality to high so we use mip maps. We should find the non mipped texture
343 // in the cache for the SkImage. Since the texture is 1x1 we should just use that texture
344 // instead of trying to do a copy to a mipped texture.
345 paint.setFilterQuality(kHigh_SkFilterQuality);
346 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400347 surface->flushAndSubmit();
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400348}
349
Greg Daniel40903af2020-01-30 14:55:05 -0500350// Create a new render target and draw 'mipmapView' into it using the provided 'filter'.
Brian Salomoneebe7352020-12-09 16:37:04 -0500351static std::unique_ptr<GrSurfaceDrawContext> draw_mipmap_into_new_render_target(
Adlai Holler14dc7912020-08-11 15:48:49 +0000352 GrRecordingContext* rContext,
Brian Salomone69b9ef2020-07-22 11:18:06 -0400353 GrColorType colorType,
354 SkAlphaType alphaType,
355 GrSurfaceProxyView mipmapView,
356 GrSamplerState::MipmapMode mm) {
Adlai Holler14dc7912020-08-11 15:48:49 +0000357 auto proxyProvider = rContext->priv().proxyProvider();
Brian Salomone69b9ef2020-07-22 11:18:06 -0400358 sk_sp<GrSurfaceProxy> renderTarget =
359 proxyProvider->createProxy(mipmapView.proxy()->backendFormat(),
360 {1, 1},
361 GrRenderable::kYes,
362 1,
363 GrMipmapped::kNo,
364 SkBackingFit::kApprox,
365 SkBudgeted::kYes,
366 GrProtected::kNo);
Greg Danielba0ff782020-01-07 15:42:57 -0500367
Brian Salomoneebe7352020-12-09 16:37:04 -0500368 auto rtc = GrSurfaceDrawContext::Make(rContext,
369 colorType,
370 nullptr,
371 std::move(renderTarget),
372 kTopLeft_GrSurfaceOrigin,
373 nullptr);
Greg Danielba0ff782020-01-07 15:42:57 -0500374
Brian Salomone69b9ef2020-07-22 11:18:06 -0400375 rtc->drawTexture(nullptr,
376 std::move(mipmapView),
377 alphaType,
378 GrSamplerState::Filter::kLinear,
379 mm,
380 SkBlendMode::kSrcOver,
381 {1, 1, 1, 1},
382 SkRect::MakeWH(4, 4),
383 SkRect::MakeWH(1, 1),
384 GrAA::kYes,
385 GrQuadAAFlags::kAll,
386 SkCanvas::kFast_SrcRectConstraint,
387 SkMatrix::I(),
Brian Salomonfc118442019-11-22 19:09:27 -0500388 nullptr);
Chris Dalton3d770272019-08-14 09:24:37 -0600389 return rtc;
390}
391
Greg Danielf41b2bd2019-08-22 16:19:24 -0400392// Test that two opsTasks using the same mipmaps both depend on the same GrTextureResolveRenderTask.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600393DEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) {
Chris Dalton30eea6c2019-08-21 10:22:50 -0600394 using Enable = GrContextOptions::Enable;
Brian Salomone69b9ef2020-07-22 11:18:06 -0400395 using MipmapMode = GrSamplerState::MipmapMode;
Chris Dalton30eea6c2019-08-21 10:22:50 -0600396
397 for (auto enableSortingAndReduction : {Enable::kYes, Enable::kNo}) {
398 GrMockOptions mockOptions;
Brian Salomon69100f02020-07-21 10:49:25 -0400399 mockOptions.fMipmapSupport = true;
Chris Dalton30eea6c2019-08-21 10:22:50 -0600400 GrContextOptions ctxOptions;
Greg Daniel93138742019-08-22 17:15:39 -0400401 ctxOptions.fReduceOpsTaskSplitting = enableSortingAndReduction;
Adlai Holler14dc7912020-08-11 15:48:49 +0000402 sk_sp<GrDirectContext> dContext = GrDirectContext::MakeMock(&mockOptions, ctxOptions);
403 GrDrawingManager* drawingManager = dContext->priv().drawingManager();
404 if (!dContext) {
405 ERRORF(reporter, "could not create mock dContext with fReduceOpsTaskSplitting %s.",
Chris Dalton30eea6c2019-08-21 10:22:50 -0600406 (Enable::kYes == enableSortingAndReduction) ? "enabled" : "disabled");
407 continue;
408 }
409
Adlai Holler14dc7912020-08-11 15:48:49 +0000410 SkASSERT(dContext->priv().caps()->mipmapSupport());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600411
Adlai Holler14dc7912020-08-11 15:48:49 +0000412 GrBackendFormat format = dContext->defaultBackendFormat(
Chris Dalton30eea6c2019-08-21 10:22:50 -0600413 kRGBA_8888_SkColorType, GrRenderable::kYes);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600414 GrColorType colorType = GrColorType::kRGBA_8888;
Brian Salomonfc118442019-11-22 19:09:27 -0500415 SkAlphaType alphaType = kPremul_SkAlphaType;
Chris Dalton30eea6c2019-08-21 10:22:50 -0600416
Adlai Holler14dc7912020-08-11 15:48:49 +0000417 GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
Chris Dalton30eea6c2019-08-21 10:22:50 -0600418
419 // Create a mipmapped render target.
Greg Daniel47c20e82020-01-21 14:29:57 -0500420
Brian Salomonbeb7f522019-08-30 16:19:42 -0400421 sk_sp<GrTextureProxy> mipmapProxy = proxyProvider->createProxy(
Brian Salomon7e67dca2020-07-21 09:27:25 -0400422 format, {4, 4}, GrRenderable::kYes, 1, GrMipmapped::kYes, SkBackingFit::kExact,
Brian Salomondf1bd6d2020-03-26 20:37:01 -0400423 SkBudgeted::kYes, GrProtected::kNo);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600424
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600425 // Mark the mipmaps clean to ensure things still work properly when they won't be marked
426 // dirty again until GrRenderTask::makeClosed().
Brian Salomon8c82a872020-07-21 12:09:58 -0400427 mipmapProxy->markMipmapsClean();
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600428
Brian Salomoneebe7352020-12-09 16:37:04 -0500429 auto mipmapRTC = GrSurfaceDrawContext::Make(
Adlai Holler14dc7912020-08-11 15:48:49 +0000430 dContext.get(), colorType, nullptr, mipmapProxy, kTopLeft_GrSurfaceOrigin, nullptr);
Greg Danielba0ff782020-01-07 15:42:57 -0500431
Brian Salomon590f5672020-12-16 11:44:47 -0500432 mipmapRTC->clear(SkPMColor4f{.1f, .2f, .3f, .4f});
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400433 REPORTER_ASSERT(reporter, drawingManager->getLastRenderTask(mipmapProxy.get()));
Greg Danielf41b2bd2019-08-22 16:19:24 -0400434 // mipmapProxy's last render task should now just be the opsTask containing the clear.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600435 REPORTER_ASSERT(reporter,
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400436 mipmapRTC->testingOnly_PeekLastOpsTask() ==
437 drawingManager->getLastRenderTask(mipmapProxy.get()));
Chris Dalton30eea6c2019-08-21 10:22:50 -0600438
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600439 // Mipmaps don't get marked dirty until makeClosed().
Brian Salomon8c82a872020-07-21 12:09:58 -0400440 REPORTER_ASSERT(reporter, !mipmapProxy->mipmapsAreDirty());
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600441
Adlai Holler14dc7912020-08-11 15:48:49 +0000442 GrSwizzle swizzle = dContext->priv().caps()->getReadSwizzle(format, colorType);
Greg Daniel40903af2020-01-30 14:55:05 -0500443 GrSurfaceProxyView mipmapView(mipmapProxy, kTopLeft_GrSurfaceOrigin, swizzle);
444
Chris Dalton30eea6c2019-08-21 10:22:50 -0600445 // Draw the dirty mipmap texture into a render target.
Adlai Holler14dc7912020-08-11 15:48:49 +0000446 auto rtc1 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType,
447 mipmapView, MipmapMode::kLinear);
Brian Salomon3b8486a2020-04-21 12:43:26 -0400448 auto rtc1Task = sk_ref_sp(rtc1->testingOnly_PeekLastOpsTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600449
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600450 // Mipmaps should have gotten marked dirty during makeClosed, then marked clean again as
451 // soon as a GrTextureResolveRenderTask was inserted. The way we know they were resolved is
Greg Danielf41b2bd2019-08-22 16:19:24 -0400452 // if mipmapProxy->getLastRenderTask() has switched from the opsTask that drew to it, to the
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600453 // task that resolved its mips.
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400454 GrRenderTask* initialMipmapRegenTask = drawingManager->getLastRenderTask(mipmapProxy.get());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600455 REPORTER_ASSERT(reporter, initialMipmapRegenTask);
456 REPORTER_ASSERT(reporter,
Greg Danielf41b2bd2019-08-22 16:19:24 -0400457 initialMipmapRegenTask != mipmapRTC->testingOnly_PeekLastOpsTask());
Brian Salomon8c82a872020-07-21 12:09:58 -0400458 REPORTER_ASSERT(reporter, !mipmapProxy->mipmapsAreDirty());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600459
460 // Draw the now-clean mipmap texture into a second target.
Adlai Holler14dc7912020-08-11 15:48:49 +0000461 auto rtc2 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType,
462 mipmapView, MipmapMode::kLinear);
Brian Salomon3b8486a2020-04-21 12:43:26 -0400463 auto rtc2Task = sk_ref_sp(rtc2->testingOnly_PeekLastOpsTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600464
465 // Make sure the mipmap texture still has the same regen task.
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400466 REPORTER_ASSERT(reporter,
467 drawingManager->getLastRenderTask(mipmapProxy.get()) == initialMipmapRegenTask);
Brian Salomon8c82a872020-07-21 12:09:58 -0400468 SkASSERT(!mipmapProxy->mipmapsAreDirty());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600469
470 // Reset everything so we can go again, this time with the first draw not mipmapped.
Adlai Holler14dc7912020-08-11 15:48:49 +0000471 dContext->flushAndSubmit();
Chris Dalton30eea6c2019-08-21 10:22:50 -0600472
Chris Daltone2a903e2019-09-18 13:41:50 -0600473 // Mip regen tasks don't get added as dependencies until makeClosed().
Brian Salomon3b8486a2020-04-21 12:43:26 -0400474 REPORTER_ASSERT(reporter, rtc1Task->dependsOn(initialMipmapRegenTask));
475 REPORTER_ASSERT(reporter, rtc2Task->dependsOn(initialMipmapRegenTask));
Chris Daltone2a903e2019-09-18 13:41:50 -0600476
Chris Dalton30eea6c2019-08-21 10:22:50 -0600477 // Render something to dirty the mips.
Brian Salomon590f5672020-12-16 11:44:47 -0500478 mipmapRTC->clear(SkPMColor4f{.1f, .2f, .3f, .4f});
Brian Salomon3b8486a2020-04-21 12:43:26 -0400479 auto mipmapRTCTask = sk_ref_sp(mipmapRTC->testingOnly_PeekLastOpsTask());
480 REPORTER_ASSERT(reporter, mipmapRTCTask);
481
Greg Danielf41b2bd2019-08-22 16:19:24 -0400482 // mipmapProxy's last render task should now just be the opsTask containing the clear.
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400483 REPORTER_ASSERT(reporter,
484 mipmapRTCTask.get() == drawingManager->getLastRenderTask(mipmapProxy.get()));
Chris Dalton30eea6c2019-08-21 10:22:50 -0600485
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600486 // Mipmaps don't get marked dirty until makeClosed().
Brian Salomon8c82a872020-07-21 12:09:58 -0400487 REPORTER_ASSERT(reporter, !mipmapProxy->mipmapsAreDirty());
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600488
Chris Dalton30eea6c2019-08-21 10:22:50 -0600489 // Draw the dirty mipmap texture into a render target, but don't do mipmap filtering.
Adlai Holler14dc7912020-08-11 15:48:49 +0000490 rtc1 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType,
491 mipmapView, MipmapMode::kNone);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600492
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600493 // Mipmaps should have gotten marked dirty during makeClosed() when adding the dependency.
494 // Since the last draw did not use mips, they will not have been regenerated and should
495 // therefore still be dirty.
Brian Salomon8c82a872020-07-21 12:09:58 -0400496 REPORTER_ASSERT(reporter, mipmapProxy->mipmapsAreDirty());
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600497
498 // Since mips weren't regenerated, the last render task shouldn't have changed.
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400499 REPORTER_ASSERT(reporter,
500 mipmapRTCTask.get() == drawingManager->getLastRenderTask(mipmapProxy.get()));
Chris Dalton30eea6c2019-08-21 10:22:50 -0600501
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600502 // Draw the stil-dirty mipmap texture into a second target with mipmap filtering.
Adlai Holler14dc7912020-08-11 15:48:49 +0000503 rtc2 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType,
504 std::move(mipmapView), MipmapMode::kLinear);
Brian Salomon3b8486a2020-04-21 12:43:26 -0400505 rtc2Task = sk_ref_sp(rtc2->testingOnly_PeekLastOpsTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600506
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600507 // Make sure the mipmap texture now has a new last render task that regenerates the mips,
508 // and that the mipmaps are now clean.
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400509 auto mipRegenTask2 = drawingManager->getLastRenderTask(mipmapProxy.get());
Chris Daltone2a903e2019-09-18 13:41:50 -0600510 REPORTER_ASSERT(reporter, mipRegenTask2);
Brian Salomon3b8486a2020-04-21 12:43:26 -0400511 REPORTER_ASSERT(reporter, mipmapRTCTask.get() != mipRegenTask2);
Brian Salomon8c82a872020-07-21 12:09:58 -0400512 SkASSERT(!mipmapProxy->mipmapsAreDirty());
Chris Daltone2a903e2019-09-18 13:41:50 -0600513
514 // Mip regen tasks don't get added as dependencies until makeClosed().
Adlai Holler14dc7912020-08-11 15:48:49 +0000515 dContext->flushAndSubmit();
Brian Salomon3b8486a2020-04-21 12:43:26 -0400516 REPORTER_ASSERT(reporter, rtc2Task->dependsOn(mipRegenTask2));
Chris Dalton3d770272019-08-14 09:24:37 -0600517 }
Chris Dalton3d770272019-08-14 09:24:37 -0600518}