Bug 648480 - Add shadow-layer support to d3d9 backend. r=cjones
☠☠ backed out by aee2858cf8aa ☠ ☠
authorBenoit Girard <b56girard@gmail.com>
Fri, 01 Jul 2011 16:57:15 -0400
changeset 72216 627489bb6288437a40d3b10ae9c2aa7c9a26c5c1
parent 72215 0d425ab8eb132efbcb78918d70694421b817bf69
child 72217 fac8fa6cc4b521a92111053e8504be077e08c0f0
push id20667
push usermak77@bonardo.net
push dateSat, 02 Jul 2011 08:40:37 +0000
treeherdermozilla-central@cff486d4d6a4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs648480
milestone7.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 648480 - Add shadow-layer support to d3d9 backend. r=cjones
gfx/layers/Makefile.in
gfx/layers/d3d9/CanvasLayerD3D9.cpp
gfx/layers/d3d9/CanvasLayerD3D9.h
gfx/layers/d3d9/ColorLayerD3D9.cpp
gfx/layers/d3d9/ColorLayerD3D9.h
gfx/layers/d3d9/ContainerLayerD3D9.cpp
gfx/layers/d3d9/ContainerLayerD3D9.h
gfx/layers/d3d9/ImageLayerD3D9.cpp
gfx/layers/d3d9/ImageLayerD3D9.h
gfx/layers/d3d9/LayerManagerD3D9.cpp
gfx/layers/d3d9/LayerManagerD3D9.h
gfx/layers/d3d9/ShadowBufferD3D9.cpp
gfx/layers/d3d9/ShadowBufferD3D9.h
gfx/layers/d3d9/ThebesLayerD3D9.cpp
gfx/layers/d3d9/ThebesLayerD3D9.h
gfx/layers/opengl/CanvasLayerOGL.cpp
gfx/layers/opengl/CanvasLayerOGL.h
layout/ipc/RenderFrameParent.cpp
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -97,16 +97,17 @@ EXPORTS += \
 
 CPPSRCS += \
         LayerManagerD3D9.cpp \
         ThebesLayerD3D9.cpp \
         ContainerLayerD3D9.cpp \
         ImageLayerD3D9.cpp \
         ColorLayerD3D9.cpp \
         CanvasLayerD3D9.cpp \
+        ShadowBufferD3D9.cpp \
         DeviceManagerD3D9.cpp \
         Nv3DVUtils.cpp \
         $(NULL)
 endif
 ifdef MOZ_ENABLE_D3D10_LAYER
 EXPORTS += \
         LayerManagerD3D10.h \
         ReadbackManagerD3D10.h \
--- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp
@@ -31,22 +31,27 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include "CanvasLayerD3D9.h"
+
+#include "mozilla/layers/PLayers.h"
+#include "mozilla/layers/ShadowLayers.h"
+#include "ShadowBufferD3D9.h"
 
 #include "gfxImageSurface.h"
 #include "gfxWindowsSurface.h"
 #include "gfxWindowsPlatform.h"
 
+#include "CanvasLayerD3D9.h"
+
 namespace mozilla {
 namespace layers {
 
 CanvasLayerD3D9::~CanvasLayerD3D9()
 {
   if (mD3DManager) {
     mD3DManager->deviceManager()->mLayersWithResources.RemoveElement(this);
   }
@@ -88,24 +93,24 @@ CanvasLayerD3D9::UpdateSurface()
   if (!mTexture) {
     CreateTexture();
     NS_WARNING("CanvasLayerD3D9::Updated called but no texture present!");
     return;
   }
 
   if (mGLContext) {
     // WebGL reads entire surface.
-    D3DLOCKED_RECT r;
-    HRESULT hr = mTexture->LockRect(0, &r, NULL, 0);
-
-    if (FAILED(hr)) {
+    LockTextureRectD3D9 textureLock(mTexture);
+    if (!textureLock.HasLock()) {
       NS_WARNING("Failed to lock CanvasLayer texture.");
       return;
     }
 
+    D3DLOCKED_RECT r = textureLock.GetLockRect();
+
     PRUint8 *destination;
     if (r.Pitch != mBounds.width * 4) {
       destination = new PRUint8[mBounds.width * mBounds.height * 4];
     } else {
       destination = (PRUint8*)r.pBits;
     }
 
     // We have to flush to ensure that any buffered GL operations are
@@ -138,42 +143,40 @@ CanvasLayerD3D9::UpdateSurface()
     if (r.Pitch != mBounds.width * 4) {
       for (int y = 0; y < mBounds.height; y++) {
         memcpy((PRUint8*)r.pBits + r.Pitch * y,
                destination + mBounds.width * 4 * y,
                mBounds.width * 4);
       }
       delete [] destination;
     }
-    mTexture->UnlockRect(0);
   } else if (mSurface) {
     RECT r;
     r.left = mBounds.x;
     r.top = mBounds.y;
     r.right = mBounds.XMost();
     r.bottom = mBounds.YMost();
 
-    D3DLOCKED_RECT lockedRect;
-    HRESULT hr = mTexture->LockRect(0, &lockedRect, &r, 0);
-
-    if (FAILED(hr)) {
+    LockTextureRectD3D9 textureLock(mTexture);
+    if (!textureLock.HasLock()) {
       NS_WARNING("Failed to lock CanvasLayer texture.");
       return;
     }
 
+    D3DLOCKED_RECT lockedRect = textureLock.GetLockRect();
+
     nsRefPtr<gfxImageSurface> sourceSurface;
 
     if (mSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
       sourceSurface = mSurface->GetAsImageSurface();
     } else if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) {
       sourceSurface = static_cast<gfxImageSurface*>(mSurface.get());
       if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32 &&
           sourceSurface->Format() != gfxASurface::ImageFormatRGB24)
       {
-        mTexture->UnlockRect(0);
         return;
       }
     } else {
       sourceSurface = new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height),
                                           gfxASurface::ImageFormatARGB32);
       nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface);
       ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
       ctx->SetSource(mSurface);
@@ -190,17 +193,16 @@ CanvasLayerD3D9::UpdateSurface()
     }
 
     for (int y = 0; y < mBounds.height; y++) {
       memcpy((PRUint8*)lockedRect.pBits + lockedRect.Pitch * y,
              startBits + sourceStride * y,
              mBounds.width * 4);
     }
 
-    mTexture->UnlockRect(0);
   }
 }
 
 Layer*
 CanvasLayerD3D9::GetLayer()
 {
   return this;
 }
@@ -282,10 +284,104 @@ CanvasLayerD3D9::CreateTexture()
     // D3DPOOL_MANAGED is fine here since we require Dynamic Textures for D3D9Ex
     // devices.
     device()->CreateTexture(mBounds.width, mBounds.height, 1, 0,
                             D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
                             getter_AddRefs(mTexture), NULL);
   }
 }
 
