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
/*************************************************************************************************/