Bug 782372 - Splits ImageLayers.h into ImageLayers.h ImageContainer.h and ImageTypes.h, r=bgirard
authorNicolas Silva <nsilva@mozilla.com>
Sun, 19 Aug 2012 15:33:25 -0400
changeset 108219 54f5895b567a767b6f738bd78dff3f90bc6dcd29
parent 108218 6c1dfc8d5b4b19218d57468ec1536db62f1e2fe7
child 108220 28dc3eadf4a08de39728beff55dc9cdb310a0929
push idunknown
push userunknown
push dateunknown
reviewersbgirard
bugs782372
milestone17.0a1
Bug 782372 - Splits ImageLayers.h into ImageLayers.h ImageContainer.h and ImageTypes.h, r=bgirard
content/base/src/nsContentUtils.cpp
content/html/content/src/nsHTMLCanvasElement.cpp
content/media/VideoFrameContainer.h
content/media/VideoSegment.h
content/media/nsBuiltinDecoder.h
content/media/nsBuiltinDecoderReader.cpp
content/media/nsBuiltinDecoderReader.h
content/media/nsMediaDecoder.h
content/media/webrtc/MediaEngineDefault.cpp
content/media/webrtc/MediaEngineWebRTCVideo.cpp
dom/camera/CameraPreview.cpp
dom/camera/GonkCameraPreview.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/ipc/PluginInstanceParent.cpp
dom/plugins/ipc/PluginInstanceParent.h
gfx/layers/ImageContainer.cpp
gfx/layers/ImageContainer.h
gfx/layers/ImageLayers.cpp
gfx/layers/ImageLayers.h
gfx/layers/ImageTypes.h
gfx/layers/Layers.cpp
gfx/layers/Makefile.in
gfx/layers/SharedTextureImage.h
gfx/layers/basic/BasicCanvasLayer.cpp
gfx/layers/basic/BasicImageLayer.cpp
gfx/layers/basic/BasicImages.cpp
gfx/layers/basic/BasicLayerManager.cpp
gfx/layers/basic/BasicLayers.h
gfx/layers/basic/BasicTiledThebesLayer.cpp
gfx/layers/d3d10/ImageLayerD3D10.cpp
gfx/layers/d3d10/ImageLayerD3D10.h
gfx/layers/d3d9/ImageLayerD3D9.cpp
gfx/layers/d3d9/ImageLayerD3D9.h
gfx/layers/ipc/ImageContainerChild.cpp
gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
gfx/layers/ipc/ShadowLayersParent.cpp
gfx/layers/opengl/CanvasLayerOGL.cpp
gfx/layers/opengl/CanvasLayerOGL.h
gfx/layers/opengl/ImageLayerOGL.cpp
gfx/layers/opengl/ImageLayerOGL.h
gfx/thebes/gfxUtils.h
image/src/RasterImage.cpp
layout/base/FrameLayerBuilder.cpp
layout/base/MaskLayerImageCache.cpp
layout/base/MaskLayerImageCache.h
layout/base/nsCSSRendering.cpp
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/generic/nsImageFrame.cpp
layout/generic/nsObjectFrame.cpp
layout/generic/nsVideoFrame.cpp
widget/gonk/Framebuffer.cpp
widget/gonk/nsWindow.cpp
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -7,16 +7,17 @@
 /* A namespace class for static layout utilities. */
 
 #include "mozilla/Util.h"
 
 #include "jsapi.h"
 #include "jsdbgapi.h"
 #include "jsfriendapi.h"
 
+#include "Layers.h"
 #include "nsJSUtils.h"
 #include "nsCOMPtr.h"
 #include "nsAString.h"
 #include "nsPrintfCString.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
 #include "nsDOMCID.h"
 #include "nsContentUtils.h"
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -21,17 +21,16 @@
 #include "nsJSUtils.h"
 #include "nsMathUtils.h"
 #include "nsStreamUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 
 #include "nsFrameManager.h"
 #include "nsDisplayList.h"
-#include "ImageLayers.h"
 #include "BasicLayers.h"
 #include "imgIEncoder.h"
 
 #include "nsIWritablePropertyBag2.h"
 
 #define DEFAULT_CANVAS_WIDTH 300
 #define DEFAULT_CANVAS_HEIGHT 150
 
--- a/content/media/VideoFrameContainer.h
+++ b/content/media/VideoFrameContainer.h
@@ -2,17 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef VIDEOFRAMECONTAINER_H_
 #define VIDEOFRAMECONTAINER_H_
 
