SkPixelInfo::CopyPixels() refactor part 0: only one memcpy() case

I envision this eventually looking like the following:
Fast Path 1: memcpy
Fast Path 2: Legacy RGBA/BGRA unpremul/premul
Fast Path 3: SkColorSpaceXform
Fallback: Raster pipeline

BUG=skia:6021

Change-Id: I3f0e36b08b051ab4ba3949f04474f20d0c20a963
Reviewed-on: https://skia-review.googlesource.com/7435
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Matt Sarett <msarett@google.com>
diff --git a/src/core/SkConfig8888.cpp b/src/core/SkConfig8888.cpp
index cdecf05..10bed27 100644
--- a/src/core/SkConfig8888.cpp
+++ b/src/core/SkConfig8888.cpp
@@ -18,6 +18,24 @@
 #include "SkRasterPipeline.h"
 #include "SkUnPreMultiply.h"
 
+// Fast Path 1: The memcpy() case.
+static inline bool can_memcpy(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo) {
+    if (dstInfo.colorType() != srcInfo.colorType()) {
+        return false;
+    }
+
+    if (dstInfo.alphaType() != srcInfo.alphaType() &&
+        kOpaque_SkAlphaType != dstInfo.alphaType() &&
+        kOpaque_SkAlphaType != srcInfo.alphaType())
+    {
+        // We need to premultiply or unpremultiply.
+        return false;
+    }
+
+    return !dstInfo.colorSpace() || !srcInfo.colorSpace() ||
+           SkColorSpace::Equals(dstInfo.colorSpace(), srcInfo.colorSpace());
+}
+
 // For now disable 565 in the pipeline. Its (higher) quality is so different its too much to
 // rebase (for now)
 //
@@ -169,10 +187,6 @@
     }
 }
 
