Bug 874721, bug 899435. D3D9 compositor and windows OMTC window resizing. r=Bas, mattwoodrow
authorNicholas Cameron <ncameron@mozilla.com>
Sun, 04 Aug 2013 19:46:17 +1200
changeset 153609 c6962b015a6a538c037ed847c4a74aad56fcbf6c
parent 153608 79fb01e0e3fa88bef7e666e81d5d3cb785fa7e38
child 153610 a58abd7408bfe4cf9e1005b511da9ecce42b68ad
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas, mattwoodrow
bugs874721, 899435
milestone25.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 874721, bug 899435. D3D9 compositor and windows OMTC window resizing. r=Bas, mattwoodrow
dom/ipc/TabChild.cpp
gfx/layers/CompositorTypes.h
gfx/layers/ThebesLayerBuffer.cpp
gfx/layers/YCbCrImageDataSerializer.cpp
gfx/layers/YCbCrImageDataSerializer.h
gfx/layers/basic/BasicCompositor.h
gfx/layers/client/CompositableClient.cpp
gfx/layers/client/ContentClient.cpp
gfx/layers/client/ContentClient.h
gfx/layers/client/ImageClient.cpp
gfx/layers/client/TextureClient.cpp
gfx/layers/client/TextureClient.h
gfx/layers/composite/CanvasLayerComposite.cpp
gfx/layers/composite/CompositableHost.cpp
gfx/layers/composite/CompositableHost.h
gfx/layers/composite/ImageLayerComposite.cpp
gfx/layers/composite/LayerManagerComposite.cpp
gfx/layers/composite/TextureHost.cpp
gfx/layers/composite/TextureHost.h
gfx/layers/composite/ThebesLayerComposite.cpp
gfx/layers/d3d11/CompositorD3D11.cpp
gfx/layers/d3d11/CompositorD3D11.h
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/d3d11/TextureD3D11.h
gfx/layers/d3d9/ColorLayerD3D9.cpp
gfx/layers/d3d9/CompositorD3D9.cpp
gfx/layers/d3d9/CompositorD3D9.h
gfx/layers/d3d9/DeviceManagerD3D9.cpp
gfx/layers/d3d9/DeviceManagerD3D9.h
gfx/layers/d3d9/LayerManagerD3D9.h
gfx/layers/d3d9/TextureD3D9.cpp
gfx/layers/d3d9/TextureD3D9.h
gfx/layers/ipc/CompositableForwarder.h
gfx/layers/ipc/CompositorChild.cpp
gfx/layers/ipc/CompositorChild.h
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/CompositorParent.h
gfx/layers/ipc/ISurfaceAllocator.cpp
gfx/layers/ipc/LayersSurfaces.ipdlh
gfx/layers/ipc/PCompositor.ipdl
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
gfx/layers/moz.build
gfx/layers/opengl/CompositorOGL.h
gfx/layers/opengl/TextureClientOGL.cpp
gfx/layers/opengl/TextureClientOGL.h
gfx/thebes/gfxCachedTempSurface.cpp
gfx/thebes/gfxCachedTempSurface.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
layout/reftests/bugs/reftest.list
layout/reftests/ogg-video/reftest.list
layout/reftests/transform-3d/reftest.list
layout/reftests/webm-video/reftest.list
modules/libpref/src/init/all.js
widget/windows/nsWindow.cpp
widget/windows/nsWindow.h
widget/xpwidgets/nsBaseWidget.cpp
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -2208,24 +2208,29 @@ TabChild::InitRenderingState()
       NS_WARNING("failed to construct RenderFrame");
       return false;
     }
 
     PLayerTransactionChild* shadowManager = nullptr;
     if (id != 0) {
         // Pushing layers transactions directly to a separate
         // compositor context.
-		PCompositorChild* compositorChild = CompositorChild::Get();
+        PCompositorChild* compositorChild = CompositorChild::Get();
         if (!compositorChild) {
           NS_WARNING("failed to get CompositorChild instance");
           return false;
         }
+        bool success;
         shadowManager =
             compositorChild->SendPLayerTransactionConstructor(mTextureFactoryIdentifier.mParentBackend,
-                                                              id, &mTextureFactoryIdentifier);
+                                                              id, &mTextureFactoryIdentifier, &success);
+        if (!success) {
+          NS_WARNING("failed to properly allocate layer transaction");
+          return false;
+        }
     } else {
         // Pushing transactions to the parent content.
         shadowManager = remoteFrame->SendPLayerTransactionConstructor();
     }
 
     if (!shadowManager) {
       NS_WARNING("failed to construct LayersChild");
       // This results in |remoteFrame| being deleted.
--- a/gfx/layers/CompositorTypes.h
+++ b/gfx/layers/CompositorTypes.h
@@ -2,16 +2,18 @@
 * 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_LAYERS_COMPOSITORTYPES_H
 #define MOZILLA_LAYERS_COMPOSITORTYPES_H
 
 #include "LayersTypes.h"
+#include "nsXULAppAPI.h"
+
 
 namespace mozilla {
 namespace layers {
 
 typedef int32_t SurfaceDescriptorType;
 const SurfaceDescriptorType SURFACEDESCRIPTOR_UNKNOWN = 0;
 
 /**
@@ -118,17 +120,18 @@ enum DeprecatedTextureClientType
 {
   TEXTURE_CONTENT,            // dynamically drawn content
   TEXTURE_SHMEM,              // shared memory
   TEXTURE_YCBCR,              // Deprecated YCbCr texture
   TEXTURE_SHARED_GL,          // GLContext::SharedTextureHandle
   TEXTURE_SHARED_GL_EXTERNAL, // GLContext::SharedTextureHandle, the ownership of
                               // the SurfaceDescriptor passed to the texture
                               // remains with whoever passed it.
-  TEXTURE_STREAM_GL           // WebGL streaming buffer
+  TEXTURE_STREAM_GL,          // WebGL streaming buffer
+  TEXTURE_FALLBACK            // A fallback path appropriate for the platform
 };
 
 /**
  * How the Compositable should manage textures.
  */
 enum CompositableType
 {
   BUFFER_UNKNOWN,
@@ -161,25 +164,28 @@ enum DeprecatedTextureHostFlags
 /**
  * Sent from the compositor to the content-side LayerManager, includes properties
  * of the compositor and should (in the future) include information about what
  * kinds of buffer and texture clients to create.
  */
 struct TextureFactoryIdentifier
 {
   LayersBackend mParentBackend;
+  GeckoProcessType mParentProcessId;
   int32_t mMaxTextureSize;
   bool mSupportsTextureBlitting;
   bool mSupportsPartialUploads;
 
   TextureFactoryIdentifier(LayersBackend aLayersBackend = LAYERS_NONE,
+                           GeckoProcessType aParentProcessId = GeckoProcessType_Default,
                            int32_t aMaxTextureSize = 0,
                            bool aSupportsTextureBlitting = false,
                            bool aSupportsPartialUploads = false)
     : mParentBackend(aLayersBackend)
+    , mParentProcessId(aParentProcessId)
     , mMaxTextureSize(aMaxTextureSize)
     , mSupportsTextureBlitting(aSupportsTextureBlitting)
     , mSupportsPartialUploads(aSupportsPartialUploads)
   {}
 };
 
 /**
  * Identify a texture to a compositable. Many textures can have the same id, but
--- a/gfx/layers/ThebesLayerBuffer.cpp
+++ b/gfx/layers/ThebesLayerBuffer.cpp
@@ -441,17 +441,18 @@ ComputeBufferRect(const nsIntRect& aRequ
 
 ThebesLayerBuffer::PaintState
 ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
                               uint32_t aFlags)
 {
   PaintState result;
   // We need to disable rotation if we're going to be resampled when
   // drawing, because we might sample across the rotation boundary.
-  bool canHaveRotation = !(aFlags & (PAINT_WILL_RESAMPLE | PAINT_NO_ROTATION));
+  bool canHaveRotation = gfxPlatform::BufferRotationEnabled() &&
+                         !(aFlags & (PAINT_WILL_RESAMPLE | PAINT_NO_ROTATION));
 
   nsIntRegion validRegion = aLayer->GetValidRegion();
 
   Layer::SurfaceMode mode;
   ContentType contentType;
   nsIntRegion neededRegion;
   bool canReuseBuffer;
   nsIntRect destBufferRect;
--- a/gfx/layers/YCbCrImageDataSerializer.cpp
+++ b/gfx/layers/YCbCrImageDataSerializer.cpp
@@ -35,16 +35,17 @@ struct YCbCrBufferInfo
 {
   uint32_t mYOffset;
   uint32_t mCbOffset;
   uint32_t mCrOffset;
   uint32_t mYWidth;
   uint32_t mYHeight;
   uint32_t mCbCrWidth;
   uint32_t mCbCrHeight;
+  StereoMode mStereoMode;
 };
 
 static YCbCrBufferInfo* GetYCbCrBufferInfo(uint8_t* aData)
 {
   return reinterpret_cast<YCbCrBufferInfo*>(aData);
 }
 
 bool YCbCrImageDataDeserializerBase::IsValid()
@@ -98,16 +99,22 @@ gfxIntSize YCbCrImageDataDeserializerBas
 }
 
 gfxIntSize YCbCrImageDataDeserializerBase::GetCbCrSize()
 {
   YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
   return gfxIntSize(info->mCbCrWidth, info->mCbCrHeight);
 }
 
+StereoMode YCbCrImageDataDeserializerBase::GetStereoMode()
+{
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
+  return info->mStereoMode;
+}
+
 // Offset in bytes
 static size_t ComputeOffset(uint32_t aHeight, uint32_t aStride)
 {
   return MOZ_ALIGN_WORD(aHeight * aStride);
 }
 
 // Minimum required shmem size in bytes
 size_t
@@ -139,37 +146,41 @@ static size_t ComputeOffset(uint32_t aSi
 size_t
 YCbCrImageDataSerializer::ComputeMinBufferSize(uint32_t aSize)
 {
   return ComputeOffset(aSize) + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
 }
 
 void
 YCbCrImageDataSerializer::InitializeBufferInfo(const gfx::IntSize& aYSize,
-                                               const gfx::IntSize& aCbCrSize)
+                                               const gfx::IntSize& aCbCrSize,
+                                               StereoMode aStereoMode)
 {
   YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
   info->mYOffset = MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
   info->mCbOffset = info->mYOffset
                   + MOZ_ALIGN_WORD(aYSize.width * aYSize.height);
   info->mCrOffset = info->mCbOffset
                   + MOZ_ALIGN_WORD(aCbCrSize.width * aCbCrSize.height);
 
   info->mYWidth = aYSize.width;
   info->mYHeight = aYSize.height;
   info->mCbCrWidth = aCbCrSize.width;
   info->mCbCrHeight = aCbCrSize.height;
+  info->mStereoMode = aStereoMode;
 }
 
 void
 YCbCrImageDataSerializer::InitializeBufferInfo(const gfxIntSize& aYSize,
-                                               const gfxIntSize& aCbCrSize)
+                                               const gfxIntSize& aCbCrSize,
+                                               StereoMode aStereoMode)
 {
   InitializeBufferInfo(gfx::IntSize(aYSize.width, aYSize.height),
-                       gfx::IntSize(aCbCrSize.width, aCbCrSize.height));
+                       gfx::IntSize(aCbCrSize.width, aCbCrSize.height),
+                       aStereoMode);
 }
 
 static void CopyLineWithSkip(const uint8_t* src, uint8_t* dst, uint32_t len, uint32_t skip) {
   for (uint32_t i = 0; i < len; ++i) {
     *dst = *src;
     src += 1 + skip;
     ++dst;
   }
--- a/gfx/layers/YCbCrImageDataSerializer.h
+++ b/gfx/layers/YCbCrImageDataSerializer.h
@@ -62,16 +62,21 @@ public:
   gfxIntSize GetYSize();
 
   /**
    * Returns the dimensions of the Cb and Cr Channel.
    */
   gfxIntSize GetCbCrSize();
 
   /**
+   * Stereo mode for the image.
+   */
+  StereoMode GetStereoMode();
+
+  /**
    * Return a pointer to the begining of the data buffer.
    */
   uint8_t* GetData();
 protected:
   YCbCrImageDataDeserializerBase(uint8_t* aData)
   : mData (aData) {}
 
   uint8_t* mData;
@@ -106,19 +111,21 @@ public:
   static size_t ComputeMinBufferSize(uint32_t aSize);
 
   /**
    * Write the image informations in the buffer for given dimensions.
    * The provided pointer should point to the beginning of the (chunk of)
    * buffer on which we want to store the image.
    */
   void InitializeBufferInfo(const gfx::IntSize& aYSize,
-                            const gfx::IntSize& aCbCrSize);
+                            const gfx::IntSize& aCbCrSize,
+                            StereoMode aStereoMode);
   void InitializeBufferInfo(const gfxIntSize& aYSize,
-                            const gfxIntSize& aCbCrSize);
+                            const gfxIntSize& aCbCrSize,
+                            StereoMode aStereoMode);
 
   bool CopyData(const uint8_t* aYData,
                 const uint8_t* aCbData, const uint8_t* aCrData,
                 gfxIntSize aYSize, uint32_t aYStride,
                 gfxIntSize aCbCrSize, uint32_t aCbCrStride,
                 uint32_t aYSkip, uint32_t aCbCrSkip);
 };
 
--- a/gfx/layers/basic/BasicCompositor.h
+++ b/gfx/layers/basic/BasicCompositor.h
@@ -38,17 +38,19 @@ public:
 
   virtual void Destroy() MOZ_OVERRIDE;
 
   virtual TemporaryRef<DataTextureSource>
   CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE { return nullptr; }
 
   virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() MOZ_OVERRIDE
   {
-    return TextureFactoryIdentifier(LAYERS_BASIC, GetMaxTextureSize());
+    return TextureFactoryIdentifier(LAYERS_BASIC,
+                                    XRE_GetProcessType(),
+                                    GetMaxTextureSize());
   }
 
   virtual TemporaryRef<CompositingRenderTarget>
   CreateRenderTarget(const gfx::IntRect &aRect, SurfaceInitMode aInit) MOZ_OVERRIDE;
 
   virtual TemporaryRef<CompositingRenderTarget>
   CreateRenderTargetFromSource(const gfx::IntRect &aRect,
                                const CompositingRenderTarget *aSource) MOZ_OVERRIDE;
--- a/gfx/layers/client/CompositableClient.cpp
+++ b/gfx/layers/client/CompositableClient.cpp
@@ -5,16 +5,17 @@
 
 #include "mozilla/layers/CompositableClient.h"
 #include "mozilla/layers/TextureClient.h"
 #include "mozilla/layers/TextureClientOGL.h"
 #include "mozilla/layers/LayerTransactionChild.h"
 #include "mozilla/layers/CompositableForwarder.h"
 #include "gfxPlatform.h"
 #ifdef XP_WIN
+#include "mozilla/layers/TextureD3D9.h"
 #include "mozilla/layers/TextureD3D11.h"
 #include "gfxWindowsPlatform.h"
 #endif
 
 namespace mozilla {
 namespace layers {
 
 CompositableClient::CompositableClient(CompositableForwarder* aForwarder)
@@ -107,32 +108,45 @@ CompositableClient::CreateDeprecatedText
     break;
   case TEXTURE_STREAM_GL:
     if (parentBackend == LAYERS_OPENGL) {
       result = new DeprecatedTextureClientStreamOGL(GetForwarder(), GetTextureInfo());
     }
     break;
   case TEXTURE_YCBCR:
     if (parentBackend == LAYERS_OPENGL ||
+        parentBackend == LAYERS_D3D9 ||
         parentBackend == LAYERS_D3D11 ||
         parentBackend == LAYERS_BASIC) {
       result = new DeprecatedTextureClientShmemYCbCr(GetForwarder(), GetTextureInfo());
     }
     break;
   case TEXTURE_CONTENT:
 #ifdef XP_WIN
     if (parentBackend == LAYERS_D3D11 && gfxWindowsPlatform::GetPlatform()->GetD2DDevice()) {
       result = new DeprecatedTextureClientD3D11(GetForwarder(), GetTextureInfo());
       break;
     }
+    if (parentBackend == LAYERS_D3D9 &&
+        !GetForwarder()->ForwardsToDifferentProcess()) {
+      result = new DeprecatedTextureClientD3D9(GetForwarder(), GetTextureInfo());
+      break;
+    }
 #endif
      // fall through to TEXTURE_SHMEM
   case TEXTURE_SHMEM:
     result = new DeprecatedTextureClientShmem(GetForwarder(), GetTextureInfo());
     break;
+  case TEXTURE_FALLBACK:
+#ifdef XP_WIN
+    if (parentBackend == LAYERS_D3D9) {
+      result = new DeprecatedTextureClientShmem(GetForwarder(), GetTextureInfo());
+    }
+#endif
+    break;
   default:
     MOZ_ASSERT(false, "Unhandled texture client type");
   }
 
   // If we couldn't create an appropriate texture client,
   // then return nullptr so the caller can chose another
   // type.
   if (!result) {
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -21,19 +21,20 @@ using namespace gfx;
 
 namespace layers {
 
 /* static */ TemporaryRef<ContentClient>
 ContentClient::CreateContentClient(CompositableForwarder* aForwarder)
 {
   LayersBackend backend = aForwarder->GetCompositorBackendType();
   if (backend != LAYERS_OPENGL &&
+      backend != LAYERS_D3D9 &&
       backend != LAYERS_D3D11 &&
       backend != LAYERS_BASIC) {
-        return nullptr;
+    return nullptr;
   }
 
   bool useDoubleBuffering = false;
 
 #ifdef XP_WIN
   if (backend == LAYERS_D3D11) {
     useDoubleBuffering = !!gfxWindowsPlatform::GetPlatform()->GetD2DDevice();
   } else
@@ -133,16 +134,35 @@ ContentClientRemoteBuffer::EndPaint()
   if (mDeprecatedTextureClient) {
     mDeprecatedTextureClient->Unlock();
   }
   if (mDeprecatedTextureClientOnWhite) {
     mDeprecatedTextureClientOnWhite->Unlock();
   }
 }
 
+bool
+ContentClientRemoteBuffer::CreateAndAllocateDeprecatedTextureClient(RefPtr<DeprecatedTextureClient>& aClient)
+{
+  aClient = CreateDeprecatedTextureClient(TEXTURE_CONTENT);
+  MOZ_ASSERT(aClient, "Failed to create texture client");
+
+  if (!aClient->EnsureAllocated(mSize, mContentType)) {
+    aClient = CreateDeprecatedTextureClient(TEXTURE_FALLBACK);
+    MOZ_ASSERT(aClient, "Failed to create texture client");
+    if (!aClient->EnsureAllocated(mSize, mContentType)) {
+      NS_WARNING("Could not allocate texture client");
+      return false;
+    }
+  }
+
+  MOZ_ASSERT(IsSurfaceDescriptorValid(*aClient->GetDescriptor()));
+  return true;
+}
+
 void
 ContentClientRemoteBuffer::BuildDeprecatedTextureClients(ContentType aType,
                                                const nsIntRect& aRect,
                                                uint32_t aFlags)
 {
   NS_ABORT_IF_FALSE(!mIsNewBuffer,
                     "Bad! Did we create a buffer twice without painting?");
 
@@ -150,32 +170,30 @@ ContentClientRemoteBuffer::BuildDeprecat
 
   if (mDeprecatedTextureClient) {
     mOldTextures.AppendElement(mDeprecatedTextureClient);
     if (mDeprecatedTextureClientOnWhite) {
       mOldTextures.AppendElement(mDeprecatedTextureClientOnWhite);
     }
     DestroyBuffers();
   }
-  mTextureInfo.mTextureFlags = aFlags | TEXTURE_DEALLOCATE_HOST;
-  mDeprecatedTextureClient = CreateDeprecatedTextureClient(TEXTURE_CONTENT);
-  MOZ_ASSERT(mDeprecatedTextureClient, "Failed to create texture client");
-  if (aFlags & BUFFER_COMPONENT_ALPHA) {
-    mDeprecatedTextureClientOnWhite = CreateDeprecatedTextureClient(TEXTURE_CONTENT);
-    MOZ_ASSERT(mDeprecatedTextureClientOnWhite, "Failed to create texture client");
-    mTextureInfo.mTextureFlags |= ComponentAlpha;
-  }
 
   mContentType = aType;
   mSize = gfx::IntSize(aRect.width, aRect.height);
-  mDeprecatedTextureClient->EnsureAllocated(mSize, mContentType);
-  MOZ_ASSERT(IsSurfaceDescriptorValid(*mDeprecatedTextureClient->GetDescriptor()));
-  if (mDeprecatedTextureClientOnWhite) {
-    mDeprecatedTextureClientOnWhite->EnsureAllocated(mSize, mContentType);
-    MOZ_ASSERT(IsSurfaceDescriptorValid(*mDeprecatedTextureClientOnWhite->GetDescriptor()));
+  mTextureInfo.mTextureFlags = aFlags | TEXTURE_DEALLOCATE_HOST;
+
+  if (!CreateAndAllocateDeprecatedTextureClient(mDeprecatedTextureClient)) {
+    return;
+  }
+  
+  if (aFlags & BUFFER_COMPONENT_ALPHA) {
+    if (!CreateAndAllocateDeprecatedTextureClient(mDeprecatedTextureClientOnWhite)) {
+      return;
+    }
+    mTextureInfo.mTextureFlags |= ComponentAlpha;
   }
 
   CreateFrontBufferAndNotify(aRect);
 }
 
 TemporaryRef<DrawTarget>
 ContentClientRemoteBuffer::CreateDTBuffer(ContentType aType,
                                           const nsIntRect& aRect,
@@ -278,28 +296,28 @@ ContentClientDoubleBuffered::~ContentCli
     mDeprecatedTextureClientOnWhite->SetDescriptor(SurfaceDescriptor());
     mFrontClientOnWhite->SetDescriptor(SurfaceDescriptor());
   }
 }
 
 void
 ContentClientDoubleBuffered::CreateFrontBufferAndNotify(const nsIntRect& aBufferRect)
 {
-  mFrontClient = CreateDeprecatedTextureClient(TEXTURE_CONTENT);
-  MOZ_ASSERT(mFrontClient, "Failed to create texture client");
-  mFrontClient->EnsureAllocated(mSize, mContentType);
+  if (!CreateAndAllocateDeprecatedTextureClient(mFrontClient)) {
+    return;
+  }
+
+  if (mTextureInfo.mTextureFlags & ComponentAlpha) {
+    if (!CreateAndAllocateDeprecatedTextureClient(mFrontClientOnWhite)) {
+      return;
+    }
+  }
 
   mFrontBufferRect = aBufferRect;
   mFrontBufferRotation = nsIntPoint();
-
-  if (mTextureInfo.mTextureFlags & ComponentAlpha) {
-    mFrontClientOnWhite = CreateDeprecatedTextureClient(TEXTURE_CONTENT);
-    MOZ_ASSERT(mFrontClientOnWhite, "Failed to create texture client");
-    mFrontClientOnWhite->EnsureAllocated(mSize, mContentType);
-  }
   
   mForwarder->CreatedDoubleBuffer(this,
                                   *mFrontClient->GetDescriptor(),
                                   *mDeprecatedTextureClient->GetDescriptor(),
                                   mTextureInfo,
                                   mFrontClientOnWhite ? mFrontClientOnWhite->GetDescriptor() : nullptr,
                                   mDeprecatedTextureClientOnWhite ? mDeprecatedTextureClientOnWhite->GetDescriptor() : nullptr);
 }
--- a/gfx/layers/client/ContentClient.h
+++ b/gfx/layers/client/ContentClient.h
@@ -248,16 +248,18 @@ protected:
   // Create the front buffer for the ContentClient/Host pair if necessary
   // and notify the compositor that we have created the buffer(s).
   virtual void CreateFrontBufferAndNotify(const nsIntRect& aBufferRect) = 0;
   virtual void DestroyFrontBuffer() {}
   // We're about to hand off to the compositor, if you've got a back buffer,
   // lock it now.
   virtual void LockFrontBuffer() {}
 
+  bool CreateAndAllocateDeprecatedTextureClient(RefPtr<DeprecatedTextureClient>& aClient);
+
   RefPtr<DeprecatedTextureClient> mDeprecatedTextureClient;
   RefPtr<DeprecatedTextureClient> mDeprecatedTextureClientOnWhite;
   // keep a record of texture clients we have created and need to keep
   // around, then unlock when we are done painting
   nsTArray<RefPtr<DeprecatedTextureClient> > mOldTextures;
 
   TextureInfo mTextureInfo;
   bool mIsNewBuffer;
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -116,17 +116,17 @@ ImageClientSingle::UpdateImage(ImageCont
       RemoveTextureClient(mFrontBuffer);
       mFrontBuffer = nullptr;
     }
 
     if (!mFrontBuffer) {
       mFrontBuffer = CreateBufferTextureClient(gfx::FORMAT_YUV);
       gfx::IntSize ySize(data->mYSize.width, data->mYSize.height);
       gfx::IntSize cbCrSize(data->mCbCrSize.width, data->mCbCrSize.height);
-      if (!mFrontBuffer->AsTextureClientYCbCr()->AllocateForYCbCr(ySize, cbCrSize)) {
+      if (!mFrontBuffer->AsTextureClientYCbCr()->AllocateForYCbCr(ySize, cbCrSize, data->mStereoMode)) {
         mFrontBuffer = nullptr;
         return false;
       }
       AddTextureClient(mFrontBuffer);
     }
 
     if (!mFrontBuffer->Lock(OPEN_READ_WRITE)) {
       return false;
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -235,26 +235,29 @@ BufferTextureClient::UpdateYCbCr(const P
     // We don't have support for proper locking yet, so we'll
     // have to be immutable instead.
     MarkImmutable();
   }
   return true;
 }
 
 bool
-BufferTextureClient::AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize)
+BufferTextureClient::AllocateForYCbCr(gfx::IntSize aYSize,
+                                      gfx::IntSize aCbCrSize,
+                                      StereoMode aStereoMode)
 {
   size_t bufSize = YCbCrImageDataSerializer::ComputeMinBufferSize(aYSize,
                                                                   aCbCrSize);
   if (!Allocate(bufSize)) {
     return false;
   }
   YCbCrImageDataSerializer serializer(GetBuffer());
   serializer.InitializeBufferInfo(aYSize,
-                                  aCbCrSize);
+                                  aCbCrSize,
+                                  aStereoMode);
   mSize = aYSize;
   return true;
 }
 
 
 
 
 
@@ -299,33 +302,34 @@ DeprecatedTextureClientShmem::ReleaseRes
   }
 
   if (IsSurfaceDescriptorValid(mDescriptor)) {
     mForwarder->DestroySharedSurface(&mDescriptor);
     mDescriptor = SurfaceDescriptor();
   }
 }
 
-void
+bool
 DeprecatedTextureClientShmem::EnsureAllocated(gfx::IntSize aSize,
                                     gfxASurface::gfxContentType aContentType)
 {
   if (aSize != mSize ||
       aContentType != mContentType ||
       !IsSurfaceDescriptorValid(mDescriptor)) {
     ReleaseResources();
 
     mContentType = aContentType;
     mSize = aSize;
 
     if (!mForwarder->AllocSurfaceDescriptor(gfxIntSize(mSize.width, mSize.height),
                                             mContentType, &mDescriptor)) {
       NS_WARNING("creating SurfaceDescriptor failed!");
     }
   }
+  return true;
 }
 
 void
 DeprecatedTextureClientShmem::SetDescriptor(const SurfaceDescriptor& aDescriptor)
 {
   if (IsSurfaceDescriptorValid(aDescriptor)) {
     ReleaseResources();
     mDescriptor = aDescriptor;
@@ -427,43 +431,45 @@ DeprecatedTextureClientShmemYCbCr::SetDe
   if (shYCbCr) {
     shYCbCr->Release();
     mDescriptor = SurfaceDescriptor();
   } else {
     SetDescriptor(aDescriptor);
   }
 }
 
-void
+bool
 DeprecatedTextureClientShmemYCbCr::EnsureAllocated(gfx::IntSize aSize,
                                          gfxASurface::gfxContentType aType)
 {
   NS_RUNTIMEABORT("not enough arguments to do this (need both Y and CbCr sizes)");
+  return false;
 }
 
 
 DeprecatedTextureClientTile::DeprecatedTextureClientTile(CompositableForwarder* aForwarder,
                                      const TextureInfo& aTextureInfo)
   : DeprecatedTextureClient(aForwarder, aTextureInfo)
   , mSurface(nullptr)
 {
   mTextureInfo.mDeprecatedTextureHostFlags = TEXTURE_HOST_TILED;
 }
 
-void
+bool
 DeprecatedTextureClientTile::EnsureAllocated(gfx::IntSize aSize, gfxASurface::gfxContentType aType)
 {
   if (!mSurface ||
       mSurface->Format() != gfxPlatform::GetPlatform()->OptimalFormatForContent(aType)) {
     gfxImageSurface* tmpTile = new gfxImageSurface(gfxIntSize(aSize.width, aSize.height),
                                                    gfxPlatform::GetPlatform()->OptimalFormatForContent(aType),
                                                    aType != gfxASurface::CONTENT_COLOR);
     mSurface = new gfxReusableSurfaceWrapper(tmpTile);
     mContentType = aType;
   }
+  return true;
 }
 
 gfxImageSurface*
 DeprecatedTextureClientTile::LockImageSurface()
 {
   // Use the gfxReusableSurfaceWrapper, which will reuse the surface
   // if the compositor no longer has a read lock, otherwise the surface
   // will be copied into a new writable surface.
@@ -575,17 +581,18 @@ bool AutoLockYCbCrClient::EnsureDeprecat
                                                                data->mCbCrSize);
   ipc::Shmem shmem;
   if (!mDeprecatedTextureClient->GetForwarder()->AllocUnsafeShmem(size, shmType, &shmem)) {
     return false;
   }
 
   YCbCrImageDataSerializer serializer(shmem.get<uint8_t>());
   serializer.InitializeBufferInfo(data->mYSize,
-                                  data->mCbCrSize);
+                                  data->mCbCrSize,
+                                  data->mStereoMode);
 
   *mDescriptor = YCbCrImage(shmem, 0);
 
   return true;
 }
 
 
 }
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -50,17 +50,19 @@ public:
 
 /**
  * Interface for TextureClients that can be updated using YCbCr data.
  */
 class TextureClientYCbCr
 {
 public:
   virtual bool UpdateYCbCr(const PlanarYCbCrImage::Data& aData) = 0;
-  virtual bool AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize) = 0;
+  virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
+                                gfx::IntSize aCbCrSize,
+                                StereoMode aStereoMode) = 0;
 };
 
 
 /**
  * TextureClient is a thin abstraction over texture data that need to be shared
  * between the content process and the compositor process. It is the
  * content-side half of a TextureClient/TextureHost pair. A corresponding
  * TextureHost lives on the compositor-side.
@@ -198,17 +200,19 @@ public:
   virtual bool AllocateForSurface(gfx::IntSize aSize) MOZ_OVERRIDE;
 
   // TextureClientYCbCr
 
   virtual TextureClientYCbCr* AsTextureClientYCbCr() MOZ_OVERRIDE { return this; }
 
   virtual bool UpdateYCbCr(const PlanarYCbCrImage::Data& aData) MOZ_OVERRIDE;
 
-  virtual bool AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize) MOZ_OVERRIDE;
+  virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
+                                gfx::IntSize aCbCrSize,
+                                StereoMode aStereoMode) MOZ_OVERRIDE;
 
   gfx::SurfaceFormat GetFormat() const { return mFormat; }
 
 protected:
   CompositableClient* mCompositable;
   gfx::SurfaceFormat mFormat;
   gfx::IntSize mSize;
 };
@@ -349,18 +353,19 @@ public:
    * This unlocks the current DrawableTexture and allows the host to composite
    * it directly.
    */
   virtual void Unlock() {}
 
   /**
    * Ensure that the texture client is suitable for the given size and content
    * type and that any initialisation has taken place.
+   * Returns true if succeeded, false if failed.
    */
