Revise GrDataUtils to be more self-contained (take 3)

This makes the GL and Vk backends share more code and sets up for the Metal implementation.

Change-Id: I781d5b6188fb2d46ae4ec48204fda74fe28b18c0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/218964
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index f344e2e..d2b18f1 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -1589,50 +1589,6 @@
     return state;
 }
 
-size_t GLBytesPerPixel(GrGLenum glFormat) {
-    switch (glFormat) {
-        case GR_GL_LUMINANCE8:
-        case GR_GL_ALPHA8:
-        case GR_GL_R8:
-            return 1;
-
-        case GR_GL_RGB565:
-        case GR_GL_RGBA4:
-        case GR_GL_RG8:
-        case GR_GL_R16F:
-            return 2;
-
-        case GR_GL_RGB8:
-            return 3;
-
-        case GR_GL_RGBA8:
-        case GR_GL_SRGB8_ALPHA8:
-        case GR_GL_BGRA8:
-        case GR_GL_RGB10_A2:
-            return 4;
-
-        case GR_GL_RGBA16F:
-        case GR_GL_RG32F:
-            return 8;
-
-        case GR_GL_RGBA32F:
-            return 16;
-
-        case GR_GL_COMPRESSED_RGB8_ETC2: // fall through
-        case GR_GL_COMPRESSED_ETC1_RGB8:
-            return 0;
-
-        // Experimental (for P016 and P010)
-        case GR_GL_R16:
-            return 2;
-        case GR_GL_RG16:
-            return 4;
-    }
-
-    SK_ABORT("Invalid GL format");
-    return 0;
-}
-
 sk_sp<GrTexture> GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
                                           SkBudgeted budgeted,
                                           const GrMipLevel texels[],
@@ -1652,7 +1608,7 @@
     std::unique_ptr<uint8_t[]> zeros;
     if (performClear && !this->glCaps().clearTextureSupport() &&
         !this->glCaps().canConfigBeFBOColorAttachment(desc.fConfig)) {
-        size_t rowSize = GLBytesPerPixel(glFormat) * desc.fWidth;
+        size_t rowSize = GrGLBytesPerFormat(glFormat) * desc.fWidth;
         size_t size = rowSize * desc.fHeight;
         zeros.reset(new uint8_t[size]);
         memset(zeros.get(), 0, size);
@@ -4050,7 +4006,7 @@
                                                const GrBackendFormat& format,
                                                GrMipMapped mipMapped,
                                                GrRenderable renderable,
-                                               const void* pixels, size_t rowBytes,
+                                               const void* srcPixels, size_t rowBytes,
                                                const SkColor4f& colorf) {
     this->handleDirtyContext();
 
@@ -4075,7 +4031,7 @@
     }
 
     // Currently we don't support uploading pixel data when mipped.
-    if (pixels && GrMipMapped::kYes == mipMapped) {
+    if (srcPixels && GrMipMapped::kYes == mipMapped) {
         return GrBackendTexture();  // invalid
     }
 
@@ -4089,43 +4045,39 @@
         mipLevelCount = SkMipMap::ComputeLevelCount(w, h) + 1;
     }
 
-    SkAutoMalloc pixelStorage;
-
-    if (GrGLFormatIsCompressed(*glFormat)) {
-        // we have to do something special for compressed textures
-        SkASSERT(0 == rowBytes);
-
-        if (!pixels) {
-            size_t etc1Size = GrGLFormatCompressedDataSize(*glFormat, w, h);
-            pixelStorage.reset(etc1Size);
-            GrFillInETC1WithColor(w, h, colorf, pixelStorage.get());
-            pixels = pixelStorage.get();
-            rowBytes = 0;
-        }
-    } else {
-        int bpp = GrBytesPerPixel(config);
-        const size_t trimRowBytes = w * bpp;
-        if (!rowBytes) {
-            rowBytes = trimRowBytes;
-        }
-
-        if (!pixels) {
-            size_t baseLayerSize = trimRowBytes * h;
-            pixelStorage.reset(baseLayerSize);
-            if (!GrFillBufferWithColor(config, w, h, colorf, pixelStorage.get())) {
-                return GrBackendTexture();  // invalid
-            }
-
-            pixels = pixelStorage.get();
-            rowBytes = trimRowBytes;
-        }
-    }
-
     SkAutoTMalloc<GrMipLevel> texels(mipLevelCount);
 
