Migrate texture creation methods to GrDirectContext

Cut and paste job. Getting close!

Change-Id: Ifd1673a92a44dac1e8aab578a3e41b2a2b5e3325

Cq-Include-Trybots: luci.skia.skia.primary:Perf-Debian10-EMCC-GCE-CPU-AVX2-wasm-Release-All-CanvasKit,Perf-Debian10-EMCC-GCE-CPU-AVX2-wasm-Release-All-Puppeteer_RenderSKP
Change-Id: Ifd1673a92a44dac1e8aab578a3e41b2a2b5e3325
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/325659
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Auto-Submit: Adlai Holler <adlai@google.com>
diff --git a/include/gpu/GrDirectContext.h b/include/gpu/GrDirectContext.h
index 38051fc..45c145c 100644
--- a/include/gpu/GrDirectContext.h
+++ b/include/gpu/GrDirectContext.h
@@ -94,9 +94,9 @@
      * Abandons all GPU resources and assumes the underlying backend 3D API context is no longer
      * usable. Call this if you have lost the associated GPU context, and thus internal texture,
      * buffer, etc. references/IDs are now invalid. Calling this ensures that the destructors of the
-     * GrContext and any of its created resource objects will not make backend 3D API calls. Content
+     * context and any of its created resource objects will not make backend 3D API calls. Content
      * rendered but not previously flushed may be lost. After this function is called all subsequent
-     * calls on the GrContext will fail or be no-ops.
+     * calls on the context will fail or be no-ops.
      *
      * The typical use case for this function is that the underlying 3D context was lost and further
      * API calls may crash.
@@ -373,6 +373,118 @@
     GrBackendFormat defaultBackendFormat(SkColorType ct, GrRenderable renderable) const {
         return INHERITED::defaultBackendFormat(ct, renderable);
     }
