Bug 724886: Push images from plugin code instead of pulling from nsObjectFrame. r=roc
authorBas Schouten <bschouten@mozilla.com>
Wed, 08 Feb 2012 16:34:27 +0100
changeset 89317 1a345b043b4737bd628d36ad93368012a8f3fc5f
parent 89316 988bdfe89a9b75d4cded4344eaf42584a3062016
child 89318 6771bd53e267e84665ef80a076198b2c2779546b
push id783
push userlsblakk@mozilla.com
push dateTue, 24 Apr 2012 17:33:42 +0000
treeherdermozilla-beta@11faed19f136 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs724886
milestone13.0a1
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 724886: Push images from plugin code instead of pulling from nsObjectFrame. r=roc
dom/plugins/base/PluginPRLibrary.cpp
dom/plugins/base/PluginPRLibrary.h
dom/plugins/base/nsNPAPIPluginInstance.cpp
dom/plugins/base/nsNPAPIPluginInstance.h
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/base/nsPluginInstanceOwner.h
dom/plugins/ipc/PluginInstanceParent.cpp
dom/plugins/ipc/PluginInstanceParent.h
dom/plugins/ipc/PluginLibrary.h
dom/plugins/ipc/PluginModuleParent.cpp
dom/plugins/ipc/PluginModuleParent.h
layout/generic/nsObjectFrame.cpp
layout/generic/nsObjectFrame.h
--- a/dom/plugins/base/PluginPRLibrary.cpp
+++ b/dom/plugins/base/PluginPRLibrary.cpp
@@ -290,17 +290,17 @@ PluginPRLibrary::HandleGUIEvent(NPP inst
 {
   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
   NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 #endif
 
 nsresult
-PluginPRLibrary::GetImage(NPP instance, ImageContainer* aContainer, Image** aImage)
+PluginPRLibrary::GetImageContainer(NPP instance, ImageContainer** aContainer)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 #if defined(XP_MACOSX)
 nsresult
 PluginPRLibrary::IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing)
 {
--- a/dom/plugins/base/PluginPRLibrary.h
+++ b/dom/plugins/base/PluginPRLibrary.h
@@ -137,17 +137,17 @@ public:
                              char* argv[], NPSavedData* saved,
                              NPError* error);
 
     virtual nsresult NPP_ClearSiteData(const char* site, uint64_t flags,
                                        uint64_t maxAge);
     virtual nsresult NPP_GetSitesWithData(InfallibleTArray<nsCString>& result);
 
     virtual nsresult AsyncSetWindow(NPP instance, NPWindow* window);
-    virtual nsresult GetImage(NPP instance, ImageContainer* aContainer, Image** aImage);
+    virtual nsresult GetImageContainer(NPP instance, ImageContainer** aContainer);
     virtual nsresult GetImageSize(NPP instance, nsIntSize* aSize);
     NS_OVERRIDE virtual bool UseAsyncPainting() { return false; }
 #if defined(XP_MACOSX)
     virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing);
 #endif
     NS_OVERRIDE
     virtual nsresult SetBackgroundUnknown(NPP instance);
     NS_OVERRIDE
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -953,25 +953,25 @@ nsNPAPIPluginInstance::HandleGUIEvent(co
   if (!library)
     return NS_ERROR_FAILURE;
 
   return library->HandleGUIEvent(&mNPP, anEvent, handled);
 }
 #endif
 
 nsresult
