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 108747 54f5895b567a767b6f738bd78dff3f90bc6dcd29
parent 108746 6c1dfc8d5b4b19218d57468ec1536db62f1e2fe7
child 108748 28dc3eadf4a08de39728beff55dc9cdb310a0929
push id214
push userakeybl@mozilla.com
push dateWed, 14 Nov 2012 20:38:59 +0000
treeherdermozilla-release@c8b08ec8e1aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgirard
bugs782372
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 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"