+ShadowCanvasLayerD3D9::ShadowCanvasLayerD3D9(LayerManagerD3D9* aManager)
+  : ShadowCanvasLayer(aManager, nsnull)
+  , LayerD3D9(aManager)
+  , mNeedsYFlip(PR_FALSE)
+{
+  mImplData = static_cast<LayerD3D9*>(this);
+}
+ 
+ShadowCanvasLayerD3D9::~ShadowCanvasLayerD3D9()
+{}
+
+void
+ShadowCanvasLayerD3D9::Initialize(const Data& aData)
+{
+  NS_RUNTIMEABORT("Non-shadow layer API unexpectedly used for shadow layer");
+}
+
+void
+ShadowCanvasLayerD3D9::Init(const SurfaceDescriptor& aNewFront, 
+                            const nsIntSize& aSize, bool needYFlip)
+{
+
+  if (!mBuffer) {
+    mBuffer = new ShadowBufferD3D9(this);
+  }
+
+  mNeedsYFlip = needYFlip;
+}
+
+void
+ShadowCanvasLayerD3D9::Swap(const SurfaceDescriptor& aNewFront,
+                           SurfaceDescriptor* aNewBack)
+{
+  NS_ASSERTION(aNewFront.type() == SharedImage::TSurfaceDescriptor, 
+    "ShadowCanvasLayerD3D9::Swap expected SharedImage surface");
+
+  nsRefPtr<gfxASurface> surf = 
+    ShadowLayerForwarder::OpenDescriptor(aNewFront);
+   
+  if (mBuffer) {
+    mBuffer->Upload(surf, GetVisibleRegion().GetBounds());
+  }
+
+  *aNewBack = aNewFront;
+}
+
+void
+ShadowCanvasLayerD3D9::DestroyFrontBuffer()
+{
+  Destroy();
+}
+
+void
+ShadowCanvasLayerD3D9::Disconnect()
+{
+  Destroy();
+}
+
+void
+ShadowCanvasLayerD3D9::Destroy()
+{
+  mBuffer = nsnull;
+}
+
+void
+ShadowCanvasLayerD3D9::CleanResources()
+{
+  Destroy();
+}
+
+void
+ShadowCanvasLayerD3D9::LayerManagerDestroyed()
+{
+  mD3DManager->deviceManager()->mLayersWithResources.RemoveElement(this);
+  mD3DManager = nsnull;
+}
+
+Layer*
+ShadowCanvasLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+void
+ShadowCanvasLayerD3D9::RenderLayer()
+{
+  if (!mBuffer) {
+    return;
+  }
+
+  mBuffer->RenderTo(mD3DManager, GetEffectiveVisibleRegion());
+}
+
+
 } /* namespace layers */
 } /* namespace mozilla */
--- a/gfx/layers/d3d9/CanvasLayerD3D9.h
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.h
@@ -34,23 +34,25 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef GFX_CANVASLAYERD3D9_H
 #define GFX_CANVASLAYERD3D9_H
 
-#include "LayerManagerD3D9.h"
-#include "GLContext.h"
-#include "gfxASurface.h"
+#include "LayerManagerD3D9.h"
+#include "GLContext.h"
+#include "gfxASurface.h"
 
 namespace mozilla {
 namespace layers {
 
+class ShadowBufferD3D9;
+
 class THEBES_API CanvasLayerD3D9 :
   public CanvasLayer,
   public LayerD3D9
 {
 public:
   CanvasLayerD3D9(LayerManagerD3D9 *aManager)
     : CanvasLayer(aManager, NULL)
     , LayerD3D9(aManager)
@@ -86,11 +88,47 @@ protected:
 
   PRUint32 mCanvasFramebuffer;
 
   PRPackedBool mDataIsPremultiplied;
   PRPackedBool mNeedsYFlip;
   PRPackedBool mHasAlpha;
 };
 
+// NB: eventually we'll have separate shadow canvas2d and shadow
+// canvas3d layers, but currently they look the same from the
+// perspective of the compositor process
+class ShadowCanvasLayerD3D9 : public ShadowCanvasLayer,
+                             public LayerD3D9
+{
+public:
+  ShadowCanvasLayerD3D9(LayerManagerD3D9* aManager);
+  virtual ~ShadowCanvasLayerD3D9();
+
+  // CanvasLayer impl
+  virtual void Initialize(const Data& aData);
+  virtual void Init(const SurfaceDescriptor& aNewFront, const nsIntSize& aSize, bool needYFlip);
+
+  // This isn't meaningful for shadow canvas.
+  virtual void Updated(const nsIntRect&) {}
+
+  // ShadowCanvasLayer impl
+  virtual void Swap(const SurfaceDescriptor& aNewFront,
+                    SurfaceDescriptor* aNewBack);
+  virtual void DestroyFrontBuffer();
+  virtual void Disconnect();
+
+  virtual void Destroy();
+
+  // LayerD3D9 implementation
+  virtual Layer* GetLayer();
+  virtual void RenderLayer();
+  virtual void CleanResources();
+  virtual void LayerManagerDestroyed();
+
+private:
+  PRPackedBool mNeedsYFlip;
+  nsRefPtr<ShadowBufferD3D9> mBuffer;
+};
+
 } /* layers */
 } /* mozilla */
 #endif /* GFX_CANVASLAYERD3D9_H */
--- a/gfx/layers/d3d9/ColorLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ColorLayerD3D9.cpp
@@ -42,45 +42,58 @@ namespace mozilla {
 namespace layers {
 
 Layer*
 ColorLayerD3D9::GetLayer()
 {
   return this;
 }
 
-void
-ColorLayerD3D9::RenderLayer()
+static void
+RenderColorLayerD3D9(ColorLayer* aLayer, LayerManagerD3D9 *aManager)
 {
   // XXX we might be able to improve performance by using
   // IDirect3DDevice9::Clear
 
-  nsIntRect visibleRect = mVisibleRegion.GetBounds();
+  nsIntRect visibleRect = aLayer->GetEffectiveVisibleRegion().GetBounds();
 
-  device()->SetVertexShaderConstantF(
+  aManager->device()->SetVertexShaderConstantF(
     CBvLayerQuad,
     ShaderConstantRect(visibleRect.x,
                        visibleRect.y,
                        visibleRect.width,
                        visibleRect.height),
     1);
 
-  const gfx3DMatrix& transform = GetEffectiveTransform();
-  device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4);
+  const gfx3DMatrix& transform = aLayer->GetEffectiveTransform();
+  aManager->device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4);
 
+  gfxRGBA layerColor(aLayer->GetColor());
   float color[4];
-  float opacity = GetEffectiveOpacity() * mColor.a;
+  float opacity = aLayer->GetEffectiveOpacity() * layerColor.a;
   // output color is premultiplied, so we need to adjust all channels.
   // mColor is not premultiplied.
-  color[0] = (float)(mColor.r * opacity);
-  color[1] = (float)(mColor.g * opacity);
-  color[2] = (float)(mColor.b * opacity);
+  color[0] = (float)(layerColor.r * opacity);
+  color[1] = (float)(layerColor.g * opacity);
+  color[2] = (float)(layerColor.b * opacity);
   color[3] = (float)(opacity);
 
-  device()->SetPixelShaderConstantF(0, color, 1);
+  aManager->device()->SetPixelShaderConstantF(0, color, 1);
+
+  aManager->SetShaderMode(DeviceManagerD3D9::SOLIDCOLORLAYER);
+
+  aManager->device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+}
 
-  mD3DManager->SetShaderMode(DeviceManagerD3D9::SOLIDCOLORLAYER);
+void
+ColorLayerD3D9::RenderLayer()
+{
+  return RenderColorLayerD3D9(this, mD3DManager);
+}
 
-  device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+void
+ShadowColorLayerD3D9::RenderLayer()
+{
+  return RenderColorLayerD3D9(this, mD3DManager);
 }
 
 } /* layers */
 } /* mozilla */
--- a/gfx/layers/d3d9/ColorLayerD3D9.h
+++ b/gfx/layers/d3d9/ColorLayerD3D9.h
@@ -56,12 +56,32 @@ public:
   }
 
   // LayerD3D9 Implementation
   virtual Layer* GetLayer();
 
   virtual void RenderLayer();
 };
 
+class ShadowColorLayerD3D9 : public ShadowColorLayer,
+                            public LayerD3D9
+{
+public:
+  ShadowColorLayerD3D9(LayerManagerD3D9 *aManager)
+    : ShadowColorLayer(aManager, NULL)
+    , LayerD3D9(aManager)
+  { 
+    mImplData = static_cast<LayerD3D9*>(this);
+  }
+  ~ShadowColorLayerD3D9() { Destroy(); }
+
+  // LayerOGL Implementation
+  virtual Layer* GetLayer() { return this; }
+
+  virtual void Destroy() { }
+
+  virtual void RenderLayer();
+};
+
 } /* layers */
 } /* mozilla */
 
 #endif /* GFX_COLORLAYERD3D9_H */
