tex[Sub]Image2D slow when passing in a <canvas>, faster with ImageData.
https://bugs.webkit.org/show_bug.cgi?id=184843
<rdar://problem/34898868>

Patch by Justin Fan <justin_fan@apple.com> on 2018-04-26
Reviewed by Simon Fraser.

On certain test pages passing 2d canvas objects to gl.texSubImage2D, we spend significant time doing an alpha unpremultiplication in FormatConverter::convert on a single thread.
For now, I am introducing use of the Accelerate framework to do canvas alpha unpremultiplication, specifically for RGBA8 > RGBA8.
This improves this rendering path by a factor of ~4. The rest of FormatConverter could use similar improvements; filed https://bugs.webkit.org/show_bug.cgi?id=185064 for these.

* platform/graphics/FormatConverter.cpp:
(WebCore::FormatConverter::convert):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@231084 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 542a4f3..bc57ac4 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,18 @@
+2018-04-26  Justin Fan  <justin_fan@apple.com>
+
+        tex[Sub]Image2D slow when passing in a <canvas>, faster with ImageData.
+        https://bugs.webkit.org/show_bug.cgi?id=184843
+        <rdar://problem/34898868>
+
+        Reviewed by Simon Fraser.
+
+        On certain test pages passing 2d canvas objects to gl.texSubImage2D, we spend significant time doing an alpha unpremultiplication in FormatConverter::convert on a single thread. 
+        For now, I am introducing use of the Accelerate framework to do canvas alpha unpremultiplication, specifically for RGBA8 > RGBA8.
+        This improves this rendering path by a factor of ~4. The rest of FormatConverter could use similar improvements; filed https://bugs.webkit.org/show_bug.cgi?id=185064 for these. 
+
+        * platform/graphics/FormatConverter.cpp:
+        (WebCore::FormatConverter::convert):
+
 2018-04-26  Simon Fraser  <simon.fraser@apple.com>
 
         Implement rendering support for the color-filter CSS property
diff --git a/Source/WebCore/platform/graphics/FormatConverter.cpp b/Source/WebCore/platform/graphics/FormatConverter.cpp
index 3fb9a7e..10e0d17 100644
--- a/Source/WebCore/platform/graphics/FormatConverter.cpp
+++ b/Source/WebCore/platform/graphics/FormatConverter.cpp
@@ -35,6 +35,10 @@
 #include "GraphicsContext3DNEON.h"
 #endif
 
+#if USE(ACCELERATE)
+#include <Accelerate/Accelerate.h>
+#endif
+
 namespace WebCore {
 
 
@@ -1241,6 +1245,9 @@
 
     const SrcType *srcRowStart = static_cast<const SrcType*>(m_srcStart);
     DstType* dstRowStart = static_cast<DstType*>(m_dstStart);
+    
+    m_success = true;
+    
     if (!trivialUnpack && trivialPack) {
         for (size_t i = 0; i < m_height; ++i) {
             unpack<SrcFormat>(srcRowStart, dstRowStart, m_width);
@@ -1255,14 +1262,33 @@
             dstRowStart += dstStrideInElements;
         }
     } else {
+#if USE(ACCELERATE)
+        if (SrcFormat == GraphicsContext3D::DataFormatRGBA8
+            && DstFormat == GraphicsContext3D::DataFormatRGBA8
+            && alphaOp == GraphicsContext3D::AlphaDoUnmultiply) {
+            vImage_Buffer src;
+            src.width = m_width;
+            src.height = m_height;
+            src.rowBytes = m_srcStride;
+            src.data = const_cast<void*>(m_srcStart);
+
+            vImage_Buffer dst;
+            dst.width = m_width;
+            dst.height = m_height;
+            dst.rowBytes = m_dstStride;
+            dst.data = m_dstStart;
+
+            vImageUnpremultiplyData_RGBA8888(&src, &dst, kvImageNoFlags);
+            
+            return;
+        }
+#endif
         for (size_t i = 0; i < m_height; ++i) {
             pack<DstFormat, alphaOp>(srcRowStart, dstRowStart, m_width);
             srcRowStart += srcStrideInElements;
             dstRowStart += dstStrideInElements;
         }
     }
-    m_success = true;
-    return;
 }
 
 } // namespace WebCore