-nsNPAPIPluginInstance::GetImage(ImageContainer* aContainer, Image** aImage)
+nsNPAPIPluginInstance::GetImageContainer(ImageContainer**aContainer)
 {
-  *aImage = nsnull;
+  *aContainer = nsnull;
 
   if (RUNNING != mRunning)
     return NS_OK;
 
   AutoPluginLibraryCall library(this);
-  return !library ? NS_ERROR_FAILURE : library->GetImage(&mNPP, aContainer, aImage);
+  return !library ? NS_ERROR_FAILURE : library->GetImageContainer(&mNPP, aContainer);
 }
 
 nsresult
 nsNPAPIPluginInstance::GetImageSize(nsIntSize* aSize)
 {
   *aSize = nsIntSize(0, 0);
 
   if (RUNNING != mRunning)
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -96,17 +96,17 @@ public:
   nsresult GetValueFromPlugin(NPPVariable variable, void* value);
   nsresult GetDrawingModel(PRInt32* aModel);
   nsresult IsRemoteDrawingCoreAnimation(bool* aDrawing);
   nsresult GetJSObject(JSContext *cx, JSObject** outObject);
   nsresult DefineJavaProperties();
   bool ShouldCache();
   nsresult IsWindowless(bool* isWindowless);
   nsresult AsyncSetWindow(NPWindow* window);
-  nsresult GetImage(ImageContainer* aContainer, Image** aImage);
+  nsresult GetImageContainer(ImageContainer **aContainer);
   nsresult GetImageSize(nsIntSize* aSize);
   nsresult NotifyPainted(void);
   nsresult UseAsyncPainting(bool* aIsAsync);
   nsresult SetBackgroundUnknown();
   nsresult BeginUpdateBackground(nsIntRect* aRect, gfxContext** aContext);
   nsresult EndUpdateBackground(gfxContext* aContext, nsIntRect* aRect);
   nsresult IsTransparent(bool* isTransparent);
   nsresult GetFormValue(nsAString& aValue);
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -185,50 +185,49 @@ nsPluginInstanceOwner::NotifyPaintWaiter
   }
 }
 
 #ifdef XP_MACOSX
 static void DrawPlugin(ImageContainer* aContainer, void* aPluginInstanceOwner)
 {
   nsObjectFrame* frame = static_cast<nsPluginInstanceOwner*>(aPluginInstanceOwner)->GetFrame();
   if (frame) {
-    frame->UpdateImageLayer(aContainer, gfxRect(0,0,0,0));
+    frame->UpdateImageLayer(gfxRect(0,0,0,0));
   }
 }
 
 static void OnDestroyImage(void* aPluginInstanceOwner)
 {
   nsPluginInstanceOwner* owner = static_cast<nsPluginInstanceOwner*>(aPluginInstanceOwner);
   NS_IF_RELEASE(owner);
 }
 #endif // XP_MACOSX
 
-bool
-nsPluginInstanceOwner::SetCurrentImage(ImageContainer* aContainer)
+already_AddRefed<ImageContainer>
+nsPluginInstanceOwner::GetImageContainer()
 {
   if (mInstance) {
-    nsRefPtr<Image> image;
+    nsRefPtr<ImageContainer> container;
     // Every call to nsIPluginInstance::GetImage() creates
     // a new image.  See nsIPluginInstance.idl.
-    mInstance->GetImage(aContainer, getter_AddRefs(image));
-    if (image) {
+    mInstance->GetImageContainer(getter_AddRefs(container));
+    if (container) {
 #ifdef XP_MACOSX
-      if (image->GetFormat() == Image::MAC_IO_SURFACE && mObjectFrame) {
+      nsRefPtr<Image> image = container->GetCurrentImage();
+      if (image && image->GetFormat() == Image::MAC_IO_SURFACE && mObjectFrame) {
         MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image.get());
         NS_ADDREF_THIS();
         oglImage->SetUpdateCallback(&DrawPlugin, this);
         oglImage->SetDestroyCallback(&OnDestroyImage);
       }
 #endif
-      aContainer->SetCurrentImage(image);
-      return true;
+      return container.forget();
     }
   }
-  aContainer->SetCurrentImage(nsnull);
-  return false;
+  return nsnull;
 }
 
 void
 nsPluginInstanceOwner::SetBackgroundUnknown()
 {
   if (mInstance) {
     mInstance->SetBackgroundUnknown();
   }
@@ -630,22 +629,19 @@ NS_IMETHODIMP nsPluginInstanceOwner::Inv
   }
 
   if (!mObjectFrame || !invalidRect || !mWidgetVisible)
     return NS_ERROR_FAILURE;
 
   // Each time an asynchronously-drawing plugin sends a new surface to display,
   // InvalidateRect is called. We notify reftests that painting is up to
   // date and update our ImageContainer with the new surface.
-  nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
+  nsRefPtr<ImageContainer> container;
+  mInstance->GetImageContainer(getter_AddRefs(container));
   gfxIntSize oldSize(0, 0);
-  if (container) {
-    oldSize = container->GetCurrentSize();
-    SetCurrentImage(container);
-  }
 
 #ifndef XP_MACOSX
   // Windowed plugins should not be calling NPN_InvalidateRect, but
   // Silverlight does and expects it to "work"
   if (mWidget) {
     mWidget->Invalidate(nsIntRect(invalidRect->left, invalidRect->top,
                                   invalidRect->right - invalidRect->left,
                                   invalidRect->bottom - invalidRect->top));
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -270,18 +270,20 @@ public:
   }
   
   bool MatchPluginName(const char *aPluginName)
   {
     return strncmp(GetPluginName(), aPluginName, strlen(aPluginName)) == 0;
   }
   
   void NotifyPaintWaiter(nsDisplayListBuilder* aBuilder);
-  // Return true if we set image with valid surface
-  bool SetCurrentImage(ImageContainer* aContainer);
+
+  // Returns the image container that has our currently displayed image.
+  already_AddRefed<ImageContainer> GetImageContainer();
+
   /**
    * Returns the bounds of the current async-rendered surface. This can only
    * change in response to messages received by the event loop (i.e. not during
    * painting).
    */
   nsIntSize GetCurrentImageSize();
   
   // Methods to update the background image we send to async plugins.
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -621,17 +621,17 @@ PluginInstanceParent::HandleGUIEvent(con
         NS_ERROR("Not implemented for this event type");
         return NS_ERROR_FAILURE;
     }
     return NS_OK;
 }
 #endif
 
 nsresult