--- a/gfx/layers/d3d9/ContainerLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ContainerLayerD3D9.cpp
@@ -39,231 +39,223 @@
 #include "gfxUtils.h"
 #include "nsRect.h"
 #include "ThebesLayerD3D9.h"
 #include "ReadbackProcessor.h"
 
 namespace mozilla {
 namespace layers {
 
-ContainerLayerD3D9::ContainerLayerD3D9(LayerManagerD3D9 *aManager)
-  : ContainerLayer(aManager, NULL)
-  , LayerD3D9(aManager)
-{
-  mImplData = static_cast<LayerD3D9*>(this);
-}
-
-ContainerLayerD3D9::~ContainerLayerD3D9()
+template<class Container>
+static void
+ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter)
 {
-  while (mFirstChild) {
-    RemoveChild(mFirstChild);
-  }
-}
-
-void
-ContainerLayerD3D9::InsertAfter(Layer* aChild, Layer* aAfter)
-{
-  aChild->SetParent(this);
+  aChild->SetParent(aContainer);
   if (!aAfter) {
-    Layer *oldFirstChild = GetFirstChild();
-    mFirstChild = aChild;
+    Layer *oldFirstChild = aContainer->GetFirstChild();
+    aContainer->mFirstChild = aChild;
     aChild->SetNextSibling(oldFirstChild);
     aChild->SetPrevSibling(nsnull);
     if (oldFirstChild) {
       oldFirstChild->SetPrevSibling(aChild);
     } else {
-      mLastChild = aChild;
+      aContainer->mLastChild = aChild;
     }
     NS_ADDREF(aChild);
-    DidInsertChild(aChild);
+    aContainer->DidInsertChild(aChild);
     return;
   }
-  for (Layer *child = GetFirstChild();
+  for (Layer *child = aContainer->GetFirstChild(); 
        child; child = child->GetNextSibling()) {
     if (aAfter == child) {
       Layer *oldNextSibling = child->GetNextSibling();
       child->SetNextSibling(aChild);
       aChild->SetNextSibling(oldNextSibling);
       if (oldNextSibling) {
         oldNextSibling->SetPrevSibling(aChild);
       } else {
-        mLastChild = aChild;
+        aContainer->mLastChild = aChild;
       }
       aChild->SetPrevSibling(child);
       NS_ADDREF(aChild);
-      DidInsertChild(aChild);
+      aContainer->DidInsertChild(aChild);
       return;
     }
   }
   NS_WARNING("Failed to find aAfter layer!");
 }
 
-void
-ContainerLayerD3D9::RemoveChild(Layer *aChild)
+template<class Container>
+static void
+ContainerRemoveChild(Container* aContainer, Layer* aChild)
 {
-  if (GetFirstChild() == aChild) {
-    mFirstChild = GetFirstChild()->GetNextSibling();
-    if (mFirstChild) {
-      mFirstChild->SetPrevSibling(nsnull);
+  if (aContainer->GetFirstChild() == aChild) {
+    aContainer->mFirstChild = aContainer->GetFirstChild()->GetNextSibling();
+    if (aContainer->mFirstChild) {
+      aContainer->mFirstChild->SetPrevSibling(nsnull);
     } else {
-      mLastChild = nsnull;
+      aContainer->mLastChild = nsnull;
     }
     aChild->SetNextSibling(nsnull);
     aChild->SetPrevSibling(nsnull);
     aChild->SetParent(nsnull);
-    DidRemoveChild(aChild);
+    aContainer->DidRemoveChild(aChild);
     NS_RELEASE(aChild);
     return;
   }
   Layer *lastChild = nsnull;
-  for (Layer *child = GetFirstChild(); child;
+  for (Layer *child = aContainer->GetFirstChild(); child; 
        child = child->GetNextSibling()) {
     if (child == aChild) {
       // We're sure this is not our first child. So lastChild != NULL.
       lastChild->SetNextSibling(child->GetNextSibling());
       if (child->GetNextSibling()) {
         child->GetNextSibling()->SetPrevSibling(lastChild);
       } else {
-        mLastChild = lastChild;
+        aContainer->mLastChild = lastChild;
       }
       child->SetNextSibling(nsnull);
       child->SetPrevSibling(nsnull);
       child->SetParent(nsnull);
-      DidRemoveChild(aChild);
+      aContainer->DidRemoveChild(aChild);
       NS_RELEASE(aChild);
       return;
     }
     lastChild = child;
   }
 }
 
-Layer*
-ContainerLayerD3D9::GetLayer()
-{
-  return this;
-}
-
-LayerD3D9*
-ContainerLayerD3D9::GetFirstChildD3D9()
-{
-  if (!mFirstChild) {
-    return nsnull;
-  }
-  return static_cast<LayerD3D9*>(mFirstChild->ImplData());
-}
-
 static inline LayerD3D9*
-GetNextSiblingD3D9(LayerD3D9* aLayer)
+GetNextSibling(LayerD3D9* aLayer)
 {
    Layer* layer = aLayer->GetLayer()->GetNextSibling();
    return layer ? static_cast<LayerD3D9*>(layer->
-                                          ImplData())
+                                         ImplData())
                  : nsnull;
 }
 
 static PRBool
 HasOpaqueAncestorLayer(Layer* aLayer)
 {
   for (Layer* l = aLayer->GetParent(); l; l = l->GetParent()) {
     if (l->GetContentFlags() & Layer::CONTENT_OPAQUE)
       return PR_TRUE;
   }
   return PR_FALSE;
 }
 
-void
-ContainerLayerD3D9::RenderLayer()
+static inline LayerD3D9*
+GetNextSiblingD3D9(LayerD3D9* aLayer)
+{
+   Layer* layer = aLayer->GetLayer()->GetNextSibling();
+   return layer ? static_cast<LayerD3D9*>(layer->
+                                          ImplData())
+                 : nsnull;
+}
+
+template<class Container>
+static void
+ContainerRender(Container* aContainer,
+                LayerManagerD3D9* aManager)
 {
   nsRefPtr<IDirect3DSurface9> previousRenderTarget;
   nsRefPtr<IDirect3DTexture9> renderTexture;
   float previousRenderTargetOffset[4];
   float renderTargetOffset[] = { 0, 0, 0, 0 };
   float oldViewMatrix[4][4];
 
   RECT containerD3D9ClipRect; 
-  device()->GetScissorRect(&containerD3D9ClipRect);
+  aManager->device()->GetScissorRect(&containerD3D9ClipRect);
   // Convert scissor to an nsIntRect. RECT's are exclusive on the bottom and
   // right values.
   nsIntRect oldScissor(containerD3D9ClipRect.left, 
                        containerD3D9ClipRect.top,
                        containerD3D9ClipRect.right - containerD3D9ClipRect.left,
                        containerD3D9ClipRect.bottom - containerD3D9ClipRect.top);
 
   ReadbackProcessor readback;
-  readback.BuildUpdates(this);
+  readback.BuildUpdates(aContainer);
 
-  nsIntRect visibleRect = mVisibleRegion.GetBounds();
-  PRBool useIntermediate = UseIntermediateSurface();
+  nsIntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds();
+  PRBool useIntermediate = aContainer->UseIntermediateSurface();
 
-  mSupportsComponentAlphaChildren = PR_FALSE;
+  aContainer->mSupportsComponentAlphaChildren = PR_FALSE;
   if (useIntermediate) {
-    device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget));
-    device()->CreateTexture(visibleRect.width, visibleRect.height, 1,
+    aManager->device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget));
+    aManager->device()->CreateTexture(visibleRect.width, visibleRect.height, 1,
                             D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
                             D3DPOOL_DEFAULT, getter_AddRefs(renderTexture),
                             NULL);
     nsRefPtr<IDirect3DSurface9> renderSurface;
     renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface));
-    device()->SetRenderTarget(0, renderSurface);
+    aManager->device()->SetRenderTarget(0, renderSurface);
 
-    if (mVisibleRegion.GetNumRects() == 1 && (GetContentFlags() & CONTENT_OPAQUE)) {
+    if (aContainer->mVisibleRegion.GetNumRects() == 1 && 
+        (aContainer->GetContentFlags() & aContainer->CONTENT_OPAQUE)) {
       // don't need a background, we're going to paint all opaque stuff
-      mSupportsComponentAlphaChildren = PR_TRUE;
+      aContainer->mSupportsComponentAlphaChildren = PR_TRUE;
     } else {
-      const gfx3DMatrix& transform3D = GetEffectiveTransform();
+      const gfx3DMatrix& transform3D = aContainer->GetEffectiveTransform();
       gfxMatrix transform;
       // If we have an opaque ancestor layer, then we can be sure that
       // all the pixels we draw into are either opaque already or will be
       // covered by something opaque. Otherwise copying up the background is
       // not safe.
       HRESULT hr = E_FAIL;
-      if (HasOpaqueAncestorLayer(this) &&
+      if (HasOpaqueAncestorLayer(aContainer) &&
           transform3D.Is2D(&transform) && !transform.HasNonIntegerTranslation()) {
         // Copy background up from below
         RECT dest = { 0, 0, visibleRect.width, visibleRect.height };
         RECT src = dest;
         ::OffsetRect(&src,
                      visibleRect.x + PRInt32(transform.x0),
                      visibleRect.y + PRInt32(transform.y0));
-        hr = device()->
+        hr = aManager->device()->
           StretchRect(previousRenderTarget, &src, renderSurface, &dest, D3DTEXF_NONE);
       }
       if (hr == S_OK) {
-        mSupportsComponentAlphaChildren = PR_TRUE;
+        aContainer->mSupportsComponentAlphaChildren = PR_TRUE;
       } else {
-        device()->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0);
+        aManager->device()->
+          Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0);
       }
     }
 
-    device()->GetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1);
+    aManager->device()->
+      GetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1);
     renderTargetOffset[0] = (float)visibleRect.x;
     renderTargetOffset[1] = (float)visibleRect.y;