-  virtual void EnsureAllocated(gfx::IntSize aSize,
+  virtual bool EnsureAllocated(gfx::IntSize aSize,
                                gfxASurface::gfxContentType aType) = 0;
 
   /**
    * _Only_ used at the end of the layer transaction when receiving a reply from
    *  the compositor.
    */
   virtual void SetDescriptorFromReply(const SurfaceDescriptor& aDescriptor)
   {
@@ -417,23 +422,23 @@ protected:
 class DeprecatedTextureClientShmem : public DeprecatedTextureClient
 {
 public:
   DeprecatedTextureClientShmem(CompositableForwarder* aForwarder, const TextureInfo& aTextureInfo);
   ~DeprecatedTextureClientShmem() { ReleaseResources(); }
 
   virtual bool SupportsType(DeprecatedTextureClientType aType) MOZ_OVERRIDE
   {
-    return aType == TEXTURE_SHMEM || aType == TEXTURE_CONTENT;
+    return aType == TEXTURE_SHMEM || aType == TEXTURE_CONTENT || aType == TEXTURE_FALLBACK;
   }
   virtual gfxImageSurface* LockImageSurface() MOZ_OVERRIDE;
   virtual gfxASurface* LockSurface() MOZ_OVERRIDE { return GetSurface(); }
   virtual gfx::DrawTarget* LockDrawTarget();
   virtual void Unlock() MOZ_OVERRIDE;
-  virtual void EnsureAllocated(gfx::IntSize aSize, gfxASurface::gfxContentType aType) MOZ_OVERRIDE;
+  virtual bool EnsureAllocated(gfx::IntSize aSize, gfxASurface::gfxContentType aType) MOZ_OVERRIDE;
 
   virtual void ReleaseResources() MOZ_OVERRIDE;
   virtual void SetDescriptor(const SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE;
   virtual gfxASurface::gfxContentType GetContentType() MOZ_OVERRIDE { return mContentType; }
 private:
   gfxASurface* GetSurface();
 
   nsRefPtr<gfxASurface> mSurface;
@@ -451,32 +456,32 @@ class DeprecatedTextureClientShmemYCbCr 
 {
 public:
   DeprecatedTextureClientShmemYCbCr(CompositableForwarder* aForwarder, const TextureInfo& aTextureInfo)
     : DeprecatedTextureClient(aForwarder, aTextureInfo)
   { }
   ~DeprecatedTextureClientShmemYCbCr() { ReleaseResources(); }
 
   virtual bool SupportsType(DeprecatedTextureClientType aType) MOZ_OVERRIDE { return aType == TEXTURE_YCBCR; }
-  void EnsureAllocated(gfx::IntSize aSize, gfxASurface::gfxContentType aType) MOZ_OVERRIDE;
+  bool EnsureAllocated(gfx::IntSize aSize, gfxASurface::gfxContentType aType) MOZ_OVERRIDE;
   virtual void SetDescriptorFromReply(const SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE;
   virtual void SetDescriptor(const SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE;
   virtual void ReleaseResources();
   virtual gfxASurface::gfxContentType GetContentType() MOZ_OVERRIDE { return gfxASurface::CONTENT_COLOR_ALPHA; }
 };
 
 class DeprecatedTextureClientTile : public DeprecatedTextureClient
 {
 public:
   DeprecatedTextureClientTile(const DeprecatedTextureClientTile& aOther);
   DeprecatedTextureClientTile(CompositableForwarder* aForwarder,
                     const TextureInfo& aTextureInfo);
   ~DeprecatedTextureClientTile();
 
-  virtual void EnsureAllocated(gfx::IntSize aSize,
+  virtual bool EnsureAllocated(gfx::IntSize aSize,
                                gfxASurface::gfxContentType aType) MOZ_OVERRIDE;
 
   virtual gfxImageSurface* LockImageSurface() MOZ_OVERRIDE;
 
   gfxReusableSurfaceWrapper* GetReusableSurfaceWrapper()
   {
     return mSurface;
   }
--- a/gfx/layers/composite/CanvasLayerComposite.cpp
+++ b/gfx/layers/composite/CanvasLayerComposite.cpp
@@ -28,40 +28,41 @@ CanvasLayerComposite::CanvasLayerComposi
 
 CanvasLayerComposite::~CanvasLayerComposite()
 {
   MOZ_COUNT_DTOR(CanvasLayerComposite);
 
   CleanupResources();
 }
 
-void CanvasLayerComposite::SetCompositableHost(CompositableHost* aHost) {
+void
+CanvasLayerComposite::SetCompositableHost(CompositableHost* aHost) {
   mImageHost = aHost;
 }
 
 Layer*
 CanvasLayerComposite::GetLayer()
 {
   return this;
 }
 
 LayerRenderState
 CanvasLayerComposite::GetRenderState()
 {
-  if (mDestroyed || !mImageHost) {
+  if (mDestroyed || !mImageHost || !mImageHost->IsAttached()) {
     return LayerRenderState();
   }
   return mImageHost->GetRenderState();
 }
 
 void
 CanvasLayerComposite::RenderLayer(const nsIntPoint& aOffset,
                                   const nsIntRect& aClipRect)
 {
-  if (!mImageHost) {
+  if (!mImageHost || !mImageHost->IsAttached()) {
     return;
   }
 
   mCompositor->MakeCurrent();
 
 #ifdef MOZ_DUMP_PAINTING
   if (gfxUtils::sDumpPainting) {
     nsRefPtr<gfxImageSurface> surf = mImageHost->GetAsSurface();
@@ -93,18 +94,23 @@ CanvasLayerComposite::RenderLayer(const 
                         gfx::Point(aOffset.x, aOffset.y),
                         gfx::ToFilter(filter),
                         clipRect);
 
   LayerManagerComposite::RemoveMaskEffect(mMaskLayer);
 }
 
 CompositableHost*
-CanvasLayerComposite::GetCompositableHost() {
-  return mImageHost.get();
+CanvasLayerComposite::GetCompositableHost()
+{
+  if (mImageHost->IsAttached()) {
+    return mImageHost.get();
+  }
+
+  return nullptr;
 }
 
 void
 CanvasLayerComposite::CleanupResources()
 {
   if (mImageHost) {
     mImageHost->Detach();
   }
@@ -112,17 +118,17 @@ CanvasLayerComposite::CleanupResources()
 }
 
 #ifdef MOZ_LAYERS_HAVE_LOG
 nsACString&
 CanvasLayerComposite::PrintInfo(nsACString& aTo, const char* aPrefix)
 {
   CanvasLayer::PrintInfo(aTo, aPrefix);
   aTo += "\n";
-  if (mImageHost) {
+  if (mImageHost && mImageHost->IsAttached()) {
     nsAutoCString pfx(aPrefix);
     pfx += "  ";
     mImageHost->PrintInfo(aTo, pfx.get());
   }
   return aTo;
 }
 #endif
 
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -13,16 +13,17 @@
 
 namespace mozilla {
 namespace layers {
 
 CompositableHost::CompositableHost(const TextureInfo& aTextureInfo)
   : mTextureInfo(aTextureInfo)
   , mCompositor(nullptr)
   , mLayer(nullptr)
+  , mAttached(false)
 {
   MOZ_COUNT_CTOR(CompositableHost);
 }
 
 CompositableHost::~CompositableHost()
 {
   MOZ_COUNT_DTOR(CompositableHost);
 
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -182,23 +182,28 @@ public:
   Layer* GetLayer() const { return mLayer; }
   void SetLayer(Layer* aLayer) { mLayer = aLayer; }
 
   virtual TiledLayerComposer* AsTiledLayerComposer() { return nullptr; }
 
   virtual void Attach(Layer* aLayer, Compositor* aCompositor)
   {
     MOZ_ASSERT(aCompositor, "Compositor is required");
+    MOZ_ASSERT(!IsAttached());
     SetCompositor(aCompositor);
     SetLayer(aLayer);
+    mAttached = true;
   }
-  void Detach() {
+  void Detach()
+  {
     SetLayer(nullptr);
     SetCompositor(nullptr);
+    mAttached = false;
   }
+  bool IsAttached() { return mAttached; }
 
   virtual void Dump(FILE* aFile=nullptr,
                     const char* aPrefix="",
                     bool aDumpHtml=false) { }
   static void DumpDeprecatedTextureHost(FILE* aFile, DeprecatedTextureHost* aTexture);
   static void DumpTextureHost(FILE* aFile, TextureHost* aTexture);
 
 #ifdef MOZ_DUMP_PAINTING
@@ -214,16 +219,17 @@ public:
   void RemoveTextureHost(uint64_t aTextureID);
   TextureHost* GetTextureHost(uint64_t aTextureID);
 
 protected:
   TextureInfo mTextureInfo;
   Compositor* mCompositor;
   Layer* mLayer;
   RefPtr<TextureHost> mFirstTexture;
+  bool mAttached;
 };
 
 class CompositableParentManager;
 
 class CompositableParent : public PCompositableParent
 {
 public:
   CompositableParent(CompositableParentManager* aMgr,
--- a/gfx/layers/composite/ImageLayerComposite.cpp
+++ b/gfx/layers/composite/ImageLayerComposite.cpp
@@ -49,33 +49,33 @@ void
 ImageLayerComposite::Disconnect()
 {
   Destroy();
 }
 
 LayerRenderState
 ImageLayerComposite::GetRenderState()
 {
-  if (mImageHost) {
+  if (mImageHost && mImageHost->IsAttached()) {
     return mImageHost->GetRenderState();
   }
   return LayerRenderState();
 }
 
 Layer*
 ImageLayerComposite::GetLayer()
 {
   return this;
 }
 
 void
 ImageLayerComposite::RenderLayer(const nsIntPoint& aOffset,
                                  const nsIntRect& aClipRect)
 {
-  if (!mImageHost) {
+  if (!mImageHost || !mImageHost->IsAttached()) {
     return;
   }
 
 #ifdef MOZ_DUMP_PAINTING
   if (gfxUtils::sDumpPainting) {
     nsRefPtr<gfxImageSurface> surf = mImageHost->GetAsSurface();
     WriteSnapshotToDumpFile(this, surf);
   }
@@ -103,17 +103,18 @@ ImageLayerComposite::RenderLayer(const n
 void 
 ImageLayerComposite::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
 {
   gfx3DMatrix local = GetLocalTransform();
 
   // Snap image edges to pixel boundaries
   gfxRect sourceRect(0, 0, 0, 0);
   if (mImageHost &&
-    (mImageHost->GetDeprecatedTextureHost() || mImageHost->GetTextureHost())) {
+      mImageHost->IsAttached() &&
+      (mImageHost->GetDeprecatedTextureHost() || mImageHost->GetTextureHost())) {
     IntSize size =
       mImageHost->GetTextureHost() ? mImageHost->GetTextureHost()->GetSize()
                                    : mImageHost->GetDeprecatedTextureHost()->GetSize();
     sourceRect.SizeTo(size.width, size.height);
     if (mScaleMode != SCALE_NONE &&
         sourceRect.width != 0.0 && sourceRect.height != 0.0) {
       NS_ASSERTION(mScaleMode == SCALE_STRETCH,
                    "No other scalemodes than stretch and none supported yet.");
@@ -127,18 +128,22 @@ ImageLayerComposite::ComputeEffectiveTra
   // transform, then we'd snap again when compositing the ThebesLayer).
   mEffectiveTransform =
       SnapTransform(local, sourceRect, nullptr) *
       SnapTransformTranslation(aTransformToSurface, nullptr);
   ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
 }
 
 CompositableHost*
-ImageLayerComposite::GetCompositableHost() {
-  return mImageHost.get();
+ImageLayerComposite::GetCompositableHost()
+{
+  if (mImageHost->IsAttached())
+    return mImageHost.get();
+
+  return nullptr;
 }
 
 void
 ImageLayerComposite::CleanupResources()
 {
   if (mImageHost) {
     mImageHost->Detach();
   }
@@ -146,17 +151,17 @@ ImageLayerComposite::CleanupResources()
 }
 
 #ifdef MOZ_LAYERS_HAVE_LOG
 nsACString&
 ImageLayerComposite::PrintInfo(nsACString& aTo, const char* aPrefix)
 {
   ImageLayer::PrintInfo(aTo, aPrefix);
   aTo += "\n";
-  if (mImageHost) {
+  if (mImageHost && mImageHost->IsAttached()) {
     nsAutoCString pfx(aPrefix);
     pfx += "  ";
     mImageHost->PrintInfo(aTo, pfx.get());
   }
   return aTo;
 }
 #endif
 
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -81,16 +81,17 @@ LayerManagerComposite::ClearCachedResour
 }
 
 /**
  * LayerManagerComposite
  */
 LayerManagerComposite::LayerManagerComposite(Compositor* aCompositor)
 : mCompositor(aCompositor)
 {
+  MOZ_ASSERT(aCompositor);
 }
 
 LayerManagerComposite::~LayerManagerComposite()
 {
   Destroy();
 }
 
 
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -22,45 +22,41 @@ namespace layers {
 TemporaryRef<DeprecatedTextureHost> CreateDeprecatedTextureHostOGL(SurfaceDescriptorType aDescriptorType,
                                                            uint32_t aDeprecatedTextureHostFlags,
                                                            uint32_t aTextureFlags);
 // implemented in BasicCompositor.cpp
 TemporaryRef<DeprecatedTextureHost> CreateBasicDeprecatedTextureHost(SurfaceDescriptorType aDescriptorType,
                                                              uint32_t aDeprecatedTextureHostFlags,
                                                              uint32_t aTextureFlags);
 
+#ifdef XP_WIN
 TemporaryRef<DeprecatedTextureHost> CreateDeprecatedTextureHostD3D9(SurfaceDescriptorType aDescriptorType,
                                                             uint32_t aDeprecatedTextureHostFlags,
-                                                            uint32_t aTextureFlags)
-{
-  NS_RUNTIMEABORT("not implemented");
-  return nullptr;
-}
+                                                            uint32_t aTextureFlags);
 
-#ifdef XP_WIN
 TemporaryRef<DeprecatedTextureHost> CreateDeprecatedTextureHostD3D11(SurfaceDescriptorType aDescriptorType,
                                                              uint32_t aDeprecatedTextureHostFlags,
                                                              uint32_t aTextureFlags);
 #endif
 
 /* static */ TemporaryRef<DeprecatedTextureHost>
 DeprecatedTextureHost::CreateDeprecatedTextureHost(SurfaceDescriptorType aDescriptorType,
                                            uint32_t aDeprecatedTextureHostFlags,
                                            uint32_t aTextureFlags)
 {
   switch (Compositor::GetBackend()) {
     case LAYERS_OPENGL:
       return CreateDeprecatedTextureHostOGL(aDescriptorType,
                                         aDeprecatedTextureHostFlags,
                                         aTextureFlags);
+#ifdef XP_WIN
     case LAYERS_D3D9:
       return CreateDeprecatedTextureHostD3D9(aDescriptorType,
                                          aDeprecatedTextureHostFlags,
                                          aTextureFlags);
-#ifdef XP_WIN
     case LAYERS_D3D11:
       return CreateDeprecatedTextureHostD3D11(aDescriptorType,
                                           aDeprecatedTextureHostFlags,
                                           aTextureFlags);
 #endif
     case LAYERS_BASIC:
       return CreateBasicDeprecatedTextureHost(aDescriptorType,
                                           aDeprecatedTextureHostFlags,
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -26,16 +26,17 @@ class DataSourceSurface;
 
 namespace mozilla {
 namespace layers {
 
 class Compositor;
 class SurfaceDescriptor;
 class ISurfaceAllocator;
 class TextureSourceOGL;
+class TextureSourceD3D9;
 class TextureSourceD3D11;
 class TextureSourceBasic;
 class TextureParent;
 class DataTextureSource;
 
 /**
  * A view on a TextureHost where the texture is internally represented as tiles
  * (contrast with a tiled buffer, where each texture is a tile). For iteration by
@@ -82,28 +83,21 @@ public:
   virtual gfx::IntSize GetSize() const = 0;
 
   /**
    * Return the pixel format of this texture
    */
   virtual gfx::SurfaceFormat GetFormat() const { return gfx::FORMAT_UNKNOWN; }
 
   /**
-   * Cast to a TextureSource for the OpenGL backend.
+   * Cast to a TextureSource for for each backend..
    */
   virtual TextureSourceOGL* AsSourceOGL() { return nullptr; }
-
-  /**
-   * Cast to a TextureSource for the D3D11 backend.
-   */
+  virtual TextureSourceD3D9* AsSourceD3D9() { return nullptr; }
   virtual TextureSourceD3D11* AsSourceD3D11() { return nullptr; }
-
-  /**
-   * Cast to a TextureSource for the software backend.
-   */
   virtual TextureSourceBasic* AsSourceBasic() { return nullptr; }
 
   /**
    * Cast to a DataTextureSurce.
    */
   virtual DataTextureSource* AsDataTextureSource() { return nullptr; }
 
   /**
--- a/gfx/layers/composite/ThebesLayerComposite.cpp
+++ b/gfx/layers/composite/ThebesLayerComposite.cpp
@@ -24,82 +24,83 @@
 
 namespace mozilla {
 namespace layers {
 
 ThebesLayerComposite::ThebesLayerComposite(LayerManagerComposite *aManager)
   : ThebesLayer(aManager, nullptr)
   , LayerComposite(aManager)
   , mBuffer(nullptr)
+  , mRequiresTiledProperties(false)
 {
   MOZ_COUNT_CTOR(ThebesLayerComposite);
   mImplData = static_cast<LayerComposite*>(this);
 }
 
 ThebesLayerComposite::~ThebesLayerComposite()
 {
   MOZ_COUNT_DTOR(ThebesLayerComposite);
-  if (mBuffer) {
-    mBuffer->Detach();
-  }
+  CleanupResources();
 }
 
 void
 ThebesLayerComposite::SetCompositableHost(CompositableHost* aHost)
 {
-  mBuffer= static_cast<ContentHost*>(aHost);
+  mBuffer = static_cast<ContentHost*>(aHost);
 }
 
 void
 ThebesLayerComposite::Disconnect()
 {
   Destroy();
 }
 
 void
 ThebesLayerComposite::Destroy()
 {
   if (!mDestroyed) {
-    if (mBuffer) {
-      mBuffer->Detach();
-    }
-    mBuffer = nullptr;
+    CleanupResources();
     mDestroyed = true;
   }
 }
 
 Layer*
 ThebesLayerComposite::GetLayer()
 {
   return this;
 }
 
 TiledLayerComposer*
 ThebesLayerComposite::GetTiledLayerComposer()
 {
+  MOZ_ASSERT(mBuffer && mBuffer->IsAttached());
   return mBuffer->AsTiledLayerComposer();
 }
 
 LayerRenderState
 ThebesLayerComposite::GetRenderState()
 {
-  if (!mBuffer || mDestroyed) {
+  if (!mBuffer || !mBuffer->IsAttached() || mDestroyed) {
     return LayerRenderState();
   }
   return mBuffer->GetRenderState();
 }
 
 void
 ThebesLayerComposite::RenderLayer(const nsIntPoint& aOffset,
                                   const nsIntRect& aClipRect)
 {
-  if (!mBuffer) {
+  if (!mBuffer || !mBuffer->IsAttached()) {
     return;
   }
 
+  MOZ_ASSERT(mBuffer->GetCompositor() == mCompositeManager->GetCompositor() &&
+             mBuffer->GetLayer() == this,
+             "buffer is corrupted");
+
   gfx::Matrix4x4 transform;
   ToMatrix4x4(GetEffectiveTransform(), transform);
   gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
 
 #ifdef MOZ_DUMP_PAINTING
   if (gfxUtils::sDumpPainting) {
     nsRefPtr<gfxImageSurface> surf = mBuffer->GetAsSurface();
     WriteSnapshotToDumpFile(this, surf);
@@ -140,24 +141,29 @@ ThebesLayerComposite::RenderLayer(const 
     mValidRegion = tiledLayerProps.mValidRegion;
   }
 
   LayerManagerComposite::RemoveMaskEffect(mMaskLayer);
   mCompositeManager->GetCompositor()->MakeCurrent();
 }
 
 CompositableHost*
-ThebesLayerComposite::GetCompositableHost() {
-  return mBuffer.get();
+ThebesLayerComposite::GetCompositableHost()
+{
+  if (mBuffer->IsAttached()) {
+    return mBuffer.get();
+  }
+
+  return nullptr;
 }
 
 void
 ThebesLayerComposite::CleanupResources()
 {
-  if (mBuffer)  {
+  if (mBuffer) {
     mBuffer->Detach();
   }
   mBuffer = nullptr;
 }
 
 gfxSize
 ThebesLayerComposite::GetEffectiveResolution()
 {
@@ -278,17 +284,17 @@ ThebesLayerComposite::GetCompositionBoun
 }
 
 #ifdef MOZ_LAYERS_HAVE_LOG
 nsACString&
 ThebesLayerComposite::PrintInfo(nsACString& aTo, const char* aPrefix)
 {
   ThebesLayer::PrintInfo(aTo, aPrefix);
   aTo += "\n";
-  if (mBuffer) {
+  if (mBuffer && mBuffer->IsAttached()) {
     nsAutoCString pfx(aPrefix);
     pfx += "  ";
     mBuffer->PrintInfo(aTo, pfx.get());
   }
   return aTo;
 }
 #endif
 
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -314,16 +314,17 @@ CompositorD3D11::Initialize()
   return true;
 }
 
 TextureFactoryIdentifier
 CompositorD3D11::GetTextureFactoryIdentifier()
 {
   TextureFactoryIdentifier ident;
   ident.mMaxTextureSize = GetMaxTextureSize();
+  ident.mParentProcessId = XRE_GetProcessType();
   ident.mParentBackend = LAYERS_D3D11;
   return ident;
 }
 
 bool
 CompositorD3D11::CanUseCanvasLayerForSize(const gfxIntSize& aSize)
 {
   int32_t maxTextureSize = GetMaxTextureSize();
@@ -561,49 +562,57 @@ CompositorD3D11::DrawQuad(const gfx::Rec
 
 void
 CompositorD3D11::BeginFrame(const Rect* aClipRectIn,
                             const gfxMatrix& aTransform,
                             const Rect& aRenderBounds,
                             Rect* aClipRectOut,
                             Rect* aRenderBoundsOut)
 {
-  VerifyBufferSize();
   UpdateRenderTarget();
 
-  nsIntRect rect;
-  mWidget->GetClientBounds(rect);
-
-  if (rect.IsEmpty()) {
+  if (mSize.width == 0 || mSize.height == 0) {
     *aRenderBoundsOut = Rect();
     return;
   }
 
-  mDefaultRT->SetSize(IntSize(rect.width, rect.height));
-
   mContext->IASetInputLayout(mAttachments->mInputLayout);
 
   ID3D11Buffer* buffer = mAttachments->mVertexBuffer;
   UINT size = sizeof(Vertex);
   UINT offset = 0;
   mContext->IASetVertexBuffers(0, 1, &buffer, &size, &offset);
-  SetRenderTarget(mDefaultRT);
 
   if (aClipRectOut) {
-    *aClipRectOut = Rect(0, 0, rect.width, rect.height);
+    *aClipRectOut = Rect(0, 0, mSize.width, mSize.height);
   }
   if (aRenderBoundsOut) {
-    *aRenderBoundsOut = Rect(0, 0, rect.width, rect.height);
+    *aRenderBoundsOut = Rect(0, 0, mSize.width, mSize.height);
   }
 
+  D3D11_RECT scissor;
+  if (aClipRectIn) {
+    scissor.left = aClipRectIn->x;
+    scissor.right = aClipRectIn->XMost();
+    scissor.top = aClipRectIn->y;
+    scissor.bottom = aClipRectIn->YMost();
+  } else {
+    scissor.left = scissor.top = 0;
+    scissor.right = mSize.width;
+    scissor.bottom = mSize.height;
+  }
+  mContext->RSSetScissorRects(1, &scissor);
+
   FLOAT black[] = { 0, 0, 0, 0 };
   mContext->ClearRenderTargetView(mDefaultRT->mRTView, black);
 
   mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
   mContext->RSSetState(mAttachments->mRasterizerState);
+
+  SetRenderTarget(mDefaultRT);
 }
 
 void
 CompositorD3D11::EndFrame()
 {
   mContext->Flush();
   mSwapChain->Present(0, 0);
 
@@ -635,83 +644,84 @@ CompositorD3D11::PrepareViewport(const g
   viewMatrix = aWorldTransform * viewMatrix;
 
   gfx3DMatrix projection = gfx3DMatrix::From2D(viewMatrix);
   projection._33 = 0.0f;
 
   memcpy(&mVSConstants.projection, &projection, sizeof(mVSConstants.projection));
 }
 
-const nsIntSize&
-CompositorD3D11::GetWidgetSize()
+void
+CompositorD3D11::EnsureSize()
 {
   nsIntRect rect;
   mWidget->GetClientBounds(rect);
 
   mSize = rect.Size();
-
-  return mSize;
 }
 
 void
 CompositorD3D11::VerifyBufferSize()
 {
-  nsIntRect rect;
-  mWidget->GetClientBounds(rect);
-
   DXGI_SWAP_CHAIN_DESC swapDesc;
   mSwapChain->GetDesc(&swapDesc);
 
-  if ((swapDesc.BufferDesc.Width == rect.width &&
-      swapDesc.BufferDesc.Height == rect.height) || rect.IsEmpty()) {
+  if ((swapDesc.BufferDesc.Width == mSize.width &&
+       swapDesc.BufferDesc.Height == mSize.height) ||
+      mSize.width == 0 || mSize.height == 0) {
     return;
   }
 
   mDefaultRT = nullptr;
 
   if (gfxWindowsPlatform::IsOptimus()) {
-    mSwapChain->ResizeBuffers(1, rect.width, rect.height,
+    mSwapChain->ResizeBuffers(1, mSize.width, mSize.height,
                               DXGI_FORMAT_B8G8R8A8_UNORM,
                               0);
+#ifdef MOZ_METRO
   } else if (IsRunningInWindowsMetro()) {
-    mSwapChain->ResizeBuffers(2, rect.width, rect.height,
+    mSwapChain->ResizeBuffers(2, mSize.width, mSize.height,
                               DXGI_FORMAT_B8G8R8A8_UNORM,
                               0);
+#endif
   } else {
-    mSwapChain->ResizeBuffers(1, rect.width, rect.height,
+    mSwapChain->ResizeBuffers(1, mSize.width, mSize.height,
                               DXGI_FORMAT_B8G8R8A8_UNORM,
                               DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE);
   }
 }
 
 void
 CompositorD3D11::UpdateRenderTarget()
 {
+  EnsureSize();
+  VerifyBufferSize();
+
   if (mDefaultRT) {
     return;
   }
 
   HRESULT hr;
 
   nsRefPtr<ID3D11Texture2D> backBuf;
 
   hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)backBuf.StartAssignment());
   if (FAILED(hr)) {
     return;
   }
 
   mDefaultRT = new CompositingRenderTargetD3D11(backBuf);
+  mDefaultRT->SetSize(mSize);
 }
 
 bool
 CompositorD3D11::CreateShaders()
 {
   HRESULT hr;
 
-
   hr = mDevice->CreateVertexShader(LayerQuadVS,
                                    sizeof(LayerQuadVS),
                                    nullptr,
                                    byRef(mAttachments->mVSQuadShader[MaskNone]));
   if (FAILED(hr)) {
     return false;
   }
 
@@ -819,16 +829,16 @@ CompositorD3D11::PaintToTarget()
 
   nsRefPtr<gfxImageSurface> tmpSurface =
     new gfxImageSurface((unsigned char*)map.pData,
                         gfxIntSize(bbDesc.Width, bbDesc.Height),
                         map.RowPitch,
                         gfxASurface::ImageFormatARGB32);
 
   mTarget->SetSource(tmpSurface);
-  mTarget->SetOperator(gfxContext::OPERATOR_OVER);
+  mTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
   mTarget->Paint();
 
   mContext->Unmap(readTexture, 0);
 }
 
 }
 }
--- a/gfx/layers/d3d11/CompositorD3D11.h
+++ b/gfx/layers/d3d11/CompositorD3D11.h
@@ -132,21 +132,30 @@ public:
 
 #ifdef MOZ_DUMP_PAINTING
   virtual const char* Name() const MOZ_OVERRIDE { return "Direct3D 11"; }
 #endif
 
   virtual void NotifyLayersTransaction() MOZ_OVERRIDE { }
 
   virtual nsIWidget* GetWidget() const MOZ_OVERRIDE { return mWidget; }
-  virtual const nsIntSize& GetWidgetSize() MOZ_OVERRIDE;
+  virtual const nsIntSize& GetWidgetSize() MOZ_OVERRIDE
+  {
+    NS_ASSERTION(false, "Getting the widget size on windows causes some kind of resizing of buffers. "
+                        "You should not do that outside of BeginFrame, so the best we can do is return "
+                        "the last size we got, that might not be up to date. So you probably shouldn't "
+                        "use this method.");
+    return mSize;
+  }
 
   ID3D11Device* GetDevice() { return mDevice; }
 
 private:
+  // ensure mSize is up to date with respect to mWidget
+  void EnsureSize();
   void VerifyBufferSize();
   void UpdateRenderTarget();
   bool CreateShaders();
   void UpdateConstantBuffers();
   void SetSamplerForFilter(gfx::Filter aFilter);
   void SetPSForEffect(Effect *aEffect, MaskType aMaskType);
   void PaintToTarget();
 
@@ -156,19 +165,17 @@ private:
   RefPtr<CompositingRenderTargetD3D11> mDefaultRT;
   RefPtr<CompositingRenderTargetD3D11> mCurrentRT;
 
   DeviceAttachmentsD3D11* mAttachments;
 
   nsRefPtr<gfxContext> mTarget;
 
   nsIWidget* mWidget;
-  // GetWidgetSize requires us to return a reference to an nsIntSize. Since we
-  // don't otherwise keep this value around, we need mSize to avoid a dangling
-  // reference problem.
+
   nsIntSize mSize;
 
   HWND mHwnd;
 
   D3D_FEATURE_LEVEL mFeatureLevel;
 
   VertexShaderConstants mVSConstants;
   PixelShaderConstants mPSConstants;
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -72,27 +72,27 @@ DeprecatedTextureClientD3D11::Deprecated
 
 DeprecatedTextureClientD3D11::~DeprecatedTextureClientD3D11()
 {
   mDescriptor = SurfaceDescriptor();
 
   ClearDT();
 }
 
-void
+bool
 DeprecatedTextureClientD3D11::EnsureAllocated(gfx::IntSize aSize,
                                               gfxASurface::gfxContentType aType)
 {
   D3D10_TEXTURE2D_DESC desc;
 
   if (mTexture) {
     mTexture->GetDesc(&desc);
 
     if (desc.Width == aSize.width && desc.Height == aSize.height) {
-      return;
+      return true;
     }
 
     mTexture = nullptr;
     mSurface = nullptr;
     ClearDT();
   }
 
   mSize = aSize;
@@ -104,33 +104,34 @@ DeprecatedTextureClientD3D11::EnsureAllo
                                 D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE);
 
   newDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX;
 
   HRESULT hr = device->CreateTexture2D(&newDesc, nullptr, byRef(mTexture));
 
   if (FAILED(hr)) {
     LOGD3D11("Error creating texture for client!");
-    return;
+    return false;
   }
 
   RefPtr<IDXGIResource> resource;
   mTexture->QueryInterface((IDXGIResource**)byRef(resource));
 
   HANDLE sharedHandle;
   hr = resource->GetSharedHandle(&sharedHandle);
 
   if (FAILED(hr)) {
     LOGD3D11("Error getting shared handle for texture.");
   }
 
   mDescriptor = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle,
                                        aType == gfxASurface::CONTENT_COLOR_ALPHA);
 
   mContentType = aType;
+  return true;
 }
 
 gfxASurface*
 DeprecatedTextureClientD3D11::LockSurface()
 {
   EnsureSurface();
 
   LockTexture();
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -72,17 +72,17 @@ public:
                                const TextureInfo& aTextureInfo);
   virtual ~DeprecatedTextureClientD3D11();
 
   virtual bool SupportsType(DeprecatedTextureClientType aType) MOZ_OVERRIDE
   {
     return aType == TEXTURE_CONTENT;
   }
 
-  virtual void EnsureAllocated(gfx::IntSize aSize,
+  virtual bool EnsureAllocated(gfx::IntSize aSize,
                                gfxASurface::gfxContentType aType) MOZ_OVERRIDE;
 
   virtual gfxASurface* LockSurface() MOZ_OVERRIDE;
   virtual gfx::DrawTarget* LockDrawTarget() MOZ_OVERRIDE;
   virtual void Unlock() MOZ_OVERRIDE;
 
   virtual void SetDescriptor(const SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE;
   virtual gfxASurface::gfxContentType GetContentType() MOZ_OVERRIDE
--- a/gfx/layers/d3d9/ColorLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ColorLayerD3D9.cpp
@@ -41,17 +41,17 @@ RenderColorLayerD3D9(ColorLayer* aLayer,
   float opacity = aLayer->GetEffectiveOpacity() * layerColor.a;
   // output color is premultiplied, so we need to adjust all channels.
   // mColor is not premultiplied.
   color[0] = (float)(layerColor.r * opacity);
   color[1] = (float)(layerColor.g * opacity);
   color[2] = (float)(layerColor.b * opacity);
   color[3] = (float)(opacity);
 
-  aManager->device()->SetPixelShaderConstantF(0, color, 1);
+  aManager->device()->SetPixelShaderConstantF(CBvColor, color, 1);
 
   aManager->SetShaderMode(DeviceManagerD3D9::SOLIDCOLORLAYER,
                           aLayer->GetMaskLayer());
 
   aManager->device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
 }
 
 void
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/CompositorD3D9.cpp
@@ -0,0 +1,592 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * 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 "CompositorD3D9.h"
+#include "LayerManagerD3D9Shaders.h"
+#include "gfxWindowsPlatform.h"
+#include "nsIWidget.h"
+#include "mozilla/layers/ImageHost.h"
+#include "mozilla/layers/ContentHost.h"
+#include "mozilla/layers/Effects.h"
+#include "nsWindowsHelpers.h"
+#include "Nv3DVUtils.h"
+#include "gfxFailure.h"
+
+using namespace mozilla::gfx;
+
+namespace mozilla {
+namespace layers {
+
+CompositorD3D9::CompositorD3D9(nsIWidget *aWidget)
+  : mWidget(aWidget)
+{
+  sBackend = LAYERS_D3D9;
+}
+
+CompositorD3D9::~CompositorD3D9()
+{
+  mSwapChain = nullptr;
+  mDeviceManager = nullptr;
+}
+
+bool
+CompositorD3D9::Initialize()
+{
+  if (!gfxPlatform::CanUseDirect3D9()) {
+    NS_WARNING("Direct3D 9-accelerated layers are not supported on this system.");
+    return false;
+  }
+
+  mDeviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
+  if (!mDeviceManager) {
+    return false;
+  }
+
+  mSwapChain = mDeviceManager->
+    CreateSwapChain((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW));
+
+  if (!mSwapChain) {
+    return false;
+  }
+
+  return true;
+}
+
+TextureFactoryIdentifier
+CompositorD3D9::GetTextureFactoryIdentifier()
+{
+  TextureFactoryIdentifier ident;
+  ident.mMaxTextureSize = GetMaxTextureSize();
+  ident.mParentBackend = LAYERS_D3D9;
+  ident.mParentProcessId = XRE_GetProcessType();
+  return ident;
+}
+
+bool
+CompositorD3D9::CanUseCanvasLayerForSize(const gfxIntSize &aSize)
+{
+  int32_t maxTextureSize = GetMaxTextureSize();
+
+  if (aSize.width > maxTextureSize || aSize.height > maxTextureSize) {
+    return false;
+  }
+
+  return true;
+}
+
+int32_t
+CompositorD3D9::GetMaxTextureSize() const
+{
+  return mDeviceManager->GetMaxTextureSize();
+}
+
+TemporaryRef<CompositingRenderTarget>
+CompositorD3D9::CreateRenderTarget(const gfx::IntRect &aRect,
+                                   SurfaceInitMode aInit)
+{
+  RefPtr<IDirect3DTexture9> texture;
+  HRESULT hr = device()->CreateTexture(aRect.width, aRect.height, 1,
+                                       D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
+                                       D3DPOOL_DEFAULT, byRef(texture),
+                                       NULL);
+  if (FAILED(hr)) {
+    ReportFailure(NS_LITERAL_CSTRING("CompositorD3D9::CreateRenderTarget: Failed to create texture"),
+                  hr);
+    return nullptr;
+  }
+
+  RefPtr<CompositingRenderTargetD3D9> rt =
+    new CompositingRenderTargetD3D9(texture, aInit, IntSize(aRect.width, aRect.height));
+
+  return rt;
+}
+
+TemporaryRef<CompositingRenderTarget>
+CompositorD3D9::CreateRenderTargetFromSource(const gfx::IntRect &aRect,
+                                             const CompositingRenderTarget *aSource)
+{
+  RefPtr<IDirect3DTexture9> texture;
+  HRESULT hr = device()->CreateTexture(aRect.width, aRect.height, 1,
+                                       D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
+                                       D3DPOOL_DEFAULT, byRef(texture),
+                                       NULL);
+  if (FAILED(hr)) {
+    ReportFailure(NS_LITERAL_CSTRING("CompositorD3D9::CreateRenderTargetFromSource: Failed to create texture"),
+                  hr);
+    return nullptr;
+  }
+
+  if (aSource) {
+    nsRefPtr<IDirect3DSurface9> sourceSurface =
+      static_cast<const CompositingRenderTargetD3D9*>(aSource)->GetD3D9Surface();
+
+    nsRefPtr<IDirect3DSurface9> destSurface;
+    hr = texture->GetSurfaceLevel(0, getter_AddRefs(destSurface));
+    if (FAILED(hr)) {
+      NS_WARNING("Failed to get texture surface level for dest.");
+    }
+
+    if (sourceSurface && destSurface) {
+      RECT sourceRect;
+      sourceRect.left = aRect.x;
+      sourceRect.right = aRect.XMost();
+      sourceRect.top = aRect.y;
+      sourceRect.bottom = aRect.YMost();
+      RECT destRect;
+      destRect.left = 0;
+      destRect.right = aRect.width;
+      destRect.top = 0;
+      destRect.bottom = aRect.height;
+
+      // copy the source to the dest
+      hr = device()->StretchRect(sourceSurface,
+                                 &sourceRect,
+                                 destSurface,
+                                 &destRect,
+                                 D3DTEXF_NONE);
+      if (FAILED(hr)) {
+        ReportFailure(NS_LITERAL_CSTRING("CompositorD3D9::CreateRenderTargetFromSource: Failed to update texture"),
+                      hr);
+      }
+    }
+  }
+
+  RefPtr<CompositingRenderTargetD3D9> rt =
+    new CompositingRenderTargetD3D9(texture,
+                                    INIT_MODE_NONE,
+                                    IntSize(aRect.width, aRect.height));
+
+  return rt;
+}
+
+void
+CompositorD3D9::SetRenderTarget(CompositingRenderTarget *aRenderTarget)
+{
+  MOZ_ASSERT(aRenderTarget);
+  RefPtr<CompositingRenderTargetD3D9> oldRT = mCurrentRT;
+  mCurrentRT = static_cast<CompositingRenderTargetD3D9*>(aRenderTarget);
+  mCurrentRT->BindRenderTarget(device());
+  PrepareViewport(mCurrentRT->GetSize(), gfxMatrix());
+}
+
+static DeviceManagerD3D9::ShaderMode
+ShaderModeForEffectType(EffectTypes aEffectType)
+{
+  switch (aEffectType) {
+  case EFFECT_SOLID_COLOR:
+    return DeviceManagerD3D9::SOLIDCOLORLAYER;
+  case EFFECT_BGRA:
+  case EFFECT_RENDER_TARGET:
+    return DeviceManagerD3D9::RGBALAYER;
+  case EFFECT_BGRX:
+    return DeviceManagerD3D9::RGBLAYER;
+  case EFFECT_YCBCR:
+    return DeviceManagerD3D9::YCBCRLAYER;
+  }
+
+  MOZ_CRASH("Bad effect type");
+}
+
+void
+CompositorD3D9::DrawQuad(const gfx::Rect &aRect, const gfx::Rect &aClipRect,
+                         const EffectChain &aEffectChain,
+                         gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform,
+                         const gfx::Point &aOffset)
+{
+  MOZ_ASSERT(mCurrentRT, "No render target");
+  device()->SetVertexShaderConstantF(CBmLayerTransform, &aTransform._11, 4);
+
+  float renderTargetOffset[] = { aOffset.x, aOffset.y, 0, 0 };
+  device()->SetVertexShaderConstantF(CBvRenderTargetOffset,
+                                     renderTargetOffset,
+                                     1);
+  device()->SetVertexShaderConstantF(CBvLayerQuad,
+                                     ShaderConstantRect(aRect.x,
+                                                        aRect.y,
+                                                        aRect.width,
+                                                        aRect.height),
+                                     1);
+  bool target = false;
+
+  if (aEffectChain.mPrimaryEffect->mType != EFFECT_SOLID_COLOR) {
+    float opacity[4];
+    /*
+     * We always upload a 4 component float, but the shader will use only the
+     * first component since it's declared as a 'float'.
+     */
+    opacity[0] = aOpacity;
+    device()->SetPixelShaderConstantF(CBfLayerOpacity, opacity, 1);
+  }
+
+  bool isPremultiplied = true;
+
+  MaskType maskType = MaskNone;
+
+  if (aEffectChain.mSecondaryEffects[EFFECT_MASK]) {
+    if (aTransform.Is2D()) {
+      maskType = Mask2d;
+    } else {
+      maskType = Mask3d;
+    }
+  }
+
+  RECT scissor;
+  scissor.left = aClipRect.x;
+  scissor.right = aClipRect.XMost();
+  scissor.top = aClipRect.y;
+  scissor.bottom = aClipRect.YMost();
+  device()->SetScissorRect(&scissor);
+
+  uint32_t maskTexture = 0;
+  switch (aEffectChain.mPrimaryEffect->mType) {
+  case EFFECT_SOLID_COLOR:
+    {
+      // output color is premultiplied, so we need to adjust all channels.
+      Color layerColor =
+        static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get())->mColor;
+      float color[4];
+      color[0] = layerColor.r * layerColor.a * aOpacity;
+      color[1] = layerColor.g * layerColor.a * aOpacity;
+      color[2] = layerColor.b * layerColor.a * aOpacity;
+      color[3] = layerColor.a * aOpacity;
+
+      device()->SetPixelShaderConstantF(CBvColor, color, 1);
+
+      maskTexture = mDeviceManager
+        ->SetShaderMode(DeviceManagerD3D9::SOLIDCOLORLAYER, maskType);
+    }
+    break;
+  case EFFECT_RENDER_TARGET:
+  case EFFECT_BGRX:
+  case EFFECT_BGRA:
+    {
+      TexturedEffect* texturedEffect =
+        static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
+
+      Rect textureCoords = texturedEffect->mTextureCoords;
+      device()->SetVertexShaderConstantF(CBvTextureCoords,
+                                         ShaderConstantRect(
+                                           textureCoords.x,
+                                           textureCoords.y,
+                                           textureCoords.width,
+                                           textureCoords.height),
+                                         1);
+
+      SetSamplerForFilter(texturedEffect->mFilter);
+
+      TextureSourceD3D9* source = texturedEffect->mTexture->AsSourceD3D9();
+      device()->SetTexture(0, source->GetD3D9Texture());
+
+      maskTexture = mDeviceManager
+        ->SetShaderMode(ShaderModeForEffectType(aEffectChain.mPrimaryEffect->mType),
+                        maskType);
+
+      isPremultiplied = texturedEffect->mPremultiplied;
+    }
+    break;
+  case EFFECT_YCBCR:
+    {
+      EffectYCbCr* ycbcrEffect =
+        static_cast<EffectYCbCr*>(aEffectChain.mPrimaryEffect.get());
+
+      SetSamplerForFilter(FILTER_LINEAR);
+
+      Rect textureCoords = ycbcrEffect->mTextureCoords;
+      device()->SetVertexShaderConstantF(CBvTextureCoords,
+                                         ShaderConstantRect(
+                                           textureCoords.x,
+                                           textureCoords.y,
+                                           textureCoords.width,
+                                           textureCoords.height),
+                                         1);
+                                    
+      TextureSourceD3D9* source = ycbcrEffect->mTexture->AsSourceD3D9();
+      TextureSourceD3D9::YCbCrTextures textures = source->GetYCbCrTextures();
+
+      /*
+       * Send 3d control data and metadata
+       */
+      if (mDeviceManager->GetNv3DVUtils()) {
+        Nv_Stereo_Mode mode;
+        switch (textures.mStereoMode) {
+        case STEREO_MODE_LEFT_RIGHT:
+          mode = NV_STEREO_MODE_LEFT_RIGHT;
+          break;
+        case STEREO_MODE_RIGHT_LEFT:
+          mode = NV_STEREO_MODE_RIGHT_LEFT;
+          break;
+        case STEREO_MODE_BOTTOM_TOP:
+          mode = NV_STEREO_MODE_BOTTOM_TOP;
+          break;
+        case STEREO_MODE_TOP_BOTTOM:
+          mode = NV_STEREO_MODE_TOP_BOTTOM;
+          break;
+        case STEREO_MODE_MONO:
+          mode = NV_STEREO_MODE_MONO;
+          break;
+        }
+
+        // Send control data even in mono case so driver knows to leave stereo mode.
+        mDeviceManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE);
+
+        if (textures.mStereoMode != STEREO_MODE_MONO) {
+          mDeviceManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE);
+
+          nsRefPtr<IDirect3DSurface9> renderTarget;
+          device()->GetRenderTarget(0, getter_AddRefs(renderTarget));
+          mDeviceManager->GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)aRect.width,
+                                                             (unsigned int)aRect.height,
+                                                             (HANDLE)(textures.mY),
+                                                             (HANDLE)(renderTarget));
+        }
+      }
+
+      // Linear scaling is default here, adhering to mFilter is difficult since
+      // presumably even with point filtering we'll still want chroma upsampling
+      // to be linear. In the current approach we can't.
+      device()->SetTexture(0, textures.mY);
+      device()->SetTexture(1, textures.mCb);
+      device()->SetTexture(2, textures.mCr);
+      maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER, maskType);
+    }
+    break;
+  case EFFECT_COMPONENT_ALPHA:
+    {
+      EffectComponentAlpha* effectComponentAlpha =
+        static_cast<EffectComponentAlpha*>(aEffectChain.mPrimaryEffect.get());
+      TextureSourceD3D9* sourceOnWhite = effectComponentAlpha->mOnWhite->AsSourceD3D9();
+      TextureSourceD3D9* sourceOnBlack = effectComponentAlpha->mOnBlack->AsSourceD3D9();
+
+      Rect textureCoords = effectComponentAlpha->mTextureCoords;
+      device()->SetVertexShaderConstantF(CBvTextureCoords,
+                                         ShaderConstantRect(
+                                           textureCoords.x,
+                                           textureCoords.y,
+                                           textureCoords.width,
+                                           textureCoords.height),
+                                          1);
+
+      SetSamplerForFilter(effectComponentAlpha->mFilter);
+      SetMask(aEffectChain, maskTexture);
+
+      maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::COMPONENTLAYERPASS1, maskType);
+      device()->SetTexture(0, sourceOnBlack->GetD3D9Texture());
+      device()->SetTexture(1, sourceOnWhite->GetD3D9Texture());
+      device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
+      device()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
+      device()->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+      device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+
+      maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::COMPONENTLAYERPASS2, maskType);
+      device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
+      device()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
+      device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+
+      // Restore defaults
+      device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
+      device()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
+      device()->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
+      device()->SetTexture(1, NULL);
+    }
+    return;
+  default:
+    NS_WARNING("Unknown shader type");
+    return;
+  }
+
+  SetMask(aEffectChain, maskTexture);
+
+  if (!isPremultiplied) {
+    device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
+    device()->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+  }
+
+  HRESULT hr = device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+
+  if (!isPremultiplied) {
+    device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
+    device()->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
+  }
+}
+
+void
+CompositorD3D9::SetMask(const EffectChain &aEffectChain, uint32_t aMaskTexture)
+{
+  EffectMask *maskEffect =
+    static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EFFECT_MASK].get());
+  if (!maskEffect) {
+    return;
+  }
+
+  TextureSourceD3D9 *source = maskEffect->mMaskTexture->AsSourceD3D9();
+
+  MOZ_ASSERT(aMaskTexture >= 0);
+  device()->SetTexture(aMaskTexture, source->GetD3D9Texture());
+
+  const gfx::Matrix4x4& maskTransform = maskEffect->mMaskTransform;
+  NS_ASSERTION(maskTransform.Is2D(), "How did we end up with a 3D transform here?!");
+  Rect bounds = Rect(Point(), Size(maskEffect->mSize));
+  bounds = maskTransform.As2D().TransformBounds(bounds);
+
+  device()->SetVertexShaderConstantF(DeviceManagerD3D9::sMaskQuadRegister, 
+                                     ShaderConstantRect(bounds.x,
+                                                        bounds.y,
+                                                        bounds.width,
+                                                        bounds.height),
+                                     1);
+}
+
+void
+CompositorD3D9::BeginFrame(const Rect *aClipRectIn,
+                           const gfxMatrix& aTransform,
+                           const Rect& aRenderBounds,
+                           Rect *aClipRectOut,
+                           Rect *aRenderBoundsOut)
+{
+  if (!mSwapChain->PrepareForRendering()) {
+    return;
+  }
+  mDeviceManager->SetupRenderState();
+
+  EnsureSize();
+
+  device()->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 0, 0);
+  device()->BeginScene();
+
+  if (aClipRectOut) {
+    *aClipRectOut = Rect(0, 0, mSize.width, mSize.height);
+  }
+  if (aRenderBoundsOut) {
+    *aRenderBoundsOut = Rect(0, 0, mSize.width, mSize.height);
+  }
+
+  RECT r;
+  if (aClipRectIn) {
+    r.left = (LONG)aClipRectIn->x;
+    r.top = (LONG)aClipRectIn->y;
+    r.right = (LONG)(aClipRectIn->x + aClipRectIn->width);
+    r.bottom = (LONG)(aClipRectIn->y + aClipRectIn->height);
+  } else {
+    r.left = r.top = 0;
+    r.right = mSize.width;
+    r.bottom = mSize.height;
+  }
+  device()->SetScissorRect(&r);
+
+  nsRefPtr<IDirect3DSurface9> backBuffer = mSwapChain->GetBackBuffer();
+  mDefaultRT = new CompositingRenderTargetD3D9(backBuffer,
+                                               INIT_MODE_CLEAR,
+                                               IntSize(mSize.width, mSize.height));
+  SetRenderTarget(mDefaultRT);
+}
+
+void
+CompositorD3D9::EndFrame()
+{
+  device()->EndScene();
+
+  if (!!mTarget) {
+    PaintToTarget();
+  } else {
+    mSwapChain->Present();
+  }
+
+  mCurrentRT = nullptr;
+}
+
+void
+CompositorD3D9::PrepareViewport(const gfx::IntSize& aSize,
+                                const gfxMatrix &aWorldTransform)
+{
+  gfx3DMatrix viewMatrix;
+  /*
+   * Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
+   * <1.0, -1.0> bottomright)
+   */
+  viewMatrix._11 = 2.0f / aSize.width;
+  viewMatrix._22 = -2.0f / aSize.height;
+  viewMatrix._41 = -1.0f;
+  viewMatrix._42 = 1.0f;
+
+  viewMatrix = gfx3DMatrix::From2D(aWorldTransform) * viewMatrix;
+
+  HRESULT hr = device()->SetVertexShaderConstantF(CBmProjection, &viewMatrix._11, 4);
+
+  if (FAILED(hr)) {
+    NS_WARNING("Failed to set projection matrix");
+  }
+}
+
+void
+CompositorD3D9::EnsureSize()
+{
+  nsIntRect rect;
+  mWidget->GetClientBounds(rect);
+
+  mSize = rect.Size();
+}
+
+void
+CompositorD3D9::SetSamplerForFilter(Filter aFilter)
+{
+  switch (aFilter) {
+  case FILTER_LINEAR:
+    device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+    device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+    return;
+  case FILTER_POINT:
+    device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+    device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+    return;
+  default:
+    device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+    device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+  }
+}
+
+void
+CompositorD3D9::PaintToTarget()
+{
+  nsRefPtr<IDirect3DSurface9> backBuff;
+  nsRefPtr<IDirect3DSurface9> destSurf;
+  device()->GetRenderTarget(0, getter_AddRefs(backBuff));
+
+  D3DSURFACE_DESC desc;
+  backBuff->GetDesc(&desc);
+
+  device()->CreateOffscreenPlainSurface(desc.Width, desc.Height,
+                                        D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM,
+                                        getter_AddRefs(destSurf), NULL);
+
+  device()->GetRenderTargetData(backBuff, destSurf);
+
+  D3DLOCKED_RECT rect;
+  destSurf->LockRect(&rect, NULL, D3DLOCK_READONLY);
+  mTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
+  nsRefPtr<gfxImageSurface> imageSurface =
+    new gfxImageSurface((unsigned char*)rect.pBits,
+                        gfxIntSize(desc.Width, desc.Height),
+                        rect.Pitch,
+                        gfxASurface::ImageFormatARGB32);
+  mTarget->SetSource(imageSurface);
+  mTarget->Paint();
+  destSurf->UnlockRect();
+}
+
+void
+CompositorD3D9::ReportFailure(const nsACString &aMsg, HRESULT aCode)
+{
+  // We could choose to abort here when hr == E_OUTOFMEMORY.
+  nsCString msg;
+  msg.Append(aMsg);
+  msg.AppendLiteral(" Error code: ");
+  msg.AppendInt(uint32_t(aCode));
+  NS_WARNING(msg.BeginReading());
+
+  gfx::LogFailure(msg);
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/CompositorD3D9.h
@@ -0,0 +1,142 @@
+/* -*- 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 MOZILLA_GFX_COMPOSITORD3D9_H
+#define MOZILLA_GFX_COMPOSITORD3D9_H
+
+#include "mozilla/layers/Compositor.h"
+#include "mozilla/layers/TextureD3D9.h"
+#include "DeviceManagerD3D9.h"
+
+class nsWidget;
+
+namespace mozilla {
+namespace layers {
+
+class CompositorD3D9 : public Compositor
+{
+public:
+  CompositorD3D9(nsIWidget *aWidget);
+  ~CompositorD3D9();
+
+  virtual bool Initialize() MOZ_OVERRIDE;
+  virtual void Destroy() MOZ_OVERRIDE {}
+
+  virtual TextureFactoryIdentifier
+    GetTextureFactoryIdentifier() MOZ_OVERRIDE;
+
+  virtual bool CanUseCanvasLayerForSize(const gfxIntSize &aSize) MOZ_OVERRIDE;
+  virtual int32_t GetMaxTextureSize() const MOZ_FINAL;
+
+  virtual void SetTargetContext(gfxContext *aTarget) MOZ_OVERRIDE
+  {
+    mTarget = aTarget;
+  }
+
+  virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) MOZ_OVERRIDE {}
+
+  virtual TemporaryRef<CompositingRenderTarget>
+    CreateRenderTarget(const gfx::IntRect &aRect,
+                       SurfaceInitMode aInit) MOZ_OVERRIDE;
+
+  virtual TemporaryRef<CompositingRenderTarget>
+    CreateRenderTargetFromSource(const gfx::IntRect &aRect,
+                                 const CompositingRenderTarget *aSource) MOZ_OVERRIDE;
+
+  virtual void SetRenderTarget(CompositingRenderTarget *aSurface);
+  virtual CompositingRenderTarget* GetCurrentRenderTarget() MOZ_OVERRIDE
+  {
+    return mCurrentRT;
+  }
+
+  virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) MOZ_OVERRIDE {}
+
+  virtual void DrawQuad(const gfx::Rect &aRect, const gfx::Rect &aClipRect,
+                        const EffectChain &aEffectChain,
+                        gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform,
+                        const gfx::Point &aOffset) MOZ_OVERRIDE;
+
+  virtual void BeginFrame(const gfx::Rect *aClipRectIn,
+                          const gfxMatrix& aTransform,
+                          const gfx::Rect& aRenderBounds,
+                          gfx::Rect *aClipRectOut = nullptr,
+                          gfx::Rect *aRenderBoundsOut = nullptr) MOZ_OVERRIDE;
+
+  virtual void EndFrame() MOZ_OVERRIDE;
+
+  virtual void EndFrameForExternalComposition(const gfxMatrix& aTransform) MOZ_OVERRIDE {}
+
+  virtual void AbortFrame() MOZ_OVERRIDE {}
+
+  virtual void PrepareViewport(const gfx::IntSize& aSize,
+                               const gfxMatrix& aWorldTransform) MOZ_OVERRIDE;
+
+  virtual bool SupportsPartialTextureUpdate() MOZ_OVERRIDE{ return true; }
+
+#ifdef MOZ_DUMP_PAINTING
+  virtual const char* Name() const MOZ_OVERRIDE { return "Direct3D9"; }
+#endif
+
+  virtual void NotifyLayersTransaction() MOZ_OVERRIDE {}
+
+  virtual nsIWidget* GetWidget() const MOZ_OVERRIDE { return mWidget; }
+  virtual const nsIntSize& GetWidgetSize() MOZ_OVERRIDE
+  {
+    NS_ASSERTION(false, "Getting the widget size on windows causes some kind of resizing of buffers. "
+                        "You should not do that outside of BeginFrame, so the best we can do is return "
+                        "the last size we got, that might not be up to date. So you probably shouldn't "
+                        "use this method.");
+    return mSize;
+  }
+
+  IDirect3DDevice9* device() const { return mDeviceManager->device(); }
+
+  /**
+   * Declare an offset to use when rendering layers. This will be ignored when
+   * rendering to a target instead of the screen.
+   */
+  virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) MOZ_OVERRIDE
+  {
+    if (aOffset.x || aOffset.y) {
+      NS_RUNTIMEABORT("SetScreenRenderOffset not supported by CompositorD3D9.");
+    }
+    // If the offset is 0, 0 that's okay.
+  }
+
+   virtual TemporaryRef<DataTextureSource>
+     CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE { return nullptr; } 
+private:
+  // ensure mSize is up to date with respect to mWidget
+  void EnsureSize();
+  void SetSamplerForFilter(gfx::Filter aFilter);
+  void PaintToTarget();
+  void SetMask(const EffectChain &aEffectChain, uint32_t aMaskTexture);
+
+  void ReportFailure(const nsACString &aMsg, HRESULT aCode);
+
+  /* Device manager instance for this compositor */
+  nsRefPtr<DeviceManagerD3D9> mDeviceManager;
+
+  /* Swap chain associated with this compositor */
+  nsRefPtr<SwapChainD3D9> mSwapChain;
+
+  /* Widget associated with this layer manager */
+  nsIWidget *mWidget;
+
+  /*
+   * Context target, NULL when drawing directly to our swap chain.
+   */
+  nsRefPtr<gfxContext> mTarget;
+
+  RefPtr<CompositingRenderTargetD3D9> mDefaultRT;
+  RefPtr<CompositingRenderTargetD3D9> mCurrentRT;
+
+  nsIntSize mSize;
+};
+
+}
+}
+
+#endif
--- a/gfx/layers/d3d9/DeviceManagerD3D9.cpp
+++ b/gfx/layers/d3d9/DeviceManagerD3D9.cpp
@@ -7,16 +7,17 @@
 #include "LayerManagerD3D9Shaders.h"
 #include "ThebesLayerD3D9.h"
 #include "nsIServiceManager.h"
 #include "nsIConsoleService.h"
 #include "nsPrintfCString.h"
 #include "Nv3DVUtils.h"
 #include "plstr.h"
 #include <algorithm>
+#include "gfxPlatform.h"
 
 namespace mozilla {
 namespace layers {
 
 const LPCWSTR kClassName       = L"D3D9WindowClass";
 
 #define USE_D3D9EX
 
@@ -73,16 +74,26 @@ SwapChainD3D9::Init(HWND hWnd)
   if (FAILED(hr)) {
     NS_WARNING("Failed to create swap chain for window.");
     return false;
   }
 
   return true;
 }
 
+already_AddRefed<IDirect3DSurface9>
+SwapChainD3D9::GetBackBuffer()
+{
+  nsRefPtr<IDirect3DSurface9> backBuffer;
+    mSwapChain->GetBackBuffer(0,
+                              D3DBACKBUFFER_TYPE_MONO,
+                              getter_AddRefs(backBuffer));
+  return backBuffer.forget();
+}
+
 bool
 SwapChainD3D9::PrepareForRendering()
 {
   RECT r;
   if (!::GetClientRect(mWnd, &r)) {
     return false;
   }
 
@@ -90,20 +101,17 @@ SwapChainD3D9::PrepareForRendering()
     return false;
   }
 
   if (!mSwapChain) {
     Init(mWnd);
   }
 
   if (mSwapChain) {
-    nsRefPtr<IDirect3DSurface9> backBuffer;
-    mSwapChain->GetBackBuffer(0,
-                              D3DBACKBUFFER_TYPE_MONO,
-                              getter_AddRefs(backBuffer));
+    nsRefPtr<IDirect3DSurface9> backBuffer = GetBackBuffer();
 
     D3DSURFACE_DESC desc;
     backBuffer->GetDesc(&desc);
 
     if (desc.Width == r.right - r.left && desc.Height == r.bottom - r.top) {
       mDeviceManager->device()->SetRenderTarget(0, backBuffer);
       return true;
     }
@@ -111,20 +119,17 @@ SwapChainD3D9::PrepareForRendering()
     mSwapChain = nullptr;
     
     Init(mWnd);
     
     if (!mSwapChain) {
       return false;
     }
     
-    mSwapChain->GetBackBuffer(0,
-                              D3DBACKBUFFER_TYPE_MONO,
-                              getter_AddRefs(backBuffer));
-
+    backBuffer = GetBackBuffer();
     mDeviceManager->device()->SetRenderTarget(0, backBuffer);
     
     return true;
   }
   return false;
 }
 
 void
@@ -135,40 +140,46 @@ SwapChainD3D9::Present(const nsIntRect &
   r.top = aRect.y;
   r.right = aRect.XMost();
   r.bottom = aRect.YMost();
 
   mSwapChain->Present(&r, &r, 0, 0, 0);
 }
 
 void
+SwapChainD3D9::Present()
+{
+  mSwapChain->Present(NULL, NULL, 0, 0, 0);
+}
+
+void
 SwapChainD3D9::Reset()
 {
   mSwapChain = nullptr;
 }
 
 #define HAS_CAP(a, b) (((a) & (b)) == (b))
 #define LACKS_CAP(a, b) !(((a) & (b)) == (b))
 
+uint32_t DeviceManagerD3D9::sMaskQuadRegister = 11;
+
 DeviceManagerD3D9::DeviceManagerD3D9()
   : mDeviceResetCount(0)
   , mMaxTextureSize(0)
+  , mTextureAddressingMode(D3DTADDRESS_CLAMP)
   , mHasDynamicTextures(false)
   , mDeviceWasRemoved(false)
 {
 }
 
 DeviceManagerD3D9::~DeviceManagerD3D9()
 {
   LayerManagerD3D9::OnDeviceManagerDestroy(this);
 }
 
-NS_IMPL_ADDREF(DeviceManagerD3D9)
-NS_IMPL_RELEASE(DeviceManagerD3D9)
-
 bool
 DeviceManagerD3D9::Init()
 {
   WNDCLASSW wc;
   HRESULT hr;
 
   if (!GetClassInfoW(GetModuleHandle(nullptr), kClassName, &wc)) {
       ZeroMemory(&wc, sizeof(WNDCLASSW));
@@ -491,22 +502,22 @@ DeviceManagerD3D9::SetupRenderState()
   mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
   mDevice->SetRenderState(D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD);
   mDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
   mDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
   mDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
   mDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
   mDevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
   mDevice->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
-  mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
-  mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
-  mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
-  mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
-  mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
-  mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+  mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, mTextureAddressingMode);
+  mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, mTextureAddressingMode);
+  mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, mTextureAddressingMode);
+  mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, mTextureAddressingMode);
+  mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, mTextureAddressingMode);
+  mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, mTextureAddressingMode);
 }
 
 already_AddRefed<SwapChainD3D9>
 DeviceManagerD3D9::CreateSwapChain(HWND hWnd)
 {
   nsRefPtr<SwapChainD3D9> swapChain = new SwapChainD3D9(this);
   
   // See bug 604647. This line means that if we create a window while the
@@ -528,94 +539,47 @@ DeviceManagerD3D9::CreateSwapChain(HWND 
 /*
   * Finds a texture for the mask layer and sets it as an
   * input to the shaders.
   * Returns true if a texture is loaded, false if 
   * a texture for the mask layer could not be loaded.
   */
 bool
 LoadMaskTexture(Layer* aMask, IDirect3DDevice9* aDevice,
-                uint32_t aMaskQuadTexture, uint32_t aMaskTexRegister)
+                uint32_t aMaskTexRegister)
 {
   gfxIntSize size;
   nsRefPtr<IDirect3DTexture9> texture =
     static_cast<LayerD3D9*>(aMask->ImplData())->GetAsTexture(&size);
   
   if (!texture) {
     return false;
   }
   
   gfxMatrix maskTransform;
   bool maskIs2D = aMask->GetEffectiveTransform().CanDraw2D(&maskTransform);
   NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
   gfxRect bounds = gfxRect(gfxPoint(), size);
   bounds = maskTransform.TransformBounds(bounds);
 
-  aDevice->SetVertexShaderConstantF(aMaskQuadTexture, 
+  aDevice->SetVertexShaderConstantF(DeviceManagerD3D9::sMaskQuadRegister, 
                                     ShaderConstantRect((float)bounds.x,
                                                        (float)bounds.y,
                                                        (float)bounds.width,
                                                        (float)bounds.height),
                                     1);
 
   aDevice->SetTexture(aMaskTexRegister, texture);
   return true;
 }
 
-void
-DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, Layer* aMask, bool aIs2D)
+uint32_t
+DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, MaskType aMaskType)
 {
-  if (aMask) {
-    // register allocations are taken from LayerManagerD3D9Shaders.h after
-    // the shaders are compiled (genshaders.sh)
-    const uint32_t maskQuadRegister = 11;
-    uint32_t maskTexRegister;
-    switch (aMode) {
-      case RGBLAYER:
-        mDevice->SetVertexShader(mLayerVSMask);
-        mDevice->SetPixelShader(mRGBPSMask);
-        maskTexRegister = 1;
-        break;
-      case RGBALAYER:
-        if (aIs2D) {
-          mDevice->SetVertexShader(mLayerVSMask);
-          mDevice->SetPixelShader(mRGBAPSMask);
-        } else {
-          mDevice->SetVertexShader(mLayerVSMask3D);
-          mDevice->SetPixelShader(mRGBAPSMask3D);
-        }
-        maskTexRegister = 1;
-        break;
-      case COMPONENTLAYERPASS1:
-        mDevice->SetVertexShader(mLayerVSMask);
-        mDevice->SetPixelShader(mComponentPass1PSMask);
-        maskTexRegister = 2;
-        break;
-      case COMPONENTLAYERPASS2:
-        mDevice->SetVertexShader(mLayerVSMask);
-        mDevice->SetPixelShader(mComponentPass2PSMask);
-        maskTexRegister = 2;
-        break;
-      case YCBCRLAYER:
-        mDevice->SetVertexShader(mLayerVSMask);
-        mDevice->SetPixelShader(mYCbCrPSMask);
-        maskTexRegister = 3;
-        break;
-      case SOLIDCOLORLAYER:
-        mDevice->SetVertexShader(mLayerVSMask);
-        mDevice->SetPixelShader(mSolidColorPSMask);
-        maskTexRegister = 0;
-        break;
-    }
-    if (!LoadMaskTexture(aMask, mDevice, maskQuadRegister, maskTexRegister)) {
-      // if we can't load the mask, fall back to unmasked rendering
-      NS_WARNING("Could not load texture for mask layer.");
-      SetShaderMode(aMode, nullptr, true);
-    }
-  } else {
+  if (aMaskType == MaskNone) {
     switch (aMode) {
       case RGBLAYER:
         mDevice->SetVertexShader(mLayerVS);
         mDevice->SetPixelShader(mRGBPS);
         break;
       case RGBALAYER:
         mDevice->SetVertexShader(mLayerVS);
         mDevice->SetPixelShader(mRGBAPS);
@@ -632,16 +596,76 @@ DeviceManagerD3D9::SetShaderMode(ShaderM
         mDevice->SetVertexShader(mLayerVS);
         mDevice->SetPixelShader(mYCbCrPS);
         break;
       case SOLIDCOLORLAYER:
         mDevice->SetVertexShader(mLayerVS);
         mDevice->SetPixelShader(mSolidColorPS);
         break;
     }
+    return 0;
+  }
+
+  uint32_t maskTexRegister;
+  switch (aMode) {
+    case RGBLAYER:
+      mDevice->SetVertexShader(mLayerVSMask);
+      mDevice->SetPixelShader(mRGBPSMask);
+      maskTexRegister = 1;
+      break;
+    case RGBALAYER:
+      if (aMaskType == Mask2d) {
+        mDevice->SetVertexShader(mLayerVSMask);
+        mDevice->SetPixelShader(mRGBAPSMask);
+      } else {
+        mDevice->SetVertexShader(mLayerVSMask3D);
+        mDevice->SetPixelShader(mRGBAPSMask3D);
+      }
+      maskTexRegister = 1;
+      break;
+    case COMPONENTLAYERPASS1:
+      mDevice->SetVertexShader(mLayerVSMask);
+      mDevice->SetPixelShader(mComponentPass1PSMask);
+      maskTexRegister = 2;
+      break;
+    case COMPONENTLAYERPASS2:
+      mDevice->SetVertexShader(mLayerVSMask);
+      mDevice->SetPixelShader(mComponentPass2PSMask);
+      maskTexRegister = 2;
+      break;
+    case YCBCRLAYER:
+      mDevice->SetVertexShader(mLayerVSMask);
+      mDevice->SetPixelShader(mYCbCrPSMask);
+      maskTexRegister = 3;
+      break;
+    case SOLIDCOLORLAYER:
+      mDevice->SetVertexShader(mLayerVSMask);
+      mDevice->SetPixelShader(mSolidColorPSMask);
+      maskTexRegister = 0;
+      break;
+  }
+  return maskTexRegister;
+}
+
+void
+DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, Layer* aMask, bool aIs2D)
+{
+  MaskType maskType = MaskNone;
+  if (aMask) {
+    maskType = aIs2D ? Mask2d : Mask3d;
+  }
+  uint32_t maskTexRegister = SetShaderMode(aMode, maskType);
+  if (aMask) {
+    // register allocations are taken from LayerManagerD3D9Shaders.h after
+    // the shaders are compiled (genshaders.sh)
+    if (!LoadMaskTexture(aMask, mDevice, maskTexRegister)) {
+      // if we can't load the mask, fall back to unmasked rendering
+      NS_WARNING("Could not load texture for mask layer.");
+      SetShaderMode(aMode, MaskNone);
+    }
   }
 }
 
 bool
 DeviceManagerD3D9::VerifyReadyForRendering()
 {
   HRESULT hr = mDevice->TestCooperativeLevel();
 
@@ -768,16 +792,23 @@ DeviceManagerD3D9::VerifyCaps()
       (caps.VertexShaderVersion & 0xffff) < 0x200) {
     return false;
   }
 
   if (HAS_CAP(caps.Caps2, D3DCAPS2_DYNAMICTEXTURES)) {
     mHasDynamicTextures = true;
   }
 
+  if (HAS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_WRAP) &&
+      LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL)) {
+    mTextureAddressingMode = D3DTADDRESS_WRAP;
+  } else {
+    gfxPlatform::DisableBufferRotation();
+  }
+
   return true;
 }
 
 bool
 DeviceManagerD3D9::CreateVertexBuffer()
 {
   HRESULT hr;
 
--- a/gfx/layers/d3d9/DeviceManagerD3D9.h
+++ b/gfx/layers/d3d9/DeviceManagerD3D9.h
@@ -6,32 +6,65 @@
 #ifndef GFX_DEVICEMANAGERD3D9_H
 #define GFX_DEVICEMANAGERD3D9_H
 
 #include "gfxTypes.h"
 #include "nsRect.h"
 #include "nsAutoPtr.h"
 #include "d3d9.h"
 #include "nsTArray.h"
+#include "mozilla/layers/CompositorTypes.h"
 
 namespace mozilla {
 namespace layers {
 
 class DeviceManagerD3D9;
 class LayerD3D9;
 class Nv3DVUtils;
 class Layer;
 
 // Shader Constant locations
 const int CBmLayerTransform = 0;
 const int CBmProjection = 4;
 const int CBvRenderTargetOffset = 8;
 const int CBvTextureCoords = 9;
 const int CBvLayerQuad = 10;
+// we don't use opacity with solid color shaders
 const int CBfLayerOpacity = 0;
+const int CBvColor = 0;
+
+/**
+ * This structure is used to pass rectangles to our shader constant. We can use
+ * this for passing rectangular areas to SetVertexShaderConstant. In the format
+ * of a 4 component float(x,y,width,height). Our vertex shader can then use
+ * this to construct rectangular positions from the 0,0-1,1 quad that we source
+ * it with.
+ */
+struct ShaderConstantRect
+{
+  float mX, mY, mWidth, mHeight;
+
+  // Provide all the commonly used argument types to prevent all the local
+  // casts in the code.
+  ShaderConstantRect(float aX, float aY, float aWidth, float aHeight)
+    : mX(aX), mY(aY), mWidth(aWidth), mHeight(aHeight)
+  { }
+
+  ShaderConstantRect(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight)
+    : mX((float)aX), mY((float)aY)
+    , mWidth((float)aWidth), mHeight((float)aHeight)
+  { }
+
+  ShaderConstantRect(int32_t aX, int32_t aY, float aWidth, float aHeight)
+    : mX((float)aX), mY((float)aY), mWidth(aWidth), mHeight(aHeight)
+  { }
+
+  // For easy passing to SetVertexShaderConstantF.
+  operator float* () { return &mX; }
+};
 
 /**
  * SwapChain class, this class manages the swap chain belonging to a
  * LayerManagerD3D9.
  */
 class SwapChainD3D9
 {
   NS_INLINE_DECL_REFCOUNTING(SwapChainD3D9)
@@ -45,21 +78,24 @@ public:
    * swap chain belonging to this device will the device draw to it. Passed in
    * is the size of the swap chain. If the window size differs from the size
    * during the last call to this function the swap chain will resize. Note that
    * in no case does this function guarantee the backbuffer to still have its
    * old content.
    */
   bool PrepareForRendering();
 
+  already_AddRefed<IDirect3DSurface9> GetBackBuffer();
+
   /**
    * This function will present the selected rectangle of the swap chain to
    * its associated window.
    */
   void Present(const nsIntRect &aRect);
+  void Present();
 
 private:
   friend class DeviceManagerD3D9;
 
   SwapChainD3D9(DeviceManagerD3D9 *aDeviceManager);
   
   bool Init(HWND hWnd);
 
@@ -78,23 +114,18 @@ private:
  * Device manager, this class is used by the layer managers to share the D3D9
  * device and create swap chains for the individual windows the layer managers
  * belong to.
  */
 class DeviceManagerD3D9 MOZ_FINAL
 {
 public:
   DeviceManagerD3D9();
-  NS_IMETHOD_(nsrefcnt) AddRef(void);
-  NS_IMETHOD_(nsrefcnt) Release(void);
-protected:
-  nsAutoRefCnt mRefCnt;
-  NS_DECL_OWNINGTHREAD
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DeviceManagerD3D9)
 
-public:
   bool Init();
 
   /**
    * Sets up the render state for the device for layer rendering.
    */
   void SetupRenderState();
 
   /**
@@ -113,16 +144,18 @@ public:
     RGBALAYER,
     COMPONENTLAYERPASS1,
     COMPONENTLAYERPASS2,
     YCBCRLAYER,
     SOLIDCOLORLAYER
   };
 
   void SetShaderMode(ShaderMode aMode, Layer* aMask, bool aIs2D);
+  // returns the register to be used for the mask texture, if appropriate
+  uint32_t SetShaderMode(ShaderMode aMode, MaskType aMaskType);
 
   /** 
    * Return pointer to the Nv3DVUtils instance 
    */ 
   Nv3DVUtils *GetNv3DVUtils()  { return mNv3DVUtils; }
 
   /**
    * Returns true if this device was removed.
@@ -134,16 +167,18 @@ public:
   /**
    * We keep a list of all layers here that may have hardware resource allocated
    * so we can clean their resources on reset.
    */
   nsTArray<LayerD3D9*> mLayersWithResources;
 
   int32_t GetMaxTextureSize() { return mMaxTextureSize; }
 
+  static uint32_t sMaskQuadRegister;
+
 private:
   friend class SwapChainD3D9;
 
   ~DeviceManagerD3D9();
 
   /**
    * This function verifies the device is ready for rendering, internally this
    * will test the cooperative level of the device and reset the device if
@@ -217,16 +252,22 @@ private:
 
   /* we use this to help track if our device temporarily or permanently lost */
   HMONITOR mDeviceMonitor;
 
   uint32_t mDeviceResetCount;
 
   uint32_t mMaxTextureSize;
 
+  /**
+   * Wrap (repeat) or clamp textures. We prefer the former so we can do buffer
+   * rotation, but some older hardware doesn't support it.
+   */
+  D3DTEXTUREADDRESS mTextureAddressingMode;
+
   /* If this device supports dynamic textures */
   bool mHasDynamicTextures;
 
   /* If this device was removed */
   bool mDeviceWasRemoved;
 
   /* Nv3DVUtils instance */ 
   nsAutoPtr<Nv3DVUtils> mNv3DVUtils; 
--- a/gfx/layers/d3d9/LayerManagerD3D9.h
+++ b/gfx/layers/d3d9/LayerManagerD3D9.h
@@ -17,46 +17,16 @@
 #include "DeviceManagerD3D9.h"
 
 namespace mozilla {
 namespace layers {
 
 class LayerD3D9;
 class ThebesLayerD3D9;
 
-/**
- * This structure is used to pass rectangles to our shader constant. We can use
- * this for passing rectangular areas to SetVertexShaderConstant. In the format
- * of a 4 component float(x,y,width,height). Our vertex shader can then use
- * this to construct rectangular positions from the 0,0-1,1 quad that we source
- * it with.
- */
-struct ShaderConstantRect
-{
-  float mX, mY, mWidth, mHeight;
-
-  // Provide all the commonly used argument types to prevent all the local
-  // casts in the code.
-  ShaderConstantRect(float aX, float aY, float aWidth, float aHeight)
-    : mX(aX), mY(aY), mWidth(aWidth), mHeight(aHeight)
-  { }
-
-  ShaderConstantRect(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight)
-    : mX((float)aX), mY((float)aY)
-    , mWidth((float)aWidth), mHeight((float)aHeight)
-  { }
-
-  ShaderConstantRect(int32_t aX, int32_t aY, float aWidth, float aHeight)
-    : mX((float)aX), mY((float)aY), mWidth(aWidth), mHeight(aHeight)
-  { }
-
-  // For easy passing to SetVertexShaderConstantF.
-  operator float* () { return &mX; }
-};
-
 /*
  * This is the LayerManager used for Direct3D 9. For now this will render on
  * the main thread.
  */
 class LayerManagerD3D9 : public LayerManager {
 public:
   LayerManagerD3D9(nsIWidget *aWidget);
   virtual ~LayerManagerD3D9();
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/TextureD3D9.cpp
@@ -0,0 +1,628 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * 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 "TextureD3D9.h"
+#include "CompositorD3D9.h"
+#include "gfxContext.h"
+#include "gfxImageSurface.h"
+#include "Effects.h"
+#include "ipc/AutoOpenSurface.h"
+#include "mozilla/layers/YCbCrImageDataSerializer.h"
+#include "gfxWindowsPlatform.h"
+
+using namespace mozilla::gfx;
+
+namespace mozilla {
+namespace layers {
+
+TemporaryRef<DeprecatedTextureHost>
+CreateDeprecatedTextureHostD3D9(SurfaceDescriptorType aDescriptorType,
+                      uint32_t aDeprecatedTextureHostFlags,
+                      uint32_t aTextureFlags)
+{
+  RefPtr<DeprecatedTextureHost> result;
+  if (aDescriptorType == SurfaceDescriptor::TYCbCrImage) {
+    result = new DeprecatedTextureHostYCbCrD3D9();
+  } else if (aDescriptorType == SurfaceDescriptor::TSurfaceDescriptorD3D9) {
+    result = new DeprecatedTextureHostSystemMemD3D9();
+  } else {
+    result = new DeprecatedTextureHostShmemD3D9();
+  }
+
+  result->SetFlags(aTextureFlags);
+
+  return result.forget();
+}
+
+
+CompositingRenderTargetD3D9::CompositingRenderTargetD3D9(IDirect3DTexture9* aTexture,
+                                                         SurfaceInitMode aInit,
+                                                         const gfx::IntSize& aSize)
+  : mInitMode(aInit)
+  , mInitialized(false)
+{
+  MOZ_COUNT_CTOR(CompositingRenderTargetD3D9);
+  MOZ_ASSERT(aTexture);
+
+  mTextures[0] = aTexture;
+  HRESULT hr = mTextures[0]->GetSurfaceLevel(0, getter_AddRefs(mSurface));
+  NS_ASSERTION(mSurface, "Couldn't create surface for texture");
+  TextureSourceD3D9::SetSize(aSize);
+}
+
+CompositingRenderTargetD3D9::CompositingRenderTargetD3D9(IDirect3DSurface9* aSurface,
+                                                         SurfaceInitMode aInit,
+                                                         const gfx::IntSize& aSize)
+  : mSurface(aSurface)
+  , mInitMode(aInit)
+  , mInitialized(false)
+{
+  MOZ_COUNT_CTOR(CompositingRenderTargetD3D9);
+  MOZ_ASSERT(mSurface);
+  TextureSourceD3D9::SetSize(aSize);
+}
+
+CompositingRenderTargetD3D9::~CompositingRenderTargetD3D9()
+{
+  MOZ_COUNT_DTOR(CompositingRenderTargetD3D9);
+}
+
+void
+CompositingRenderTargetD3D9::BindRenderTarget(IDirect3DDevice9* aDevice)
+{
+  aDevice->SetRenderTarget(0, mSurface);
+  if (!mInitialized &&
+      mInitMode == INIT_MODE_CLEAR) {
+    mInitialized = true;
+    aDevice->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0);
+  }
+}
+
+IntSize
+CompositingRenderTargetD3D9::GetSize() const
+{
+  return TextureSourceD3D9::GetSize();
+}
+
+DeprecatedTextureHostD3D9::DeprecatedTextureHostD3D9()
+  : mIsTiled(false)
+  , mCurrentTile(0)
+  , mIterating(false)
+{
+  MOZ_COUNT_CTOR(DeprecatedTextureHostD3D9);
+}
+
+DeprecatedTextureHostD3D9::~DeprecatedTextureHostD3D9()
+{
+  MOZ_COUNT_DTOR(DeprecatedTextureHostD3D9);
+}
+
+IntSize
+DeprecatedTextureHostD3D9::GetSize() const
+{
+  if (mIterating) {
+    gfx::IntRect rect = GetTileRect(mCurrentTile);
+    return gfx::IntSize(rect.width, rect.height);
+  }
+  return TextureSourceD3D9::GetSize();
+}
+
+nsIntRect
+DeprecatedTextureHostD3D9::GetTileRect()
+{
+  IntRect rect = GetTileRect(mCurrentTile);
+  return nsIntRect(rect.x, rect.y, rect.width, rect.height);
+}
+
+static uint32_t GetRequiredTiles(uint32_t aSize, uint32_t aMaxSize)
+{
+  uint32_t requiredTiles = aSize / aMaxSize;
+  if (aSize % aMaxSize) {
+    requiredTiles++;
+  }
+  return requiredTiles;
+}
+
+void
+DeprecatedTextureHostD3D9::SetCompositor(Compositor* aCompositor)
+{
+  mCompositor = static_cast<CompositorD3D9*>(aCompositor);
+  mDevice = mCompositor ? mCompositor->device() : nullptr;
+}
+
+static TemporaryRef<IDirect3DTexture9>
+DataToTexture(IDirect3DDevice9 *aDevice,
+              unsigned char *aData,
+              int aStride,
+              const gfxIntSize &aSize,
+              _D3DFORMAT aFormat,
+              uint32_t aBPP)
+{
+  RefPtr<IDirect3DTexture9> texture;
+  nsRefPtr<IDirect3DDevice9Ex> deviceEx;
+  aDevice->QueryInterface(IID_IDirect3DDevice9Ex,
+                          (void**)getter_AddRefs(deviceEx));
+
+  RefPtr<IDirect3DSurface9> surface;
+  D3DLOCKED_RECT lockedRect;
+  if (deviceEx) {
+    // D3D9Ex doesn't support managed textures. We could use dynamic textures
+    // here but since Images are immutable that probably isn't such a great
+    // idea.
+    if (FAILED(aDevice->
+               CreateTexture(aSize.width, aSize.height,
+                             1, 0, aFormat, D3DPOOL_DEFAULT,
+                             byRef(texture), nullptr)))
+    {
+      return nullptr;
+    }
+
+    RefPtr<IDirect3DTexture9> tmpTexture;
+    if (FAILED(aDevice->
+               CreateTexture(aSize.width, aSize.height,
+                             1, 0, aFormat, D3DPOOL_SYSTEMMEM,
+                             byRef(tmpTexture), nullptr)))
+    {
+      return nullptr;
+    }
+
+    tmpTexture->GetSurfaceLevel(0, byRef(surface));
+    surface->LockRect(&lockedRect, NULL, 0);
+    NS_ASSERTION(lockedRect.pBits, "Could not lock surface");
+  } else {
+    if (FAILED(aDevice->
+               CreateTexture(aSize.width, aSize.height,
+                             1, 0, aFormat, D3DPOOL_MANAGED,
+                             byRef(texture), nullptr))) {
+      return nullptr;
+    }
+
+    /* lock the entire texture */
+    texture->LockRect(0, &lockedRect, nullptr, 0);
+  }
+
+  uint32_t width = aSize.width * aBPP;
+
+  for (int y = 0; y < aSize.height; y++) {
+    memcpy((char*)lockedRect.pBits + lockedRect.Pitch * y,
+            aData + aStride * y,
+            width);
+  }
+
+  if (deviceEx) {
+    surface->UnlockRect();
+    nsRefPtr<IDirect3DSurface9> dstSurface;
+    texture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
+    aDevice->UpdateSurface(surface, NULL, dstSurface, NULL);
+  } else {
+    texture->UnlockRect(0);
+  }
+
+  return texture.forget();
+}
+
+void
+DeprecatedTextureHostShmemD3D9::UpdateImpl(const SurfaceDescriptor& aImage,
+                                 nsIntRegion *aRegion,
+                                 nsIntPoint *aOffset)
+{
+  MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TShmem ||
+             aImage.type() == SurfaceDescriptor::TMemoryImage);
+  MOZ_ASSERT(mCompositor, "Must have compositor to update.");
+
+  AutoOpenSurface openSurf(OPEN_READ_ONLY, aImage);
+
+  nsRefPtr<gfxImageSurface> surf = openSurf.GetAsImage();
+
+  gfxIntSize size = surf->GetSize();
+  mSize = IntSize(size.width, size.height);
+
+  uint32_t bpp = 0;
+
+  _D3DFORMAT format = D3DFMT_A8R8G8B8;
+  switch (surf->Format()) {
+  case gfxImageSurface::ImageFormatRGB24:
+    mFormat = FORMAT_B8G8R8X8;
+    format = D3DFMT_X8R8G8B8;
+    bpp = 4;
+    break;
+  case gfxImageSurface::ImageFormatARGB32:
+    mFormat = FORMAT_B8G8R8A8;
+    format = D3DFMT_A8R8G8B8;
+    bpp = 4;
+    break;
+  case gfxImageSurface::ImageFormatA8:
+    mFormat = FORMAT_A8;
+    format = D3DFMT_A8;
+    bpp = 1;
+    break;
+  default:
+    NS_ERROR("Bad image format");
+  }
+
+  int32_t maxSize = mCompositor->GetMaxTextureSize();
+  if (size.width <= maxSize && size.height <= maxSize) {
+    mTextures[0] = DataToTexture(mDevice,
+                                 surf->Data(), surf->Stride(),
+                                 size, format, bpp);
+    NS_ASSERTION(mTextures[0], "Could not upload texture");
+    mIsTiled = false;
+  } else {
+    mIsTiled = true;
+    uint32_t tileCount = GetRequiredTiles(size.width, maxSize) *
+                         GetRequiredTiles(size.height, maxSize);
+    mTileTextures.resize(tileCount);
+
+    for (uint32_t i = 0; i < tileCount; i++) {
+      IntRect tileRect = GetTileRect(i);
+      unsigned char* data = surf->Data() +
+                            tileRect.y * surf->Stride() +
+                            tileRect.x * bpp;
+      mTileTextures[i] = DataToTexture(mDevice,
+                                       data,
+                                       surf->Stride(),
+                                       gfxIntSize(tileRect.width, tileRect.height),
+                                       format,
+                                       bpp);
+    }
+  }
+}
+
+IntRect
+DeprecatedTextureHostD3D9::GetTileRect(uint32_t aID) const
+{
+  uint32_t maxSize = mCompositor->GetMaxTextureSize();
+  uint32_t horizontalTiles = GetRequiredTiles(mSize.width, maxSize);
+  uint32_t verticalTiles = GetRequiredTiles(mSize.height, maxSize);
+
+  uint32_t verticalTile = aID / horizontalTiles;
+  uint32_t horizontalTile = aID % horizontalTiles;
+
+  return IntRect(horizontalTile * maxSize,
+                 verticalTile * maxSize,
+                 horizontalTile < (horizontalTiles - 1) ? maxSize : mSize.width % maxSize,
+                 verticalTile < (verticalTiles - 1) ? maxSize : mSize.height % maxSize);
+}
+
+void
+DeprecatedTextureHostYCbCrD3D9::SetCompositor(Compositor* aCompositor)
+{
+  CompositorD3D9 *d3dCompositor = static_cast<CompositorD3D9*>(aCompositor);
+  mDevice = d3dCompositor ? d3dCompositor->device() : nullptr;
+}
+
+IntSize
+DeprecatedTextureHostYCbCrD3D9::GetSize() const
+{
+  return TextureSourceD3D9::GetSize();
+}
+
+void
+DeprecatedTextureHostYCbCrD3D9::UpdateImpl(const SurfaceDescriptor& aImage,
+                                 nsIntRegion *aRegion,
+                                 nsIntPoint *aOffset)
+{
+  MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TYCbCrImage);
+
+  YCbCrImageDataDeserializer yuvDeserializer(aImage.get_YCbCrImage().data().get<uint8_t>());
+
+  gfxIntSize gfxCbCrSize = yuvDeserializer.GetCbCrSize();
+  gfxIntSize size = yuvDeserializer.GetYSize();
+  mSize = IntSize(size.width, size.height);
+  mStereoMode = yuvDeserializer.GetStereoMode();
+
+  mTextures[0] = DataToTexture(mDevice,
+                               yuvDeserializer.GetYData(),
+                               yuvDeserializer.GetYStride(),
+                               size,
+                               D3DFMT_L8, 1);
+  mTextures[1] = DataToTexture(mDevice,
+                               yuvDeserializer.GetCbData(),
+                               yuvDeserializer.GetCbCrStride(),
+                               gfxCbCrSize,
+                               D3DFMT_L8, 1);
+  mTextures[2] = DataToTexture(mDevice,
+                               yuvDeserializer.GetCrData(),
+                               yuvDeserializer.GetCbCrStride(),
+                               gfxCbCrSize,
+                               D3DFMT_L8, 1);
+}
+
+// aTexture should be in SYSTEMMEM, returns a texture in the default
+// pool (that is, in video memory).
+static TemporaryRef<IDirect3DTexture9>
+TextureToTexture(IDirect3DDevice9* aDevice,
+                 IDirect3DTexture9* aTexture,
+                 const IntSize& aSize,
+                 _D3DFORMAT aFormat)
+{
+  RefPtr<IDirect3DTexture9> texture;
+  if (FAILED(aDevice->
+              CreateTexture(aSize.width, aSize.height,
+                            1, 0, aFormat, D3DPOOL_DEFAULT,
+                            byRef(texture), nullptr))) {
+    return nullptr;
+  }
+
+  HRESULT hr = aDevice->UpdateTexture(aTexture, texture);
+  if (FAILED(hr)) {
+    return nullptr;
+  }
+
+  return texture.forget();
+}
+
+void
+DeprecatedTextureHostSystemMemD3D9::UpdateImpl(const SurfaceDescriptor& aImage,
+                                     nsIntRegion *aRegion,
+                                     nsIntPoint *aOffset)
+{
+  MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TSurfaceDescriptorD3D9);
+  MOZ_ASSERT(mCompositor, "Must have compositor to update.");
+
+  IDirect3DTexture9* texture =
+    reinterpret_cast<IDirect3DTexture9*>(aImage.get_SurfaceDescriptorD3D9().texture());
+
+  if (!texture) {
+    mTextures[0] = nullptr;
+    return;
+  }
+
+  D3DSURFACE_DESC desc;
+  texture->GetLevelDesc(0, &desc);
+  mSize.width = desc.Width;
+  mSize.height = desc.Height;
+
+  _D3DFORMAT format = desc.Format;
+  uint32_t bpp = 0;
+  switch (format) {
+  case D3DFMT_X8R8G8B8:
+    mFormat = FORMAT_B8G8R8X8;
+    bpp = 4;
+    break;
+  case D3DFMT_A8R8G8B8:
+    mFormat = FORMAT_B8G8R8A8;
+    bpp = 4;
+    break;
+  case D3DFMT_A8:
+    mFormat = FORMAT_A8;
+    bpp = 1;
+    break;
+  default:
+    NS_ERROR("Bad image format");
+  }
+
+  int32_t maxSize = mCompositor->GetMaxTextureSize();
+  if (mSize.width <= maxSize && mSize.height <= maxSize) {
+    mIsTiled = false;
+
+    mTextures[0] = TextureToTexture(mDevice, texture, mSize, format);
+    NS_ASSERTION(mTextures[0], "Could not upload texture");
+  } else {
+    mIsTiled = true;
+
+    uint32_t tileCount = GetRequiredTiles(mSize.width, maxSize) *
+                         GetRequiredTiles(mSize.height, maxSize);
+    mTileTextures.resize(tileCount);
+
+    for (uint32_t i = 0; i < tileCount; i++) {
+      IntRect tileRect = GetTileRect(i);
+      RECT d3dTileRect;
+      d3dTileRect.left = tileRect.x;
+      d3dTileRect.top = tileRect.y;
+      d3dTileRect.right = tileRect.XMost();
+      d3dTileRect.bottom = tileRect.YMost();
+      D3DLOCKED_RECT lockedRect;
+      texture->LockRect(0, &lockedRect, &d3dTileRect, 0);
+      mTileTextures[i] = DataToTexture(mDevice,
+                                       reinterpret_cast<unsigned char*>(lockedRect.pBits),
+                                       lockedRect.Pitch,
+                                       gfxIntSize(tileRect.width, tileRect.height),
+                                       format,
+                                       bpp);
+      texture->UnlockRect(0);
+    }
+  }
+}
+
+DeprecatedTextureClientD3D9::DeprecatedTextureClientD3D9(CompositableForwarder* aCompositableForwarder,
+                                     const TextureInfo& aTextureInfo)
+  : DeprecatedTextureClient(aCompositableForwarder, aTextureInfo)
+  , mDC(nullptr)
+  , mTextureLocked(false)
+{
+  MOZ_COUNT_CTOR(DeprecatedTextureClientD3D9);
+}
+
+DeprecatedTextureClientD3D9::~DeprecatedTextureClientD3D9()
+{
+  MOZ_COUNT_DTOR(DeprecatedTextureClientD3D9);
+  Unlock();
+  mDescriptor = SurfaceDescriptor();
+
+  ClearDT();
+}
+
+bool
+DeprecatedTextureClientD3D9::EnsureAllocated(gfx::IntSize aSize,
+                                   gfxASurface::gfxContentType aType)
+{
+  if (mTexture) {
+    D3DSURFACE_DESC desc;
+    mTexture->GetLevelDesc(0, &desc);
+
+    if (desc.Width == aSize.width &&
+        desc.Height == aSize.height) {
+      return true;
+    }
+
+    Unlock();
+    mD3D9Surface = nullptr;
+    mTexture = nullptr;
+  }
+
+  mSize = aSize;
+
+  _D3DFORMAT format = D3DFMT_A8R8G8B8;
+  switch (aType) {
+  case gfxASurface::CONTENT_COLOR:
+    format = D3DFMT_X8R8G8B8;
+    mIsOpaque = true;
+    break;
+  case gfxASurface::CONTENT_COLOR_ALPHA:
+    format = D3DFMT_A8R8G8B8;
+    mIsOpaque = false;
+    break;
+  case gfxASurface::CONTENT_ALPHA:
+    format = D3DFMT_A8;
+    mIsOpaque = true;
+    break;
+  default:
+    NS_ERROR("Bad image type");
+  }
+
+  IDirect3DDevice9 *device = gfxWindowsPlatform::GetPlatform()->GetD3D9Device();
+  if (!device ||
+      FAILED(device->
+               CreateTexture(aSize.width, aSize.height,
+                             1, 0, format, D3DPOOL_SYSTEMMEM,
+                             getter_AddRefs(mTexture), nullptr)))
+  {
+    NS_WARNING("Could not create texture");
+    return false;
+  }
+
+  MOZ_ASSERT(mTexture);
+  mDescriptor = SurfaceDescriptorD3D9(reinterpret_cast<uintptr_t>(mTexture.get()));
+
+  if (!mIsOpaque) {
+    nsRefPtr<gfxASurface> surface = LockSurface();
+    nsRefPtr<gfxContext> ctx = new gfxContext(surface);
+    ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
+    ctx->SetColor(gfxRGBA(0.0, 0.0, 0.0, 0.0));
+    ctx->Paint();
+    Unlock();
+  }
+
+  mContentType = aType;
+  return true;
+}
+
+gfxASurface*
+DeprecatedTextureClientD3D9::LockSurface()
+{
+  if (mSurface) {
+    return mSurface.get();
+  }
+
+  MOZ_ASSERT(mTexture, "Cannot lock surface without a texture to lock");
+
+  if (mIsOpaque) {
+    MOZ_ASSERT(!mTextureLocked, "Shouldn't lock texture and have a surface");
+    if (!mD3D9Surface) {
+      HRESULT hr = mTexture->GetSurfaceLevel(0, getter_AddRefs(mD3D9Surface));
+      if (FAILED(hr)) {
+        NS_WARNING("Failed to get texture surface level.");
+        return nullptr;
+      }
+    }
+
+    if (!mDC) {
+      HRESULT hr = mD3D9Surface->GetDC(&mDC);
+      if (FAILED(hr)) {
+        NS_WARNING("Failed to get device context for texture surface.");
+        return nullptr;
+      }
+    }
+    NS_ASSERTION(mDC, "We need a DC here");
+    mSurface = new gfxWindowsSurface(mDC);
+  } else {
+    // d3d9 SYSTEMMEM surfaces do not support GDI with an alpha channel
+    MOZ_ASSERT(!mD3D9Surface && !mDC, "Shouldn't lock texture and have a surface");
+    if (!mTextureLocked) {
+      D3DLOCKED_RECT lockedRect;
+      mTexture->LockRect(0, &lockedRect, nullptr, 0);
+      mTextureLocked = true;
+
+      mSurface = new gfxImageSurface(reinterpret_cast<unsigned char*>(lockedRect.pBits),
+                                     gfxIntSize(mSize.width, mSize.height),
+                                     lockedRect.Pitch,
+                                     gfxASurface::ImageFormatARGB32);
+    }
+  }
+
+  NS_ASSERTION(mSurface, "should have a surface one way or the other");
+  return mSurface.get();
+}
+
+DrawTarget*
+DeprecatedTextureClientD3D9::LockDrawTarget()
+{
+  if (!mDrawTarget) {
+    mDrawTarget =
+      gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(LockSurface(), mSize);
+  }
+
+  return mDrawTarget.get();
+}
+
+void
+DeprecatedTextureClientD3D9::Unlock()
+{
+  if (mDrawTarget) {
+    mDrawTarget->Flush();
+    mDrawTarget = nullptr;
+  }
+
+  if (mTextureLocked) {
+    MOZ_ASSERT(!mD3D9Surface && !mDC, "Shouldn't lock texture and have a surface");
+    mTexture->UnlockRect(0);
+    mTextureLocked = false;
+  } else if (mDC) {
+    MOZ_ASSERT(mD3D9Surface, "we need a D3D9Surface to release our DC");
+    MOZ_ASSERT(!mTextureLocked, "Shouldn't lock texture and have a surface");
+    mD3D9Surface->ReleaseDC(mDC);
+    mDC = nullptr;
+  }
+
+  if (mSurface) {
+    mSurface = nullptr;
+  }
+}
+
+void
+DeprecatedTextureClientD3D9::SetDescriptor(const SurfaceDescriptor& aDescriptor)
+{
+  if (aDescriptor.type() == SurfaceDescriptor::Tnull_t) {
+    EnsureAllocated(mSize, mContentType);
+    return;
+  }
+
+  mDescriptor = aDescriptor;
+  mSurface = nullptr;
+  ClearDT();
+
+  if (aDescriptor.type() == SurfaceDescriptor::T__None) {
+    return;
+  }
+
+  MOZ_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorD3D9);
+  Unlock();
+  mD3D9Surface = nullptr;
+  mTexture = reinterpret_cast<IDirect3DTexture9*>(
+               mDescriptor.get_SurfaceDescriptorD3D9().texture());
+}
+
+void
+DeprecatedTextureClientD3D9::ClearDT()
+{
+  // Perhaps this should be debug only.
+  if (mDrawTarget) {
+    mDrawTarget = nullptr;
+  }
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/TextureD3D9.h
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * 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_GFX_TEXTURED3D9_H
+#define MOZILLA_GFX_TEXTURED3D9_H
+
+#include "mozilla/layers/Compositor.h"
+#include "mozilla/layers/TextureClient.h"
+#include "mozilla/layers/TextureHost.h"
+#include "gfxWindowsPlatform.h"
+#include "d3d9.h"
+#include <vector>
+
+namespace mozilla {
+namespace layers {
+
+class CompositorD3D9;
+
+class TextureSourceD3D9
+{
+public:
+  virtual IDirect3DTexture9* GetD3D9Texture() { return mTextures[0]; }
+  virtual bool IsYCbCrSource() const { return false; }
+
+  struct YCbCrTextures
+  {
+    IDirect3DTexture9 *mY;
+    IDirect3DTexture9 *mCb;
+    IDirect3DTexture9 *mCr;
+    StereoMode mStereoMode;
+  };
+
+  virtual YCbCrTextures GetYCbCrTextures() {
+    YCbCrTextures textures = { mTextures[0],
+                               mTextures[1],
+                               mTextures[2],
+                               mStereoMode };
+    return textures;
+  }
+
+protected:
+  virtual gfx::IntSize GetSize() const { return mSize; }
+  void SetSize(const gfx::IntSize& aSize) { mSize = aSize; }
+
+  gfx::IntSize mSize;
+  StereoMode mStereoMode;
+  RefPtr<IDirect3DTexture9> mTextures[3];
+};
+
+class CompositingRenderTargetD3D9 : public CompositingRenderTarget,
+                                    public TextureSourceD3D9
+{
+public:
+  CompositingRenderTargetD3D9(IDirect3DTexture9* aTexture,
+                              SurfaceInitMode aInit,
+                              const gfx::IntSize& aSize);
+  // use for rendering to the main window, cannot be rendered as a texture
+  CompositingRenderTargetD3D9(IDirect3DSurface9* aSurface,
+                              SurfaceInitMode aInit,
+                              const gfx::IntSize& aSize);
+  ~CompositingRenderTargetD3D9();
+
+  virtual TextureSourceD3D9* AsSourceD3D9() MOZ_OVERRIDE
+  {
+    MOZ_ASSERT(mTextures[0],
+               "No texture, can't be indirectly rendered. Is this the screen backbuffer?");
+    return this;
+  }
+
+  virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
+
+  void BindRenderTarget(IDirect3DDevice9* aDevice);
+
+  IDirect3DSurface9* GetD3D9Surface() const { return mSurface; }
+
+private:
+  friend class CompositorD3D9;
+
+  nsRefPtr<IDirect3DSurface9> mSurface;
+  SurfaceInitMode mInitMode;
+  bool mInitialized;
+};
+
+// Shared functionality for non-YCbCr texture hosts
+class DeprecatedTextureHostD3D9 : public DeprecatedTextureHost
+                      , public TextureSourceD3D9
+                      , public TileIterator
+{
+public:
+  DeprecatedTextureHostD3D9();
+  virtual ~DeprecatedTextureHostD3D9();
+
+  virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
+
+  virtual TextureSourceD3D9* AsSourceD3D9() MOZ_OVERRIDE { return this; }
+
+  virtual IDirect3DTexture9 *GetD3D9Texture() MOZ_OVERRIDE {
+    return mIsTiled ? mTileTextures[mCurrentTile].get()
+                    : TextureSourceD3D9::GetD3D9Texture();
+  }
+
+  virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
+
+  virtual LayerRenderState GetRenderState() { return LayerRenderState(); }
+
+  virtual bool Lock() MOZ_OVERRIDE { return true; }
+
+  virtual already_AddRefed<gfxImageSurface> GetAsSurface() MOZ_OVERRIDE
+  {
+    return nullptr; // TODO: cf bug 872568
+  }
+
+  virtual void BeginTileIteration() MOZ_OVERRIDE
+  {
+    mIterating = true;
+    mCurrentTile = 0;
+  }
+  virtual void EndTileIteration() MOZ_OVERRIDE
+  {
+    mIterating = false;
+  }
+  virtual nsIntRect GetTileRect() MOZ_OVERRIDE;
+  virtual size_t GetTileCount() MOZ_OVERRIDE { return mTileTextures.size(); }
+  virtual bool NextTile() MOZ_OVERRIDE
+  {
+    return (++mCurrentTile < mTileTextures.size());
+  }
+
+  virtual TileIterator* AsTileIterator() MOZ_OVERRIDE
+  {
+    return mIsTiled ? this : nullptr;
+  }
+
+protected:
+  gfx::IntRect GetTileRect(uint32_t aID) const;
+
+  RefPtr<IDirect3DDevice9> mDevice;
+  RefPtr<CompositorD3D9> mCompositor;
+  bool mIsTiled;
+  std::vector< RefPtr<IDirect3DTexture9> > mTileTextures;
+  uint32_t mCurrentTile;
+  bool mIterating;
+};
+
+class DeprecatedTextureHostShmemD3D9 : public DeprecatedTextureHostD3D9
+{
+public:
+#ifdef MOZ_LAYERS_HAVE_LOG
+  virtual const char* Name() { return "DeprecatedTextureHostShmemD3D9"; }
+#endif
+
+protected:
+  virtual void UpdateImpl(const SurfaceDescriptor& aSurface,
+                          nsIntRegion* aRegion,
+                          nsIntPoint *aOffset = nullptr) MOZ_OVERRIDE;
+};
+
+class DeprecatedTextureHostSystemMemD3D9 : public DeprecatedTextureHostD3D9
+{
+public:
+#ifdef MOZ_LAYERS_HAVE_LOG
+  virtual const char* Name() { return "DeprecatedTextureHostSystemMemD3D9"; }
+#endif
+
+protected:
+  virtual void UpdateImpl(const SurfaceDescriptor& aSurface,
+                          nsIntRegion* aRegion,
+                          nsIntPoint *aOffset = nullptr) MOZ_OVERRIDE;
+
+  nsRefPtr<IDirect3DTexture9> mTexture;
+};
+
+class DeprecatedTextureHostYCbCrD3D9 : public DeprecatedTextureHost
+                           , public TextureSourceD3D9
+{
+public:
+  DeprecatedTextureHostYCbCrD3D9()
+    : mDevice(nullptr)
+  {
+    mFormat = gfx::FORMAT_YUV;
+  }
+
+  virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
+
+  virtual TextureSourceD3D9* AsSourceD3D9() MOZ_OVERRIDE { return this; }
+
+  virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
+
+  virtual bool IsYCbCrSource() const MOZ_OVERRIDE { return true; }
+
+  virtual already_AddRefed<gfxImageSurface> GetAsSurface() MOZ_OVERRIDE
+  {
+    return nullptr; // TODO: cf bug 872568
+  }
+
+#ifdef MOZ_LAYERS_HAVE_LOG
+  virtual const char* Name() MOZ_OVERRIDE
+  {
+    return "TextureImageDeprecatedTextureHostD3D11";
+  }
+#endif
+
+protected:
+  virtual void UpdateImpl(const SurfaceDescriptor& aSurface,
+                          nsIntRegion* aRegion,
+                          nsIntPoint* aOffset = nullptr) MOZ_OVERRIDE;
+
+private:
+  RefPtr<IDirect3DDevice9> mDevice;
+};
+
+// If we want to use d3d9 textures for transport, use this class.
+// If we are using shmem, then use DeprecatedTextureClientShmem with DeprecatedTextureHostShmemD3D9
+// Since we pass a raw pointer, you should not use this texture client for
+// multi-process compositing.
+class DeprecatedTextureClientD3D9 : public DeprecatedTextureClient
+{
+public:
+  DeprecatedTextureClientD3D9(CompositableForwarder* aCompositableForwarder,
+                    const TextureInfo& aTextureInfo);
+  virtual ~DeprecatedTextureClientD3D9();
+
+  virtual bool SupportsType(DeprecatedTextureClientType aType) MOZ_OVERRIDE
+  {
+    return aType == TEXTURE_CONTENT;
+  }
+
+  virtual bool EnsureAllocated(gfx::IntSize aSize,
+                               gfxASurface::gfxContentType aType) MOZ_OVERRIDE;
+
+  virtual gfxASurface* LockSurface() MOZ_OVERRIDE;
+  virtual gfx::DrawTarget* LockDrawTarget() MOZ_OVERRIDE;
+  virtual void Unlock() MOZ_OVERRIDE;
+
+  virtual void SetDescriptor(const SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE;
+  virtual gfxASurface::gfxContentType GetContentType() MOZ_OVERRIDE
+  {
+    return mContentType;
+  }
+
+private:
+  void ClearDT();
+
+  nsRefPtr<IDirect3DTexture9> mTexture;
+  nsRefPtr<gfxASurface> mSurface;
+  nsRefPtr<IDirect3DSurface9> mD3D9Surface;
+  HDC mDC;
+  RefPtr<gfx::DrawTarget> mDrawTarget;
+  gfx::IntSize mSize;
+  gfxContentType mContentType;
+  bool mTextureLocked;
+  bool mIsOpaque;
+};
+
+}
+}
+
+#endif /* MOZILLA_GFX_TEXTURED3D9_H */
--- a/gfx/layers/ipc/CompositableForwarder.h
+++ b/gfx/layers/ipc/CompositableForwarder.h
@@ -36,16 +36,17 @@ class BasicTiledLayerBuffer;
 class CompositableForwarder : public ISurfaceAllocator
 {
   friend class AutoOpenSurface;
   friend class DeprecatedTextureClientShmem;
 public:
   typedef gfxASurface::gfxContentType gfxContentType;
 
   CompositableForwarder()
+    : mMultiProcess(false)
   {}
 
   /**
    * Setup the IPDL actor for aCompositable to be part of layers
    * transactions.
    */
   virtual void Connect(CompositableClient* aCompositable) = 0;
 
@@ -202,16 +203,22 @@ public:
     return mTextureFactoryIdentifier.mSupportsTextureBlitting;
   }
 
   bool SupportsPartialUploads() const
   {
     return mTextureFactoryIdentifier.mSupportsPartialUploads;
   }
 
+  bool ForwardsToDifferentProcess() const
+  {
+    return mMultiProcess;
+  }
+
 protected:
   TextureFactoryIdentifier mTextureFactoryIdentifier;
+  bool mMultiProcess;
 };
 
 } // namespace
 } // namespace
 
 #endif
--- a/gfx/layers/ipc/CompositorChild.cpp
+++ b/gfx/layers/ipc/CompositorChild.cpp
@@ -68,17 +68,18 @@ CompositorChild::Get()
   // This is only expected to be used in child processes.
   MOZ_ASSERT(XRE_GetProcessType() != GeckoProcessType_Default);
   return sCompositor;
 }
 
 PLayerTransactionChild*
 CompositorChild::AllocPLayerTransactionChild(const LayersBackend& aBackendHint,
                                              const uint64_t& aId,
-                                             TextureFactoryIdentifier*)
+                                             TextureFactoryIdentifier*,
+                                             bool*)
 {
   return new LayerTransactionChild();
 }
 
 bool
 CompositorChild::DeallocPLayerTransactionChild(PLayerTransactionChild* actor)
 {
   delete actor;
--- a/gfx/layers/ipc/CompositorChild.h
+++ b/gfx/layers/ipc/CompositorChild.h
@@ -36,17 +36,18 @@ public:
 
   static PCompositorChild* Get();
 
   static bool ChildProcessHasCompositor() { return sCompositor != nullptr; }
 protected:
   virtual PLayerTransactionChild*
     AllocPLayerTransactionChild(const LayersBackend& aBackendHint,
                                 const uint64_t& aId,
-                                TextureFactoryIdentifier* aTextureFactoryIdentifier) MOZ_OVERRIDE;
+                                TextureFactoryIdentifier* aTextureFactoryIdentifier,
+                                bool* aSuccess) MOZ_OVERRIDE;
 
   virtual bool DeallocPLayerTransactionChild(PLayerTransactionChild *aChild) MOZ_OVERRIDE;
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
 private:
   nsRefPtr<LayerManager> mLayerManager;
   nsCOMPtr<nsIObserver> mMemoryPressureObserver;
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -9,16 +9,17 @@
 #include "mozilla/DebugOnly.h"
 
 #include "AutoOpenSurface.h"
 #include "CompositorParent.h"
 #include "mozilla/layers/CompositorOGL.h"
 #include "mozilla/layers/BasicCompositor.h"
 #ifdef XP_WIN
 #include "mozilla/layers/CompositorD3D11.h"
+#include "mozilla/layers/CompositorD3D9.h"
 #endif
 #include "LayerTransactionParent.h"
 #include "nsIWidget.h"
 #include "nsGkAtoms.h"
 #include "RenderTrace.h"
 #include "gfxPlatform.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/layers/AsyncCompositionManager.h"
@@ -418,26 +419,23 @@ CompositorParent::ScheduleTask(Cancelabl
   } else {
     MessageLoop::current()->PostDelayedTask(FROM_HERE, task, time);
   }
 }
 
 void
 CompositorParent::NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint)
 {
-  if (mApzcTreeManager) {
+  if (mApzcTreeManager &&
+      mLayerManager &&
+      mLayerManager->GetRoot()) {
     AutoResolveRefLayers resolve(mCompositionManager);
     mApzcTreeManager->UpdatePanZoomControllerTree(this, mLayerManager->GetRoot(), aIsFirstPaint, aId);
-  }
 
-  if (mLayerManager) {
-    LayerManagerComposite* managerComposite = mLayerManager->AsLayerManagerComposite();
-    if (managerComposite) {
-      managerComposite->NotifyShadowTreeTransaction();
-    }
+    mLayerManager->AsLayerManagerComposite()->NotifyShadowTreeTransaction();
   }
   ScheduleComposition();
 }
 
 void
 CompositorParent::ScheduleComposition()
 {
   if (mCurrentCompositeTask) {
@@ -598,17 +596,18 @@ CompositorParent::ShadowLayersUpdated(La
   if (layerComposite) {
     layerComposite->NotifyShadowTreeTransaction();
   }
 }
 
 PLayerTransactionParent*
 CompositorParent::AllocPLayerTransactionParent(const LayersBackend& aBackendHint,
                                                const uint64_t& aId,
-                                               TextureFactoryIdentifier* aTextureFactoryIdentifier)
+                                               TextureFactoryIdentifier* aTextureFactoryIdentifier,
+                                               bool *aSuccess)
 {
   MOZ_ASSERT(aId == 0);
 
   // mWidget doesn't belong to the compositor thread, so it should be set to
   // nullptr before returning from this method, to avoid accessing it elsewhere.
   nsIntRect rect;
   mWidget->GetClientBounds(rect);
 
@@ -620,33 +619,39 @@ CompositorParent::AllocPLayerTransaction
                                                   mUseExternalSurfaceSize));
   } else if (aBackendHint == mozilla::layers::LAYERS_BASIC) {
     mLayerManager =
       new LayerManagerComposite(new BasicCompositor(mWidget));
 #ifdef XP_WIN
   } else if (aBackendHint == mozilla::layers::LAYERS_D3D11) {
     mLayerManager =
       new LayerManagerComposite(new CompositorD3D11(mWidget));
+  } else if (aBackendHint == mozilla::layers::LAYERS_D3D9) {
+    mLayerManager =
+      new LayerManagerComposite(new CompositorD3D9(mWidget));
 #endif
   } else {
-    NS_ERROR("Unsupported backend selected for Async Compositor");
-    return nullptr;
+    NS_WARNING("Unsupported backend selected for Async Compositor");
+    *aSuccess = false;
+    return new LayerTransactionParent(nullptr, this, 0);
   }
 
   mWidget = nullptr;
   mLayerManager->SetCompositorID(mCompositorID);
 
   if (!mLayerManager->Initialize()) {
-    NS_ERROR("Failed to init Compositor");
-    return nullptr;
+    NS_WARNING("Failed to init Compositor");
+    *aSuccess = false;
+    return new LayerTransactionParent(nullptr, this, 0);
   }
 
   mCompositionManager = new AsyncCompositionManager(mLayerManager);
 
   *aTextureFactoryIdentifier = mLayerManager->GetTextureFactoryIdentifier();
+  *aSuccess = true;
   return new LayerTransactionParent(mLayerManager, this, 0);
 }
 
 bool
 CompositorParent::DeallocPLayerTransactionParent(PLayerTransactionParent* actor)
 {
   delete actor;
   return true;
@@ -826,17 +831,18 @@ public:
   virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
                                 SurfaceDescriptor* aOutSnapshot)
   { return true; }
   virtual bool RecvFlushRendering() MOZ_OVERRIDE { return true; }
 
   virtual PLayerTransactionParent*
     AllocPLayerTransactionParent(const LayersBackend& aBackendType,
                                  const uint64_t& aId,
-                                 TextureFactoryIdentifier* aTextureFactoryIdentifier) MOZ_OVERRIDE;
+                                 TextureFactoryIdentifier* aTextureFactoryIdentifier,
+                                 bool *aSuccess) MOZ_OVERRIDE;
 
   virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) MOZ_OVERRIDE;
 
   virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
                                    const TargetConfig& aTargetConfig,
                                    bool isFirstPaint) MOZ_OVERRIDE;
 
 private:
@@ -907,27 +913,32 @@ CrossProcessCompositorParent::ActorDestr
   MessageLoop::current()->PostTask(
     FROM_HERE,
     NewRunnableMethod(this, &CrossProcessCompositorParent::DeferredDestroy));
 }
 
 PLayerTransactionParent*
 CrossProcessCompositorParent::AllocPLayerTransactionParent(const LayersBackend& aBackendType,
                                                            const uint64_t& aId,
-                                                           TextureFactoryIdentifier* aTextureFactoryIdentifier)
+                                                           TextureFactoryIdentifier* aTextureFactoryIdentifier,
+                                                           bool *aSuccess)
 {
   MOZ_ASSERT(aId != 0);
 
   if (sIndirectLayerTrees[aId].mParent) {
     LayerManagerComposite* lm = sIndirectLayerTrees[aId].mParent->GetLayerManager();
     *aTextureFactoryIdentifier = lm->GetTextureFactoryIdentifier();
+    *aSuccess = true;
     return new LayerTransactionParent(lm, this, aId);
   }
 
   NS_WARNING("Created child without a matching parent?");
+  // XXX: should be false, but that causes us to fail some tests on Mac w/ OMTC.
+  // Bug 900745. change *aSuccess to false to see test failures.
+  *aSuccess = true;
   return new LayerTransactionParent(nullptr, this, aId);
 }
 
 bool
 CrossProcessCompositorParent::DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers)
 {
   LayerTransactionParent* slp = static_cast<LayerTransactionParent*>(aLayers);
   RemoveIndirectTree(slp->GetId());
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -203,17 +203,18 @@ public:
   /**
    * Returns true if the calling thrad is the compositor thread.
    */
   static bool IsInCompositorThread();
 protected:
   virtual PLayerTransactionParent*
     AllocPLayerTransactionParent(const LayersBackend& aBackendHint,
                                  const uint64_t& aId,
-                                 TextureFactoryIdentifier* aTextureFactoryIdentifier);
+                                 TextureFactoryIdentifier* aTextureFactoryIdentifier,
+                                 bool* aSuccess);
   virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers);
   virtual void ScheduleTask(CancelableTask*, int);
   virtual void Composite();
   virtual void ComposeToTarget(gfxContext* aTarget);
 
   void SetEGLSurfaceSize(int width, int height);
 
 private:
