Bug 1256475 - Use libyuv for non scaling YUV color conversion r=jrmuizel
☠☠ backed out by d8c954e520e4 ☠ ☠
authorSotaro Ikeda <sotaro.ikeda.g@gmail.com>
Mon, 06 Jun 2016 20:10:59 -0700
changeset 376168 c88f2cb8e4fae6764f559c0e43a93edd518102d2
parent 376167 851259fb3bc45b0ef5c54c390fb953ec0789096d
child 376169 b093026fc747724b11856fcf72e6dccfdaac829c
push id20510
push usercholler@mozilla.com
push dateTue, 07 Jun 2016 13:42:30 +0000
reviewersjrmuizel
bugs1256475
milestone50.0a1
Bug 1256475 - Use libyuv for non scaling YUV color conversion r=jrmuizel
gfx/thebes/gfxPrefs.h
gfx/thebes/gfxUtils.cpp
gfx/ycbcr/chromium_types.h
gfx/ycbcr/moz.build
gfx/ycbcr/yuv_convert.cpp
gfx/ycbcr/yuv_convert.h
layout/reftests/webm-video/reftest.list
modules/libpref/init/all.js
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -268,16 +268,17 @@ private:
   DECL_GFX_PREF(Once, "gfx.logging.peak-texture-usage.enabled",GfxLoggingPeakTextureUsageEnabled, bool, false);
   DECL_GFX_PREF(Once, "gfx.max-alloc-size",                    MaxAllocSize, int32_t, (int32_t)500000000);
   DECL_GFX_PREF(Once, "gfx.max-texture-size",                  MaxTextureSize, int32_t, (int32_t)32767);
   DECL_GFX_PREF(Live, "gfx.partialpresent.force",              PartialPresent, int32_t, 0);
   DECL_GFX_PREF(Live, "gfx.perf-warnings.enabled",             PerfWarnings, bool, false);
   DECL_GFX_PREF(Live, "gfx.SurfaceTexture.detach.enabled",     SurfaceTextureDetachEnabled, bool, true);
   DECL_GFX_PREF(Live, "gfx.testing.device-reset",              DeviceResetForTesting, int32_t, 0);
   DECL_GFX_PREF(Live, "gfx.testing.device-fail",               DeviceFailForTesting, bool, false);
+  DECL_GFX_PREF(Live, "gfx.ycbcr.accurate-conversion",         YCbCrAccurateConversion, bool, false);
 
   DECL_GFX_PREF(Live, "gfx.content.use-native-pushlayer",      UseNativePushLayer, bool, false);
 
   // Disable surface sharing due to issues with compatible FBConfigs on
   // NVIDIA drivers as described in bug 1193015.
   DECL_GFX_PREF(Live, "gfx.use-glx-texture-from-pixmap",       UseGLXTextureFromPixmap, bool, false);
 
   // These times should be in milliseconds
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -26,18 +26,16 @@
 #include "nsComponentManagerUtils.h"
 #include "nsIClipboardHelper.h"
 #include "nsIFile.h"
 #include "nsIGfxInfo.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsRegion.h"
 #include "nsServiceManagerUtils.h"
-#include "yuv_convert.h"
-#include "ycbcr_to_rgb565.h"
 #include "GeckoProfiler.h"
 #include "ImageContainer.h"
 #include "ImageRegion.h"
 #include "gfx2DGlue.h"
 #include "gfxPrefs.h"
 
 #ifdef XP_WIN
 #include "gfxWindowsPlatform.h"
--- a/gfx/ycbcr/chromium_types.h
+++ b/gfx/ycbcr/chromium_types.h
@@ -2,24 +2,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef GFX_CHROMIUMTYPES_H
 #define GFX_CHROMIUMTYPES_H
 
 #include <stdint.h>
 