-    device()->SetVertexShaderConstantF(CBvRenderTargetOffset, renderTargetOffset, 1);
+    aManager->device()->
+      SetVertexShaderConstantF(CBvRenderTargetOffset, renderTargetOffset, 1);
 
     gfx3DMatrix viewMatrix;
     /*
      * Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
      * <1.0, -1.0> bottomright)
      */
     viewMatrix._11 = 2.0f / visibleRect.width;
     viewMatrix._22 = -2.0f / visibleRect.height;
     viewMatrix._41 = -1.0f;
     viewMatrix._42 = 1.0f;
 
-    device()->GetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4);
-    device()->SetVertexShaderConstantF(CBmProjection, &viewMatrix._11, 4);
+    aManager->device()->
+      GetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4);
+    aManager->device()->
+      SetVertexShaderConstantF(CBmProjection, &viewMatrix._11, 4);
   } else {
-    mSupportsComponentAlphaChildren = (GetContentFlags() & CONTENT_OPAQUE) ||
-        (mParent && mParent->SupportsComponentAlphaChildren());
+    aContainer->mSupportsComponentAlphaChildren = 
+        (aContainer->GetContentFlags() & aContainer->CONTENT_OPAQUE) ||
+        (aContainer->mParent && 
+         aContainer->mParent->SupportsComponentAlphaChildren());
   }
 
   /*
    * Render this container's contents.
    */
-  for (LayerD3D9* layerToRender = GetFirstChildD3D9();
+  for (LayerD3D9* layerToRender = aContainer->GetFirstChildD3D9();
        layerToRender != nsnull;
        layerToRender = GetNextSiblingD3D9(layerToRender)) {
 
     if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) {
       continue;
     }
     
     nsIntRect scissorRect =
@@ -272,51 +264,146 @@ ContainerLayerD3D9::RenderLayer()
       continue;
     }
 
     RECT d3drect;
     d3drect.left = scissorRect.x;
     d3drect.top = scissorRect.y;
     d3drect.right = scissorRect.x + scissorRect.width;
     d3drect.bottom = scissorRect.y + scissorRect.height;
-    device()->SetScissorRect(&d3drect);
+    aManager->device()->SetScissorRect(&d3drect);
 
-    if (layerToRender->GetLayer()->GetType() == TYPE_THEBES) {
+    if (layerToRender->GetLayer()->GetType() == aContainer->TYPE_THEBES) {
       static_cast<ThebesLayerD3D9*>(layerToRender)->RenderThebesLayer(&readback);
     } else {
       layerToRender->RenderLayer();
     }
   }
     
-  device()->SetScissorRect(&containerD3D9ClipRect);
+  aManager->device()->SetScissorRect(&containerD3D9ClipRect);
 
   if (useIntermediate) {
-    device()->SetRenderTarget(0, previousRenderTarget);
-    device()->SetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1);
-    device()->SetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4);
+    aManager->device()->SetRenderTarget(0, previousRenderTarget);
+    aManager->device()->SetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1);
+    aManager->device()->SetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4);
 
-    device()->SetVertexShaderConstantF(CBvLayerQuad,
+    aManager->device()->SetVertexShaderConstantF(CBvLayerQuad,
                                        ShaderConstantRect(visibleRect.x,
                                                           visibleRect.y,
                                                           visibleRect.width,
                                                           visibleRect.height),
                                        1);
 
-    SetShaderTransformAndOpacity();
+    aContainer->SetShaderTransformAndOpacity();
+
+    aManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER);
+
+    aManager->device()->SetTexture(0, renderTexture);
+    aManager->device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+  }
+}
+
 
-    mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER);
+ContainerLayerD3D9::ContainerLayerD3D9(LayerManagerD3D9 *aManager)
+  : ContainerLayer(aManager, NULL)
+  , LayerD3D9(aManager)
+{
+  mImplData = static_cast<LayerD3D9*>(this);
+}
+
+ContainerLayerD3D9::~ContainerLayerD3D9()
+{
+  while (mFirstChild) {
+    RemoveChild(mFirstChild);
+  }
+}
 
-    device()->SetTexture(0, renderTexture);
-    device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+void
+ContainerLayerD3D9::InsertAfter(Layer* aChild, Layer* aAfter)
+{
+  ContainerInsertAfter(this, aChild, aAfter);
+}
+
+void
+ContainerLayerD3D9::RemoveChild(Layer *aChild)
+{
+  ContainerRemoveChild(this, aChild);
+}
+
+Layer*
+ContainerLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+LayerD3D9*
+ContainerLayerD3D9::GetFirstChildD3D9()
+{
+  if (!mFirstChild) {
+    return nsnull;
   }
+  return static_cast<LayerD3D9*>(mFirstChild->ImplData());
+}
+
+void
+ContainerLayerD3D9::RenderLayer()
+{
+  ContainerRender(this, mD3DManager);
 }
 
 void
 ContainerLayerD3D9::LayerManagerDestroyed()
 {
   while (mFirstChild) {
     GetFirstChildD3D9()->LayerManagerDestroyed();
     RemoveChild(mFirstChild);
   }
 }
 