--- a/gfx/layers/ipc/ISurfaceAllocator.cpp
+++ b/gfx/layers/ipc/ISurfaceAllocator.cpp
@@ -85,17 +85,20 @@ ISurfaceAllocator::AllocSurfaceDescripto
       PlatformAllocSurfaceDescriptor(aSize, aContent, aCaps, aBuffer)) {
     return true;
   }
 
   if (XRE_GetProcessType() == GeckoProcessType_Default) {
     gfxImageFormat format =
       gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent);
     int32_t stride = gfxASurface::FormatStrideForWidth(format, aSize.width);
-    uint8_t *data = new uint8_t[stride * aSize.height];
+    uint8_t *data = new (std::nothrow) uint8_t[stride * aSize.height];
+    if (!data) {
+      return false;
+    }
 #ifdef XP_MACOSX
     // Workaround a bug in Quartz where drawing an a8 surface to another a8
     // surface with OPERATOR_SOURCE still requires the destination to be clear.
     if (format == gfxASurface::ImageFormatA8) {
       memset(data, 0, stride * aSize.height);
     }
 #endif
     *aBuffer = MemoryImage((uintptr_t)data, aSize, stride, format);
@@ -128,16 +131,17 @@ ISurfaceAllocator::DestroySharedSurface(
       DeallocShmem(aSurface->get_Shmem());
       break;
     case SurfaceDescriptor::TYCbCrImage:
       DeallocShmem(aSurface->get_YCbCrImage().data());
       break;
     case SurfaceDescriptor::TRGBImage:
       DeallocShmem(aSurface->get_RGBImage().data());
       break;
+    case SurfaceDescriptor::TSurfaceDescriptorD3D9:
     case SurfaceDescriptor::TSurfaceDescriptorD3D10:
       break;
     case SurfaceDescriptor::TMemoryImage:
       delete [] (unsigned char *)aSurface->get_MemoryImage().data();
       break;
     case SurfaceDescriptor::Tnull_t:
     case SurfaceDescriptor::T__None:
       break;
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -31,16 +31,21 @@ using mozilla::gfx::IntSize;
 namespace mozilla {
 namespace layers {
 
 union MaybeMagicGrallocBufferHandle {
   MagicGrallocBufferHandle;
   null_t;
 };
 
+struct SurfaceDescriptorD3D9 {
+  // IDirect3DTexture9*
+  uintptr_t texture;
+};
+
 struct SurfaceDescriptorD3D10 {
   WindowsHandle handle;
   bool hasAlpha;
 };
 
 struct SharedTextureDescriptor {
   SharedTextureShareType shareType;
   SharedTextureHandle handle;
@@ -119,16 +124,17 @@ struct SurfaceDescriptorShmem {
  struct SurfaceDescriptorMemory {
   uintptr_t data;
   SurfaceFormat format;
 };
 
 union SurfaceDescriptor {
   SurfaceDescriptorShmem;
   SurfaceDescriptorMemory;
+  SurfaceDescriptorD3D9;
   SurfaceDescriptorD3D10;
   SurfaceDescriptorX11;
   SharedTextureDescriptor;
   SurfaceStreamDescriptor;
   YCbCrImage;                 // XXX - deprecated
   SurfaceDescriptorGralloc;   // XXX - deprecated
   Shmem;                      // XXX - deprecated
   RGBImage;                   // XXX - deprecated
--- a/gfx/layers/ipc/PCompositor.ipdl
+++ b/gfx/layers/ipc/PCompositor.ipdl
@@ -55,13 +55,13 @@ parent:
   sync MakeSnapshot(SurfaceDescriptor inSnapshot)
     returns (SurfaceDescriptor outSnapshot);
 
   // Make sure any pending composites are started immediately and
   // block until they are completed.
   sync FlushRendering();
 
   sync PLayerTransaction(LayersBackend layersBackendHint, uint64_t id)
-    returns (TextureFactoryIdentifier textureFactoryIdentifier);
+    returns (TextureFactoryIdentifier textureFactoryIdentifier, bool success);
 };
 
 } // layers
 } // mozilla
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -156,16 +156,17 @@ struct AutoTxnEnd {
   ~AutoTxnEnd() { mTxn->End(); }
   Transaction* mTxn;
 };
 
 void
 CompositableForwarder::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier)
 {
   mTextureFactoryIdentifier = aIdentifier;
+  mMultiProcess = aIdentifier.mParentProcessId != XRE_GetProcessType();
 }
 
 ShadowLayerForwarder::ShadowLayerForwarder()
  : mShadowManager(nullptr)
  , mIsFirstPaint(false)
  , mDrawColoredBorders(false)
  , mWindowOverlayChanged(false)
 {
--- a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
+++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
@@ -114,17 +114,18 @@ SharedPlanarYCbCrImage::AllocateAndGetNe
 
 void
 SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
 {
   mData = aData;
   mSize = aData.mPicSize;
   YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer());
   serializer.InitializeBufferInfo(aData.mYSize,
-                                  aData.mCbCrSize);
+                                  aData.mCbCrSize,
+                                  aData.mStereoMode);
 }
 
 uint8_t*
 SharedPlanarYCbCrImage::AllocateBuffer(uint32_t aSize)
 {
   NS_ABORT_IF_FALSE(!mTextureClient->IsAllocated(),
                     "This image already has allocated data");
   if (!mTextureClient->Allocate(aSize)) {
@@ -148,17 +149,18 @@ SharedPlanarYCbCrImage::Allocate(PlanarY
                                                                aData.mCbCrSize);
 
   if (AllocateBuffer(static_cast<uint32_t>(size)) == nullptr) {
     return false;
   }
 
   YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer());
   serializer.InitializeBufferInfo(aData.mYSize,
-                                  aData.mCbCrSize);
+                                  aData.mCbCrSize,
+                                  aData.mStereoMode);
   MOZ_ASSERT(serializer.IsValid());
 
   aData.mYChannel = serializer.GetYData();
   aData.mCbChannel = serializer.GetCbData();
   aData.mCrChannel = serializer.GetCrData();
 
   // copy some of aData's values in mData (most of them)
   mData.mYChannel = aData.mYChannel;
@@ -234,17 +236,18 @@ DeprecatedSharedPlanarYCbCrImage::Alloca
 
 void
 DeprecatedSharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
 {
   mData = aData;
   mSize = aData.mPicSize;
   YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>());
   serializer.InitializeBufferInfo(aData.mYSize,
-                                  aData.mCbCrSize);
+                                  aData.mCbCrSize,
+                                  aData.mStereoMode);
 }
 
 uint8_t* 
 DeprecatedSharedPlanarYCbCrImage::AllocateBuffer(uint32_t aSize)
 {
   NS_ABORT_IF_FALSE(!mAllocated, "This image already has allocated data");
   SharedMemory::SharedMemoryType shmType = OptimalShmemType();
   if (!mSurfaceAllocator->AllocUnsafeShmem(aSize, shmType, &mShmem)) {
@@ -264,17 +267,18 @@ DeprecatedSharedPlanarYCbCrImage::Alloca
                                                                aData.mCbCrSize);
 
   if (AllocateBuffer(static_cast<uint32_t>(size)) == nullptr) {
     return false;
   }
 
   YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>());
   serializer.InitializeBufferInfo(aData.mYSize,
-                                  aData.mCbCrSize);
+                                  aData.mCbCrSize,
+                                  aData.mStereoMode);
   if (!serializer.IsValid() || mShmem.Size<uint8_t>() < size) {
     mSurfaceAllocator->DeallocShmem(mShmem);
     return false;
   }
 
   aData.mYChannel = serializer.GetYData();
   aData.mCbChannel = serializer.GetCbData();
   aData.mCrChannel = serializer.GetCrData();
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -47,17 +47,23 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind
     CPP_SOURCES += [
         'D3D9SurfaceImage.cpp',
     ]
     if CONFIG['MOZ_ENABLE_D3D9_LAYER']:
         EXPORTS += [
             'd3d9/DeviceManagerD3D9.h',
             'd3d9/LayerManagerD3D9.h',
         ]
