Bug 800319 - Make the gradient cache differentiate between backend types. r=Bas
authorPaul Adenot <paul@paul.cx>
Fri, 26 Oct 2012 15:34:43 +0200
changeset 111695 70f9b80d208702240bb5255e5607b0f033123beb
parent 111694 48a8c0a22b24ff3b2de9e10fd4162ae33caf4358
child 111696 ceb1c72cd35f4a8eadfec7f307d5804a53973981
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersBas
bugs800319
milestone19.0a1
Bug 800319 - Make the gradient cache differentiate between backend types. r=Bas
layout/base/nsCSSRendering.cpp
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -44,16 +44,17 @@
 #include "nsSVGIntegrationUtils.h"
 #include "gfxDrawable.h"
 #include "sampler.h"
 #include "nsCSSRenderingBorders.h"
 #include "mozilla/css/ImageLoader.h"
 #include "ImageContainer.h"
 #include "mozilla/HashFunctions.h"
 #include "mozilla/Telemetry.h"
+#include "mozilla/Types.h"
 #include <ctime>
 
 using namespace mozilla;
 using namespace mozilla::css;
 
 // To avoid storing this data on nsInlineFrame (bloat) and to avoid
 // recalculating this for each frame in a continuation (perf), hold
 // a cache of various coordinate information that we need in order
@@ -277,42 +278,46 @@ protected:
 struct GradientCacheKey : public PLDHashEntryHdr {
   typedef const GradientCacheKey& KeyType;
   typedef const GradientCacheKey* KeyTypePointer;
   enum { ALLOW_MEMMOVE = true };
   const nsRefPtr<nsStyleGradient> mGradient;
   const gfxSize mGradientSize;
   enum { SINGLE_CELL = 0x01 };
   const uint32_t mFlags;
+  const gfx::BackendType mBackendType;
 
   GradientCacheKey(nsStyleGradient* aGradient, const gfxSize& aGradientSize,
-                   uint32_t aFlags)
-    : mGradient(aGradient), mGradientSize(aGradientSize), mFlags(aFlags)
+                   uint32_t aFlags, gfx::BackendType aBackendType)
+    : mGradient(aGradient), mGradientSize(aGradientSize), mFlags(aFlags),
+      mBackendType(aBackendType)
   { }
 
   GradientCacheKey(const GradientCacheKey* aOther)
     : mGradient(aOther->mGradient), mGradientSize(aOther->mGradientSize),
-      mFlags(aOther->mFlags)
+      mFlags(aOther->mFlags), mBackendType(aOther->mBackendType)
   { }
 
   static PLDHashNumber
   HashKey(const KeyTypePointer aKey)
   {
     PLDHashNumber hash = 0;
     hash = AddToHash(hash, aKey->mGradientSize.width);
     hash = AddToHash(hash, aKey->mGradientSize.height);
     hash = AddToHash(hash, aKey->mFlags);
+    hash = AddToHash(hash, aKey->mBackendType);
     hash = aKey->mGradient->Hash(hash);
     return hash;
   }
 
   bool KeyEquals(KeyTypePointer aKey) const
   {
     return (*aKey->mGradient == *mGradient) &&
            (aKey->mGradientSize == mGradientSize) &&
+           (aKey->mBackendType == mBackendType) &&
            (aKey->mFlags == mFlags);
   }
   static KeyTypePointer KeyToPointer(KeyType aKey)
   {
     return &aKey;
   }
 };
 
@@ -371,28 +376,28 @@ class GradientCache MOZ_FINAL : public n
     virtual void NotifyExpired(GradientCacheData* aObject)
     {
       // This will free the gfxPattern.
       RemoveObject(aObject);
       mHashEntries.Remove(aObject->mKey);
     }
 
     GradientCacheData* Lookup(nsStyleGradient* aKey, const gfxSize& aGradientSize,
-                              uint32_t aFlags)
+                              uint32_t aFlags, gfx::BackendType aBackendType)
     {
       // We don't cache gradient that have Calc value, because the Calc object
       // can be deallocated by the time we want to compute the hash, and thus we
       // would have a dangling pointer in some nsStyleCoord in the
       // nsStyleGradient that are in the hash table.
       if (aKey->HasCalc()) {
         return nullptr;
       }
 
       GradientCacheData* gradient =
-        mHashEntries.Get(GradientCacheKey(aKey, aGradientSize, aFlags));
+        mHashEntries.Get(GradientCacheKey(aKey, aGradientSize, aFlags, aBackendType));
 
       if (gradient) {
         MarkUsed(gradient);
       }
 
       return gradient;
     }
 
@@ -2027,18 +2032,28 @@ nsCSSRendering::PaintGradient(nsPresCont
   nscoord appUnitsPerPixel = aPresContext->AppUnitsPerDevPixel();
   gfxRect oneCellArea =
     nsLayoutUtils::RectToGfxRect(aOneCellArea, appUnitsPerPixel);
   bool gradientRegistered = true;
   uint32_t flags = 0;
   if (aOneCellArea.Contains(aFillArea)) {
     flags |= GradientCacheKey::SINGLE_CELL;
   }
+
+  gfx::BackendType backendType = gfx::BACKEND_NONE;
+  if (ctx->IsCairo()) {
+    backendType = gfx::BACKEND_CAIRO;
+  } else {
+    gfx::DrawTarget* dt = ctx->GetDrawTarget();
+    NS_ASSERTION(dt, "If we are not using Cairo, we should have a draw target.");
+    backendType = dt->GetType();
+  }
+
   GradientCacheData* pattern =
-    gGradientCache->Lookup(aGradient, oneCellArea.Size(), flags);
+    gGradientCache->Lookup(aGradient, oneCellArea.Size(), flags, backendType);
 
   if (pattern == nullptr) {
     // Compute "gradient line" start and end relative to oneCellArea
     gfxPoint lineStart, lineEnd;
     double radiusX = 0, radiusY = 0; // for radial gradients only
     if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR) {
       ComputeLinearGradientLine(aPresContext, aGradient, oneCellArea.Size(),
                                 &lineStart, &lineEnd);
@@ -2277,17 +2292,17 @@ nsCSSRendering::PaintGradient(nsPresCont
     }
 
     // Set repeat mode. Default cairo extend mode is PAD.
     if (aGradient->mRepeating || forceRepeatToCoverTiles) {
       gradientPattern->SetExtend(gfxPattern::EXTEND_REPEAT);
     }
     // Register the gradient newly computed in the cache.
     pattern = new GradientCacheData(gradientPattern, forceRepeatToCoverTiles,
-      GradientCacheKey(aGradient, oneCellArea.Size(), flags));
+      GradientCacheKey(aGradient, oneCellArea.Size(), flags, backendType));
     gradientRegistered = gGradientCache->RegisterEntry(pattern);
   }
 
   // Paint gradient tiles. This isn't terribly efficient, but doing it this
   // way is simple and sure to get pixel-snapping right. We could speed things
   // up by drawing tiles into temporary surfaces and copying those to the
   // destination, but after pixel-snapping tiles may not all be the same size.
   nsRect dirty;