Create a GrGpu::createBackendTexture choke point

This also makes createBackendTexture take SkPixmaps (instead of a raw pixels pointer)

Change-Id: I5d8a5a58fa7b15862fbf46a3c232cb6ea7f58976
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/243158
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index efc000f..0262554 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -12,6 +12,7 @@
 #include "include/gpu/GrBackendSurface.h"
 #include "include/gpu/GrContext.h"
 #include "src/core/SkMathPriv.h"
+#include "src/core/SkMipMap.h"
 #include "src/gpu/GrAuditTrail.h"
 #include "src/gpu/GrCaps.h"
 #include "src/gpu/GrContextPriv.h"
@@ -701,6 +702,73 @@
     keys->push_back(SkString("shader_compilations")); values->push_back(fShaderCompilations);
 }
 
-#endif
+#endif // GR_GPU_STATS
+#endif // GR_TEST_UTILS
 
-#endif
+
+bool GrGpu::MipMapsAreCorrect(int baseWidth, int baseHeight, GrMipMapped mipMapped,
+                              const SkPixmap srcData[], int numMipLevels) {
+    if (!srcData) {
+        return true;
+    }
+
+    if (baseWidth != srcData[0].width() || baseHeight != srcData[0].height()) {
+        return false;
+    }
+
+    if (mipMapped == GrMipMapped::kYes) {
+        if (numMipLevels != SkMipMap::ComputeLevelCount(baseWidth, baseHeight) + 1) {
+            return false;
+        }
+
+        SkColorType colorType = srcData[0].colorType();
+
+        int currentWidth = baseWidth;
+        int currentHeight = baseHeight;
+        for (int i = 1; i < numMipLevels; ++i) {
+            currentWidth = SkTMax(1, currentWidth / 2);
+            currentHeight = SkTMax(1, currentHeight / 2);
+
+            if (srcData[i].colorType() != colorType) { // all levels must have same colorType
+                return false;
+            }
+
+            if (srcData[i].width() != currentWidth || srcData[i].height() != currentHeight) {
+                return false;
+            }
+        }
+    } else if (numMipLevels != 1) {
+        return false;
+    }
+
+    return true;
+}
+
+GrBackendTexture GrGpu::createBackendTexture(int w, int h, const GrBackendFormat& format,
+                                             GrMipMapped mipMapped, GrRenderable renderable,
+                                             const SkPixmap srcData[], int numMipLevels,
+                                             const SkColor4f* color, GrProtected isProtected) {
+    const GrCaps* caps = this->caps();
+
+    if (!format.isValid()) {
+        return {};
+    }
+
+    SkASSERT(!caps->isFormatCompressed(format) || !srcData);      // There is no ETC1 SkColorType
+
+    if (w < 1 || w > caps->maxTextureSize() || h < 1 || h > caps->maxTextureSize()) {
+        return {};
+    }
+
+    // TODO: maybe just ignore the mipMapped parameter in this case
+    if (mipMapped == GrMipMapped::kYes && !this->caps()->mipMapSupport()) {
+        return {};
+    }
+
+    if (!MipMapsAreCorrect(w, h, mipMapped, srcData, numMipLevels)) {
+        return {};
+    }
+
+    return this->onCreateBackendTexture(w, h, format, mipMapped, renderable,
+                                        srcData, numMipLevels, color, isProtected);
+}