-#include "ImageLayers.h"
+#include "ImageContainer.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/TimeStamp.h"
 #include "nsISupportsImpl.h"
 #include "gfxPoint.h"
 
 class nsHTMLMediaElement;
 
 namespace mozilla {
--- a/content/media/VideoSegment.h
+++ b/content/media/VideoSegment.h
@@ -2,17 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_VIDEOSEGMENT_H_
 #define MOZILLA_VIDEOSEGMENT_H_
 
 #include "MediaSegment.h"
-#include "ImageLayers.h"
+#include "ImageContainer.h"
 
 namespace mozilla {
 
 class VideoFrame {
 public:
   typedef mozilla::layers::Image Image;
 
   VideoFrame(already_AddRefed<Image> aImage, const gfxIntSize& aIntrinsicSize)
--- a/content/media/nsBuiltinDecoder.h
+++ b/content/media/nsBuiltinDecoder.h
@@ -190,21 +190,26 @@ destroying the nsBuiltinDecoder object.
 #include "nsSize.h"
 #include "prlog.h"
 #include "gfxContext.h"
 #include "gfxRect.h"
 #include "MediaResource.h"
 #include "nsMediaDecoder.h"
 #include "nsHTMLMediaElement.h"
 #include "mozilla/ReentrantMonitor.h"
-#include "ImageLayers.h"
-class nsAudioStream;
 
-typedef mozilla::layers::Image Image;
-typedef mozilla::layers::ImageContainer ImageContainer;
+namespace mozilla {
+namespace layers {
+class Image;
+} //namespace
+} //namespace
+
+typedef mozilla::layers::Image Image; 
+
+class nsAudioStream;
 
 static inline bool IsCurrentThread(nsIThread* aThread) {
   return NS_GetCurrentThread() == aThread;
 }
 
 // Decoder backends must implement this class to perform the codec
 // specific parts of decoding the video/audio format.
 class nsDecoderStateMachine : public nsRunnable
--- a/content/media/nsBuiltinDecoderReader.cpp
+++ b/content/media/nsBuiltinDecoderReader.cpp
@@ -143,22 +143,22 @@ VideoData* VideoData::Create(nsVideoInfo
   nsAutoPtr<VideoData> v(new VideoData(aOffset,
                                        aTime,
                                        aEndTime,
                                        aKeyframe,
                                        aTimecode,
                                        aInfo.mDisplay));
   // Currently our decoder only knows how to output to PLANAR_YCBCR
   // format.
-  Image::Format format = Image::PLANAR_YCBCR;
+  ImageFormat format = ImageFormat::PLANAR_YCBCR;
   v->mImage = aContainer->CreateImage(&format, 1);
   if (!v->mImage) {
     return nullptr;
   }
-  NS_ASSERTION(v->mImage->GetFormat() == Image::PLANAR_YCBCR,
+  NS_ASSERTION(v->mImage->GetFormat() == ImageFormat::PLANAR_YCBCR,
                "Wrong format?");
   PlanarYCbCrImage* videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get());
 
   PlanarYCbCrImage::Data data;
   const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
   const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
   const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2];
 
--- a/content/media/nsBuiltinDecoderReader.h
+++ b/content/media/nsBuiltinDecoderReader.h
@@ -14,17 +14,17 @@
 
 // Stores info relevant to presenting media frames.
 class nsVideoInfo {
 public:
   nsVideoInfo()
     : mAudioRate(44100),
       mAudioChannels(2),
       mDisplay(0,0),
-      mStereoMode(mozilla::layers::STEREO_MODE_MONO),
+      mStereoMode(mozilla::STEREO_MODE_MONO),
       mHasAudio(false),
       mHasVideo(false)
   {}
 
   // Returns true if it's safe to use aPicture as the picture to be
   // extracted inside a frame of size aFrame, and scaled up to and displayed
   // at a size of aDisplay. You should validate the frame, picture, and
   // display regions before using them to display video frames.
@@ -38,17 +38,17 @@ public:
   // Number of audio channels.
   PRUint32 mAudioChannels;
 
   // Size in pixels at which the video is rendered. This is after it has
   // been scaled by its aspect ratio.
   nsIntSize mDisplay;
 
   // Indicates the frame layout for single track stereo videos.
-  mozilla::layers::StereoMode mStereoMode;
+  mozilla::StereoMode mStereoMode;
 
   // True if we have an active audio bitstream.
   bool mHasAudio;
 
   // True if we have an active video bitstream.
   bool mHasVideo;
 };
 
@@ -457,17 +457,17 @@ public:
   public:
     VideoQueueMemoryFunctor() : mResult(0) {}
 
     virtual void* operator()(void* anObject) {
       const VideoData* v = static_cast<const VideoData*>(anObject);
       if (!v->mImage) {
         return nullptr;
       }
-      NS_ASSERTION(v->mImage->GetFormat() == mozilla::layers::Image::PLANAR_YCBCR,
+      NS_ASSERTION(v->mImage->GetFormat() == mozilla::ImageFormat::PLANAR_YCBCR,
                    "Wrong format?");
       mozilla::layers::PlanarYCbCrImage* vi = static_cast<mozilla::layers::PlanarYCbCrImage*>(v->mImage.get());
 
       mResult += vi->GetDataSize();
       return nullptr;
     }
 
     PRInt64 mResult;
--- a/content/media/nsMediaDecoder.h
+++ b/content/media/nsMediaDecoder.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(nsMediaDecoder_h_)
 #define nsMediaDecoder_h_
 
 #include "mozilla/ReentrantMonitor.h"
 #include "VideoFrameContainer.h"
 #include "MediaStreamGraph.h"
+#include "nsIObserver.h"
 
 class nsHTMLMediaElement;
 class nsIStreamListener;
 class nsTimeRanges;
 class nsIMemoryReporter;
 class nsIPrincipal;
 class nsITimer;
 
--- a/content/media/webrtc/MediaEngineDefault.cpp
+++ b/content/media/webrtc/MediaEngineDefault.cpp
@@ -2,16 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MediaEngineDefault.h"
 
 #include "nsCOMPtr.h"
 #include "nsDOMFile.h"
 #include "nsILocalFile.h"
+#include "Layers.h"
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidBridge.h"
 #include "nsISupportsUtils.h"
 #endif
 
 #define WIDTH 320
 #define HEIGHT 240
@@ -89,17 +90,17 @@ MediaEngineDefaultVideoSource::Start(Sou
   mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
   if (!mTimer) {
     return NS_ERROR_FAILURE;
   }
 
   mSource = aStream;
 
   // Allocate a single blank Image
-  layers::Image::Format format = layers::Image::PLANAR_YCBCR;
+  ImageFormat format = ImageFormat::PLANAR_YCBCR;
   mImageContainer = layers::LayerManager::CreateImageContainer();
 
   nsRefPtr<layers::Image> image = mImageContainer->CreateImage(&format, 1);
 
   int len = ((WIDTH * HEIGHT) * 3 / 2);
   mImage = static_cast<layers::PlanarYCbCrImage*>(image.get());
   PRUint8* frame = (PRUint8*) PR_Malloc(len);
   memset(frame, 0x80, len); // Gray
@@ -113,17 +114,17 @@ MediaEngineDefaultVideoSource::Start(Sou
   data.mYStride = WIDTH * lumaBpp / 8.0;
   data.mCbCrStride = WIDTH * chromaBpp / 8.0;
   data.mCbChannel = frame + HEIGHT * data.mYStride;
   data.mCrChannel = data.mCbChannel + HEIGHT * data.mCbCrStride / 2;
   data.mCbCrSize = gfxIntSize(WIDTH / 2, HEIGHT / 2);
   data.mPicX = 0;
   data.mPicY = 0;
   data.mPicSize = gfxIntSize(WIDTH, HEIGHT);
-  data.mStereoMode = layers::STEREO_MODE_MONO;
+  data.mStereoMode = STEREO_MODE_MONO;
 
   // SetData copies data, so we can free the frame
   mImage->SetData(data);
   PR_Free(frame);
 
   // AddTrack takes ownership of segment
   VideoSegment *segment = new VideoSegment();
   segment->AppendFrame(image.forget(), USECS_PER_S / FPS, gfxIntSize(WIDTH, HEIGHT));
--- a/content/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCVideo.cpp
@@ -1,13 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MediaEngineWebRTC.h"
+#include "Layers.h"
 
 namespace mozilla {
 
 /**
  * Webrtc video source.
  */
 NS_IMPL_THREADSAFE_ISUPPORTS1(MediaEngineWebRTCVideoSource, nsIRunnable)
 
@@ -42,17 +43,17 @@ MediaEngineWebRTCVideoSource::DeliverFra
   }
 
   // Check for proper state.
   if (mState != kStarted) {
     return 0;
   }
 
   // Create a video frame and append it to the track.
-  layers::Image::Format format = layers::Image::PLANAR_YCBCR;
+  ImageFormat format = ImageFormat::PLANAR_YCBCR;
   nsRefPtr<layers::Image> image = mImageContainer->CreateImage(&format, 1);
 
   layers::PlanarYCbCrImage* videoImage = static_cast<layers::PlanarYCbCrImage*>(image.get());
 
   PRUint8* frame = static_cast<PRUint8*> (buffer);
   const PRUint8 lumaBpp = 8;
   const PRUint8 chromaBpp = 4;
 
@@ -62,17 +63,17 @@ MediaEngineWebRTCVideoSource::DeliverFra
   data.mYStride = mWidth * lumaBpp/ 8;
   data.mCbCrStride = mWidth * chromaBpp / 8;
   data.mCbChannel = frame + mHeight * data.mYStride;
   data.mCrChannel = data.mCbChannel + mHeight * data.mCbCrStride / 2;
   data.mCbCrSize = gfxIntSize(mWidth/ 2, mHeight/ 2);
   data.mPicX = 0;
   data.mPicY = 0;
   data.mPicSize = gfxIntSize(mWidth, mHeight);
-  data.mStereoMode = layers::STEREO_MODE_MONO;
+  data.mStereoMode = STEREO_MODE_MONO;
 
   videoImage->SetData(data);
 
   VideoSegment segment;
   segment.AppendFrame(image.forget(), 1, gfxIntSize(mWidth, mHeight));
   mSource->AppendToTrack(mTrackID, &(segment));
   return 0;
 }
--- a/dom/camera/CameraPreview.cpp
+++ b/dom/camera/CameraPreview.cpp
@@ -1,14 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CameraPreview.h"
-
+#include "Layers.h"
 #define DOM_CAMERA_LOG_LEVEL  3
 #include "CameraCommon.h"
 
 using namespace mozilla;
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(CameraPreview, CameraPreview)
 
 class CameraPreviewListener : public MediaStreamListener
--- a/dom/camera/GonkCameraPreview.cpp
+++ b/dom/camera/GonkCameraPreview.cpp
@@ -28,17 +28,17 @@ using namespace mozilla;
 
 void
 GonkCameraPreview::ReceiveFrame(mozilla::layers::GraphicBufferLocked* aBuffer)
 {
   DOM_CAMERA_LOGI("%s:%d : this=%p\n", __func__, __LINE__, this);
   if (!aBuffer)
     return;
 
-  Image::Format format = Image::GONK_IO_SURFACE;
+  ImageFormat format = ImageFormat::GONK_IO_SURFACE;
   nsRefPtr<Image> image = mImageContainer->CreateImage(&format, 1);
   GonkIOSurfaceImage* videoImage = static_cast<GonkIOSurfaceImage*>(image.get());
   GonkIOSurfaceImage::Data data;
   data.mGraphicBuffer = aBuffer;
   data.mPicSize = gfxIntSize(mWidth, mHeight);
   videoImage->SetData(data);
 
   // AppendFrame() takes over image's reference
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -54,16 +54,17 @@ using mozilla::DefaultXDisplay;
 #include "nsIAppShell.h"
 #include "nsIDOMHTMLAppletElement.h"
 #include "nsAttrName.h"
 #include "nsIFocusManager.h"
 #include "nsFocusManager.h"
 #include "nsIDOMDragEvent.h"
 #include "nsIScrollableFrame.h"
 #include "nsIDocShell.h"
+#include "ImageContainer.h"
 
 #include "nsContentCID.h"
 #include "nsWidgetsCID.h"
 static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 #ifdef XP_WIN
 #include <wtypes.h>
@@ -172,17 +173,17 @@ nsPluginInstanceOwner::GetImageContainer
 #if MOZ_WIDGET_ANDROID
   // Right now we only draw with Gecko layers on Honeycomb and higher. See Paint()
   // for what we do on other versions.
   if (AndroidBridge::Bridge()->GetAPIVersion() < 11)
     return NULL;
   
   nsRefPtr<ImageContainer> container = LayerManager::CreateImageContainer();
 
-  Image::Format format = Image::SHARED_TEXTURE;
+  ImageFormat format = ImageFormat::SHARED_TEXTURE;
   nsRefPtr<Image> img = container->CreateImage(&format, 1);
 
   SharedTextureImage::Data data;
   data.mHandle = mInstance->CreateSharedHandle();
   data.mShareType = mozilla::gl::TextureImage::ThreadShared;
   data.mInverted = mInstance->Inverted();
 
   gfxRect r = GetPluginRect();
@@ -205,17 +206,17 @@ nsPluginInstanceOwner::GetImageContainer
     nsRefPtr<ImageContainer> container;
     // Every call to nsIPluginInstance::GetImage() creates
     // a new image.  See nsIPluginInstance.idl.
     mInstance->GetImageContainer(getter_AddRefs(container));
     if (container) {
 #ifdef XP_MACOSX
       AutoLockImage autoLock(container);
       Image* image = autoLock.GetImage();
-      if (image && image->GetFormat() == Image::MAC_IO_SURFACE && mObjectFrame) {
+      if (image && image->GetFormat() == ImageFormat::MAC_IO_SURFACE && mObjectFrame) {
         MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image);
         NS_ADDREF_THIS();
         oglImage->SetUpdateCallback(&DrawPlugin, this);
         oglImage->SetDestroyCallback(&OnDestroyImage);
       }
 #endif
       return container.forget();
     }
@@ -1799,17 +1800,17 @@ void nsPluginInstanceOwner::GetVideos(ns
 
   mInstance->GetVideos(aVideos);
 }
 
 already_AddRefed<ImageContainer> nsPluginInstanceOwner::GetImageContainerForVideo(nsNPAPIPluginInstance::VideoInfo* aVideoInfo)
 {
   nsRefPtr<ImageContainer> container = LayerManager::CreateImageContainer();
 
-  Image::Format format = Image::SHARED_TEXTURE;
+  ImageFormat format = ImageFormat::SHARED_TEXTURE;
   nsRefPtr<Image> img = container->CreateImage(&format, 1);
 
   SharedTextureImage::Data data;
 
   data.mHandle = mInstance->GLContext()->CreateSharedHandle(gl::TextureImage::ThreadShared, aVideoInfo->mSurfaceTexture, gl::GLContext::SurfaceTexture);
   data.mShareType = mozilla::gl::TextureImage::ThreadShared;
   data.mInverted = mInstance->Inverted();
   data.mSize = gfxIntSize(aVideoInfo->mDimensions.width, aVideoInfo->mDimensions.height);
@@ -3711,17 +3712,17 @@ void nsPluginInstanceOwner::SetFrame(nsO
   if (mObjectFrame) {
     // We have an old frame.
     // Drop image reference because the child may destroy the surface after we return.
     nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
     if (container) {
 #ifdef XP_MACOSX
       AutoLockImage autoLock(container);
       Image *image = autoLock.GetImage();
-      if (image && (image->GetFormat() == Image::MAC_IO_SURFACE) && mObjectFrame) {
+      if (image && (image->GetFormat() == ImageFormat::MAC_IO_SURFACE) && mObjectFrame) {
         // Undo what we did to the current image in SetCurrentImageInTransaction().
         MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image);
         oglImage->SetUpdateCallback(nullptr, nullptr);
         oglImage->SetDestroyCallback(nullptr);
         // If we have a current image here, its destructor hasn't yet been
         // called, so OnDestroyImage() can't yet have been called.  So we need
         // to do ourselves what OnDestroyImage() would have done.
         NS_RELEASE_THIS();
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -20,16 +20,17 @@
 #include "mozilla/StandardInteger.h" // for intptr_t
 #ifdef MOZ_X11
 #include "gfxXlibSurface.h"
 #endif
 #include "gfxContext.h"
 #include "gfxColor.h"
 #include "gfxUtils.h"
 #include "nsNPAPIPluginInstance.h"
+#include "Layers.h"
 
 #if defined(OS_WIN)
 #include <windowsx.h>
 #include "gfxWindowsPlatform.h"
 #include "mozilla/plugins/PluginSurfaceParent.h"
 
 // Plugin focus event for widget.
 extern const PRUnichar* kOOPPPluginFocusEventId;
@@ -725,20 +726,20 @@ PluginInstanceParent::GetImageContainer(
     }
 
     if (!mFrontSurface && !ioSurface)
 #else
     if (!mFrontSurface)
 #endif
         return NS_ERROR_NOT_AVAILABLE;
 
-    Image::Format format = Image::CAIRO_SURFACE;
+    ImageFormat format = ImageFormat::CAIRO_SURFACE;
 #ifdef XP_MACOSX
     if (ioSurface) {
-        format = Image::MAC_IO_SURFACE;
+        format = ImageFormat::MAC_IO_SURFACE;
     }
 #endif
 
     ImageContainer *container = GetImageContainer();
 
     if (!container) {
         return NS_ERROR_FAILURE;
     }
@@ -752,30 +753,30 @@ PluginInstanceParent::GetImageContainer(
     nsRefPtr<Image> image;
     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?");
+        NS_ASSERTION(image->GetFormat() == ImageFormat::MAC_IO_SURFACE, "Wrong format?");
         MacIOSurfaceImage* ioImage = static_cast<MacIOSurfaceImage*>(image.get());
         MacIOSurfaceImage::Data ioData;
         ioData.mIOSurface = ioSurface;
         ioImage->SetData(ioData);
         container->SetCurrentImageInTransaction(ioImage);
 
         NS_IF_ADDREF(container);
         *aContainer = container;
         return NS_OK;
     }
 #endif
 
-    NS_ASSERTION(image->GetFormat() == Image::CAIRO_SURFACE, "Wrong format?");
+    NS_ASSERTION(image->GetFormat() == ImageFormat::CAIRO_SURFACE, "Wrong format?");
     CairoImage* pluginImage = static_cast<CairoImage*>(image.get());
     CairoImage::Data cairoData;
     cairoData.mSurface = mFrontSurface;
     cairoData.mSize = mFrontSurface->GetSize();
     pluginImage->SetData(cairoData);
 
     container->SetCurrentImageInTransaction(pluginImage);
 
--- a/dom/plugins/ipc/PluginInstanceParent.h
+++ b/dom/plugins/ipc/PluginInstanceParent.h
@@ -18,25 +18,29 @@
 #endif
 
 #include "npfunctions.h"
 #include "nsAutoPtr.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsRect.h"
 #include "gfxASurface.h"
-#include "ImageLayers.h"
+
 #ifdef MOZ_X11
 class gfxXlibSurface;
 #endif
 #include "mozilla/unused.h"
 #include "nsGUIEvent.h"
 #include "mozilla/unused.h"
 
 namespace mozilla {
+namespace layers {
+class ImageContainer;
+class CompositionNotifySink;
+}
 namespace plugins {
 
 class PBrowserStreamParent;
 class PluginModuleParent;
 
 class PluginInstanceParent : public PPluginInstanceParent
 {
     friend class PluginModuleParent;
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ImageContainer.cpp
@@ -0,0 +1,552 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+
+#include "mozilla/layers/ImageBridgeChild.h"
+#include "mozilla/layers/ImageContainerChild.h"
+
+#include "ImageContainer.h"
+#include "GonkIOSurfaceImage.h"
+#include "mozilla/ipc/Shmem.h"
+#include "mozilla/ipc/CrossProcessMutex.h"
+#include "SharedTextureImage.h"
+#include "gfxImageSurface.h"
+#include "gfxSharedImageSurface.h"
+#include "yuv_convert.h"
+#include "gfxUtils.h"
+
+#ifdef XP_MACOSX
+#include "mozilla/gfx/QuartzSupport.h"
+#endif
+
+#ifdef XP_WIN
+#include "gfxD2DSurface.h"
+#include "gfxWindowsPlatform.h"
+#include <d3d10_1.h>
+
+#include "d3d10/ImageLayerD3D10.h"
+#endif
+
+using namespace mozilla::ipc;
+using mozilla::gfx::DataSourceSurface;
+using mozilla::gfx::SourceSurface;
+
+
+namespace mozilla {
+namespace layers {
+
+already_AddRefed<Image>
+ImageFactory::CreateImage(const ImageFormat *aFormats,
+                          PRUint32 aNumFormats,
+                          const gfxIntSize &,
+                          BufferRecycleBin *aRecycleBin)
+{
+  if (!aNumFormats) {
+    return nullptr;
+  }
+  nsRefPtr<Image> img;
+  if (FormatInList(aFormats, aNumFormats, ImageFormat::PLANAR_YCBCR)) {
+    img = new PlanarYCbCrImage(aRecycleBin);
+  } else if (FormatInList(aFormats, aNumFormats, ImageFormat::CAIRO_SURFACE)) {
+    img = new CairoImage();
+  } else if (FormatInList(aFormats, aNumFormats, ImageFormat::SHARED_TEXTURE)) {
+    img = new SharedTextureImage();
+#ifdef XP_MACOSX
+  } else if (FormatInList(aFormats, aNumFormats, ImageFormat::MAC_IO_SURFACE)) {
+    img = new MacIOSurfaceImage();
+#endif
+#ifdef MOZ_WIDGET_GONK
+  } else if (FormatInList(aFormats, aNumFormats, ImageFormat::GONK_IO_SURFACE)) {
+    img = new GonkIOSurfaceImage();
+#endif
+  }
+  return img.forget();
+}
+
+BufferRecycleBin::BufferRecycleBin()
+  : mLock("mozilla.layers.BufferRecycleBin.mLock")
+{
+}
+
+void
+BufferRecycleBin::RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize)
+{
+  MutexAutoLock lock(mLock);
+
+  if (!mRecycledBuffers.IsEmpty() && aSize != mRecycledBufferSize) {
+    mRecycledBuffers.Clear();
+  }
+  mRecycledBufferSize = aSize;
+  mRecycledBuffers.AppendElement(aBuffer);
+}
+
+PRUint8*
+BufferRecycleBin::GetBuffer(PRUint32 aSize)
+{
+  MutexAutoLock lock(mLock);
+
+  if (mRecycledBuffers.IsEmpty() || mRecycledBufferSize != aSize)
+    return new PRUint8[aSize];
+
+  PRUint32 last = mRecycledBuffers.Length() - 1;
+  PRUint8* result = mRecycledBuffers[last].forget();
+  mRecycledBuffers.RemoveElementAt(last);
+  return result;
+}
+
+ImageContainer::ImageContainer(int flag) 
+: mReentrantMonitor("ImageContainer.mReentrantMonitor"),
+  mPaintCount(0),
+  mPreviousImagePainted(false),
+  mImageFactory(new ImageFactory()),
+  mRecycleBin(new BufferRecycleBin()),
+  mRemoteData(nullptr),
+  mRemoteDataMutex(nullptr),
+  mCompositionNotifySink(nullptr),
+  mImageContainerChild(nullptr)
+{
+  if (flag == ENABLE_ASYNC && ImageBridgeChild::IsCreated()) {
+    mImageContainerChild = 
+      ImageBridgeChild::GetSingleton()->CreateImageContainerChild();
+  }
+}
+
+ImageContainer::~ImageContainer()
+{
+  if (mImageContainerChild) {
+    mImageContainerChild->DispatchStop();
+  }
+}
+
+already_AddRefed<Image>
+ImageContainer::CreateImage(const ImageFormat *aFormats,
+                            PRUint32 aNumFormats)
+{
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+  return mImageFactory->CreateImage(aFormats, aNumFormats, mScaleHint, mRecycleBin);
+}
+
+void 
+ImageContainer::SetCurrentImageInternal(Image *aImage)
+{
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+  if (mRemoteData) {
+    NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
+    mRemoteDataMutex->Lock();
+    // This is important since it ensures we won't change the active image
+    // when we currently have a locked image that depends on mRemoteData.
+  }
+
+  mActiveImage = aImage;
+  CurrentImageChanged();
+
+  if (mRemoteData) {
+    mRemoteDataMutex->Unlock();
+  }
+}
+
+void
+ImageContainer::SetCurrentImage(Image *aImage)
+{
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+  if (mImageContainerChild) {
+    if (aImage) {
+      mImageContainerChild->SendImageAsync(this, aImage);
+    } else {
+      mImageContainerChild->DispatchSetIdle();
+    }
+  }
+  
+  SetCurrentImageInternal(aImage);
+}
+
+void
+ImageContainer::SetCurrentImageInTransaction(Image *aImage)
+{
+  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
+  NS_ASSERTION(!mImageContainerChild, "Should use async image transfer with ImageBridge.");
+  
+  SetCurrentImageInternal(aImage);
+}
+
+bool ImageContainer::IsAsync() const {
+  return mImageContainerChild != nullptr;
+}
+
+PRUint64 ImageContainer::GetAsyncContainerID() const
+{
+  NS_ASSERTION(IsAsync(),"Shared image ID is only relevant to async ImageContainers");
+  if (IsAsync()) {
+    return mImageContainerChild->GetID();
+  } else {
+    return 0; // zero is always an invalid SharedImageID
+  }
+}
+
+bool
+ImageContainer::HasCurrentImage()
+{
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+  if (mRemoteData) {
+    CrossProcessMutexAutoLock autoLock(*mRemoteDataMutex);
+    
+    EnsureActiveImage();
+
+    return !!mActiveImage.get();
+  }
+
+  return !!mActiveImage.get();
+}
+
+already_AddRefed<Image>
+ImageContainer::LockCurrentImage()
+{
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+  
+  if (mRemoteData) {
+    NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
+    mRemoteDataMutex->Lock();
+  }
+
+  EnsureActiveImage();
+
+  nsRefPtr<Image> retval = mActiveImage;
+  return retval.forget();
+}
+
+already_AddRefed<gfxASurface>
+ImageContainer::LockCurrentAsSurface(gfxIntSize *aSize, Image** aCurrentImage)
+{
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+  if (mRemoteData) {
+    NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
+    mRemoteDataMutex->Lock();
+
+    EnsureActiveImage();
+
+    if (aCurrentImage) {
+      NS_IF_ADDREF(mActiveImage);
+      *aCurrentImage = mActiveImage.get();
+    }
+
+    if (!mActiveImage) {
+      return nullptr;
+    } 
+
+    if (mActiveImage->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP) {
+      nsRefPtr<gfxImageSurface> newSurf =
+        new gfxImageSurface(mRemoteData->mBitmap.mData, mRemoteData->mSize, mRemoteData->mBitmap.mStride,
+                            mRemoteData->mFormat == RemoteImageData::BGRX32 ?
+                                                   gfxASurface::ImageFormatARGB32 :
+                                                   gfxASurface::ImageFormatRGB24);
+
+      *aSize = newSurf->GetSize();
+    
+      return newSurf.forget();
+    }
+
+    *aSize = mActiveImage->GetSize();
+    return mActiveImage->GetAsSurface();
+  }
+
+  if (aCurrentImage) {
+    NS_IF_ADDREF(mActiveImage);
+    *aCurrentImage = mActiveImage.get();
+  }
+
+  if (!mActiveImage) {
+    return nullptr;
+  }
+
+  *aSize = mActiveImage->GetSize();
+  return mActiveImage->GetAsSurface();
+}
+
+void
+ImageContainer::UnlockCurrentImage()
+{
+  if (mRemoteData) {
+    NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
+    mRemoteDataMutex->Unlock();
+  }
+}
+
+already_AddRefed<gfxASurface>
+ImageContainer::GetCurrentAsSurface(gfxIntSize *aSize)
+{
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+  if (mRemoteData) {
+    CrossProcessMutexAutoLock autoLock(*mRemoteDataMutex);
+    EnsureActiveImage();
+
+    if (!mActiveImage)
+      return nullptr;
+    *aSize = mRemoteData->mSize;
+  } else {
+    if (!mActiveImage)
+      return nullptr;
+    *aSize = mActiveImage->GetSize();
+  }
+  return mActiveImage->GetAsSurface();
+}
+
+gfxIntSize
+ImageContainer::GetCurrentSize()
+{
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+  if (mRemoteData) {
+    CrossProcessMutexAutoLock autoLock(*mRemoteDataMutex);
+
+    // We don't need to ensure we have an active image here, as we need to
+    // be in the mutex anyway, and this is easiest to return from there.
+    return mRemoteData->mSize;
+  }
+
+  if (!mActiveImage) {
+    return gfxIntSize(0,0);
+  }
+
+  return mActiveImage->GetSize();
+}
+
+void
+ImageContainer::SetRemoteImageData(RemoteImageData *aData, CrossProcessMutex *aMutex)
+{
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+  NS_ASSERTION(!mActiveImage || !aData, "No active image expected when SetRemoteImageData is called with non-NULL aData.");
+  NS_ASSERTION(!mRemoteData || !aData, "No remote data expected when SetRemoteImageData is called with non-NULL aData.");
+
+  mRemoteData = aData;
+
+  if (aData) {
+    memset(aData, 0, sizeof(RemoteImageData));
+  } else {
+    mActiveImage = nullptr;
+  }
+
+  mRemoteDataMutex = aMutex;
+}
+
+void
+ImageContainer::EnsureActiveImage()
+{
+  if (mRemoteData) {
+    if (mRemoteData->mWasUpdated) {
+      mActiveImage = nullptr;
+    }
+
+    if (mRemoteData->mType == RemoteImageData::RAW_BITMAP &&
+        mRemoteData->mBitmap.mData && !mActiveImage) {
+      nsRefPtr<RemoteBitmapImage> newImg = new RemoteBitmapImage();
+      
+      newImg->mFormat = mRemoteData->mFormat;
+      newImg->mData = mRemoteData->mBitmap.mData;
+      newImg->mSize = mRemoteData->mSize;
+      newImg->mStride = mRemoteData->mBitmap.mStride;
+      mRemoteData->mWasUpdated = false;
+              
+      mActiveImage = newImg;
+    }
+#ifdef XP_WIN
+    else if (mRemoteData->mType == RemoteImageData::DXGI_TEXTURE_HANDLE &&
+             mRemoteData->mTextureHandle && !mActiveImage) {
+      nsRefPtr<RemoteDXGITextureImage> newImg = new RemoteDXGITextureImage();
+      newImg->mSize = mRemoteData->mSize;
+      newImg->mHandle = mRemoteData->mTextureHandle;
+      newImg->mFormat = mRemoteData->mFormat;
+      mRemoteData->mWasUpdated = false;
+
+      mActiveImage = newImg;
+    }
+#endif
+  }
+}
+
+
+PlanarYCbCrImage::PlanarYCbCrImage(BufferRecycleBin *aRecycleBin)
+  : Image(nullptr, PLANAR_YCBCR)
+  , mBufferSize(0)
+  , mRecycleBin(aRecycleBin)
+{
+}
+
+PlanarYCbCrImage::~PlanarYCbCrImage()
+{
+  if (mBuffer) {
+    mRecycleBin->RecycleBuffer(mBuffer.forget(), mBufferSize);
+  }
+}
+
+PRUint8* 
+PlanarYCbCrImage::AllocateBuffer(PRUint32 aSize)
+{
+  return mRecycleBin->GetBuffer(aSize); 
+}
+
+static void
+CopyPlane(PRUint8 *aDst, PRUint8 *aSrc,
+          const gfxIntSize &aSize, PRInt32 aStride,
+          PRInt32 aOffset, PRInt32 aSkip)
+{
+  if (!aOffset && !aSkip) {
+    // Fast path: planar input.
+    memcpy(aDst, aSrc, aSize.height * aStride);
+  } else {
+    PRInt32 height = aSize.height;
+    PRInt32 width = aSize.width;
+    for (int y = 0; y < height; ++y) {
+      PRUint8 *src = aSrc + aOffset;
+      PRUint8 *dst = aDst;
+      if (!aSkip) {
+        // Fast path: offset only, no per-pixel skip.
+        memcpy(dst, src, width);
+      } else {
+        // Slow path
+        for (int x = 0; x < width; ++x) {
+          *dst++ = *src++;
+          src += aSkip;
+        }
+      }
+      aSrc += aStride;
+      aDst += aStride;
+    }
+  }
+}
+
+void
+PlanarYCbCrImage::CopyData(const Data& aData,
+                           PRInt32 aYOffset, PRInt32 aYSkip,
+                           PRInt32 aCbOffset, PRInt32 aCbSkip,
+                           PRInt32 aCrOffset, PRInt32 aCrSkip)
+{
+  mData = aData;
+
+  // update buffer size
+  mBufferSize = mData.mCbCrStride * mData.mCbCrSize.height * 2 +
+                mData.mYStride * mData.mYSize.height;
+
+  // get new buffer
+  mBuffer = AllocateBuffer(mBufferSize); 
+  if (!mBuffer)
+    return;
+
+  mData.mYChannel = mBuffer;
+  mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
+  mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
+
+  CopyPlane(mData.mYChannel, aData.mYChannel,
+            mData.mYSize, mData.mYStride,
+            aYOffset, aYSkip);
+  CopyPlane(mData.mCbChannel, aData.mCbChannel,
+            mData.mCbCrSize, mData.mCbCrStride,
+            aCbOffset, aCbSkip);
+  CopyPlane(mData.mCrChannel, aData.mCrChannel,
+            mData.mCbCrSize, mData.mCbCrStride,
+            aCrOffset, aCrSkip);
+
+  mSize = aData.mPicSize;
+}
+
+void
+PlanarYCbCrImage::SetData(const Data &aData)
+{
+  CopyData(aData);
+}
+
+already_AddRefed<gfxASurface>
+PlanarYCbCrImage::GetAsSurface()
+{
+  if (mSurface) {
+    nsRefPtr<gfxASurface> result = mSurface.get();
+    return result.forget();
+  }
+
+  gfxASurface::gfxImageFormat format = GetOffscreenFormat();
+
+  gfxIntSize size(mSize);
+  gfxUtils::GetYCbCrToRGBDestFormatAndSize(mData, format, size);
+  if (size.width > PlanarYCbCrImage::MAX_DIMENSION ||
+      size.height > PlanarYCbCrImage::MAX_DIMENSION) {
+    NS_ERROR("Illegal image dest width or height");
+    return nullptr;
+  }
+
+  nsRefPtr<gfxImageSurface> imageSurface =
+    new gfxImageSurface(mSize, format);
+
+  gfxUtils::ConvertYCbCrToRGB(mData, format, mSize,
+                              imageSurface->Data(),
+                              imageSurface->Stride());
+
+  mSurface = imageSurface;
+
+  return imageSurface.forget().get();
+}
+
+#ifdef XP_MACOSX
+void
+MacIOSurfaceImage::SetData(const Data& aData)
+{
+  mIOSurface = MacIOSurface::LookupSurface(aData.mIOSurface->GetIOSurfaceID());
+  mSize = gfxIntSize(mIOSurface->GetWidth(), mIOSurface->GetHeight());
+}
+
+already_AddRefed<gfxASurface>
+MacIOSurfaceImage::GetAsSurface()
+{
+  mIOSurface->Lock();
+  size_t bytesPerRow = mIOSurface->GetBytesPerRow();
+  size_t ioWidth = mIOSurface->GetWidth();
+  size_t ioHeight = mIOSurface->GetHeight();
+
+  unsigned char* ioData = (unsigned char*)mIOSurface->GetBaseAddress();
+
+  nsRefPtr<gfxImageSurface> imgSurface =
+    new gfxImageSurface(gfxIntSize(ioWidth, ioHeight), gfxASurface::ImageFormatARGB32);
+
+  for (int i = 0; i < ioHeight; i++) {
+    memcpy(imgSurface->Data() + i * imgSurface->Stride(),
+           ioData + i * bytesPerRow, ioWidth * 4);
+  }
+
+  mIOSurface->Unlock();
+
+  return imgSurface.forget();
+}
+
+void
+MacIOSurfaceImage::Update(ImageContainer* aContainer)
+{
+  if (mUpdateCallback) {
+    mUpdateCallback(aContainer, mPluginInstanceOwner);
+  }
+}
+#endif
+
+already_AddRefed<gfxASurface>
+RemoteBitmapImage::GetAsSurface()
+{
+  nsRefPtr<gfxImageSurface> newSurf =
+    new gfxImageSurface(mSize,
+    mFormat == RemoteImageData::BGRX32 ? gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32);
+
+  for (int y = 0; y < mSize.height; y++) {
+    memcpy(newSurf->Data() + newSurf->Stride() * y,
+           mData + mStride * y,
+           mSize.width * 4);
+  }
+
+  return newSurf.forget();
+}
+
+} // namespace
+} // namespace
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ImageContainer.h
@@ -0,0 +1,830 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GFX_IMAGECONTAINER_H
+#define GFX_IMAGECONTAINER_H
+
+#include "mozilla/Mutex.h"
+#include "mozilla/ReentrantMonitor.h"
+#include "gfxASurface.h" // for gfxImageFormat
+#include "LayersTypes.h" // for LayersBackend
+#include "mozilla/TimeStamp.h"
+#include "ImageTypes.h"
+
+#ifdef XP_WIN
+struct ID3D10Texture2D;
+struct ID3D10Device;
+struct ID3D10ShaderResourceView;
+#endif
+
+#ifdef XP_MACOSX
+#include "mozilla/gfx/MacIOSurface.h"
+#endif
+
+#ifdef MOZ_WIDGET_GONK
+# include <ui/GraphicBuffer.h>
+#endif
+
+typedef void* HANDLE;
+
+namespace mozilla {
+
+class CrossProcessMutex;
+namespace ipc {
+class Shmem;
+}
+    
+namespace layers {
+
+class ImageContainerChild;
+
+struct ImageBackendData
+{
+  virtual ~ImageBackendData() {}
+
+protected:
+  ImageBackendData() {}
+};
+
+/**
+ * A class representing a buffer of pixel data. The data can be in one
+ * of various formats including YCbCr.
+ * 
+ * Create an image using an ImageContainer. Fill the image with data, and
+ * then call ImageContainer::SetImage to display it. An image must not be
+ * modified after calling SetImage. Image implementations do not need to
+ * perform locking; when filling an Image, the Image client is responsible
+ * for ensuring only one thread accesses the Image at a time, and after
+ * SetImage the image is immutable.
+ * 
+ * When resampling an Image, only pixels within the buffer should be
+ * sampled. For example, cairo images should be sampled in EXTEND_PAD mode.
+ */
+class THEBES_API Image {
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Image)
+
+public:
+  virtual ~Image() {}
+
+
+  ImageFormat GetFormat() { return mFormat; }
+  void* GetImplData() { return mImplData; }
+
+  virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
+  virtual gfxIntSize GetSize() = 0;
+
+  ImageBackendData* GetBackendData(LayersBackend aBackend)
+  { return mBackendData[aBackend]; }
+  void SetBackendData(LayersBackend aBackend, ImageBackendData* aData)
+  { mBackendData[aBackend] = aData; }
+
+protected:
+  Image(void* aImplData, ImageFormat aFormat) :
+    mImplData(aImplData),
+    mFormat(aFormat)
+  {}
+
+  nsAutoPtr<ImageBackendData> mBackendData[mozilla::layers::LAYERS_LAST];
+
+  void* mImplData;
+  ImageFormat mFormat;
+};
+
+/**
+ * A RecycleBin is owned by an ImageContainer. We store buffers in it that we
+ * want to recycle from one image to the next.It's a separate object from 
+ * ImageContainer because images need to store a strong ref to their RecycleBin
+ * and we must avoid creating a reference loop between an ImageContainer and
+ * its active image.
+ */
+class BufferRecycleBin {
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RecycleBin)
+
+  //typedef mozilla::gl::GLContext GLContext;
+
+public:
+  BufferRecycleBin();
+
+  void RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize);
+  // Returns a recycled buffer of the right size, or allocates a new buffer.
+  PRUint8* GetBuffer(PRUint32 aSize);
+
+private:
+  typedef mozilla::Mutex Mutex;
+
+  // This protects mRecycledBuffers, mRecycledBufferSize, mRecycledTextures
+  // and mRecycledTextureSizes
+  Mutex mLock;
+
+  // We should probably do something to prune this list on a timer so we don't
+  // eat excess memory while video is paused...
+  nsTArray<nsAutoArrayPtr<PRUint8> > mRecycledBuffers;
+  // This is only valid if mRecycledBuffers is non-empty
+  PRUint32 mRecycledBufferSize;
+};
+
+/**
+ * Returns true if aFormat is in the given format array.
+ */
+static inline bool
+FormatInList(const ImageFormat* aFormats, PRUint32 aNumFormats,
+             ImageFormat aFormat)
+{
+  for (PRUint32 i = 0; i < aNumFormats; ++i) {
+    if (aFormats[i] == aFormat) {
+      return true;
+    }
+  }
+  return false;
+}
+
+class CompositionNotifySink
+{
+public:
+  virtual void DidComposite() = 0;
+  virtual ~CompositionNotifySink() {}
+};
+
+/**
+ * A class that manages Image creation for a LayerManager. The only reason
+ * we need a separate class here is that LayerMananers aren't threadsafe
+ * (because layers can only be used on the main thread) and we want to
+ * be able to create images from any thread, to facilitate video playback
+ * without involving the main thread, for example.
+ * Different layer managers can implement child classes of this making it
+ * possible to create layer manager specific images.
+ * This class is not meant to be used directly but rather can be set on an
+ * image container. This is usually done by the layer system internally and
+ * not explicitly by users. For PlanarYCbCr or Cairo images the default
+ * implementation will creates images whose data lives in system memory, for
+ * MacIOSurfaces the default implementation will be a simple MacIOSurface
+ * wrapper.
+ */
+
+class THEBES_API ImageFactory
+{
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageFactory)
+protected:
+  friend class ImageContainer;
+
+  ImageFactory() {}
+  virtual ~ImageFactory() {}
+
+  virtual already_AddRefed<Image> CreateImage(const ImageFormat* aFormats,
+                                              PRUint32 aNumFormats,
+                                              const gfxIntSize &aScaleHint,
+                                              BufferRecycleBin *aRecycleBin);
+
+};
+ 
+/**
+ * This struct is used to store RemoteImages, it is meant to be able to live in
+ * shared memory. Therefor it should not contain a vtable pointer. Remote
+ * users can manipulate the data in this structure to specify what image is to
+ * be drawn by the container. When accessing this data users should make sure
+ * the mutex synchronizing access to the structure is held!
+ */
+struct RemoteImageData {
+  enum Type {
+    /**
+     * This is a format that uses raw bitmap data.
+     */
+    RAW_BITMAP,
+
+    /**
+     * This is a format that uses a pointer to a texture do draw directly
+     * from a shared texture. Any process may have created this texture handle,
+     * the process creating the texture handle is responsible for managing it's
+     * lifetime by managing the lifetime of the first D3D texture object this
+     * handle was created for. It must also ensure the handle is not set
+     * current anywhere when the last reference to this object is released.
+     */
+    DXGI_TEXTURE_HANDLE
+  };
+  /* These formats describe the format in the memory byte-order */
+  enum Format {
+    /* 8 bits per channel */
+    BGRA32,
+    /* 8 bits per channel, alpha channel is ignored */
+    BGRX32
+  };
+
+  // This should be set to true if a change was made so that the ImageContainer
+  // knows to throw out any cached RemoteImage objects.
+  bool mWasUpdated;
+  Type mType;
+  Format mFormat;
+  gfxIntSize mSize;
+  union {
+    struct {
+      /* This pointer is set by a remote process, however it will be set to
+       * the container process' address the memory of the raw bitmap resides
+       * at.
+       */
+      unsigned char *mData;
+      int mStride;
+    } mBitmap;
+#ifdef XP_WIN
+    HANDLE mTextureHandle;
+#endif
+  };
+};
+
+/**
+ * A class that manages Images for an ImageLayer. The only reason
+ * we need a separate class here is that ImageLayers aren't threadsafe
+ * (because layers can only be used on the main thread) and we want to
+ * be able to set the current Image from any thread, to facilitate
+ * video playback without involving the main thread, for example.
+ *
+ * An ImageContainer can operate in one of three modes:
+ * 1) Normal. Triggered by constructing the ImageContainer with
+ * DISABLE_ASYNC or when compositing is happening on the main thread.
+ * SetCurrentImage changes ImageContainer state but nothing is sent to the
+ * compositor until the next layer transaction.
+ * 2) Asynchronous. Initiated by constructing the ImageContainer with
+ * ENABLE_ASYNC when compositing is happening on the main thread.
+ * SetCurrentImage sends a message through the ImageBridge to the compositor
+ * thread to update the image, without going through the main thread or
+ * a layer transaction.
+ * 3) Remote. Initiated by calling SetRemoteImageData on the ImageContainer
+ * before any other activity.
+ * The ImageContainer uses a shared memory block containing a cross-process mutex
+ * to communicate with the compositor thread. SetCurrentImage synchronously
+ * updates the shared state to point to the new image and the old image
+ * is immediately released (not true in Normal or Asynchronous modes).
+ */
+class THEBES_API ImageContainer {
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainer)
+public:
+
+  enum { DISABLE_ASYNC = 0x0, ENABLE_ASYNC = 0x01 };
+
+  ImageContainer(int flag = 0);
+
+  ~ImageContainer();
+
+  /**
+   * Create an Image in one of the given formats.
+   * Picks the "best" format from the list and creates an Image of that
+   * format.
+   * Returns null if this backend does not support any of the formats.
+   * Can be called on any thread. This method takes mReentrantMonitor
+   * when accessing thread-shared state.
+   */
+  already_AddRefed<Image> CreateImage(const ImageFormat* aFormats,
+                                      PRUint32 aNumFormats);
+
+  /**
+   * Set an Image as the current image to display. The Image must have
+   * been created by this ImageContainer.
+   * Can be called on any thread. This method takes mReentrantMonitor
+   * when accessing thread-shared state.
+   * aImage can be null. While it's null, nothing will be painted.
+   * 
+   * The Image data must not be modified after this method is called!
+   * Note that this must not be called if ENABLE_ASYNC has not been set.
+   *
+   * Implementations must call CurrentImageChanged() while holding
+   * mReentrantMonitor.
+   *
+   * If this ImageContainer has an ImageContainerChild for async video: 
+   * Schelude a task to send the image to the compositor using the 
+   * PImageBridge protcol without using the main thread.
+   */
+  void SetCurrentImage(Image* aImage);
+
+  /**
+   * Set an Image as the current image to display. The Image must have
+   * been created by this ImageContainer.
+   * Must be called on the main thread, within a layers transaction. 
+   * 
+   * This method takes mReentrantMonitor
+   * when accessing thread-shared state.
+   * aImage can be null. While it's null, nothing will be painted.
+   * 
+   * The Image data must not be modified after this method is called!
+   * Note that this must not be called if ENABLE_ASYNC been set.
+   *
+   * Implementations must call CurrentImageChanged() while holding
+   * mReentrantMonitor.
+   */
+  void SetCurrentImageInTransaction(Image* aImage);
+
+  /**
+   * Returns true if this ImageContainer uses the ImageBridge IPDL protocol.
+   *
+   * Can be called from any thread.
+   */
+  bool IsAsync() const;
+
+  /**
+   * If this ImageContainer uses ImageBridge, returns the ID associated to
+   * this container, for use in the ImageBridge protocol.
+   * Returns 0 if this ImageContainer does not use ImageBridge. Note that
+   * 0 is always an invalid ID for asynchronous image containers. 
+   *
+   * Can be called from ay thread.
+   */
+  PRUint64 GetAsyncContainerID() const;
+
+  /**
+   * Returns if the container currently has an image.
+   * Can be called on any thread. This method takes mReentrantMonitor
+   * when accessing thread-shared state.
+   */
+  bool HasCurrentImage();
+
+  /**
+   * Lock the current Image.
+   * This has to add a reference since otherwise there are race conditions
+   * where the current image is destroyed before the caller can add
+   * a reference. This lock strictly guarantees the underlying image remains
+   * valid, it does not mean the current image cannot change.
+   * Can be called on any thread. This method will lock the cross-process
+   * mutex to ensure remote processes cannot alter underlying data. This call
+   * -must- be balanced by a call to UnlockCurrentImage and users should avoid
+   * holding the image locked for a long time.
+   */
+  already_AddRefed<Image> LockCurrentImage();
+
+  /**
+   * This call unlocks the image. For remote images releasing the cross-process
+   * mutex.
+   */
+  void UnlockCurrentImage();
+
+  /**
+   * Get the current image as a gfxASurface. This is useful for fallback
+   * rendering.
+   * This can only be called from the main thread, since cairo objects
+   * can only be used from the main thread.
+   * This is defined here and not on Image because it's possible (likely)
+   * that some backends will make an Image "ready to draw" only when it
+   * becomes the current image for an image container.
+   * Returns null if there is no current image.
+   * Returns the size in aSize.
+   * The returned surface will never be modified. The caller must not
+   * modify it.
+   * Can be called on any thread. This method takes mReentrantMonitor
+   * when accessing thread-shared state.
+   * If the current image is a remote image, that is, if it is an image that
+   * may be shared accross processes, calling this function will make
+   * a copy of the image data while holding the mRemoteDataMutex. If possible,
+   * the lock methods should be used to avoid the copy, however this should be
+   * avoided if the surface is required for a long period of time.
+   */
+  already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSizeResult);
+
+  /**
+   * This is similar to GetCurrentAsSurface, however this does not make a copy
+   * of the image data and requires the user to call UnlockCurrentImage when
+   * done with the image data. Once UnlockCurrentImage has been called the
+   * surface returned by this function is no longer valid! This works for any
+   * type of image. Optionally a pointer can be passed to receive the current
+   * image.
+   */
+  already_AddRefed<gfxASurface> LockCurrentAsSurface(gfxIntSize* aSizeResult,
+                                                     Image** aCurrentImage = nullptr);
+
+  /**
+   * Returns the size of the image in pixels.
+   * Can be called on any thread. This method takes mReentrantMonitor when accessing
+   * thread-shared state.
+   */
+  gfxIntSize GetCurrentSize();
+
+  /**
+   * Sets a size that the image is expected to be rendered at.
+   * This is a hint for image backends to optimize scaling.
+   * Default implementation in this class is to ignore the hint.
+   * Can be called on any thread. This method takes mReentrantMonitor
+   * when accessing thread-shared state.
+   */
+  void SetScaleHint(const gfxIntSize& aScaleHint)
+  { mScaleHint = aScaleHint; }
+
+  void SetImageFactory(ImageFactory *aFactory)
+  {
+    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+    mImageFactory = aFactory ? aFactory : new ImageFactory();
+  }
+
+  /**
+   * Returns the time at which the currently contained image was first
+   * painted.  This is reset every time a new image is set as the current
+   * image.  Note this may return a null timestamp if the current image
+   * has not yet been painted.  Can be called from any thread.
+   */
+  TimeStamp GetPaintTime() {
+    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+    return mPaintTime;
+  }
+
+  /**
+   * Returns the number of images which have been contained in this container
+   * and painted at least once.  Can be called from any thread.
+   */
+  PRUint32 GetPaintCount() {
+    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+    return mPaintCount;
+  }
+
+  /**
+   * Increments mPaintCount if this is the first time aPainted has been
+   * painted, and sets mPaintTime if the painted image is the current image.
+   * current image.  Can be called from any thread.
+   */
+  void NotifyPaintedImage(Image* aPainted) {
+    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+    nsRefPtr<Image> current = mActiveImage;
+    if (aPainted == current) {
+      if (mPaintTime.IsNull()) {
+        mPaintTime = TimeStamp::Now();
+        mPaintCount++;
+      }
+    } else if (!mPreviousImagePainted) {
+      // While we were painting this image, the current image changed. We
+      // still must count it as painted, but can't set mPaintTime, since we're
+      // no longer the current image.
+      mPaintCount++;
+      mPreviousImagePainted = true;
+    }
+
+    if (mCompositionNotifySink) {
+      mCompositionNotifySink->DidComposite();
+    }
+  }
+
+  void SetCompositionNotifySink(CompositionNotifySink *aSink) {
+    mCompositionNotifySink = aSink;
+  }
+
+  /**
+   * This function is called to tell the ImageContainer where the
+   * (cross-process) segment lives where the shared data about possible
+   * remote images are stored. In addition to this a CrossProcessMutex object
+   * is passed telling the container how to synchronize access to this data.
+   * NOTE: This should be called during setup of the container and not after
+   * usage has started.
+   */
+  void SetRemoteImageData(RemoteImageData *aRemoteData,
+                          CrossProcessMutex *aRemoteDataMutex);
+  /**
+   * This can be used to check if the container has RemoteData set.
+   */
+  RemoteImageData *GetRemoteImageData() { return mRemoteData; }
+
+protected:
+  typedef mozilla::ReentrantMonitor ReentrantMonitor;
+
+  void SetCurrentImageInternal(Image* aImage);
+
+  // This is called to ensure we have an active image, this may not be true
+  // when we're storing image information in a RemoteImageData structure.
+  // NOTE: If we have remote data mRemoteDataMutex should be locked when
+  // calling this function!
+  void EnsureActiveImage();
+
+  // ReentrantMonitor to protect thread safe access to the "current
+  // image", and any other state which is shared between threads.
+  ReentrantMonitor mReentrantMonitor;
+
+  // Performs necessary housekeeping to ensure the painted frame statistics
+  // are accurate. Must be called by SetCurrentImage() implementations with
+  // mReentrantMonitor held.
+  void CurrentImageChanged() {
+    mReentrantMonitor.AssertCurrentThreadIn();
+    mPreviousImagePainted = !mPaintTime.IsNull();
+    mPaintTime = TimeStamp();
+  }
+
+  nsRefPtr<Image> mActiveImage;
+
+  // Number of contained images that have been painted at least once.  It's up
+  // to the ImageContainer implementation to ensure accesses to this are
+  // threadsafe.
+  PRUint32 mPaintCount;
+
+  // Time stamp at which the current image was first painted.  It's up to the
+  // ImageContainer implementation to ensure accesses to this are threadsafe.
+  TimeStamp mPaintTime;
+
+  // Denotes whether the previous image was painted.
+  bool mPreviousImagePainted;
+
+  // This is the image factory used by this container, layer managers using
+  // this container can set an alternative image factory that will be used to
+  // create images for this container.
+  nsRefPtr<ImageFactory> mImageFactory;
+
+  gfxIntSize mScaleHint;
+
+  nsRefPtr<BufferRecycleBin> mRecycleBin;
+
+  // This contains the remote image data for this container, if this is NULL
+  // that means the container has no other process that may control its active
+  // image.
+  RemoteImageData *mRemoteData;
+
+  // This cross-process mutex is used to synchronise access to mRemoteData.
+  // When this mutex is held, we will always be inside the mReentrantMonitor
+  // however the same is not true vice versa.
+  CrossProcessMutex *mRemoteDataMutex;
+
+  CompositionNotifySink *mCompositionNotifySink;
+
+  // This member points to an ImageContainerChild if this ImageContainer was 
+  // sucessfully created with ENABLE_ASYNC, or points to null otherwise.
+  // 'unsuccessful' in this case only means that the ImageContainerChild could not
+  // be created, most likely because off-main-thread compositing is not enabled.
+  // In this case the ImageContainer is perfectly usable, but it will forward 
+  // frames to the compositor through transactions in the main thread rather than 
+  // asynchronusly using the ImageBridge IPDL protocol.
+  nsRefPtr<ImageContainerChild> mImageContainerChild;
+};
+
+class AutoLockImage
+{
+public:
+  AutoLockImage(ImageContainer *aContainer) : mContainer(aContainer) { mImage = mContainer->LockCurrentImage(); }
+  AutoLockImage(ImageContainer *aContainer, gfxASurface **aSurface) : mContainer(aContainer) {
+    *aSurface = mContainer->LockCurrentAsSurface(&mSize, getter_AddRefs(mImage)).get();
+  }
+  ~AutoLockImage() { if (mContainer) { mContainer->UnlockCurrentImage(); } }
+
+  Image* GetImage() { return mImage; }
+  const gfxIntSize &GetSize() { return mSize; }
+
+  void Unlock() { 
+    if (mContainer) {
+      mImage = nullptr;
+      mContainer->UnlockCurrentImage();
+      mContainer = nullptr;
+    }
+  }
+
+  /** Things get a little tricky here, because our underlying image can -still-
+   * change, and OS X requires a complicated callback mechanism to update this
+   * we need to support staying the lock and getting the new image in a proper
+   * way. This method makes any images retrieved with GetImage invalid!
+   */
+  void Refresh() {
+    if (mContainer) {
+      mContainer->UnlockCurrentImage();
+      mImage = mContainer->LockCurrentImage();
+    }
+  }
+
+private:
+  ImageContainer *mContainer;
+  nsRefPtr<Image> mImage;
+  gfxIntSize mSize;
+};
+
+/****** Image subtypes for the different formats ******/
+
+/**
+ * We assume that the image data is in the REC 470M color space (see
+ * Theora specification, section 4.3.1).
+ *
+ * The YCbCr format can be:
+ *
+ * 4:4:4 - CbCr width/height are the same as Y.
+ * 4:2:2 - CbCr width is half that of Y. Height is the same.
+ * 4:2:0 - CbCr width and height is half that of Y.
+ *
+ * The color format is detected based on the height/width ratios
+ * defined above.
+ * 
+ * The Image that is rendered is the picture region defined by
+ * mPicX, mPicY and mPicSize. The size of the rendered image is
+ * mPicSize, not mYSize or mCbCrSize.
+ */
+class THEBES_API PlanarYCbCrImage : public Image {
+public:
+  struct Data {
+    // Luminance buffer
+    PRUint8* mYChannel;
+    PRInt32 mYStride;
+    gfxIntSize mYSize;
+    // Chroma buffers
+    PRUint8* mCbChannel;
+    PRUint8* mCrChannel;
+    PRInt32 mCbCrStride;
+    gfxIntSize mCbCrSize;
+    // Picture region
+    PRUint32 mPicX;
+    PRUint32 mPicY;
+    gfxIntSize mPicSize;
+    StereoMode mStereoMode;
+
+    nsIntRect GetPictureRect() const {
+      return nsIntRect(mPicX, mPicY,
+                       mPicSize.width,
+                       mPicSize.height);
+    }
+  };
+
+  enum {
+    MAX_DIMENSION = 16384
+  };
+
+  ~PlanarYCbCrImage();
+
+  /**
+   * This makes a copy of the data buffers, in order to support functioning
+   * in all different layer managers.
+   */
+  virtual void SetData(const Data& aData);
+
+  /**
+   * Ask this Image to not convert YUV to RGB during SetData, and make
+   * the original data available through GetData. This is optional,
+   * and not all PlanarYCbCrImages will support it.
+   */
+  virtual void SetDelayedConversion(bool aDelayed) { }
+
+  /**
+   * Grab the original YUV data. This is optional.
+   */
+  virtual const Data* GetData() { return &mData; }
+
+  /**
+   * Make a copy of the YCbCr data into local storage.
+   *
+   * @param aData           Input image data.
+   * @param aYOffset        Pixels to skip between lines in the Y plane.
+   * @param aYSkip          Pixels to skip between pixels in the Y plane.
+   * @param aCbOffset       Pixels to skip between lines in the Cb plane.
+   * @param aCbSkip         Pixels to skip between pixels in the Cb plane.
+   * @param aCrOffset       Pixels to skip between lines in the Cr plane.
+   * @param aCrSkip         Pixels to skip between pixels in the Cr plane.
+   */
+  void CopyData(const Data& aData,
+                PRInt32 aYOffset = 0, PRInt32 aYSkip = 0,
+                PRInt32 aCbOffset = 0, PRInt32 aCbSkip = 0,
+                PRInt32 aCrOffset = 0, PRInt32 aCrSkip = 0);
+
+  /**
+   * Return a buffer to store image data in.
+   * The default implementation returns memory that can
+   * be freed wit delete[]
+   */
+  virtual PRUint8* AllocateBuffer(PRUint32 aSize);
+
+  /**
+   * Return the number of bytes of heap memory used to store this image.
+   */
+  virtual PRUint32 GetDataSize() { return mBufferSize; }
+
+  already_AddRefed<gfxASurface> GetAsSurface();
+
+  virtual gfxIntSize GetSize() { return mSize; }
+
+  void SetOffscreenFormat(gfxASurface::gfxImageFormat aFormat) { mOffscreenFormat = aFormat; }
+  gfxASurface::gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; }
+
+  // XXX - not easy to protect these sadly.
+  nsAutoArrayPtr<PRUint8> mBuffer;
+  PRUint32 mBufferSize;
+  Data mData;
+  gfxIntSize mSize;
+  gfxASurface::gfxImageFormat mOffscreenFormat;
+  nsCountedRef<nsMainThreadSurfaceRef> mSurface;
+  nsRefPtr<BufferRecycleBin> mRecycleBin;
+
+  PlanarYCbCrImage(BufferRecycleBin *aRecycleBin);
+};
+
+/**
+ * Currently, the data in a CairoImage surface is treated as being in the
+ * device output color space. This class is very simple as all backends
+ * have to know about how to deal with drawing a cairo image.
+ */
+class THEBES_API CairoImage : public Image {
+public:
+  struct Data {
+    gfxASurface* mSurface;
+    gfxIntSize mSize;
+  };
+
+  /**
+   * This can only be called on the main thread. It may add a reference
+   * to the surface (which will eventually be released on the main thread).
+   * The surface must not be modified after this call!!!
+   */
+  void SetData(const Data& aData)
+  {
+    mSurface = aData.mSurface;
+    mSize = aData.mSize;
+  }
+
+
+  virtual already_AddRefed<gfxASurface> GetAsSurface()
+  {
+    NS_ASSERTION(NS_IsMainThread(), "Must be main thread");
+    nsRefPtr<gfxASurface> surface = mSurface.get();
+    return surface.forget();
+  }
+
+  gfxIntSize GetSize() { return mSize; }
+
+  CairoImage() : Image(NULL, CAIRO_SURFACE) {}
+
+  nsCountedRef<nsMainThreadSurfaceRef> mSurface;
+  gfxIntSize mSize;
+};
+
+#ifdef XP_MACOSX
+class THEBES_API MacIOSurfaceImage : public Image {
+public:
+  struct Data {
+    MacIOSurface* mIOSurface;
+  };
+
+  MacIOSurfaceImage()
+    : Image(NULL, MAC_IO_SURFACE)
+    , mSize(0, 0)
+    , mPluginInstanceOwner(NULL)
+    , mUpdateCallback(NULL)
+    , mDestroyCallback(NULL)
+    {}
+
+  virtual ~MacIOSurfaceImage()
+  {
+    if (mDestroyCallback) {
+      mDestroyCallback(mPluginInstanceOwner);
+    }
+  }
+
+ /**
+  * This can only be called on the main thread. It may add a reference
+  * to the surface (which will eventually be released on the main thread).
+  * The surface must not be modified after this call!!!
+  */
+  virtual void SetData(const Data& aData);
+
+  /**
+   * Temporary hacks to force plugin drawing during an empty transaction.
+   * This should not be used for anything else, and will be removed
+   * when async plugin rendering is complete.
+   */
+  typedef void (*UpdateSurfaceCallback)(ImageContainer* aContainer, void* aInstanceOwner);
+  virtual void SetUpdateCallback(UpdateSurfaceCallback aCallback, void* aInstanceOwner)
+  {
+    mUpdateCallback = aCallback;
+    mPluginInstanceOwner = aInstanceOwner;
+  }
+
+  typedef void (*DestroyCallback)(void* aInstanceOwner);
+  virtual void SetDestroyCallback(DestroyCallback aCallback)
+  {
+    mDestroyCallback = aCallback;
+  }
+
+  virtual gfxIntSize GetSize()
+  {
+    return mSize;
+  }
+
+  MacIOSurface* GetIOSurface()
+  {
+    return mIOSurface;
+  }
+
+  void Update(ImageContainer* aContainer);
+
+  virtual already_AddRefed<gfxASurface> GetAsSurface();
+
+private:
+  gfxIntSize mSize;
+  RefPtr<MacIOSurface> mIOSurface;
+  void* mPluginInstanceOwner;
+  UpdateSurfaceCallback mUpdateCallback;
+  DestroyCallback mDestroyCallback;
+};
+#endif
+
+class RemoteBitmapImage : public Image {
+public:
+  RemoteBitmapImage() : Image(NULL, REMOTE_IMAGE_BITMAP) {}
+
+  already_AddRefed<gfxASurface> GetAsSurface();
+
+  gfxIntSize GetSize() { return mSize; }
+
+  unsigned char *mData;
+  int mStride;
+  gfxIntSize mSize;
+  RemoteImageData::Format mFormat;
+};
+
+
+} //namespace
+} //namespace
+
+#endif
\ No newline at end of file
--- a/gfx/layers/ImageLayers.cpp
+++ b/gfx/layers/ImageLayers.cpp
@@ -1,548 +1,44 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/ipc/Shmem.h"
-#include "mozilla/ipc/CrossProcessMutex.h"
 #include "ImageLayers.h"
-#include "SharedTextureImage.h"
-#include "gfxImageSurface.h"
-#include "gfxSharedImageSurface.h"
-#include "yuv_convert.h"
-#include "gfxUtils.h"
-#include "mozilla/layers/ImageBridgeChild.h"
-#include "mozilla/layers/ImageContainerChild.h"
-#include "GonkIOSurfaceImage.h"
-
-#ifdef XP_MACOSX
-#include "mozilla/gfx/QuartzSupport.h"
-#endif
-
-#ifdef XP_WIN
-#include "gfxD2DSurface.h"
-#include "gfxWindowsPlatform.h"
-#include <d3d10_1.h>
-
-#include "d3d10/ImageLayerD3D10.h"
-#endif
-
-using namespace mozilla::ipc;
-using mozilla::gfx::DataSourceSurface;
-using mozilla::gfx::SourceSurface;
+#include "ImageContainer.h"
 
 namespace mozilla {
 namespace layers {
 
-already_AddRefed<Image>
-ImageFactory::CreateImage(const Image::Format *aFormats,
-                          PRUint32 aNumFormats,
-                          const gfxIntSize &,
-                          BufferRecycleBin *aRecycleBin)
-{
-  if (!aNumFormats) {
-    return nullptr;
-  }
-  nsRefPtr<Image> img;
-  if (FormatInList(aFormats, aNumFormats, Image::PLANAR_YCBCR)) {
-    img = new PlanarYCbCrImage(aRecycleBin);
-  } else if (FormatInList(aFormats, aNumFormats, Image::CAIRO_SURFACE)) {
-    img = new CairoImage();
-  } else if (FormatInList(aFormats, aNumFormats, Image::SHARED_TEXTURE)) {
-    img = new SharedTextureImage();
-#ifdef XP_MACOSX
-  } else if (FormatInList(aFormats, aNumFormats, Image::MAC_IO_SURFACE)) {
-    img = new MacIOSurfaceImage();
-#endif
-#ifdef MOZ_WIDGET_GONK
-  } else if (FormatInList(aFormats, aNumFormats, Image::GONK_IO_SURFACE)) {
-    img = new GonkIOSurfaceImage();
-#endif
-  }
-  return img.forget();
-}
-
-BufferRecycleBin::BufferRecycleBin()
-  : mLock("mozilla.layers.BufferRecycleBin.mLock")
-{
-}
-
-void
-BufferRecycleBin::RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize)
-{
-  MutexAutoLock lock(mLock);
-
-  if (!mRecycledBuffers.IsEmpty() && aSize != mRecycledBufferSize) {
-    mRecycledBuffers.Clear();
-  }
-  mRecycledBufferSize = aSize;
-  mRecycledBuffers.AppendElement(aBuffer);
-}
-
-PRUint8*
-BufferRecycleBin::GetBuffer(PRUint32 aSize)
-{
-  MutexAutoLock lock(mLock);
-
-  if (mRecycledBuffers.IsEmpty() || mRecycledBufferSize != aSize)
-    return new PRUint8[aSize];
-
-  PRUint32 last = mRecycledBuffers.Length() - 1;
-  PRUint8* result = mRecycledBuffers[last].forget();
-  mRecycledBuffers.RemoveElementAt(last);
-  return result;
-}
-
-ImageContainer::ImageContainer(int flag) 
-: mReentrantMonitor("ImageContainer.mReentrantMonitor"),
-  mPaintCount(0),
-  mPreviousImagePainted(false),
-  mImageFactory(new ImageFactory()),
-  mRecycleBin(new BufferRecycleBin()),
-  mRemoteData(nullptr),
-  mRemoteDataMutex(nullptr),
-  mCompositionNotifySink(nullptr),
-  mImageContainerChild(nullptr)
-{
-  if (flag == ENABLE_ASYNC && ImageBridgeChild::IsCreated()) {
-    mImageContainerChild = 
-      ImageBridgeChild::GetSingleton()->CreateImageContainerChild();
-  }
-}
-
-ImageContainer::~ImageContainer()
-{
-  if (mImageContainerChild) {
-    mImageContainerChild->DispatchStop();
-  }
-}
-
-already_AddRefed<Image>
-ImageContainer::CreateImage(const Image::Format *aFormats,
-                            PRUint32 aNumFormats)
-{
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-  return mImageFactory->CreateImage(aFormats, aNumFormats, mScaleHint, mRecycleBin);
-}
-
-void 
-ImageContainer::SetCurrentImageInternal(Image *aImage)
-{
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-  if (mRemoteData) {
-    NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
-    mRemoteDataMutex->Lock();
-    // This is important since it ensures we won't change the active image
-    // when we currently have a locked image that depends on mRemoteData.
-  }
-
-  mActiveImage = aImage;
-  CurrentImageChanged();
-
-  if (mRemoteData) {
-    mRemoteDataMutex->Unlock();
-  }
-}
-
-void
-ImageContainer::SetCurrentImage(Image *aImage)
-{
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+ImageLayer::ImageLayer(LayerManager* aManager, void* aImplData)
+: Layer(aManager, aImplData), mFilter(gfxPattern::FILTER_GOOD)
+, mScaleMode(SCALE_NONE), mForceSingleTile(false) 
+{}
 
-  if (mImageContainerChild) {
-    if (aImage) {
-      mImageContainerChild->SendImageAsync(this, aImage);
-    } else {
-      mImageContainerChild->DispatchSetIdle();
-    }
-  }
-  
-  SetCurrentImageInternal(aImage);
-}
-
-void
-ImageContainer::SetCurrentImageInTransaction(Image *aImage)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
-  NS_ASSERTION(!mImageContainerChild, "Should use async image transfer with ImageBridge.");
-  
-  SetCurrentImageInternal(aImage);
-}
-
-bool ImageContainer::IsAsync() const {
-  return mImageContainerChild != nullptr;
-}
-
-PRUint64 ImageContainer::GetAsyncContainerID() const
-{
-  NS_ASSERTION(IsAsync(),"Shared image ID is only relevant to async ImageContainers");
-  if (IsAsync()) {
-    return mImageContainerChild->GetID();
-  } else {
-    return 0; // zero is always an invalid SharedImageID
-  }
-}
-
-bool
-ImageContainer::HasCurrentImage()
-{
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-  if (mRemoteData) {
-    CrossProcessMutexAutoLock autoLock(*mRemoteDataMutex);
-    
-    EnsureActiveImage();
-
-    return !!mActiveImage.get();
-  }
-
-  return !!mActiveImage.get();
-}
-
-already_AddRefed<Image>
-ImageContainer::LockCurrentImage()
-{
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-  
-  if (mRemoteData) {
-    NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
-    mRemoteDataMutex->Lock();
-  }
+ImageLayer::~ImageLayer()
+{}
 
-  EnsureActiveImage();
-
-  nsRefPtr<Image> retval = mActiveImage;
-  return retval.forget();
-}
-
-already_AddRefed<gfxASurface>
-ImageContainer::LockCurrentAsSurface(gfxIntSize *aSize, Image** aCurrentImage)
+void ImageLayer::SetContainer(ImageContainer* aContainer) 
 {
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-  if (mRemoteData) {
-    NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
-    mRemoteDataMutex->Lock();
-
-    EnsureActiveImage();
-
-    if (aCurrentImage) {
-      NS_IF_ADDREF(mActiveImage);
-      *aCurrentImage = mActiveImage.get();
-    }
-
-    if (!mActiveImage) {
-      return nullptr;
-    } 
-
-    if (mActiveImage->GetFormat() == Image::REMOTE_IMAGE_BITMAP) {
-      nsRefPtr<gfxImageSurface> newSurf =
-        new gfxImageSurface(mRemoteData->mBitmap.mData, mRemoteData->mSize, mRemoteData->mBitmap.mStride,
-                            mRemoteData->mFormat == RemoteImageData::BGRX32 ?
-                                                   gfxASurface::ImageFormatARGB32 :
-                                                   gfxASurface::ImageFormatRGB24);
-
-      *aSize = newSurf->GetSize();
-    
-      return newSurf.forget();
-    }
-
-    *aSize = mActiveImage->GetSize();
-    return mActiveImage->GetAsSurface();
-  }
-
-  if (aCurrentImage) {
-    NS_IF_ADDREF(mActiveImage);
-    *aCurrentImage = mActiveImage.get();
-  }
-
-  if (!mActiveImage) {
-    return nullptr;
-  }
-
-  *aSize = mActiveImage->GetSize();
-  return mActiveImage->GetAsSurface();
-}
-
-void
-ImageContainer::UnlockCurrentImage()
-{
-  if (mRemoteData) {
-    NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
-    mRemoteDataMutex->Unlock();
-  }
+  mContainer = aContainer;
 }
 
-already_AddRefed<gfxASurface>
-ImageContainer::GetCurrentAsSurface(gfxIntSize *aSize)
-{
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-  if (mRemoteData) {
-    CrossProcessMutexAutoLock autoLock(*mRemoteDataMutex);
-    EnsureActiveImage();
-
-    if (!mActiveImage)
-      return nullptr;
-    *aSize = mRemoteData->mSize;
-  } else {
-    if (!mActiveImage)
-      return nullptr;
-    *aSize = mActiveImage->GetSize();
-  }
-  return mActiveImage->GetAsSurface();
-}
-
-gfxIntSize
-ImageContainer::GetCurrentSize()
-{
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-  if (mRemoteData) {
-    CrossProcessMutexAutoLock autoLock(*mRemoteDataMutex);
-
-    // We don't need to ensure we have an active image here, as we need to
-    // be in the mutex anyway, and this is easiest to return from there.
-    return mRemoteData->mSize;
-  }
-
-  if (!mActiveImage) {
-    return gfxIntSize(0,0);
-  }
-
-  return mActiveImage->GetSize();
-}
-
-void
-ImageContainer::SetRemoteImageData(RemoteImageData *aData, CrossProcessMutex *aMutex)
-{
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-  NS_ASSERTION(!mActiveImage || !aData, "No active image expected when SetRemoteImageData is called with non-NULL aData.");
-  NS_ASSERTION(!mRemoteData || !aData, "No remote data expected when SetRemoteImageData is called with non-NULL aData.");
-
-  mRemoteData = aData;
-
-  if (aData) {
-    memset(aData, 0, sizeof(RemoteImageData));
-  } else {
-    mActiveImage = nullptr;
-  }
-
-  mRemoteDataMutex = aMutex;
-}
-
-void
-ImageContainer::EnsureActiveImage()
-{
-  if (mRemoteData) {
-    if (mRemoteData->mWasUpdated) {
-      mActiveImage = nullptr;
-    }
-
-    if (mRemoteData->mType == RemoteImageData::RAW_BITMAP &&
-        mRemoteData->mBitmap.mData && !mActiveImage) {
-      nsRefPtr<RemoteBitmapImage> newImg = new RemoteBitmapImage();
-      
-      newImg->mFormat = mRemoteData->mFormat;
-      newImg->mData = mRemoteData->mBitmap.mData;
-      newImg->mSize = mRemoteData->mSize;
-      newImg->mStride = mRemoteData->mBitmap.mStride;
-      mRemoteData->mWasUpdated = false;
-              
-      mActiveImage = newImg;
-    }
-#ifdef XP_WIN
-    else if (mRemoteData->mType == RemoteImageData::DXGI_TEXTURE_HANDLE &&
-             mRemoteData->mTextureHandle && !mActiveImage) {
-      nsRefPtr<RemoteDXGITextureImage> newImg = new RemoteDXGITextureImage();
-      newImg->mSize = mRemoteData->mSize;
-      newImg->mHandle = mRemoteData->mTextureHandle;
-      newImg->mFormat = mRemoteData->mFormat;
-      mRemoteData->mWasUpdated = false;
-
-      mActiveImage = newImg;
-    }
-#endif
-  }
-}
-
-PlanarYCbCrImage::PlanarYCbCrImage(BufferRecycleBin *aRecycleBin)
-  : Image(nullptr, PLANAR_YCBCR)
-  , mBufferSize(0)
-  , mRecycleBin(aRecycleBin)
-{
-}
-
-PlanarYCbCrImage::~PlanarYCbCrImage()
-{
-  if (mBuffer) {
-    mRecycleBin->RecycleBuffer(mBuffer.forget(), mBufferSize);
-  }
-}
-
-PRUint8* 
-PlanarYCbCrImage::AllocateBuffer(PRUint32 aSize)
-{
-  return mRecycleBin->GetBuffer(aSize); 
-}
-
-static void
-CopyPlane(PRUint8 *aDst, PRUint8 *aSrc,
-          const gfxIntSize &aSize, PRInt32 aStride,
-          PRInt32 aOffset, PRInt32 aSkip)
+void ImageLayer::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
 {
-  if (!aOffset && !aSkip) {
-    // Fast path: planar input.
-    memcpy(aDst, aSrc, aSize.height * aStride);
-  } else {
-    PRInt32 height = aSize.height;
-    PRInt32 width = aSize.width;
-    for (int y = 0; y < height; ++y) {
-      PRUint8 *src = aSrc + aOffset;
-      PRUint8 *dst = aDst;
-      if (!aSkip) {
-        // Fast path: offset only, no per-pixel skip.
-        memcpy(dst, src, width);
-      } else {
-        // Slow path
-        for (int x = 0; x < width; ++x) {
-          *dst++ = *src++;
-          src += aSkip;
-        }
-      }
-      aSrc += aStride;
-      aDst += aStride;
-    }
-  }
-}
-
-void
-PlanarYCbCrImage::CopyData(const Data& aData,
-                           PRInt32 aYOffset, PRInt32 aYSkip,
-                           PRInt32 aCbOffset, PRInt32 aCbSkip,
-                           PRInt32 aCrOffset, PRInt32 aCrSkip)
-{
-  mData = aData;
-
-  // update buffer size
-  mBufferSize = mData.mCbCrStride * mData.mCbCrSize.height * 2 +
-                mData.mYStride * mData.mYSize.height;
-
-  // get new buffer
-  mBuffer = AllocateBuffer(mBufferSize); 
-  if (!mBuffer)
-    return;
-
-  mData.mYChannel = mBuffer;
-  mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
-  mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
-
-  CopyPlane(mData.mYChannel, aData.mYChannel,
-            mData.mYSize, mData.mYStride,
-            aYOffset, aYSkip);
-  CopyPlane(mData.mCbChannel, aData.mCbChannel,
-            mData.mCbCrSize, mData.mCbCrStride,
-            aCbOffset, aCbSkip);
-  CopyPlane(mData.mCrChannel, aData.mCrChannel,
-            mData.mCbCrSize, mData.mCbCrStride,
-            aCrOffset, aCrSkip);
-
-  mSize = aData.mPicSize;
-}
-
-void
-PlanarYCbCrImage::SetData(const Data &aData)
-{
-  CopyData(aData);
-}
-
-already_AddRefed<gfxASurface>
-PlanarYCbCrImage::GetAsSurface()
-{
-  if (mSurface) {
-    nsRefPtr<gfxASurface> result = mSurface.get();
-    return result.forget();
+  // Snap image edges to pixel boundaries
+  gfxRect snap(0, 0, 0, 0);
+  if (mContainer) {
+    gfxIntSize size = mContainer->GetCurrentSize();
+    snap.SizeTo(gfxSize(size.width, size.height));
   }
-
-  gfxASurface::gfxImageFormat format = GetOffscreenFormat();
-
-  gfxIntSize size(mSize);
-  gfxUtils::GetYCbCrToRGBDestFormatAndSize(mData, format, size);
-  if (size.width > PlanarYCbCrImage::MAX_DIMENSION ||
-      size.height > PlanarYCbCrImage::MAX_DIMENSION) {
-    NS_ERROR("Illegal image dest width or height");
-    return nullptr;
-  }
-
-  nsRefPtr<gfxImageSurface> imageSurface =
-    new gfxImageSurface(mSize, format);
-
-  gfxUtils::ConvertYCbCrToRGB(mData, format, mSize,
-                              imageSurface->Data(),
-                              imageSurface->Stride());
-
-  mSurface = imageSurface;
-
-  return imageSurface.forget().get();
-}
-
-#ifdef XP_MACOSX
-void
-MacIOSurfaceImage::SetData(const Data& aData)
-{
-  mIOSurface = MacIOSurface::LookupSurface(aData.mIOSurface->GetIOSurfaceID());
-  mSize = gfxIntSize(mIOSurface->GetWidth(), mIOSurface->GetHeight());
-}
-
-already_AddRefed<gfxASurface>
-MacIOSurfaceImage::GetAsSurface()
-{
-  mIOSurface->Lock();
-  size_t bytesPerRow = mIOSurface->GetBytesPerRow();
-  size_t ioWidth = mIOSurface->GetWidth();
-  size_t ioHeight = mIOSurface->GetHeight();
-
-  unsigned char* ioData = (unsigned char*)mIOSurface->GetBaseAddress();
-
-  nsRefPtr<gfxImageSurface> imgSurface =
-    new gfxImageSurface(gfxIntSize(ioWidth, ioHeight), gfxASurface::ImageFormatARGB32);
-
-  for (int i = 0; i < ioHeight; i++) {
-    memcpy(imgSurface->Data() + i * imgSurface->Stride(),
-           ioData + i * bytesPerRow, ioWidth * 4);
-  }
-
-  mIOSurface->Unlock();
-
-  return imgSurface.forget();
-}
-
-void
-MacIOSurfaceImage::Update(ImageContainer* aContainer)
-{
-  if (mUpdateCallback) {
-    mUpdateCallback(aContainer, mPluginInstanceOwner);
-  }
-}
-#endif
-
-already_AddRefed<gfxASurface>
-RemoteBitmapImage::GetAsSurface()
-{
-  nsRefPtr<gfxImageSurface> newSurf =
-    new gfxImageSurface(mSize,
-    mFormat == RemoteImageData::BGRX32 ? gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32);
-
-  for (int y = 0; y < mSize.height; y++) {
-    memcpy(newSurf->Data() + newSurf->Stride() * y,
-           mData + mStride * y,
-           mSize.width * 4);
-  }
-
-  return newSurf.forget();
+  // Snap our local transform first, and snap the inherited transform as well.
+  // This makes our snapping equivalent to what would happen if our content
+  // was drawn into a ThebesLayer (gfxContext would snap using the local
+  // transform, then we'd snap again when compositing the ThebesLayer).
+  mEffectiveTransform =
+      SnapTransform(GetLocalTransform(), snap, nullptr)*
+      SnapTransform(aTransformToSurface, gfxRect(0, 0, 0, 0), nullptr);
+  ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
 }
 
 }
 }
--- a/gfx/layers/ImageLayers.h
+++ b/gfx/layers/ImageLayers.h
@@ -3,652 +3,24 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_IMAGELAYER_H
 #define GFX_IMAGELAYER_H
 
 #include "Layers.h"
 
+#include "ImageTypes.h"
 #include "nsISupportsImpl.h"
 #include "gfxPattern.h"
-#include "nsThreadUtils.h"
-#include "mozilla/ReentrantMonitor.h"
-#include "mozilla/TimeStamp.h"
-#include "mozilla/mozalloc.h"
-#include "mozilla/Mutex.h"
-#include "gfxPlatform.h"
-
-#ifdef XP_MACOSX
-#include "mozilla/gfx/MacIOSurface.h"
-#endif
-#ifdef XP_WIN
-struct ID3D10Texture2D;
-struct ID3D10Device;
-struct ID3D10ShaderResourceView;
-
-typedef void* HANDLE;
-#endif
 
 namespace mozilla {
-
-class CrossProcessMutex;
-namespace ipc {
-class Shmem;
-}
-
 namespace layers {
 
-class ImageContainerChild;
-class ImageBridgeChild;
-
-enum StereoMode {
-  STEREO_MODE_MONO,
-  STEREO_MODE_LEFT_RIGHT,
-  STEREO_MODE_RIGHT_LEFT,
-  STEREO_MODE_BOTTOM_TOP,
-  STEREO_MODE_TOP_BOTTOM
-};
-
-struct ImageBackendData
-{
-  virtual ~ImageBackendData() {}
-
-protected:
-  ImageBackendData() {}
-};
-
-/**
- * A class representing a buffer of pixel data. The data can be in one
- * of various formats including YCbCr.
- * 
- * Create an image using an ImageContainer. Fill the image with data, and
- * then call ImageContainer::SetImage to display it. An image must not be
- * modified after calling SetImage. Image implementations do not need to
- * perform locking; when filling an Image, the Image client is responsible
- * for ensuring only one thread accesses the Image at a time, and after
- * SetImage the image is immutable.
- * 
- * When resampling an Image, only pixels within the buffer should be
- * sampled. For example, cairo images should be sampled in EXTEND_PAD mode.
- */
-class THEBES_API Image {
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Image)
-
-public:
-  virtual ~Image() {}
-
-  enum Format {
-    /**
-     * The PLANAR_YCBCR format creates a PlanarYCbCrImage. All backends should
-     * support this format, because the Ogg video decoder depends on it.
-     * The maximum image width and height is 16384.
-     */
-    PLANAR_YCBCR,
-
-    /**
-     * The CAIRO_SURFACE format creates a CairoImage. All backends should
-     * support this format, because video rendering sometimes requires it.
-     * 
-     * This format is useful even though a ThebesLayer could be used.
-     * It makes it easy to render a cairo surface when another Image format
-     * could be used. It can also avoid copying the surface data in some
-     * cases.
-     * 
-     * Images in CAIRO_SURFACE format should only be created and
-     * manipulated on the main thread, since the underlying cairo surface
-     * is main-thread-only.
-     */
-    CAIRO_SURFACE,
-
-    /**
-     * The MAC_IO_SURFACE format creates a MacIOSurfaceImage.
-     *
-     * It wraps an IOSurface object and binds it directly to a GL texture.
-     */
-    MAC_IO_SURFACE,
-
-    /**
-     * The GONK_IO_SURFACE format creates a GonkIOSurfaceImage.
-     *
-     * It wraps an GraphicBuffer object and binds it directly to a GL texture.
-     */
-    GONK_IO_SURFACE,
-
-    /**
-     * An bitmap image that can be shared with a remote process.
-     */
-    REMOTE_IMAGE_BITMAP,
-
-    /**
-     * A OpenGL texture that can be shared across threads or processes
-     */
-    SHARED_TEXTURE,
-
-    /**
-     * An DXGI shared surface handle that can be shared with a remote process.
-     */
-    REMOTE_IMAGE_DXGI_TEXTURE
-  };
-
-  Format GetFormat() { return mFormat; }
-  void* GetImplData() { return mImplData; }
-
-  virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
-  virtual gfxIntSize GetSize() = 0;
-
-  ImageBackendData* GetBackendData(LayersBackend aBackend)
-  { return mBackendData[aBackend]; }
-  void SetBackendData(LayersBackend aBackend, ImageBackendData* aData)
-  { mBackendData[aBackend] = aData; }
-
-protected:
-  Image(void* aImplData, Format aFormat) :
-    mImplData(aImplData),
-    mFormat(aFormat)
-  {}
-
-  nsAutoPtr<ImageBackendData> mBackendData[mozilla::layers::LAYERS_LAST];
-
-  void* mImplData;
-  Format mFormat;
-};
-
-/**
- * A RecycleBin is owned by an ImageContainer. We store buffers in it that we
- * want to recycle from one image to the next.It's a separate object from 
- * ImageContainer because images need to store a strong ref to their RecycleBin
- * and we must avoid creating a reference loop between an ImageContainer and
- * its active image.
- */
-class BufferRecycleBin {
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RecycleBin)
-
-  typedef mozilla::gl::GLContext GLContext;
-
-public:
-  BufferRecycleBin();
-
-  void RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize);
-  // Returns a recycled buffer of the right size, or allocates a new buffer.
-  PRUint8* GetBuffer(PRUint32 aSize);
-
-private:
-  typedef mozilla::Mutex Mutex;
-
-  // This protects mRecycledBuffers, mRecycledBufferSize, mRecycledTextures
-  // and mRecycledTextureSizes
-  Mutex mLock;
-
-  // We should probably do something to prune this list on a timer so we don't
-  // eat excess memory while video is paused...
-  nsTArray<nsAutoArrayPtr<PRUint8> > mRecycledBuffers;
-  // This is only valid if mRecycledBuffers is non-empty
-  PRUint32 mRecycledBufferSize;
-};
-
-/**
- * Returns true if aFormat is in the given format array.
- */
-static inline bool
-FormatInList(const Image::Format* aFormats, PRUint32 aNumFormats,
-             Image::Format aFormat)
-{
-  for (PRUint32 i = 0; i < aNumFormats; ++i) {
-    if (aFormats[i] == aFormat) {
-      return true;
-    }
-  }
-  return false;
-}
-
-class CompositionNotifySink
-{
-public:
-  virtual void DidComposite() = 0;
-  virtual ~CompositionNotifySink() {}
-};
-
-/**
- * A class that manages Image creation for a LayerManager. The only reason
- * we need a separate class here is that LayerMananers aren't threadsafe
- * (because layers can only be used on the main thread) and we want to
- * be able to create images from any thread, to facilitate video playback
- * without involving the main thread, for example.
- * Different layer managers can implement child classes of this making it
- * possible to create layer manager specific images.
- * This class is not meant to be used directly but rather can be set on an
- * image container. This is usually done by the layer system internally and
- * not explicitly by users. For PlanarYCbCr or Cairo images the default
- * implementation will creates images whose data lives in system memory, for
- * MacIOSurfaces the default implementation will be a simple MacIOSurface
- * wrapper.
- */
-
-class THEBES_API ImageFactory
-{
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageFactory)
-protected:
-  friend class ImageContainer;
-
-  ImageFactory() {}
-  virtual ~ImageFactory() {}
-
-  virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
-                                              PRUint32 aNumFormats,
-                                              const gfxIntSize &aScaleHint,
-                                              BufferRecycleBin *aRecycleBin);
-
-};
- 
-/**
- * This struct is used to store RemoteImages, it is meant to be able to live in
- * shared memory. Therefor it should not contain a vtable pointer. Remote
- * users can manipulate the data in this structure to specify what image is to
- * be drawn by the container. When accessing this data users should make sure
- * the mutex synchronizing access to the structure is held!
- */
-struct RemoteImageData {
-  enum Type {
-    /**
-     * This is a format that uses raw bitmap data.
-     */
-    RAW_BITMAP,
-
-    /**
-     * This is a format that uses a pointer to a texture do draw directly
-     * from a shared texture. Any process may have created this texture handle,
-     * the process creating the texture handle is responsible for managing it's
-     * lifetime by managing the lifetime of the first D3D texture object this
-     * handle was created for. It must also ensure the handle is not set
-     * current anywhere when the last reference to this object is released.
-     */
-    DXGI_TEXTURE_HANDLE
-  };
-  /* These formats describe the format in the memory byte-order */
-  enum Format {
-    /* 8 bits per channel */
-    BGRA32,
-    /* 8 bits per channel, alpha channel is ignored */
-    BGRX32
-  };
-
-  // This should be set to true if a change was made so that the ImageContainer
-  // knows to throw out any cached RemoteImage objects.
-  bool mWasUpdated;
-  Type mType;
-  Format mFormat;
-  gfxIntSize mSize;
-  union {
-    struct {
-      /* This pointer is set by a remote process, however it will be set to
-       * the container process' address the memory of the raw bitmap resides
-       * at.
-       */
-      unsigned char *mData;
-      int mStride;
-    } mBitmap;
-#ifdef XP_WIN
-    HANDLE mTextureHandle;
-#endif
-  };
-};
-
-/**
- * A class that manages Images for an ImageLayer. The only reason
- * we need a separate class here is that ImageLayers aren't threadsafe
- * (because layers can only be used on the main thread) and we want to
- * be able to set the current Image from any thread, to facilitate
- * video playback without involving the main thread, for example.
- *
- * An ImageContainer can operate in one of three modes:
- * 1) Normal. Triggered by constructing the ImageContainer with
- * DISABLE_ASYNC or when compositing is happening on the main thread.
- * SetCurrentImage changes ImageContainer state but nothing is sent to the
- * compositor until the next layer transaction.
- * 2) Asynchronous. Initiated by constructing the ImageContainer with
- * ENABLE_ASYNC when compositing is happening on the main thread.
- * SetCurrentImage sends a message through the ImageBridge to the compositor
- * thread to update the image, without going through the main thread or
- * a layer transaction.
- * 3) Remote. Initiated by calling SetRemoteImageData on the ImageContainer
- * before any other activity.
- * The ImageContainer uses a shared memory block containing a cross-process mutex
- * to communicate with the compositor thread. SetCurrentImage synchronously
- * updates the shared state to point to the new image and the old image
- * is immediately released (not true in Normal or Asynchronous modes).
- */
-class THEBES_API ImageContainer {
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainer)
-public:
-
-  enum { DISABLE_ASYNC = 0x0, ENABLE_ASYNC = 0x01 };
-
-  ImageContainer(int flag = 0);
-
-  ~ImageContainer();
-
-  /**
-   * Create an Image in one of the given formats.
-   * Picks the "best" format from the list and creates an Image of that
-   * format.
-   * Returns null if this backend does not support any of the formats.
-   * Can be called on any thread. This method takes mReentrantMonitor
-   * when accessing thread-shared state.
-   */
-  already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
-                                      PRUint32 aNumFormats);
-
-  /**
-   * Set an Image as the current image to display. The Image must have
-   * been created by this ImageContainer.
-   * Can be called on any thread. This method takes mReentrantMonitor
-   * when accessing thread-shared state.
-   * aImage can be null. While it's null, nothing will be painted.
-   * 
-   * The Image data must not be modified after this method is called!
-   * Note that this must not be called if ENABLE_ASYNC has not been set.
-   *
-   * Implementations must call CurrentImageChanged() while holding
-   * mReentrantMonitor.
-   *
-   * If this ImageContainer has an ImageContainerChild for async video: 
-   * Schelude a task to send the image to the compositor using the 
-   * PImageBridge protcol without using the main thread.
-   */
-  void SetCurrentImage(Image* aImage);
-
-  /**
-   * Set an Image as the current image to display. The Image must have
-   * been created by this ImageContainer.
-   * Must be called on the main thread, within a layers transaction. 
-   * 
-   * This method takes mReentrantMonitor
-   * when accessing thread-shared state.
-   * aImage can be null. While it's null, nothing will be painted.
-   * 
-   * The Image data must not be modified after this method is called!
-   * Note that this must not be called if ENABLE_ASYNC been set.
-   *
-   * Implementations must call CurrentImageChanged() while holding
-   * mReentrantMonitor.
-   */
-  void SetCurrentImageInTransaction(Image* aImage);
-
-  /**
-   * Returns true if this ImageContainer uses the ImageBridge IPDL protocol.
-   *
-   * Can be called from any thread.
-   */
-  bool IsAsync() const;
-
-  /**
-   * If this ImageContainer uses ImageBridge, returns the ID associated to
-   * this container, for use in the ImageBridge protocol.
-   * Returns 0 if this ImageContainer does not use ImageBridge. Note that
-   * 0 is always an invalid ID for asynchronous image containers. 
-   *
-   * Can be called from ay thread.
-   */
-  PRUint64 GetAsyncContainerID() const;
-
-  /**
-   * Returns if the container currently has an image.
-   * Can be called on any thread. This method takes mReentrantMonitor
-   * when accessing thread-shared state.
-   */
-  bool HasCurrentImage();
-
-  /**
-   * Lock the current Image.
-   * This has to add a reference since otherwise there are race conditions
-   * where the current image is destroyed before the caller can add
-   * a reference. This lock strictly guarantees the underlying image remains
-   * valid, it does not mean the current image cannot change.
-   * Can be called on any thread. This method will lock the cross-process
-   * mutex to ensure remote processes cannot alter underlying data. This call
-   * -must- be balanced by a call to UnlockCurrentImage and users should avoid
-   * holding the image locked for a long time.
-   */
-  already_AddRefed<Image> LockCurrentImage();
-
-  /**
-   * This call unlocks the image. For remote images releasing the cross-process
-   * mutex.
-   */
-  void UnlockCurrentImage();
-
-  /**
-   * Get the current image as a gfxASurface. This is useful for fallback
-   * rendering.
-   * This can only be called from the main thread, since cairo objects
-   * can only be used from the main thread.
-   * This is defined here and not on Image because it's possible (likely)
-   * that some backends will make an Image "ready to draw" only when it
-   * becomes the current image for an image container.
-   * Returns null if there is no current image.
-   * Returns the size in aSize.
-   * The returned surface will never be modified. The caller must not
-   * modify it.
-   * Can be called on any thread. This method takes mReentrantMonitor
-   * when accessing thread-shared state.
-   * If the current image is a remote image, that is, if it is an image that
-   * may be shared accross processes, calling this function will make
-   * a copy of the image data while holding the mRemoteDataMutex. If possible,
-   * the lock methods should be used to avoid the copy, however this should be
-   * avoided if the surface is required for a long period of time.
-   */
-  already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSizeResult);
-
-  /**
-   * This is similar to GetCurrentAsSurface, however this does not make a copy
-   * of the image data and requires the user to call UnlockCurrentImage when
-   * done with the image data. Once UnlockCurrentImage has been called the
-   * surface returned by this function is no longer valid! This works for any
-   * type of image. Optionally a pointer can be passed to receive the current
-   * image.
-   */
-  already_AddRefed<gfxASurface> LockCurrentAsSurface(gfxIntSize* aSizeResult,
-                                                     Image** aCurrentImage = nullptr);
-
-  /**
-   * Returns the size of the image in pixels.
-   * Can be called on any thread. This method takes mReentrantMonitor when accessing
-   * thread-shared state.
-   */
-  gfxIntSize GetCurrentSize();
-
-  /**
-   * Sets a size that the image is expected to be rendered at.
-   * This is a hint for image backends to optimize scaling.
-   * Default implementation in this class is to ignore the hint.
-   * Can be called on any thread. This method takes mReentrantMonitor
-   * when accessing thread-shared state.
-   */
-  void SetScaleHint(const gfxIntSize& aScaleHint)
-  { mScaleHint = aScaleHint; }
-
-  void SetImageFactory(ImageFactory *aFactory)
-  {
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-    mImageFactory = aFactory ? aFactory : new ImageFactory();
-  }
-
-  /**
-   * Returns the time at which the currently contained image was first
-   * painted.  This is reset every time a new image is set as the current
-   * image.  Note this may return a null timestamp if the current image
-   * has not yet been painted.  Can be called from any thread.
-   */
-  TimeStamp GetPaintTime() {
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-    return mPaintTime;
-  }
-
-  /**
-   * Returns the number of images which have been contained in this container
-   * and painted at least once.  Can be called from any thread.
-   */
-  PRUint32 GetPaintCount() {
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-    return mPaintCount;
-  }
-
-  /**
-   * Increments mPaintCount if this is the first time aPainted has been
-   * painted, and sets mPaintTime if the painted image is the current image.
-   * current image.  Can be called from any thread.
-   */
-  void NotifyPaintedImage(Image* aPainted) {
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-    nsRefPtr<Image> current = mActiveImage;
-    if (aPainted == current) {
-      if (mPaintTime.IsNull()) {
-        mPaintTime = TimeStamp::Now();
-        mPaintCount++;
-      }
-    } else if (!mPreviousImagePainted) {
-      // While we were painting this image, the current image changed. We
-      // still must count it as painted, but can't set mPaintTime, since we're
-      // no longer the current image.
-      mPaintCount++;
-      mPreviousImagePainted = true;
-    }
-
-    if (mCompositionNotifySink) {
-      mCompositionNotifySink->DidComposite();
-    }
-  }
-
-  void SetCompositionNotifySink(CompositionNotifySink *aSink) {
-    mCompositionNotifySink = aSink;
-  }
-
-  /**
-   * This function is called to tell the ImageContainer where the
-   * (cross-process) segment lives where the shared data about possible
-   * remote images are stored. In addition to this a CrossProcessMutex object
-   * is passed telling the container how to synchronize access to this data.
-   * NOTE: This should be called during setup of the container and not after
-   * usage has started.
-   */
-  void SetRemoteImageData(RemoteImageData *aRemoteData,
-                          CrossProcessMutex *aRemoteDataMutex);
-  /**
-   * This can be used to check if the container has RemoteData set.
-   */
-  RemoteImageData *GetRemoteImageData() { return mRemoteData; }
-
-protected:
-  typedef mozilla::ReentrantMonitor ReentrantMonitor;
-
-  void SetCurrentImageInternal(Image* aImage);
-
-  // This is called to ensure we have an active image, this may not be true
-  // when we're storing image information in a RemoteImageData structure.
-  // NOTE: If we have remote data mRemoteDataMutex should be locked when
-  // calling this function!
-  void EnsureActiveImage();
-
-  // ReentrantMonitor to protect thread safe access to the "current
-  // image", and any other state which is shared between threads.
-  ReentrantMonitor mReentrantMonitor;
-
-  // Performs necessary housekeeping to ensure the painted frame statistics
-  // are accurate. Must be called by SetCurrentImage() implementations with
-  // mReentrantMonitor held.
-  void CurrentImageChanged() {
-    mReentrantMonitor.AssertCurrentThreadIn();
-    mPreviousImagePainted = !mPaintTime.IsNull();
-    mPaintTime = TimeStamp();
-  }
-
-  nsRefPtr<Image> mActiveImage;
-
-  // Number of contained images that have been painted at least once.  It's up
-  // to the ImageContainer implementation to ensure accesses to this are
-  // threadsafe.
-  PRUint32 mPaintCount;
-
-  // Time stamp at which the current image was first painted.  It's up to the
-  // ImageContainer implementation to ensure accesses to this are threadsafe.
-  TimeStamp mPaintTime;
-
-  // Denotes whether the previous image was painted.
-  bool mPreviousImagePainted;
-
-  // This is the image factory used by this container, layer managers using
-  // this container can set an alternative image factory that will be used to
-  // create images for this container.
-  nsRefPtr<ImageFactory> mImageFactory;
-
-  gfxIntSize mScaleHint;
-
-  nsRefPtr<BufferRecycleBin> mRecycleBin;
-
-  // This contains the remote image data for this container, if this is NULL
-  // that means the container has no other process that may control its active
-  // image.
-  RemoteImageData *mRemoteData;
-
-  // This cross-process mutex is used to synchronise access to mRemoteData.
-  // When this mutex is held, we will always be inside the mReentrantMonitor
-  // however the same is not true vice versa.
-  CrossProcessMutex *mRemoteDataMutex;
-
-  CompositionNotifySink *mCompositionNotifySink;
-
-  // This member points to an ImageContainerChild if this ImageContainer was 
-  // sucessfully created with ENABLE_ASYNC, or points to null otherwise.
-  // 'unsuccessful' in this case only means that the ImageContainerChild could not
-  // be created, most likely because off-main-thread compositing is not enabled.
-  // In this case the ImageContainer is perfectly usable, but it will forward 
-  // frames to the compositor through transactions in the main thread rather than 
-  // asynchronusly using the ImageBridge IPDL protocol.
-  nsRefPtr<ImageContainerChild> mImageContainerChild;
-};
- 
-class AutoLockImage
-{
-public:
-  AutoLockImage(ImageContainer *aContainer) : mContainer(aContainer) { mImage = mContainer->LockCurrentImage(); }
-  AutoLockImage(ImageContainer *aContainer, gfxASurface **aSurface) : mContainer(aContainer) {
-    *aSurface = mContainer->LockCurrentAsSurface(&mSize, getter_AddRefs(mImage)).get();
-  }
-  ~AutoLockImage() { if (mContainer) { mContainer->UnlockCurrentImage(); } }
-
-  Image* GetImage() { return mImage; }
-  const gfxIntSize &GetSize() { return mSize; }
-
-  void Unlock() { 
-    if (mContainer) {
-      mImage = nullptr;
-      mContainer->UnlockCurrentImage();
-      mContainer = nullptr;
-    }
-  }
-
-  /** Things get a little tricky here, because our underlying image can -still-
-   * change, and OS X requires a complicated callback mechanism to update this
-   * we need to support staying the lock and getting the new image in a proper
-   * way. This method makes any images retrieved with GetImage invalid!
-   */
-  void Refresh() {
-    if (mContainer) {
-      mContainer->UnlockCurrentImage();
-      mImage = mContainer->LockCurrentImage();
-    }
-  }
-
-private:
-  ImageContainer *mContainer;
-  nsRefPtr<Image> mImage;
-  gfxIntSize mSize;
-};
+class ImageContainer;
 
 /**
  * A Layer which renders an Image.
  */
 class THEBES_API ImageLayer : public Layer {
 public:
   enum ScaleMode {
     SCALE_NONE,
@@ -656,20 +28,18 @@ public:
   // Unimplemented - SCALE_PRESERVE_ASPECT_RATIO_CONTAIN
   };
 
   /**
    * CONSTRUCTION PHASE ONLY
    * Set the ImageContainer. aContainer must have the same layer manager
    * as this layer.
    */
-  void SetContainer(ImageContainer* aContainer) 
-  {
-    mContainer = aContainer;  
-  }
+  void SetContainer(ImageContainer* aContainer);
+
   /**
    * CONSTRUCTION PHASE ONLY
    * Set the filter used to resample this image if necessary.
    */
   void SetFilter(gfxPattern::GraphicsFilter aFilter) { mFilter = aFilter; }
 
   /**
    * CONSTRUCTION PHASE ONLY
@@ -682,292 +52,36 @@ public:
   }
 
 
   ImageContainer* GetContainer() { return mContainer; }
   gfxPattern::GraphicsFilter GetFilter() { return mFilter; }
 
   MOZ_LAYER_DECL_NAME("ImageLayer", TYPE_IMAGE)
 
-  virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
-  {
-    // Snap image edges to pixel boundaries
-    gfxRect snap(0, 0, 0, 0);
-    if (mContainer) {
-      gfxIntSize size = mContainer->GetCurrentSize();
-      snap.SizeTo(gfxSize(size.width, size.height));
-    }
-    // Snap our local transform first, and snap the inherited transform as well.
-    // This makes our snapping equivalent to what would happen if our content
-    // was drawn into a ThebesLayer (gfxContext would snap using the local
-    // transform, then we'd snap again when compositing the ThebesLayer).
-    mEffectiveTransform =
-        SnapTransform(GetLocalTransform(), snap, nullptr)*
-        SnapTransform(aTransformToSurface, gfxRect(0, 0, 0, 0), nullptr);
-    ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
-  }
+  virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface);
 
   /**
    * if true, the image will only be backed by a single tile texture
    */
   void SetForceSingleTile(bool aForceSingleTile)
   {
     mForceSingleTile = aForceSingleTile;
     Mutated();
   }
 
 protected:
-  ImageLayer(LayerManager* aManager, void* aImplData)
-    : Layer(aManager, aImplData), mFilter(gfxPattern::FILTER_GOOD)
-    , mScaleMode(SCALE_NONE), mForceSingleTile(false) {}
-
+  ImageLayer(LayerManager* aManager, void* aImplData);
+  ~ImageLayer();
   virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
 
 
   nsRefPtr<ImageContainer> mContainer;
   gfxPattern::GraphicsFilter mFilter;
   gfxIntSize mScaleToSize;
   ScaleMode mScaleMode;
   bool mForceSingleTile;
 };
 
