• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
8 #include "include/core/SkAlphaType.h"
9 #include "include/core/SkBitmap.h"
10 #include "include/core/SkColor.h"
11 #include "include/core/SkColorSpace.h"
12 #include "include/core/SkColorType.h"
13 #include "include/core/SkData.h"
14 #include "include/core/SkImageInfo.h"
15 #include "include/core/SkPixmap.h"
16 #include "include/core/SkRect.h"
17 #include "include/core/SkRefCnt.h"
18 #include "include/core/SkSamplingOptions.h"
19 #include "include/core/SkSize.h"
20 #include "include/core/SkString.h"
21 #include "include/core/SkTextureCompressionType.h"
22 #include "include/core/SkTypes.h"
23 #include "include/gpu/GpuTypes.h"
24 #include "include/gpu/GrBackendSurface.h"
25 #include "include/gpu/GrContextOptions.h"
26 #include "include/gpu/GrDirectContext.h"
27 #include "include/gpu/GrTypes.h"
28 #include "include/private/base/SkTo.h"
29 #include "include/private/gpu/ganesh/GrTypesPriv.h"
30 #include "src/core/SkAutoPixmapStorage.h"
31 #include "src/core/SkCompressedDataUtils.h"
32 #include "src/gpu/DataUtils.h"
33 #include "src/gpu/SkBackingFit.h"
34 #include "src/gpu/Swizzle.h"
35 #include "src/gpu/ganesh/GrBackendUtils.h"
36 #include "src/gpu/ganesh/GrCaps.h"
37 #include "src/gpu/ganesh/GrColorInfo.h"
38 #include "src/gpu/ganesh/GrDataUtils.h"
39 #include "src/gpu/ganesh/GrDirectContextPriv.h"
40 #include "src/gpu/ganesh/GrGpu.h"
41 #include "src/gpu/ganesh/GrImageInfo.h"
42 #include "src/gpu/ganesh/GrProxyProvider.h"
43 #include "src/gpu/ganesh/GrRenderTarget.h"
44 #include "src/gpu/ganesh/GrResourceCache.h"
45 #include "src/gpu/ganesh/GrResourceProvider.h"
46 #include "src/gpu/ganesh/GrSamplerState.h"
47 #include "src/gpu/ganesh/GrSurface.h"
48 #include "src/gpu/ganesh/GrSurfaceProxy.h"
49 #include "src/gpu/ganesh/GrSurfaceProxyView.h"
50 #include "src/gpu/ganesh/GrTexture.h"
51 #include "src/gpu/ganesh/GrTextureProxy.h"
52 #include "src/gpu/ganesh/SkGr.h"
53 #include "src/gpu/ganesh/SurfaceContext.h"
54 #include "src/gpu/ganesh/TestFormatColorTypeCombination.h"
55 #include "tests/CtsEnforcement.h"
56 #include "tests/Test.h"
57 #include "tools/gpu/ContextType.h"
58 #include "tools/gpu/ManagedBackendTexture.h"
59 
60 #include <cstdint>
61 #include <functional>
62 #include <initializer_list>
63 #include <memory>
64 #include <tuple>
65 #include <utility>
66 #include <vector>
67 
68 // Tests that GrSurface::asTexture(), GrSurface::asRenderTarget(), and static upcasting of texture
69 // and render targets to GrSurface all work as expected.
DEF_GANESH_TEST_FOR_MOCK_CONTEXT(GrSurface,reporter,ctxInfo)70 DEF_GANESH_TEST_FOR_MOCK_CONTEXT(GrSurface, reporter, ctxInfo) {
71     auto context = ctxInfo.directContext();
72     auto resourceProvider = context->priv().resourceProvider();
73 
74     static constexpr SkISize kDesc = {256, 256};
75     auto format = context->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
76                                                                   GrRenderable::kYes);
77     sk_sp<GrSurface> texRT1 = resourceProvider->createTexture(kDesc,
78                                                               format,
79                                                               GrTextureType::k2D,
80                                                               GrRenderable::kYes,
81                                                               1,
82                                                               skgpu::Mipmapped::kNo,
83                                                               skgpu::Budgeted::kNo,
84                                                               GrProtected::kNo,
85                                                               /*label=*/{});
86 
87     REPORTER_ASSERT(reporter, texRT1.get() == texRT1->asRenderTarget());
88     REPORTER_ASSERT(reporter, texRT1.get() == texRT1->asTexture());
89     REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT1->asRenderTarget()) ==
90                     texRT1->asTexture());
91     REPORTER_ASSERT(reporter, texRT1->asRenderTarget() ==
92                     static_cast<GrSurface*>(texRT1->asTexture()));
93     REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT1->asRenderTarget()) ==
94                     static_cast<GrSurface*>(texRT1->asTexture()));
95 
96     sk_sp<GrTexture> tex1 = resourceProvider->createTexture(kDesc,
97                                                             format,
98                                                             GrTextureType::k2D,
99                                                             GrRenderable::kNo,
100                                                             1,
101                                                             skgpu::Mipmapped::kNo,
102                                                             skgpu::Budgeted::kNo,
103                                                             GrProtected::kNo,
104                                                             /*label=*/{});
105     REPORTER_ASSERT(reporter, nullptr == tex1->asRenderTarget());
106     REPORTER_ASSERT(reporter, tex1.get() == tex1->asTexture());
107     REPORTER_ASSERT(reporter, static_cast<GrSurface*>(tex1.get()) == tex1->asTexture());
108 
109     GrBackendTexture backendTex = context->createBackendTexture(256,
110                                                                 256,
111                                                                 kRGBA_8888_SkColorType,
112                                                                 SkColors::kTransparent,
113                                                                 skgpu::Mipmapped::kNo,
114                                                                 GrRenderable::kNo,
115                                                                 GrProtected::kNo);
116 
117     sk_sp<GrSurface> texRT2 = resourceProvider->wrapRenderableBackendTexture(
118             backendTex, 1, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo);
119 
120     REPORTER_ASSERT(reporter, texRT2.get() == texRT2->asRenderTarget());
121     REPORTER_ASSERT(reporter, texRT2.get() == texRT2->asTexture());
122     REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT2->asRenderTarget()) ==
123                     texRT2->asTexture());
124     REPORTER_ASSERT(reporter, texRT2->asRenderTarget() ==
125                     static_cast<GrSurface*>(texRT2->asTexture()));
126     REPORTER_ASSERT(reporter, static_cast<GrSurface*>(texRT2->asRenderTarget()) ==
127                     static_cast<GrSurface*>(texRT2->asTexture()));
128 
129     context->deleteBackendTexture(backendTex);
130 }
131 
132 // This test checks that the isFormatTexturable and isFormatRenderable are
133 // consistent with createTexture's result.
DEF_GANESH_TEST_FOR_ALL_CONTEXTS(GrSurfaceRenderability,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)134 DEF_GANESH_TEST_FOR_ALL_CONTEXTS(GrSurfaceRenderability,
135                                  reporter,
136                                  ctxInfo,
137                                  CtsEnforcement::kApiLevel_T) {
138     auto context = ctxInfo.directContext();
139     GrProxyProvider* proxyProvider = context->priv().proxyProvider();
140     GrResourceProvider* resourceProvider = context->priv().resourceProvider();
141     const GrCaps* caps = context->priv().caps();
142 
143     // TODO: Should only need format here but need to determine compression type from format
144     // without config.
145     auto createTexture = [](SkISize dimensions, GrColorType colorType,
146                             const GrBackendFormat& format, GrRenderable renderable,
147                             GrResourceProvider* rp) -> sk_sp<GrTexture> {
148         SkTextureCompressionType compression = GrBackendFormatToCompressionType(format);
149         if (compression != SkTextureCompressionType::kNone) {
150             if (renderable == GrRenderable::kYes) {
151                 return nullptr;
152             }
153             auto size = SkCompressedDataSize(compression, dimensions, nullptr, false);
154             auto data = SkData::MakeUninitialized(size);
155             SkColor4f color = {0, 0, 0, 0};
156             skgpu::FillInCompressedData(compression,
157                                         dimensions,
158                                         skgpu::Mipmapped::kNo,
159                                         (char*)data->writable_data(),
160                                         color);
161             return rp->createCompressedTexture(dimensions,
162                                                format,
163                                                skgpu::Budgeted::kNo,
164                                                skgpu::Mipmapped::kNo,
165                                                GrProtected::kNo,
166                                                data.get(),
167                                                /*label=*/{});
168         } else {
169             return rp->createTexture(dimensions,
170                                      format,
171                                      GrTextureType::k2D,
172                                      renderable,
173                                      1,
174                                      skgpu::Mipmapped::kNo,
175                                      skgpu::Budgeted::kNo,
176                                      GrProtected::kNo,
177                                      /*label=*/{});
178         }
179     };
180 
181     static constexpr SkISize kDims = {64, 64};
182 
183     const std::vector<GrTest::TestFormatColorTypeCombination>& combos =
184             caps->getTestingCombinations();
185 
186     for (const GrTest::TestFormatColorTypeCombination& combo : combos) {
187 
188         SkASSERT(combo.fColorType != GrColorType::kUnknown);
189         SkASSERT(combo.fFormat.isValid());
190 
191         // Right now Vulkan has two backend formats that support ABGR_4444 (R4G4B4A4 and B4G4R4A4).
192         // Until we can create textures directly from the backend format this yields some
193         // ambiguity in what is actually supported and which textures can be created.
194         if (ctxInfo.backend() == kVulkan_GrBackend && combo.fColorType == GrColorType::kABGR_4444) {
195             continue;
196         }
197 
198         // Check if 'isFormatTexturable' agrees with 'createTexture' and that the mipmap
199         // support check is working
200         {
201             bool isCompressed = caps->isFormatCompressed(combo.fFormat);
202             bool isTexturable = caps->isFormatTexturable(combo.fFormat, GrTextureType::k2D);
203 
204             sk_sp<GrSurface> tex = createTexture(kDims, combo.fColorType, combo.fFormat,
205                                                  GrRenderable::kNo, resourceProvider);
206             REPORTER_ASSERT(reporter, SkToBool(tex) == isTexturable,
207                             "ct:%s format:%s, tex:%d, isTexturable:%d",
208                             GrColorTypeToStr(combo.fColorType), combo.fFormat.toStr().c_str(),
209                             SkToBool(tex), isTexturable);
210 
211             // Check that the lack of mipmap support blocks the creation of mipmapped
212             // proxies
213             bool expectedMipMapability = isTexturable && caps->mipmapSupport() && !isCompressed;
214 
215             sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(combo.fFormat,
216                                                                      kDims,
217                                                                      GrRenderable::kNo,
218                                                                      1,
219                                                                      skgpu::Mipmapped::kYes,
220                                                                      SkBackingFit::kExact,
221                                                                      skgpu::Budgeted::kNo,
222                                                                      GrProtected::kNo,
223                                                                      /*label=*/{});
224             REPORTER_ASSERT(reporter, SkToBool(proxy.get()) == expectedMipMapability,
225                             "ct:%s format:%s, tex:%d, expectedMipMapability:%d",
226                             GrColorTypeToStr(combo.fColorType), combo.fFormat.toStr().c_str(),
227                             SkToBool(proxy.get()), expectedMipMapability);
228         }
229 
230         // Check if 'isFormatAsColorTypeRenderable' agrees with 'createTexture' (w/o MSAA)
231         {
232             bool isRenderable = caps->isFormatRenderable(combo.fFormat, 1);
233 
234             sk_sp<GrSurface> tex = resourceProvider->createTexture(kDims,
235                                                                    combo.fFormat,
236                                                                    GrTextureType::k2D,
237                                                                    GrRenderable::kYes,
238                                                                    1,
239                                                                    skgpu::Mipmapped::kNo,
240                                                                    skgpu::Budgeted::kNo,
241                                                                    GrProtected::kNo,
242                                                                    /*label=*/{});
243             REPORTER_ASSERT(reporter, SkToBool(tex) == isRenderable,
244                             "ct:%s format:%s, tex:%d, isRenderable:%d",
245                             GrColorTypeToStr(combo.fColorType), combo.fFormat.toStr().c_str(),
246                             SkToBool(tex), isRenderable);
247         }
248 
249         // Check if 'isFormatAsColorTypeRenderable' agrees with 'createTexture' w/ MSAA
250         {
251             bool isRenderable = caps->isFormatRenderable(combo.fFormat, 2);
252 
253             sk_sp<GrSurface> tex = resourceProvider->createTexture(kDims,
254                                                                    combo.fFormat,
255                                                                    GrTextureType::k2D,
256                                                                    GrRenderable::kYes,
257                                                                    2,
258                                                                    skgpu::Mipmapped::kNo,
259                                                                    skgpu::Budgeted::kNo,
260                                                                    GrProtected::kNo,
261                                                                    /*label=*/{});
262             REPORTER_ASSERT(reporter, SkToBool(tex) == isRenderable,
263                             "ct:%s format:%s, tex:%d, isRenderable:%d",
264                             GrColorTypeToStr(combo.fColorType), combo.fFormat.toStr().c_str(),
265                             SkToBool(tex), isRenderable);
266         }
267     }
268 }
269 
270 // For each context, set it to always clear the textures and then run through all the
271 // supported formats checking that the textures are actually cleared
DEF_GANESH_TEST(InitialTextureClear,reporter,baseOptions,CtsEnforcement::kApiLevel_T)272 DEF_GANESH_TEST(InitialTextureClear, reporter, baseOptions, CtsEnforcement::kApiLevel_T) {
273     GrContextOptions options = baseOptions;
274     options.fClearAllTextures = true;
275 
276     static constexpr int kSize = 100;
277     static constexpr SkColor kClearColor = 0xABABABAB;
278 
279     const SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
280                                                     kPremul_SkAlphaType);
281 
282     SkAutoPixmapStorage readback;
283     readback.alloc(imageInfo);
284 
285     SkISize desc;
286     desc.fWidth = desc.fHeight = kSize;
287 
288     for (int ct = 0; ct < skgpu::kContextTypeCount; ++ct) {
289         sk_gpu_test::GrContextFactory factory(options);
290         auto contextType = static_cast<skgpu::ContextType>(ct);
291         if (!skgpu::IsRenderingContext(contextType)) {
292             continue;
293         }
294         auto dContext = factory.get(contextType);
295         if (!dContext) {
296             continue;
297         }
298 
299         GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
300         const GrCaps* caps = dContext->priv().caps();
301 
302         const std::vector<GrTest::TestFormatColorTypeCombination>& combos =
303                 caps->getTestingCombinations();
304 
305         for (const GrTest::TestFormatColorTypeCombination& combo : combos) {
306 
307             SkASSERT(combo.fColorType != GrColorType::kUnknown);
308             SkASSERT(combo.fFormat.isValid());
309 
310             if (!caps->isFormatTexturable(combo.fFormat, GrTextureType::k2D)) {
311                 continue;
312             }
313 
314             auto checkColor = [reporter](const GrTest::TestFormatColorTypeCombination& combo,
315                                          uint32_t readColor) {
316                 // We expect that if there is no alpha in the src color type and we read it to a
317                 // color type with alpha that we will get one for alpha rather than zero. We used to
318                 // require this but the Intel Iris 6100 on Win 10 test bot doesn't put one in the
319                 // alpha channel when reading back from GL_RG16 or GL_RG16F. So now we allow either.
320                 uint32_t channels = GrColorTypeChannelFlags(combo.fColorType);
321                 bool allowAlphaOne = !(channels & kAlpha_SkColorChannelFlag);
322                 if (allowAlphaOne) {
323                     if (readColor != 0x00000000 && readColor != 0xFF000000) {
324                         ERRORF(reporter,
325                                "Failed on ct %s format %s 0x%08x is not 0x00000000 or 0xFF000000",
326                                GrColorTypeToStr(combo.fColorType), combo.fFormat.toStr().c_str(),
327                                readColor);
328                         return false;
329                     }
330                 } else {
331                     if (readColor) {
332                         ERRORF(reporter, "Failed on ct %s format %s 0x%08x != 0x00000000",
333                                GrColorTypeToStr(combo.fColorType), combo.fFormat.toStr().c_str(),
334                                readColor);
335                         return false;
336                     }
337                 }
338                 return true;
339             };
340 
341             for (auto renderable : {GrRenderable::kNo, GrRenderable::kYes}) {
342                 if (renderable == GrRenderable::kYes &&
343                     !caps->isFormatAsColorTypeRenderable(combo.fColorType, combo.fFormat)) {
344                     continue;
345                 }
346 
347                 for (auto fit : {SkBackingFit::kApprox, SkBackingFit::kExact}) {
348 
349                     // Does directly allocating a texture clear it?
350                     {
351                         auto proxy = proxyProvider->testingOnly_createInstantiatedProxy(
352                                 {kSize, kSize},
353                                 combo.fFormat,
354                                 renderable,
355                                 1,
356                                 fit,
357                                 skgpu::Budgeted::kYes,
358                                 GrProtected::kNo);
359                         if (proxy) {
360                             skgpu::Swizzle swizzle = caps->getReadSwizzle(combo.fFormat,
361                                                                           combo.fColorType);
362                             GrSurfaceProxyView view(std::move(proxy), kTopLeft_GrSurfaceOrigin,
363                                                     swizzle);
364                             GrColorInfo info(combo.fColorType, kPremul_SkAlphaType, nullptr);
365                             auto texCtx = dContext->priv().makeSC(std::move(view), info);
366 
367                             readback.erase(kClearColor);
368                             if (texCtx->readPixels(dContext, readback, {0, 0})) {
369                                 for (int i = 0; i < kSize * kSize; ++i) {
370                                     if (!checkColor(combo, readback.addr32()[i])) {
371                                         break;
372                                     }
373                                 }
374                             }
375                         }
376 
377                         dContext->priv().getResourceCache()->purgeUnlockedResources(
378                                 GrPurgeResourceOptions::kAllResources);
379                     }
380 
381                     // Try creating the texture as a deferred proxy.
382                     {
383                         GrImageInfo info(combo.fColorType,
384                                          GrColorTypeHasAlpha(combo.fColorType)
385                                                                             ? kPremul_SkAlphaType
386                                                                             : kOpaque_SkAlphaType,
387                                          nullptr,
388                                          {desc.fHeight, desc.fHeight});
389 
390                         auto sc = dContext->priv().makeSC(info,
391                                                           combo.fFormat,
392                                                           /*label=*/{},
393                                                           fit,
394                                                           kTopLeft_GrSurfaceOrigin,
395                                                           renderable);
396                         if (!sc) {
397                             continue;
398                         }
399 
400                         readback.erase(kClearColor);
401                         if (sc->readPixels(dContext, readback, {0, 0})) {
402                             for (int i = 0; i < kSize * kSize; ++i) {
403                                 if (!checkColor(combo, readback.addr32()[i])) {
404                                     break;
405                                 }
406                             }
407                         }
408                         dContext->priv().getResourceCache()->purgeUnlockedResources(
409                                 GrPurgeResourceOptions::kAllResources);
410                     }
411                 }
412             }
413         }
414     }
415 }
416 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ReadOnlyTexture,reporter,context_info,CtsEnforcement::kApiLevel_T)417 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(ReadOnlyTexture,
418                                        reporter,
419                                        context_info,
420                                        CtsEnforcement::kApiLevel_T) {
421     using namespace skgpu;
422 
423     auto fillPixels = [](SkPixmap* p, const std::function<uint32_t(int x, int y)>& f) {
424         for (int y = 0; y < p->height(); ++y) {
425             for (int x = 0; x < p->width(); ++x) {
426                 *p->writable_addr32(x, y) = f(x, y);
427             }
428         }
429     };
430 
431     auto comparePixels = [](const SkPixmap& p1, const SkPixmap& p2, skiatest::Reporter* reporter) {
432         SkASSERT(p1.info() == p2.info());
433         for (int y = 0; y < p1.height(); ++y) {
434             for (int x = 0; x < p1.width(); ++x) {
435                 REPORTER_ASSERT(reporter, p1.getColor(x, y) == p2.getColor(x, y));
436                 if (p1.getColor(x, y) != p2.getColor(x, y)) {
437                     return;
438                 }
439             }
440         }
441     };
442 
443     static constexpr int kSize = 100;
444     SkImageInfo ii = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
445     SkAutoPixmapStorage srcPixmap;
446     srcPixmap.alloc(ii);
447     fillPixels(&srcPixmap,
448                [](int x, int y) {
449                     return (0xFFU << 24) | (x << 16) | (y << 8) | uint8_t((x * y) & 0xFF);
450                });
451 
452     auto dContext = context_info.directContext();
453     GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
454 
455     Protected isProtected = Protected(dContext->priv().caps()->supportsProtectedContent());
456 
457     // We test both kRW in addition to kRead mostly to ensure that the calls are structured such
458     // that they'd succeed if the texture wasn't kRead. We want to be sure we're failing with
459     // kRead for the right reason.
460     for (auto ioType : {kRead_GrIOType, kRW_GrIOType}) {
461         auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithData(dContext,
462                                                                      srcPixmap,
463                                                                      kTopLeft_GrSurfaceOrigin,
464                                                                      GrRenderable::kNo,
465                                                                      isProtected);
466         if (!mbet) {
467             ERRORF(reporter, "Could not make texture.");
468             return;
469         }
470         auto proxy = proxyProvider->wrapBackendTexture(mbet->texture(), kBorrow_GrWrapOwnership,
471                                                        GrWrapCacheable::kNo, ioType,
472                                                        mbet->refCountedCallback());
473         Swizzle swizzle = dContext->priv().caps()->getReadSwizzle(proxy->backendFormat(),
474                                                                   GrColorType::kRGBA_8888);
475         GrSurfaceProxyView view(proxy, kTopLeft_GrSurfaceOrigin, swizzle);
476         auto surfContext = dContext->priv().makeSC(std::move(view), ii.colorInfo());
477         // Read pixels should work with a read-only texture.
478         {
479             SkAutoPixmapStorage read;
480             read.alloc(srcPixmap.info());
481             auto readResult = surfContext->readPixels(dContext, read, {0, 0});
482             REPORTER_ASSERT(reporter, readResult);
483             if (readResult) {
484                 comparePixels(srcPixmap, read, reporter);
485             }
486         }
487 
488         // Write pixels should not work with a read-only texture.
489         SkAutoPixmapStorage write;
490         write.alloc(srcPixmap.info());
491         fillPixels(&write, [&srcPixmap](int x, int y) { return ~*srcPixmap.addr32(); });
492         auto writeResult = surfContext->writePixels(dContext, write, {0, 0});
493         REPORTER_ASSERT(reporter, writeResult == (ioType == kRW_GrIOType));
494         // Try the low level write.
495         dContext->flushAndSubmit();
496         auto gpuWriteResult = dContext->priv().getGpu()->writePixels(
497                 proxy->peekTexture(),
498                 SkIRect::MakeWH(kSize, kSize),
499                 GrColorType::kRGBA_8888,
500                 GrColorType::kRGBA_8888,
501                 write.addr32(),
502                 kSize*GrColorTypeBytesPerPixel(GrColorType::kRGBA_8888));
503         REPORTER_ASSERT(reporter, gpuWriteResult == (ioType == kRW_GrIOType));
504 
505         SkBitmap copySrcBitmap;
506         copySrcBitmap.installPixels(write);
507         copySrcBitmap.setImmutable();
508 
509         auto copySrc = std::get<0>(GrMakeUncachedBitmapProxyView(dContext, copySrcBitmap));
510 
511         REPORTER_ASSERT(reporter, copySrc);
512         auto copyResult = surfContext->testCopy(copySrc.refProxy());
513         REPORTER_ASSERT(reporter, copyResult == (ioType == kRW_GrIOType));
514         // Try the low level copy.
515         dContext->flushAndSubmit();
516         auto gpuCopyResult = dContext->priv().getGpu()->copySurface(
517                 proxy->peekSurface(),
518                 SkIRect::MakeWH(kSize, kSize),
519                 copySrc.proxy()->peekSurface(),
520                 SkIRect::MakeWH(kSize, kSize),
521                 GrSamplerState::Filter::kNearest);
522         REPORTER_ASSERT(reporter, gpuCopyResult == (ioType == kRW_GrIOType));
523 
524         // Mip regen should not work with a read only texture.
525         if (dContext->priv().caps()->mipmapSupport()) {
526             mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(dContext,
527                                                                        kSize,
528                                                                        kSize,
529                                                                        kRGBA_8888_SkColorType,
530                                                                        Mipmapped::kYes,
531                                                                        GrRenderable::kNo,
532                                                                        isProtected);
533             proxy = proxyProvider->wrapBackendTexture(mbet->texture(), kBorrow_GrWrapOwnership,
534                                                       GrWrapCacheable::kNo, ioType,
535                                                       mbet->refCountedCallback());
536             dContext->flushAndSubmit();
537             proxy->peekTexture()->markMipmapsDirty();  // avoids assert in GrGpu.
538             auto regenResult =
539                     dContext->priv().getGpu()->regenerateMipMapLevels(proxy->peekTexture());
540             REPORTER_ASSERT(reporter, regenResult == (ioType == kRW_GrIOType));
541         }
542     }
543 }
544