+ShadowContainerLayerD3D9::ShadowContainerLayerD3D9(LayerManagerD3D9 *aManager)
+  : ShadowContainerLayer(aManager, NULL)
+  , LayerD3D9(aManager)
+{
+  mImplData = static_cast<LayerD3D9*>(this);
+}
+ 
+ShadowContainerLayerD3D9::~ShadowContainerLayerD3D9()
+{
+  Destroy();
+}
+
+void
+ShadowContainerLayerD3D9::InsertAfter(Layer* aChild, Layer* aAfter)
+{
+  ContainerInsertAfter(this, aChild, aAfter);
+}
+
+void
+ShadowContainerLayerD3D9::RemoveChild(Layer *aChild)
+{
+  ContainerRemoveChild(this, aChild);
+}
+
+void
+ShadowContainerLayerD3D9::Destroy()
+{
+  while (mFirstChild) {
+    RemoveChild(mFirstChild);
+  }
+}
+
+LayerD3D9*
+ShadowContainerLayerD3D9::GetFirstChildD3D9()
+{
+  if (!mFirstChild) {
+    return nsnull;
+   }
+  return static_cast<LayerD3D9*>(mFirstChild->ImplData());
+}
+ 
+void
+ShadowContainerLayerD3D9::RenderLayer()
+{
+  ContainerRender(this, mD3DManager);
+}
+
 } /* layers */
 } /* mozilla */
--- a/gfx/layers/d3d9/ContainerLayerD3D9.h
+++ b/gfx/layers/d3d9/ContainerLayerD3D9.h
@@ -38,20 +38,34 @@
 #ifndef GFX_CONTAINERLAYERD3D9_H
 #define GFX_CONTAINERLAYERD3D9_H
 
 #include "Layers.h"
 #include "LayerManagerD3D9.h"
 
 namespace mozilla {
 namespace layers {
+  
+template<class Container>
+static void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter);
+template<class Container>
+static void ContainerRemoveChild(Container* aContainer, Layer* aChild);
+template<class Container>
+static void ContainerRender(Container* aContainer, LayerManagerD3D9* aManager);
 
 class ContainerLayerD3D9 : public ContainerLayer,
                            public LayerD3D9
 {
+  template<class Container>
+  friend void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter);
+  template<class Container>
+  friend void ContainerRemoveChild(Container* aContainer, Layer* aChild);
+  template<class Container>
+  friend void ContainerRender(Container* aContainer, LayerManagerD3D9* aManager);
+
 public:
   ContainerLayerD3D9(LayerManagerD3D9 *aManager);
   ~ContainerLayerD3D9();
 
   nsIntRect GetVisibleRect() { return mVisibleRegion.GetBounds(); }
 
   /* ContainerLayer implementation */
   virtual void InsertAfter(Layer* aChild, Layer* aAfter);
@@ -70,12 +84,45 @@ public:
   virtual void LayerManagerDestroyed();
 
   virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
   {
     DefaultComputeEffectiveTransforms(aTransformToSurface);
   }
 };
 
+class ShadowContainerLayerD3D9 : public ShadowContainerLayer,
+                                public LayerD3D9
+{
+  template<class Container>
+  friend void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter);
+  template<class Container>
+  friend void ContainerRemoveChild(Container* aContainer, Layer* aChild);
+  template<class Container>
+  friend void ContainerRender(Container* aContainer, LayerManagerD3D9* aManager);
+
+public:
+  ShadowContainerLayerD3D9(LayerManagerD3D9 *aManager);
+  ~ShadowContainerLayerD3D9();
+
+  void InsertAfter(Layer* aChild, Layer* aAfter);
+
+  void RemoveChild(Layer* aChild);
+
+  // LayerD3D9 Implementation
+  virtual Layer* GetLayer() { return this; }
+
+  virtual void Destroy();
+
+  LayerD3D9* GetFirstChildD3D9();
+
+  virtual void RenderLayer();
+
+  virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
+  {
+    DefaultComputeEffectiveTransforms(aTransformToSurface);
+  }
+};
+
 } /* layers */
 } /* mozilla */
 
 #endif /* GFX_CONTAINERLAYERD3D9_H */
--- a/gfx/layers/d3d9/ImageLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -30,17 +30,24 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "mozilla/layers/PLayers.h"
+#include "mozilla/layers/ShadowLayers.h"
+#include "ShadowBufferD3D9.h"
+#include "gfxSharedImageSurface.h"
+
 #include "ImageLayerD3D9.h"
+#include "ThebesLayerD3D9.h"
+#include "gfxPlatform.h"
 #include "gfxImageSurface.h"
 #include "yuv_convert.h"
 #include "nsIServiceManager.h" 
 #include "nsIConsoleService.h" 
 #include "nsPrintfCString.h" 
 #include "Nv3DVUtils.h"
 
 namespace mozilla {
@@ -638,10 +645,152 @@ CairoImageD3D9::GetOrCreateTexture()
 
 already_AddRefed<gfxASurface>
 CairoImageD3D9::GetAsSurface()
 {
   nsRefPtr<gfxASurface> surface = mCachedSurface;
   return surface.forget();
 }
 
+ShadowImageLayerD3D9::ShadowImageLayerD3D9(LayerManagerD3D9* aManager)
+  : ShadowImageLayer(aManager, nsnull)
+  , LayerD3D9(aManager)
+{
+  mImplData = static_cast<LayerD3D9*>(this);
+}  
+
+ShadowImageLayerD3D9::~ShadowImageLayerD3D9()
+{}
+
+PRBool
+ShadowImageLayerD3D9::Init(const SharedImage& aFront,
+                          const nsIntSize& aSize)
+{
+   if (aFront.type() == SharedImage::TSurfaceDescriptor) {
+    SurfaceDescriptor desc = aFront.get_SurfaceDescriptor();
+    nsRefPtr<gfxASurface> surf = 
+      ShadowLayerForwarder::OpenDescriptor(desc);
+    
+    if (!mBuffer) {
+      mBuffer = new ShadowBufferD3D9(this);
+    }
+    return !!mBuffer;
+  } else {
+    if (!mYCbCrImage) {
+      mYCbCrImage = new PlanarYCbCrImageD3D9();
+    }
+    return !!mYCbCrImage;
+  }
+}
+
+void
+ShadowImageLayerD3D9::Swap(const SharedImage& aNewFront, SharedImage* aNewBack)
+{
+  
+  if (aNewFront.type() == SharedImage::TSurfaceDescriptor) {
+    nsRefPtr<gfxASurface> surf = 
+      ShadowLayerForwarder::OpenDescriptor(aNewFront.get_SurfaceDescriptor());
+   
+    if (mBuffer) {
+      mBuffer->Upload(surf, GetVisibleRegion().GetBounds());
+    }
+  } else {
+
+    const YUVImage& yuv = aNewFront.get_YUVImage();
+
+    nsRefPtr<gfxSharedImageSurface> surfY =
+      gfxSharedImageSurface::Open(yuv.Ydata());
+    nsRefPtr<gfxSharedImageSurface> surfU =
+      gfxSharedImageSurface::Open(yuv.Udata());
+    nsRefPtr<gfxSharedImageSurface> surfV =
+      gfxSharedImageSurface::Open(yuv.Vdata());
+
+    PlanarYCbCrImage::Data data;
+    data.mYChannel = surfY->Data();
+    data.mYStride = surfY->Stride();
+    data.mYSize = surfY->GetSize();
+    data.mCbChannel = surfU->Data();
+    data.mCrChannel = surfV->Data();
+    data.mCbCrStride = surfU->Stride();
+    data.mCbCrSize = surfU->GetSize();
+    data.mPicSize = surfY->GetSize();
+    data.mPicX = 0;
+    data.mPicY = 0;
+
+    mYCbCrImage->SetData(data);
+
+  }
+  
+  *aNewBack = aNewFront;
+}
+
+void
+ShadowImageLayerD3D9::DestroyFrontBuffer()
+{
+  Destroy();
+}
+
+void
+ShadowImageLayerD3D9::Disconnect()
+{
+  Destroy();
+}
+
+void
+ShadowImageLayerD3D9::Destroy()
+{
+  mBuffer = nsnull;
+  mYCbCrImage = nsnull;
+}
+
+Layer*
+ShadowImageLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+void
+ShadowImageLayerD3D9::RenderLayer()
+{
+  if (mBuffer) {
+    mBuffer->RenderTo(mD3DManager, GetEffectiveVisibleRegion());
+  } else if (mYCbCrImage) {
+    if (!mYCbCrImage->HasData()) {
+      return;
+    }
+    
+    mYCbCrImage->AllocateTextures(device());
+
+    SetShaderTransformAndOpacity();
+
+    device()->SetVertexShaderConstantF(CBvLayerQuad,
+                                       ShaderConstantRect(0,
+                                                          0,
+                                                          mYCbCrImage->mSize.width,
+                                                          mYCbCrImage->mSize.height),
+                                       1);
+
+    mD3DManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER);
+
+    /*
+     * Send 3d control data and metadata
+     */
+    if (mD3DManager->GetNv3DVUtils()) {
+      // TODO Add 3D support
+    }
+
+    // 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, mYCbCrImage->mYTexture);
+    device()->SetTexture(1, mYCbCrImage->mCbTexture);
+    device()->SetTexture(2, mYCbCrImage->mCrTexture);
+
+    device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+  } else {
+    NS_ERROR("Unexpected image format.");
+  }
+
+}
+
+
 } /* layers */
 } /* mozilla */