-    for (int i = 0; i < mipLevelCount; ++i) {
-        // TODO: this isn't correct when pixels for additional mip levels are passed in
-        texels.get()[i] = { pixels, rowBytes };
+    SkAutoMalloc pixelStorage;
+
+    if (!srcPixels) {
+        GrCompression compression = GrGLFormat2Compression(*glFormat);
+
+        SkTArray<size_t> individualMipOffsets(mipLevelCount);
+        size_t bytesPerPixel = GrBytesPerPixel(config);
+
+        size_t totalSize = GrComputeTightCombinedBufferSize(compression, bytesPerPixel, w, h,
+                                                            &individualMipOffsets, mipLevelCount);
+
+        char* tmpPixels = (char *) pixelStorage.reset(totalSize);
+
+        GrFillInData(compression, config, w, h, individualMipOffsets, tmpPixels, colorf);
+
+        for (int i = 0; i < mipLevelCount; ++i) {
+            size_t offset = individualMipOffsets[i];
+
+            int twoToTheMipLevel = 1 << i;
+            int currentWidth = SkTMax(1, w / twoToTheMipLevel);
+
+            texels.get()[i] = { &(tmpPixels[offset]), currentWidth*bytesPerPixel };
+        }
+    } else {
+        SkASSERT(1 == mipLevelCount);
+
+        if (GrGLFormatIsCompressed(*glFormat)) {
+            SkASSERT(0 == rowBytes);
+        }
+
+        texels.get()[0] = { srcPixels, rowBytes };
     }
 
     GrSurfaceDesc desc;
diff --git a/src/gpu/gl/GrGLUtil.cpp b/src/gpu/gl/GrGLUtil.cpp
index 8f67be7..f50932e 100644
--- a/src/gpu/gl/GrGLUtil.cpp
+++ b/src/gpu/gl/GrGLUtil.cpp
@@ -573,6 +573,18 @@
     return false;
 }
 
+GrCompression GrGLFormat2Compression(GrGLenum glFormat) {
+    switch (glFormat) {
+        case GR_GL_COMPRESSED_RGB8_ETC2: // fall through
+        case GR_GL_COMPRESSED_ETC1_RGB8:
+            return GrCompression::kETC1;
+        default:
+            return GrCompression::kNone;
+    }
+    SK_ABORT("Invalid format");
+    return GrCompression::kNone;
+}
+
 size_t GrGLFormatCompressedDataSize(GrGLenum glFormat, int width, int height) {
     SkASSERT(GrGLFormatIsCompressed(glFormat));
 
diff --git a/src/gpu/gl/GrGLUtil.h b/src/gpu/gl/GrGLUtil.h
index c9bd3c2..332cddd 100644
--- a/src/gpu/gl/GrGLUtil.h
+++ b/src/gpu/gl/GrGLUtil.h
@@ -10,6 +10,7 @@
 
 #include "include/gpu/gl/GrGLInterface.h"
 #include "include/private/GrTypesPriv.h"
+#include "src/gpu/GrDataUtils.h"
 #include "src/gpu/GrStencilSettings.h"
 #include "src/gpu/gl/GrGLDefines.h"
 
@@ -265,6 +266,11 @@
 bool GrGLFormatIsCompressed(GrGLenum glFormat);
 
 /**
+ * Maps a gl format into the GrCompressed enum.
+ */
+GrCompression GrGLFormat2Compression(GrGLenum glFormat);
+
+/**
  * Returns the data size for the given compressed format
  */
 size_t GrGLFormatCompressedDataSize(GrGLenum glFormat, int width, int height);