Bug 486918 - Create and obey a high-quality downscaling pref, and turn it off on OS X and mobile. r=jlebar
authorJoe Drew <joe@drew.ca>
Thu, 27 Sep 2012 14:12:56 -0400
changeset 108789 aaf9e3020132bbeeaff9180d9da9d1da76b81f53
parent 108788 27e0c22b96e5ef918e0de7817ee572a26d0aa274
child 108790 129629b6106fb033310e9cb8f363c2fa00e586c9
child 108856 a17579743ac9d4c34e68ee7e321af7df14432004
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersjlebar
bugs486918
milestone18.0a1
Bug 486918 - Create and obey a high-quality downscaling pref, and turn it off on OS X and mobile. r=jlebar
b2g/app/b2g.js
image/src/RasterImage.cpp
layout/tools/reftest/bootstrap.js
layout/tools/reftest/reftest-cmdline.js
mobile/android/app/mobile.js
modules/libpref/src/init/all.js
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -22,16 +22,17 @@ pref("browser.cache.disk.parent_director
 pref("browser.cache.disk.smart_size.enabled", false);
 pref("browser.cache.disk.smart_size.first_run", false);
 
 pref("browser.cache.memory.enable", true);
 pref("browser.cache.memory.capacity", 1024); // kilobytes
 
 /* image cache prefs */
 pref("image.cache.size", 1048576); // bytes
+pref("image.high_quality_downscaling.enabled", false);
 
 /* offline cache prefs */
 pref("browser.offline-apps.notify", false);
 pref("browser.cache.offline.enable", true);
 pref("offline-apps.allow_by_default", true);
 
 /* protocol warning prefs */
 pref("network.protocol-handler.warn-external.tel", false);
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -104,24 +104,31 @@ static PRLogModuleInfo *gCompressedImage
 #define gCompressedImageAccountingLog
 #endif
 
 // Tweakable progressive decoding parameters.  These are initialized to 0 here
 // because otherwise, we have to initialize them in a static initializer, which
 // makes us slower to start up.
 static uint32_t gDecodeBytesAtATime = 0;
 static uint32_t gMaxMSBeforeYield = 0;
+static bool gHQDownscaling = false;
+// This is interpreted as a floating-point value / 1000
+static uint32_t gHQDownscalingMinFactor = 1000;
 
 static void
 InitPrefCaches()
 {
   Preferences::AddUintVarCache(&gDecodeBytesAtATime,
                                "image.mem.decode_bytes_at_a_time", 200000);
   Preferences::AddUintVarCache(&gMaxMSBeforeYield,
                                "image.mem.max_ms_before_yield", 400);
+  Preferences::AddBoolVarCache(&gHQDownscaling,
+                               "image.high_quality_downscaling.enabled", false);
+  Preferences::AddUintVarCache(&gHQDownscalingMinFactor,
+                               "image.high_quality_downscaling.min_factor", 1000);
 }
 
 /* We define our own error checking macros here for 2 reasons:
  *
  * 1) Most of the failures we encounter here will (hopefully) be
  * the result of decoding failures (ie, bad data) and not code
  * failures. As such, we don't want to clutter up debug consoles
  * with spurious messages about NS_ENSURE_SUCCESS failures.
@@ -184,19 +191,16 @@ DiscardingEnabled()
 
   return enabled;
 }
 
 namespace mozilla {
 namespace image {
 
 /* static */ StaticRefPtr<RasterImage::DecodeWorker> RasterImage::DecodeWorker::sSingleton;
-
-#define PRE_DOWNSCALE_MIN_FACTOR 0.9
-
 /* static */ nsRefPtr<RasterImage::ScaleWorker> RasterImage::ScaleWorker::sSingleton;
 /* static */ nsRefPtr<RasterImage::DrawWorker> RasterImage::DrawWorker::sSingleton;
 static nsCOMPtr<nsIThread> sScaleWorkerThread = nullptr;
 
 #ifndef DEBUG
 NS_IMPL_ISUPPORTS3(RasterImage, imgIContainer, nsIProperties,
                    nsISupportsWeakReference)
 #else
@@ -2788,24 +2792,25 @@ RasterImage::ScaleRequest::Stop(RasterIm
 }
 
 bool
 RasterImage::CanScale(gfxPattern::GraphicsFilter aFilter,
                       gfxSize aScale)
 {
 // The high-quality scaler requires Skia.
 #ifdef MOZ_ENABLE_SKIA
-  return (aFilter == gfxPattern::FILTER_GOOD) &&
-          !mAnim && mDecoded &&
-          (aScale.width <= 1.0 && aScale.height <= 1.0) &&
-          (aScale.width < PRE_DOWNSCALE_MIN_FACTOR ||
-           aScale.height < PRE_DOWNSCALE_MIN_FACTOR);
-#else
+  if (gHQDownscaling && aFilter == gfxPattern::FILTER_GOOD &&
+      !mAnim && mDecoded &&
+      (aScale.width <= 1.0 && aScale.height <= 1.0)) {
+    gfxFloat factor = gHQDownscalingMinFactor / 1000.0;
+    return (aScale.width < factor || aScale.height < factor);
+  }
+#endif
+
   return false;
-#endif
 }
 
 void
 RasterImage::DrawWithPreDownscaleIfNeeded(imgFrame *aFrame,
                                           gfxContext *aContext,
                                           gfxPattern::GraphicsFilter aFilter,
                                           const gfxMatrix &aUserSpaceToImageSpace,
                                           const gfxRect &aFill,
--- a/layout/tools/reftest/bootstrap.js
+++ b/layout/tools/reftest/bootstrap.js
@@ -22,16 +22,18 @@ function setDefaultPrefs() {
     branch.setIntPref("hangmonitor.timeout", 0);
     // Ensure autoplay is enabled for all platforms.
     branch.setBoolPref("media.autoplay.enabled", true);
     // Disable updates
     branch.setBoolPref("app.update.enabled", false);
     // Disable addon updates and prefetching so we don't leak them
     branch.setBoolPref("extensions.update.enabled", false);
     branch.setBoolPref("extensions.getAddons.cache.enabled", false);
+    // Disable high-quality downscaling, since it makes reftests more difficult.
+    branch.setBoolPref("image.high_quality_downscaling.enabled", false);
 }
 
 var windowListener = {
     onOpenWindow: function(aWindow) {
         let domWindow = aWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowInternal || Components.interfaces.nsIDOMWindow);
         domWindow.addEventListener("load", function() {
             domWindow.removeEventListener("load", arguments.callee, false);
 
--- a/layout/tools/reftest/reftest-cmdline.js
+++ b/layout/tools/reftest/reftest-cmdline.js
@@ -86,16 +86,18 @@ RefTestCmdLineHandler.prototype =
     branch.setIntPref("hangmonitor.timeout", 0);
     // Ensure autoplay is enabled for all platforms.
     branch.setBoolPref("media.autoplay.enabled", true);
     // Disable updates
     branch.setBoolPref("app.update.enabled", false);
     // Disable addon updates and prefetching so we don't leak them
     branch.setBoolPref("extensions.update.enabled", false);
     branch.setBoolPref("extensions.getAddons.cache.enabled", false);
+    // Disable high-quality downscaling, since it makes reftests more difficult.
+    branch.setBoolPref("image.high_quality_downscaling.enabled", false);
 
     var wwatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
                            .getService(nsIWindowWatcher);
     wwatch.openWindow(null, "chrome://reftest/content/reftest.xul", "_blank",
                       "chrome,dialog=no,all", args);
     cmdLine.preventDefault = true;
   },
 
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -55,16 +55,17 @@ pref("browser.cache.disk.smart_size.firs
 pref("browser.cache.memory.enable", false);
 #else
 pref("browser.cache.memory.enable", true);
 #endif
 pref("browser.cache.memory.capacity", 1024); // kilobytes
 
 /* image cache prefs */
 pref("image.cache.size", 1048576); // bytes
+pref("image.high_quality_downscaling.enabled", false);
 
 /* offline cache prefs */
 pref("browser.offline-apps.notify", true);
 pref("browser.cache.offline.enable", true);
 pref("browser.cache.offline.capacity", 5120); // kilobytes
 pref("offline-apps.quota.warn", 1024); // kilobytes
 
 // cache compression turned off for now - see bug #715198
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -3515,26 +3515,38 @@ pref("browser.formfill.boundaryWeight", 
 pref("browser.formfill.prefixWeight",     5);
 
 // Zoom prefs
 pref("browser.zoom.full", false);
 pref("zoom.minPercent", 30);
 pref("zoom.maxPercent", 300);
 pref("toolkit.zoomManager.zoomValues", ".3,.5,.67,.8,.9,1,1.1,1.2,1.33,1.5,1.7,2,2.4,3");
 
-// Image cache prefs
+// Image-related prefs
 // The maximum size, in bytes, of the decoded images we cache
 pref("image.cache.size", 5242880);
 // A weight, from 0-1000, to place on time when comparing to size.
 // Size is given a weight of 1000 - timeweight.
 pref("image.cache.timeweight", 500);
 
 // The default Accept header sent for images loaded over HTTP(S)
 pref("image.http.accept", "image/png,image/*;q=0.8,*/*;q=0.5");
 
+// Whether we do high-quality image downscaling. OS X natively supports
+// high-quality image scaling.
+#ifdef XP_MACOSX
+pref("image.high_quality_downscaling.enabled", false);
+#else
+pref("image.high_quality_downscaling.enabled", true);
+#endif
+
+// The minimum percent downscaling we'll use high-quality downscaling on,
+// interpreted as a floating-point number / 1000.
+pref("image.high_quality_downscaling.min_factor", 1000);
+
 //
 // Image memory management prefs
 //
 
 // Discards inactive image frames and re-decodes them on demand from
 // compressed data.
 pref("image.mem.discardable", true);