--- a/gfx/layers/d3d9/ImageLayerD3D9.h
+++ b/gfx/layers/d3d9/ImageLayerD3D9.h
@@ -40,16 +40,18 @@
 
 #include "LayerManagerD3D9.h"
 #include "ImageLayers.h"
 #include "yuv_convert.h"
 
 namespace mozilla {
 namespace layers {
 
+class ShadowBufferD3D9;
+
 class THEBES_API ImageContainerD3D9 : public ImageContainer
 {
 public:
   ImageContainerD3D9(IDirect3DDevice9 *aDevice);
   virtual ~ImageContainerD3D9() {}
 
   virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
                                               PRUint32 aNumFormats);
@@ -168,11 +170,39 @@ public:
 private:
   gfxIntSize mSize;
   nsRefPtr<gfxASurface> mCachedSurface;
   nsRefPtr<IDirect3DDevice9> mDevice;
   nsRefPtr<IDirect3DTexture9> mTexture;
   LayerManagerD3D9 *mManager;
 };
 
+class ShadowImageLayerD3D9 : public ShadowImageLayer,
+                            public LayerD3D9
+{
+public:
+  ShadowImageLayerD3D9(LayerManagerD3D9* aManager);
+  virtual ~ShadowImageLayerD3D9();
+
+  // ShadowImageLayer impl
+  virtual PRBool Init(const SharedImage& aFront, const nsIntSize& aSize);
+
+  virtual void Swap(const SharedImage& aFront, SharedImage* aNewBack);
+
+  virtual void DestroyFrontBuffer();
+
+  virtual void Disconnect();
+
+  // LayerD3D9 impl
+  virtual void Destroy();
+
+  virtual Layer* GetLayer();
+
+  virtual void RenderLayer();
+
+private:
+  nsRefPtr<ShadowBufferD3D9> mBuffer;
+  nsRefPtr<PlanarYCbCrImageD3D9> mYCbCrImage;
+};
+
 } /* layers */
 } /* mozilla */
 #endif /* GFX_IMAGELAYERD3D9_H */
--- a/gfx/layers/d3d9/LayerManagerD3D9.cpp
+++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp
@@ -240,16 +240,66 @@ LayerManagerD3D9::CreateReadbackLayer()
 
 already_AddRefed<ImageContainer>
 LayerManagerD3D9::CreateImageContainer()
 {
   nsRefPtr<ImageContainer> container = new ImageContainerD3D9(device());
   return container.forget();
 }
 
+already_AddRefed<ShadowThebesLayer>
+LayerManagerD3D9::CreateShadowThebesLayer()
+{
+  if (LayerManagerD3D9::mDestroyed) {
+    NS_WARNING("Call on destroyed layer manager");
+    return nsnull;
+  }
+  return nsRefPtr<ShadowThebesLayerD3D9>(new ShadowThebesLayerD3D9(this)).forget();
+}
+
+already_AddRefed<ShadowContainerLayer>
+LayerManagerD3D9::CreateShadowContainerLayer()
+{
+  if (LayerManagerD3D9::mDestroyed) {
+    NS_WARNING("Call on destroyed layer manager");
+    return nsnull;
+  }
+  return nsRefPtr<ShadowContainerLayerD3D9>(new ShadowContainerLayerD3D9(this)).forget();
+}
+
+already_AddRefed<ShadowImageLayer>
+LayerManagerD3D9::CreateShadowImageLayer()
+{
+  if (LayerManagerD3D9::mDestroyed) {
+    NS_WARNING("Call on destroyed layer manager");
+    return nsnull;
+  }
+  return nsRefPtr<ShadowImageLayerD3D9>(new ShadowImageLayerD3D9(this)).forget();
+}
+
+already_AddRefed<ShadowColorLayer>
+LayerManagerD3D9::CreateShadowColorLayer()
+{
+  if (LayerManagerD3D9::mDestroyed) {
+    NS_WARNING("Call on destroyed layer manager");
+    return nsnull;
+  }
+  return nsRefPtr<ShadowColorLayerD3D9>(new ShadowColorLayerD3D9(this)).forget();
+}
+
+already_AddRefed<ShadowCanvasLayer>
+LayerManagerD3D9::CreateShadowCanvasLayer()
+{
+  if (LayerManagerD3D9::mDestroyed) {
+    NS_WARNING("Call on destroyed layer manager");
+    return nsnull;
+  }
+  return nsRefPtr<ShadowCanvasLayerD3D9>(new ShadowCanvasLayerD3D9(this)).forget();
+}
+
 void ReleaseTexture(void *texture)
 {
   static_cast<IDirect3DTexture9*>(texture)->Release();
 }
 
 void
 LayerManagerD3D9::ReportFailure(const nsACString &aMsg, HRESULT aCode)
 {
--- a/gfx/layers/d3d9/LayerManagerD3D9.h
+++ b/gfx/layers/d3d9/LayerManagerD3D9.h
@@ -35,16 +35,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef GFX_LAYERMANAGERD3D9_H
 #define GFX_LAYERMANAGERD3D9_H
 
 #include "Layers.h"
 
+#include "mozilla/layers/ShadowLayers.h"
+
 #include <windows.h>
 #include <d3d9.h>
 
 #include "gfxContext.h"
 #include "nsIWidget.h"
 
 #include "DeviceManagerD3D9.h"
 
@@ -83,17 +85,17 @@ struct ShaderConstantRect
   // 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 THEBES_API LayerManagerD3D9 : public LayerManager {
+class THEBES_API LayerManagerD3D9 : public ShadowLayerManager {
 public:
   LayerManagerD3D9(nsIWidget *aWidget);
   virtual ~LayerManagerD3D9();
 
   /*
    * Initializes the layer manager, this is when the layer manager will
    * actually access the device and attempt to create the swap chain used
    * to draw to the window. If this method fails the device cannot be used.
@@ -148,16 +150,22 @@ public:
   virtual already_AddRefed<ColorLayer> CreateColorLayer();
 
   virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
 
   virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer();
 
   virtual already_AddRefed<ImageContainer> CreateImageContainer();
 
+  virtual already_AddRefed<ShadowThebesLayer> CreateShadowThebesLayer();
+  virtual already_AddRefed<ShadowContainerLayer> CreateShadowContainerLayer();
+  virtual already_AddRefed<ShadowImageLayer> CreateShadowImageLayer();
+  virtual already_AddRefed<ShadowColorLayer> CreateShadowColorLayer();
+  virtual already_AddRefed<ShadowCanvasLayer> CreateShadowCanvasLayer();
+
   virtual LayersBackend GetBackendType() { return LAYERS_D3D9; }
   virtual void GetBackendName(nsAString& name) { name.AssignLiteral("Direct3D 9"); }
   bool DeviceWasRemoved() { return deviceManager()->DeviceWasRemoved(); }
 
   /*
    * Helper methods.
    */
   void SetClippingEnabled(PRBool aEnabled);
@@ -278,12 +286,46 @@ public:
     opacity[0] = layer->GetEffectiveOpacity();
     device()->SetPixelShaderConstantF(CBfLayerOpacity, opacity, 1);
   }
 
 protected:
   LayerManagerD3D9 *mD3DManager;
 };
 