+
+    /**
+     * 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 context used to create them. If the backend is Vulkan, the textures must
+     * be deleted before abandoning the context as well. Additionally, clients should only delete
+     * these objects on the thread for which that context is active.
+     *
+     * The client is responsible for ensuring synchronization between different uses
+     * of the backend object (i.e., wrapping it in a surface, rendering to it, deleting the
+     * surface, rewrapping it in a image and drawing the image will require explicit
+     * synchronization on the client's part).
+     */
+
+     /**
+      * If possible, create an uninitialized backend texture. The client should ensure that the
+      * returned backend texture is valid.
+      * For the Vulkan backend the layout of the created VkImage will be:
+      *      VK_IMAGE_LAYOUT_UNDEFINED.
+      */
+     GrBackendTexture createBackendTexture(int width, int height,
+                                           const GrBackendFormat&,
+                                           GrMipmapped,
+                                           GrRenderable,
+                                           GrProtected = GrProtected::kNo);
+
+     /**
+      * 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.
+      * For the Vulkan backend the layout of the created VkImage will be:
+      *      VK_IMAGE_LAYOUT_UNDEFINED.
+      */
+     GrBackendTexture createBackendTexture(int width, int height,
+                                           SkColorType,
+                                           GrMipmapped,
+                                           GrRenderable,
+                                           GrProtected = GrProtected::kNo);
+
+     /**
+      * If possible, create a backend texture initialized to a particular color. The client should
+      * ensure that the returned backend texture is valid. The client can pass in a finishedProc
+      * to be notified when the data has been uploaded by the gpu and the texture can be deleted. The
+      * client is required to call `submit` to send the upload work to the gpu. The
+      * finishedProc will always get called even if we failed to create the GrBackendTexture.
+      * For the Vulkan backend the layout of the created VkImage will be:
+      *      VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+      */
+     GrBackendTexture createBackendTexture(int width, int height,
+                                           const GrBackendFormat&,
+                                           const SkColor4f& color,
+                                           GrMipmapped,
+                                           GrRenderable,
+                                           GrProtected = GrProtected::kNo,
+                                           GrGpuFinishedProc finishedProc = nullptr,
+                                           GrGpuFinishedContext finishedContext = nullptr);
+
+     /**
+      * If possible, create a backend texture initialized to a particular color. The client should
+      * ensure that the returned backend texture is valid. The client can pass in a finishedProc
+      * to be notified when the data has been uploaded by the gpu and the texture can be deleted. The
+      * client is required to call `submit` to send the upload work to the gpu. The
+      * finishedProc will always get called even if we failed to create the GrBackendTexture.
+      * If successful, the created backend texture will be compatible with the provided
+      * SkColorType.
+      * For the Vulkan backend the layout of the created VkImage will be:
+      *      VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+      */
+     GrBackendTexture createBackendTexture(int width, int height,
+                                           SkColorType,
+                                           const SkColor4f& color,
+                                           GrMipmapped,
+                                           GrRenderable,
+                                           GrProtected = GrProtected::kNo,
+                                           GrGpuFinishedProc finishedProc = nullptr,
+                                           GrGpuFinishedContext finishedContext = nullptr);
+
+     /**
+      * If possible, create a backend texture initialized with the provided pixmap data. The client
+      * should ensure that the returned backend texture is valid. The client can pass in a
+      * finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
+      * deleted. The client is required to call `submit` to send the upload work to the gpu.
+      * The finishedProc will always get called even if we failed to create the GrBackendTexture.
+      * If successful, the created backend texture will be compatible with the provided
+      * pixmap(s). Compatible, in this case, means that the backend format will be the result
+      * of calling defaultBackendFormat on the base pixmap's colortype. The src data can be deleted
+      * when this call returns.
+      * If numLevels is 1 a non-mipMapped texture will result. If a mipMapped texture is desired
+      * the data for all the mipmap levels must be provided. In the mipmapped case all the
+      * colortypes of the provided pixmaps must be the same. Additionally, all the miplevels
+      * must be sized correctly (please see SkMipmap::ComputeLevelSize and ComputeLevelCount).
+      * Note: the pixmap's alphatypes and colorspaces are ignored.
+      * For the Vulkan backend the layout of the created VkImage will be:
+      *      VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+      */
+     GrBackendTexture createBackendTexture(const SkPixmap srcData[], int numLevels,
+                                           GrRenderable, GrProtected,
+                                           GrGpuFinishedProc finishedProc = nullptr,
+                                           GrGpuFinishedContext finishedContext = nullptr);
+
+     // Helper version of above for a single level.
+     GrBackendTexture createBackendTexture(const SkPixmap& srcData,
+                                           GrRenderable renderable,
+                                           GrProtected isProtected,
+                                           GrGpuFinishedProc finishedProc = nullptr,
+                                           GrGpuFinishedContext finishedContext = nullptr) {
+         return this->createBackendTexture(&srcData, 1, renderable, isProtected, finishedProc,
+                                           finishedContext);
+     }
 protected:
     GrDirectContext(GrBackendApi backend, const GrContextOptions& options);
 
diff --git a/include/private/GrContext.h b/include/private/GrContext.h
index 3da11b0..d912f6c 100644
--- a/include/private/GrContext.h
+++ b/include/private/GrContext.h
@@ -57,118 +57,6 @@
 public:
     ~GrContext() override;
 