-PluginInstanceParent::GetImage(ImageContainer* aContainer, Image** aImage)
+PluginInstanceParent::GetImageContainer(ImageContainer** aContainer)
 {
 #ifdef XP_MACOSX
     nsIOSurface* ioSurface = NULL;
   
     if (mFrontIOSurface) {
       ioSurface = mFrontIOSurface;
     } else if (mIOSurface) {
       ioSurface = mIOSurface;
@@ -645,42 +645,54 @@ PluginInstanceParent::GetImage(ImageCont
 
     Image::Format format = Image::CAIRO_SURFACE;
 #ifdef XP_MACOSX
     if (ioSurface) {
         format = Image::MAC_IO_SURFACE;
     }
 #endif
 
+    ImageContainer *container = GetImageContainer();
+
+    if (!container) {
+        return NS_ERROR_FAILURE;
+    }
+
     nsRefPtr<Image> image;
-    image = aContainer->CreateImage(&format, 1);
+    image = container->CreateImage(&format, 1);
     if (!image) {
         return NS_ERROR_FAILURE;
     }
 
 #ifdef XP_MACOSX
     if (ioSurface) {
         NS_ASSERTION(image->GetFormat() == Image::MAC_IO_SURFACE, "Wrong format?");
         MacIOSurfaceImage* ioImage = static_cast<MacIOSurfaceImage*>(image.get());
         MacIOSurfaceImage::Data ioData;
         ioData.mIOSurface = ioSurface;
         ioImage->SetData(ioData);
-        *aImage = image.forget().get();
+        container->SetCurrentImage(ioImage);
+
+        NS_IF_ADDREF(container);
+        *aContainer = container;
         return NS_OK;
     }
 #endif
 
     NS_ASSERTION(image->GetFormat() == Image::CAIRO_SURFACE, "Wrong format?");
     CairoImage* pluginImage = static_cast<CairoImage*>(image.get());
     CairoImage::Data cairoData;
     cairoData.mSurface = mFrontSurface;
     cairoData.mSize = mFrontSurface->GetSize();
     pluginImage->SetData(cairoData);
 
-    *aImage = image.forget().get();
+    container->SetCurrentImage(pluginImage);
+
+    NS_IF_ADDREF(container);
+    *aContainer = container;
     return NS_OK;
 }
 
 nsresult
 PluginInstanceParent::GetImageSize(nsIntSize* aSize)
 {
     if (mFrontSurface) {
         gfxIntSize size = mFrontSurface->GetSize();
@@ -848,16 +860,27 @@ PluginInstanceParent::BackgroundDescript
     return shmem->GetShmem();
 #endif
 
     // If this is ever used, which it shouldn't be, it will trigger a
     // hard assertion in IPDL-generated code.
     return SurfaceDescriptor();
 }
 
+ImageContainer*
+PluginInstanceParent::GetImageContainer()
+{
+  if (mImageContainer) {
+    return mImageContainer;
+  }
+
+  mImageContainer = LayerManager::CreateImageContainer();
+  return mImageContainer;
+}
+
 PPluginBackgroundDestroyerParent*
 PluginInstanceParent::AllocPPluginBackgroundDestroyer()
 {
     NS_RUNTIMEABORT("'Power-user' ctor is used exclusively");
     return nsnull;
 }
 
 bool
--- a/dom/plugins/ipc/PluginInstanceParent.h
+++ b/dom/plugins/ipc/PluginInstanceParent.h
@@ -275,17 +275,17 @@ public:
     {
       return mNPP;
     }
 
     virtual bool
     AnswerPluginFocusChange(const bool& gotFocus);
 
     nsresult AsyncSetWindow(NPWindow* window);
-    nsresult GetImage(mozilla::layers::ImageContainer* aContainer, mozilla::layers::Image** aImage);
+    nsresult GetImageContainer(mozilla::layers::ImageContainer** aContainer);
     nsresult GetImageSize(nsIntSize* aSize);
 #ifdef XP_MACOSX
     nsresult IsRemoteDrawingCoreAnimation(bool *aDrawing);
 #endif
     nsresult SetBackgroundUnknown();
     nsresult BeginUpdateBackground(const nsIntRect& aRect,
                                    gfxContext** aCtx);
     nsresult EndUpdateBackground(gfxContext* aCtx,
@@ -296,16 +296,19 @@ public:
 
 private:
     // Create an appropriate platform surface for a background of size
     // |aSize|.  Return true if successful.
     bool CreateBackground(const nsIntSize& aSize);
     void DestroyBackground();
     SurfaceDescriptor BackgroundDescriptor() /*const*/;
 
+    typedef mozilla::layers::ImageContainer ImageContainer;
+    ImageContainer *GetImageContainer();
+
     NS_OVERRIDE
     virtual PPluginBackgroundDestroyerParent*
     AllocPPluginBackgroundDestroyer();
 
     NS_OVERRIDE
     virtual bool
     DeallocPPluginBackgroundDestroyer(PPluginBackgroundDestroyerParent* aActor);
 
@@ -360,15 +363,17 @@ private:
     // On the plugin side, we use this surface to avoid doing alpha
     // recovery when possible.  This surface is created and owned by
     // the browser, but a "read-only" reference is sent to the plugin.
     //
     // We have explicitly chosen not to provide any guarantees about
     // the consistency of the pixels in |mBackground|.  A plugin may
     // be able to observe partial updates to the background.
     nsRefPtr<gfxASurface>    mBackground;
+    
+    nsRefPtr<ImageContainer> mImageContainer;
 };
 
 
 } // namespace plugins
 } // namespace mozilla
 
 #endif // ifndef dom_plugins_PluginInstanceParent_h
--- a/dom/plugins/ipc/PluginLibrary.h
+++ b/dom/plugins/ipc/PluginLibrary.h
@@ -95,17 +95,17 @@ public:
                            char* argv[], NPSavedData* saved,
                            NPError* error) = 0;
 
   virtual nsresult NPP_ClearSiteData(const char* site, uint64_t flags,
                                      uint64_t maxAge) = 0;
   virtual nsresult NPP_GetSitesWithData(InfallibleTArray<nsCString>& aResult) = 0;
 
   virtual nsresult AsyncSetWindow(NPP instance, NPWindow* window) = 0;
