Direct backend object allocation API
Change-Id: Ie8733a4db8061c67678a41cf239ce4407e967df7
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/212965
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index a0b3e17..ce2fcdd 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1643,6 +1643,9 @@
import("gn/tests.gni")
test_lib("tests") {
sources = tests_sources + pathops_tests_sources
+ if (skia_use_metal) {
+ sources += metal_tests_sources
+ }
if (!skia_enable_fontmgr_android) {
sources -= [ "//tests/FontMgrAndroidParserTest.cpp" ]
}
diff --git a/gn/tests.gni b/gn/tests.gni
index e0073f2..160a016 100644
--- a/gn/tests.gni
+++ b/gn/tests.gni
@@ -15,6 +15,7 @@
"$_tests/ApplyGammaTest.cpp",
"$_tests/ArenaAllocTest.cpp",
"$_tests/AsADashTest.cpp",
+ "$_tests/BackendAllocationTest.cpp",
"$_tests/BadIcoTest.cpp",
"$_tests/BitSetTest.cpp",
"$_tests/BitmapCopyTest.cpp",
@@ -305,6 +306,8 @@
"$_tests/YUVTest.cpp",
]
+metal_tests_sources = [ "$_tests/MtlBackendAllocationTest.mm" ]
+
pathops_tests_sources = [
"$_tests/PathOpsAngleIdeas.cpp",
"$_tests/PathOpsAngleTest.cpp",
diff --git a/src/gpu/GrContextPriv.cpp b/src/gpu/GrContextPriv.cpp
index 09b5327..816a7dc 100644
--- a/src/gpu/GrContextPriv.cpp
+++ b/src/gpu/GrContextPriv.cpp
@@ -764,3 +764,58 @@
fContext->drawingManager()->testingOnly_removeOnFlushCallbackObject(cb);
}
#endif
+
+//////////////////////////////////////////////////////////////////////////////
+GrBackendTexture GrContextPriv::createBackendTexture(int width, int height,
+ GrBackendFormat backendFormat,
+ GrMipMapped mipMapped,
+ GrRenderable renderable) {
+ if (!fContext->asDirectContext()) {
+ return GrBackendTexture();
+ }
+
+ if (this->abandoned()) {
+ return GrBackendTexture();
+ }
+
+ if (!backendFormat.isValid()) {
+ return GrBackendTexture();
+ }
+
+ GrGpu* gpu = fContext->fGpu.get();
+
+ return gpu->createTestingOnlyBackendTexture(width, height, backendFormat,
+ mipMapped, renderable,
+ nullptr, 0);
+}
+
+GrBackendTexture GrContextPriv::createBackendTexture(int width, int height,
+ SkColorType colorType,
+ GrMipMapped mipMapped,
+ GrRenderable renderable) {
+ if (!fContext->asDirectContext()) {
+ return GrBackendTexture();
+ }
+
+ if (this->abandoned()) {
+ return GrBackendTexture();
+ }
+
+ GrBackendFormat format = fContext->caps()->getBackendFormatFromColorType(colorType);
+ if (!format.isValid()) {
+ return GrBackendTexture();
+ }
+
+ return this->createBackendTexture(width, height, format, mipMapped, renderable);
+}
+
+void GrContextPriv::deleteBackendTexture(GrBackendTexture backendTex) {
+ if (this->abandoned() || !backendTex.isValid()) {
+ return;
+ }
+
+ GrGpu* gpu = fContext->fGpu.get();
+
+ gpu->deleteTestingOnlyBackendTexture(backendTex);
+}
+
diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h
index 86af1f3..9543ffc 100644
--- a/src/gpu/GrContextPriv.h
+++ b/src/gpu/GrContextPriv.h
@@ -292,6 +292,34 @@
void testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject*);
#endif
+ /*
+ * The explicitly allocated backend texture API allows clients to use Skia to create backend
+ * objects outside of Skia proper (i.e., Skia's caching system will not know about them.)
+ *
+ * It is the client's responsibility to delete all these objects (using deleteBackendTexture)
+ * before deleting the GrContext used to create them. Additionally, clients should only
+ * delete these objects on the thread for which that GrContext is active.
+ *
+ * Additionally, the client is responsible for ensuring synchronization between different uses
+ * of the backend object.
+ */
+
+ // If possible, create an uninitialized backend texture. The client should ensure that the
+ // returned backend texture is valid.
+ GrBackendTexture createBackendTexture(int width, int height,
+ GrBackendFormat,
+ GrMipMapped, GrRenderable);
+
+ // If possible, create an uninitialized backend texture. The client should ensure that the
+ // returned backend texture is valid.
+ // If successful, the created backend texture will be compatible with the provided
+ // SkColorType.
+ GrBackendTexture createBackendTexture(int width, int height,
+ SkColorType,
+ GrMipMapped, GrRenderable);
+
+ void deleteBackendTexture(GrBackendTexture);
+
private:
explicit GrContextPriv(GrContext* context) : fContext(context) {}
GrContextPriv(const GrContextPriv&); // unimpl
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index d235c77..e0f768c 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -3198,7 +3198,7 @@
}
break;
}
- SkDebugf("Unknown pixel config %d\n", format);
+ SkDebugf("Unknown pixel config 0x%x\n", format);
return kUnknown_GrPixelConfig;
}
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index c52da42..f177d18 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1535,11 +1535,11 @@
return false;
}
- if (texturable && !fVkCaps->isConfigTexturable(config)) {
+ if (texturable && !fVkCaps->isFormatTexturable(vkFormat)) {
return false;
}
- if (renderable && !fVkCaps->isConfigRenderable(config)) {
+ if (renderable && !fVkCaps->isFormatRenderable(vkFormat)) {
return false;
}
diff --git a/tests/BackendAllocationTest.cpp b/tests/BackendAllocationTest.cpp
new file mode 100644
index 0000000..16b3d85
--- /dev/null
+++ b/tests/BackendAllocationTest.cpp
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/gpu/GrContext.h"
+#include "src/gpu/GrContextPriv.h"
+#include "include/core/SkSurface.h"
+#include "tests/Test.h"
+
+// Test wrapping of GrBackendObjects in SkSurfaces and SkImages
+void test_wrapping(GrContext* context, skiatest::Reporter* reporter,
+ std::function<GrBackendTexture (GrContext*, GrRenderable)> createMtd,
+ SkColorType colorType, GrRenderable renderable) {
+ GrResourceCache* cache = context->priv().getResourceCache();
+
+ const int initialCount = cache->getResourceCount();
+
+ GrBackendTexture t = createMtd(context, renderable);
+ if (!t.isValid()) {
+ ERRORF(reporter, "Couldn't create backendTexture for colorType %d renderable %s\n",
+ colorType,
+ GrRenderable::kYes == renderable ? "yes" : "no");
+ return;
+ }
+ // Skia proper should know nothing about the new backend object
+ REPORTER_ASSERT(reporter, initialCount == cache->getResourceCount());
+
+ if (kUnknown_SkColorType != colorType) {
+ if (GrRenderable::kYes == renderable) {
+ sk_sp<SkSurface> s = SkSurface::MakeFromBackendTexture(context,
+ t,
+ kTopLeft_GrSurfaceOrigin,
+ 0,
+ colorType,
+ nullptr, nullptr);
+ if (!s) {
+ ERRORF(reporter, "Couldn't make surface from backendTexture for colorType %d\n",
+ colorType);
+ } else {
+ REPORTER_ASSERT(reporter, initialCount+1 == cache->getResourceCount());
+ }
+ }
+
+ {
+ sk_sp<SkImage> i = SkImage::MakeFromTexture(context,
+ t,
+ kTopLeft_GrSurfaceOrigin,
+ colorType,
+ kPremul_SkAlphaType,
+ nullptr);
+ if (!i) {
+ ERRORF(reporter, "Couldn't make image from backendTexture for colorType %d\n",
+ colorType);
+ } else {
+ REPORTER_ASSERT(reporter, initialCount+1 == cache->getResourceCount());
+ }
+ }
+ }
+
+ REPORTER_ASSERT(reporter, initialCount == cache->getResourceCount());
+
+ context->priv().deleteBackendTexture(t);
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ColorTypeBackendAllocationTest, reporter, ctxInfo) {
+ GrContext* context = ctxInfo.grContext();
+ const GrCaps* caps = context->priv().caps();
+
+ struct {
+ SkColorType fColorType;
+ GrPixelConfig fConfig;
+ } combinations[] = {
+ { kAlpha_8_SkColorType, kAlpha_8_GrPixelConfig },
+ { kRGB_565_SkColorType, kRGB_565_GrPixelConfig },
+ { kARGB_4444_SkColorType, kRGBA_4444_GrPixelConfig },
+ { kRGBA_8888_SkColorType, kRGBA_8888_GrPixelConfig },
+ { kRGB_888x_SkColorType, kRGB_888_GrPixelConfig },
+ { kBGRA_8888_SkColorType, kBGRA_8888_GrPixelConfig },
+ { kRGBA_1010102_SkColorType, kRGBA_1010102_GrPixelConfig },
+ { kRGB_101010x_SkColorType, kUnknown_GrPixelConfig }, // No Ganesh correlate
+ { kGray_8_SkColorType, kGray_8_GrPixelConfig },
+ { kRGBA_F16Norm_SkColorType, kRGBA_half_Clamped_GrPixelConfig },
+ { kRGBA_F16_SkColorType, kRGBA_half_GrPixelConfig },
+ { kRGBA_F32_SkColorType, kRGBA_float_GrPixelConfig },
+ };
+
+ SkASSERT(kLastEnum_SkColorType == SK_ARRAY_COUNT(combinations));
+
+ for (auto combo : combinations) {
+ SkColorType colorType = combo.fColorType;
+
+ if (!caps->isConfigTexturable(combo.fConfig)) {
+ continue;
+ }
+
+ if (GrBackendApi::kMetal == context->backend()) {
+ // skbug.com/9086 (Metal caps may not be handling RGBA32 correctly)
+ if (kRGBA_F32_SkColorType == combo.fColorType) {
+ continue;
+ }
+ }
+
+ for (auto renderable : { GrRenderable::kNo, GrRenderable::kYes }) {
+ if (GrRenderable::kYes == renderable) {
+ if (kRGB_888x_SkColorType == combo.fColorType) {
+ // Ganesh can't perform the blends correctly when rendering this format
+ continue;
+ }
+ if (!caps->isConfigRenderable(combo.fConfig)) {
+ continue;
+ }
+ }
+
+ auto createMtd = [colorType](GrContext* context, GrRenderable renderable) {
+ return context->priv().createBackendTexture(32, 32, colorType,
+ GrMipMapped::kNo, renderable);
+ };
+
+ test_wrapping(context, reporter, createMtd, colorType, renderable);
+ }
+ }
+
+}
+
+#include "src/gpu/gl/GrGLDefines.h"
+
+DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(GLBackendAllocationTest, reporter, ctxInfo) {
+ sk_gpu_test::GLTestContext* glCtx = ctxInfo.glContext();
+ GrGLStandard standard = glCtx->gl()->fStandard;
+ GrContext* context = ctxInfo.grContext();
+ const GrCaps* caps = context->priv().caps();
+
+ struct {
+ SkColorType fColorType;
+ GrGLenum fFormat;
+ // TODO: remove 'fConfig' and directly use 'fFormat' in GrGLCaps::isFormatTexturable
+ GrPixelConfig fConfig;
+ } combinations[] = {
+ { kRGBA_8888_SkColorType, GR_GL_RGBA8, kRGBA_8888_GrPixelConfig },
+ { kRGBA_8888_SkColorType, GR_GL_SRGB8_ALPHA8, kSRGBA_8888_GrPixelConfig },
+
+ { kRGB_888x_SkColorType, GR_GL_RGBA8, kRGBA_8888_GrPixelConfig },
+ { kRGB_888x_SkColorType, GR_GL_RGB8, kRGB_888_GrPixelConfig },
+
+ { kBGRA_8888_SkColorType, GR_GL_RGBA8, kRGBA_8888_GrPixelConfig },
+ { kBGRA_8888_SkColorType, GR_GL_BGRA8, kBGRA_8888_GrPixelConfig },
+ { kBGRA_8888_SkColorType, GR_GL_SRGB8_ALPHA8, kSBGRA_8888_GrPixelConfig },
+
+ { kRGBA_1010102_SkColorType, GR_GL_RGB10_A2, kRGBA_1010102_GrPixelConfig },
+ { kRGB_565_SkColorType, GR_GL_RGB565, kRGB_565_GrPixelConfig },
+ { kARGB_4444_SkColorType, GR_GL_RGBA4, kRGBA_4444_GrPixelConfig },
+
+ { kAlpha_8_SkColorType, GR_GL_ALPHA8, kAlpha_8_as_Alpha_GrPixelConfig },
+ { kAlpha_8_SkColorType, GR_GL_R8, kAlpha_8_as_Red_GrPixelConfig },
+
+ { kGray_8_SkColorType, GR_GL_LUMINANCE8, kGray_8_as_Lum_GrPixelConfig },
+ { kGray_8_SkColorType, GR_GL_R8, kGray_8_as_Red_GrPixelConfig },
+
+ { kRGBA_F32_SkColorType, GR_GL_RGBA32F, kRGBA_float_GrPixelConfig },
+
+ { kRGBA_F16Norm_SkColorType, GR_GL_RGBA16F, kRGBA_half_Clamped_GrPixelConfig },
+ { kRGBA_F16_SkColorType, GR_GL_RGBA16F, kRGBA_half_GrPixelConfig },
+
+ // These backend formats don't have SkColorType equivalents
+ { kUnknown_SkColorType, GR_GL_RG32F, kRG_float_GrPixelConfig },
+ { kUnknown_SkColorType, GR_GL_RG8, kRG_88_GrPixelConfig },
+ { kUnknown_SkColorType, GR_GL_R16F, kAlpha_half_as_Red_GrPixelConfig },
+ { kUnknown_SkColorType, GR_GL_COMPRESSED_RGB8_ETC2, kRGB_ETC1_GrPixelConfig },
+ };
+
+ for (auto combo : combinations) {
+ GrBackendFormat format = GrBackendFormat::MakeGL(combo.fFormat, GR_GL_TEXTURE_2D);
+
+ if (GR_GL_COMPRESSED_RGB8_ETC2 == combo.fFormat) {
+ // We current disallow uninitialized ETC1 textures in the GL backend
+ continue;
+ }
+ if (!caps->isConfigTexturable(combo.fConfig)) {
+ continue;
+ }
+
+ if (kBGRA_8888_SkColorType == combo.fColorType) {
+ if (GR_GL_RGBA8 == combo.fFormat && kGL_GrGLStandard != standard) {
+ continue;
+ }
+ if (GR_GL_BGRA8 == combo.fFormat && kGL_GrGLStandard == standard) {
+ continue;
+ }
+ }
+
+ for (auto renderable : { GrRenderable::kNo, GrRenderable::kYes }) {
+
+ if (GrRenderable::kYes == renderable) {
+ if (kRGB_888x_SkColorType == combo.fColorType) {
+ // Ganesh can't perform the blends correctly when rendering this format
+ continue;
+ }
+ if (!caps->isConfigRenderable(combo.fConfig)) {
+ continue;
+ }
+ }
+
+ auto createMtd = [format](GrContext* context, GrRenderable renderable) {
+ return context->priv().createBackendTexture(32, 32, format,
+ GrMipMapped::kNo, renderable);
+ };
+
+ test_wrapping(context, reporter, createMtd, combo.fColorType, renderable);
+ }
+ }
+}
+
+
+#ifdef SK_VULKAN
+
+#include "src/gpu/vk/GrVkCaps.h"
+
+DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkBackendAllocationTest, reporter, ctxInfo) {
+ GrContext* context = ctxInfo.grContext();
+ const GrVkCaps* vkCaps = static_cast<const GrVkCaps*>(context->priv().caps());
+
+ struct {
+ SkColorType fColorType;
+ VkFormat fFormat;
+ } combinations[] = {
+ { kRGBA_8888_SkColorType, VK_FORMAT_R8G8B8A8_UNORM },
+ { kRGBA_8888_SkColorType, VK_FORMAT_R8G8B8A8_SRGB },
+
+ { kRGB_888x_SkColorType, VK_FORMAT_R8G8B8_UNORM },
+ { kRGB_888x_SkColorType, VK_FORMAT_R8G8B8A8_UNORM },
+
+ { kBGRA_8888_SkColorType, VK_FORMAT_B8G8R8A8_UNORM },
+ { kBGRA_8888_SkColorType, VK_FORMAT_B8G8R8A8_SRGB },
+
+ { kRGBA_1010102_SkColorType, VK_FORMAT_A2B10G10R10_UNORM_PACK32 },
+ { kRGB_565_SkColorType, VK_FORMAT_R5G6B5_UNORM_PACK16 },
+ { kARGB_4444_SkColorType, VK_FORMAT_B4G4R4A4_UNORM_PACK16 },
+ { kAlpha_8_SkColorType, VK_FORMAT_R8_UNORM },
+ { kGray_8_SkColorType, VK_FORMAT_R8_UNORM },
+ { kRGBA_F32_SkColorType, VK_FORMAT_R32G32B32A32_SFLOAT },
+
+ { kRGBA_F16Norm_SkColorType, VK_FORMAT_R16G16B16A16_SFLOAT },
+ { kRGBA_F16_SkColorType, VK_FORMAT_R16G16B16A16_SFLOAT },
+
+ // These backend formats don't have SkColorType equivalents
+ { kUnknown_SkColorType, VK_FORMAT_R32G32_SFLOAT },
+ { kUnknown_SkColorType, VK_FORMAT_R8G8_UNORM },
+ { kUnknown_SkColorType, VK_FORMAT_R16_SFLOAT },
+ { kUnknown_SkColorType, VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK },
+ };
+
+ for (auto combo : combinations) {
+ if (!vkCaps->isFormatTexturable(combo.fFormat)) {
+ continue;
+ }
+
+ GrBackendFormat format = GrBackendFormat::MakeVk(combo.fFormat);
+
+ for (auto renderable : { GrRenderable::kNo, GrRenderable::kYes }) {
+
+ if (GrRenderable::kYes == renderable) {
+ if (kRGB_888x_SkColorType == combo.fColorType) {
+ // Ganesh can't perform the blends correctly when rendering this format
+ continue;
+ }
+ if (!vkCaps->isFormatRenderable(combo.fFormat)) {
+ continue;
+ }
+ }
+
+ auto createMtd = [format](GrContext* context, GrRenderable renderable) {
+ return context->priv().createBackendTexture(32, 32, format,
+ GrMipMapped::kNo, renderable);
+ };
+
+ test_wrapping(context, reporter, createMtd, combo.fColorType, renderable);
+ }
+ }
+}
+
+#endif
diff --git a/tests/MtlBackendAllocationTest.mm b/tests/MtlBackendAllocationTest.mm
new file mode 100644
index 0000000..191e191
--- /dev/null
+++ b/tests/MtlBackendAllocationTest.mm
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/gpu/GrContext.h"
+#include "src/gpu/GrContextPriv.h"
+#include "tests/Test.h"
+
+#import <metal/metal.h>
+
+// In BackendAllocationTest.cpp
+void test_wrapping(GrContext* context, skiatest::Reporter* reporter,
+ std::function<GrBackendTexture (GrContext*, GrRenderable)> createMtd,
+ SkColorType colorType, GrRenderable renderable);
+
+DEF_GPUTEST_FOR_METAL_CONTEXT(MtlBackendAllocationTest, reporter, ctxInfo) {
+ GrContext* context = ctxInfo.grContext();
+ const GrCaps* caps = context->priv().caps();
+
+ struct {
+ SkColorType fColorType;
+ GrMTLPixelFormat fFormat;
+ // TODO: remove 'fConfig' and directly use 'fFormat' in GrMtlCaps::isFormatTexturable
+ GrPixelConfig fConfig;
+ } combinations[] = {
+ { kRGBA_8888_SkColorType, MTLPixelFormatRGBA8Unorm, kRGBA_8888_GrPixelConfig },
+ { kRGBA_8888_SkColorType, MTLPixelFormatRGBA8Unorm_sRGB, kSRGBA_8888_GrPixelConfig },
+
+ { kRGB_888x_SkColorType, MTLPixelFormatRGBA8Unorm, kRGBA_8888_GrPixelConfig },
+
+ { kBGRA_8888_SkColorType, MTLPixelFormatBGRA8Unorm, kBGRA_8888_GrPixelConfig },
+ { kBGRA_8888_SkColorType, MTLPixelFormatBGRA8Unorm_sRGB, kSBGRA_8888_GrPixelConfig },
+
+ { kRGBA_1010102_SkColorType, MTLPixelFormatRGB10A2Unorm, kRGBA_1010102_GrPixelConfig },
+#ifdef SK_BUILD_FOR_IOS
+ { kRGB_565_SkColorType, MTLPixelFormatB5G6R5Unorm, kRGB_565_GrPixelConfig },
+ { kARGB_4444_SkColorType, MTLPixelFormatABGR4Unorm, kRGBA_4444_GrPixelConfig },
+#endif
+
+ { kAlpha_8_SkColorType, MTLPixelFormatA8Unorm, kAlpha_8_as_Alpha_GrPixelConfig },
+ { kAlpha_8_SkColorType, MTLPixelFormatR8Unorm, kAlpha_8_as_Red_GrPixelConfig },
+
+ { kGray_8_SkColorType, MTLPixelFormatR8Unorm, kGray_8_as_Red_GrPixelConfig },
+
+ { kRGBA_F32_SkColorType, MTLPixelFormatRGBA32Float, kRGBA_float_GrPixelConfig },
+
+ { kRGBA_F16Norm_SkColorType, MTLPixelFormatRGBA16Float, kRGBA_half_Clamped_GrPixelConfig },
+ { kRGBA_F16_SkColorType, MTLPixelFormatRGBA16Float, kRGBA_half_GrPixelConfig },
+
+ // These backend formats don't have SkColorType equivalents
+ { kUnknown_SkColorType, MTLPixelFormatRG32Float, kRG_float_GrPixelConfig },
+ { kUnknown_SkColorType, MTLPixelFormatRG8Unorm, kRG_88_GrPixelConfig },
+ { kUnknown_SkColorType, MTLPixelFormatR16Float, kAlpha_half_as_Red_GrPixelConfig },
+#ifdef SK_BUILD_FOR_IOS
+ { kUnknown_SkColorType, MTLPixelFormatETC2_RGB8, kRGB_ETC1_GrPixelConfig }
+#endif
+ };
+
+ for (auto combo : combinations) {
+ GrBackendFormat format = GrBackendFormat::MakeMtl(combo.fFormat);
+
+ if (!caps->isConfigTexturable(combo.fConfig)) {
+ continue;
+ }
+
+ // skbug.com/9086 (Metal caps may not be handling RGBA32 correctly)
+ if (kRGBA_F32_SkColorType == combo.fColorType) {
+ continue;
+ }
+
+ for (auto renderable : { GrRenderable::kNo, GrRenderable::kYes }) {
+
+ if (GrRenderable::kYes == renderable) {
+ if (kRGB_888x_SkColorType == combo.fColorType) {
+ // Ganesh can't perform the blends correctly when rendering this format
+ continue;
+ }
+ if (!caps->isConfigRenderable(combo.fConfig)) {
+ continue;
+ }
+ }
+
+ auto createMtd = [format](GrContext* context, GrRenderable renderable) {
+ return context->priv().createBackendTexture(32, 32, format,
+ GrMipMapped::kNo, renderable);
+ };
+
+ test_wrapping(context, reporter, createMtd, combo.fColorType, renderable);
+ }
+ }
+}