+/*
+ * RAII helper for locking D3D9 textures.
+ */
+class LockTextureRectD3D9 
+{
+public:
+  LockTextureRectD3D9(IDirect3DTexture9* aTexture) 
+    : mTexture(aTexture)
+  {
+    mLockResult = mTexture->LockRect(0, &mR, NULL, 0);
+  }
+
+  ~LockTextureRectD3D9()
+  {
+    mTexture->UnlockRect(0);
+  }
+
+  bool HasLock() {
+    return SUCCEEDED(mLockResult);
+  }
+
+  D3DLOCKED_RECT GetLockRect() 
+  {
+    return mR;
+  }
+private:
+  LockTextureRectD3D9 (const LockTextureRectD3D9&);
+  LockTextureRectD3D9& operator= (const LockTextureRectD3D9&);
+
+  IDirect3DTexture9* mTexture;
+  D3DLOCKED_RECT mR;
+  HRESULT mLockResult;
+};
+
 } /* layers */
 } /* mozilla */
 
 #endif /* GFX_LAYERMANAGERD3D9_H */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ShadowBufferD3D9.cpp
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Benoit Girard <bgirard@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "LayerManagerD3D9.h"
+#include "ShadowBufferD3D9.h"
+
+#include "gfxWindowsSurface.h"
+#include "gfxWindowsPlatform.h"
+
+
+namespace mozilla {
+namespace layers {
+
+void 
+ShadowBufferD3D9::Upload(gfxASurface* aUpdate, 
+                         const nsIntRect& aVisibleRect)
+{
+
+  gfxIntSize size = aUpdate->GetSize();
+
+  if (GetSize() != nsIntSize(size.width, size.height)) {
+    mLayer->device()->CreateTexture(size.width, size.height, 1,
+                          D3DUSAGE_DYNAMIC,
+                          D3DFMT_A8R8G8B8,
+                          D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
+
+    mTextureRect = aVisibleRect;
+  }
+
+  LockTextureRectD3D9 textureLock(mTexture);
+  if (!textureLock.HasLock()) {
+    NS_WARNING("Failed to lock ShadowBufferD3D9 texture.");
+    return;
+  }
+
+  D3DLOCKED_RECT r = textureLock.GetLockRect();
+
+  nsRefPtr<gfxImageSurface> imgSurface =
+    new gfxImageSurface((unsigned char *)r.pBits,
+                        GetSize(),
+                        r.Pitch,
+                        gfxASurface::ImageFormatARGB32);
+
+  nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
+  context->SetSource(aUpdate);
+  context->SetOperator(gfxContext::OPERATOR_SOURCE);
+  context->Paint();
+
+  imgSurface = NULL;
+}
+
+void 
+ShadowBufferD3D9::RenderTo(LayerManagerD3D9 *aD3DManager, 
+                           const nsIntRegion& aVisibleRegion)
+{
+  mLayer->SetShaderTransformAndOpacity();
+
+  aD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER);
+  mLayer->device()->SetTexture(0, mTexture);
+
+  nsIntRegionRectIterator iter(aVisibleRegion);
+
+  const nsIntRect *iterRect;
+  while ((iterRect = iter.Next())) {
+    mLayer->device()->SetVertexShaderConstantF(CBvLayerQuad,
+                                       ShaderConstantRect(iterRect->x,
+                                                          iterRect->y,
+                                                          iterRect->width,
+                                                          iterRect->height),
+                                       1);
+
+    mLayer->device()->SetVertexShaderConstantF(CBvTextureCoords,
+      ShaderConstantRect(
+        (float)(iterRect->x - mTextureRect.x) / (float)mTextureRect.width,
+        (float)(iterRect->y - mTextureRect.y) / (float)mTextureRect.height,
+        (float)iterRect->width / (float)mTextureRect.width,
+        (float)iterRect->height / (float)mTextureRect.height), 1);
+
+    mLayer->device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+  }
+}
+
+} /* namespace layers */
+} /* namespace mozilla */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ShadowBufferD3D9.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Benoit Girard <bgirard@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef GFX_SHADOWBUFFERD3D9_H
+#define GFX_SHADOWBUFFERD3D9_H
+
+#include "LayerManagerD3D9.h"
+
+namespace mozilla {
+namespace layers {
+
+class LayerManagerD3D9;
+class LayerD3D9;
+
+class ShadowBufferD3D9
+{
+  NS_INLINE_DECL_REFCOUNTING(ShadowBufferD3D9)
+public:
+
+  ShadowBufferD3D9(LayerD3D9* aLayer)
+    : mLayer(aLayer)
+  {
+  }
+  virtual ~ShadowBufferD3D9() {}
+  
+  void Upload(gfxASurface* aUpdate, const nsIntRect& aVisibleRect);
+
+  void RenderTo(LayerManagerD3D9 *aD3DManager, const nsIntRegion& aVisibleRegion);
+
+  nsIntSize GetSize() {
+    if (mTexture)
+      return nsIntSize(mTextureRect.Width(), mTextureRect.Height());
+    return nsIntSize(0, 0);
+  }
+protected:
+  nsRefPtr<IDirect3DTexture9> mTexture;
+  nsIntRect mTextureRect;
+  LayerD3D9* mLayer;
+};
+
+} /* layers */
+} /* mozilla */
+#endif /* GFX_SHADOWBUFFERD3D9_H */
--- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp
@@ -30,16 +30,20 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "mozilla/layers/PLayers.h"
+#include "mozilla/layers/ShadowLayers.h"
+#include "ShadowBufferD3D9.h"
+
 #include "ThebesLayerD3D9.h"
 #include "gfxPlatform.h"
 
 #include "gfxWindowsPlatform.h"
 #include "gfxTeeSurface.h"
 #include "gfxUtils.h"
 #include "ReadbackProcessor.h"
 
