blob: 15718c70420360545a62e76071e2c712e9d15333 [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"
15#include "include/private/GrTextureProxy.h"
16#include "src/gpu/GrBackendTextureImageGenerator.h"
17#include "src/gpu/GrContextPriv.h"
18#include "src/gpu/GrGpu.h"
19#include "src/gpu/GrRenderTargetContext.h"
20#include "src/gpu/GrSemaphore.h"
21#include "src/gpu/GrSurfaceProxyPriv.h"
22#include "src/gpu/GrTexturePriv.h"
23#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 Phillips5c7a25b2019-05-20 08:38:07 -040043 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040044 kSize, kSize, kRGBA_8888_SkColorType, mipMapped, renderable);
Greg Daniel177e6952017-10-12 12:27:11 -040045
Robert Phillipse0070c02017-11-13 12:47:24 -050046 sk_sp<GrTextureProxy> proxy;
Greg Daniel177e6952017-10-12 12:27:11 -040047 sk_sp<SkImage> image;
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040048 if (GrRenderable::kYes == renderable) {
Greg Daniel177e6952017-10-12 12:27:11 -040049 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(
50 context,
51 backendTex,
52 kTopLeft_GrSurfaceOrigin,
53 0,
Greg Danielfaa095e2017-12-19 13:15:02 -050054 kRGBA_8888_SkColorType,
Greg Daniel177e6952017-10-12 12:27:11 -040055 nullptr,
56 nullptr);
57
58 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
Robert Phillipse0070c02017-11-13 12:47:24 -050059 proxy = device->accessRenderTargetContext()->asTextureProxyRef();
Greg Daniel177e6952017-10-12 12:27:11 -040060 } else {
61 image = SkImage::MakeFromTexture(context, backendTex,
62 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -050063 kRGBA_8888_SkColorType,
64 kPremul_SkAlphaType, nullptr,
65 nullptr, nullptr);
Robert Phillips6603a172019-03-05 12:35:44 -050066 proxy = as_IB(image)->asTextureProxyRef(context);
Greg Daniel177e6952017-10-12 12:27:11 -040067 }
68 REPORTER_ASSERT(reporter, proxy);
69 if (!proxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -040070 context->deleteBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040071 return;
72 }
73
Brian Salomonfd98c2c2018-07-31 17:25:29 -040074 REPORTER_ASSERT(reporter, proxy->isInstantiated());
Greg Daniel177e6952017-10-12 12:27:11 -040075
Brian Salomonfd98c2c2018-07-31 17:25:29 -040076 GrTexture* texture = proxy->peekTexture();
Greg Daniel177e6952017-10-12 12:27:11 -040077 REPORTER_ASSERT(reporter, texture);
78 if (!texture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -040079 context->deleteBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040080 return;
81 }
82
83 if (GrMipMapped::kYes == mipMapped) {
Greg Daniele252f082017-10-23 16:05:23 -040084 REPORTER_ASSERT(reporter, GrMipMapped::kYes == texture->texturePriv().mipMapped());
Robert Phillips9dbcdcc2019-05-13 10:40:06 -040085 if (GrRenderable::kYes == renderable) {
Greg Daniel177e6952017-10-12 12:27:11 -040086 REPORTER_ASSERT(reporter, texture->texturePriv().mipMapsAreDirty());
87 } else {
88 REPORTER_ASSERT(reporter, !texture->texturePriv().mipMapsAreDirty());
89 }
90 } else {
Greg Daniele252f082017-10-23 16:05:23 -040091 REPORTER_ASSERT(reporter, GrMipMapped::kNo == texture->texturePriv().mipMapped());
Greg Daniel177e6952017-10-12 12:27:11 -040092 }
Robert Phillips5c7a25b2019-05-20 08:38:07 -040093 context->deleteBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040094 }
95 }
96}
97
Greg Daniel261b8aa2017-10-23 09:37:36 -040098// Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator
99// based on if we will use mips in the draw and the mip status of the GrBackendTexture.
100DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400101 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500102 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400103 return;
104 }
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500105
Greg Daniel261b8aa2017-10-23 09:37:36 -0400106 for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
107 for (auto willUseMips : {false, true}) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400108 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips9dbcdcc2019-05-13 10:40:06 -0400109 kSize, kSize, kRGBA_8888_SkColorType, mipMapped, GrRenderable::kNo);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400110
Greg Daniel261b8aa2017-10-23 09:37:36 -0400111 sk_sp<SkImage> image = SkImage::MakeFromTexture(context, backendTex,
112 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -0500113 kRGBA_8888_SkColorType,
114 kPremul_SkAlphaType, nullptr,
115 nullptr, nullptr);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400116
117 GrTextureProxy* proxy = as_IB(image)->peekProxy();
118 REPORTER_ASSERT(reporter, proxy);
119 if (!proxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400120 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400121 return;
122 }
123
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400124 REPORTER_ASSERT(reporter, proxy->isInstantiated());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400125
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400126 sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400127 REPORTER_ASSERT(reporter, texture);
128 if (!texture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400129 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400130 return;
131 }
132
133 std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make(
Brian Osman052ef692018-03-27 09:56:31 -0400134 texture, kTopLeft_GrSurfaceOrigin, nullptr, kRGBA_8888_SkColorType,
135 kPremul_SkAlphaType, nullptr);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400136 REPORTER_ASSERT(reporter, imageGen);
137 if (!imageGen) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400138 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400139 return;
140 }
141
142 SkIPoint origin = SkIPoint::Make(0,0);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400143 SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
144 kPremul_SkAlphaType);
145 sk_sp<GrTextureProxy> genProxy = imageGen->generateTexture(context, imageInfo,
Brian Osmanc87cfb62018-07-11 09:08:46 -0400146 origin, willUseMips);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400147
148 REPORTER_ASSERT(reporter, genProxy);
149 if (!genProxy) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400150 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400151 return;
152 }
153
Greg Daniele728f672018-01-17 10:52:04 -0500154 if (GrSurfaceProxy::LazyState::kNot != genProxy->lazyInstantiationState()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500155 genProxy->priv().doLazyInstantiation(context->priv().resourceProvider());
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400156 } else if (!genProxy->isInstantiated()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500157 genProxy->instantiate(context->priv().resourceProvider());
Greg Daniele728f672018-01-17 10:52:04 -0500158 }
159
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400160 REPORTER_ASSERT(reporter, genProxy->isInstantiated());
161 if (!genProxy->isInstantiated()) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400162 context->deleteBackendTexture(backendTex);
Greg Danielbddcc952018-01-24 13:22:24 -0500163 return;
164 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400165
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400166 GrTexture* genTexture = genProxy->peekTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400167 REPORTER_ASSERT(reporter, genTexture);
168 if (!genTexture) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400169 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400170 return;
171 }
172
Robert Phillipsb67821d2017-12-13 15:00:45 -0500173 GrBackendTexture genBackendTex = genTexture->getBackendTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400174
Greg Danielbdf12ad2018-10-12 09:31:11 -0400175 if (GrBackendApi::kOpenGL == genBackendTex.backend()) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400176 GrGLTextureInfo genTexInfo;
177 GrGLTextureInfo origTexInfo;
178 if (genBackendTex.getGLTextureInfo(&genTexInfo) &&
179 backendTex.getGLTextureInfo(&origTexInfo)) {
180 if (willUseMips && GrMipMapped::kNo == mipMapped) {
181 // We did a copy so the texture IDs should be different
182 REPORTER_ASSERT(reporter, origTexInfo.fID != genTexInfo.fID);
183 } else {
184 REPORTER_ASSERT(reporter, origTexInfo.fID == genTexInfo.fID);
185 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400186 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400187 ERRORF(reporter, "Failed to get GrGLTextureInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400188 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400189#ifdef SK_VULKAN
Greg Danielbdf12ad2018-10-12 09:31:11 -0400190 } else if (GrBackendApi::kVulkan == genBackendTex.backend()) {
Greg Daniel52e16d92018-04-10 09:34:07 -0400191 GrVkImageInfo genImageInfo;
192 GrVkImageInfo origImageInfo;
193 if (genBackendTex.getVkImageInfo(&genImageInfo) &&
194 backendTex.getVkImageInfo(&origImageInfo)) {
195 if (willUseMips && GrMipMapped::kNo == mipMapped) {
196 // We did a copy so the texture IDs should be different
197 REPORTER_ASSERT(reporter, origImageInfo.fImage != genImageInfo.fImage);
198 } else {
199 REPORTER_ASSERT(reporter, origImageInfo.fImage == genImageInfo.fImage);
200 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400201 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400202 ERRORF(reporter, "Failed to get GrVkImageInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400203 }
204#endif
Jim Van Verth9896a0d2019-04-10 15:11:12 -0400205#ifdef SK_METAL
206 } else if (GrBackendApi::kMetal == genBackendTex.backend()) {
207 GrMtlTextureInfo genImageInfo;
208 GrMtlTextureInfo origImageInfo;
209 if (genBackendTex.getMtlTextureInfo(&genImageInfo) &&
210 backendTex.getMtlTextureInfo(&origImageInfo)) {
211 if (willUseMips && GrMipMapped::kNo == mipMapped) {
212 // We did a copy so the texture IDs should be different
213 REPORTER_ASSERT(reporter, origImageInfo.fTexture != genImageInfo.fTexture);
214 } else {
215 REPORTER_ASSERT(reporter, origImageInfo.fTexture == genImageInfo.fTexture);
216 }
217 } else {
218 ERRORF(reporter, "Failed to get GrMtlTextureInfo");
219 }
220#endif
Greg Daniel261b8aa2017-10-23 09:37:36 -0400221 } else {
222 REPORTER_ASSERT(reporter, false);
223 }
224
225 // Must make sure the uses of the backend texture have finished (we possibly have a
Greg Daniel26b50a42018-03-08 09:49:58 -0500226 // queued up copy) before we delete the backend texture.
227 context->flush();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400228
Robert Phillips9b16f812019-05-17 10:01:21 -0400229 context->priv().getGpu()->testingOnly_flushGpuAndSync();
230
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400231 context->deleteBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400232 }
233 }
234}
235
Greg Daniel45d63032017-10-30 13:41:26 -0400236// Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the
237// resource we took the snapshot of.
238DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) {
239 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500240 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel45d63032017-10-30 13:41:26 -0400241 return;
242 }
243
Robert Phillips9da87e02019-02-04 13:26:26 -0500244 auto resourceProvider = context->priv().resourceProvider();
Robert Phillips6be756b2018-01-16 15:07:54 -0500245
Greg Daniel45d63032017-10-30 13:41:26 -0400246 for (auto willUseMips : {false, true}) {
247 for (auto isWrapped : {false, true}) {
248 GrMipMapped mipMapped = willUseMips ? GrMipMapped::kYes : GrMipMapped::kNo;
249 sk_sp<SkSurface> surface;
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400250 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips9dbcdcc2019-05-13 10:40:06 -0400251 kSize, kSize, kRGBA_8888_SkColorType, mipMapped, GrRenderable::kYes);
Greg Daniel45d63032017-10-30 13:41:26 -0400252 if (isWrapped) {
Greg Daniel45d63032017-10-30 13:41:26 -0400253 surface = SkSurface::MakeFromBackendTexture(context,
254 backendTex,
255 kTopLeft_GrSurfaceOrigin,
256 0,
Greg Danielfaa095e2017-12-19 13:15:02 -0500257 kRGBA_8888_SkColorType,
Greg Daniel45d63032017-10-30 13:41:26 -0400258 nullptr,
259 nullptr);
260 } else {
261 SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
262 kPremul_SkAlphaType);
263 surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
264 kTopLeft_GrSurfaceOrigin, nullptr,
265 willUseMips);
266 }
267 REPORTER_ASSERT(reporter, surface);
268 if (!surface) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400269 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400270 }
271 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
272 GrTextureProxy* texProxy = device->accessRenderTargetContext()->asTextureProxy();
273 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
274
Robert Phillips6be756b2018-01-16 15:07:54 -0500275 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400276 GrTexture* texture = texProxy->peekTexture();
Greg Daniel45d63032017-10-30 13:41:26 -0400277 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
278
279 sk_sp<SkImage> image = surface->makeImageSnapshot();
280 REPORTER_ASSERT(reporter, image);
281 if (!image) {
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400282 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400283 }
284 texProxy = as_IB(image)->peekProxy();
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 texture = texProxy->peekTexture();
Greg Daniel45d63032017-10-30 13:41:26 -0400289 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
290
291 // Must flush the context to make sure all the cmds (copies, etc.) from above are sent
292 // to the gpu before we delete the backendHandle.
293 context->flush();
Robert Phillips9b16f812019-05-17 10:01:21 -0400294 context->priv().getGpu()->testingOnly_flushGpuAndSync();
Robert Phillips5c7a25b2019-05-20 08:38:07 -0400295 context->deleteBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400296 }
297 }
298}
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400299
300// Test that we don't create a mip mapped texture if the size is 1x1 even if the filter mode is set
301// to use mips. This test passes by not crashing or hitting asserts in code.
302DEF_GPUTEST_FOR_RENDERING_CONTEXTS(Gr1x1TextureMipMappedTest, reporter, ctxInfo) {
303 GrContext* context = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500304 if (!context->priv().caps()->mipMapSupport()) {
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400305 return;
306 }
307
308 // Make surface to draw into
309 SkImageInfo info = SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType);
310 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info);
311
312 // Make 1x1 raster bitmap
313 SkBitmap bmp;
314 bmp.allocN32Pixels(1, 1);
315 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(bmp.getPixels());
316 *pixel = 0;
317
318 sk_sp<SkImage> bmpImage = SkImage::MakeFromBitmap(bmp);
319
320 // Make sure we scale so we don't optimize out the use of mips.
321 surface->getCanvas()->scale(0.5f, 0.5f);
322
323 SkPaint paint;
324 // This should upload the image to a non mipped GrTextureProxy.
325 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
326 surface->flush();
327
328 // Now set the filter quality to high so we use mip maps. We should find the non mipped texture
329 // in the cache for the SkImage. Since the texture is 1x1 we should just use that texture
330 // instead of trying to do a copy to a mipped texture.
331 paint.setFilterQuality(kHigh_SkFilterQuality);
332 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
333 surface->flush();
334}
335