+        EXPORTS.mozilla.layers += [
+            'CompositorD3D9.h',
+            'TextureD3D9.h',
+        ]
         CPP_SOURCES += [
+            'CompositorD3D9.cpp',
+            'TextureD3D9.cpp',
             'LayerManagerD3D9.cpp',
             'ThebesLayerD3D9.cpp',
             'ContainerLayerD3D9.cpp',
             'ImageLayerD3D9.cpp',
             'ColorLayerD3D9.cpp',
             'CanvasLayerD3D9.cpp',
             'DeviceManagerD3D9.cpp',
             'Nv3DVUtils.cpp',
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -39,16 +39,17 @@ public:
 
   virtual bool Initialize() MOZ_OVERRIDE;
 
   virtual void Destroy() MOZ_OVERRIDE;
 
   virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() MOZ_OVERRIDE
   {
     return TextureFactoryIdentifier(LAYERS_OPENGL,
+                                    XRE_GetProcessType(),
                                     GetMaxTextureSize(),
                                     mFBOTextureTarget == LOCAL_GL_TEXTURE_2D,
                                     SupportsPartialTextureUpdate());
   }
 
   virtual TemporaryRef<CompositingRenderTarget> 
   CreateRenderTarget(const gfx::IntRect &aRect, SurfaceInitMode aInit) MOZ_OVERRIDE;
 
--- a/gfx/layers/opengl/TextureClientOGL.cpp
+++ b/gfx/layers/opengl/TextureClientOGL.cpp
@@ -73,18 +73,19 @@ DeprecatedTextureClientSharedOGL::Releas
     return;
   }
   MOZ_ASSERT(mDescriptor.type() == SurfaceDescriptor::TSharedTextureDescriptor);
   mDescriptor = SurfaceDescriptor();
   // It's important our handle gets released! SharedDeprecatedTextureHostOGL will take
   // care of this for us though.
 }
 
