blob: d4571d1a944c1e3198b2708791332eabb619a12f [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
8#include "SkTypes.h"
9
Greg Daniel177e6952017-10-12 12:27:11 -040010#include "GrBackendSurface.h"
Greg Daniel261b8aa2017-10-23 09:37:36 -040011#include "GrBackendTextureImageGenerator.h"
Greg Daniel177e6952017-10-12 12:27:11 -040012#include "GrContext.h"
13#include "GrContextPriv.h"
14#include "GrGpu.h"
15#include "GrRenderTargetContext.h"
Greg Daniel261b8aa2017-10-23 09:37:36 -040016#include "GrSemaphore.h"
Greg Daniel177e6952017-10-12 12:27:11 -040017#include "GrSurfaceProxyPriv.h"
18#include "GrTest.h"
19#include "GrTexturePriv.h"
20#include "GrTextureProxy.h"
21#include "SkCanvas.h"
22#include "SkImage_Base.h"
23#include "SkGpuDevice.h"
Greg Daniel261b8aa2017-10-23 09:37:36 -040024#include "SkPoint.h"
Greg Daniel177e6952017-10-12 12:27:11 -040025#include "SkSurface.h"
26#include "SkSurface_Gpu.h"
27#include "Test.h"
28
Greg Daniel45d63032017-10-30 13:41:26 -040029static constexpr int kSize = 8;
30
Greg Daniel177e6952017-10-12 12:27:11 -040031// Test that the correct mip map states are on the GrTextures when wrapping GrBackendTextures in
32// SkImages and SkSurfaces
33DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest, reporter, ctxInfo) {
34 GrContext* context = ctxInfo.grContext();
Brian Salomonc7fe0f72018-05-11 10:14:21 -040035 if (!context->contextPriv().caps()->mipMapSupport()) {
Greg Daniel261b8aa2017-10-23 09:37:36 -040036 return;
37 }
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050038 GrGpu* gpu = context->contextPriv().getGpu();
39
Greg Daniel177e6952017-10-12 12:27:11 -040040 for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
41 for (auto isRT : {false, true}) {
42 // CreateTestingOnlyBackendTexture currently doesn't support uploading data to mip maps
43 // so we don't send any. However, we pretend there is data for the checks below which is
44 // fine since we are never actually using these textures for any work on the gpu.
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050045 GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
Robert Phillips57e08282017-11-16 14:59:48 -050046 nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig, isRT, mipMapped);
Greg Daniel177e6952017-10-12 12:27:11 -040047
Robert Phillipse0070c02017-11-13 12:47:24 -050048 sk_sp<GrTextureProxy> proxy;
Greg Daniel177e6952017-10-12 12:27:11 -040049 sk_sp<SkImage> image;
50 if (isRT) {
51 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(
52 context,
53 backendTex,
54 kTopLeft_GrSurfaceOrigin,
55 0,
Greg Danielfaa095e2017-12-19 13:15:02 -050056 kRGBA_8888_SkColorType,
Greg Daniel177e6952017-10-12 12:27:11 -040057 nullptr,
58 nullptr);
59
60 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
Robert Phillipse0070c02017-11-13 12:47:24 -050061 proxy = device->accessRenderTargetContext()->asTextureProxyRef();
Greg Daniel177e6952017-10-12 12:27:11 -040062 } else {
63 image = SkImage::MakeFromTexture(context, backendTex,
64 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -050065 kRGBA_8888_SkColorType,
66 kPremul_SkAlphaType, nullptr,
67 nullptr, nullptr);
Robert Phillipse0070c02017-11-13 12:47:24 -050068 proxy = as_IB(image)->asTextureProxyRef();
Greg Daniel177e6952017-10-12 12:27:11 -040069 }
70 REPORTER_ASSERT(reporter, proxy);
71 if (!proxy) {
Brian Salomon26102cb2018-03-09 09:33:19 -050072 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040073 return;
74 }
75
Brian Salomonfd98c2c2018-07-31 17:25:29 -040076 REPORTER_ASSERT(reporter, proxy->isInstantiated());
Greg Daniel177e6952017-10-12 12:27:11 -040077
Brian Salomonfd98c2c2018-07-31 17:25:29 -040078 GrTexture* texture = proxy->peekTexture();
Greg Daniel177e6952017-10-12 12:27:11 -040079 REPORTER_ASSERT(reporter, texture);
80 if (!texture) {
Brian Salomon26102cb2018-03-09 09:33:19 -050081 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040082 return;
83 }
84
85 if (GrMipMapped::kYes == mipMapped) {
Greg Daniele252f082017-10-23 16:05:23 -040086 REPORTER_ASSERT(reporter, GrMipMapped::kYes == texture->texturePriv().mipMapped());
Greg Daniel177e6952017-10-12 12:27:11 -040087 if (isRT) {
88 REPORTER_ASSERT(reporter, texture->texturePriv().mipMapsAreDirty());
89 } else {
90 REPORTER_ASSERT(reporter, !texture->texturePriv().mipMapsAreDirty());
91 }
92 } else {
Greg Daniele252f082017-10-23 16:05:23 -040093 REPORTER_ASSERT(reporter, GrMipMapped::kNo == texture->texturePriv().mipMapped());
Greg Daniel177e6952017-10-12 12:27:11 -040094 }
Brian Salomon26102cb2018-03-09 09:33:19 -050095 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Daniel177e6952017-10-12 12:27:11 -040096 }
97 }
98}
99
Greg Daniel261b8aa2017-10-23 09:37:36 -0400100// Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator
101// based on if we will use mips in the draw and the mip status of the GrBackendTexture.
102DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400103 GrContext* context = ctxInfo.grContext();
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400104 if (!context->contextPriv().caps()->mipMapSupport()) {
Greg Daniel261b8aa2017-10-23 09:37:36 -0400105 return;
106 }
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500107 GrGpu* gpu = context->contextPriv().getGpu();
108
Greg Daniel261b8aa2017-10-23 09:37:36 -0400109 for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
110 for (auto willUseMips : {false, true}) {
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500111 GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
Greg Daniel261b8aa2017-10-23 09:37:36 -0400112 nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig, false, mipMapped);
113
Greg Daniel261b8aa2017-10-23 09:37:36 -0400114 sk_sp<SkImage> image = SkImage::MakeFromTexture(context, backendTex,
115 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -0500116 kRGBA_8888_SkColorType,
117 kPremul_SkAlphaType, nullptr,
118 nullptr, nullptr);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400119
120 GrTextureProxy* proxy = as_IB(image)->peekProxy();
121 REPORTER_ASSERT(reporter, proxy);
122 if (!proxy) {
Brian Salomon26102cb2018-03-09 09:33:19 -0500123 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400124 return;
125 }
126
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400127 REPORTER_ASSERT(reporter, proxy->isInstantiated());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400128
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400129 sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
Greg Daniel261b8aa2017-10-23 09:37:36 -0400130 REPORTER_ASSERT(reporter, texture);
131 if (!texture) {
Brian Salomon26102cb2018-03-09 09:33:19 -0500132 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400133 return;
134 }
135
136 std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make(
Brian Osman052ef692018-03-27 09:56:31 -0400137 texture, kTopLeft_GrSurfaceOrigin, nullptr, kRGBA_8888_SkColorType,
138 kPremul_SkAlphaType, nullptr);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400139 REPORTER_ASSERT(reporter, imageGen);
140 if (!imageGen) {
Brian Salomon26102cb2018-03-09 09:33:19 -0500141 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400142 return;
143 }
144
145 SkIPoint origin = SkIPoint::Make(0,0);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400146 SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
147 kPremul_SkAlphaType);
148 sk_sp<GrTextureProxy> genProxy = imageGen->generateTexture(context, imageInfo,
Brian Osmanc87cfb62018-07-11 09:08:46 -0400149 origin, willUseMips);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400150
151 REPORTER_ASSERT(reporter, genProxy);
152 if (!genProxy) {
Brian Salomon26102cb2018-03-09 09:33:19 -0500153 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400154 return;
155 }
156
Greg Daniele728f672018-01-17 10:52:04 -0500157 if (GrSurfaceProxy::LazyState::kNot != genProxy->lazyInstantiationState()) {
158 genProxy->priv().doLazyInstantiation(context->contextPriv().resourceProvider());
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400159 } else if (!genProxy->isInstantiated()) {
Greg Danielf6f7b672018-02-15 13:06:26 -0500160 genProxy->instantiate(context->contextPriv().resourceProvider());
Greg Daniele728f672018-01-17 10:52:04 -0500161 }
162
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400163 REPORTER_ASSERT(reporter, genProxy->isInstantiated());
164 if (!genProxy->isInstantiated()) {
Brian Salomon26102cb2018-03-09 09:33:19 -0500165 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Danielbddcc952018-01-24 13:22:24 -0500166 return;
167 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400168
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400169 GrTexture* genTexture = genProxy->peekTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400170 REPORTER_ASSERT(reporter, genTexture);
171 if (!genTexture) {
Brian Salomon26102cb2018-03-09 09:33:19 -0500172 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400173 return;
174 }
175
Robert Phillipsb67821d2017-12-13 15:00:45 -0500176 GrBackendTexture genBackendTex = genTexture->getBackendTexture();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400177
Greg Daniel52e16d92018-04-10 09:34:07 -0400178 if (kOpenGL_GrBackend == genBackendTex.backend()) {
179 GrGLTextureInfo genTexInfo;
180 GrGLTextureInfo origTexInfo;
181 if (genBackendTex.getGLTextureInfo(&genTexInfo) &&
182 backendTex.getGLTextureInfo(&origTexInfo)) {
183 if (willUseMips && GrMipMapped::kNo == mipMapped) {
184 // We did a copy so the texture IDs should be different
185 REPORTER_ASSERT(reporter, origTexInfo.fID != genTexInfo.fID);
186 } else {
187 REPORTER_ASSERT(reporter, origTexInfo.fID == genTexInfo.fID);
188 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400189 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400190 ERRORF(reporter, "Failed to get GrGLTextureInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400191 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400192#ifdef SK_VULKAN
Greg Daniel52e16d92018-04-10 09:34:07 -0400193 } else if (kVulkan_GrBackend == genBackendTex.backend()) {
194 GrVkImageInfo genImageInfo;
195 GrVkImageInfo origImageInfo;
196 if (genBackendTex.getVkImageInfo(&genImageInfo) &&
197 backendTex.getVkImageInfo(&origImageInfo)) {
198 if (willUseMips && GrMipMapped::kNo == mipMapped) {
199 // We did a copy so the texture IDs should be different
200 REPORTER_ASSERT(reporter, origImageInfo.fImage != genImageInfo.fImage);
201 } else {
202 REPORTER_ASSERT(reporter, origImageInfo.fImage == genImageInfo.fImage);
203 }
Greg Daniel261b8aa2017-10-23 09:37:36 -0400204 } else {
Greg Daniel52e16d92018-04-10 09:34:07 -0400205 ERRORF(reporter, "Failed to get GrVkImageInfo");
Greg Daniel261b8aa2017-10-23 09:37:36 -0400206 }
207#endif
Greg Daniel261b8aa2017-10-23 09:37:36 -0400208 } else {
209 REPORTER_ASSERT(reporter, false);
210 }
211
212 // Must make sure the uses of the backend texture have finished (we possibly have a
Greg Daniel26b50a42018-03-08 09:49:58 -0500213 // queued up copy) before we delete the backend texture.
214 context->flush();
215 gpu->testingOnly_flushGpuAndSync();
Greg Daniel261b8aa2017-10-23 09:37:36 -0400216
Brian Salomon26102cb2018-03-09 09:33:19 -0500217 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Daniel261b8aa2017-10-23 09:37:36 -0400218 }
219 }
220}
221
Greg Daniel45d63032017-10-30 13:41:26 -0400222// Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the
223// resource we took the snapshot of.
224DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) {
225 GrContext* context = ctxInfo.grContext();
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400226 if (!context->contextPriv().caps()->mipMapSupport()) {
Greg Daniel45d63032017-10-30 13:41:26 -0400227 return;
228 }
229
Robert Phillips6be756b2018-01-16 15:07:54 -0500230 auto resourceProvider = context->contextPriv().resourceProvider();
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500231 GrGpu* gpu = context->contextPriv().getGpu();
Robert Phillips6be756b2018-01-16 15:07:54 -0500232
Greg Daniel45d63032017-10-30 13:41:26 -0400233 for (auto willUseMips : {false, true}) {
234 for (auto isWrapped : {false, true}) {
235 GrMipMapped mipMapped = willUseMips ? GrMipMapped::kYes : GrMipMapped::kNo;
236 sk_sp<SkSurface> surface;
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500237 GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
Robert Phillipsd21b2a52017-12-12 13:01:25 -0500238 nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig, true, mipMapped);
Greg Daniel45d63032017-10-30 13:41:26 -0400239 if (isWrapped) {
Greg Daniel45d63032017-10-30 13:41:26 -0400240 surface = SkSurface::MakeFromBackendTexture(context,
241 backendTex,
242 kTopLeft_GrSurfaceOrigin,
243 0,
Greg Danielfaa095e2017-12-19 13:15:02 -0500244 kRGBA_8888_SkColorType,
Greg Daniel45d63032017-10-30 13:41:26 -0400245 nullptr,
246 nullptr);
247 } else {
248 SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
249 kPremul_SkAlphaType);
250 surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
251 kTopLeft_GrSurfaceOrigin, nullptr,
252 willUseMips);
253 }
254 REPORTER_ASSERT(reporter, surface);
255 if (!surface) {
Brian Salomon26102cb2018-03-09 09:33:19 -0500256 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400257 }
258 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
259 GrTextureProxy* texProxy = device->accessRenderTargetContext()->asTextureProxy();
260 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
261
Robert Phillips6be756b2018-01-16 15:07:54 -0500262 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400263 GrTexture* texture = texProxy->peekTexture();
Greg Daniel45d63032017-10-30 13:41:26 -0400264 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
265
266 sk_sp<SkImage> image = surface->makeImageSnapshot();
267 REPORTER_ASSERT(reporter, image);
268 if (!image) {
Brian Salomon26102cb2018-03-09 09:33:19 -0500269 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400270 }
271 texProxy = as_IB(image)->peekProxy();
272 REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
273
Robert Phillips6be756b2018-01-16 15:07:54 -0500274 texProxy->instantiate(resourceProvider);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400275 texture = texProxy->peekTexture();
Greg Daniel45d63032017-10-30 13:41:26 -0400276 REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
277
278 // Must flush the context to make sure all the cmds (copies, etc.) from above are sent
279 // to the gpu before we delete the backendHandle.
280 context->flush();
Greg Danield2d367d2018-04-16 10:24:45 -0400281 gpu->testingOnly_flushGpuAndSync();
Brian Salomon26102cb2018-03-09 09:33:19 -0500282 gpu->deleteTestingOnlyBackendTexture(backendTex);
Greg Daniel45d63032017-10-30 13:41:26 -0400283 }
284 }
285}
Greg Daniel8e9b4c42018-07-20 10:30:48 -0400286
287// Test that we don't create a mip mapped texture if the size is 1x1 even if the filter mode is set
288// to use mips. This test passes by not crashing or hitting asserts in code.
289DEF_GPUTEST_FOR_RENDERING_CONTEXTS(Gr1x1TextureMipMappedTest, reporter, ctxInfo) {
290 GrContext* context = ctxInfo.grContext();
291 if (!context->contextPriv().caps()->mipMapSupport()) {
292 return;
293 }
294
295 // Make surface to draw into
296 SkImageInfo info = SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType);
297 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info);
298
299 // Make 1x1 raster bitmap
300 SkBitmap bmp;
301 bmp.allocN32Pixels(1, 1);
302 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(bmp.getPixels());
303 *pixel = 0;
304
305 sk_sp<SkImage> bmpImage = SkImage::MakeFromBitmap(bmp);
306
307 // Make sure we scale so we don't optimize out the use of mips.
308 surface->getCanvas()->scale(0.5f, 0.5f);
309
310 SkPaint paint;
311 // This should upload the image to a non mipped GrTextureProxy.
312 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
313 surface->flush();
314
315 // Now set the filter quality to high so we use mip maps. We should find the non mipped texture
316 // in the cache for the SkImage. Since the texture is 1x1 we should just use that texture
317 // instead of trying to do a copy to a mipped texture.
318 paint.setFilterQuality(kHigh_SkFilterQuality);
319 surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
320 surface->flush();
321}
322