blob: 23fdd57a5116f7f6182d9025ee3fb543a6d65269 [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"
Jim Van Verth1c318eb2021-05-07 16:25:49 -040015#ifdef SK_DIRECT3D
16#include "include/gpu/d3d/GrD3DTypes.h"
17#endif
Robert Phillipscc44feb2021-07-06 12:21:37 -040018#include "src/gpu/BaseDevice.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "src/gpu/GrBackendTextureImageGenerator.h"
Adlai Hollera0693042020-10-14 11:23:11 -040020#include "src/gpu/GrDirectContextPriv.h"
Chris Dalton3d770272019-08-14 09:24:37 -060021#include "src/gpu/GrDrawingManager.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050022#include "src/gpu/GrGpu.h"
Robert Phillipse19babf2020-04-06 13:57:30 -040023#include "src/gpu/GrProxyProvider.h"
Greg Daniel47c20e82020-01-21 14:29:57 -050024#include "src/gpu/GrRecordingContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "src/gpu/GrSemaphore.h"
26#include "src/gpu/GrSurfaceProxyPriv.h"
Brian Salomon4cfae3b2020-07-23 10:33:24 -040027#include "src/gpu/GrTexture.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040028#include "src/gpu/GrTextureProxy.h"
Robert Phillips4dca8312021-07-28 15:13:20 -040029#include "src/gpu/v1/SurfaceDrawContext_v1.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050030#include "src/image/SkImage_Base.h"
31#include "src/image/SkSurface_Gpu.h"
32#include "tests/Test.h"
Greg Danielc1ad77c2020-05-06 11:40:03 -040033#include "tests/TestUtils.h"
Brian Salomon72050802020-10-12 20:45:06 -040034#include "tools/gpu/BackendSurfaceFactory.h"
35#include "tools/gpu/BackendTextureImageFactory.h"
36#include "tools/gpu/ManagedBackendTexture.h"
Brian Salomone6662542021-02-23 10:45:39 -050037#include "tools/gpu/ProxyUtils.h"
Greg Daniel177e6952017-10-12 12:27:11 -040038
Greg Daniel45d63032017-10-30 13:41:26 -040039static constexpr int kSize = 8;
40
Greg Daniel177e6952017-10-12 12:27:11 -040041// Test that the correct mip map states are on the GrTextures when wrapping GrBackendTextures in
42// SkImages and SkSurfaces
43DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest, reporter, ctxInfo) {
Adlai Holler14dc7912020-08-11 15:48:49 +000044 auto dContext = ctxInfo.directContext();
45 if (!dContext->priv().caps()->mipmapSupport()) {
Greg Daniel261b8aa2017-10-23 09:37:36 -040046 return;
47 }
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050048
Brian Salomon7d2757f2021-01-26 17:46:50 -050049 for (auto mipmapped : {GrMipmapped::kNo, GrMipmapped::kYes}) {
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040050 for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
Robert Phillips9b16f812019-05-17 10:01:21 -040051 // createBackendTexture currently doesn't support uploading data to mip maps
Greg Daniel177e6952017-10-12 12:27:11 -040052 // so we don't send any. However, we pretend there is data for the checks below which is
53 // fine since we are never actually using these textures for any work on the gpu.
Brian Salomon72050802020-10-12 20:45:06 -040054 auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithData(dContext,
55 kSize,
56 kSize,
57 kRGBA_8888_SkColorType,
58 SkColors::kTransparent,
Brian Salomon7d2757f2021-01-26 17:46:50 -050059 mipmapped,
Brian Salomon72050802020-10-12 20:45:06 -040060 renderable,
61 GrProtected::kNo);
Brian Salomon88d7e622020-11-05 11:11:20 -050062 if (!mbet) {
63 ERRORF(reporter, "Could not make texture.");
64 return;
65 }
Greg Daniel177e6952017-10-12 12:27:11 -040066
Robert Phillipse0070c02017-11-13 12:47:24 -050067 sk_sp<GrTextureProxy> proxy;
Greg Daniel177e6952017-10-12 12:27:11 -040068 sk_sp<SkImage> image;
Brian Salomon7d2757f2021-01-26 17:46:50 -050069 if (renderable == GrRenderable::kYes) {
Greg Daniel177e6952017-10-12 12:27:11 -040070 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(
Brian Salomon72050802020-10-12 20:45:06 -040071 dContext,
72 mbet->texture(),
73 kTopLeft_GrSurfaceOrigin,
74 0,
75 kRGBA_8888_SkColorType,
76 /*color space*/ nullptr,
77 /*surface props*/ nullptr,
78 sk_gpu_test::ManagedBackendTexture::ReleaseProc,
79 mbet->releaseContext());
Greg Daniel177e6952017-10-12 12:27:11 -040080
Robert Phillipscc44feb2021-07-06 12:21:37 -040081 auto device = ((SkSurface_Gpu*)surface.get())->getDevice();
Robert Phillips5ccb4c12021-05-24 15:35:08 -040082 proxy = device->readSurfaceView().asTextureProxyRef();
Greg Daniel177e6952017-10-12 12:27:11 -040083 } else {
Brian Salomon72050802020-10-12 20:45:06 -040084 image = SkImage::MakeFromTexture(dContext,
85 mbet->texture(),
Greg Daniel177e6952017-10-12 12:27:11 -040086 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -050087 kRGBA_8888_SkColorType,
Brian Salomon72050802020-10-12 20:45:06 -040088 kPremul_SkAlphaType,
89 /* color space */ nullptr,
90 sk_gpu_test::ManagedBackendTexture::ReleaseProc,
91 mbet->releaseContext());
Brian Salomon7d2757f2021-01-26 17:46:50 -050092 REPORTER_ASSERT(reporter, (mipmapped == GrMipmapped::kYes) == image->hasMipmaps());
Brian Salomone6662542021-02-23 10:45:39 -050093 proxy = sk_ref_sp(sk_gpu_test::GetTextureImageProxy(image.get(), dContext));
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 Salomon7d2757f2021-01-26 17:46:50 -0500108 if (mipmapped == GrMipmapped::kYes) {
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 Salomon7d2757f2021-01-26 17:46:50 -0500130 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(
Brian Salomon7d2757f2021-01-26 17:46:50 -0500135 dContext, ii, SkColors::kTransparent, betMipmapped);
136 REPORTER_ASSERT(reporter, (betMipmapped == GrMipmapped::kYes) == image->hasMipmaps());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400137
Brian Salomone6662542021-02-23 10:45:39 -0500138 GrTextureProxy* proxy = sk_gpu_test::GetTextureImageProxy(image.get(), dContext);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400139 REPORTER_ASSERT(reporter, proxy);
140 if (!proxy) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400141 return;
142 }
143
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400144 REPORTER_ASSERT(reporter, proxy->isInstantiated());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400145
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400146 sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400147 REPORTER_ASSERT(reporter, texture);
148 if (!texture) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400149 return;
150 }
151
152 std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make(
Brian Osman052ef692018-03-27 09:56:31 -0400153 texture, kTopLeft_GrSurfaceOrigin, nullptr, kRGBA_8888_SkColorType,
154 kPremul_SkAlphaType, nullptr);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400155 REPORTER_ASSERT(reporter, imageGen);
156 if (!imageGen) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400157 return;
158 }
159
160 SkIPoint origin = SkIPoint::Make(0,0);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400161 SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
162 kPremul_SkAlphaType);
Brian Salomonbc074a62020-03-18 10:06:13 -0400163 GrSurfaceProxyView genView = imageGen->generateTexture(
Brian Salomon7d2757f2021-01-26 17:46:50 -0500164 dContext, imageInfo, origin, requestMipmapped, GrImageTexGenPolicy::kDraw);
Greg Danielcc104db2020-02-03 14:17:08 -0500165 GrSurfaceProxy* genProxy = genView.proxy();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400166
167 REPORTER_ASSERT(reporter, genProxy);
168 if (!genProxy) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400169 return;
170 }
171
Brian Salomonbeb7f522019-08-30 16:19:42 -0400172 if (genProxy->isLazy()) {
Adlai Holler14dc7912020-08-11 15:48:49 +0000173 genProxy->priv().doLazyInstantiation(dContext->priv().resourceProvider());
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400174 } else if (!genProxy->isInstantiated()) {
Adlai Holler14dc7912020-08-11 15:48:49 +0000175 genProxy->instantiate(dContext->priv().resourceProvider());
Greg Daniele728f672018-01-17 10:52:04 -0500176 }
177
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400178 REPORTER_ASSERT(reporter, genProxy->isInstantiated());
179 if (!genProxy->isInstantiated()) {
Greg Danielbddcc952018-01-24 13:22:24 -0500180 return;
181 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400182
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400183 GrTexture* genTexture = genProxy->peekTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400184 REPORTER_ASSERT(reporter, genTexture);
185 if (!genTexture) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400186 return;
187 }
188
Brian Salomon72050802020-10-12 20:45:06 -0400189 GrBackendTexture backendTex = texture->getBackendTexture();
Robert Phillipsb67821d2017-12-13 15:00:45 -0500190 GrBackendTexture genBackendTex = genTexture->getBackendTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400191
Greg Danielbdf12ad2018-10-12 09:31:11 -0400192 if (GrBackendApi::kOpenGL == genBackendTex.backend()) {
Greg Daniel84261652021-09-19 17:53:40 -0400193#ifdef SK_GL
Greg Daniel52e16d92018-04-10 09:34:07 -0400194 GrGLTextureInfo genTexInfo;
195 GrGLTextureInfo origTexInfo;
196 if (genBackendTex.getGLTextureInfo(&genTexInfo) &&
197 backendTex.getGLTextureInfo(&origTexInfo)) {
Brian Salomon7d2757f2021-01-26 17:46:50 -0500198 if (requestMipmapped == GrMipmapped::kYes && betMipmapped == GrMipmapped::kNo) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400199 // We did a copy so the texture IDs should be different
200 REPORTER_ASSERT(reporter, origTexInfo.fID != genTexInfo.fID);
201 } else {
202 REPORTER_ASSERT(reporter, origTexInfo.fID == genTexInfo.fID);
203 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400204 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400205 ERRORF(reporter, "Failed to get GrGLTextureInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400206 }
Greg Daniel84261652021-09-19 17:53:40 -0400207#endif
Greg Daniel261b8aa2017-10-23 09:37:36 -0400208#ifdef SK_VULKAN
Greg Danielbdf12ad2018-10-12 09:31:11 -0400209 } else if (GrBackendApi::kVulkan == genBackendTex.backend()) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400210 GrVkImageInfo genImageInfo;
211 GrVkImageInfo origImageInfo;
212 if (genBackendTex.getVkImageInfo(&genImageInfo) &&
213 backendTex.getVkImageInfo(&origImageInfo)) {
Brian Salomon7d2757f2021-01-26 17:46:50 -0500214 if (requestMipmapped == GrMipmapped::kYes && betMipmapped == GrMipmapped::kNo) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400215 // We did a copy so the texture IDs should be different
216 REPORTER_ASSERT(reporter, origImageInfo.fImage != genImageInfo.fImage);
217 } else {
218 REPORTER_ASSERT(reporter, origImageInfo.fImage == genImageInfo.fImage);
219 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400220 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400221 ERRORF(reporter, "Failed to get GrVkImageInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400222 }
223#endif
Jim Van Verth9896a0d2019-04-10 15:11:12 -0400224#ifdef SK_METAL
225 } else if (GrBackendApi::kMetal == genBackendTex.backend()) {
226 GrMtlTextureInfo genImageInfo;
227 GrMtlTextureInfo origImageInfo;
228 if (genBackendTex.getMtlTextureInfo(&genImageInfo) &&
229 backendTex.getMtlTextureInfo(&origImageInfo)) {
Brian Salomon7d2757f2021-01-26 17:46:50 -0500230 if (requestMipmapped == GrMipmapped::kYes && betMipmapped == GrMipmapped::kNo) {
Jim Van Verth9896a0d2019-04-10 15:11:12 -0400231 // We did a copy so the texture IDs should be different
232 REPORTER_ASSERT(reporter, origImageInfo.fTexture != genImageInfo.fTexture);
233 } else {
234 REPORTER_ASSERT(reporter, origImageInfo.fTexture == genImageInfo.fTexture);
235 }
236 } else {
237 ERRORF(reporter, "Failed to get GrMtlTextureInfo");
238 }
239#endif
Jim Van Verth1c318eb2021-05-07 16:25:49 -0400240#ifdef SK_DIRECT3D
241 } else if (GrBackendApi::kDirect3D == genBackendTex.backend()) {
242 GrD3DTextureResourceInfo genImageInfo;
243 GrD3DTextureResourceInfo origImageInfo;
244 if (genBackendTex.getD3DTextureResourceInfo(&genImageInfo) &&
245 backendTex.getD3DTextureResourceInfo(&origImageInfo)) {
246 if (requestMipmapped == GrMipmapped::kYes && betMipmapped == GrMipmapped::kNo) {
247 // We did a copy so the texture resources should be different
248 REPORTER_ASSERT(reporter,
249 origImageInfo.fResource != genImageInfo.fResource);
250 } else {
251 REPORTER_ASSERT(reporter,
252 origImageInfo.fResource == genImageInfo.fResource);
253 }
254 } else {
255 ERRORF(reporter, "Failed to get GrMtlTextureInfo");
256 }
257#endif
Stephen Whitee895cdc2020-10-08 13:43:40 -0400258#ifdef SK_DAWN
259 } else if (GrBackendApi::kDawn == genBackendTex.backend()) {
260 GrDawnTextureInfo genImageInfo;
261 GrDawnTextureInfo origImageInfo;
262 if (genBackendTex.getDawnTextureInfo(&genImageInfo) &&
263 backendTex.getDawnTextureInfo(&origImageInfo)) {
Brian Salomon7d2757f2021-01-26 17:46:50 -0500264 if (requestMipmapped == GrMipmapped::kYes && betMipmapped == GrMipmapped::kNo) {
Stephen Whitee895cdc2020-10-08 13:43:40 -0400265 // We did a copy so the texture IDs should be different
266 REPORTER_ASSERT(reporter,
267 origImageInfo.fTexture.Get() != genImageInfo.fTexture.Get());
268 } else {
269 REPORTER_ASSERT(reporter,
270 origImageInfo.fTexture.Get() == genImageInfo.fTexture.Get());
271 }
272 } else {
273 ERRORF(reporter, "Failed to get GrDawnTextureInfo");
274 }
275#endif
Greg Daniel261b8aa2017-10-23 09:37:36 -0400276 } else {
277 REPORTER_ASSERT(reporter, false);
278 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400279 }
280 }
281}
282
Greg Daniel45d63032017-10-30 13:41:26 -0400283// Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the
284// resource we took the snapshot of.
285DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) {
Adlai Holler14dc7912020-08-11 15:48:49 +0000286 auto dContext = ctxInfo.directContext();
287 if (!dContext->priv().caps()->mipmapSupport()) {
Greg Daniel45d63032017-10-30 13:41:26 -0400288 return;
289 }
290
Adlai Holler14dc7912020-08-11 15:48:49 +0000291 auto resourceProvider = dContext->priv().resourceProvider();
Robert Phillips6be756b2018-01-16 15:07:54 -0500292
Greg Daniel45d63032017-10-30 13:41:26 -0400293 for (auto willUseMips : {false, true}) {
294 for (auto isWrapped : {false, true}) {
Brian Salomon7d2757f2021-01-26 17:46:50 -0500295 GrMipmapped mipmapped = willUseMips ? GrMipmapped::kYes : GrMipmapped::kNo;
Greg Daniel45d63032017-10-30 13:41:26 -0400296 sk_sp<SkSurface> surface;
Brian Salomon72050802020-10-12 20:45:06 -0400297 SkImageInfo info =
298 SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
Greg Daniel45d63032017-10-30 13:41:26 -0400299 if (isWrapped) {
Brian Salomon72050802020-10-12 20:45:06 -0400300 surface = sk_gpu_test::MakeBackendTextureSurface(dContext,
301 info,
302 kTopLeft_GrSurfaceOrigin,
303 /* sample count */ 1,
Brian Salomon7d2757f2021-01-26 17:46:50 -0500304 mipmapped);
Greg Daniel45d63032017-10-30 13:41:26 -0400305 } else {
Brian Salomon72050802020-10-12 20:45:06 -0400306 surface = SkSurface::MakeRenderTarget(dContext,
307 SkBudgeted::kYes,
308 info,
309 /* sample count */ 1,
310 kTopLeft_GrSurfaceOrigin,
311 nullptr,
Greg Daniel45d63032017-10-30 13:41:26 -0400312 willUseMips);
313 }
314 REPORTER_ASSERT(reporter, surface);
Robert Phillipscc44feb2021-07-06 12:21:37 -0400315 auto device = ((SkSurface_Gpu*)surface.get())->getDevice();
Robert Phillips5ccb4c12021-05-24 15:35:08 -0400316 GrTextureProxy* texProxy = device->readSurfaceView().asTextureProxy();
Brian Salomon7d2757f2021-01-26 17:46:50 -0500317 REPORTER_ASSERT(reporter, mipmapped == texProxy->mipmapped());
Greg Daniel45d63032017-10-30 13:41:26 -0400318
Robert Phillips6be756b2018-01-16 15:07:54 -0500319 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400320 GrTexture* texture = texProxy->peekTexture();
Brian Salomon7d2757f2021-01-26 17:46:50 -0500321 REPORTER_ASSERT(reporter, mipmapped == texture->mipmapped());
Greg Daniel45d63032017-10-30 13:41:26 -0400322
323 sk_sp<SkImage> image = surface->makeImageSnapshot();
Brian Salomon7d2757f2021-01-26 17:46:50 -0500324 REPORTER_ASSERT(reporter, willUseMips == image->hasMipmaps());
Greg Daniel45d63032017-10-30 13:41:26 -0400325 REPORTER_ASSERT(reporter, image);
Brian Salomone6662542021-02-23 10:45:39 -0500326 texProxy = sk_gpu_test::GetTextureImageProxy(image.get(), dContext);
Brian Salomon7d2757f2021-01-26 17:46:50 -0500327 REPORTER_ASSERT(reporter, mipmapped == texProxy->mipmapped());
Greg Daniel45d63032017-10-30 13:41:26 -0400328
Robert Phillips6be756b2018-01-16 15:07:54 -0500329 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400330 texture = texProxy->peekTexture();
Brian Salomon7d2757f2021-01-26 17:46:50 -0500331 REPORTER_ASSERT(reporter, mipmapped == texture->mipmapped());
Greg Daniel45d63032017-10-30 13:41:26 -0400332 }
333 }
334}
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400335
336// Test that we don't create a mip mapped texture if the size is 1x1 even if the filter mode is set
337// to use mips. This test passes by not crashing or hitting asserts in code.
338DEF_GPUTEST_FOR_RENDERING_CONTEXTS(Gr1x1TextureMipMappedTest, reporter, ctxInfo) {
Adlai Holler14dc7912020-08-11 15:48:49 +0000339 auto dContext = ctxInfo.directContext();
340 if (!dContext->priv().caps()->mipmapSupport()) {
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400341 return;
342 }
343
344 // Make surface to draw into
345 SkImageInfo info = SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType);
Adlai Holler14dc7912020-08-11 15:48:49 +0000346 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, info);
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400347
348 // Make 1x1 raster bitmap
349 SkBitmap bmp;
350 bmp.allocN32Pixels(1, 1);
351 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(bmp.getPixels());
352 *pixel = 0;
353
Mike Reeddc607e32020-12-23 11:50:36 -0500354 sk_sp<SkImage> bmpImage = bmp.asImage();
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400355
356 // Make sure we scale so we don't optimize out the use of mips.
357 surface->getCanvas()->scale(0.5f, 0.5f);
358
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400359 // This should upload the image to a non mipped GrTextureProxy.
Mike Reed039f1362021-01-27 21:21:08 -0500360 surface->getCanvas()->drawImage(bmpImage, 0, 0);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400361 surface->flushAndSubmit();
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400362
363 // Now set the filter quality to high so we use mip maps. We should find the non mipped texture
364 // in the cache for the SkImage. Since the texture is 1x1 we should just use that texture
365 // instead of trying to do a copy to a mipped texture.
Mike Reed039f1362021-01-27 21:21:08 -0500366 surface->getCanvas()->drawImage(bmpImage, 0, 0, SkSamplingOptions({1.0f/3, 1.0f/3}));
Greg Daniel0a2464f2020-05-14 15:45:44 -0400367 surface->flushAndSubmit();
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400368}
369
Greg Daniel40903af2020-01-30 14:55:05 -0500370// Create a new render target and draw 'mipmapView' into it using the provided 'filter'.
Robert Phillips4dca8312021-07-28 15:13:20 -0400371static std::unique_ptr<skgpu::v1::SurfaceDrawContext> draw_mipmap_into_new_render_target(
Adlai Holler14dc7912020-08-11 15:48:49 +0000372 GrRecordingContext* rContext,
Brian Salomone69b9ef2020-07-22 11:18:06 -0400373 GrColorType colorType,
374 SkAlphaType alphaType,
375 GrSurfaceProxyView mipmapView,
376 GrSamplerState::MipmapMode mm) {
Adlai Holler14dc7912020-08-11 15:48:49 +0000377 auto proxyProvider = rContext->priv().proxyProvider();
Brian Salomone69b9ef2020-07-22 11:18:06 -0400378 sk_sp<GrSurfaceProxy> renderTarget =
379 proxyProvider->createProxy(mipmapView.proxy()->backendFormat(),
380 {1, 1},
381 GrRenderable::kYes,
382 1,
383 GrMipmapped::kNo,
384 SkBackingFit::kApprox,
385 SkBudgeted::kYes,
386 GrProtected::kNo);
Greg Danielba0ff782020-01-07 15:42:57 -0500387
Robert Phillips4dca8312021-07-28 15:13:20 -0400388 auto sdc = skgpu::v1::SurfaceDrawContext::Make(rContext,
389 colorType,
390 std::move(renderTarget),
391 nullptr,
392 kTopLeft_GrSurfaceOrigin,
393 SkSurfaceProps(),
394 false);
Greg Danielba0ff782020-01-07 15:42:57 -0500395
Robert Phillips4dca8312021-07-28 15:13:20 -0400396 sdc->drawTexture(nullptr,
Brian Salomone69b9ef2020-07-22 11:18:06 -0400397 std::move(mipmapView),
398 alphaType,
399 GrSamplerState::Filter::kLinear,
400 mm,
401 SkBlendMode::kSrcOver,
402 {1, 1, 1, 1},
403 SkRect::MakeWH(4, 4),
404 SkRect::MakeWH(1, 1),
405 GrAA::kYes,
406 GrQuadAAFlags::kAll,
407 SkCanvas::kFast_SrcRectConstraint,
408 SkMatrix::I(),
Brian Salomonfc118442019-11-22 19:09:27 -0500409 nullptr);
Robert Phillips4dca8312021-07-28 15:13:20 -0400410 return sdc;
Chris Dalton3d770272019-08-14 09:24:37 -0600411}
412
Greg Danielf41b2bd2019-08-22 16:19:24 -0400413// Test that two opsTasks using the same mipmaps both depend on the same GrTextureResolveRenderTask.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600414DEF_GPUTEST(GrManyDependentsMipMappedTest, reporter, /* options */) {
Chris Dalton30eea6c2019-08-21 10:22:50 -0600415 using Enable = GrContextOptions::Enable;
Brian Salomone69b9ef2020-07-22 11:18:06 -0400416 using MipmapMode = GrSamplerState::MipmapMode;
Chris Dalton30eea6c2019-08-21 10:22:50 -0600417
418 for (auto enableSortingAndReduction : {Enable::kYes, Enable::kNo}) {
419 GrMockOptions mockOptions;
Brian Salomon69100f02020-07-21 10:49:25 -0400420 mockOptions.fMipmapSupport = true;
Chris Dalton30eea6c2019-08-21 10:22:50 -0600421 GrContextOptions ctxOptions;
Greg Daniel93138742019-08-22 17:15:39 -0400422 ctxOptions.fReduceOpsTaskSplitting = enableSortingAndReduction;
Adlai Holler14dc7912020-08-11 15:48:49 +0000423 sk_sp<GrDirectContext> dContext = GrDirectContext::MakeMock(&mockOptions, ctxOptions);
424 GrDrawingManager* drawingManager = dContext->priv().drawingManager();
425 if (!dContext) {
426 ERRORF(reporter, "could not create mock dContext with fReduceOpsTaskSplitting %s.",
Chris Dalton30eea6c2019-08-21 10:22:50 -0600427 (Enable::kYes == enableSortingAndReduction) ? "enabled" : "disabled");
428 continue;
429 }
430
Adlai Holler14dc7912020-08-11 15:48:49 +0000431 SkASSERT(dContext->priv().caps()->mipmapSupport());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600432
Adlai Holler14dc7912020-08-11 15:48:49 +0000433 GrBackendFormat format = dContext->defaultBackendFormat(
Chris Dalton30eea6c2019-08-21 10:22:50 -0600434 kRGBA_8888_SkColorType, GrRenderable::kYes);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600435 GrColorType colorType = GrColorType::kRGBA_8888;
Brian Salomonfc118442019-11-22 19:09:27 -0500436 SkAlphaType alphaType = kPremul_SkAlphaType;
Chris Dalton30eea6c2019-08-21 10:22:50 -0600437
Adlai Holler14dc7912020-08-11 15:48:49 +0000438 GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
Chris Dalton30eea6c2019-08-21 10:22:50 -0600439
440 // Create a mipmapped render target.
Greg Daniel47c20e82020-01-21 14:29:57 -0500441
Brian Salomonbeb7f522019-08-30 16:19:42 -0400442 sk_sp<GrTextureProxy> mipmapProxy = proxyProvider->createProxy(
Brian Salomon7e67dca2020-07-21 09:27:25 -0400443 format, {4, 4}, GrRenderable::kYes, 1, GrMipmapped::kYes, SkBackingFit::kExact,
Brian Salomondf1bd6d2020-03-26 20:37:01 -0400444 SkBudgeted::kYes, GrProtected::kNo);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600445
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600446 // Mark the mipmaps clean to ensure things still work properly when they won't be marked
447 // dirty again until GrRenderTask::makeClosed().
Brian Salomon8c82a872020-07-21 12:09:58 -0400448 mipmapProxy->markMipmapsClean();
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600449
Robert Phillips4dca8312021-07-28 15:13:20 -0400450 auto mipmapSDC = skgpu::v1::SurfaceDrawContext::Make(
Robert Phillips779125d2021-05-24 13:14:39 -0400451 dContext.get(), colorType, mipmapProxy, nullptr, kTopLeft_GrSurfaceOrigin,
Chris Daltonf5b87f92021-04-19 17:27:09 -0600452 SkSurfaceProps(), false);
Greg Danielba0ff782020-01-07 15:42:57 -0500453
Robert Phillips4dca8312021-07-28 15:13:20 -0400454 mipmapSDC->clear(SkPMColor4f{.1f, .2f, .3f, .4f});
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400455 REPORTER_ASSERT(reporter, drawingManager->getLastRenderTask(mipmapProxy.get()));
Greg Danielf41b2bd2019-08-22 16:19:24 -0400456 // mipmapProxy's last render task should now just be the opsTask containing the clear.
Chris Dalton30eea6c2019-08-21 10:22:50 -0600457 REPORTER_ASSERT(reporter,
Robert Phillips4dca8312021-07-28 15:13:20 -0400458 mipmapSDC->testingOnly_PeekLastOpsTask() ==
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400459 drawingManager->getLastRenderTask(mipmapProxy.get()));
Chris Dalton30eea6c2019-08-21 10:22:50 -0600460
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600461 // Mipmaps don't get marked dirty until makeClosed().
Brian Salomon8c82a872020-07-21 12:09:58 -0400462 REPORTER_ASSERT(reporter, !mipmapProxy->mipmapsAreDirty());
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600463
Adlai Holler14dc7912020-08-11 15:48:49 +0000464 GrSwizzle swizzle = dContext->priv().caps()->getReadSwizzle(format, colorType);
Greg Daniel40903af2020-01-30 14:55:05 -0500465 GrSurfaceProxyView mipmapView(mipmapProxy, kTopLeft_GrSurfaceOrigin, swizzle);
466
Chris Dalton30eea6c2019-08-21 10:22:50 -0600467 // Draw the dirty mipmap texture into a render target.
Robert Phillips4dca8312021-07-28 15:13:20 -0400468 auto sdc1 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType,
Adlai Holler14dc7912020-08-11 15:48:49 +0000469 mipmapView, MipmapMode::kLinear);
Robert Phillips4dca8312021-07-28 15:13:20 -0400470 auto sdc1Task = sk_ref_sp(sdc1->testingOnly_PeekLastOpsTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600471
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600472 // Mipmaps should have gotten marked dirty during makeClosed, then marked clean again as
473 // soon as a GrTextureResolveRenderTask was inserted. The way we know they were resolved is
Greg Danielf41b2bd2019-08-22 16:19:24 -0400474 // if mipmapProxy->getLastRenderTask() has switched from the opsTask that drew to it, to the
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600475 // task that resolved its mips.
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400476 GrRenderTask* initialMipmapRegenTask = drawingManager->getLastRenderTask(mipmapProxy.get());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600477 REPORTER_ASSERT(reporter, initialMipmapRegenTask);
478 REPORTER_ASSERT(reporter,
Robert Phillips4dca8312021-07-28 15:13:20 -0400479 initialMipmapRegenTask != mipmapSDC->testingOnly_PeekLastOpsTask());
Brian Salomon8c82a872020-07-21 12:09:58 -0400480 REPORTER_ASSERT(reporter, !mipmapProxy->mipmapsAreDirty());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600481
482 // Draw the now-clean mipmap texture into a second target.
Robert Phillips4dca8312021-07-28 15:13:20 -0400483 auto sdc2 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType,
Adlai Holler14dc7912020-08-11 15:48:49 +0000484 mipmapView, MipmapMode::kLinear);
Robert Phillips4dca8312021-07-28 15:13:20 -0400485 auto sdc2Task = sk_ref_sp(sdc2->testingOnly_PeekLastOpsTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600486
487 // Make sure the mipmap texture still has the same regen task.
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400488 REPORTER_ASSERT(reporter,
489 drawingManager->getLastRenderTask(mipmapProxy.get()) == initialMipmapRegenTask);
Brian Salomon8c82a872020-07-21 12:09:58 -0400490 SkASSERT(!mipmapProxy->mipmapsAreDirty());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600491
492 // Reset everything so we can go again, this time with the first draw not mipmapped.
Adlai Holler14dc7912020-08-11 15:48:49 +0000493 dContext->flushAndSubmit();
Chris Dalton30eea6c2019-08-21 10:22:50 -0600494
Chris Daltone2a903e2019-09-18 13:41:50 -0600495 // Mip regen tasks don't get added as dependencies until makeClosed().
Robert Phillips4dca8312021-07-28 15:13:20 -0400496 REPORTER_ASSERT(reporter, sdc1Task->dependsOn(initialMipmapRegenTask));
497 REPORTER_ASSERT(reporter, sdc2Task->dependsOn(initialMipmapRegenTask));
Chris Daltone2a903e2019-09-18 13:41:50 -0600498
Chris Dalton30eea6c2019-08-21 10:22:50 -0600499 // Render something to dirty the mips.
Robert Phillips4dca8312021-07-28 15:13:20 -0400500 mipmapSDC->clear(SkPMColor4f{.1f, .2f, .3f, .4f});
501 auto mipmapRTCTask = sk_ref_sp(mipmapSDC->testingOnly_PeekLastOpsTask());
Brian Salomon3b8486a2020-04-21 12:43:26 -0400502 REPORTER_ASSERT(reporter, mipmapRTCTask);
503
Greg Danielf41b2bd2019-08-22 16:19:24 -0400504 // mipmapProxy's last render task should now just be the opsTask containing the clear.
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400505 REPORTER_ASSERT(reporter,
506 mipmapRTCTask.get() == drawingManager->getLastRenderTask(mipmapProxy.get()));
Chris Dalton30eea6c2019-08-21 10:22:50 -0600507
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600508 // Mipmaps don't get marked dirty until makeClosed().
Brian Salomon8c82a872020-07-21 12:09:58 -0400509 REPORTER_ASSERT(reporter, !mipmapProxy->mipmapsAreDirty());
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600510
Chris Dalton30eea6c2019-08-21 10:22:50 -0600511 // Draw the dirty mipmap texture into a render target, but don't do mipmap filtering.
Robert Phillips4dca8312021-07-28 15:13:20 -0400512 sdc1 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType,
Adlai Holler14dc7912020-08-11 15:48:49 +0000513 mipmapView, MipmapMode::kNone);
Chris Dalton30eea6c2019-08-21 10:22:50 -0600514
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600515 // Mipmaps should have gotten marked dirty during makeClosed() when adding the dependency.
516 // Since the last draw did not use mips, they will not have been regenerated and should
517 // therefore still be dirty.
Brian Salomon8c82a872020-07-21 12:09:58 -0400518 REPORTER_ASSERT(reporter, mipmapProxy->mipmapsAreDirty());
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600519
520 // Since mips weren't regenerated, the last render task shouldn't have changed.
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400521 REPORTER_ASSERT(reporter,
522 mipmapRTCTask.get() == drawingManager->getLastRenderTask(mipmapProxy.get()));
Chris Dalton30eea6c2019-08-21 10:22:50 -0600523
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600524 // Draw the stil-dirty mipmap texture into a second target with mipmap filtering.
Robert Phillips4dca8312021-07-28 15:13:20 -0400525 sdc2 = draw_mipmap_into_new_render_target(dContext.get(), colorType, alphaType,
Adlai Holler14dc7912020-08-11 15:48:49 +0000526 std::move(mipmapView), MipmapMode::kLinear);
Robert Phillips4dca8312021-07-28 15:13:20 -0400527 sdc2Task = sk_ref_sp(sdc2->testingOnly_PeekLastOpsTask());
Chris Dalton30eea6c2019-08-21 10:22:50 -0600528
Chris Daltonaa3cbb82019-08-21 00:01:21 -0600529 // Make sure the mipmap texture now has a new last render task that regenerates the mips,
530 // and that the mipmaps are now clean.
Adlai Hollerd71b7b02020-06-08 15:55:00 -0400531 auto mipRegenTask2 = drawingManager->getLastRenderTask(mipmapProxy.get());
Chris Daltone2a903e2019-09-18 13:41:50 -0600532 REPORTER_ASSERT(reporter, mipRegenTask2);
Brian Salomon3b8486a2020-04-21 12:43:26 -0400533 REPORTER_ASSERT(reporter, mipmapRTCTask.get() != mipRegenTask2);
Brian Salomon8c82a872020-07-21 12:09:58 -0400534 SkASSERT(!mipmapProxy->mipmapsAreDirty());
Chris Daltone2a903e2019-09-18 13:41:50 -0600535
536 // Mip regen tasks don't get added as dependencies until makeClosed().
Adlai Holler14dc7912020-08-11 15:48:49 +0000537 dContext->flushAndSubmit();
Robert Phillips4dca8312021-07-28 15:13:20 -0400538 REPORTER_ASSERT(reporter, sdc2Task->dependsOn(mipRegenTask2));
Chris Dalton3d770272019-08-14 09:24:37 -0600539 }
Chris Dalton3d770272019-08-14 09:24:37 -0600540}