-void
+bool
 DeprecatedTextureClientSharedOGL::EnsureAllocated(gfx::IntSize aSize,
                                         gfxASurface::gfxContentType aContentType)
 {
   mSize = aSize;
+  return true;
 }
 
 
 } // namespace
 } // namespace
--- a/gfx/layers/opengl/TextureClientOGL.h
+++ b/gfx/layers/opengl/TextureClientOGL.h
@@ -51,17 +51,17 @@ protected:
 
 class DeprecatedTextureClientSharedOGL : public DeprecatedTextureClient
 {
 public:
   DeprecatedTextureClientSharedOGL(CompositableForwarder* aForwarder, const TextureInfo& aTextureInfo);
   ~DeprecatedTextureClientSharedOGL() { ReleaseResources(); }
 
   virtual bool SupportsType(DeprecatedTextureClientType aType) MOZ_OVERRIDE { return aType == TEXTURE_SHARED_GL; }
-  virtual void EnsureAllocated(gfx::IntSize aSize, gfxASurface::gfxContentType aType);
+  virtual bool EnsureAllocated(gfx::IntSize aSize, gfxASurface::gfxContentType aType);
   virtual void ReleaseResources();
   virtual gfxASurface::gfxContentType GetContentType() MOZ_OVERRIDE { return gfxASurface::CONTENT_COLOR_ALPHA; }
 
 protected:
   gl::GLContext* mGL;
   gfx::IntSize mSize;
 
   friend class CompositingFactory;
@@ -83,17 +83,17 @@ class DeprecatedTextureClientStreamOGL :
 {
 public:
   DeprecatedTextureClientStreamOGL(CompositableForwarder* aForwarder, const TextureInfo& aTextureInfo)
     : DeprecatedTextureClient(aForwarder, aTextureInfo)
   {}
   ~DeprecatedTextureClientStreamOGL() { ReleaseResources(); }
 
   virtual bool SupportsType(DeprecatedTextureClientType aType) MOZ_OVERRIDE { return aType == TEXTURE_STREAM_GL; }
-  virtual void EnsureAllocated(gfx::IntSize aSize, gfxASurface::gfxContentType aType) { }
+  virtual bool EnsureAllocated(gfx::IntSize aSize, gfxASurface::gfxContentType aType) { return true; }
   virtual void ReleaseResources() { mDescriptor = SurfaceDescriptor(); }
   virtual gfxASurface::gfxContentType GetContentType() MOZ_OVERRIDE { return gfxASurface::CONTENT_COLOR_ALPHA; }
 };
 
 } // namespace
 } // namespace
 
 #endif