-  virtual nsresult GetImage(NPP instance, ImageContainer* aContainer, Image** aImage) = 0;
+  virtual nsresult GetImageContainer(NPP instance, ImageContainer** aContainer) = 0;
   virtual nsresult GetImageSize(NPP instance, nsIntSize* aSize) = 0;
   virtual bool UseAsyncPainting() = 0;
 #if defined(XP_MACOSX)
   virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing) = 0;
 #endif
 
   /**
    * The next three methods are the third leg in the trip to
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -682,22 +682,21 @@ PluginModuleParent::HandleGUIEvent(NPP i
     if (!i)
         return NS_ERROR_FAILURE;
 
     return i->HandleGUIEvent(anEvent, handled);
 }
 #endif
 
 nsresult
-PluginModuleParent::GetImage(NPP instance,
-                             mozilla::layers::ImageContainer* aContainer,
-                             mozilla::layers::Image** aImage)
+PluginModuleParent::GetImageContainer(NPP instance,
+                             mozilla::layers::ImageContainer** aContainer)
 {
     PluginInstanceParent* i = InstCast(instance);
-    return !i ? NS_ERROR_FAILURE : i->GetImage(aContainer, aImage);
+    return !i ? NS_ERROR_FAILURE : i->GetImageContainer(aContainer);
 }
 
 nsresult
 PluginModuleParent::GetImageSize(NPP instance,
                                  nsIntSize* aSize)
 {
     PluginInstanceParent* i = InstCast(instance);
     return !i ? NS_ERROR_FAILURE : i->GetImageSize(aSize);
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -257,17 +257,17 @@ private:
                                 NPPVariable variable, void *ret_value);
     static NPError NPP_SetValue(NPP instance, NPNVariable variable,
                                 void *value);
     static void NPP_URLRedirectNotify(NPP instance, const char* url,
                                       int32_t status, void* notifyData);
 
     virtual bool HasRequiredFunctions();
     virtual nsresult AsyncSetWindow(NPP instance, NPWindow* window);
-    virtual nsresult GetImage(NPP instance, mozilla::layers::ImageContainer* aContainer, mozilla::layers::Image** aImage);
+    virtual nsresult GetImageContainer(NPP instance, mozilla::layers::ImageContainer** aContainer);
     virtual nsresult GetImageSize(NPP instance, nsIntSize* aSize);
     NS_OVERRIDE virtual bool UseAsyncPainting() { return true; }
     NS_OVERRIDE
     virtual nsresult SetBackgroundUnknown(NPP instance);
     NS_OVERRIDE
     virtual nsresult BeginUpdateBackground(NPP instance,
                                            const nsIntRect& aRect,
                                            gfxContext** aCtx);
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -1493,29 +1493,32 @@ nsObjectFrame::GetPaintedRect(nsDisplayP
   nsIntSize size = mInstanceOwner->GetCurrentImageSize();
   nsPresContext* pc = PresContext();
   r.IntersectRect(r, nsRect(0, 0, pc->DevPixelsToAppUnits(size.width),
                                   pc->DevPixelsToAppUnits(size.height)));
   return r;
 }
 
 void
-nsObjectFrame::UpdateImageLayer(ImageContainer* aContainer, const gfxRect& aRect)
+nsObjectFrame::UpdateImageLayer(const gfxRect& aRect)
 {
   if (!mInstanceOwner) {
     return;
   }
 
 #ifdef XP_MACOSX
   if (!mInstanceOwner->UseAsyncRendering()) {
     mInstanceOwner->DoCocoaEventDrawRect(aRect, nsnull);
+    // This makes sure the image on the container is up to date.
+    // XXX - Eventually we probably just want to make sure DoCocoaEventDrawRect
+    // updates the image container, to make this truly use 'push' semantics
+    // too.
+    mInstanceOwner->GetImageContainer();
   }
 #endif
-
-  mInstanceOwner->SetCurrentImage(aContainer);
 }
 
 LayerState
 nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder,
                              LayerManager* aManager)
 {
   if (!mInstanceOwner)
     return LAYER_NONE;
@@ -1547,26 +1550,21 @@ nsObjectFrame::BuildLayer(nsDisplayListB
   mInstanceOwner->GetWindow(window);
   if (!window)
     return nsnull;
 
   if (window->width <= 0 || window->height <= 0)
     return nsnull;
 
   // Create image
-  nsRefPtr<ImageContainer> container = GetImageContainer();
+  nsRefPtr<ImageContainer> container = mInstanceOwner->GetImageContainer();
 
-  {
-    nsRefPtr<Image> current = container->GetCurrentImage();
-    if (!current) {
-      // Only set the current image if there isn't already one. If there is
-      // already one, InvalidateRect() will be keeping it up to date.
-      if (!mInstanceOwner->SetCurrentImage(container))
-        return nsnull;
-    }
+  if (!container) {
+    // This can occur if our instance is gone.
+    return nsnull;
   }
 
   gfxIntSize size = container->GetCurrentSize();
 
   nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
   gfxRect r = nsLayoutUtils::RectToGfxRect(area, PresContext()->AppUnitsPerDevPixel());
   // to provide crisper and faster drawing.
   r.Round();
@@ -1580,17 +1578,17 @@ nsObjectFrame::BuildLayer(nsDisplayListB
       layer = aManager->CreateImageLayer();
       if (!layer)
         return nsnull;
     }
 
     NS_ASSERTION(layer->GetType() == Layer::TYPE_IMAGE, "Bad layer type");
 
     ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
-    UpdateImageLayer(container, r);
+    UpdateImageLayer(r);
 
     imglayer->SetContainer(container);
     gfxPattern::GraphicsFilter filter =
       nsLayoutUtils::GetGraphicsFilterForFrame(this);
 #ifdef MOZ_GFX_OPTIMIZE_MOBILE
     if (!aManager->IsCompositingCheap()) {
       // Pixman just horrible with bilinear filter scaling
       filter = gfxPattern::FILTER_NEAREST;
--- a/layout/generic/nsObjectFrame.h
+++ b/layout/generic/nsObjectFrame.h
@@ -153,17 +153,17 @@ public:
   // for a given aRoot, this walks the frame tree looking for the next outFrame
   static nsIObjectFrame* GetNextObjectFrame(nsPresContext* aPresContext,
                                             nsIFrame* aRoot);
 
   // nsIReflowCallback
   virtual bool ReflowFinished();
   virtual void ReflowCallbackCanceled();
 
-  void UpdateImageLayer(ImageContainer* aContainer, const gfxRect& aRect);
+  void UpdateImageLayer(const gfxRect& aRect);
 
   /**
    * Builds either an ImageLayer or a ReadbackLayer, depending on the type
    * of aItem (TYPE_PLUGIN or TYPE_PLUGIN_READBACK respectively).
    */
   already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                      LayerManager* aManager,
                                      nsDisplayItem* aItem);