Bug 579276. Part 1: Change layer/layermanager user data API to use keys and values. r=cjones,sr=vlad
authorRobert O'Callahan <robert@ocallahan.org>
Thu, 02 Sep 2010 21:18:39 +1200
changeset 51874 f2aaa2cc5059e73dfcf720d76297d1c3f62c9e31
parent 51873 cc06207827f47e5351e62fdc09b4bfbce5505078
child 51875 e9376ab8b26ab8434a1ef277dc2f7573245631d8
push idunknown
push userunknown
push dateunknown
reviewerscjones, vlad
bugs579276
milestone2.0b6pre
Bug 579276. Part 1: Change layer/layermanager user data API to use keys and values. r=cjones,sr=vlad
content/canvas/src/WebGLContext.cpp
content/canvas/src/nsCanvasRenderingContext2D.cpp
gfx/layers/Layers.h
layout/base/FrameLayerBuilder.cpp
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -503,31 +503,31 @@ WebGLContext::GetThebesSurface(gfxASurfa
 
 static PRUint8 gWebGLLayerUserData;
 
 already_AddRefed<layers::CanvasLayer>
 WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer,
                              LayerManager *aManager)
 {
     if (!mResetLayer && aOldLayer &&
-        aOldLayer->GetUserData() == &gWebGLLayerUserData) {
+        aOldLayer->HasUserData(&gWebGLLayerUserData)) {
         NS_ADDREF(aOldLayer);
         if (mInvalidated) {
             aOldLayer->Updated(nsIntRect(0, 0, mWidth, mHeight));
             mInvalidated = PR_FALSE;
         }
         return aOldLayer;
     }
 
     nsRefPtr<CanvasLayer> canvasLayer = aManager->CreateCanvasLayer();
     if (!canvasLayer) {
         NS_WARNING("CreateCanvasLayer returned null!");
         return nsnull;
     }
-    canvasLayer->SetUserData(&gWebGLLayerUserData);
+    canvasLayer->SetUserData(&gWebGLLayerUserData, nsnull);
 
     CanvasLayer::Data data;
 
     // the gl context may either provide a native PBuffer, in which case we want to initialize
     // data with the gl context directly, or may provide a surface to which it renders (this is the case
     // of OSMesa contexts), in which case we want to initialize data with that surface.
 
     void* native_surface = gl->GetNativeData(gl::GLContext::NativeImageSurface);
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -4149,29 +4149,29 @@ static PRUint8 g2DContextLayerUserData;
 already_AddRefed<CanvasLayer>
 nsCanvasRenderingContext2D::GetCanvasLayer(CanvasLayer *aOldLayer,
                                            LayerManager *aManager)
 {
     if (!mValid)
         return nsnull;
 
     if (!mResetLayer && aOldLayer &&
-        aOldLayer->GetUserData() == &g2DContextLayerUserData) {
+        aOldLayer->HasUserData(&g2DContextLayerUserData)) {
         NS_ADDREF(aOldLayer);
         // XXX Need to just update the changed area here
         aOldLayer->Updated(nsIntRect(0, 0, mWidth, mHeight));
         return aOldLayer;
     }
 
     nsRefPtr<CanvasLayer> canvasLayer = aManager->CreateCanvasLayer();
     if (!canvasLayer) {
         NS_WARNING("CreateCanvasLayer returned null!");
         return nsnull;
     }
-    canvasLayer->SetUserData(&g2DContextLayerUserData);
+    canvasLayer->SetUserData(&g2DContextLayerUserData, nsnull);
 
     CanvasLayer::Data data;
 
     data.mSurface = mSurface.get();
     data.mSize = nsIntSize(mWidth, mHeight);
 
     canvasLayer->Initialize(data);
     canvasLayer->SetIsOpaqueContent(mOpaque);
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -78,16 +78,24 @@ class ColorLayer;
 class ImageContainer;
 class CanvasLayer;
 class SpecificLayerAttributes;
 
 #define MOZ_LAYER_DECL_NAME(n, e)                           \
   virtual const char* Name() const { return n; }            \
   virtual LayerType GetType() const { return e; }
 
+/**
+ * Base class for userdata objects attached to layers and layer managers.
+ */
+class THEBES_API LayerUserData {
+public:
+  virtual ~LayerUserData() {}
+};
+
 /*
  * Motivation: For truly smooth animation and video playback, we need to
  * be able to compose frames and render them on a dedicated thread (i.e.
  * off the main thread where DOM manipulation, script execution and layout
  * induce difficult-to-bound latency). This requires Gecko to construct
  * some kind of persistent scene structure (graph or tree) that can be
  * safely transmitted across threads. We have other scenarios (e.g. mobile 
  * browsing) where retaining some rendered data between paints is desired
@@ -105,16 +113,62 @@ class SpecificLayerAttributes;
  * Gecko used it before layers were introduced). But we also don't want
  * to have bifurcated "layers"/"non-layers" rendering paths in Gecko.
  * Therefore the layers API is carefully designed to permit maximally
  * efficient implementation in an "immediate mode" style. See the
  * BasicLayerManager for such an implementation.
  */
 
 /**
+ * Helper class to manage user data for layers and LayerManagers.
+ */
+class THEBES_API LayerUserDataSet {
+public:
+  LayerUserDataSet() : mKey(nsnull) {}
+
+  void Set(void* aKey, LayerUserData* aValue)
+  {
+    NS_ASSERTION(!mKey || mKey == aKey,
+                 "Multiple LayerUserData objects not supported");
+    mKey = aKey;
+    mValue = aValue;
+  }
+  /**
+   * This can be used anytime. Ownership passes to the caller!
+   */
+  LayerUserData* Remove(void* aKey)
+  {
+    if (mKey == aKey) {
+      mKey = nsnull;
+      LayerUserData* d = mValue.forget();
+      return d;
+    }
+    return nsnull;
+  }
+  /**
+   * This getter can be used anytime.
+   */
+  PRBool Has(void* aKey)
+  {
+    return mKey == aKey;
+  }
+  /**
+   * This getter can be used anytime. Ownership is retained by this object.
+   */
+  LayerUserData* Get(void* aKey)
+  {
+    return mKey == aKey ? mValue.get() : nsnull;
+  }
+
+private:
+  void* mKey;
+  nsAutoPtr<LayerUserData> mValue;
+};
+
+/**
  * A LayerManager controls a tree of layers. All layers in the tree
  * must use the same LayerManager.
  * 
  * All modifications to a layer tree must happen inside a transaction.
  * Only the state of the layer tree at the end of a transaction is
  * rendered. Transactions cannot be nested
  * 
  * Each transaction has two phases:
@@ -137,17 +191,17 @@ class THEBES_API LayerManager {
 
 public:
   enum LayersBackend {
     LAYERS_BASIC = 0,
     LAYERS_OPENGL,
     LAYERS_D3D9
   };
 
-  LayerManager() : mUserData(nsnull), mDestroyed(PR_FALSE)
+  LayerManager() : mDestroyed(PR_FALSE)
   {
     InitLog();
   }
   virtual ~LayerManager() {}
 
   /**
    * Release layers and resources held by this layer manager, and mark
    * it as destroyed.  Should do any cleanup necessary in preparation
@@ -262,20 +316,38 @@ public:
 
   /**
    * Type of layer manager his is. This is to be used sparsely in order to
    * avoid a lot of Layers backend specific code. It should be used only when
    * Layers backend specific functionality is necessary.
    */
   virtual LayersBackend GetBackendType() = 0;
 
-  // This setter and getter can be used anytime. The user data is initially
-  // null.
-  void SetUserData(void* aData) { mUserData = aData; }
-  void* GetUserData() { return mUserData; }
+  /**
+   * This setter can be used anytime. The user data for all keys is
+   * initially null. Ownership pases to the layer manager.
+   */
+  void SetUserData(void* aKey, LayerUserData* aData)
+  { mUserData.Set(aKey, aData); }
+  /**
+   * This can be used anytime. Ownership passes to the caller!
+   */
+  nsAutoPtr<LayerUserData> RemoveUserData(void* aKey)
+  { nsAutoPtr<LayerUserData> d(mUserData.Remove(aKey)); return d; }
+  /**
+   * This getter can be used anytime.
+   */
+  PRBool HasUserData(void* aKey)
+  { return mUserData.Has(aKey); }
+  /**
+   * This getter can be used anytime. Ownership is retained by the layer
+   * manager.
+   */
+  LayerUserData* GetUserData(void* aKey)
+  { return mUserData.Get(aKey); }
 
   // We always declare the following logging symbols, because it's
   // extremely tricky to conditionally declare them.  However, for
   // ifndef MOZ_LAYERS_HAVE_LOG builds, they only have trivial
   // definitions in Layers.cpp.
   virtual const char* Name() const { return "???"; }
 
   /**
@@ -300,17 +372,17 @@ public:
    */
   void LogSelf(const char* aPrefix="");
 
   static bool IsLogEnabled();
   static PRLogModuleInfo* GetLog() { return sLog; }
 
 protected:
   nsRefPtr<Layer> mRoot;
-  void* mUserData;
+  LayerUserDataSet mUserData;
   PRPackedBool mDestroyed;
 
   // Print interesting information about this into aTo.  Internally
   // used to implement Dump*() and Log*().
   virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
 
   static void InitLog();
   static PRLogModuleInfo* sLog;
@@ -455,20 +527,38 @@ public:
 
   // Returns true if it's OK to save the contents of aLayer in an
   // opaque surface (a surface without an alpha channel).
   // If we can use a surface without an alpha channel, we should, because
   // it will often make painting of antialiased text faster and higher
   // quality.
   PRBool CanUseOpaqueSurface();
 
-  // This setter and getter can be used anytime. The user data is initially
-  // null.
-  void SetUserData(void* aData) { mUserData = aData; }
-  void* GetUserData() { return mUserData; }
+  /**
+   * This setter can be used anytime. The user data for all keys is
+   * initially null. Ownership pases to the layer manager.
+   */
+  void SetUserData(void* aKey, LayerUserData* aData)
+  { mUserData.Set(aKey, aData); }
+  /**
+   * This can be used anytime. Ownership passes to the caller!
+   */
+  nsAutoPtr<LayerUserData> RemoveUserData(void* aKey)
+  { nsAutoPtr<LayerUserData> d(mUserData.Remove(aKey)); return d; }
+  /**
+   * This getter can be used anytime.
+   */
+  PRBool HasUserData(void* aKey)
+  { return mUserData.Has(aKey); }
+  /**
+   * This getter can be used anytime. Ownership is retained by the layer
+   * manager.
+   */
+  LayerUserData* GetUserData(void* aKey)
+  { return mUserData.Get(aKey); }
 
   /**
    * Dynamic downcast to a Thebes layer. Returns null if this is not
    * a ThebesLayer.
    */
   virtual ThebesLayer* AsThebesLayer() { return nsnull; }
 
   virtual const char* Name() const =0;
@@ -514,17 +604,16 @@ public:
 
 protected:
   Layer(LayerManager* aManager, void* aImplData) :
     mManager(aManager),
     mParent(nsnull),
     mNextSibling(nsnull),
     mPrevSibling(nsnull),
     mImplData(aImplData),
-    mUserData(nsnull),
     mOpacity(1.0),
     mUseClipRect(PR_FALSE),
     mIsOpaqueContent(PR_FALSE)
     {}
 
   void Mutated() { mManager->Mutated(this); }
 
   // Print interesting information about this into aTo.  Internally
@@ -534,17 +623,17 @@ protected:
   // appends additional info to aTo.
   virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
 
   LayerManager* mManager;
   ContainerLayer* mParent;
   Layer* mNextSibling;
   Layer* mPrevSibling;
   void* mImplData;
-  void* mUserData;
+  LayerUserDataSet mUserData;
   nsIntRegion mVisibleRegion;
   gfx3DMatrix mTransform;
   float mOpacity;
   nsIntRect mClipRect;
   PRPackedBool mUseClipRect;
   PRPackedBool mIsOpaqueContent;
 };
 
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -52,24 +52,29 @@ using namespace mozilla::layers;
 
 namespace mozilla {
 
 namespace {
 
 /**
  * This is the userdata we associate with a layer manager.
  */
-class LayerManagerData {
+class LayerManagerData : public LayerUserData {
 public:
   LayerManagerData() :
     mInvalidateAllThebesContent(PR_FALSE),
     mInvalidateAllLayers(PR_FALSE)
   {
+    MOZ_COUNT_CTOR(LayerManagerData);
+
     mFramesWithLayers.Init();
   }
+  ~LayerManagerData() {
+    MOZ_COUNT_DTOR(LayerManagerData);
+  }
 
   /**
    * Tracks which frames have layers associated with them.
    */
   nsTHashtable<nsPtrHashKey<nsIFrame> > mFramesWithLayers;
   PRPackedBool mInvalidateAllThebesContent;
   PRPackedBool mInvalidateAllLayers;
 };
@@ -299,28 +304,36 @@ protected:
   nsTArray<nsRefPtr<ColorLayer> >  mRecycledColorLayers;
   PRUint32                         mNextFreeRecycledThebesLayer;
   PRUint32                         mNextFreeRecycledColorLayer;
   PRPackedBool                     mInvalidateAllThebesContent;
 };
 
 /**
  * The address of gThebesDisplayItemLayerUserData is used as the user
- * data pointer for ThebesLayers created by FrameLayerBuilder.
+ * data key for ThebesLayers created by FrameLayerBuilder.
  * It identifies ThebesLayers used to draw non-layer content, which are
  * therefore eligible for recycling. We want display items to be able to
  * create their own dedicated ThebesLayers in BuildLayer, if necessary,
  * and we wouldn't want to accidentally recycle those.
+ * The user data is null.
  */
-static PRUint8 gThebesDisplayItemLayerUserData;
+PRUint8 gThebesDisplayItemLayerUserData;
 /**
  * The address of gColorLayerUserData is used as the user
- * data pointer for ColorLayers
+ * data key for ColorLayers created by FrameLayerBuilder.
+ * The user data is null.
  */
-static PRUint8 gColorLayerUserData;
+PRUint8 gColorLayerUserData;
+/**
+ * The address of gLayerManagerUserData is used as the user
+ * data key for retained LayerManagers managed by FrameLayerBuilder.
+ * The user data is a LayerManagerData.
+ */
+PRUint8 gLayerManagerUserData;
 
 } // anonymous namespace
 
 PRBool
 FrameLayerBuilder::DisplayItemDataEntry::HasContainerLayer()
 {
   for (PRUint32 i = 0; i < mData.Length(); ++i) {
     if (mData[i].mLayer->GetType() == Layer::TYPE_CONTAINER)
@@ -337,22 +350,21 @@ FrameLayerBuilder::InternalDestroyDispla
   nsRefPtr<LayerManager> managerRef;
   nsTArray<DisplayItemData>* array =
     reinterpret_cast<nsTArray<DisplayItemData>*>(&aPropertyValue);
   NS_ASSERTION(!array->IsEmpty(), "Empty arrays should not be stored");
 
   if (aRemoveFromFramesWithLayers) {
     LayerManager* manager = array->ElementAt(0).mLayer->Manager();
     LayerManagerData* data = static_cast<LayerManagerData*>
-      (manager->GetUserData());
+      (manager->GetUserData(&gLayerManagerUserData));
     NS_ASSERTION(data, "Frame with layer should have been recorded");
     data->mFramesWithLayers.RemoveEntry(aFrame);
     if (data->mFramesWithLayers.Count() == 0) {
-      delete data;
-      manager->SetUserData(nsnull);
+      manager->RemoveUserData(&gLayerManagerUserData);
       // Consume the reference we added when we set the user data
       // in DidEndTransaction. But don't actually release until we've
       // released all the layers in the DisplayItemData array below!
       managerRef = manager;
       NS_RELEASE(manager);
     }
   }
 
@@ -366,17 +378,17 @@ FrameLayerBuilder::DestroyDisplayItemDat
   InternalDestroyDisplayItemData(aFrame, aPropertyValue, PR_TRUE);
 }
 
 void
 FrameLayerBuilder::WillBeginRetainedLayerTransaction(LayerManager* aManager)
 {
   mRetainingManager = aManager;
   LayerManagerData* data = static_cast<LayerManagerData*>
-    (aManager->GetUserData());
+    (aManager->GetUserData(&gLayerManagerUserData));
   if (data) {
     mInvalidateAllThebesContent = data->mInvalidateAllThebesContent;
     mInvalidateAllLayers = data->mInvalidateAllLayers;
   }
 }
 
 /**
  * A helper function to remove the mThebesLayerItems entries for every
@@ -415,23 +427,23 @@ FrameLayerBuilder::WillEndTransaction(La
     return;
 
   // We need to save the data we'll need to support retaining. We do this
   // before we paint so that invalidation triggered by painting will
   // be able to update the ThebesLayerInvalidRegionProperty values
   // correctly and the NS_FRAME_HAS_CONTAINER_LAYER bits will be set
   // correctly.
   LayerManagerData* data = static_cast<LayerManagerData*>
-    (mRetainingManager->GetUserData());
+    (mRetainingManager->GetUserData(&gLayerManagerUserData));
   if (data) {
     // Update all the frames that used to have layers.
     data->mFramesWithLayers.EnumerateEntries(UpdateDisplayItemDataForFrame, this);
   } else {
     data = new LayerManagerData();
-    mRetainingManager->SetUserData(data);
+    mRetainingManager->SetUserData(&gLayerManagerUserData, data);
     // Addref mRetainingManager. We'll release it when 'data' is
     // removed.
     NS_ADDREF(mRetainingManager);
   }
   // Now go through all the frames that didn't have any retained
   // display items before, and record those retained display items.
   // This also empties mNewDisplayItemData.
   mNewDisplayItemData.EnumerateEntries(StoreNewDisplayItemData, data);
@@ -590,17 +602,17 @@ ContainerState::CreateOrRecycleColorLaye
     // reapply any necessary clipping.
     layer->SetClipRect(nsnull);
   } else {
     // Create a new layer
     layer = mManager->CreateColorLayer();
     if (!layer)
       return nsnull;
     // Mark this layer as being used for Thebes-painting display items
-    layer->SetUserData(&gColorLayerUserData);
+    layer->SetUserData(&gColorLayerUserData, nsnull);
   }
   return layer.forget();
 }
 
 already_AddRefed<ThebesLayer>
 ContainerState::CreateOrRecycleThebesLayer(nsIFrame* aActiveScrolledRoot)
 {
   // We need a new thebes layer
@@ -632,17 +644,17 @@ ContainerState::CreateOrRecycleThebesLay
     // InvalidateAllThebesLayerContents has ensured
     // the area is invalidated in the widget.
   } else {
     // Create a new thebes layer
     layer = mManager->CreateThebesLayer();
     if (!layer)
       return nsnull;
     // Mark this layer as being used for Thebes-painting display items
-    layer->SetUserData(&gThebesDisplayItemLayerUserData);
+    layer->SetUserData(&gThebesDisplayItemLayerUserData, nsnull);
   }
 
   // Set up transform so that 0,0 in the Thebes layer corresponds to the
   // (pixel-snapped) top-left of the aActiveScrolledRoot.
   nsPoint offset = mBuilder->ToReferenceFrame(aActiveScrolledRoot);
   nsIntPoint pixOffset = offset.ToNearestPixels(
       aActiveScrolledRoot->PresContext()->AppUnitsPerDevPixel());
   gfxMatrix matrix;
@@ -960,17 +972,17 @@ ContainerState::ProcessDisplayItems(cons
       nsRefPtr<Layer> ownLayer = item->BuildLayer(mBuilder, mManager);
       if (!ownLayer) {
         InvalidateForLayerChange(item, ownLayer);
         continue;
       }
 
       // Update that layer's clip and visible rects.
       NS_ASSERTION(ownLayer->Manager() == mManager, "Wrong manager");
-      NS_ASSERTION(ownLayer->GetUserData() != &gThebesDisplayItemLayerUserData,
+      NS_ASSERTION(!ownLayer->HasUserData(&gLayerManagerUserData),
                    "We shouldn't have a FrameLayerBuilder-managed layer here!");
       // It has its own layer. Update that layer's clip and visible rects.
       if (aClipRect) {
         ownLayer->IntersectClipRect(
             aClipRect->ToNearestPixels(appUnitsPerDevPixel));
       }
       ThebesLayerData* data = GetTopThebesLayerData();
       if (data) {
@@ -1114,20 +1126,19 @@ FrameLayerBuilder::AddLayerDisplayItem(L
   }
 }
 
 void
 ContainerState::CollectOldLayers()
 {
   for (Layer* layer = mContainerLayer->GetFirstChild(); layer;
        layer = layer->GetNextSibling()) {
-    void* data = layer->GetUserData();
-    if (data == &gColorLayerUserData) {
+    if (layer->HasUserData(&gColorLayerUserData)) {
       mRecycledColorLayers.AppendElement(static_cast<ColorLayer*>(layer));
-    } else if (data == &gThebesDisplayItemLayerUserData) {
+    } else if (layer->HasUserData(&gThebesDisplayItemLayerUserData)) {
       NS_ASSERTION(layer->AsThebesLayer(), "Wrong layer type");
       mRecycledThebesLayers.AppendElement(static_cast<ThebesLayer*>(layer));
     }
   }
 }
 
 void
 ContainerState::Finish()
@@ -1198,17 +1209,17 @@ FrameLayerBuilder::BuildContainerLayerFo
                aContainerItem->GetUnderlyingFrame() == aContainerFrame,
                "Container display item must match given frame");
 
   nsRefPtr<ContainerLayer> containerLayer;
   if (aManager == mRetainingManager) {
     Layer* oldLayer = GetOldLayerFor(aContainerFrame, containerDisplayItemKey);
     if (oldLayer) {
       NS_ASSERTION(oldLayer->Manager() == aManager, "Wrong manager");
-      if (oldLayer->GetUserData() == &gThebesDisplayItemLayerUserData) {
+      if (oldLayer->HasUserData(&gThebesDisplayItemLayerUserData)) {
         // The old layer for this item is actually our ThebesLayer
         // because we rendered its layer into that ThebesLayer. So we
         // don't actually have a retained container layer.
       } else {
         NS_ASSERTION(oldLayer->GetType() == Layer::TYPE_CONTAINER,
                      "Wrong layer type");
         containerLayer = static_cast<ContainerLayer*>(oldLayer);
         // Clear clip rect; the caller will set it if necessary.
@@ -1271,17 +1282,17 @@ FrameLayerBuilder::GetLeafLayerFor(nsDis
   if (aManager != mRetainingManager)
     return nsnull;
 
   nsIFrame* f = aItem->GetUnderlyingFrame();
   NS_ASSERTION(f, "Can only call GetLeafLayerFor on items that have a frame");
   Layer* layer = GetOldLayerFor(f, aItem->GetPerFrameKey());
   if (!layer)
     return nsnull;
-  if (layer->GetUserData() == &gThebesDisplayItemLayerUserData) {
+  if (layer->HasUserData(&gThebesDisplayItemLayerUserData)) {
     // This layer was created to render Thebes-rendered content for this
     // display item. The display item should not use it for its own
     // layer rendering.
     return nsnull;
   }
   // Clear clip rect; the caller is responsible for setting it.
   layer->SetClipRect(nsnull);
   return layer;
@@ -1347,27 +1358,27 @@ FrameLayerBuilder::InvalidateThebesLayer
 {
   InternalInvalidateThebesLayersInSubtree(aFrame);
 }
 
 /* static */ void
 FrameLayerBuilder::InvalidateAllThebesLayerContents(LayerManager* aManager)
 {
   LayerManagerData* data = static_cast<LayerManagerData*>
-    (aManager->GetUserData());
+    (aManager->GetUserData(&gLayerManagerUserData));
   if (data) {
     data->mInvalidateAllThebesContent = PR_TRUE;
   }
 }
 
 /* static */ void
 FrameLayerBuilder::InvalidateAllLayers(LayerManager* aManager)
 {
   LayerManagerData* data = static_cast<LayerManagerData*>
-    (aManager->GetUserData());
+    (aManager->GetUserData(&gLayerManagerUserData));
   if (data) {
     data->mInvalidateAllLayers = PR_TRUE;
   }
 }
 
 /* static */
 PRBool
 FrameLayerBuilder::HasDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
@@ -1375,19 +1386,19 @@ FrameLayerBuilder::HasDedicatedLayer(nsI
   void* propValue = aFrame->Properties().Get(DisplayItemDataProperty());
   if (!propValue)
     return PR_FALSE;
 
   nsTArray<DisplayItemData>* array =
     (reinterpret_cast<nsTArray<DisplayItemData>*>(&propValue));
   for (PRUint32 i = 0; i < array->Length(); ++i) {
     if (array->ElementAt(i).mDisplayItemKey == aDisplayItemKey) {
-      void* layerUserData = array->ElementAt(i).mLayer->GetUserData();
-      if (layerUserData != &gColorLayerUserData &&
-          layerUserData != &gThebesDisplayItemLayerUserData)
+      Layer* layer = array->ElementAt(i).mLayer;
+      if (!layer->HasUserData(&gColorLayerUserData) &&
+          !layer->HasUserData(&gThebesDisplayItemLayerUserData))
         return PR_TRUE;
     }
   }
   return PR_FALSE;
 }
 
 /* static */ void
 FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,