--- a/gfx/thebes/gfxCachedTempSurface.cpp
+++ b/gfx/thebes/gfxCachedTempSurface.cpp
@@ -68,35 +68,31 @@ gfxCachedTempSurface::~gfxCachedTempSurf
 already_AddRefed<gfxContext>
 gfxCachedTempSurface::Get(gfxASurface::gfxContentType aContentType,
                           const gfxRect& aRect,
                           gfxASurface* aSimilarTo)
 {
   if (mSurface) {
     /* Verify the current buffer is valid for this purpose */
     if (mSize.width < aRect.width || mSize.height < aRect.height
-        || mSurface->GetContentType() != aContentType) {
+        || mSurface->GetContentType() != aContentType
+        || mType != aSimilarTo->GetType()) {
       mSurface = nullptr;
-    } else {
-      NS_ASSERTION(mType == aSimilarTo->GetType(),
-                   "Unexpected surface type change");
     }
   }
 
   bool cleared = false;
   if (!mSurface) {
     mSize = gfxIntSize(int32_t(ceil(aRect.width)), int32_t(ceil(aRect.height)));
     mSurface = aSimilarTo->CreateSimilarSurface(aContentType, mSize);
     if (!mSurface)
       return nullptr;
 
     cleared = true;
-#ifdef DEBUG
     mType = aSimilarTo->GetType();
-#endif
   }
   mSurface->SetDeviceOffset(-aRect.TopLeft());
 
   nsRefPtr<gfxContext> ctx = new gfxContext(mSurface);
   ctx->Rectangle(aRect);
   ctx->Clip();
   if (!cleared && aContentType != gfxASurface::CONTENT_COLOR) {
     ctx->SetOperator(gfxContext::OPERATOR_CLEAR);
--- a/gfx/thebes/gfxCachedTempSurface.h
+++ b/gfx/thebes/gfxCachedTempSurface.h
@@ -28,33 +28,30 @@ public:
    * Returns a context for a surface that can be efficiently copied to
    * |aSimilarTo|.
    *
    * When |aContentType| has an alpha component, the surface will be cleared.
    * For opaque surfaces, the initial surface contents are undefined.
    * When |aContentType| differs in different invocations this is handled
    * appropriately, creating a new surface if necessary.
    * 
-   * |aSimilarTo| should be of the same gfxSurfaceType in each invocation.
    * Because the cached surface may have been created during a previous
    * invocation, this will not be efficient if the new |aSimilarTo| has a
-   * different format.
+   * different format, size, or gfxSurfaceType.
    */
   already_AddRefed<gfxContext> Get(gfxASurface::gfxContentType aContentType,
                                    const gfxRect& aRect,
                                    gfxASurface* aSimilarTo);
 
   void Expire() { mSurface = nullptr; }
   nsExpirationState* GetExpirationState() { return &mExpirationState; }
   ~gfxCachedTempSurface();
 
   bool IsSurface(gfxASurface* aSurface) { return mSurface == aSurface; }
 
 private:
   nsRefPtr<gfxASurface> mSurface;
   gfxIntSize mSize;
   nsExpirationState mExpirationState;
-#ifdef DEBUG
   gfxASurface::gfxSurfaceType mType;
-#endif 
 };
 
 #endif /* GFX_CACHED_TEMP_SURFACE_H */
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -72,25 +72,28 @@
 #include "skia/GrContext.h"
 #include "skia/GrGLInterface.h"
 #include "GLContextSkia.h"
 #endif
 
 #include "mozilla/Preferences.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/Mutex.h"
 
 #include "nsIGfxInfo.h"
 
 using namespace mozilla;
 using namespace mozilla::layers;
 
 gfxPlatform *gPlatform = nullptr;
 static bool gEverInitialized = false;
 
+static Mutex* gGfxPlatformPrefsLock = nullptr;
+
 // These two may point to the same profile
 static qcms_profile *gCMSOutputProfile = nullptr;
 static qcms_profile *gCMSsRGBProfile = nullptr;
 
 static qcms_transform *gCMSRGBTransform = nullptr;
 static qcms_transform *gCMSInverseRGBTransform = nullptr;
 static qcms_transform *gCMSRGBATransform = nullptr;
 
@@ -308,16 +311,18 @@ gfxPlatform::Init()
 #ifdef PR_LOGGING
     sFontlistLog = PR_NewLogModule("fontlist");;
     sFontInitLog = PR_NewLogModule("fontinit");;
     sTextrunLog = PR_NewLogModule("textrun");;
     sTextrunuiLog = PR_NewLogModule("textrunui");;
     sCmapDataLog = PR_NewLogModule("cmapdata");;
 #endif
 
+    gGfxPlatformPrefsLock = new Mutex("gfxPlatform::gGfxPlatformPrefsLock");
+
     /* Initialize the GfxInfo service.
      * Note: we can't call functions on GfxInfo that depend
      * on gPlatform until after it has been initialized
      * below. GfxInfo initialization annotates our
      * crash reports so we want to do it before
      * we try to load any drivers and do device detection
      * incase that code crashes. See bug #591561. */
     nsCOMPtr<nsIGfxInfo> gfxInfo;
@@ -470,16 +475,18 @@ gfxPlatform::Shutdown()
 #endif
 
     // This will block this thread untill the ImageBridge protocol is completely
     // deleted.
     ImageBridgeChild::ShutDown();
 
     CompositorParent::ShutDown();
 
+    delete gGfxPlatformPrefsLock;
+
     delete gPlatform;
     gPlatform = nullptr;
 }
 
 gfxPlatform::~gfxPlatform()
 {
     mScreenReferenceSurface = nullptr;
 
@@ -1851,72 +1858,119 @@ gfxPlatform::GetOrientationSyncMillis() 
  */
 static bool sPrefLayersOffMainThreadCompositionEnabled = false;
 static bool sPrefLayersOffMainThreadCompositionTestingEnabled = false;
 static bool sPrefLayersOffMainThreadCompositionForceEnabled = false;
 static bool sPrefLayersAccelerationForceEnabled = false;
 static bool sPrefLayersAccelerationDisabled = false;
 static bool sPrefLayersPreferOpenGL = false;
 static bool sPrefLayersPreferD3D9 = false;
+static bool sLayersSupportsD3D9 = true;
 static int  sPrefLayoutFrameRate = -1;
+static bool sBufferRotationEnabled = false;
 
-void InitLayersAccelerationPrefs()
+static bool sLayersAccelerationPrefsInitialized = false;
+
+void
+InitLayersAccelerationPrefs()
 {
-  static bool sLayersAccelerationPrefsInitialized = false;
   if (!sLayersAccelerationPrefsInitialized)
   {
     sPrefLayersOffMainThreadCompositionEnabled = Preferences::GetBool("layers.offmainthreadcomposition.enabled", false);
     sPrefLayersOffMainThreadCompositionTestingEnabled = Preferences::GetBool("layers.offmainthreadcomposition.testing.enabled", false);
     sPrefLayersOffMainThreadCompositionForceEnabled = Preferences::GetBool("layers.offmainthreadcomposition.force-enabled", false);
     sPrefLayersAccelerationForceEnabled = Preferences::GetBool("layers.acceleration.force-enabled", false);
     sPrefLayersAccelerationDisabled = Preferences::GetBool("layers.acceleration.disabled", false);
     sPrefLayersPreferOpenGL = Preferences::GetBool("layers.prefer-opengl", false);
     sPrefLayersPreferD3D9 = Preferences::GetBool("layers.prefer-d3d9", false);
     sPrefLayoutFrameRate = Preferences::GetInt("layout.frame_rate", -1);
+    sBufferRotationEnabled = Preferences::GetBool("layers.bufferrotation.enabled", true);
+
+    nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
+    if (gfxInfo) {
+      int32_t status;
+      if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, &status))) {
+        if (status != nsIGfxInfo::FEATURE_NO_INFO && !sPrefLayersAccelerationForceEnabled) {
+          sLayersSupportsD3D9 = false;
+        }
+      }
+    }
 
     sLayersAccelerationPrefsInitialized = true;
   }
 }
 