-// On Windows, protypes.h is #included, which defines these types.  This sucks!
-#ifndef PROTYPES_H
-typedef uint8_t uint8;
-typedef int8_t int8;
-typedef int16_t int16;
-typedef uint16_t uint16;
-typedef uint32_t uint32;
-#endif
+#include "libyuv/basic_types.h"
 
 // From Chromium build_config.h:
 // Processor architecture detection.  For more info on what's defined, see:
 //   http://msdn.microsoft.com/en-us/library/b0084kay.aspx
 //   http://www.agner.org/optimize/calling_conventions.pdf
 //   or with gcc, run: "echo | gcc -E -dM -"
 #if defined(_M_X64) || defined(__x86_64__)
 #define ARCH_CPU_X86_FAMILY 1
--- a/gfx/ycbcr/moz.build
+++ b/gfx/ycbcr/moz.build
@@ -1,20 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS += [
-    'chromium_types.h',
-    'ycbcr_to_rgb565.h',
     'YCbCrUtils.h',
-    'yuv_convert.h',
-    'yuv_row.h',
 ]
 
 UNIFIED_SOURCES += [
     'ycbcr_to_rgb565.cpp',
     'YCbCrUtils.cpp',
     'yuv_convert.cpp',
     'yuv_row_c.cpp',
     'yuv_row_table.cpp',
@@ -58,9 +54,11 @@ else:
 if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['HAVE_ARM_NEON']:
     SOURCES += [
         'yuv_row_arm.s',
     ]
     SOURCES += [
         'yuv_convert_arm.cpp',
     ]
 
+LOCAL_INCLUDES += ['/media/libyuv/include']
+
 FINAL_LIBRARY = 'xul'
--- a/gfx/ycbcr/yuv_convert.cpp
+++ b/gfx/ycbcr/yuv_convert.cpp
@@ -13,16 +13,18 @@
 // YV16 is a full plane of Y and a full height, half width chroma planes
 // YV24 is a full plane of Y and a full height, full width chroma planes
 //
 // ARGB pixel format is output, which on little endian is stored as BGRA.
 // The alpha is set to 255, allowing the application to use RGBA or RGB32.
 
 #include "yuv_convert.h"
 
+#include "gfxPrefs.h"
+#include "libyuv.h"
 // Header for low level row functions.
 #include "yuv_row.h"
 #include "mozilla/SSE.h"
 
 namespace mozilla {
 
 namespace gfx {
 
@@ -55,16 +57,82 @@ void ConvertYCbCrToRGB32(const uint8* y_
                          int pic_x,
                          int pic_y,
                          int pic_width,
                          int pic_height,
                          int y_pitch,
                          int uv_pitch,
                          int rgb_pitch,
                          YUVType yuv_type) {
+
+
+  // Deprecated function's conversion is accurate.
+  // libyuv converion is a bit inaccurate to get performance. It dynamically
+  // calculates RGB from YUV to use simd. In it, signed byte is used for conversion's
+  // coefficient, but it requests 129. libyuv cut 129 to 127. And only 6 bits are
+  // used for a decimal part during the dynamic calculation.
+  //
+  // The function is still fast on some old intel chips.
+  // See Bug 1256475.
+  bool use_deprecated = gfxPrefs::YCbCrAccurateConversion() ||
+                        (supports_mmx() && supports_sse() && !supports_sse3());
+  if (use_deprecated) {
+    ConvertYCbCrToRGB32_deprecated(y_buf, u_buf, v_buf, rgb_buf,
+                                   pic_x, pic_y, pic_width, pic_height,
+                                   y_pitch, uv_pitch, rgb_pitch, yuv_type);
+    return;
+  }
+                                    
+  if (yuv_type == YV24) {
+    const uint8* src_y = y_buf + y_pitch * pic_y + pic_x;
+    const uint8* src_u = u_buf + uv_pitch * pic_y + pic_x;
+    const uint8* src_v = v_buf + uv_pitch * pic_y + pic_x;
+    DebugOnly<int> err = libyuv::I444ToARGB(src_y, y_pitch,
+                                            src_u, uv_pitch,
+                                            src_v, uv_pitch,
+                                            rgb_buf, rgb_pitch,
+                                            pic_width, pic_height);
+    MOZ_ASSERT(!err);
+  } else if (yuv_type == YV16) {
+    const uint8* src_y = y_buf + y_pitch * pic_y + pic_x;
+    const uint8* src_u = u_buf + uv_pitch * pic_y + pic_x / 2;
+    const uint8* src_v = v_buf + uv_pitch * pic_y + pic_x / 2;
+    DebugOnly<int> err = libyuv::I422ToARGB(src_y, y_pitch,
+                                            src_u, uv_pitch,
+                                            src_v, uv_pitch,
+                                            rgb_buf, rgb_pitch,
+                                            pic_width, pic_height);
+    MOZ_ASSERT(!err);
+  } else {
+    MOZ_ASSERT(yuv_type == YV12);
+    const uint8* src_y = y_buf + y_pitch * pic_y + pic_x;
+    const uint8* src_u = u_buf + (uv_pitch * pic_y + pic_x) / 2;
+    const uint8* src_v = v_buf + (uv_pitch * pic_y + pic_x) / 2;
+    DebugOnly<int> err = libyuv::I420ToARGB(src_y, y_pitch,
+                                            src_u, uv_pitch,
+                                            src_v, uv_pitch,
+                                            rgb_buf, rgb_pitch,
+                                            pic_width, pic_height);
+    MOZ_ASSERT(!err);
+  }
+}
+
+// Convert a frame of YUV to 32 bit ARGB.
+void ConvertYCbCrToRGB32_deprecated(const uint8* y_buf,
+                                    const uint8* u_buf,
+                                    const uint8* v_buf,
+                                    uint8* rgb_buf,
+                                    int pic_x,
+                                    int pic_y,
+                                    int pic_width,
+                                    int pic_height,
+                                    int y_pitch,
+                                    int uv_pitch,
+                                    int rgb_pitch,
+                                    YUVType yuv_type) {
   unsigned int y_shift = yuv_type == YV12 ? 1 : 0;
   unsigned int x_shift = yuv_type == YV24 ? 0 : 1;
   // Test for SSE because the optimized code uses movntq, which is not part of MMX.
   bool has_sse = supports_mmx() && supports_sse();
   // There is no optimized YV24 SSE routine so we check for this and
   // fall back to the C code.
   has_sse &= yuv_type != YV24;
   bool odd_pic_x = yuv_type != YV24 && pic_x % 2 != 0;
--- a/gfx/ycbcr/yuv_convert.h
+++ b/gfx/ycbcr/yuv_convert.h
@@ -52,16 +52,29 @@ void ConvertYCbCrToRGB32(const uint8* yp
                          int pic_y,
                          int pic_width,
                          int pic_height,
                          int ystride,
                          int uvstride,
                          int rgbstride,
                          YUVType yuv_type);
 
+void ConvertYCbCrToRGB32_deprecated(const uint8* yplane,
+                                    const uint8* uplane,
+                                    const uint8* vplane,
+                                    uint8* rgbframe,
+                                    int pic_x,
+                                    int pic_y,
+                                    int pic_width,
+                                    int pic_height,
+                                    int ystride,
+                                    int uvstride,
+                                    int rgbstride,
+                                    YUVType yuv_type);
+
 // Scale a frame of YUV to 32 bit ARGB.
 // Supports rotation and mirroring.
 void ScaleYCbCrToRGB32(const uint8* yplane,
                        const uint8* uplane,
                        const uint8* vplane,
                        uint8* rgbframe,
                        int source_width,
                        int source_height,
--- a/layout/reftests/webm-video/reftest.list
+++ b/layout/reftests/webm-video/reftest.list
@@ -34,17 +34,17 @@ skip-if(Android||B2G||Mulet) == poster-1
 skip-if(Android||B2G||Mulet) == poster-15.html poster-ref-green70x30.html # Initial mulet triage: parity with B2G/B2G Desktop
 random-if(winWidget) random-if(cocoaWidget) skip-if(Android||B2G||Mulet) == bug686957.html bug686957-ref.html # bug 922951 for OS X # Initial mulet triage: parity with B2G/B2G Desktop
 
 # Tests for <video src> with 'object-fit' & 'object-position':
 # These tests should be very similar to tests in our w3c-css/submitted/images3
 # reftest directory. They live here because they use WebM video (VP9), and it
 # wouldn't be fair of us to make a W3C testsuite implicitly depend on any
 # particular (non-spec-mandated) video codec.
-default-preferences test-pref(layout.css.object-fit-and-position.enabled,true)
+default-preferences test-pref(layout.css.object-fit-and-position.enabled,true) test-pref(gfx.ycbcr.accurate-conversion,true)
 fails-if(layersGPUAccelerated) skip-if(Android||B2G||Mulet) == object-fit-contain-webm-001.html object-fit-contain-webm-001-ref.html # Bug 1083516 for layersGPUAccelerated failures, Bug 1084564 for Android/B2G failures # Initial mulet triage: parity with B2G/B2G Desktop
 fails-if(layersGPUAccelerated) skip-if(Android||B2G||Mulet) == object-fit-contain-webm-002.html object-fit-contain-webm-002-ref.html # Bug 1083516 for layersGPUAccelerated failures, Bug 1084564 for Android/B2G failures # Initial mulet triage: parity with B2G/B2G Desktop
 fails-if(layersGPUAccelerated) skip-if(Android||B2G||Mulet) == object-fit-cover-webm-001.html object-fit-cover-webm-001-ref.html # Bug 1083516 for layersGPUAccelerated failures, Bug 1084564 for Android/B2G failures # Initial mulet triage: parity with B2G/B2G Desktop
 fails-if(layersGPUAccelerated) skip-if(Android||B2G||Mulet) == object-fit-cover-webm-002.html object-fit-cover-webm-002-ref.html # Bug 1083516 for layersGPUAccelerated failures, Bug 1084564 for Android/B2G failures # Initial mulet triage: parity with B2G/B2G Desktop
 fails-if(layersGPUAccelerated) skip-if(Android||B2G||Mulet) == object-fit-fill-webm-001.html object-fit-fill-webm-001-ref.html # Bug 1083516 for layersGPUAccelerated failures, Bug 1084564 for Android/B2G failures # Initial mulet triage: parity with B2G/B2G Desktop
 fails-if(layersGPUAccelerated) skip-if(Android||B2G||Mulet) == object-fit-fill-webm-002.html object-fit-fill-webm-002-ref.html # Bug 1083516 for layersGPUAccelerated failures, Bug 1084564 for Android/B2G failures # Initial mulet triage: parity with B2G/B2G Desktop
 fails-if(layersGPUAccelerated) skip-if(Android||B2G||Mulet) == object-fit-none-webm-001.html object-fit-none-webm-001-ref.html # Bug 1083516 for layersGPUAccelerated failures, Bug 1084564 for Android/B2G failures # Initial mulet triage: parity with B2G/B2G Desktop
 fails-if(layersGPUAccelerated) skip-if(Android||B2G||Mulet) == object-fit-none-webm-002.html object-fit-none-webm-002-ref.html # Bug 1083516 for layersGPUAccelerated failures, Bug 1084564 for Android/B2G failures # Initial mulet triage: parity with B2G/B2G Desktop
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -759,16 +759,18 @@ pref("gfx.work-around-driver-bugs", true
 pref("gfx.prefer-mesa-llvmpipe", false);
 
 pref("gfx.draw-color-bars", false);
 
 pref("gfx.logging.painted-pixel-count.enabled", false);
 pref("gfx.logging.texture-usage.enabled", false);
 pref("gfx.logging.peak-texture-usage.enabled", false);
 
+pref("gfx.ycbcr.accurate-conversion", false);
+
 pref("accessibility.browsewithcaret", false);
 pref("accessibility.warn_on_browsewithcaret", true);
 
 pref("accessibility.browsewithcaret_shortcut.enabled", true);
 
 #ifndef XP_MACOSX
 // Tab focus model bit field:
 // 1 focuses text controls, 2 focuses other form elements, 4 adds links.