-/****** Image subtypes for the different formats ******/
-
-/**
- * We assume that the image data is in the REC 470M color space (see
- * Theora specification, section 4.3.1).
- *
- * The YCbCr format can be:
- *
- * 4:4:4 - CbCr width/height are the same as Y.
- * 4:2:2 - CbCr width is half that of Y. Height is the same.
- * 4:2:0 - CbCr width and height is half that of Y.
- *
- * The color format is detected based on the height/width ratios
- * defined above.
- * 
- * The Image that is rendered is the picture region defined by
- * mPicX, mPicY and mPicSize. The size of the rendered image is
- * mPicSize, not mYSize or mCbCrSize.
- */
-class THEBES_API PlanarYCbCrImage : public Image {
-public:
-  struct Data {
-    // Luminance buffer
-    PRUint8* mYChannel;
-    PRInt32 mYStride;
-    gfxIntSize mYSize;
-    // Chroma buffers
-    PRUint8* mCbChannel;
-    PRUint8* mCrChannel;
-    PRInt32 mCbCrStride;
-    gfxIntSize mCbCrSize;
-    // Picture region
-    PRUint32 mPicX;
-    PRUint32 mPicY;
-    gfxIntSize mPicSize;
-    StereoMode mStereoMode;
-
-    nsIntRect GetPictureRect() const {
-      return nsIntRect(mPicX, mPicY,
-                       mPicSize.width,
-                       mPicSize.height);
-    }
-  };
-
-  enum {
-    MAX_DIMENSION = 16384
-  };
-
-  ~PlanarYCbCrImage();
-
-  /**
-   * This makes a copy of the data buffers, in order to support functioning
-   * in all different layer managers.
-   */
-  virtual void SetData(const Data& aData);
-
-  /**
-   * Ask this Image to not convert YUV to RGB during SetData, and make
-   * the original data available through GetData. This is optional,
-   * and not all PlanarYCbCrImages will support it.
-   */
-  virtual void SetDelayedConversion(bool aDelayed) { }
-
-  /**
-   * Grab the original YUV data. This is optional.
-   */
-  virtual const Data* GetData() { return &mData; }
-
-  /**
-   * Make a copy of the YCbCr data into local storage.
-   *
-   * @param aData           Input image data.
-   * @param aYOffset        Pixels to skip between lines in the Y plane.
-   * @param aYSkip          Pixels to skip between pixels in the Y plane.
-   * @param aCbOffset       Pixels to skip between lines in the Cb plane.
-   * @param aCbSkip         Pixels to skip between pixels in the Cb plane.
-   * @param aCrOffset       Pixels to skip between lines in the Cr plane.
-   * @param aCrSkip         Pixels to skip between pixels in the Cr plane.
-   */
-  void CopyData(const Data& aData,
-                PRInt32 aYOffset = 0, PRInt32 aYSkip = 0,
-                PRInt32 aCbOffset = 0, PRInt32 aCbSkip = 0,
-                PRInt32 aCrOffset = 0, PRInt32 aCrSkip = 0);
-
-  /**
-   * Return a buffer to store image data in.
-   * The default implementation returns memory that can
-   * be freed wit delete[]
-   */
-  virtual PRUint8* AllocateBuffer(PRUint32 aSize);
-
-  /**
-   * Return the number of bytes of heap memory used to store this image.
-   */
-  virtual PRUint32 GetDataSize() { return mBufferSize; }
-
-  already_AddRefed<gfxASurface> GetAsSurface();
-
-  virtual gfxIntSize GetSize() { return mSize; }
-
-  void SetOffscreenFormat(gfxImageFormat aFormat) { mOffscreenFormat = aFormat; }
-  gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; }
-
-  // XXX - not easy to protect these sadly.
-  nsAutoArrayPtr<PRUint8> mBuffer;
-  PRUint32 mBufferSize;
-  Data mData;
-  gfxIntSize mSize;
-  gfxImageFormat mOffscreenFormat;
-  nsCountedRef<nsMainThreadSurfaceRef> mSurface;
-  nsRefPtr<BufferRecycleBin> mRecycleBin;
-
-  PlanarYCbCrImage(BufferRecycleBin *aRecycleBin);
-};
-
-/**
- * Currently, the data in a CairoImage surface is treated as being in the
- * device output color space. This class is very simple as all backends
- * have to know about how to deal with drawing a cairo image.
- */
-class THEBES_API CairoImage : public Image {
-public:
-  struct Data {
-    gfxASurface* mSurface;
-    gfxIntSize mSize;
-  };
-
-  /**
-   * This can only be called on the main thread. It may add a reference
-   * to the surface (which will eventually be released on the main thread).
-   * The surface must not be modified after this call!!!
-   */
-  void SetData(const Data& aData)
-  {
-    mSurface = aData.mSurface;
-    mSize = aData.mSize;
-  }
-
-
-  virtual already_AddRefed<gfxASurface> GetAsSurface()
-  {
-    NS_ASSERTION(NS_IsMainThread(), "Must be main thread");
-    nsRefPtr<gfxASurface> surface = mSurface.get();
-    return surface.forget();
-  }
-
-  gfxIntSize GetSize() { return mSize; }
-
-  CairoImage() : Image(NULL, CAIRO_SURFACE) {}
-
-  nsCountedRef<nsMainThreadSurfaceRef> mSurface;
-  gfxIntSize mSize;
-};
-
-#ifdef XP_MACOSX
-class THEBES_API MacIOSurfaceImage : public Image {
-public:
-  struct Data {
-    MacIOSurface* mIOSurface;
-  };
-
-  MacIOSurfaceImage()
-    : Image(NULL, MAC_IO_SURFACE)
-    , mSize(0, 0)
-    , mPluginInstanceOwner(NULL)
-    , mUpdateCallback(NULL)
-    , mDestroyCallback(NULL)
-    {}
-
-  virtual ~MacIOSurfaceImage()
-  {
-    if (mDestroyCallback) {
-      mDestroyCallback(mPluginInstanceOwner);
-    }
-  }
-
- /**
-  * This can only be called on the main thread. It may add a reference
-  * to the surface (which will eventually be released on the main thread).
-  * The surface must not be modified after this call!!!
-  */
-  virtual void SetData(const Data& aData);
-
-  /**
-   * Temporary hacks to force plugin drawing during an empty transaction.
-   * This should not be used for anything else, and will be removed
-   * when async plugin rendering is complete.
-   */
-  typedef void (*UpdateSurfaceCallback)(ImageContainer* aContainer, void* aInstanceOwner);
-  virtual void SetUpdateCallback(UpdateSurfaceCallback aCallback, void* aInstanceOwner)
-  {
-    mUpdateCallback = aCallback;
-    mPluginInstanceOwner = aInstanceOwner;
-  }
-
-  typedef void (*DestroyCallback)(void* aInstanceOwner);
-  virtual void SetDestroyCallback(DestroyCallback aCallback)
-  {
-    mDestroyCallback = aCallback;
-  }
-
-  virtual gfxIntSize GetSize()
-  {
-    return mSize;
-  }
-
-  MacIOSurface* GetIOSurface()
-  {
-    return mIOSurface;
-  }
-
-  void Update(ImageContainer* aContainer);
-
-  virtual already_AddRefed<gfxASurface> GetAsSurface();
-
-private:
-  gfxIntSize mSize;
-  RefPtr<MacIOSurface> mIOSurface;
-  void* mPluginInstanceOwner;
-  UpdateSurfaceCallback mUpdateCallback;
-  DestroyCallback mDestroyCallback;
-};
-#endif
-
-class RemoteBitmapImage : public Image {
-public:
-  RemoteBitmapImage() : Image(NULL, REMOTE_IMAGE_BITMAP) {}
-
-  already_AddRefed<gfxASurface> GetAsSurface();
-
-  gfxIntSize GetSize() { return mSize; }
-
-  unsigned char *mData;
-  int mStride;
-  gfxIntSize mSize;
-  RemoteImageData::Format mFormat;
-};
-
 }
 }
 
 #endif /* GFX_IMAGELAYER_H */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ImageTypes.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GFX_IMAGETYPES_H