-bool gfxPlatform::GetPrefLayersOffMainThreadCompositionEnabled()
+bool
+gfxPlatform::GetPrefLayersOffMainThreadCompositionEnabled()
 {
   InitLayersAccelerationPrefs();
   return sPrefLayersOffMainThreadCompositionEnabled ||
          sPrefLayersOffMainThreadCompositionForceEnabled ||
          sPrefLayersOffMainThreadCompositionTestingEnabled;
 }
 
-bool gfxPlatform::GetPrefLayersOffMainThreadCompositionForceEnabled()
+bool
+gfxPlatform::GetPrefLayersOffMainThreadCompositionForceEnabled()
 {
   InitLayersAccelerationPrefs();
   return sPrefLayersOffMainThreadCompositionForceEnabled;
 }
 
-bool gfxPlatform::GetPrefLayersAccelerationForceEnabled()
+bool
+gfxPlatform::GetPrefLayersAccelerationForceEnabled()
 {
   InitLayersAccelerationPrefs();
   return sPrefLayersAccelerationForceEnabled;
 }
 
 bool
 gfxPlatform::GetPrefLayersAccelerationDisabled()
 {
   InitLayersAccelerationPrefs();
   return sPrefLayersAccelerationDisabled;
 }
 
-bool gfxPlatform::GetPrefLayersPreferOpenGL()
+bool
+gfxPlatform::GetPrefLayersPreferOpenGL()
 {
   InitLayersAccelerationPrefs();
   return sPrefLayersPreferOpenGL;
 }
 
