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
--- 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