-static void memcpy32_row(uint32_t* dst, const uint32_t* src, int count) {
-    memcpy(dst, src, count * 4);
-}
-
 bool SkSrcPixelInfo::convertPixelsTo(SkDstPixelInfo* dst, int width, int height) const {
     SkASSERT(width > 0 && height > 0);
 
@@ -186,14 +200,8 @@
 
     switch (doAlpha) {
         case kNothing_AlphaVerb:
-            if (doSwapRB) {
-                proc = convert32_row<true, kNothing_AlphaVerb>;
-            } else {
-                if (fPixels == dst->fPixels) {
-                    return true;
-                }
-                proc = memcpy32_row;
-            }
+            SkASSERT(doSwapRB);
+            proc = convert32_row<true, kNothing_AlphaVerb>;
             break;
         case kPremul_AlphaVerb:
             if (doSwapRB) {
@@ -370,14 +378,9 @@
     const int width = srcInfo.width();
     const int height = srcInfo.height();
 
-    // Do the easiest one first : both configs are equal
-    if (srcInfo == dstInfo) {
-        size_t bytes = width * srcInfo.bytesPerPixel();
-        for (int y = 0; y < height; ++y) {
-            memcpy(dstPixels, srcPixels, bytes);
-            srcPixels = (const char*)srcPixels + srcRB;
-            dstPixels = (char*)dstPixels + dstRB;
-        }
+    // Fast Path 1: The memcpy() case.
+    if (can_memcpy(dstInfo, srcInfo)) {
+        SkRectMemcpy(dstPixels, dstRB, srcPixels, srcRB, dstInfo.minRowBytes(), dstInfo.height());
         return true;
     }
 
@@ -405,30 +408,6 @@
         return true;
     }
 
-    // If they agree on colorType and the alphaTypes are compatible, then we just memcpy.
-    // Note: we've already taken care of 32bit colortypes above.
-    if (srcInfo.colorType() == dstInfo.colorType()) {
-        switch (srcInfo.colorType()) {
-            case kRGBA_F16_SkColorType:
-                if (!SkColorSpace::Equals(srcInfo.colorSpace(), dstInfo.colorSpace())) {
-                    break;
-                }
-            case kIndex_8_SkColorType:
-            case kARGB_4444_SkColorType:
-                if (srcInfo.alphaType() != dstInfo.alphaType()) {
-                    break;
-                }
-            case kRGB_565_SkColorType:
-            case kAlpha_8_SkColorType:
-            case kGray_8_SkColorType:
-                SkRectMemcpy(dstPixels, dstRB, srcPixels, srcRB,
-                             width * srcInfo.bytesPerPixel(), height);
-                return true;
-            default:
-                break;
-        }
-    }
-
     /*
      *  Begin section where we try to change colorTypes along the way. Not all combinations
      *  are supported.
diff --git a/src/core/SkConfig8888.h b/src/core/SkConfig8888.h
index ff28726..3544cbe 100644
--- a/src/core/SkConfig8888.h
+++ b/src/core/SkConfig8888.h
@@ -9,6 +9,7 @@
 #define SkPixelInfo_DEFINED
 
 #include "SkImageInfo.h"
+#include "SkTemplates.h"
 
 class SkColorTable;
 
@@ -36,12 +37,17 @@
 
 static inline void SkRectMemcpy(void* dst, size_t dstRB, const void* src, size_t srcRB,
                                 size_t bytesPerRow, int rowCount) {
-    SkASSERT(bytesPerRow <= srcRB);
     SkASSERT(bytesPerRow <= dstRB);
+    SkASSERT(bytesPerRow <= srcRB);
+    if (bytesPerRow == dstRB && bytesPerRow == srcRB) {
+        memcpy(dst, src, bytesPerRow * rowCount);
+        return;
+    }
+
     for (int i = 0; i < rowCount; ++i) {
         memcpy(dst, src, bytesPerRow);
-        dst = (char*)dst + dstRB;
-        src = (const char*)src + srcRB;
+        dst = SkTAddOffset<void>(dst, dstRB);
+        src = SkTAddOffset<const void>(src, srcRB);
     }
 }
 
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 9bb4c57..b6b8a5d 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -477,13 +477,8 @@
             dstRow -= layout.rowPitch;
         }
     } else {
-        // If there is no padding on the src (rowBytes) or dst (layout.rowPitch) we can memcpy
-        if (trimRowBytes == rowBytes && trimRowBytes == layout.rowPitch) {
-            memcpy(mapPtr, data, trimRowBytes * height);
-        } else {
-            SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), data, rowBytes, trimRowBytes,
-                         height);
-        }
+        SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), data, rowBytes, trimRowBytes,
+                     height);
     }
 
     GrVkMemory::FlushMappedAlloc(this, alloc);
@@ -580,8 +575,6 @@
                 src -= rowBytes;
                 dst += trimRowBytes;
             }
-        } else if (trimRowBytes == rowBytes) {
-            memcpy(dst, src, trimRowBytes * currentHeight);
         } else {
             SkRectMemcpy(dst, trimRowBytes, src, rowBytes, trimRowBytes, currentHeight);
         }
@@ -966,12 +959,7 @@
 
     // If there is no padding on dst we can do a single memcopy.
     // This assumes the srcData comes in with no padding.
-    if (srcRowBytes == dstRowBytes) {
-        memcpy(mapPtr, srcData, srcRowBytes * h);
-    } else {
-        SkRectMemcpy(mapPtr, static_cast<size_t>(dstRowBytes), srcData, srcRowBytes,
-                     srcRowBytes, h);
-    }
+    SkRectMemcpy(mapPtr, static_cast<size_t>(dstRowBytes), srcData, srcRowBytes, srcRowBytes, h);
     GrVkMemory::FlushMappedAlloc(gpu, alloc);
     GR_VK_CALL(gpu->vkInterface(), UnmapMemory(gpu->device(), alloc.fMemory));
     return true;
@@ -1756,12 +1744,7 @@
             dstRow -= rowBytes;
         }
     } else {
-        if (transBufferRowBytes == rowBytes) {
-            memcpy(buffer, mappedMemory, rowBytes*height);
-        } else {
-            SkRectMemcpy(buffer, rowBytes, mappedMemory, transBufferRowBytes, tightRowBytes,
-                         height);
-        }
+        SkRectMemcpy(buffer, rowBytes, mappedMemory, transBufferRowBytes, tightRowBytes, height);
     }
 
     transferBuffer->unmap();