blob: 525788ccb00aae7d0b195951b1fb946bc48c2807 [file] [log] [blame]
bsalomon@google.com686bcb82013-04-09 15:04:12 +00001/*
2 * Copyright 2013 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
Brian Salomon614c1a82018-12-19 15:42:06 -05008#include <set>
Mike Kleinc0bd9f92019-04-23 12:05:21 -05009#include "include/core/SkSurface.h"
Robert Phillips6d344c32020-07-06 10:56:46 -040010#include "include/gpu/GrDirectContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/core/SkAutoPixmapStorage.h"
Brian Salomon8f7d9532020-12-23 09:16:59 -050012#include "src/core/SkCanvasPriv.h"
Robert Phillips99dead92020-01-27 16:11:57 -050013#include "src/core/SkCompressedDataUtils.h"
Greg Daniel01f278c2020-06-12 16:58:17 -040014#include "src/gpu/GrBackendUtils.h"
Adlai Hollera0693042020-10-14 11:23:11 -040015#include "src/gpu/GrDirectContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/gpu/GrGpu.h"
Brian Salomonf2ebdd92019-09-30 12:15:30 -040017#include "src/gpu/GrImageInfo.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/gpu/GrProxyProvider.h"
Brian Salomon201cdbb2019-08-14 17:00:30 -040019#include "src/gpu/GrRenderTarget.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/gpu/GrResourceProvider.h"
Robert Phillips1a2e7de2021-07-29 11:23:48 -040021#include "src/gpu/GrSurfaceContext.h"
Greg Daniel456f9b52020-03-05 19:14:18 +000022#include "src/gpu/GrTexture.h"
Brian Salomon27c42022021-04-28 12:39:21 -040023#include "src/gpu/SkGr.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "tests/Test.h"
Robert Phillipsee5fd132019-05-07 13:29:22 -040025#include "tests/TestUtils.h"
Brian Salomon72050802020-10-12 20:45:06 -040026#include "tools/gpu/BackendTextureImageFactory.h"
27#include "tools/gpu/ManagedBackendTexture.h"
bsalomon@google.com686bcb82013-04-09 15:04:12 +000028
bsalomona2c23232014-11-25 07:41:12 -080029// Tests that GrSurface::asTexture(), GrSurface::asRenderTarget(), and static upcasting of texture
30// and render targets to GrSurface all work as expected.
Brian Osmanfbe24062019-04-03 16:04:45 +000031DEF_GPUTEST_FOR_MOCK_CONTEXT(GrSurface, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -040032 auto context = ctxInfo.directContext();
Robert Phillips9da87e02019-02-04 13:26:26 -050033 auto resourceProvider = context->priv().resourceProvider();
Robert Phillips6be756b2018-01-16 15:07:54 -050034
Brian Salomona56a7462020-02-07 14:17:25 -050035 static constexpr SkISize kDesc = {256, 256};
Brian Salomon4eb38b72019-08-05 12:58:39 -040036 auto format = context->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
37 GrRenderable::kYes);
Brian Salomona90382f2019-09-17 09:01:56 -040038 sk_sp<GrSurface> texRT1 =
Brian Salomon7e67dca2020-07-21 09:27:25 -040039 resourceProvider->createTexture(kDesc, format, GrRenderable::kYes, 1, GrMipmapped::kNo,
Brian Salomona90382f2019-09-17 09:01:56 -040040 SkBudgeted::kNo, GrProtected::kNo);
bsalomona2c23232014-11-25 07:41:12 -080041
Robert Phillipse78b7252017-04-06 07:59:41 -040042 REPORTER_ASSERT(reporter, texRT1.get() == texRT1->asRenderTarget());
43 REPORTER_ASSERT(reporter, texRT1.get() == texRT1->asTexture());
kkinnunen15302832015-12-01 04:35:26 -080044 REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT1->asRenderTarget()) ==
45 texRT1->asTexture());
46 REPORTER_ASSERT(reporter, texRT1->asRenderTarget() ==
47 static_cast<GrSurface*>(texRT1->asTexture()));
48 REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT1->asRenderTarget()) ==
49 static_cast<GrSurface*>(texRT1->asTexture()));
bsalomona2c23232014-11-25 07:41:12 -080050
Brian Salomona90382f2019-09-17 09:01:56 -040051 sk_sp<GrTexture> tex1 =
Brian Salomon7e67dca2020-07-21 09:27:25 -040052 resourceProvider->createTexture(kDesc, format, GrRenderable::kNo, 1, GrMipmapped::kNo,
Brian Salomona90382f2019-09-17 09:01:56 -040053 SkBudgeted::kNo, GrProtected::kNo);
kkinnunen15302832015-12-01 04:35:26 -080054 REPORTER_ASSERT(reporter, nullptr == tex1->asRenderTarget());
Robert Phillipse78b7252017-04-06 07:59:41 -040055 REPORTER_ASSERT(reporter, tex1.get() == tex1->asTexture());
56 REPORTER_ASSERT(reporter, static_cast<GrSurface*>(tex1.get()) == tex1->asTexture());
bsalomon@google.com686bcb82013-04-09 15:04:12 +000057
Robert Phillips4bdd36f2019-06-04 11:03:06 -040058 GrBackendTexture backendTex = context->createBackendTexture(
Robert Phillips80626792019-06-04 07:16:10 -040059 256, 256, kRGBA_8888_SkColorType,
Brian Salomon7e67dca2020-07-21 09:27:25 -040060 SkColors::kTransparent, GrMipmapped::kNo, GrRenderable::kNo, GrProtected::kNo);
bsalomon091f60c2015-11-10 11:54:56 -080061
Brian Salomonaa6ca0a2019-01-24 16:03:07 -050062 sk_sp<GrSurface> texRT2 = resourceProvider->wrapRenderableBackendTexture(
Brian Salomon8a78e9c2020-03-27 10:42:15 -040063 backendTex, 1, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo);
Greg Daniel7ef28f32017-04-20 16:41:55 +000064
bungeman6bd52842016-10-27 09:30:08 -070065 REPORTER_ASSERT(reporter, texRT2.get() == texRT2->asRenderTarget());
66 REPORTER_ASSERT(reporter, texRT2.get() == texRT2->asTexture());
kkinnunen15302832015-12-01 04:35:26 -080067 REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT2->asRenderTarget()) ==
68 texRT2->asTexture());
69 REPORTER_ASSERT(reporter, texRT2->asRenderTarget() ==
70 static_cast<GrSurface*>(texRT2->asTexture()));
71 REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT2->asRenderTarget()) ==
72 static_cast<GrSurface*>(texRT2->asTexture()));
bsalomon@google.com686bcb82013-04-09 15:04:12 +000073
Robert Phillips5c7a25b2019-05-20 08:38:07 -040074 context->deleteBackendTexture(backendTex);
bsalomon@google.com686bcb82013-04-09 15:04:12 +000075}
76
Greg Daniel7bfc9132019-08-14 14:23:53 -040077// This test checks that the isFormatTexturable and isFormatRenderable are
Robert Phillipsb7b7e5f2017-05-22 13:23:19 -040078// consistent with createTexture's result.
79DEF_GPUTEST_FOR_ALL_CONTEXTS(GrSurfaceRenderability, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -040080 auto context = ctxInfo.directContext();
Robert Phillips9da87e02019-02-04 13:26:26 -050081 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
82 GrResourceProvider* resourceProvider = context->priv().resourceProvider();
83 const GrCaps* caps = context->priv().caps();
Robert Phillipsb7b7e5f2017-05-22 13:23:19 -040084
Brian Salomon4eb38b72019-08-05 12:58:39 -040085 // TODO: Should only need format here but need to determine compression type from format
86 // without config.
Robert Phillips48257d72019-12-16 14:20:53 -050087 auto createTexture = [](SkISize dimensions, GrColorType colorType,
Brian Salomon4eb38b72019-08-05 12:58:39 -040088 const GrBackendFormat& format, GrRenderable renderable,
Brian Salomonbb8dde82019-06-27 10:52:13 -040089 GrResourceProvider* rp) -> sk_sp<GrTexture> {
Greg Daniel01f278c2020-06-12 16:58:17 -040090 SkImage::CompressionType compression = GrBackendFormatToCompressionType(format);
Robert Phillipsd6df7b52019-12-13 11:17:46 -050091 if (compression != SkImage::CompressionType::kNone) {
Brian Salomonbb8dde82019-06-27 10:52:13 -040092 if (renderable == GrRenderable::kYes) {
93 return nullptr;
94 }
Robert Phillips99dead92020-01-27 16:11:57 -050095 auto size = SkCompressedDataSize(compression, dimensions, nullptr, false);
Brian Salomonbb8dde82019-06-27 10:52:13 -040096 auto data = SkData::MakeUninitialized(size);
97 SkColor4f color = {0, 0, 0, 0};
Brian Salomon7e67dca2020-07-21 09:27:25 -040098 GrFillInCompressedData(compression, dimensions, GrMipmapped::kNo,
Robert Phillips48257d72019-12-16 14:20:53 -050099 (char*)data->writable_data(), color);
Robert Phillipse4720c62020-01-14 14:33:24 -0500100 return rp->createCompressedTexture(dimensions, format, SkBudgeted::kNo,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400101 GrMipmapped::kNo, GrProtected::kNo, data.get());
Brian Salomonbb8dde82019-06-27 10:52:13 -0400102 } else {
Brian Salomon7e67dca2020-07-21 09:27:25 -0400103 return rp->createTexture(dimensions, format, renderable, 1, GrMipmapped::kNo,
Brian Salomona56a7462020-02-07 14:17:25 -0500104 SkBudgeted::kNo, GrProtected::kNo);
Brian Salomonbb8dde82019-06-27 10:52:13 -0400105 }
106 };
Robert Phillipsb7b7e5f2017-05-22 13:23:19 -0400107
Brian Salomona56a7462020-02-07 14:17:25 -0500108 static constexpr SkISize kDims = {64, 64};
Robert Phillipsa5e78be2019-07-09 12:34:38 -0400109
Robert Phillipsffe27292019-08-01 10:08:07 -0400110 const std::vector<GrCaps::TestFormatColorTypeCombination>& combos =
John Stilesbd3ffa42020-07-30 20:24:57 -0400111 caps->getTestingCombinations();
Robert Phillips0902c982019-07-16 07:47:56 -0400112
John Stilesbd3ffa42020-07-30 20:24:57 -0400113 for (const GrCaps::TestFormatColorTypeCombination& combo : combos) {
Robert Phillipsffe27292019-08-01 10:08:07 -0400114
115 SkASSERT(combo.fColorType != GrColorType::kUnknown);
116 SkASSERT(combo.fFormat.isValid());
117
118 // Right now Vulkan has two backend formats that support ABGR_4444 (R4G4B4A4 and B4G4R4A4).
119 // Until we can create textures directly from the backend format this yields some
120 // ambiguity in what is actually supported and which textures can be created.
121 if (ctxInfo.backend() == kVulkan_GrBackend && combo.fColorType == GrColorType::kABGR_4444) {
Robert Phillips0902c982019-07-16 07:47:56 -0400122 continue;
123 }
124
Greg Daniel3a365112020-02-14 10:47:18 -0500125 // Check if 'isFormatTexturable' agrees with 'createTexture' and that the mipmap
126 // support check is working
127 {
128 bool isCompressed = caps->isFormatCompressed(combo.fFormat);
Brian Salomon469046c2020-03-30 14:21:04 -0400129 bool isTexturable = caps->isFormatTexturable(combo.fFormat);
Robert Phillipsffe27292019-08-01 10:08:07 -0400130
Greg Daniel3a365112020-02-14 10:47:18 -0500131 sk_sp<GrSurface> tex = createTexture(kDims, combo.fColorType, combo.fFormat,
132 GrRenderable::kNo, resourceProvider);
133 REPORTER_ASSERT(reporter, SkToBool(tex) == isTexturable,
134 "ct:%s format:%s, tex:%d, isTexturable:%d",
135 GrColorTypeToStr(combo.fColorType), combo.fFormat.toStr().c_str(),
136 SkToBool(tex), isTexturable);
Robert Phillipsffe27292019-08-01 10:08:07 -0400137
Greg Daniel3a365112020-02-14 10:47:18 -0500138 // Check that the lack of mipmap support blocks the creation of mipmapped
139 // proxies
Brian Salomon69100f02020-07-21 10:49:25 -0400140 bool expectedMipMapability = isTexturable && caps->mipmapSupport() && !isCompressed;
Robert Phillipsffe27292019-08-01 10:08:07 -0400141
Greg Daniel3a365112020-02-14 10:47:18 -0500142 sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(
Brian Salomon7e67dca2020-07-21 09:27:25 -0400143 combo.fFormat, kDims, GrRenderable::kNo, 1, GrMipmapped::kYes,
Greg Daniel3a365112020-02-14 10:47:18 -0500144 SkBackingFit::kExact, SkBudgeted::kNo, GrProtected::kNo);
145 REPORTER_ASSERT(reporter, SkToBool(proxy.get()) == expectedMipMapability,
146 "ct:%s format:%s, tex:%d, expectedMipMapability:%d",
147 GrColorTypeToStr(combo.fColorType), combo.fFormat.toStr().c_str(),
148 SkToBool(proxy.get()), expectedMipMapability);
149 }
150
151 // Check if 'isFormatAsColorTypeRenderable' agrees with 'createTexture' (w/o MSAA)
152 {
153 bool isRenderable = caps->isFormatRenderable(combo.fFormat, 1);
154
155 sk_sp<GrSurface> tex = resourceProvider->createTexture(
Brian Salomon7e67dca2020-07-21 09:27:25 -0400156 kDims, combo.fFormat, GrRenderable::kYes, 1, GrMipmapped::kNo, SkBudgeted::kNo,
Greg Daniel3a365112020-02-14 10:47:18 -0500157 GrProtected::kNo);
158 REPORTER_ASSERT(reporter, SkToBool(tex) == isRenderable,
159 "ct:%s format:%s, tex:%d, isRenderable:%d",
160 GrColorTypeToStr(combo.fColorType), combo.fFormat.toStr().c_str(),
161 SkToBool(tex), isRenderable);
162 }
163
164 // Check if 'isFormatAsColorTypeRenderable' agrees with 'createTexture' w/ MSAA
165 {
166 bool isRenderable = caps->isFormatRenderable(combo.fFormat, 2);
167
168 sk_sp<GrSurface> tex = resourceProvider->createTexture(
Brian Salomon7e67dca2020-07-21 09:27:25 -0400169 kDims, combo.fFormat, GrRenderable::kYes, 2, GrMipmapped::kNo, SkBudgeted::kNo,
Greg Daniel3a365112020-02-14 10:47:18 -0500170 GrProtected::kNo);
171 REPORTER_ASSERT(reporter, SkToBool(tex) == isRenderable,
172 "ct:%s format:%s, tex:%d, isRenderable:%d",
173 GrColorTypeToStr(combo.fColorType), combo.fFormat.toStr().c_str(),
174 SkToBool(tex), isRenderable);
Robert Phillipsb7b7e5f2017-05-22 13:23:19 -0400175 }
176 }
177}
Robert Phillipsb7b7e5f2017-05-22 13:23:19 -0400178
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500179#include "src/gpu/GrDrawingManager.h"
Greg Danielf91aeb22019-06-18 09:58:02 -0400180#include "src/gpu/GrSurfaceProxy.h"
Brian Salomond17b4a62017-05-23 16:53:47 -0400181
Robert Phillipsffe27292019-08-01 10:08:07 -0400182// For each context, set it to always clear the textures and then run through all the
183// supported formats checking that the textures are actually cleared
Brian Salomona3e29962019-07-16 11:52:08 -0400184DEF_GPUTEST(InitialTextureClear, reporter, baseOptions) {
185 GrContextOptions options = baseOptions;
186 options.fClearAllTextures = true;
Robert Phillipsd3442842019-08-02 12:26:22 -0400187
Brian Salomond17b4a62017-05-23 16:53:47 -0400188 static constexpr int kSize = 100;
Robert Phillipsd3442842019-08-02 12:26:22 -0400189 static constexpr SkColor kClearColor = 0xABABABAB;
Robert Phillipsffe27292019-08-01 10:08:07 -0400190
191 const SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
192 kPremul_SkAlphaType);
193
Robert Phillipsd3442842019-08-02 12:26:22 -0400194 SkAutoPixmapStorage readback;
195 readback.alloc(info);
196
Brian Salomona56a7462020-02-07 14:17:25 -0500197 SkISize desc;
Robert Phillipsffe27292019-08-01 10:08:07 -0400198 desc.fWidth = desc.fHeight = kSize;
199
Brian Salomona3e29962019-07-16 11:52:08 -0400200 for (int ct = 0; ct < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++ct) {
201 sk_gpu_test::GrContextFactory factory(options);
202 auto contextType = static_cast<sk_gpu_test::GrContextFactory::ContextType>(ct);
203 if (!sk_gpu_test::GrContextFactory::IsRenderingContext(contextType)) {
Brian Salomond17b4a62017-05-23 16:53:47 -0400204 continue;
205 }
Adlai Hollerc95b5892020-08-11 12:02:22 -0400206 auto dContext = factory.get(contextType);
207 if (!dContext) {
Brian Salomona3e29962019-07-16 11:52:08 -0400208 continue;
209 }
Brian Salomona3e29962019-07-16 11:52:08 -0400210
Adlai Hollerc95b5892020-08-11 12:02:22 -0400211 GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
212 const GrCaps* caps = dContext->priv().caps();
Brian Salomona3e29962019-07-16 11:52:08 -0400213
Robert Phillipsffe27292019-08-01 10:08:07 -0400214 const std::vector<GrCaps::TestFormatColorTypeCombination>& combos =
John Stilesbd3ffa42020-07-30 20:24:57 -0400215 caps->getTestingCombinations();
Robert Phillipsffe27292019-08-01 10:08:07 -0400216
John Stilesbd3ffa42020-07-30 20:24:57 -0400217 for (const GrCaps::TestFormatColorTypeCombination& combo : combos) {
Robert Phillipsffe27292019-08-01 10:08:07 -0400218
219 SkASSERT(combo.fColorType != GrColorType::kUnknown);
220 SkASSERT(combo.fFormat.isValid());
221
Brian Salomon469046c2020-03-30 14:21:04 -0400222 if (!caps->isFormatTexturable(combo.fFormat)) {
Brian Salomond17b4a62017-05-23 16:53:47 -0400223 continue;
224 }
Robert Phillipsffe27292019-08-01 10:08:07 -0400225
Brian Salomon614cdab2019-09-26 11:04:28 -0400226 auto checkColor = [reporter](const GrCaps::TestFormatColorTypeCombination& combo,
227 uint32_t readColor) {
228 // We expect that if there is no alpha in the src color type and we read it to a
229 // color type with alpha that we will get one for alpha rather than zero. We used to
230 // require this but the Intel Iris 6100 on Win 10 test bot doesn't put one in the
231 // alpha channel when reading back from GL_RG16 or GL_RG16F. So now we allow either.
Brian Salomon2f23ae62020-03-26 16:17:56 -0400232 uint32_t channels = GrColorTypeChannelFlags(combo.fColorType);
233 bool allowAlphaOne = !(channels & kAlpha_SkColorChannelFlag);
Brian Salomon614cdab2019-09-26 11:04:28 -0400234 if (allowAlphaOne) {
235 if (readColor != 0x00000000 && readColor != 0xFF000000) {
236 ERRORF(reporter,
237 "Failed on ct %s format %s 0x%08x is not 0x00000000 or 0xFF000000",
238 GrColorTypeToStr(combo.fColorType), combo.fFormat.toStr().c_str(),
239 readColor);
240 return false;
241 }
242 } else {
243 if (readColor) {
244 ERRORF(reporter, "Failed on ct %s format %s 0x%08x != 0x00000000",
245 GrColorTypeToStr(combo.fColorType), combo.fFormat.toStr().c_str(),
246 readColor);
247 return false;
248 }
249 }
250 return true;
251 };
Robert Phillipsffe27292019-08-01 10:08:07 -0400252
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400253 for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
Robert Phillipsffe27292019-08-01 10:08:07 -0400254 if (renderable == GrRenderable::kYes &&
Greg Daniel900583a2019-08-06 12:05:31 -0400255 !caps->isFormatAsColorTypeRenderable(combo.fColorType, combo.fFormat)) {
Brian Salomona3e29962019-07-16 11:52:08 -0400256 continue;
257 }
Robert Phillipsffe27292019-08-01 10:08:07 -0400258
259 for (auto fit : {SkBackingFit::kApprox, SkBackingFit::kExact}) {
260
261 // Does directly allocating a texture clear it?
262 {
Chris Daltond004e0b2018-09-27 09:28:03 -0600263 auto proxy = proxyProvider->testingOnly_createInstantiatedProxy(
Brian Salomondf1bd6d2020-03-26 20:37:01 -0400264 {kSize, kSize}, combo.fFormat, renderable, 1, fit, SkBudgeted::kYes,
265 GrProtected::kNo);
Robert Phillipsffe27292019-08-01 10:08:07 -0400266 if (proxy) {
Greg Daniel3912a4b2020-01-14 09:56:04 -0500267 GrSwizzle swizzle = caps->getReadSwizzle(combo.fFormat,
268 combo.fColorType);
269 GrSurfaceProxyView view(std::move(proxy), kTopLeft_GrSurfaceOrigin,
270 swizzle);
Brian Salomon14f99fc2020-12-07 12:19:47 -0500271 GrColorInfo info(combo.fColorType, kPremul_SkAlphaType, nullptr);
Robert Phillips33bf2b52021-08-02 11:14:38 -0400272 auto texCtx = dContext->priv().makeSC(std::move(view), info);
Robert Phillipsffe27292019-08-01 10:08:07 -0400273
Robert Phillipsd3442842019-08-02 12:26:22 -0400274 readback.erase(kClearColor);
Brian Salomondd4087d2020-12-23 20:36:44 -0500275 if (texCtx->readPixels(dContext, readback, {0, 0})) {
Robert Phillipsffe27292019-08-01 10:08:07 -0400276 for (int i = 0; i < kSize * kSize; ++i) {
Brian Salomon614cdab2019-09-26 11:04:28 -0400277 if (!checkColor(combo, readback.addr32()[i])) {
Robert Phillipsffe27292019-08-01 10:08:07 -0400278 break;
279 }
280 }
281 }
282 }
283
Michael Ludwig9d1cc052021-06-09 20:49:48 -0400284 dContext->priv().getResourceCache()->purgeUnlockedResources();
Robert Phillipsffe27292019-08-01 10:08:07 -0400285 }
286
287 // Try creating the texture as a deferred proxy.
288 {
Robert Phillips1a2e7de2021-07-29 11:23:48 -0400289 GrImageInfo info(combo.fColorType,
290 GrColorTypeHasAlpha(combo.fColorType)
291 ? kPremul_SkAlphaType
292 : kOpaque_SkAlphaType,
293 nullptr,
294 {desc.fHeight, desc.fHeight});
295
296 auto sc = GrSurfaceContext::Make(dContext,
297 info,
298 combo.fFormat,
299 fit,
300 kTopLeft_GrSurfaceOrigin,
301 renderable);
302 if (!sc) {
Greg Daniel90f28ec2017-09-25 12:26:58 -0400303 continue;
304 }
Robert Phillipsffe27292019-08-01 10:08:07 -0400305
Robert Phillipsd3442842019-08-02 12:26:22 -0400306 readback.erase(kClearColor);
Robert Phillips1a2e7de2021-07-29 11:23:48 -0400307 if (sc->readPixels(dContext, readback, {0, 0})) {
Greg Daniel90f28ec2017-09-25 12:26:58 -0400308 for (int i = 0; i < kSize * kSize; ++i) {
Brian Salomon614cdab2019-09-26 11:04:28 -0400309 if (!checkColor(combo, readback.addr32()[i])) {
Greg Daniel90f28ec2017-09-25 12:26:58 -0400310 break;
Brian Salomond17b4a62017-05-23 16:53:47 -0400311 }
312 }
Brian Salomond17b4a62017-05-23 16:53:47 -0400313 }
Michael Ludwig9d1cc052021-06-09 20:49:48 -0400314 dContext->priv().getResourceCache()->purgeUnlockedResources();
Greg Daniel90f28ec2017-09-25 12:26:58 -0400315 }
Brian Salomond17b4a62017-05-23 16:53:47 -0400316 }
317 }
318 }
319 }
320}
Brian Salomonc67c31c2018-12-06 10:00:03 -0500321
322DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadOnlyTexture, reporter, context_info) {
Robert Phillipscb1adb42019-06-10 15:09:34 -0400323 auto fillPixels = [](SkPixmap* p, const std::function<uint32_t(int x, int y)>& f) {
Brian Salomonc67c31c2018-12-06 10:00:03 -0500324 for (int y = 0; y < p->height(); ++y) {
325 for (int x = 0; x < p->width(); ++x) {
326 *p->writable_addr32(x, y) = f(x, y);
327 }
328 }
329 };
330
331 auto comparePixels = [](const SkPixmap& p1, const SkPixmap& p2, skiatest::Reporter* reporter) {
332 SkASSERT(p1.info() == p2.info());
333 for (int y = 0; y < p1.height(); ++y) {
334 for (int x = 0; x < p1.width(); ++x) {
335 REPORTER_ASSERT(reporter, p1.getColor(x, y) == p2.getColor(x, y));
336 if (p1.getColor(x, y) != p2.getColor(x, y)) {
337 return;
338 }
339 }
340 }
341 };
342
343 static constexpr int kSize = 100;
Robert Phillips4d87b2b2019-07-23 13:44:16 -0400344 SkImageInfo ii = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
345 SkAutoPixmapStorage srcPixmap;
346 srcPixmap.alloc(ii);
347 fillPixels(&srcPixmap,
Robert Phillipscb1adb42019-06-10 15:09:34 -0400348 [](int x, int y) {
349 return (0xFFU << 24) | (x << 16) | (y << 8) | uint8_t((x * y) & 0xFF);
350 });
Brian Salomonc67c31c2018-12-06 10:00:03 -0500351
Adlai Hollerc95b5892020-08-11 12:02:22 -0400352 auto dContext = context_info.directContext();
353 GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
Brian Salomonc67c31c2018-12-06 10:00:03 -0500354
355 // We test both kRW in addition to kRead mostly to ensure that the calls are structured such
356 // that they'd succeed if the texture wasn't kRead. We want to be sure we're failing with
357 // kRead for the right reason.
358 for (auto ioType : {kRead_GrIOType, kRW_GrIOType}) {
Brian Salomon72050802020-10-12 20:45:06 -0400359 auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithData(
Brian Salomonb5f880a2020-12-07 11:30:16 -0500360 dContext, srcPixmap, kTopLeft_GrSurfaceOrigin, GrRenderable::kNo, GrProtected::kNo);
Brian Salomon88d7e622020-11-05 11:11:20 -0500361 if (!mbet) {
362 ERRORF(reporter, "Could not make texture.");
363 return;
364 }
Brian Salomon72050802020-10-12 20:45:06 -0400365 auto proxy = proxyProvider->wrapBackendTexture(mbet->texture(), kBorrow_GrWrapOwnership,
366 GrWrapCacheable::kNo, ioType,
367 mbet->refCountedCallback());
Adlai Hollerc95b5892020-08-11 12:02:22 -0400368 GrSwizzle swizzle = dContext->priv().caps()->getReadSwizzle(proxy->backendFormat(),
369 GrColorType::kRGBA_8888);
Greg Daniel3912a4b2020-01-14 09:56:04 -0500370 GrSurfaceProxyView view(proxy, kTopLeft_GrSurfaceOrigin, swizzle);
Robert Phillips33bf2b52021-08-02 11:14:38 -0400371 auto surfContext = dContext->priv().makeSC(std::move(view), ii.colorInfo());
Brian Salomonc67c31c2018-12-06 10:00:03 -0500372 // Read pixels should work with a read-only texture.
Robert Phillips4d87b2b2019-07-23 13:44:16 -0400373 {
374 SkAutoPixmapStorage read;
375 read.alloc(srcPixmap.info());
Brian Salomondd4087d2020-12-23 20:36:44 -0500376 auto readResult = surfContext->readPixels(dContext, read, {0, 0});
Robert Phillips4d87b2b2019-07-23 13:44:16 -0400377 REPORTER_ASSERT(reporter, readResult);
378 if (readResult) {
379 comparePixels(srcPixmap, read, reporter);
380 }
Brian Salomonc67c31c2018-12-06 10:00:03 -0500381 }
382
383 // Write pixels should not work with a read-only texture.
384 SkAutoPixmapStorage write;
Robert Phillips4d87b2b2019-07-23 13:44:16 -0400385 write.alloc(srcPixmap.info());
386 fillPixels(&write, [&srcPixmap](int x, int y) { return ~*srcPixmap.addr32(); });
Brian Salomondd4087d2020-12-23 20:36:44 -0500387 auto writeResult = surfContext->writePixels(dContext, write, {0, 0});
Brian Salomonc67c31c2018-12-06 10:00:03 -0500388 REPORTER_ASSERT(reporter, writeResult == (ioType == kRW_GrIOType));
389 // Try the low level write.
Adlai Hollerc95b5892020-08-11 12:02:22 -0400390 dContext->flushAndSubmit();
391 auto gpuWriteResult = dContext->priv().getGpu()->writePixels(
Brian Salomone2078f12021-05-24 12:40:46 -0400392 proxy->peekTexture(),
393 SkIRect::MakeWH(kSize, kSize),
394 GrColorType::kRGBA_8888,
395 GrColorType::kRGBA_8888,
396 write.addr32(),
397 kSize*GrColorTypeBytesPerPixel(GrColorType::kRGBA_8888));
Brian Salomonc67c31c2018-12-06 10:00:03 -0500398 REPORTER_ASSERT(reporter, gpuWriteResult == (ioType == kRW_GrIOType));
399
Greg Daniel6f5441a2020-01-28 17:02:49 -0500400 SkBitmap copySrcBitmap;
401 copySrcBitmap.installPixels(write);
402 copySrcBitmap.setImmutable();
403
Brian Salomon27c42022021-04-28 12:39:21 -0400404 auto copySrc = std::get<0>(GrMakeUncachedBitmapProxyView(dContext, copySrcBitmap));
Greg Daniel6f5441a2020-01-28 17:02:49 -0500405
Brian Salomon27c42022021-04-28 12:39:21 -0400406 REPORTER_ASSERT(reporter, copySrc);
Brian Salomon982127b2021-01-21 10:43:35 -0500407 auto copyResult = surfContext->testCopy(copySrc.refProxy());
Brian Salomonc67c31c2018-12-06 10:00:03 -0500408 REPORTER_ASSERT(reporter, copyResult == (ioType == kRW_GrIOType));
409 // Try the low level copy.
Adlai Hollerc95b5892020-08-11 12:02:22 -0400410 dContext->flushAndSubmit();
411 auto gpuCopyResult = dContext->priv().getGpu()->copySurface(
Greg Danielcc104db2020-02-03 14:17:08 -0500412 proxy->peekSurface(), copySrc.proxy()->peekSurface(), SkIRect::MakeWH(kSize, kSize),
Greg Daniel46cfbc62019-06-07 11:43:30 -0400413 {0, 0});
Brian Salomonc67c31c2018-12-06 10:00:03 -0500414 REPORTER_ASSERT(reporter, gpuCopyResult == (ioType == kRW_GrIOType));
415
416 // Mip regen should not work with a read only texture.
Adlai Hollerc95b5892020-08-11 12:02:22 -0400417 if (dContext->priv().caps()->mipmapSupport()) {
Brian Salomon72050802020-10-12 20:45:06 -0400418 mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(dContext,
419 kSize,
420 kSize,
421 kRGBA_8888_SkColorType,
422 GrMipmapped::kYes,
423 GrRenderable::kNo,
424 GrProtected::kNo);
425 proxy = proxyProvider->wrapBackendTexture(mbet->texture(), kBorrow_GrWrapOwnership,
426 GrWrapCacheable::kNo, ioType,
427 mbet->refCountedCallback());
Adlai Hollerc95b5892020-08-11 12:02:22 -0400428 dContext->flushAndSubmit();
Brian Salomon4cfae3b2020-07-23 10:33:24 -0400429 proxy->peekTexture()->markMipmapsDirty(); // avoids assert in GrGpu.
Brian Salomonc67c31c2018-12-06 10:00:03 -0500430 auto regenResult =
Adlai Hollerc95b5892020-08-11 12:02:22 -0400431 dContext->priv().getGpu()->regenerateMipMapLevels(proxy->peekTexture());
Brian Salomonc67c31c2018-12-06 10:00:03 -0500432 REPORTER_ASSERT(reporter, regenResult == (ioType == kRW_GrIOType));
433 }
434 }
435}