+#define GFX_IMAGETYPES_H
+
+namespace mozilla {
+
+enum ImageFormat {
+  /**
+   * The PLANAR_YCBCR format creates a PlanarYCbCrImage. All backends should
+   * support this format, because the Ogg video decoder depends on it.
+   * The maximum image width and height is 16384.
+   */
+  PLANAR_YCBCR,
+
+  /**
+   * The CAIRO_SURFACE format creates a CairoImage. All backends should
+   * support this format, because video rendering sometimes requires it.
+   * 
+   * This format is useful even though a ThebesLayer could be used.
+   * It makes it easy to render a cairo surface when another Image format
+   * could be used. It can also avoid copying the surface data in some
+   * cases.
+   * 
+   * Images in CAIRO_SURFACE format should only be created and
+   * manipulated on the main thread, since the underlying cairo surface
+   * is main-thread-only.
+   */
+  CAIRO_SURFACE,
+
+  /**
+   * The MAC_IO_SURFACE format creates a MacIOSurfaceImage.
+   *
+   * It wraps an IOSurface object and binds it directly to a GL texture.
+   */
+  MAC_IO_SURFACE,
+
+  /**
+   * The GONK_IO_SURFACE format creates a GonkIOSurfaceImage.
+   *
+   * It wraps an GraphicBuffer object and binds it directly to a GL texture.
+   */
+  GONK_IO_SURFACE,
+
+  /**
+   * An bitmap image that can be shared with a remote process.
+   */
+  REMOTE_IMAGE_BITMAP,
+
+  /**
+   * A OpenGL texture that can be shared across threads or processes
+   */
+  SHARED_TEXTURE,
+
+  /**
+   * An DXGI shared surface handle that can be shared with a remote process.
+   */
+  REMOTE_IMAGE_DXGI_TEXTURE
+};
+
+
+enum StereoMode {
+  STEREO_MODE_MONO,
+  STEREO_MODE_LEFT_RIGHT,
+  STEREO_MODE_RIGHT_LEFT,
+  STEREO_MODE_BOTTOM_TOP,
+  STEREO_MODE_TOP_BOTTOM
+};
+
+
+} // namespace
+
+#endif
\ No newline at end of file
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -2,19 +2,19 @@
  * vim: sw=2 ts=8 et :
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/layers/PLayers.h"
 #include "mozilla/layers/ShadowLayers.h"
