Bug 1421187 - P3. Optimize pixels data copy and remove extra loop. r?mattwoodrow draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Tue, 28 Nov 2017 16:29:49 +0100
changeset 705062 86e61836040c433a4c729605b9c9cf75de208527
parent 705061 607219d441bf07a22e35a7d52ff3f9c79fd4c888
child 705063 d2ce013777aebeda160ee3f147e53ee3eedc2c79
push id91349
push userbmo:jyavenard@mozilla.com
push dateWed, 29 Nov 2017 12:37:47 +0000
reviewersmattwoodrow
bugs1421187
milestone59.0a1
Bug 1421187 - P3. Optimize pixels data copy and remove extra loop. r?mattwoodrow There's no need to perform the format test within the loop, so we can separate the different cases as needed. Also copy the entire pixel data in one go, by using C types. The skip value definition doesn't specify if it's in bytes, or in "pixels". We will assume the later. There are currently no decoders returning HDR content with a skip value different than zero anyway. MozReview-Commit-ID: KTwYuNKJq3R
gfx/layers/client/TextureClient.cpp
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -1807,49 +1807,79 @@ already_AddRefed<TextureClient>
 TextureClient::CreateWithData(TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator)
 {
   if (!aData) {
     return nullptr;
   }
   return MakeAndAddRef<TextureClient>(aData, aFlags, aAllocator);
 }
 
+template<class PixelDataType>
+static void
+copyData(PixelDataType* aDst,
+         const MappedYCbCrChannelData& aChannelDst,
+         PixelDataType* aSrc,
+         const MappedYCbCrChannelData& aChannelSrc)
+{
+  uint8_t* srcByte = reinterpret_cast<uint8_t*>(aSrc);
+  const int32_t srcSkip = aChannelSrc.skip + 1;
+  uint8_t* dstByte = reinterpret_cast<uint8_t*>(aDst);
+  const int32_t dstSkip = aChannelDst.skip + 1;
+  for (int32_t i = 0; i < aChannelSrc.size.height; ++i) {
+    for (int32_t j = 0; j < aChannelSrc.size.width; ++j) {
+      *aDst = *aSrc;
+      aSrc += srcSkip;
+      aDst += dstSkip;
+    }
+    srcByte += aChannelSrc.stride;
+    aSrc = reinterpret_cast<PixelDataType*>(srcByte);
+    dstByte += aChannelDst.stride;
+    aDst = reinterpret_cast<PixelDataType*>(dstByte);
+  }
+}
+
 bool
 MappedYCbCrChannelData::CopyInto(MappedYCbCrChannelData& aDst)
 {
   if (!data || !aDst.data || size != aDst.size) {
     return false;
   }
 
   if (stride == aDst.stride && skip == aDst.skip) {
     // fast path!
     // We assume that the padding in the destination is there for alignment
     // purposes and doesn't contain useful data.
     memcpy(aDst.data, data, stride * size.height);
     return true;
   }
 
-  for (int32_t i = 0; i < size.height; ++i) {
-    if (aDst.skip == 0 && skip == 0) {
-      // fast-ish path
+  if (aDst.skip == 0 && skip == 0) {
+    // fast-ish path
+    for (int32_t i = 0; i < size.height; ++i) {
       memcpy(aDst.data + i * aDst.stride,
              data + i * stride,
              size.width * bytesPerPixel);
-    } else {
-      // slow path
-      uint8_t* src = data + i * stride;
-      uint8_t* dst = aDst.data + i * aDst.stride;
-      for (int32_t j = 0; j < size.width; ++j) {
-        for (uint32_t k = 0; k < bytesPerPixel; ++k) {
-          *dst = *src;
-          src += 1;
-          dst += 1;
-        }
-        src += skip;
-        dst += aDst.skip;
-      }
     }
+    return true;
+  }
+
+  MOZ_ASSERT(bytesPerPixel == 1 || bytesPerPixel == 2);
+  // slow path
+  if (bytesPerPixel == 1) {
+    copyData(aDst.data, aDst, data, *this);
+  } else if (bytesPerPixel == 2) {
+    if (skip != 0) {
+      // The skip value definition doesn't specify if it's in bytes, or in
+      // "pixels". We will assume the later. There are currently no decoders
+      // returning HDR content with a skip value different than zero anyway.
+      NS_WARNING("skip value non zero for HDR content, please verify code "
+                 "(see bug 1421187)");
+    }
+    copyData(reinterpret_cast<uint16_t*>(aDst.data),
+             aDst,
+             reinterpret_cast<uint16_t*>(data),
+             *this);
   }
   return true;
 }
 
 } // namespace layers
 } // namespace mozilla