@@ -511,36 +515,39 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion 
   {
     case SURFACE_OPAQUE:
       opaqueRenderer.End();
       srcTextures.AppendElement(opaqueRenderer.GetTexture());
       destTextures.AppendElement(mTexture);
       break;
 
     case SURFACE_SINGLE_CHANNEL_ALPHA: {
-      D3DLOCKED_RECT r;
-      tmpTexture->LockRect(0, &r, NULL, 0);
+      LockTextureRectD3D9 textureLock(tmpTexture);
+      if (!textureLock.HasLock()) {
+        NS_WARNING("Failed to lock ThebesLayer tmpTexture texture.");
+        return;
+      }
+
+      D3DLOCKED_RECT r = textureLock.GetLockRect();
 
       nsRefPtr<gfxImageSurface> imgSurface =
         new gfxImageSurface((unsigned char *)r.pBits,
                             bounds.Size(),
                             r.Pitch,
                             gfxASurface::ImageFormatARGB32);
 
       if (destinationSurface) {
         nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
         context->SetSource(destinationSurface);
         context->SetOperator(gfxContext::OPERATOR_SOURCE);
         context->Paint();
       }
 
       imgSurface = NULL;
 
-      tmpTexture->UnlockRect(0);
-
       srcTextures.AppendElement(tmpTexture);
       destTextures.AppendElement(mTexture);
       break;
     }
 
     case SURFACE_COMPONENT_ALPHA: {
       opaqueRenderer.End();
       opaqueRendererOnWhite.End();
@@ -596,10 +603,100 @@ ThebesLayerD3D9::CreateNewTextures(const
   if (aMode == SURFACE_COMPONENT_ALPHA) {
     device()->CreateTexture(aSize.width, aSize.height, 1,
                             D3DUSAGE_RENDERTARGET,
                             D3DFMT_X8R8G8B8,
                             D3DPOOL_DEFAULT, getter_AddRefs(mTextureOnWhite), NULL);
   }
 }
 
+ShadowThebesLayerD3D9::ShadowThebesLayerD3D9(LayerManagerD3D9 *aManager)
+  : ShadowThebesLayer(aManager, nsnull)
+  , LayerD3D9(aManager)
+{
+  mImplData = static_cast<LayerD3D9*>(this);
+}
+
+ShadowThebesLayerD3D9::~ShadowThebesLayerD3D9()
+{}
+
+void
+ShadowThebesLayerD3D9::SetFrontBuffer(const OptionalThebesBuffer& aNewFront,
+                                     const nsIntRegion& aValidRegion)
+{
+  if (!mBuffer) {
+    mBuffer = new ShadowBufferD3D9(this);
+  }
+
+  NS_ASSERTION(OptionalThebesBuffer::Tnull_t == aNewFront.type(),
+               "Only one system-memory buffer expected");
+}
+
+void
+ShadowThebesLayerD3D9::Swap(const ThebesBuffer& aNewFront,
+                           const nsIntRegion& aUpdatedRegion,
+                           ThebesBuffer* aNewBack,
+                           nsIntRegion* aNewBackValidRegion,
+                           OptionalThebesBuffer* aReadOnlyFront,
+                           nsIntRegion* aFrontUpdatedRegion)
+{
+  if (mBuffer) {
+    nsRefPtr<gfxASurface> surf = ShadowLayerForwarder::OpenDescriptor(aNewFront.buffer());
+    mBuffer->Upload(surf, GetVisibleRegion().GetBounds());
+  }
+
+  *aNewBack = aNewFront;
+  *aNewBackValidRegion = mValidRegion;
+  *aReadOnlyFront = null_t();
+  aFrontUpdatedRegion->SetEmpty();
+}
+
+void
+ShadowThebesLayerD3D9::DestroyFrontBuffer()
+{
+  mBuffer = nsnull;
+}
+
+void
+ShadowThebesLayerD3D9::Disconnect()
+{
+  mBuffer = nsnull;
+}
+
+Layer*
+ShadowThebesLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+PRBool
+ShadowThebesLayerD3D9::IsEmpty()
+{
+  return !mBuffer;
+}
+
+void
+ShadowThebesLayerD3D9::RenderThebesLayer()
+{
+  if (!mBuffer) {
+    return;
+  }
+  NS_ABORT_IF_FALSE(mBuffer, "should have a buffer here");
+
+  mBuffer->RenderTo(mD3DManager, GetEffectiveVisibleRegion());
+}
+
+void
+ShadowThebesLayerD3D9::CleanResources()
+{
+  mBuffer = nsnull;
+  mValidRegion.SetEmpty();
+}
+
+void
+ShadowThebesLayerD3D9::LayerManagerDestroyed()
+{
+  mD3DManager->deviceManager()->mLayersWithResources.RemoveElement(this);
+  mD3DManager = nsnull;
+}
+
 } /* namespace layers */
 } /* namespace mozilla */
--- a/gfx/layers/d3d9/ThebesLayerD3D9.h
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.h
@@ -42,16 +42,17 @@
 #include "LayerManagerD3D9.h"
 #include "gfxImageSurface.h"
 #include "ReadbackProcessor.h"
 
 namespace mozilla {
 namespace layers {
 
 class ReadbackProcessor;
+class ShadowBufferD3D9;
 
 class ThebesLayerD3D9 : public ThebesLayer,
                         public LayerD3D9
 {
 public:
   ThebesLayerD3D9(LayerManagerD3D9 *aManager);
   virtual ~ThebesLayerD3D9();
 
@@ -107,11 +108,42 @@ private:
   /* Create a new texture */
   void CreateNewTextures(const gfxIntSize &aSize, SurfaceMode aMode);
 
   void CopyRegion(IDirect3DTexture9* aSrc, const nsIntPoint &aSrcOffset,
                   IDirect3DTexture9* aDest, const nsIntPoint &aDestOffset,
                   const nsIntRegion &aCopyRegion, nsIntRegion* aValidRegion);
 };
 
+class ShadowThebesLayerD3D9 : public ShadowThebesLayer,
+                              public LayerD3D9
+{
+public:
+  ShadowThebesLayerD3D9(LayerManagerD3D9 *aManager);
+  virtual ~ShadowThebesLayerD3D9();
+
+  // ShadowThebesLayer impl
+  virtual void SetFrontBuffer(const OptionalThebesBuffer& aNewFront,
+                              const nsIntRegion& aValidRegion);
+  virtual void
+  Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion,
+       ThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion,
+       OptionalThebesBuffer* aReadOnlyFront, nsIntRegion* aFrontUpdatedRegion);
+  virtual void DestroyFrontBuffer();
+
+  virtual void Disconnect();
+
+  // LayerD3D9 impl
+  Layer* GetLayer();
+  virtual PRBool IsEmpty();
+  virtual void RenderLayer() { RenderThebesLayer(); }
+  virtual void CleanResources();
+  virtual void LayerManagerDestroyed();
+
+  void RenderThebesLayer();
+
+private:
+  nsRefPtr<ShadowBufferD3D9> mBuffer;
+};
+
 } /* layers */
 } /* mozilla */
 #endif /* GFX_THEBESLAYERD3D9_H */
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -30,16 +30,19 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "mozilla/layers/PLayers.h"
+#include "mozilla/layers/ShadowLayers.h"
+
 #include "gfxSharedImageSurface.h"
 
 #include "CanvasLayerOGL.h"
 
 #include "gfxImageSurface.h"
 #include "gfxContext.h"
 #include "GLContextProvider.h"
 
--- a/gfx/layers/opengl/CanvasLayerOGL.h
+++ b/gfx/layers/opengl/CanvasLayerOGL.h
@@ -33,18 +33,16 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef GFX_CANVASLAYEROGL_H
 #define GFX_CANVASLAYEROGL_H
 
-#include "mozilla/layers/PLayers.h"
-#include "mozilla/layers/ShadowLayers.h"
 
 #include "LayerManagerOGL.h"
 #include "gfxASurface.h"
 #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
 #include "GLXLibrary.h"
 #include "mozilla/X11Util.h"
 #endif
 
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -37,16 +37,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/layers/ShadowLayersParent.h"
 
 #include "BasicLayers.h"
 #include "LayerManagerOGL.h"
+#include "LayerManagerD3D9.h"
 #include "RenderFrameParent.h"
 
 #include "gfx3DMatrix.h"
 #include "nsFrameLoader.h"
 #include "nsViewportFrame.h"
 #include "nsSubDocumentFrame.h"
 #include "nsIObserver.h"
 
@@ -718,16 +719,20 @@ RenderFrameParent::AllocPLayers()
   case LayerManager::LAYERS_BASIC: {
     BasicShadowLayerManager* bslm = static_cast<BasicShadowLayerManager*>(lm);
     return new ShadowLayersParent(bslm);
   }
   case LayerManager::LAYERS_OPENGL: {
     LayerManagerOGL* lmo = static_cast<LayerManagerOGL*>(lm);
     return new ShadowLayersParent(lmo);
   }
+  case LayerManager::LAYERS_D3D9: {
+    LayerManagerD3D9* lmd3d9 = static_cast<LayerManagerD3D9*>(lm);
+    return new ShadowLayersParent(lmd3d9);
+  }
   default: {
     NS_WARNING("shadow layers no sprechen D3D backend yet");
     return nsnull;
   }
   }
 }
 
 bool