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 id15461
push userrocallahan@mozilla.com
push dateThu, 02 Sep 2010 09:57:15 +0000
treeherdermozilla-central@8565ee385867 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones, vlad
bugs579276
milestone2.0b6pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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,