-bool gfxPlatform::GetPrefLayersPreferD3D9()
+bool
+gfxPlatform::GetPrefLayersPreferD3D9()
 {
   InitLayersAccelerationPrefs();
   return sPrefLayersPreferD3D9;
 }
 
-int gfxPlatform::GetPrefLayoutFrameRate()
+bool
+gfxPlatform::CanUseDirect3D9()
+{
+  // this function is called from the compositor thread, so it is not
+  // safe to init the prefs etc. from here.
+  MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
+  return sLayersSupportsD3D9;
+}
+
+int
+gfxPlatform::GetPrefLayoutFrameRate()
 {
   InitLayersAccelerationPrefs();
   return sPrefLayoutFrameRate;
 }
+
+bool
+gfxPlatform::BufferRotationEnabled()
+{
+  MutexAutoLock autoLock(*gGfxPlatformPrefsLock);
+
+  InitLayersAccelerationPrefs();
+  return sBufferRotationEnabled;
+}
+
+void
+gfxPlatform::DisableBufferRotation()
+{
+  MutexAutoLock autoLock(*gGfxPlatformPrefsLock);
+
+  sBufferRotationEnabled = false;
+}
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -466,19 +466,25 @@ public:
      * only once, and remain the same until restart.
      */
     static bool GetPrefLayersOffMainThreadCompositionEnabled();
     static bool GetPrefLayersOffMainThreadCompositionForceEnabled();
     static bool GetPrefLayersAccelerationForceEnabled();
     static bool GetPrefLayersAccelerationDisabled();
     static bool GetPrefLayersPreferOpenGL();
     static bool GetPrefLayersPreferD3D9();
+    static bool CanUseDirect3D9();
     static int  GetPrefLayoutFrameRate();
 
     /**
+     * Is it possible to use buffer rotation
+     */
+    static bool BufferRotationEnabled();
+    static void DisableBufferRotation();
+    /**
      * Are we going to try color management?
      */
     static eCMSMode GetCMSMode();
 
     /**
      * Determines the rendering intent for color management.
      *
      * If the value in the pref gfx.color_management.rendering_intent is a
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -23,30 +23,33 @@
 
 #include "nsIGfxInfo.h"
 
 #include "gfxCrashReporterUtils.h"
 
 #include "gfxGDIFontList.h"
 #include "gfxGDIFont.h"
 
+#include "DeviceManagerD3D9.h"
+
 #ifdef CAIRO_HAS_DWRITE_FONT
 #include "gfxDWriteFontList.h"
 #include "gfxDWriteFonts.h"
 #include "gfxDWriteCommon.h"
 #include <dwrite.h>
 #endif
 
 #include "gfxUserFontSet.h"
 #include "nsWindowsHelpers.h"
 
 #include <string>
 
 using namespace mozilla;
 using namespace mozilla::gfx;
+using namespace mozilla::layers;
 
 #ifdef CAIRO_HAS_D2D_SURFACE
 #include "gfxD2DSurface.h"
 
 #include <d3d10_1.h>
 
 #include "mozilla/gfx/2D.h"
 
@@ -345,17 +348,18 @@ static __inline void
 BuildKeyNameFromFontName(nsAString &aName)
 {
     if (aName.Length() >= LF_FACESIZE)
         aName.Truncate(LF_FACESIZE - 1);
     ToLowerCase(aName);
 }
 
 gfxWindowsPlatform::gfxWindowsPlatform()
-  : mD3D11DeviceInitialized(false)
+  : mD3D9DeviceInitialized(false)
+  , mD3D11DeviceInitialized(false)
 {
     mPrefFonts.Init(50);
 
     mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
     mUseClearTypeAlways = UNINITIALIZED_VALUE;
 
     mUsingGDIFonts = false;
 
@@ -379,16 +383,18 @@ gfxWindowsPlatform::gfxWindowsPlatform()
     mGPUAdapterMultiReporter = new GPUAdapterMultiReporter();
     NS_RegisterMemoryMultiReporter(mGPUAdapterMultiReporter);
 }
 
 gfxWindowsPlatform::~gfxWindowsPlatform()
 {
     NS_UnregisterMemoryMultiReporter(mGPUAdapterMultiReporter);
     
+     mDeviceManager = nullptr;
+     
     ::ReleaseDC(nullptr, mScreenDC);
     // not calling FT_Done_FreeType because cairo may still hold references to
     // these FT_Faces.  See bug 458169.
 #ifdef CAIRO_HAS_D2D_SURFACE
     if (mD2DDevice) {
         cairo_release_device(mD2DDevice);
     }
 #endif
@@ -1442,16 +1448,39 @@ gfxWindowsPlatform::SetupClearTypeParams
 
         GetDWriteFactory()->CreateCustomRenderingParams(gamma, contrast, level,
 	    dwriteGeometry, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC,
             getter_AddRefs(mRenderingParams[TEXT_RENDERING_GDI_CLASSIC]));
     }
 #endif
 }
 
+IDirect3DDevice9*
+gfxWindowsPlatform::GetD3D9Device()
+{
+  DeviceManagerD3D9* manager = GetD3D9DeviceManager();
+  return manager ? manager->device() : nullptr;
+}
+
+DeviceManagerD3D9*
+gfxWindowsPlatform::GetD3D9DeviceManager()
+{
+  if (!mD3D9DeviceInitialized) {
+    mD3D9DeviceInitialized = true;
+
+    mDeviceManager = new DeviceManagerD3D9();
+    if (!mDeviceManager->Init()) {
+      NS_WARNING("Could not initialise devive manager");
+      mDeviceManager = nullptr;
+    }
+  }
+
+  return mDeviceManager;
+}
+
 ID3D11Device*
 gfxWindowsPlatform::GetD3D11Device()
 {
   if (mD3D11DeviceInitialized) {
     return mD3D11Device;
   }
 
   mD3D11DeviceInitialized = true;
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -38,16 +38,22 @@
 #include <d3dcommon.h>
 // Win 8.0 SDK types we'll need when building using older sdks.
 #if !defined(D3D_FEATURE_LEVEL_11_1) // defined in the 8.0 SDK only
 #define D3D_FEATURE_LEVEL_11_1 static_cast<D3D_FEATURE_LEVEL>(0xb100)
 #define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048
 #define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096
 #endif
 
+namespace mozilla {
+namespace layers {
+class DeviceManagerD3D9;
+}
+}
+class IDirect3DDevice9;
 class ID3D11Device;
 class IDXGIAdapter1;
 
 class nsIMemoryMultiReporter;
 
 // Utility to get a Windows HDC from a thebes context,
 // used by both GDI and Uniscribe font shapers
 struct DCFromContext {
@@ -260,16 +266,18 @@ public:
     inline DWRITE_MEASURING_MODE DWriteMeasuringMode() { return mMeasuringMode; }
     IDWriteTextAnalyzer *GetDWriteAnalyzer() { return mDWriteAnalyzer; }
 
     IDWriteRenderingParams *GetRenderingParams(TextRenderingMode aRenderMode)
     { return mRenderingParams[aRenderMode]; }
 #else
     inline bool DWriteEnabled() { return false; }
 #endif
+    mozilla::layers::DeviceManagerD3D9* GetD3D9DeviceManager();
+    IDirect3DDevice9* GetD3D9Device();
 #ifdef CAIRO_HAS_D2D_SURFACE
     cairo_device_t *GetD2DDevice() { return mD2DDevice; }
     ID3D10Device1 *GetD3D10Device() { return mD2DDevice ? cairo_d2d_device_get_device(mD2DDevice) : nullptr; }
 #endif
     ID3D11Device *GetD3D11Device();
 
     static bool IsOptimus();
 
@@ -292,17 +300,19 @@ private:
     nsRefPtr<IDWriteTextAnalyzer> mDWriteAnalyzer;
     nsRefPtr<IDWriteRenderingParams> mRenderingParams[TEXT_RENDERING_COUNT];
     DWRITE_MEASURING_MODE mMeasuringMode;
 #endif
 #ifdef CAIRO_HAS_D2D_SURFACE
     cairo_device_t *mD2DDevice;
 #endif
     mozilla::RefPtr<IDXGIAdapter1> mAdapter;
+    nsRefPtr<mozilla::layers::DeviceManagerD3D9> mDeviceManager;
     mozilla::RefPtr<ID3D11Device> mD3D11Device;
+    bool mD3D9DeviceInitialized;
     bool mD3D11DeviceInitialized;
 
     virtual qcms_profile* GetPlatformCMSOutputProfile();
 
     // TODO: unify this with mPrefFonts (NB: holds families, not fonts) in gfxPlatformFontList
     nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<gfxFontEntry> > > mPrefFonts;
 
     nsIMemoryMultiReporter* mGPUAdapterMultiReporter;
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1636,24 +1636,24 @@ HTTP(..) == 621253-2-externalFilter.html
 skip-if(B2G) random-if(winWidget) fuzzy-if(OSX==10.8,19,17) == 621918-1.svg 621918-1-ref.svg # 1-pixel diacritic positioning discrepancy in rotated text (may depend on platform fonts)
 random-if(winWidget) HTTP(..) == 621918-2.svg 621918-2-ref.svg # same 1px issue as above, and HTTP(..) for filters.svg, used to mask antialiasing issues where glyphs touch
 fuzzy-if(d2d,5,1) == 622585-1.html 622585-1-ref.html # bug 789402
 fuzzy-if(Android&&AndroidVersion>=15,8,100) == 625409-1.html 625409-1-ref.html
 == 627393-1.html about:blank
 == 630835-1.html about:blank
 == 631352-1.html 631352-1-ref.html
 skip-if(B2G) fails-if(Android) == 632423-1.html 632423-1-ref.html
-skip-if(Android||B2G) random-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == 632781-verybig.html 632781-ref.html
+skip-if(Android||B2G) random-if(winWidget&&!d2d) == 632781-verybig.html 632781-ref.html
 == 632781-normalsize.html 632781-ref.html
 fails-if(Android) == 633344-1.html 633344-1-ref.html
 == 634232-1.html 634232-1-ref.html
 fails-if(Android) == 635302-1.html 635302-1-ref.html
-skip-if(B2G) random-if(d2d) fails-if(Android) == 635373-1.html 635373-1-ref.html
-skip-if(B2G) random-if(d2d) fails-if(Android) == 635373-2.html 635373-2-ref.html
-skip-if(B2G) random-if(d2d) fails-if(Android) == 635373-3.html 635373-3-ref.html
+skip-if(B2G) random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,1,11) == 635373-1.html 635373-1-ref.html
+skip-if(B2G) random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,1,15) == 635373-2.html 635373-2-ref.html
+skip-if(B2G) random-if(d2d) fails-if(Android) fuzzy-if(winWidget&&!d2d,1,15) == 635373-3.html 635373-3-ref.html
 HTTP(..) == 635639-1.html 635639-1-ref.html
 HTTP(..) == 635639-2.html 635639-2-ref.html
 random == 637597-1.html 637597-1-ref.html # bug 637597 was never really fixed!
 skip-if(B2G) fuzzy-if(Android&&AndroidVersion>=15,8,500) == 637852-1.html 637852-1-ref.html # bug 839735
 == 637852-2.html 637852-2-ref.html
 fuzzy-if(Android&&AndroidVersion>=15,8,500) == 637852-3.html 637852-3-ref.html
 skip-if(B2G) == 641770-1.html 641770-1-ref.html
 == 641856-1.html 641856-1-ref.html
--- a/layout/reftests/ogg-video/reftest.list
+++ b/layout/reftests/ogg-video/reftest.list
@@ -12,17 +12,17 @@ fails-if(Android||B2G) HTTP(..) == canva
 == empty-1a.html empty-1-ref.html
 == empty-1b.html empty-1-ref.html
 #these is skipped because we hang on the htmlparser tests when this is ran
 random skip-if(Android||B2G) HTTP(..) == object-aspect-ratio-1a.xhtml aspect-ratio-1-ref.html
 random skip-if(Android||B2G) HTTP(..) == object-aspect-ratio-1b.xhtml aspect-ratio-1-ref.html
 skip-if(Android||B2G) HTTP(..) == offset-1.xhtml offset-1-ref.html
 random skip-if(Android||B2G) HTTP(..) == object-aspect-ratio-2a.xhtml aspect-ratio-2-ref.html
 random skip-if(Android||B2G) HTTP(..) == object-aspect-ratio-2b.xhtml aspect-ratio-2-ref.html
-skip-if(Android||B2G) skip-if(gtk2Widget) fuzzy-if(/^Windows\x20NT\x205\.1/.test(http.oscpu),1,56000) fuzzy-if(cocoaWidget,1,56000) fuzzy-if(d2d&&layersGPUAccelerated,1,56000) HTTP(..) == zoomed-1.xhtml zoomed-1-ref.html # bug 778995 for fuzzy
+skip-if(Android||B2G) skip-if(gtk2Widget) fuzzy-if(winWidget,1,56000) fuzzy-if(cocoaWidget,1,56000) HTTP(..) == zoomed-1.xhtml zoomed-1-ref.html # bug 778995 for fuzzy
 skip-if(Android||B2G) == poster-1.html poster-ref-blue250x200.html
 skip-if(Android||B2G) == poster-2.html poster-ref-black140x100.html
 skip-if(Android||B2G) == poster-3.html poster-ref-black140x100.html
 skip-if(Android||B2G) == poster-4.html poster-ref-black140x100.html
 skip-if(Android||B2G) == poster-5.html poster-ref-black140x100.html
 skip-if(Android||B2G) == poster-6.html poster-ref-black140x100.html
 skip-if(Android||B2G) == poster-7.html poster-ref-red140x100.html
 skip-if(Android||B2G) == poster-8.html poster-ref-black140x100.html
--- a/layout/reftests/transform-3d/reftest.list
+++ b/layout/reftests/transform-3d/reftest.list
@@ -17,18 +17,18 @@ fails-if(Android) == rotatex-perspective
 == preserve3d-2a.html preserve3d-2-ref.html
 == preserve3d-2b.html preserve3d-2-ref.html
 == preserve3d-2c.html preserve3d-2-ref.html
 == preserve3d-2d.html preserve3d-2-ref.html
 == preserve3d-3a.html preserve3d-3-ref.html
 skip-if(B2G) == preserve3d-4a.html green-rect.html
 fuzzy-if(Android&&AndroidVersion>=15,4,300) == preserve3d-5a.html preserve3d-5-ref.html
 == scale3d-z.html scalez-1-ref.html
-fuzzy-if(winWidget&&!layersGPUAccelerated,102,580) fuzzy-if(d2d,143,681) fails-if(Android) fuzzy-if(OSX==10.8,145,752) == scale3d-all.html scale3d-1-ref.html # subpixel AA
-fuzzy-if(winWidget&&!layersGPUAccelerated,102,580) fuzzy-if(d2d,143,681) fails-if(Android) fuzzy-if(OSX==10.8,145,752) == scale3d-all-separate.html scale3d-1-ref.html # subpixel AA
+fuzzy-if(winWidget,102,580) fuzzy-if(d2d,143,681) fails-if(Android) fuzzy-if(OSX==10.8,145,752) == scale3d-all.html scale3d-1-ref.html # subpixel AA
+fuzzy-if(winWidget,102,580) fuzzy-if(d2d,143,681) fails-if(Android) fuzzy-if(OSX==10.8,145,752) == scale3d-all-separate.html scale3d-1-ref.html # subpixel AA
 == scale3d-xz.html scale3d-1-ref.html
 == translatez-1a.html translatez-1-ref.html
 != translatez-1b.html translatez-1-ref.html
 == translate3d-1a.html translate3d-1-ref.html
 == matrix3d-1a.html matrix3d-1-ref.html
 == matrix3d-2a.html matrix3d-2-ref.html
 == rotate3d-1a.html rotatex-1-ref.html
 == rotate3d-2a.html rotatey-1-ref.html
--- a/layout/reftests/webm-video/reftest.list
+++ b/layout/reftests/webm-video/reftest.list
@@ -12,17 +12,17 @@ fails-if(Android||B2G) HTTP(..) == canva
 == empty-1a.html empty-1-ref.html
 == empty-1b.html empty-1-ref.html
 #these is skipped because we hang on the htmlparser tests when this is ran
 random skip-if(Android||B2G) HTTP(..) == object-aspect-ratio-1a.xhtml aspect-ratio-1-ref.html
 random skip-if(Android||B2G) HTTP(..) == object-aspect-ratio-1b.xhtml aspect-ratio-1-ref.html
 skip-if(Android||B2G) HTTP(..) == offset-1.xhtml offset-1-ref.html
 random skip-if(Android||B2G) HTTP(..) == object-aspect-ratio-2a.xhtml aspect-ratio-2-ref.html
 random skip-if(Android||B2G) HTTP(..) == object-aspect-ratio-2b.xhtml aspect-ratio-2-ref.html
-skip-if(Android||B2G) skip-if(gtk2Widget) fuzzy-if(/^Windows\x20NT\x205\.1/.test(http.oscpu),1,56000) fuzzy-if(cocoaWidget,1,56000) fuzzy-if(d2d&&layersGPUAccelerated,1,56000) HTTP(..) == zoomed-1.xhtml zoomed-1-ref.html # bug 778995 for fuzzy
+skip-if(Android||B2G) skip-if(gtk2Widget) fuzzy-if(winWidget,1,56000) fuzzy-if(cocoaWidget,1,56000) HTTP(..) == zoomed-1.xhtml zoomed-1-ref.html # bug 778995 for fuzzy
 skip-if(Android||B2G) == poster-1.html poster-ref-blue250x200.html
 skip-if(Android||B2G) == poster-2.html poster-ref-black140x100.html
 skip-if(Android||B2G) == poster-3.html poster-ref-black140x100.html
 skip-if(Android||B2G) == poster-4.html poster-ref-black140x100.html
 skip-if(Android||B2G) == poster-5.html poster-ref-black140x100.html
 skip-if(Android||B2G) == poster-6.html poster-ref-black140x100.html
 skip-if(Android||B2G) == poster-7.html poster-ref-red140x100.html
 skip-if(Android||B2G) == poster-8.html poster-ref-black140x100.html
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -4083,16 +4083,18 @@ pref("layers.offmainthreadcomposition.en
 // same effect as layers.offmainthreadcomposition.enabled, but specifically for
 // use with tests.
 pref("layers.offmainthreadcomposition.testing.enabled", false);
 // Whether to animate simple opacity and transforms on the compositor
 pref("layers.offmainthreadcomposition.async-animations", false);
 // Whether to prefer normal memory over shared memory. Ignored with cross-process compositing
 pref("layers.prefer-memory-over-shmem", true);
 
+pref("layers.bufferrotation.enabled", true);
+
 #ifdef MOZ_X11
 #ifdef MOZ_WIDGET_GTK2
 pref("gfx.xrender.enabled",true);
 #endif
 #endif
 
 #ifdef XP_WIN
 // Whether to disable the automatic detection and use of direct2d.
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -6546,16 +6546,30 @@ nsWindow::StartAllowingD3D9(bool aReinit
 
   if (aReinitialize) {
     EnumAllWindows(AllowD3D9WithReinitializeCallback);
   } else {
     EnumAllWindows(AllowD3D9Callback);
   }
 }
 
+mozilla::layers::LayersBackend
+nsWindow::GetPreferredCompositorBackend()
+{
+  LayerManagerPrefs prefs;
+  GetLayerManagerPrefs(&prefs);
+  if (prefs.mDisableAcceleration) {
+    return mozilla::layers::LAYERS_BASIC;
+  }
+  if (prefs.mPreferD3D9) {
+    return mozilla::layers::LAYERS_D3D9;
+  }
+  return mozilla::layers::LAYERS_D3D11;
+}
+
 bool
 nsWindow::HasBogusPopupsDropShadowOnMultiMonitor() {
   if (sHasBogusPopupsDropShadowOnMultiMonitor == TRI_UNKNOWN) {
     // Since any change in the preferences requires a restart, this can be
     // done just once.
     // Check for Direct2D first.
     sHasBogusPopupsDropShadowOnMultiMonitor =
       gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -268,17 +268,17 @@ public:
   NS_IMETHOD              ReparentNativeWidget(nsIWidget* aNewParent);
 
   // Open file picker tracking
   void                    PickerOpen();
   void                    PickerClosed();
 
   bool                    const DestroyCalled() { return mDestroyCalled; }
 
-  virtual mozilla::layers::LayersBackend GetPreferredCompositorBackend() { return mozilla::layers::LAYERS_D3D11; }
+  virtual mozilla::layers::LayersBackend GetPreferredCompositorBackend();
 
 protected:
 
   // A magic number to identify the FAKETRACKPOINTSCROLLABLE window created
   // when the trackpoint hack is enabled.
   enum { eFakeTrackPointScrollableID = 0x46545053 };
 
   /**
--- a/widget/xpwidgets/nsBaseWidget.cpp
+++ b/widget/xpwidgets/nsBaseWidget.cpp
@@ -942,36 +942,36 @@ void nsBaseWidget::CreateCompositor(int 
   mCompositorChild = new CompositorChild(lm);
   AsyncChannel::Side childSide = mozilla::ipc::AsyncChannel::Child;
   mCompositorChild->Open(parentChannel, childMessageLoop, childSide);
 
   TextureFactoryIdentifier textureFactoryIdentifier;
   PLayerTransactionChild* shadowManager;
   mozilla::layers::LayersBackend backendHint = GetPreferredCompositorBackend();
 
+  bool success;
   shadowManager = mCompositorChild->SendPLayerTransactionConstructor(
-    backendHint, 0, &textureFactoryIdentifier);
+    backendHint, 0, &textureFactoryIdentifier, &success);
 
-  if (shadowManager) {
+  if (success) {
     ShadowLayerForwarder* lf = lm->AsShadowForwarder();
     if (!lf) {
       delete lm;
       mCompositorChild = nullptr;
       return;
     }
     lf->SetShadowManager(shadowManager);
     lf->IdentifyTextureHost(textureFactoryIdentifier);
     ImageBridgeChild::IdentifyCompositorTextureHost(textureFactoryIdentifier);
 
     mLayerManager = lm;
     return;
   }
 
-  // Failed to create a compositor!
-  NS_WARNING("Failed to create an OMT compositor.");
+  NS_ASSERTION(false, "Failed to create an OMT compositor.");
   DestroyCompositor();
   // Compositor child had the only reference to LayerManager and will have
   // deallocated it when being freed.
 }
 
 bool nsBaseWidget::IsSmallPopup()
 {
   return mWindowType == eWindowType_popup &&