-#include "mozilla/layers/ImageBridgeChild.h" // TODO: temp
 
 #include "ImageLayers.h"
+#include "ImageContainer.h"
 #include "Layers.h"
 #include "gfxPlatform.h"
 #include "ReadbackLayer.h"
 #include "gfxUtils.h"
 #include "nsPrintfCString.h"
 #include "mozilla/Util.h"
 #include "LayerSorter.h"
 #include "AnimationCommon.h"
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -29,17 +29,19 @@ endif
 
 EXPORTS = \
         BasicLayers.h \
         BasicTiledThebesLayer.h \
         BasicImplData.h \
         GonkIOSurfaceImage.h \
         FrameMetrics.h \
         CompositorParent.h \
+        ImageContainer.h \
         ImageLayers.h \
+        ImageTypes.h \
         Layers.h \
         LayersTypes.h \
         LayerManagerOGLShaders.h \
         LayerManagerOGL.h \
         LayerManagerOGLProgram.h \
         LayerSorter.h \
         ReadbackLayer.h \
         ShadowLayersManager.h \
@@ -53,16 +55,17 @@ CPPSRCS = \
         BasicCanvasLayer.cpp \
         BasicColorLayer.cpp \
         BasicContainerLayer.cpp \
         BasicImageLayer.cpp \
         BasicLayersImpl.cpp \
         BasicThebesLayer.cpp \
         BasicBuffers.cpp \
         BasicTiledThebesLayer.cpp \
