Bug 747274 - Add a pref (default to true on Android) to forcible use nearest pixel filtering for background drawing. r=jrmuizel,ajuma a=blassey
authorGeorge Wright <gwright@mozilla.com>
Tue, 24 Apr 2012 10:28:46 -0400
changeset 92200 b88fba85586ba81d8709fbcdcc15a0b7e36a025a
parent 92199 bf3d41520582e8c03a4d835750fa548e5143d024
child 92207 f410f3436cdbf5e7c6f62209d41beb61bb319232
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjrmuizel, ajuma, blassey
bugs747274
milestone14.0a1
Bug 747274 - Add a pref (default to true on Android) to forcible use nearest pixel filtering for background drawing. r=jrmuizel,ajuma a=blassey
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/reftests/backgrounds/reftest.list
layout/reftests/backgrounds/vector/reftest.list
modules/libpref/src/init/all.js
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -163,16 +163,30 @@ nsLayoutUtils::Are3DTransformsEnabled()
     s3DTransformPrefCached = true;
     mozilla::Preferences::AddBoolVarCache(&s3DTransformsEnabled, 
                                           "layout.3d-transforms.enabled");
   }
 
   return s3DTransformsEnabled;
 }
 
+bool
+nsLayoutUtils::UseBackgroundNearestFiltering()
+{
+  static bool sUseBackgroundNearestFilteringEnabled;
+  static bool sUseBackgroundNearestFilteringPrefInitialised = false;
+
+  if (!sUseBackgroundNearestFilteringPrefInitialised) {
+    sUseBackgroundNearestFilteringPrefInitialised = true;
+    sUseBackgroundNearestFilteringEnabled = mozilla::Preferences::GetBool("gfx.filter.nearest.force-enabled", false);
+  }
+
+  return sUseBackgroundNearestFilteringEnabled;
+}
+
 void
 nsLayoutUtils::UnionChildOverflow(nsIFrame* aFrame,
                                   nsOverflowAreas& aOverflowAreas)
 {
   // Iterate over all children except pop-ups.
   const nsIFrame::ChildListIDs skip(nsIFrame::kPopupList |
                                     nsIFrame::kSelectPopupList);
   for (nsIFrame::ChildListIterator childLists(aFrame);
@@ -3729,16 +3743,21 @@ nsLayoutUtils::DrawBackgroundImage(nsRen
                                    GraphicsFilter      aGraphicsFilter,
                                    const nsRect&       aDest,
                                    const nsRect&       aFill,
                                    const nsPoint&      aAnchor,
                                    const nsRect&       aDirty,
                                    PRUint32            aImageFlags)
 {
   SAMPLE_LABEL("layout", "nsLayoutUtils::DrawBackgroundImage");
+
+  if (UseBackgroundNearestFiltering()) {
+    aGraphicsFilter = gfxPattern::FILTER_NEAREST;
+  }
+
   return DrawImageInternal(aRenderingContext, aImage, aGraphicsFilter,
                            aDest, aFill, aAnchor, aDirty,
                            aImageSize, aImageFlags);
 }
 
 /* static */ nsresult
 nsLayoutUtils::DrawImage(nsRenderingContext* aRenderingContext,
                          imgIContainer*       aImage,
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -1492,16 +1492,22 @@ public:
                                         bool clear);
 
   /**
    * Checks if CSS 3D transforms are currently enabled.
    */
   static bool Are3DTransformsEnabled();
 
   /**
+   * Checks if we should forcibly use nearest pixel filtering for the
+   * background.
+   */
+  static bool UseBackgroundNearestFiltering();
+
+  /**
    * Unions the overflow areas of all non-popup children of aFrame with
    * aOverflowAreas.
    */
   static void UnionChildOverflow(nsIFrame* aFrame,
                                  nsOverflowAreas& aOverflowAreas);
 
   /**
    * Return whether this is a frame whose width is used when computing
--- a/layout/reftests/backgrounds/reftest.list
+++ b/layout/reftests/backgrounds/reftest.list
@@ -112,17 +112,18 @@ fails-if(Android) == viewport-translucen
 == background-size-monster-px.html background-size-monster-ref.html
 == background-size-monster-rem.html background-size-monster-ref.html
 
 # There seems to be a pixel-snapping problem here, where the repeated background
 # image isn't being snapped at its boundaries.  Note that the boundaries within
 # the image aren't the issue, because they're being obscured to avoid sampling
 # algorithm dependencies (at least assuming the sampling algorithm in use
 # doesn't sample too far astray from the boundaries).
-fails == background-size-zoom-repeat.html background-size-zoom-repeat-ref.html
+# Android uses FILTER_NEAREST which doesn't suffer from this issue.
+fails-if(!Android) == background-size-zoom-repeat.html background-size-zoom-repeat-ref.html
 
 # -moz-default-background-color and -moz-default-color (bug 591341)
 == background-moz-default-background-color.html background-moz-default-background-color-ref.html
 
 == fixed-bg-with-transform-outside-viewport-1.html fixed-bg-with-transform-outside-viewport-ref.html
 
 HTTP == root-background-1.html root-background-ref.html
 HTTP != root-background-1.html about:blank
--- a/layout/reftests/backgrounds/vector/reftest.list
+++ b/layout/reftests/backgrounds/vector/reftest.list
@@ -81,18 +81,19 @@ include empty/reftest.list
 == tall--contain--percent-width-nonpercent-height.html ref-tall-lime256x384-aqua256x384.html
 == tall--contain--percent-width-nonpercent-height-viewbox.html ref-tall-lime48x384-aqua48x384.html
 == tall--contain--percent-width-omitted-height.html ref-tall-lime256x384-aqua256x384.html
 == tall--contain--percent-width-omitted-height-viewbox.html ref-tall-lime48x384-aqua48x384.html
 == tall--contain--percent-width-percent-height.html ref-tall-lime256x384-aqua256x384.html
 == tall--contain--percent-width-percent-height-viewbox.html ref-tall-lime48x384-aqua48x384.html
 
 # We smear the background image when scaling it in these two tests...
-fails == tall--cover--nonpercent-width-nonpercent-height.html ref-tall-lime256x512-aqua256x256.html
-fails == tall--cover--nonpercent-width-nonpercent-height-viewbox.html ref-tall-lime256x512-aqua256x256.html
+# Android uses FILTER_NEAREST for background images so the smear doesn't occur
+fails-if(!Android) == tall--cover--nonpercent-width-nonpercent-height.html ref-tall-lime256x512-aqua256x256.html
+fails-if(!Android) == tall--cover--nonpercent-width-nonpercent-height-viewbox.html ref-tall-lime256x512-aqua256x256.html
 
 # ...but we don't in identical tests with image-rendering: -moz-crisp-edges.
 == tall--cover--nonpercent-width-nonpercent-height--crisp.html ref-tall-lime256x512-aqua256x256.html
 == tall--cover--nonpercent-width-nonpercent-height-viewbox--crisp.html ref-tall-lime256x512-aqua256x256.html
 
 == tall--cover--nonpercent-width-omitted-height.html ref-tall-lime256x384-aqua256x384.html
 == tall--cover--nonpercent-width-omitted-height-viewbox.html ref-tall-lime256x768.html
 == tall--cover--nonpercent-width-percent-height.html ref-tall-lime256x384-aqua256x384.html
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -207,16 +207,22 @@ pref("gfx.color_management.mode", 2);
 pref("gfx.color_management.display_profile", "");
 pref("gfx.color_management.rendering_intent", 0);
 pref("gfx.color_management.enablev4", false);
 
 pref("gfx.downloadable_fonts.enabled", true);
 pref("gfx.downloadable_fonts.fallback_delay", 3000);
 pref("gfx.downloadable_fonts.sanitize", true);
 
+#ifdef ANDROID
+pref("gfx.filter.nearest.force-enabled", true);
+#else
+pref("gfx.filter.nearest.force-enabled", false);
+#endif
+
 // whether to always search all font cmaps during system font fallback
 pref("gfx.font_rendering.fallback.always_use_cmaps", false);
 
 #ifdef MOZ_GRAPHITE
 pref("gfx.font_rendering.graphite.enabled", false);
 #endif
 
 // see gfx/thebes/gfxUnicodeProperties.h for definitions of script bits