blob: c63534924dc1bea77f055f700a805256c0584aa9 [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"
17#include "src/gpu/GrGpu.h"
18#include "src/gpu/GrRenderTargetContext.h"
19#include "src/gpu/GrSemaphore.h"
20#include "src/gpu/GrSurfaceProxyPriv.h"
21#include "src/gpu/GrTexturePriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040022#include "src/gpu/GrTextureProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "src/gpu/SkGpuDevice.h"
24#include "src/image/SkImage_Base.h"
25#include "src/image/SkSurface_Gpu.h"
26#include "tests/Test.h"
Greg Daniel177e6952017-10-12 12:27:11 -040027
Greg Daniel45d63032017-10-30 13:41:26 -040028static constexpr int kSize = 8;
29
Greg Daniel177e6952017-10-12 12:27:11 -040030// Test that the correct mip map states are on the GrTextures when wrapping GrBackendTextures in
31// SkImages and SkSurfaces
32DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest, reporter, ctxInfo) {
33 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -050034 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel261b8aa2017-10-23 09:37:36 -040035 return;
36 }
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050037
Greg Daniel177e6952017-10-12 12:27:11 -040038 for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040039 for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
Robert Phillips9b16f812019-05-17 10:01:21 -040040 // createBackendTexture currently doesn't support uploading data to mip maps
Greg Daniel177e6952017-10-12 12:27:11 -040041 // so we don't send any. However, we pretend there is data for the checks below which is
42 // fine since we are never actually using these textures for any work on the gpu.
Robert Phillips4bdd36f2019-06-04 11:03:06 -040043 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -040044 kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -040045 SkColors::kTransparent, mipMapped, renderable, GrProtected::kNo);
Greg Daniel177e6952017-10-12 12:27:11 -040046
Robert Phillipse0070c02017-11-13 12:47:24 -050047 sk_sp<GrTextureProxy> proxy;
Greg Daniel177e6952017-10-12 12:27:11 -040048 sk_sp<SkImage> image;
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040049 if (GrRenderable::kYes == renderable) {
Greg Daniel177e6952017-10-12 12:27:11 -040050 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(
51 context,
52 backendTex,
53 kTopLeft_GrSurfaceOrigin,
54 0,
Greg Danielfaa095e2017-12-19 13:15:02 -050055 kRGBA_8888_SkColorType,
Greg Daniel177e6952017-10-12 12:27:11 -040056 nullptr,
57 nullptr);
58
59 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
Robert Phillipse0070c02017-11-13 12:47:24 -050060 proxy = device->accessRenderTargetContext()->asTextureProxyRef();
Greg Daniel177e6952017-10-12 12:27:11 -040061 } else {
62 image = SkImage::MakeFromTexture(context, backendTex,
63 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -050064 kRGBA_8888_SkColorType,
65 kPremul_SkAlphaType, nullptr,
66 nullptr, nullptr);
Robert Phillips6603a172019-03-05 12:35:44 -050067 proxy = as_IB(image)->asTextureProxyRef(context);
Greg Daniel177e6952017-10-12 12:27:11 -040068 }
69 REPORTER_ASSERT(reporter, proxy);
70 if (!proxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -040071 context->deleteBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040072 return;
73 }
74
Brian Salomonfd98c2c2018-07-31 17:25:29 -040075 REPORTER_ASSERT(reporter, proxy->isInstantiated());
Greg Daniel177e6952017-10-12 12:27:11 -040076
Brian Salomonfd98c2c2018-07-31 17:25:29 -040077 GrTexture* texture = proxy->peekTexture();
Greg Daniel177e6952017-10-12 12:27:11 -040078 REPORTER_ASSERT(reporter, texture);
79 if (!texture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -040080 context->deleteBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040081 return;
82 }
83
84 if (GrMipMapped::kYes == mipMapped) {
Greg Daniele252f082017-10-23 16:05:23 -040085 REPORTER_ASSERT(reporter, GrMipMapped::kYes == texture->texturePriv().mipMapped());
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040086 if (GrRenderable::kYes == renderable) {
Greg Daniel177e6952017-10-12 12:27:11 -040087 REPORTER_ASSERT(reporter, texture->texturePriv().mipMapsAreDirty());
88 } else {
89 REPORTER_ASSERT(reporter, !texture->texturePriv().mipMapsAreDirty());
90 }
91 } else {
Greg Daniele252f082017-10-23 16:05:23 -040092 REPORTER_ASSERT(reporter, GrMipMapped::kNo == texture->texturePriv().mipMapped());
Greg Daniel177e6952017-10-12 12:27:11 -040093 }
Robert Phillips5c7a25b2019-05-20 08:38:07 -040094 context->deleteBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040095 }
96 }
97}
98
Greg Daniel261b8aa2017-10-23 09:37:36 -040099// Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator
100// based on if we will use mips in the draw and the mip status of the GrBackendTexture.
101DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400102 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500103 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400104 return;
105 }
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500106
Greg Daniel261b8aa2017-10-23 09:37:36 -0400107 for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
108 for (auto willUseMips : {false, true}) {
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400109 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400110 kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400111 SkColors::kTransparent, mipMapped, GrRenderable::kNo, GrProtected::kNo);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400112
Greg Daniel261b8aa2017-10-23 09:37:36 -0400113 sk_sp<SkImage> image = SkImage::MakeFromTexture(context, backendTex,
114 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -0500115 kRGBA_8888_SkColorType,
116 kPremul_SkAlphaType, nullptr,
117 nullptr, nullptr);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400118
119 GrTextureProxy* proxy = as_IB(image)->peekProxy();
120 REPORTER_ASSERT(reporter, proxy);
121 if (!proxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400122 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400123 return;
124 }
125
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400126 REPORTER_ASSERT(reporter, proxy->isInstantiated());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400127
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400128 sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400129 REPORTER_ASSERT(reporter, texture);
130 if (!texture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400131 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400132 return;
133 }
134
135 std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make(
Brian Osman052ef692018-03-27 09:56:31 -0400136 texture, kTopLeft_GrSurfaceOrigin, nullptr, kRGBA_8888_SkColorType,
137 kPremul_SkAlphaType, nullptr);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400138 REPORTER_ASSERT(reporter, imageGen);
139 if (!imageGen) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400140 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400141 return;
142 }
143
144 SkIPoint origin = SkIPoint::Make(0,0);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400145 SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
146 kPremul_SkAlphaType);
147 sk_sp<GrTextureProxy> genProxy = imageGen->generateTexture(context, imageInfo,
Brian Osmanc87cfb62018-07-11 09:08:46 -0400148 origin, willUseMips);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400149
150 REPORTER_ASSERT(reporter, genProxy);
151 if (!genProxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400152 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400153 return;
154 }
155
Greg Daniele728f672018-01-17 10:52:04 -0500156 if (GrSurfaceProxy::LazyState::kNot != genProxy->lazyInstantiationState()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500157 genProxy->priv().doLazyInstantiation(context->priv().resourceProvider());
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400158 } else if (!genProxy->isInstantiated()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500159 genProxy->instantiate(context->priv().resourceProvider());
Greg Daniele728f672018-01-17 10:52:04 -0500160 }
161
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400162 REPORTER_ASSERT(reporter, genProxy->isInstantiated());
163 if (!genProxy->isInstantiated()) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400164 context->deleteBackendTexture(backendTex);
Greg Danielbddcc952018-01-24 13:22:24 -0500165 return;
166 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400167
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400168 GrTexture* genTexture = genProxy->peekTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400169 REPORTER_ASSERT(reporter, genTexture);
170 if (!genTexture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400171 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400172 return;
173 }
174
Robert Phillipsb67821d2017-12-13 15:00:45 -0500175 GrBackendTexture genBackendTex = genTexture->getBackendTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400176
Greg Danielbdf12ad2018-10-12 09:31:11 -0400177 if (GrBackendApi::kOpenGL == genBackendTex.backend()) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400178 GrGLTextureInfo genTexInfo;
179 GrGLTextureInfo origTexInfo;
180 if (genBackendTex.getGLTextureInfo(&genTexInfo) &&
181 backendTex.getGLTextureInfo(&origTexInfo)) {
182 if (willUseMips && GrMipMapped::kNo == mipMapped) {
183 // We did a copy so the texture IDs should be different
184 REPORTER_ASSERT(reporter, origTexInfo.fID != genTexInfo.fID);
185 } else {
186 REPORTER_ASSERT(reporter, origTexInfo.fID == genTexInfo.fID);
187 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400188 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400189 ERRORF(reporter, "Failed to get GrGLTextureInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400190 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400191#ifdef SK_VULKAN
Greg Danielbdf12ad2018-10-12 09:31:11 -0400192 } else if (GrBackendApi::kVulkan == genBackendTex.backend()) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400193 GrVkImageInfo genImageInfo;
194 GrVkImageInfo origImageInfo;
195 if (genBackendTex.getVkImageInfo(&genImageInfo) &&
196 backendTex.getVkImageInfo(&origImageInfo)) {
197 if (willUseMips && GrMipMapped::kNo == mipMapped) {
198 // We did a copy so the texture IDs should be different
199 REPORTER_ASSERT(reporter, origImageInfo.fImage != genImageInfo.fImage);
200 } else {
201 REPORTER_ASSERT(reporter, origImageInfo.fImage == genImageInfo.fImage);
202 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400203 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400204 ERRORF(reporter, "Failed to get GrVkImageInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400205 }
206#endif
Jim Van Verth9896a0d2019-04-10 15:11:12 -0400207#ifdef SK_METAL
208 } else if (GrBackendApi::kMetal == genBackendTex.backend()) {
209 GrMtlTextureInfo genImageInfo;
210 GrMtlTextureInfo origImageInfo;
211 if (genBackendTex.getMtlTextureInfo(&genImageInfo) &&
212 backendTex.getMtlTextureInfo(&origImageInfo)) {
213 if (willUseMips && GrMipMapped::kNo == mipMapped) {
214 // We did a copy so the texture IDs should be different
215 REPORTER_ASSERT(reporter, origImageInfo.fTexture != genImageInfo.fTexture);
216 } else {
217 REPORTER_ASSERT(reporter, origImageInfo.fTexture == genImageInfo.fTexture);
218 }
219 } else {
220 ERRORF(reporter, "Failed to get GrMtlTextureInfo");
221 }
222#endif
Greg Daniel261b8aa2017-10-23 09:37:36 -0400223 } else {
224 REPORTER_ASSERT(reporter, false);
225 }
226
227 // Must make sure the uses of the backend texture have finished (we possibly have a
Greg Daniel26b50a42018-03-08 09:49:58 -0500228 // queued up copy) before we delete the backend texture.
229 context->flush();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400230
Robert Phillips9b16f812019-05-17 10:01:21 -0400231 context->priv().getGpu()->testingOnly_flushGpuAndSync();
232
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400233 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400234 }
235 }
236}
237
Greg Daniel45d63032017-10-30 13:41:26 -0400238// Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the
239// resource we took the snapshot of.
240DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) {
241 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500242 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel45d63032017-10-30 13:41:26 -0400243 return;
244 }
245
Robert Phillips9da87e02019-02-04 13:26:26 -0500246 auto resourceProvider = context->priv().resourceProvider();
Robert Phillips6be756b2018-01-16 15:07:54 -0500247
Greg Daniel45d63032017-10-30 13:41:26 -0400248 for (auto willUseMips : {false, true}) {
249 for (auto isWrapped : {false, true}) {
250 GrMipMapped mipMapped = willUseMips ? GrMipMapped::kYes : GrMipMapped::kNo;
251 sk_sp<SkSurface> surface;
Robert Phillips4bdd36f2019-06-04 11:03:06 -0400252 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -0400253 kSize, kSize, kRGBA_8888_SkColorType,
Robert Phillipsda2e67a2019-07-01 15:04:06 -0400254 SkColors::kTransparent, mipMapped, GrRenderable::kYes, GrProtected::kNo);
Greg Daniel45d63032017-10-30 13:41:26 -0400255 if (isWrapped) {
Greg Daniel45d63032017-10-30 13:41:26 -0400256 surface = SkSurface::MakeFromBackendTexture(context,
257 backendTex,
258 kTopLeft_GrSurfaceOrigin,
259 0,
Greg Danielfaa095e2017-12-19 13:15:02 -0500260 kRGBA_8888_SkColorType,
Greg Daniel45d63032017-10-30 13:41:26 -0400261 nullptr,
262 nullptr);
263 } else {
264 SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
265 kPremul_SkAlphaType);
266 surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
267 kTopLeft_GrSurfaceOrigin, nullptr,
268 willUseMips);
269 }
270 REPORTER_ASSERT(reporter, surface);
271 if (!surface) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400272 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400273 }
274 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
275 GrTextureProxy* texProxy = device->accessRenderTargetContext()->asTextureProxy();
276 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
277
Robert Phillips6be756b2018-01-16 15:07:54 -0500278 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400279 GrTexture* texture = texProxy->peekTexture();
Greg Daniel45d63032017-10-30 13:41:26 -0400280 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
281
282 sk_sp<SkImage> image = surface->makeImageSnapshot();
283 REPORTER_ASSERT(reporter, image);
284 if (!image) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400285 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400286 }
287 texProxy = as_IB(image)->peekProxy();
288 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
289
Robert Phillips6be756b2018-01-16 15:07:54 -0500290 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400291 texture = texProxy->peekTexture();
Greg Daniel45d63032017-10-30 13:41:26 -0400292 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
293
294 // Must flush the context to make sure all the cmds (copies, etc.) from above are sent
295 // to the gpu before we delete the backendHandle.
296 context->flush();
Robert Phillips9b16f812019-05-17 10:01:21 -0400297 context->priv().getGpu()->testingOnly_flushGpuAndSync();
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400298 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400299 }
300 }
301}
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400302
303// Test that we don't create a mip mapped texture if the size is 1x1 even if the filter mode is set
304// to use mips. This test passes by not crashing or hitting asserts in code.
305DEF_GPUTEST_FOR_RENDERING_CONTEXTS(Gr1x1TextureMipMappedTest, reporter, ctxInfo) {
306 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500307 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400308 return;
309 }
310
311 // Make surface to draw into
312 SkImageInfo info = SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType);
313 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info);
314
315 // Make 1x1 raster bitmap
316 SkBitmap bmp;
317 bmp.allocN32Pixels(1, 1);
318 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(bmp.getPixels());
319 *pixel = 0;
320
321 sk_sp<SkImage> bmpImage = SkImage::MakeFromBitmap(bmp);
322
323 // Make sure we scale so we don't optimize out the use of mips.
324 surface->getCanvas()->scale(0.5f, 0.5f);
325
326 SkPaint paint;
327 // This should upload the image to a non mipped GrTextureProxy.
328 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
329 surface->flush();
330
331 // Now set the filter quality to high so we use mip maps. We should find the non mipped texture
332 // in the cache for the SkImage. Since the texture is 1x1 we should just use that texture
333 // instead of trying to do a copy to a mipped texture.
334 paint.setFilterQuality(kHigh_SkFilterQuality);
335 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
336 surface->flush();
337}
338