+        ImageContainer.cpp \
         Layers.cpp \
         RenderTrace.cpp \
         ReadbackProcessor.cpp \
         ThebesLayerBuffer.cpp \
         CanvasLayerOGL.cpp \
         ColorLayerOGL.cpp \
         ContainerLayerOGL.cpp \
         ImageLayerOGL.cpp \
--- a/gfx/layers/SharedTextureImage.h
+++ b/gfx/layers/SharedTextureImage.h
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_SHAREDTEXTUREIMAGE_H
 #define GFX_SHAREDTEXTUREIMAGE_H
 
-#include "ImageLayers.h"
+#include "ImageContainer.h"
 #include "GLContext.h"
 
 // Split into a separate header from ImageLayers.h due to GLContext.h dependence
 // Implementation remains in ImageLayers.cpp
 
 namespace mozilla {
 
 namespace layers {
--- a/gfx/layers/basic/BasicCanvasLayer.cpp
+++ b/gfx/layers/basic/BasicCanvasLayer.cpp
@@ -2,16 +2,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/layers/PLayersParent.h"
 #include "gfxImageSurface.h"
 #include "GLContext.h"
 #include "gfxUtils.h"
+#include "gfxPlatform.h"
 
 #include "BasicLayersImpl.h"
 #include "nsXULAppAPI.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
--- a/gfx/layers/basic/BasicImageLayer.cpp
+++ b/gfx/layers/basic/BasicImageLayer.cpp
@@ -276,28 +276,28 @@ BasicShadowableImageLayer::Paint(gfxCont
     return;
   }
 
   if (aMaskLayer) {
     static_cast<BasicImplData*>(aMaskLayer->ImplData())
       ->Paint(aContext, nullptr);
   }
 
-  if (image->GetFormat() == Image::SHARED_TEXTURE &&
+  if (image->GetFormat() == ImageFormat::SHARED_TEXTURE &&
       BasicManager()->GetParentBackendType() == mozilla::layers::LAYERS_OPENGL) {
     SharedTextureImage *sharedImage = static_cast<SharedTextureImage*>(image);
     const SharedTextureImage::Data *data = sharedImage->GetData();
 
     SharedTextureDescriptor texture(data->mShareType, data->mHandle, data->mSize, data->mInverted);
     SurfaceDescriptor descriptor(texture);
     BasicManager()->PaintedImage(BasicManager()->Hold(this), descriptor);
     return;
   }
 
-  if (image->GetFormat() == Image::PLANAR_YCBCR && BasicManager()->IsCompositingCheap()) {
+  if (image->GetFormat() == ImageFormat::PLANAR_YCBCR && BasicManager()->IsCompositingCheap()) {
     PlanarYCbCrImage *YCbCrImage = static_cast<PlanarYCbCrImage*>(image);
     const PlanarYCbCrImage::Data *data = YCbCrImage->GetData();
     NS_ASSERTION(data, "Must be able to retrieve yuv data from image!");
 
     if (mSize != data->mYSize || mCbCrSize != data->mCbCrSize || !IsSurfaceDescriptorValid(mBackBufferY)) {
       DestroyBackBuffer();
       mSize = data->mYSize;
       mCbCrSize = data->mCbCrSize;
--- a/gfx/layers/basic/BasicImages.cpp
+++ b/gfx/layers/basic/BasicImages.cpp
@@ -52,27 +52,27 @@ private:
   nsAutoArrayPtr<PRUint8> mDecodedBuffer;
 };
 
 class BasicImageFactory : public ImageFactory
 {
 public:
   BasicImageFactory() {}
 
-  virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
+  virtual already_AddRefed<Image> CreateImage(const ImageFormat* aFormats,
                                               PRUint32 aNumFormats,
                                               const gfxIntSize &aScaleHint,
                                               BufferRecycleBin *aRecycleBin)
   {
     if (!aNumFormats) {
       return nullptr;
     }
 
     nsRefPtr<Image> image;
-    if (aFormats[0] == Image::PLANAR_YCBCR) {
+    if (aFormats[0] == ImageFormat::PLANAR_YCBCR) {
       image = new BasicPlanarYCbCrImage(aScaleHint, gfxPlatform::GetPlatform()->GetOffscreenFormat(), aRecycleBin);
       return image.forget();
     }
 
     return ImageFactory::CreateImage(aFormats, aNumFormats, aScaleHint, aRecycleBin);
   }
 };
 
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -5,16 +5,17 @@
 
 #include "mozilla/layers/PLayerChild.h"
 #include "mozilla/layers/PLayersChild.h"
 #include "mozilla/layers/PLayersParent.h"
 
 #include "gfxSharedImageSurface.h"
 #include "gfxImageSurface.h"
 #include "gfxUtils.h"
+#include "gfxPlatform.h"
 #include "nsXULAppAPI.h"
 #include "RenderTrace.h"
 #include "sampler.h"
 
 #define PIXMAN_DONT_DEFINE_STDINT
 #include "pixman.h"
 
 #include "BasicTiledThebesLayer.h"
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -22,16 +22,17 @@ namespace layers {
 
 class BasicShadowableLayer;
 class ShadowThebesLayer;
 class ShadowContainerLayer;
 class ShadowImageLayer;
 class ShadowCanvasLayer;
 class ShadowColorLayer;
 class ReadbackProcessor;
+class ImageFactory;
 
 /**
  * This is a cairo/Thebes-only, main-thread-only implementation of layers.
  * 
  * In each transaction, the client sets up the layer tree and then during
  * the drawing phase, each ThebesLayer is painted directly into the target
  * context (with appropriate clipping and Push/PopGroups performed
  * between layers).
--- a/gfx/layers/basic/BasicTiledThebesLayer.cpp
+++ b/gfx/layers/basic/BasicTiledThebesLayer.cpp
@@ -1,16 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/layers/PLayersChild.h"
 #include "BasicTiledThebesLayer.h"
 #include "gfxImageSurface.h"
 #include "sampler.h"
+#include "gfxPlatform.h"
 
 #ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
 #include "cairo.h"
 #include <sstream>
 using mozilla::layers::Layer;
 static void DrawDebugOverlay(gfxImageSurface* imgSurf, int x, int y)
 {
   gfxContext c(imgSurf);
--- a/gfx/layers/d3d10/ImageLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ImageLayerD3D10.cpp
@@ -91,39 +91,39 @@ ImageLayerD3D10::GetLayer()
  * If successful, aHasAlpha will be true iff the resulting texture 
  * has an alpha component.
  */
 ID3D10ShaderResourceView*
 ImageLayerD3D10::GetImageSRView(Image* aImage, bool& aHasAlpha, IDXGIKeyedMutex **aMutex)
 {
   NS_ASSERTION(aImage, "Null image.");
 
-  if (aImage->GetFormat() == Image::REMOTE_IMAGE_BITMAP) {
+  if (aImage->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP) {
     RemoteBitmapImage *remoteImage =
       static_cast<RemoteBitmapImage*>(aImage);
 
     if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D10)) {
       nsAutoPtr<TextureD3D10BackendData> dat(new TextureD3D10BackendData());
       dat->mTexture = DataToTexture(device(), remoteImage->mData, remoteImage->mStride, remoteImage->mSize);
 
       if (dat->mTexture) {
         device()->CreateShaderResourceView(dat->mTexture, NULL, getter_AddRefs(dat->mSRView));
         aImage->SetBackendData(mozilla::layers::LAYERS_D3D10, dat.forget());
       }
     }
 
     aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
-  } else if (aImage->GetFormat() == Image::REMOTE_IMAGE_DXGI_TEXTURE) {
+  } else if (aImage->GetFormat() == ImageFormat::REMOTE_IMAGE_DXGI_TEXTURE) {
     RemoteDXGITextureImage *remoteImage =
       static_cast<RemoteDXGITextureImage*>(aImage);
 
     remoteImage->GetD3D10TextureBackendData(device());
 
     aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
-  } else if (aImage->GetFormat() == Image::CAIRO_SURFACE) {
+  } else if (aImage->GetFormat() == ImageFormat::CAIRO_SURFACE) {
     CairoImage *cairoImage =
       static_cast<CairoImage*>(aImage);
 
     if (!cairoImage->mSurface) {
       return nullptr;
     }
 
     if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D10)) {
@@ -183,20 +183,20 @@ ImageLayerD3D10::RenderLayer()
 
   gfxIntSize size = mScaleMode == SCALE_NONE ? image->GetSize() : mScaleToSize;
 
   SetEffectTransformAndOpacity();
 
   ID3D10EffectTechnique *technique;
   nsRefPtr<IDXGIKeyedMutex> keyedMutex;
 
-  if (image->GetFormat() == Image::CAIRO_SURFACE || image->GetFormat() == Image::REMOTE_IMAGE_BITMAP ||
-      image->GetFormat() == Image::REMOTE_IMAGE_DXGI_TEXTURE)
+  if (image->GetFormat() == ImageFormat::CAIRO_SURFACE || image->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP ||
+      image->GetFormat() == ImageFormat::REMOTE_IMAGE_DXGI_TEXTURE)
   {
-    NS_ASSERTION(image->GetFormat() != Image::CAIRO_SURFACE ||
+    NS_ASSERTION(image->GetFormat() != ImageFormat::CAIRO_SURFACE ||
                  !static_cast<CairoImage*>(image)->mSurface ||
                  static_cast<CairoImage*>(image)->mSurface->GetContentType() != gfxASurface::CONTENT_ALPHA,
                  "Image layer has alpha image");
     bool hasAlpha = false;
 
     nsRefPtr<ID3D10ShaderResourceView> srView = GetImageSRView(image, hasAlpha, getter_AddRefs(keyedMutex));
     if (!srView) {
       return;
@@ -215,17 +215,17 @@ ImageLayerD3D10::RenderLayer()
 
     effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
       ShaderConstantRectD3D10(
         (float)0,
         (float)0,
         (float)size.width,
         (float)size.height)
       );
-  } else if (image->GetFormat() == Image::PLANAR_YCBCR) {
+  } else if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) {
     PlanarYCbCrImage *yuvImage =
       static_cast<PlanarYCbCrImage*>(image);
 
     if (!yuvImage->mBufferSize) {
       return;
     }
 
     if (!yuvImage->GetBackendData(mozilla::layers::LAYERS_D3D10)) {
@@ -301,17 +301,17 @@ ImageLayerD3D10::RenderLayer()
       ShaderConstantRectD3D10(
         (float)yuvImage->mData.mPicX / yuvImage->mData.mYSize.width,
         (float)yuvImage->mData.mPicY / yuvImage->mData.mYSize.height,
         (float)yuvImage->mData.mPicSize.width / yuvImage->mData.mYSize.width,
         (float)yuvImage->mData.mPicSize.height / yuvImage->mData.mYSize.height)
        );
   }
   
-  bool resetTexCoords = image->GetFormat() == Image::PLANAR_YCBCR;
+  bool resetTexCoords = image->GetFormat() == ImageFormat::PLANAR_YCBCR;
   image = nullptr;
   autoLock.Unlock();
 
   technique->GetPassByIndex(0)->Apply(0);
   device()->Draw(4, 0);
 
   if (keyedMutex) {
     keyedMutex->ReleaseSync(0);
@@ -379,17 +379,17 @@ ImageLayerD3D10::GetAsTexture(gfxIntSize
 
   AutoLockImage autoLock(GetContainer());
 
   Image *image = autoLock.GetImage();
   if (!image) {
     return nullptr;
   }
 
-  if (image->GetFormat() != Image::CAIRO_SURFACE) {
+  if (image->GetFormat() != ImageFormat::CAIRO_SURFACE) {
     return nullptr;
   }
   
   *aSize = image->GetSize();
   bool dontCare;
   nsRefPtr<ID3D10ShaderResourceView> result = GetImageSRView(image, dontCare);
   return result.forget();
 }
--- a/gfx/layers/d3d10/ImageLayerD3D10.h
+++ b/gfx/layers/d3d10/ImageLayerD3D10.h
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_IMAGELAYERD3D10_H
 #define GFX_IMAGELAYERD3D10_H
 
 #include "LayerManagerD3D10.h"
 #include "ImageLayers.h"
+#include "ImageContainer.h"
 #include "yuv_convert.h"
 
 namespace mozilla {
 namespace layers {
 
 class THEBES_API ImageLayerD3D10 : public ImageLayer,
                                    public LayerD3D10
 {
--- a/gfx/layers/d3d9/ImageLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -295,30 +295,30 @@ ImageLayerD3D9::GetLayer()
   * If successful, aHasAlpha will be set to true if the texture has an
   * alpha component, false otherwise.
   */
 IDirect3DTexture9*
 ImageLayerD3D9::GetTexture(Image *aImage, bool& aHasAlpha)
 {
   NS_ASSERTION(aImage, "Null image.");
 
-  if (aImage->GetFormat() == Image::REMOTE_IMAGE_BITMAP) {
+  if (aImage->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP) {
     RemoteBitmapImage *remoteImage =
       static_cast<RemoteBitmapImage*>(aImage);
       
     if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D9)) {
       nsAutoPtr<TextureD3D9BackendData> dat(new TextureD3D9BackendData());
       dat->mTexture = DataToTexture(device(), remoteImage->mData, remoteImage->mStride, remoteImage->mSize, D3DFMT_A8R8G8B8);
       if (dat->mTexture) {
         aImage->SetBackendData(mozilla::layers::LAYERS_D3D9, dat.forget());
       }
     }
 
     aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
-  } else if (aImage->GetFormat() == Image::CAIRO_SURFACE) {
+  } else if (aImage->GetFormat() == ImageFormat::CAIRO_SURFACE) {
     CairoImage *cairoImage =
       static_cast<CairoImage*>(aImage);
 
     if (!cairoImage->mSurface) {
       return nullptr;
     }
 
     if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D9)) {
@@ -365,20 +365,20 @@ ImageLayerD3D9::RenderLayer()
   if (!image) {
     return;
   }
 
   SetShaderTransformAndOpacity();
 
   gfxIntSize size = mScaleMode == SCALE_NONE ? image->GetSize() : mScaleToSize;
 
-  if (image->GetFormat() == Image::CAIRO_SURFACE ||
-      image->GetFormat() == Image::REMOTE_IMAGE_BITMAP)
+  if (image->GetFormat() == ImageFormat::CAIRO_SURFACE ||
+      image->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP)
   {
-    NS_ASSERTION(image->GetFormat() != Image::CAIRO_SURFACE ||
+    NS_ASSERTION(image->GetFormat() != ImageFormat::CAIRO_SURFACE ||
                  !static_cast<CairoImage*>(image)->mSurface ||
                  static_cast<CairoImage*>(image)->mSurface->GetContentType() != gfxASurface::CONTENT_ALPHA,
                  "Image layer has alpha image");
 
     bool hasAlpha = false;
     nsRefPtr<IDirect3DTexture9> texture = GetTexture(image, hasAlpha);
 
     device()->SetVertexShaderConstantF(CBvLayerQuad,
@@ -517,18 +517,18 @@ ImageLayerD3D9::GetAsTexture(gfxIntSize*
   AutoLockImage autoLock(GetContainer());
 
   Image *image = autoLock.GetImage();
 
   if (!image) {
     return nullptr;
   }
 
-  if (image->GetFormat() != Image::CAIRO_SURFACE &&
-      image->GetFormat() != Image::REMOTE_IMAGE_BITMAP) {
+  if (image->GetFormat() != ImageFormat::CAIRO_SURFACE &&
+      image->GetFormat() != ImageFormat::REMOTE_IMAGE_BITMAP) {
     return nullptr;
   }
   
   bool dontCare;
   *aSize = image->GetSize();
   nsRefPtr<IDirect3DTexture9> result = GetTexture(image, dontCare);
   return result.forget();
 }
--- a/gfx/layers/d3d9/ImageLayerD3D9.h
+++ b/gfx/layers/d3d9/ImageLayerD3D9.h
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_IMAGELAYERD3D9_H
 #define GFX_IMAGELAYERD3D9_H
 
 #include "LayerManagerD3D9.h"
 #include "ImageLayers.h"
+#include "ImageContainer.h"
 #include "yuv_convert.h"
 
 namespace mozilla {
 namespace layers {
 
 class ShadowBufferD3D9;
 
 class THEBES_API ImageLayerD3D9 : public ImageLayer,
--- a/gfx/layers/ipc/ImageContainerChild.cpp
+++ b/gfx/layers/ipc/ImageContainerChild.cpp
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "ImageContainerChild.h"
 #include "gfxSharedImageSurface.h"
 #include "ShadowLayers.h"
 #include "mozilla/layers/PLayers.h"
 #include "mozilla/layers/SharedImageUtils.h"
-#include "ImageLayers.h"
+#include "ImageContainer.h"
 #include "GonkIOSurfaceImage.h"
 
 namespace mozilla {
 namespace layers {
 
 /*
  * - POOL_MAX_SHARED_IMAGES is the maximum number number of shared images to
  * store in the ImageContainerChild's pool.
@@ -116,17 +116,17 @@ void ImageContainerChild::DestroySharedI
                     "Should be in ImageBridgeChild thread.");
 
   --mActiveImageCount;
   DeallocSharedImageData(this, aImage);
 }
 
 bool ImageContainerChild::CopyDataIntoSharedImage(Image* src, SharedImage* dest)
 {
-  if ((src->GetFormat() == Image::PLANAR_YCBCR) && 
+  if ((src->GetFormat() == ImageFormat::PLANAR_YCBCR) && 
       (dest->type() == SharedImage::TYUVImage)) {
     PlanarYCbCrImage *YCbCrImage = static_cast<PlanarYCbCrImage*>(src);
     const PlanarYCbCrImage::Data *data = YCbCrImage->GetData();
     NS_ASSERTION(data, "Must be able to retrieve yuv data from image!");
     YUVImage& yuv = dest->get_YUVImage();
 
     nsRefPtr<gfxSharedImageSurface> surfY =
       gfxSharedImageSurface::Open(yuv.Ydata());
@@ -156,17 +156,17 @@ bool ImageContainerChild::CopyDataIntoSh
 
 SharedImage* ImageContainerChild::CreateSharedImageFromData(Image* image)
 {
   NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                   "Should be in ImageBridgeChild thread.");
   
   ++mActiveImageCount;
 
-  if (image->GetFormat() == Image::PLANAR_YCBCR ) {
+  if (image->GetFormat() == ImageFormat::PLANAR_YCBCR ) {
     PlanarYCbCrImage *YCbCrImage = static_cast<PlanarYCbCrImage*>(image);
     const PlanarYCbCrImage::Data *data = YCbCrImage->GetData();
     NS_ASSERTION(data, "Must be able to retrieve yuv data from image!");
     
     nsRefPtr<gfxSharedImageSurface> tempBufferY;
     nsRefPtr<gfxSharedImageSurface> tempBufferU;
     nsRefPtr<gfxSharedImageSurface> tempBufferV;
     
@@ -197,17 +197,17 @@ SharedImage* ImageContainerChild::Create
               YUVImage(tempBufferY->GetShmem(),
                        tempBufferU->GetShmem(),
                        tempBufferV->GetShmem(),
                        data->GetPictureRect()));
     NS_ABORT_IF_FALSE(result->type() == SharedImage::TYUVImage,
                       "SharedImage type not set correctly");
     return result;
 #ifdef MOZ_WIDGET_GONK
-  } else if (image->GetFormat() == Image::GONK_IO_SURFACE) {
+  } else if (image->GetFormat() == ImageFormat::GONK_IO_SURFACE) {
     GonkIOSurfaceImage* gonkImage = static_cast<GonkIOSurfaceImage*>(image);
     SharedImage* result = new SharedImage(gonkImage->GetSurfaceDescriptor());
     return result;
 #endif
   } else {
     NS_RUNTIMEABORT("TODO: Only YUVImage is supported here right now.");
   }
   return nullptr;
@@ -231,17 +231,17 @@ bool ImageContainerChild::AddSharedImage
   return false; // TODO accept more image formats in the pool
 }
 
 static bool
 SharedImageCompatibleWith(SharedImage* aSharedImage, Image* aImage)
 {
   // TODO accept more image formats
   switch (aImage->GetFormat()) {
-  case Image::PLANAR_YCBCR: {
+  case ImageFormat::PLANAR_YCBCR: {
     if (aSharedImage->type() != SharedImage::TYUVImage) {
       return false;
     }
     const PlanarYCbCrImage::Data* data =
       static_cast<PlanarYCbCrImage*>(aImage)->GetData();
     const YUVImage& yuv = aSharedImage->get_YUVImage();
 
     nsRefPtr<gfxSharedImageSurface> surfY =
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
@@ -10,16 +10,17 @@
 #include "mozilla/layers/PLayersChild.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "mozilla/unused.h"
 #include "nsXULAppAPI.h"
 
 #include "ShadowLayerUtilsGralloc.h"
 
 #include "gfxImageSurface.h"
+#include "gfxPlatform.h"
 
 #include "sampler.h"
 
 using namespace android;
 using namespace base;
 using namespace mozilla::layers;
 
 namespace IPC {
--- a/gfx/layers/ipc/ShadowLayersParent.cpp
+++ b/gfx/layers/ipc/ShadowLayersParent.cpp
@@ -14,16 +14,17 @@
 #include "mozilla/layout/RenderFrameParent.h"
 #include "mozilla/unused.h"
 #include "RenderTrace.h"
 #include "ShadowLayerParent.h"
 #include "ShadowLayersParent.h"
 #include "ShadowLayers.h"
 #include "ShadowLayerUtils.h"
 #include "TiledLayerBuffer.h"
+#include "gfxPlatform.h" 
 
 typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
 
 using mozilla::layout::RenderFrameParent;
 
 namespace mozilla {
 namespace layers {
 
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -11,16 +11,20 @@
 
 #include "CanvasLayerOGL.h"
 
 #include "gfxImageSurface.h"
 #include "gfxContext.h"
 #include "GLContextProvider.h"
 #include "gfxPlatform.h"
 
+#ifdef XP_MACOSX
+#include "mozilla/gfx/MacIOSurface.h"
+#endif
+
 #ifdef XP_WIN
 #include "gfxWindowsSurface.h"
 #include "WGLLibrary.h"
 #endif
 
 #ifdef XP_MACOSX
 #include <OpenGL/OpenGL.h>
 #endif
--- a/gfx/layers/opengl/CanvasLayerOGL.h
+++ b/gfx/layers/opengl/CanvasLayerOGL.h
@@ -61,19 +61,20 @@ protected:
   bool mGLBufferIsPremultiplied;
   bool mNeedsYFlip;
 #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
   GLXPixmap mPixmap;
 #endif
 
   nsRefPtr<gfxImageSurface> mCachedTempSurface;
   gfxIntSize mCachedSize;
-  gfxImageFormat mCachedFormat;
+  gfxASurface::gfxImageFormat mCachedFormat;
 
-  gfxImageSurface* GetTempSurface(const gfxIntSize& aSize, const gfxImageFormat aFormat)
+  gfxImageSurface* GetTempSurface(const gfxIntSize& aSize,
+                                  const gfxASurface::gfxImageFormat aFormat)
   {
     if (!mCachedTempSurface ||
         aSize.width != mCachedSize.width ||
         aSize.height != mCachedSize.height ||
         aFormat != mCachedFormat)
     {
       mCachedTempSurface = new gfxImageSurface(aSize, aFormat);
       mCachedSize = aSize;
--- a/gfx/layers/opengl/ImageLayerOGL.cpp
+++ b/gfx/layers/opengl/ImageLayerOGL.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gfxSharedImageSurface.h"
 #include "mozilla/layers/ImageContainerParent.h"
 
+#include "ImageContainer.h" // for PlanarYCBCRImage
 #include "ipc/AutoOpenSurface.h"
 #include "ImageLayerOGL.h"
 #include "gfxImageSurface.h"
 #include "gfxUtils.h"
 #include "yuv_convert.h"
 #include "GLContextProvider.h"
 #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
 # include "GLXLibrary.h"
@@ -238,22 +239,22 @@ ImageLayerOGL::RenderLayer(int,
 
   AutoLockImage autoLock(container);
 
   Image *image = autoLock.GetImage();
   if (!image) {
     return;
   }
 
-  NS_ASSERTION(image->GetFormat() != Image::REMOTE_IMAGE_BITMAP,
+  NS_ASSERTION(image->GetFormat() != ImageFormat::REMOTE_IMAGE_BITMAP,
     "Remote images aren't handled yet in OGL layers!");
   NS_ASSERTION(mScaleMode == SCALE_NONE,
     "Scale modes other than none not handled yet in OGL layers!");
 
-  if (image->GetFormat() == Image::PLANAR_YCBCR) {
+  if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) {
     PlanarYCbCrImage *yuvImage =
       static_cast<PlanarYCbCrImage*>(image);
 
     if (!yuvImage->mBufferSize) {
       return;
     }
 
     PlanarYCbCrOGLBackendData *data =
@@ -303,17 +304,17 @@ ImageLayerOGL::RenderLayer(int,
     mOGLManager->BindAndDrawQuadWithTextureRect(program,
                                                 yuvImage->mData.GetPictureRect(),
                                                 nsIntSize(yuvImage->mData.mYSize.width,
                                                           yuvImage->mData.mYSize.height));
 
     // We shouldn't need to do this, but do it anyway just in case
     // someone else forgets.
     gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
-  } else if (image->GetFormat() == Image::CAIRO_SURFACE) {
+  } else if (image->GetFormat() == ImageFormat::CAIRO_SURFACE) {
     CairoImage *cairoImage =
       static_cast<CairoImage*>(image);
 
     if (!cairoImage->mSurface) {
       return;
     }
 
     NS_ASSERTION(cairoImage->mSurface->GetContentType() != gfxASurface::CONTENT_ALPHA,
@@ -379,17 +380,17 @@ ImageLayerOGL::RenderLayer(int,
 
 #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
     if (cairoImage->mSurface && pixmap) {
         sGLXLibrary.ReleaseTexImage(pixmap);
         sGLXLibrary.DestroyPixmap(pixmap);
     }
 #endif
 #ifdef XP_MACOSX
-  } else if (image->GetFormat() == Image::MAC_IO_SURFACE) {
+  } else if (image->GetFormat() == ImageFormat::MAC_IO_SURFACE) {
      MacIOSurfaceImage *ioImage =
        static_cast<MacIOSurfaceImage*>(image);
 
      if (!mOGLManager->GetThebesLayerCallback()) {
        // If its an empty transaction we still need to update
        // the plugin IO Surface and make sure we grab the
        // new image
        ioImage->Update(GetContainer());
@@ -435,17 +436,17 @@ ImageLayerOGL::RenderLayer(int,
      program->SetRenderOffset(aOffset);
      program->SetTextureUnit(0);
      program->LoadMask(GetMaskLayer());
 
      mOGLManager->BindAndDrawQuad(program);
      gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
 #endif
 #ifdef MOZ_WIDGET_GONK
-  } else if (image->GetFormat() == Image::GONK_IO_SURFACE) {
+  } else if (image->GetFormat() == ImageFormat::GONK_IO_SURFACE) {
 
     GonkIOSurfaceImage *ioImage = static_cast<GonkIOSurfaceImage*>(image);
     if (!ioImage) {
       return;
     }
 
     gl()->MakeCurrent();
     gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
@@ -630,17 +631,17 @@ ImageLayerOGL::LoadAsTexture(GLuint aTex
 
   AutoLockImage autoLock(GetContainer());
 
   Image *image = autoLock.GetImage();
   if (!image) {
     return false;
   }
 
-  if (image->GetFormat() != Image::CAIRO_SURFACE) {
+  if (image->GetFormat() != ImageFormat::CAIRO_SURFACE) {
     return false;
   }
 
   CairoImage* cairoImage = static_cast<CairoImage*>(image);
 
   if (!cairoImage->mSurface) {
     return false;
   }
--- a/gfx/layers/opengl/ImageLayerOGL.h
+++ b/gfx/layers/opengl/ImageLayerOGL.h
@@ -6,22 +6,26 @@
 #ifndef GFX_IMAGELAYEROGL_H
 #define GFX_IMAGELAYEROGL_H
 
 #include "mozilla/layers/PLayers.h"
 #include "mozilla/layers/ShadowLayers.h"
 
 #include "LayerManagerOGL.h"
 #include "ImageLayers.h"
+#include "ImageContainer.h"
 #include "yuv_convert.h"
 #include "mozilla/Mutex.h"
 
 namespace mozilla {
 namespace layers {
 
+class CairoImage;
+class PlanarYCbCrImage;
+
 /**
  * This class wraps a GL texture. It includes a GLContext reference
  * so we can use to free the texture when destroyed. The implementation
  * makes sure to always free the texture on the main thread, even if the
  * destructor runs on another thread.
  *
  * We ensure that the GLContext reference is only addrefed and released
  * on the main thread, although it uses threadsafe recounting so we don't
--- a/gfx/thebes/gfxUtils.h
+++ b/gfx/thebes/gfxUtils.h
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_UTILS_H
 #define GFX_UTILS_H
 
 #include "gfxTypes.h"
 #include "gfxPattern.h"
 #include "gfxImageSurface.h"
-#include "ImageLayers.h"
+#include "ImageContainer.h"
 #include "mozilla/gfx/2D.h"
 #include "imgIContainer.h"
 
 class gfxDrawable;
 class nsIntRegion;
 struct nsIntRect;
 
 class THEBES_API gfxUtils {
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -12,17 +12,18 @@
 #include "RasterImage.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsAutoPtr.h"
 #include "nsStringStream.h"
 #include "prmem.h"
 #include "prenv.h"
 #include "ImageLogging.h"
-#include "ImageLayers.h"
+#include "ImageContainer.h"
+#include "Layers.h"
 
 #include "nsPNGDecoder.h"
 #include "nsGIFDecoder2.h"
 #include "nsJPEGDecoder.h"
 #include "nsBMPDecoder.h"
 #include "nsICODecoder.h"
 #include "nsIconDecoder.h"
 
@@ -877,17 +878,17 @@ RasterImage::GetImageContainer(ImageCont
 
   cairoData.mSurface = imageSurface;
   GetWidth(&cairoData.mSize.width);
   GetHeight(&cairoData.mSize.height);
 
   mImageContainer = LayerManager::CreateImageContainer();
   
   // Now create a CairoImage to display the surface.
-  layers::Image::Format cairoFormat = layers::Image::CAIRO_SURFACE;
+  ImageFormat cairoFormat = ImageFormat::CAIRO_SURFACE;
   nsRefPtr<layers::Image> image = mImageContainer->CreateImage(&cairoFormat, 1);
   NS_ASSERTION(image, "Failed to create Image");
 
   NS_ASSERTION(image->GetFormat() == cairoFormat, "Wrong format");
   static_cast<CairoImage*>(image.get())->SetData(cairoData);
   mImageContainer->SetCurrentImageInTransaction(image);
 
   *_retval = mImageContainer;
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -3183,17 +3183,17 @@ ContainerState::SetupMaskLayer(Layer *aL
 
     // paint the clipping rects with alpha to create the mask
     context->SetColor(gfxRGBA(1, 1, 1, 1));
     aClip.DrawRoundedRectsTo(context, A2D, 0, aRoundedRectClipCount);
 
     // build the image and container
     container = aLayer->Manager()->CreateImageContainer();
     NS_ASSERTION(container, "Could not create image container for mask layer.");
-    static const Image::Format format = Image::CAIRO_SURFACE;
+    static const ImageFormat format = ImageFormat::CAIRO_SURFACE;
     nsRefPtr<Image> image = container->CreateImage(&format, 1);
     NS_ASSERTION(image, "Could not create image container for mask layer.");
     CairoImage::Data data;
     data.mSurface = surface;
     data.mSize = surfaceSize;
     static_cast<CairoImage*>(image.get())->SetData(data);
     container->SetCurrentImageInTransaction(image);
 
--- a/layout/base/MaskLayerImageCache.cpp
+++ b/layout/base/MaskLayerImageCache.cpp
@@ -1,19 +1,28 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MaskLayerImageCache.h"
+#include "ImageContainer.h"
 
 using namespace mozilla::layers;
 
 namespace mozilla {
 
+MaskLayerImageCache::MaskLayerImageCache()
+{
+  mMaskImageContainers.Init();
+}
+MaskLayerImageCache::~MaskLayerImageCache()
+{}
+
+
 /* static */ PLDHashOperator
 MaskLayerImageCache::SweepFunc(MaskLayerImageEntry* aEntry,
                                void* aUserArg)
 {
   const MaskLayerImageCache::MaskLayerImageKey* key = aEntry->mKey;
 
   if (key->mLayerCount == 0) {
     return PL_DHASH_REMOVE;
--- a/layout/base/MaskLayerImageCache.h
+++ b/layout/base/MaskLayerImageCache.h
@@ -3,20 +3,23 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MASKLAYERIMAGECACHE_H_
 #define MASKLAYERIMAGECACHE_H_
 
 #include "FrameLayerBuilder.h"
 #include "nsPresContext.h"
-#include "ImageLayers.h"
 
 namespace mozilla {
 
+namespace layers {
+class ImageContainer;
+}
+
 /**
  * Keeps a record of image containers for mask layers, containers are mapped
  * from the rounded rects used to create them.
  * The cache stores MaskLayerImageEntries indexed by MaskLayerImageKeys.
  * Each MaskLayerImageEntry owns a heap-allocated MaskLayerImageKey
  * (heap-allocated so that a mask layer's userdata can keep a pointer to the
  * key for its image, in spite of the hashtable moving its entries around).
  * The key consists of the rounded rects used to create the mask,
@@ -24,20 +27,18 @@ namespace mozilla {
  * of the number of layers currently using this ImageContainer.
  * When the key's layer count is zero, the cache
  * may remove the entry, which deletes the key object.
  */
 class MaskLayerImageCache
 {
   typedef mozilla::layers::ImageContainer ImageContainer;
 public:
-  MaskLayerImageCache()
-  {
-    mMaskImageContainers.Init();
-  }
+  MaskLayerImageCache();
+  ~MaskLayerImageCache();
 
   /**
    * Representation of a rounded rectangle in device pixel coordinates, in
    * contrast to FrameLayerBuilder::Clip::RoundedRect, which uses app units.
    * In particular, our internal representation uses a gfxRect, rather than
    * an nsRect, so this class is easier to use with transforms.
    */
   struct PixelRoundedRect
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -41,16 +41,17 @@
 #include "nsCSSProps.h"
 #include "nsContentUtils.h"
 #include "nsSVGEffects.h"
 #include "nsSVGIntegrationUtils.h"
 #include "gfxDrawable.h"
 #include "sampler.h"
 #include "nsCSSRenderingBorders.h"
 #include "mozilla/css/ImageLoader.h"
+#include "ImageContainer.h"
 
 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
 // to paint inline backgrounds.
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -36,16 +36,18 @@
 #include "nsViewportFrame.h"
 #include "nsSVGEffects.h"
 #include "nsSVGElement.h"
 #include "nsSVGClipPathFrame.h"
 #include "sampler.h"
 #include "nsAnimationManager.h"
 #include "nsTransitionManager.h"
 #include "nsIViewManager.h"
+#include "ImageLayers.h"
+#include "ImageContainer.h"
 
 #include "mozilla/StandardInteger.h"
 
 using namespace mozilla;
 using namespace mozilla::layers;
 typedef FrameMetrics::ViewID ViewID;
 
 static void AddTransformFunctions(nsCSSValueList* aList,
@@ -1378,16 +1380,23 @@ nsDisplayBackground::nsDisplayBackground
     nsStyleContext* bgSC;
     bool hasBG = nsCSSRendering::FindBackground(presContext, mFrame, &bgSC);
     if (hasBG && bgSC->GetStyleBackground()->HasFixedBackground()) {
       aBuilder->SetHasFixedItems();
     }
   }
 }
 
+nsDisplayBackground::~nsDisplayBackground()
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+  MOZ_COUNT_DTOR(nsDisplayBackground);
+#endif
+}
+
 // Helper for RoundedRectIntersectsRect.
 static bool
 CheckCorner(nscoord aXOffset, nscoord aYOffset,
             nscoord aXRadius, nscoord aYRadius)
 {
   NS_ABORT_IF_FALSE(aXOffset > 0 && aYOffset > 0,
                     "must not pass nonpositives to CheckCorner");
   NS_ABORT_IF_FALSE(aXRadius >= 0 && aYRadius >= 0,
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -18,30 +18,36 @@
 #include "nsPoint.h"
 #include "nsRect.h"
 #include "nsISelection.h"
 #include "nsCaret.h"
 #include "plarena.h"
 #include "nsRegion.h"
 #include "FrameLayerBuilder.h"
 #include "nsThemeConstants.h"
-#include "ImageLayers.h"
 #include "nsLayoutUtils.h"
 
 #include "mozilla/StandardInteger.h"
 
 #include <stdlib.h>
 
 class nsIPresShell;
 class nsIContent;
 class nsRenderingContext;
 class nsDeviceContext;
 class nsDisplayTableItem;
 class nsDisplayItem;
 
+namespace mozilla {
+namespace layers {
+class ImageLayer;
+class ImageContainer;
+} //namepsace
+} //namepsace
+
 /*
  * An nsIFrame can have many different visual parts. For example an image frame
  * can have a background, border, and outline, the image itself, and a
  * translucent selection overlay. In general these parts can be drawn at
  * discontiguous z-levels; see CSS2.1 appendix E:
  * http://www.w3.org/TR/CSS21/zindex.html
  * 
  * We construct a display list for a frame tree that contains one item
@@ -1587,21 +1593,17 @@ private:
 };
 
 /**
  * The standard display item to paint the CSS background of a frame.
  */
 class nsDisplayBackground : public nsDisplayItem {
 public:
   nsDisplayBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
-#ifdef NS_BUILD_REFCNT_LOGGING
-  virtual ~nsDisplayBackground() {
-    MOZ_COUNT_DTOR(nsDisplayBackground);
-  }
-#endif
+  virtual ~nsDisplayBackground();
 
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerParameters& aParameters);
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerParameters& aContainerParameters);
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -61,16 +61,17 @@
 #include "nsContentPolicyUtils.h"
 #include "nsEventStates.h"
 #include "nsError.h"
 #include "nsBidiUtils.h"
 #include "nsBidiPresUtils.h"
 
 #include "gfxRect.h"
 #include "ImageLayers.h"
+#include "ImageContainer.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/Util.h" // for DebugOnly
 
 using namespace mozilla;
 
 // sizes (pixels) for image icon, padding and border frame
 #define ICON_SIZE        (16)
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -83,16 +83,17 @@
 #include "nsPluginNativeWindow.h"
 #include "nsIPluginDocument.h"
 #include "FrameLayerBuilder.h"
 
 #include "nsThreadUtils.h"
 
 #include "gfxContext.h"
 #include "gfxPlatform.h"
+#include "ImageLayers.h"
 
 #ifdef XP_WIN
 #include "gfxWindowsNativeDrawing.h"
 #include "gfxWindowsSurface.h"
 #endif
 
 #include "gfxImageSurface.h"
 #include "gfxUtils.h"
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -23,16 +23,18 @@
 #include "nsContentCreatorFunctions.h"
 #include "nsBoxLayoutState.h"
 #include "nsBoxFrame.h"
 #include "nsImageFrame.h"
 #include "nsIImageLoadingContent.h"
 #include "nsCSSRendering.h"
 #include "nsContentUtils.h"
 #include "mozilla/layers/ShadowLayers.h"
+#include "ImageContainer.h"
+#include "ImageLayers.h"
 
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::layers;
 using namespace mozilla::dom;
--- a/widget/gonk/Framebuffer.cpp
+++ b/widget/gonk/Framebuffer.cpp
@@ -30,16 +30,17 @@
 #include "android/log.h"
 
 #include "Framebuffer.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "gfxUtils.h"
 #include "mozilla/FileUtils.h"
 #include "nsTArray.h"
+#include "nsRegion.h"
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
 
 using namespace std;
 
 namespace mozilla {
 
 namespace Framebuffer {
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -20,16 +20,17 @@
 #include "android/log.h"
 #include "ui/FramebufferNativeWindow.h"
 
 #include "mozilla/Hal.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/FileUtils.h"
 #include "Framebuffer.h"
 #include "gfxContext.h"
+#include "gfxPlatform.h"
 #include "gfxUtils.h"
 #include "GLContextProvider.h"
 #include "LayerManagerOGL.h"
 #include "nsAutoPtr.h"
 #include "nsAppShell.h"
 #include "nsIdleService.h"
 #include "nsScreenManagerGonk.h"
 #include "nsTArray.h"