-   /**
-    * 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. If the backend is Vulkan, the textures must
-    * be deleted before abandoning the GrContext as well. Additionally, clients should only delete
-    * these objects on the thread for which that GrContext is active.
-    *
-    * The client is responsible for ensuring synchronization between different uses
-    * of the backend object (i.e., wrapping it in a surface, rendering to it, deleting the
-    * surface, rewrapping it in a image and drawing the image will require explicit
-    * sychronization on the client's part).
-    */
-
-    /**
-     * If possible, create an uninitialized backend texture. The client should ensure that the
-     * returned backend texture is valid.
-     * For the Vulkan backend the layout of the created VkImage will be:
-     *      VK_IMAGE_LAYOUT_UNDEFINED.
-     */
-    GrBackendTexture createBackendTexture(int width, int height,
-                                          const GrBackendFormat&,
-                                          GrMipmapped,
-                                          GrRenderable,
-                                          GrProtected = GrProtected::kNo);
-
-    /**
-     * 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.
-     * For the Vulkan backend the layout of the created VkImage will be:
-     *      VK_IMAGE_LAYOUT_UNDEFINED.
-     */
-    GrBackendTexture createBackendTexture(int width, int height,
-                                          SkColorType,
-                                          GrMipmapped,
-                                          GrRenderable,
-                                          GrProtected = GrProtected::kNo);
-
-    /**
-     * If possible, create a backend texture initialized to a particular color. The client should
-     * ensure that the returned backend texture is valid. The client can pass in a finishedProc
-     * to be notified when the data has been uploaded by the gpu and the texture can be deleted. The
-     * client is required to call GrContext::submit to send the upload work to the gpu. The
-     * finishedProc will always get called even if we failed to create the GrBackendTexture.
-     * For the Vulkan backend the layout of the created VkImage will be:
-     *      VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
-     */
-    GrBackendTexture createBackendTexture(int width, int height,
-                                          const GrBackendFormat&,
-                                          const SkColor4f& color,
-                                          GrMipmapped,
-                                          GrRenderable,
-                                          GrProtected = GrProtected::kNo,
-                                          GrGpuFinishedProc finishedProc = nullptr,
-                                          GrGpuFinishedContext finishedContext = nullptr);
-
-    /**
-     * If possible, create a backend texture initialized to a particular color. The client should
-     * ensure that the returned backend texture is valid. The client can pass in a finishedProc
-     * to be notified when the data has been uploaded by the gpu and the texture can be deleted. The
-     * client is required to call GrContext::submit to send the upload work to the gpu. The
-     * finishedProc will always get called even if we failed to create the GrBackendTexture.
-     * If successful, the created backend texture will be compatible with the provided
-     * SkColorType.
-     * For the Vulkan backend the layout of the created VkImage will be:
-     *      VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
-     */
-    GrBackendTexture createBackendTexture(int width, int height,
-                                          SkColorType,
-                                          const SkColor4f& color,
-                                          GrMipmapped,
-                                          GrRenderable,
-                                          GrProtected = GrProtected::kNo,
-                                          GrGpuFinishedProc finishedProc = nullptr,
-                                          GrGpuFinishedContext finishedContext = nullptr);
-
-    /**
-     * If possible, create a backend texture initialized with the provided pixmap data. The client
-     * should ensure that the returned backend texture is valid. The client can pass in a
-     * finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
-     * deleted. The client is required to call GrContext::submit to send the upload work to the gpu.
-     * The finishedProc will always get called even if we failed to create the GrBackendTexture.
-     * If successful, the created backend texture will be compatible with the provided
-     * pixmap(s). Compatible, in this case, means that the backend format will be the result
-     * of calling defaultBackendFormat on the base pixmap's colortype. The src data can be deleted
-     * when this call returns.
-     * If numLevels is 1 a non-mipMapped texture will result. If a mipMapped texture is desired
-     * the data for all the mipmap levels must be provided. In the mipmapped case all the
-     * colortypes of the provided pixmaps must be the same. Additionally, all the miplevels
-     * must be sized correctly (please see SkMipmap::ComputeLevelSize and ComputeLevelCount).
-     * Note: the pixmap's alphatypes and colorspaces are ignored.
-     * For the Vulkan backend the layout of the created VkImage will be:
-     *      VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
-     */
-    GrBackendTexture createBackendTexture(const SkPixmap srcData[], int numLevels,
-                                          GrRenderable, GrProtected,
-                                          GrGpuFinishedProc finishedProc = nullptr,
-                                          GrGpuFinishedContext finishedContext = nullptr);
-
-    // Helper version of above for a single level.
-    GrBackendTexture createBackendTexture(const SkPixmap& srcData,
-                                          GrRenderable renderable,
-                                          GrProtected isProtected,
-                                          GrGpuFinishedProc finishedProc = nullptr,
-                                          GrGpuFinishedContext finishedContext = nullptr) {
-        return this->createBackendTexture(&srcData, 1, renderable, isProtected, finishedProc,
-                                          finishedContext);
-    }
-
     /**
      * If possible, updates a backend texture to be filled to a particular color. The client should
      * check the return value to see if the update was successful. The client can pass in a
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 575adf9..1d28619 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -39,188 +39,10 @@
 #include <atomic>
 #include <memory>
 
-#define ASSERT_OWNED_PROXY(P) \
-    SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == this)
-
-#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
-#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(this->singleOwner())
-#define RETURN_IF_ABANDONED if (this->abandoned()) { return; }
-#define RETURN_FALSE_IF_ABANDONED if (this->abandoned()) { return false; }
-#define RETURN_NULL_IF_ABANDONED if (this->abandoned()) { return nullptr; }
-
 GrContext::GrContext(sk_sp<GrContextThreadSafeProxy> proxy) : INHERITED(std::move(proxy)) { }
 
 GrContext::~GrContext() = default;
 
-GrBackendTexture GrContext::createBackendTexture(int width, int height,
-                                                 const GrBackendFormat& backendFormat,
-                                                 GrMipmapped mipMapped,
-                                                 GrRenderable renderable,
-                                                 GrProtected isProtected) {
-    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
-    if (!this->asDirectContext()) {
-        return GrBackendTexture();
-    }
-
-    if (this->abandoned()) {
-        return GrBackendTexture();
-    }
-
-    return fGpu->createBackendTexture({width, height}, backendFormat, renderable,
-                                      mipMapped, isProtected);
-}
-
-GrBackendTexture GrContext::createBackendTexture(int width, int height,
-                                                 SkColorType skColorType,
-                                                 GrMipmapped mipMapped,
-                                                 GrRenderable renderable,
-                                                 GrProtected isProtected) {
-    if (!this->asDirectContext()) {
-        return GrBackendTexture();
-    }
-
-    if (this->abandoned()) {
-        return GrBackendTexture();
-    }
-
-    const GrBackendFormat format = this->defaultBackendFormat(skColorType, renderable);
-
-    return this->createBackendTexture(width, height, format, mipMapped, renderable, isProtected);
-}
-
-static GrBackendTexture create_and_update_backend_texture(
-        GrDirectContext* context,
-        SkISize dimensions,
-        const GrBackendFormat& backendFormat,
-        GrMipmapped mipMapped,
-        GrRenderable renderable,
-        GrProtected isProtected,
-        sk_sp<GrRefCntedCallback> finishedCallback,
-        const GrGpu::BackendTextureData* data) {
-    GrGpu* gpu = context->priv().getGpu();
-
-    GrBackendTexture beTex = gpu->createBackendTexture(dimensions, backendFormat, renderable,
-                                                       mipMapped, isProtected);
-    if (!beTex.isValid()) {
-        return {};
-    }
-
-    if (!context->priv().getGpu()->updateBackendTexture(beTex, std::move(finishedCallback), data)) {
-        context->deleteBackendTexture(beTex);
-        return {};
-    }
-    return beTex;
-}
-
-GrBackendTexture GrContext::createBackendTexture(int width, int height,
-                                                 const GrBackendFormat& backendFormat,
-                                                 const SkColor4f& color,
-                                                 GrMipmapped mipMapped,
-                                                 GrRenderable renderable,
-                                                 GrProtected isProtected,
-                                                 GrGpuFinishedProc finishedProc,
-                                                 GrGpuFinishedContext finishedContext) {
-    sk_sp<GrRefCntedCallback> finishedCallback;
-    if (finishedProc) {
-        finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
-    }
-
-    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
-    if (!this->asDirectContext()) {
-        return {};
-    }
-
-    if (this->abandoned()) {
-        return {};
-    }
-
-    GrGpu::BackendTextureData data(color);
-    return create_and_update_backend_texture(this->asDirectContext(), {width, height},
-                                             backendFormat, mipMapped, renderable, isProtected,
-                                             std::move(finishedCallback), &data);
-}
-
-GrBackendTexture GrContext::createBackendTexture(int width, int height,
-                                                 SkColorType skColorType,
-                                                 const SkColor4f& color,
-                                                 GrMipmapped mipMapped,
-                                                 GrRenderable renderable,
-                                                 GrProtected isProtected,
-                                                 GrGpuFinishedProc finishedProc,
-                                                 GrGpuFinishedContext finishedContext) {
-    sk_sp<GrRefCntedCallback> finishedCallback;
-    if (finishedProc) {
-        finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
-    }
-
-    if (!this->asDirectContext()) {
-        return {};
-    }
-
-    if (this->abandoned()) {
-        return {};
-    }
-
-    GrBackendFormat format = this->defaultBackendFormat(skColorType, renderable);
-    if (!format.isValid()) {
-        return {};
-    }
-
-    GrColorType grColorType = SkColorTypeToGrColorType(skColorType);
-    SkColor4f swizzledColor = this->caps()->getWriteSwizzle(format, grColorType).applyTo(color);
-
-    GrGpu::BackendTextureData data(swizzledColor);
-    return create_and_update_backend_texture(this->asDirectContext(), {width, height}, format,
-                                             mipMapped, renderable, isProtected,
-                                             std::move(finishedCallback), &data);
-}
-
-GrBackendTexture GrContext::createBackendTexture(const SkPixmap srcData[], int numProvidedLevels,
-                                                 GrRenderable renderable, GrProtected isProtected,
-                                                 GrGpuFinishedProc finishedProc,
-                                                 GrGpuFinishedContext finishedContext) {
-    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
-
-    sk_sp<GrRefCntedCallback> finishedCallback;
-    if (finishedProc) {
-        finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
-    }
-
-    if (!this->asDirectContext()) {
-        return {};
-    }
-
-    if (this->abandoned()) {
-        return {};
-    }
-
-    if (!srcData || numProvidedLevels <= 0) {
-        return {};
-    }
-
-    int baseWidth = srcData[0].width();
-    int baseHeight = srcData[0].height();
-    SkColorType colorType = srcData[0].colorType();
-
-    GrMipmapped mipMapped = GrMipmapped::kNo;
-    int numExpectedLevels = 1;
-    if (numProvidedLevels > 1) {
-        numExpectedLevels = SkMipmap::ComputeLevelCount(baseWidth, baseHeight) + 1;
-        mipMapped = GrMipmapped::kYes;
-    }
-
-    if (numProvidedLevels != numExpectedLevels) {
-        return {};
-    }
-
-    GrBackendFormat backendFormat = this->defaultBackendFormat(colorType, renderable);
-
-    GrGpu::BackendTextureData data(srcData);
-    return create_and_update_backend_texture(this->asDirectContext(), {baseWidth, baseHeight},
-                                             backendFormat, mipMapped, renderable, isProtected,
-                                             std::move(finishedCallback), &data);
-}
-
 bool GrContext::updateBackendTexture(const GrBackendTexture& backendTexture,
                                      const SkColor4f& color,
                                      GrGpuFinishedProc finishedProc,
diff --git a/src/gpu/GrDirectContext.cpp b/src/gpu/GrDirectContext.cpp
index 78fa9ab..ac5722a 100644
--- a/src/gpu/GrDirectContext.cpp
+++ b/src/gpu/GrDirectContext.cpp
@@ -449,6 +449,159 @@
                                   colorSamplesPerPixel, mipMapped, useNextPow2);
 }
 
+GrBackendTexture GrDirectContext::createBackendTexture(int width, int height,
+                                                       const GrBackendFormat& backendFormat,
+                                                       GrMipmapped mipMapped,
+                                                       GrRenderable renderable,
+                                                       GrProtected isProtected) {
+    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
+    if (this->abandoned()) {
+        return GrBackendTexture();
+    }
+
+    return fGpu->createBackendTexture({width, height}, backendFormat, renderable,
+                                      mipMapped, isProtected);
+}
+
+GrBackendTexture GrDirectContext::createBackendTexture(int width, int height,
+                                                       SkColorType skColorType,
+                                                       GrMipmapped mipMapped,
+                                                       GrRenderable renderable,
+                                                       GrProtected isProtected) {
+    if (this->abandoned()) {
+        return GrBackendTexture();
+    }
+
+    const GrBackendFormat format = this->defaultBackendFormat(skColorType, renderable);
+
+    return this->createBackendTexture(width, height, format, mipMapped, renderable, isProtected);
+}
+
+static GrBackendTexture create_and_update_backend_texture(
+        GrDirectContext* dContext,
+        SkISize dimensions,
+        const GrBackendFormat& backendFormat,
+        GrMipmapped mipMapped,
+        GrRenderable renderable,
+        GrProtected isProtected,
+        sk_sp<GrRefCntedCallback> finishedCallback,
+        const GrGpu::BackendTextureData* data) {
+    GrGpu* gpu = dContext->priv().getGpu();
+
+    GrBackendTexture beTex = gpu->createBackendTexture(dimensions, backendFormat, renderable,
+                                                       mipMapped, isProtected);
+    if (!beTex.isValid()) {
+        return {};
+    }
+
+    if (!dContext->priv().getGpu()->updateBackendTexture(beTex,
+                                                         std::move(finishedCallback),
+                                                         data)) {
+        dContext->deleteBackendTexture(beTex);
+        return {};
+    }
+    return beTex;
+}
+
+GrBackendTexture GrDirectContext::createBackendTexture(int width, int height,
+                                                       const GrBackendFormat& backendFormat,
+                                                       const SkColor4f& color,
+                                                       GrMipmapped mipMapped,
+                                                       GrRenderable renderable,
+                                                       GrProtected isProtected,
+                                                       GrGpuFinishedProc finishedProc,
+                                                       GrGpuFinishedContext finishedContext) {
+    sk_sp<GrRefCntedCallback> finishedCallback;
+    if (finishedProc) {
+        finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
+    }
+
+    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
+    if (this->abandoned()) {
+        return {};
+    }
+
+    GrGpu::BackendTextureData data(color);
+    return create_and_update_backend_texture(this, {width, height},
+                                             backendFormat, mipMapped, renderable, isProtected,
+                                             std::move(finishedCallback), &data);
+}
+
+GrBackendTexture GrDirectContext::createBackendTexture(int width, int height,
+                                                       SkColorType skColorType,
+                                                       const SkColor4f& color,
+                                                       GrMipmapped mipMapped,
+                                                       GrRenderable renderable,
+                                                       GrProtected isProtected,
+                                                       GrGpuFinishedProc finishedProc,
+                                                       GrGpuFinishedContext finishedContext) {
+    sk_sp<GrRefCntedCallback> finishedCallback;
+    if (finishedProc) {
+        finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
+    }
+
+    if (this->abandoned()) {
+        return {};
+    }
+
+    GrBackendFormat format = this->defaultBackendFormat(skColorType, renderable);
+    if (!format.isValid()) {
+        return {};
+    }
+
+    GrColorType grColorType = SkColorTypeToGrColorType(skColorType);
+    SkColor4f swizzledColor = this->caps()->getWriteSwizzle(format, grColorType).applyTo(color);
+
+    GrGpu::BackendTextureData data(swizzledColor);
+    return create_and_update_backend_texture(this, {width, height}, format,
+                                             mipMapped, renderable, isProtected,
+                                             std::move(finishedCallback), &data);
+}
+
+GrBackendTexture GrDirectContext::createBackendTexture(const SkPixmap srcData[],
+                                                       int numProvidedLevels,
+                                                       GrRenderable renderable,
+                                                       GrProtected isProtected,
+                                                       GrGpuFinishedProc finishedProc,
+                                                       GrGpuFinishedContext finishedContext) {
+    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
+
+    sk_sp<GrRefCntedCallback> finishedCallback;
+    if (finishedProc) {
+        finishedCallback.reset(new GrRefCntedCallback(finishedProc, finishedContext));
+    }
+
+    if (this->abandoned()) {
+        return {};
+    }
+
+    if (!srcData || numProvidedLevels <= 0) {
+        return {};
+    }
+
+    int baseWidth = srcData[0].width();
+    int baseHeight = srcData[0].height();
+    SkColorType colorType = srcData[0].colorType();
+
+    GrMipmapped mipMapped = GrMipmapped::kNo;
+    int numExpectedLevels = 1;
+    if (numProvidedLevels > 1) {
+        numExpectedLevels = SkMipmap::ComputeLevelCount(baseWidth, baseHeight) + 1;
+        mipMapped = GrMipmapped::kYes;
+    }
+
+    if (numProvidedLevels != numExpectedLevels) {
+        return {};
+    }
+
+    GrBackendFormat backendFormat = this->defaultBackendFormat(colorType, renderable);
+
+    GrGpu::BackendTextureData data(srcData);
+    return create_and_update_backend_texture(this, {baseWidth, baseHeight},
+                                             backendFormat, mipMapped, renderable, isProtected,
+                                             std::move(finishedCallback), &data);
+}
+
 #ifdef SK_GL
 
 /*************************************************************************************************/