Bug 546515: Part 1: Add a layers backend based on Direct3D9. r=jrmuizel
authorBas Schouten <bschouten@mozilla.com>
Mon, 24 May 2010 17:28:51 +0200
changeset 42611 f87f31d83650b20a9065f4dabf24e2cf1604baba
parent 42610 17a065ad96f40add4f72927d035157075c52a59a
child 42612 d4e5f5f19777ceda1cb62be97aebbbe10575d5a7
push idunknown
push userunknown
push dateunknown
reviewersjrmuizel
bugs546515
milestone1.9.3a5pre
Bug 546515: Part 1: Add a layers backend based on Direct3D9. r=jrmuizel
gfx/layers/Layers.h
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/LayerManagerD3D9Shaders.h
gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl
gfx/layers/d3d9/ThebesLayerD3D9.cpp
gfx/layers/d3d9/ThebesLayerD3D9.h
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -117,17 +117,18 @@ class CanvasLayer;
  * root layer, and each container layer holds a reference to its children.
  */
 class THEBES_API LayerManager {
   NS_INLINE_DECL_REFCOUNTING(LayerManager)
 
 public:
   enum LayersBackend {
     LAYERS_BASIC = 0,
-    LAYERS_OPENGL
+    LAYERS_OPENGL,
+    LAYERS_D3D9
   };
 
   virtual ~LayerManager() {}
 
   /**
    * Start a new transaction. Nested transactions are not allowed so
    * there must be no transaction currently in progress.
    * This transaction will update the state of the window from which
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -37,26 +37,30 @@
 
 DEPTH       = ../..
 topsrcdir   = @top_srcdir@
 srcdir      = @srcdir@
 VPATH       = \
   $(srcdir) \
   $(srcdir)/basic \
   $(srcdir)/opengl \
+  $(srcdir)/d3d9 \
   $(NULL)
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE         = thebes
 LIBRARY_NAME   = layers
 LIBXUL_LIBRARY = 1
 FORCE_STATIC_LIB = 1
 
 DEFINES += -DIMPL_THEBES
+ifdef MOZ_DEBUG
+DEFINES += -DD3D_DEBUG_INFO
+endif
 
 EXPORTS = \
         BasicLayers.h \
         ImageLayers.h \
         Layers.h \
         LayerManagerOGL.h \
         $(NULL)
 
@@ -65,12 +69,27 @@ CPPSRCS = \
         BasicLayers.cpp \
         LayerManagerOGL.cpp \
         ColorLayerOGL.cpp \
         ThebesLayerOGL.cpp \
         ContainerLayerOGL.cpp \
         ImageLayerOGL.cpp \
 	CanvasLayerOGL.cpp \
         $(NULL)
+ 
+ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+ifndef WINCE
+EXPORTS += LayerManagerD3D9.h
+
+CPPSRCS += \
+        LayerManagerD3D9.cpp \
+        ThebesLayerD3D9.cpp \
+        ContainerLayerD3D9.cpp \
+        ImageLayerD3D9.cpp \
+        ColorLayerD3D9.cpp \
+        CanvasLayerD3D9.cpp \
+        $(NULL)
+endif
+endif
 
 include $(topsrcdir)/config/rules.mk
 
 CXXFLAGS += $(MOZ_CAIRO_CFLAGS)
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp
@@ -0,0 +1,231 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** 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) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *   Bas Schouten <bschouten@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 "CanvasLayerD3D9.h"
+
+#include "gfxImageSurface.h"
+#include "gfxWindowsSurface.h"
+
+namespace mozilla {
+namespace layers {
+
+CanvasLayerD3D9::~CanvasLayerD3D9()
+{
+}
+
+void
+CanvasLayerD3D9::Initialize(const Data& aData)
+{
+  NS_ASSERTION(mSurface == nsnull, "BasicCanvasLayer::Initialize called twice!");
+
+  if (aData.mSurface) {
+    mSurface = aData.mSurface;
+    NS_ASSERTION(aData.mGLContext == nsnull,
+                 "CanvasLayer can't have both surface and GLContext");
+    mNeedsYFlip = PR_FALSE;
+  } else if (aData.mGLContext) {
+    mGLContext = aData.mGLContext;
+    mGLBufferIsPremultiplied = aData.mGLBufferIsPremultiplied;
+    mNeedsYFlip = PR_TRUE;
+  } else {
+    NS_ERROR("CanvasLayer created without mSurface or mGLContext?");
+  }
+
+  mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
+
+  device()->CreateTexture(mBounds.width, mBounds.height, 1, 0,
+                          D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
+                          getter_AddRefs(mTexture), NULL);
+}
+
+void
+CanvasLayerD3D9::Updated(const nsIntRect& aRect)
+{
+  if (!mTexture) {
+    NS_WARNING("CanvasLayerD3D9::Updated called but no texture present!");
+    return;
+  }
+
+  if (mGLContext) {
+    // WebGL reads entire surface.
+    D3DLOCKED_RECT r;
+    mTexture->LockRect(0, &r, NULL, 0);
+
+    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
+    // in the framebuffer before we read.
+    mGLContext->fFlush();
+
+    // For simplicity, we read the entire framebuffer for now -- in
+    // the future we should use aRect, though with WebGL we don't
+    // have an easy way to generate one.
+    mGLContext->fReadPixels(0, 0, mBounds.width, mBounds.height,
+                            LOCAL_GL_BGRA, LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV,
+                            destination);
+
+    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 = aRect.x;
+    r.top = aRect.y;
+    r.right = aRect.XMost();
+    r.bottom = aRect.YMost();
+
+    D3DLOCKED_RECT lockedRect;
+    mTexture->LockRect(0, &lockedRect, &r, 0);
+
+    PRUint8 *startBits;
+    PRUint32 sourceStride;
+
+    nsRefPtr<gfxImageSurface> sourceSurface;
+
+    if (mSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
+      sourceSurface = static_cast<gfxWindowsSurface*>(mSurface.get())->GetImageSurface();
+      startBits = sourceSurface->Data() + sourceSurface->Stride() * aRect.y +
+                  aRect.x * 4;
+      sourceStride = sourceSurface->Stride();
+    } else if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) {
+      sourceSurface = static_cast<gfxImageSurface*>(sourceSurface.get());
+      if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32 &&
+          sourceSurface->Format() != gfxASurface::ImageFormatRGB24)
+      {
+        mTexture->UnlockRect(0);
+        return;
+      }
+      startBits = sourceSurface->Data() + sourceSurface->Stride() * aRect.y +
+                  aRect.x * 4;
+      sourceStride = sourceSurface->Stride();
+    } else {
+      sourceSurface = new gfxImageSurface(gfxIntSize(aRect.width, aRect.height),
+                                          gfxASurface::ImageFormatARGB32);
+      nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface);
+      ctx->Translate(gfxPoint(-aRect.x, -aRect.y));
+      ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
+      ctx->SetSource(sourceSurface);
+      ctx->Paint();
+      startBits = sourceSurface->Data();
+      sourceStride = sourceSurface->Stride();
+    }
+
+    for (int y = 0; y < aRect.height; y++) {
+      memcpy((PRUint8*)lockedRect.pBits + lockedRect.Pitch * y,
+             startBits + sourceStride * y,
+             aRect.width * 4);
+    }
+
+    mTexture->UnlockRect(0);    
+  }
+}
+
+LayerD3D9::LayerType
+CanvasLayerD3D9::GetType()
+{
+  return TYPE_CANVAS;
+}
+
+Layer*
+CanvasLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+void
+CanvasLayerD3D9::RenderLayer()
+{
+  float quadTransform[4][4];
+  /*
+   * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
+   * and size. To get pixel perfect mapping we offset the quad half a pixel
+   * to the top-left. We also flip the Y axis here, note we can only do this
+   * because we are in CULL_NONE mode!
+   * 
+   * See: http://msdn.microsoft.com/en-us/library/bb219690%28VS.85%29.aspx
+   */
+  memset(&quadTransform, 0, sizeof(quadTransform));
+  quadTransform[0][0] = (float)mBounds.width;
+  if (mNeedsYFlip) {
+    quadTransform[1][1] = (float)-mBounds.height;
+    quadTransform[3][1] = (float)mBounds.height - 0.5f;
+  } else {
+    quadTransform[1][1] = (float)mBounds.height;
+    quadTransform[3][1] = -0.5f;
+  }
+  quadTransform[2][2] = 1.0f;
+  quadTransform[3][0] = -0.5f;
+  quadTransform[3][3] = 1.0f;
+
+  device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
+
+  device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
+
+  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] = GetOpacity();
+  device()->SetPixelShaderConstantF(0, opacity, 1);
+
+  mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
+
+  if (!mGLBufferIsPremultiplied) {
+    device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
+  }
+  device()->SetTexture(0, mTexture);
+  device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+  if (!mGLBufferIsPremultiplied) {
+    device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
+  }
+}
+
+} /* namespace layers */
+} /* namespace mozilla */
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.h
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** 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) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *   Bas Schouten <bschouten@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_CANVASLAYEROGL_H
+#define GFX_CANVASLAYEROGL_H
+
+#include "LayerManagerD3D9.h"
+#include "GLContext.h"
+#include "gfxASurface.h"
+
+namespace mozilla {
+namespace layers {
+
+class THEBES_API CanvasLayerD3D9 :
+  public CanvasLayer,
+  public LayerD3D9
+{
+public:
+  CanvasLayerD3D9(LayerManagerD3D9 *aManager)
+    : CanvasLayer(aManager, NULL),
+      LayerD3D9(aManager),
+      mTexture(0),
+      mGLBufferIsPremultiplied(PR_FALSE),
+      mNeedsYFlip(PR_FALSE)
+  { 
+      mImplData = static_cast<LayerD3D9*>(this);
+  }
+
+  ~CanvasLayerD3D9();
+
+  // CanvasLayer implementation
+  virtual void Initialize(const Data& aData);
+  virtual void Updated(const nsIntRect& aRect);
+
+  // LayerD3D9 implementation
+  virtual LayerType GetType();
+  virtual Layer* GetLayer();
+  virtual void RenderLayer();
+
+protected:
+  typedef mozilla::gl::GLContext GLContext;
+
+  nsRefPtr<gfxASurface> mSurface;
+  nsRefPtr<GLContext> mGLContext;
+  nsRefPtr<IDirect3DTexture9> mTexture;
+
+  nsIntRect mBounds;
+
+  PRPackedBool mGLBufferIsPremultiplied;
+  PRPackedBool mNeedsYFlip;
+};
+
+} /* layers */
+} /* mozilla */
+#endif /* GFX_CANVASLAYERD3D9_H */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ColorLayerD3D9.cpp
@@ -0,0 +1,91 @@
+/* -*- 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) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Robert O'Callahan <robert@ocallahan.org>
+ *   Bas Schouten <bschouten@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 "ColorLayerD3D9.h"
+
+namespace mozilla {
+namespace layers {
+
+LayerD3D9::LayerType
+ColorLayerD3D9::GetType()
+{
+  return TYPE_COLOR;
+}
+
+Layer*
+ColorLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+void
+ColorLayerD3D9::RenderLayer()
+{
+  // XXX we might be able to improve performance by using 
+  // IDirect3DDevice9::Clear
+
+  float quadTransform[4][4];
+  nsIntRect visibleRect = mVisibleRegion.GetBounds();
+  // Transform the quad to the size of the visible area.
+  memset(&quadTransform, 0, sizeof(quadTransform));
+  quadTransform[0][0] = (float)visibleRect.width;
+  quadTransform[1][1] = (float)visibleRect.height;
+  quadTransform[2][2] = 1.0f;
+  quadTransform[3][0] = (float)visibleRect.x;
+  quadTransform[3][1] = (float)visibleRect.y;
+  quadTransform[3][3] = 1.0f;
+
+  device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
+  device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
+
+  float color[4];
+  // color is premultiplied, so we need to adjust all channels
+  color[0] = (float)(mColor.r * GetOpacity());
+  color[1] = (float)(mColor.g * GetOpacity());
+  color[2] = (float)(mColor.b * GetOpacity());
+  color[3] = (float)(mColor.a * GetOpacity());
+
+  device()->SetPixelShaderConstantF(0, color, 1);
+
+  mD3DManager->SetShaderMode(LayerManagerD3D9::SOLIDCOLORLAYER);
+
+  device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+}
+
+} /* layers */
+} /* mozilla */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ColorLayerD3D9.h
@@ -0,0 +1,74 @@
+/* -*- 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) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Robert O'Callahan <robert@ocallahan.org>
+ *   Bas Schouten <bschouten@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_COLORLAYERD3D9_H
+#define GFX_COLORLAYERD3D9_H
+
+#include "LayerManagerD3D9.h"
+
+namespace mozilla {
+namespace layers {
+
+class THEBES_API ColorLayerD3D9 : public ColorLayer,
+                                 public LayerD3D9
+{
+public:
+  ColorLayerD3D9(LayerManagerD3D9 *aManager)
+    : ColorLayer(aManager, NULL)
+    , LayerD3D9(aManager)
+  { 
+    mImplData = static_cast<LayerD3D9*>(this);
+  }
+
+  virtual void SetVisibleRegion(const nsIntRegion& aRegion) { mVisibleRegion = aRegion; }
+
+  // LayerD3D9 Implementation
+  virtual LayerType GetType();
+
+  virtual Layer* GetLayer();
+
+  virtual void RenderLayer();
+
+protected:
+  nsIntRegion mVisibleRegion;
+};
+
+} /* layers */
+} /* mozilla */
+
+#endif /* GFX_COLORLAYERD3D9_H */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ContainerLayerD3D9.cpp
@@ -0,0 +1,252 @@
+/* -*- 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) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@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 "ContainerLayerD3D9.h"
+
+namespace mozilla {
+namespace layers {
+
+ContainerLayerD3D9::ContainerLayerD3D9(LayerManagerD3D9 *aManager)
+  : ContainerLayer(aManager, NULL)
+  , LayerD3D9(aManager)
+{
+  mImplData = static_cast<LayerD3D9*>(this);
+}
+
+const nsIntRect&
+ContainerLayerD3D9::GetVisibleRect()
+{
+  return mVisibleRect;
+}
+
+void
+ContainerLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion)
+{
+  mVisibleRect = aRegion.GetBounds();
+}
+
+void
+ContainerLayerD3D9::InsertAfter(Layer* aChild, Layer* aAfter)
+{
+  LayerD3D9 *newChild = static_cast<LayerD3D9*>(aChild->ImplData());
+  aChild->SetParent(this);
+  if (!aAfter) {
+    LayerD3D9 *oldFirstChild = GetFirstChildD3D9();
+    mFirstChild = newChild->GetLayer();
+    newChild->SetNextSibling(oldFirstChild);
+    return;
+  }
+  for (LayerD3D9 *child = GetFirstChildD3D9(); 
+    child; child = child->GetNextSibling()) {
+    if (aAfter == child->GetLayer()) {
+      LayerD3D9 *oldNextSibling = child->GetNextSibling();
+      child->SetNextSibling(newChild);
+      child->GetNextSibling()->SetNextSibling(oldNextSibling);
+      return;
+    }
+  }
+  NS_WARNING("Failed to find aAfter layer!");
+}
+
+void
+ContainerLayerD3D9::RemoveChild(Layer *aChild)
+{
+  if (GetFirstChild() == aChild) {
+    mFirstChild = GetFirstChildD3D9()->GetNextSibling() ?
+      GetFirstChildD3D9()->GetNextSibling()->GetLayer() : nsnull;
+    return;
+  }
+  LayerD3D9 *lastChild = NULL;
+  for (LayerD3D9 *child = GetFirstChildD3D9(); child; 
+    child = child->GetNextSibling()) {
+    if (child->GetLayer() == aChild) {
+      // We're sure this is not our first child. So lastChild != NULL.
+      lastChild->SetNextSibling(child->GetNextSibling());
+      child->SetNextSibling(NULL);
+      child->GetLayer()->SetParent(NULL);
+      return;
+    }
+    lastChild = child;
+  }
+}
+
+LayerD3D9::LayerType
+ContainerLayerD3D9::GetType()
+{
+  return TYPE_CONTAINER;
+}
+
+Layer*
+ContainerLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+LayerD3D9*
+ContainerLayerD3D9::GetFirstChildD3D9()
+{
+  if (!mFirstChild) {
+    return nsnull;
+  }
+  return static_cast<LayerD3D9*>(mFirstChild->ImplData());
+}
+
+void
+ContainerLayerD3D9::RenderLayer()
+{
+  float opacity = GetOpacity();
+  nsRefPtr<IDirect3DSurface9> previousRenderTarget;
+  nsRefPtr<IDirect3DTexture9> renderTexture;
+  float previousRenderTargetOffset[4];
+  float renderTargetOffset[] = { 0, 0, 0, 0 };
+  float oldViewMatrix[4][4];
+
+  PRBool useIntermediate = (opacity != 1.0 || !mTransform.IsIdentity());
+
+  if (useIntermediate) {
+    device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget));
+    device()->CreateTexture(mVisibleRect.width, mVisibleRect.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);
+    device()->GetVertexShaderConstantF(12, previousRenderTargetOffset, 1);
+    renderTargetOffset[0] = (float)GetVisibleRect().x;
+    renderTargetOffset[1] = (float)GetVisibleRect().y;
+    device()->SetVertexShaderConstantF(12, renderTargetOffset, 1);
+
+    float viewMatrix[4][4];
+    /*
+     * Matrix to transform to viewport space ( <-1.0, 1.0> topleft, 
+     * <1.0, -1.0> bottomright)
+     */
+    memset(&viewMatrix, 0, sizeof(viewMatrix));
+    viewMatrix[0][0] = 2.0f / mVisibleRect.width;
+    viewMatrix[1][1] = -2.0f / mVisibleRect.height;
+    viewMatrix[2][2] = 1.0f;
+    viewMatrix[3][0] = -1.0f;
+    viewMatrix[3][1] = 1.0f;
+    viewMatrix[3][3] = 1.0f;
+    
+    device()->GetVertexShaderConstantF(8, &oldViewMatrix[0][0], 4);
+    device()->SetVertexShaderConstantF(8, &viewMatrix[0][0], 4);
+  }
+
+  /*
+   * Render this container's contents.
+   */
+  LayerD3D9 *layerToRender = GetFirstChildD3D9();
+  while (layerToRender) {
+    const nsIntRect *clipRect = layerToRender->GetLayer()->GetClipRect();
+    RECT r;
+    if (clipRect) {
+      r.left = (LONG)(clipRect->x - renderTargetOffset[0]);
+      r.top = (LONG)(clipRect->y - renderTargetOffset[1]);
+      r.right = (LONG)(clipRect->x - renderTargetOffset[0] + clipRect->width);
+      r.bottom = (LONG)(clipRect->y - renderTargetOffset[1] + clipRect->height);
+    } else {
+      if (useIntermediate) {
+        r.left = 0;
+        r.top = 0;
+      } else {
+        r.left = GetVisibleRect().x;
+        r.top = GetVisibleRect().y;
+      }
+      r.right = r.left + GetVisibleRect().width;
+      r.bottom = r.top + GetVisibleRect().height;
+    }
+
+    nsRefPtr<IDirect3DSurface9> renderSurface;
+    device()->GetRenderTarget(0, getter_AddRefs(renderSurface));
+
+    D3DSURFACE_DESC desc;
+    renderSurface->GetDesc(&desc);
+
+    r.left = NS_MAX<LONG>(0, r.left);
+    r.top = NS_MAX<LONG>(0, r.top);
+    r.bottom = NS_MIN<LONG>(r.bottom, desc.Height);
+    r.right = NS_MIN<LONG>(r.right, desc.Width);
+
+    device()->SetScissorRect(&r);
+
+    layerToRender->RenderLayer();
+    layerToRender = layerToRender->GetNextSibling();
+  }
+
+  if (useIntermediate) {
+    device()->SetRenderTarget(0, previousRenderTarget);
+    device()->SetVertexShaderConstantF(12, previousRenderTargetOffset, 1);
+    device()->SetVertexShaderConstantF(8, &oldViewMatrix[0][0], 4);
+
+    float quadTransform[4][4];
+    /*
+     * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
+     * and size. To get pixel perfect mapping we offset the quad half a pixel
+     * to the top-left.
+     * 
+     * See: http://msdn.microsoft.com/en-us/library/bb219690%28VS.85%29.aspx
+     */
+    memset(&quadTransform, 0, sizeof(quadTransform));
+    quadTransform[0][0] = (float)GetVisibleRect().width;
+    quadTransform[1][1] = (float)GetVisibleRect().height;
+    quadTransform[2][2] = 1.0f;
+    quadTransform[3][0] = (float)GetVisibleRect().x - 0.5f;
+    quadTransform[3][1] = (float)GetVisibleRect().y - 0.5f;
+    quadTransform[3][3] = 1.0f;
+
+    device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
+    device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
+
+    float opacityVector[4];
+    /*
+     * We always upload a 4 component float, but the shader will use only the
+     * first component since it's declared as a 'float'.
+     */
+    opacityVector[0] = opacity;
+    device()->SetPixelShaderConstantF(0, opacityVector, 1);
+
+    mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
+
+    device()->SetTexture(0, renderTexture);
+    device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+  }
+}
+
+} /* layers */
+} /* mozilla */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ContainerLayerD3D9.h
@@ -0,0 +1,80 @@
+/* -*- 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) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@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_CONTAINERLAYERD3D9_H
+#define GFX_CONTAINERLAYERD3D9_H
+
+#include "Layers.h"
+#include "LayerManagerD3D9.h"
+
+namespace mozilla {
+namespace layers {
+
+class ContainerLayerD3D9 : public ContainerLayer, 
+                          public LayerD3D9
+{
+public:
+  ContainerLayerD3D9(LayerManagerD3D9 *aManager);
+
+  const nsIntRect &GetVisibleRect();
+
+  /* ContainerLayer implementation */
+  void SetVisibleRegion(const nsIntRegion& aRegion);
+
+  void InsertAfter(Layer* aChild, Layer* aAfter);
+
+  void RemoveChild(Layer* aChild);
+
+  /* LayerD3D9 implementation */
+  LayerType GetType();
+
+  Layer* GetLayer();
+
+  LayerD3D9* GetFirstChildD3D9();
+
+  PRBool IsEmpty();
+
+  void RenderLayer();
+
+private:
+  nsIntRect mVisibleRect;
+};
+
+} /* layers */
+} /* mozilla */
+
+#endif /* GFX_CONTAINERLAYERD3D9_H */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -0,0 +1,463 @@
+/* -*- 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) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@mozilla.org>
+ *
+ * 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 "ImageLayerD3D9.h"
+#include "gfxImageSurface.h"
+#include "yuv_convert.h"
+
+namespace mozilla {
+namespace layers {
+
+using mozilla::MutexAutoLock;
+
+ImageContainerD3D9::ImageContainerD3D9(LayerManagerD3D9 *aManager)
+  : ImageContainer(aManager)
+  , mActiveImageLock("mozilla.layers.ImageContainerD3D9.mActiveImageLock")
+{
+}
+
+already_AddRefed<Image>
+ImageContainerD3D9::CreateImage(const Image::Format *aFormats,
+                               PRUint32 aNumFormats)
+{
+  if (!aNumFormats) {
+    return nsnull;
+  }
+  nsRefPtr<Image> img;
+  if (aFormats[0] == Image::PLANAR_YCBCR) {
+    img = new PlanarYCbCrImageD3D9(static_cast<LayerManagerD3D9*>(mManager));
+  } else if (aFormats[0] == Image::CAIRO_SURFACE) {
+    img = new CairoImageD3D9(static_cast<LayerManagerD3D9*>(mManager));
+  }
+  return img.forget();
+}
+
+void
+ImageContainerD3D9::SetCurrentImage(Image *aImage)
+{
+  MutexAutoLock lock(mActiveImageLock);
+
+  mActiveImage = aImage;
+}
+
+already_AddRefed<Image>
+ImageContainerD3D9::GetCurrentImage()
+{
+  MutexAutoLock lock(mActiveImageLock);
+
+  nsRefPtr<Image> retval = mActiveImage;
+  return retval.forget();
+}
+
+already_AddRefed<gfxASurface>
+ImageContainerD3D9::GetCurrentAsSurface(gfxIntSize *aSize)
+{
+  MutexAutoLock lock(mActiveImageLock);
+  if (!mActiveImage) {
+    return nsnull;
+  }
+
+  if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
+    PlanarYCbCrImageD3D9 *yuvImage =
+      static_cast<PlanarYCbCrImageD3D9*>(mActiveImage.get());
+    if (yuvImage->HasData()) {
+      *aSize = yuvImage->mSize;
+    }
+  } else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
+    CairoImageD3D9 *cairoImage =
+      static_cast<CairoImageD3D9*>(mActiveImage.get());
+    *aSize = cairoImage->mSize;
+  }
+
+  return static_cast<ImageD3D9*>(mActiveImage->GetImplData())->GetAsSurface();
+}
+
+gfxIntSize
+ImageContainerD3D9::GetCurrentSize()
+{
+  MutexAutoLock lock(mActiveImageLock);
+  if (!mActiveImage) {
+    return gfxIntSize(0,0);
+  }
+  if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
+    PlanarYCbCrImageD3D9 *yuvImage =
+      static_cast<PlanarYCbCrImageD3D9*>(mActiveImage.get());
+    if (!yuvImage->HasData()) {
+      return gfxIntSize(0,0);
+    }
+    return yuvImage->mSize;
+
+  } else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
+    CairoImageD3D9 *cairoImage =
+      static_cast<CairoImageD3D9*>(mActiveImage.get());
+    return cairoImage->mSize;
+  }
+
+  return gfxIntSize(0,0);
+}
+
+LayerD3D9::LayerType
+ImageLayerD3D9::GetType()
+{
+  return TYPE_IMAGE;
+}
+
+Layer*
+ImageLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+void
+ImageLayerD3D9::RenderLayer()
+{
+  if (!GetContainer()) {
+    return;
+  }
+
+  nsRefPtr<Image> image = GetContainer()->GetCurrentImage();
+
+  if (image->GetFormat() == Image::PLANAR_YCBCR) {
+    PlanarYCbCrImageD3D9 *yuvImage =
+      static_cast<PlanarYCbCrImageD3D9*>(image.get());
+
+    if (!yuvImage->HasData()) {
+      return;
+    }
+    yuvImage->AllocateTextures();
+
+    float quadTransform[4][4];
+    /*
+     * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
+     * and size. To get pixel perfect mapping we extend the quad half a pixel
+     * beyond all edges.
+     */
+    memset(&quadTransform, 0, sizeof(quadTransform));
+    quadTransform[0][0] = (float)yuvImage->mSize.width + 0.5f;
+    quadTransform[1][1] = (float)yuvImage->mSize.height + 0.5f;
+    quadTransform[2][2] = 1.0f;
+    quadTransform[3][3] = 1.0f;
+
+
+    device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
+    device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
+
+    float opacity[4];
+    /*
+     * We always upload a 4 component float, but the shader will
+     * only use the the first component since it's declared as a 'float'.
+     */
+    opacity[0] = GetOpacity();
+    device()->SetPixelShaderConstantF(0, opacity, 1);
+
+    mD3DManager->SetShaderMode(LayerManagerD3D9::YCBCRLAYER);
+
+    device()->SetTexture(0, yuvImage->mYTexture);
+    device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+    device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+    device()->SetTexture(1, yuvImage->mCbTexture);
+    device()->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+    device()->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+    device()->SetTexture(2, yuvImage->mCrTexture);
+    device()->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+    device()->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+
+    device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+
+  } else if (image->GetFormat() == Image::CAIRO_SURFACE) {
+    CairoImageD3D9 *cairoImage =
+      static_cast<CairoImageD3D9*>(image.get());
+
+    float quadTransform[4][4];
+    /*
+     * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
+     * and size. To get pixel perfect mapping we extend the quad half a pixel
+     * beyond all edges.
+     */
+    memset(&quadTransform, 0, sizeof(quadTransform));
+    quadTransform[0][0] = (float)cairoImage->mSize.width + 0.5f;
+    quadTransform[1][1] = (float)cairoImage->mSize.height + 0.5f;
+    quadTransform[2][2] = 1.0f;
+    quadTransform[3][3] = 1.0f;
+
+
+    device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
+    device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
+
+    float opacity[4];
+    /*
+     * We always upload a 4 component float, but the shader will
+     * only use the the first component since it's declared as a 'float'.
+     */
+    opacity[0] = GetOpacity();
+    device()->SetPixelShaderConstantF(0, opacity, 1);
+
+    mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
+
+    device()->SetTexture(0, cairoImage->mTexture);
+    device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+  }
+}
+
+PlanarYCbCrImageD3D9::PlanarYCbCrImageD3D9(mozilla::layers::LayerManagerD3D9* aManager)
+  : PlanarYCbCrImage(static_cast<ImageD3D9*>(this))
+  , mManager(aManager)
+  , mHasData(PR_FALSE)
+{
+}
+
+void
+PlanarYCbCrImageD3D9::SetData(const PlanarYCbCrImage::Data &aData)
+{
+  // For now, we copy the data
+  int width_shift = 0;
+  int height_shift = 0;
+  if (aData.mYSize.width == aData.mCbCrSize.width &&
+      aData.mYSize.height == aData.mCbCrSize.height) {
+     // YV24 format
+     width_shift = 0;
+     height_shift = 0;
+  } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
+             aData.mYSize.height == aData.mCbCrSize.height) {
+    // YV16 format
+    width_shift = 1;
+    height_shift = 0;
+  } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
+             aData.mYSize.height / 2 == aData.mCbCrSize.height ) {
+      // YV12 format
+    width_shift = 1;
+    height_shift = 1;
+  } else {
+    NS_ERROR("YCbCr format not supported");
+  }
+
+  mData = aData;
+  mData.mCbCrStride = mData.mCbCrSize.width = aData.mPicSize.width >> width_shift;
+  mData.mCbCrSize.height = aData.mPicSize.height >> height_shift;
+  mData.mYSize = aData.mPicSize;
+  mData.mYStride = mData.mYSize.width;
+  
+  mBuffer = new PRUint8[mData.mCbCrStride * mData.mCbCrSize.height * 2 +
+                        mData.mYStride * mData.mYSize.height];
+  mData.mYChannel = mBuffer;
+  mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
+  mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
+
+  mData.mCrChannel = new PRUint8[mData.mCbCrStride * mData.mCbCrSize.height];
+  int cbcr_x = aData.mPicX >> width_shift;
+  int cbcr_y = aData.mPicY >> height_shift;
+
+  for (int i = 0; i < mData.mYSize.height; i++) {
+    memcpy(mData.mYChannel + i * mData.mYStride,
+           aData.mYChannel + ((aData.mPicY + i) * aData.mYStride) + aData.mPicX,
+           mData.mYStride);
+  }
+  for (int i = 0; i < mData.mCbCrSize.height; i++) {
+    memcpy(mData.mCbChannel + i * mData.mCbCrStride,
+           aData.mCbChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
+           mData.mCbCrStride);
+  }
+  for (int i = 0; i < mData.mCbCrSize.height; i++) {
+    memcpy(mData.mCrChannel + i * mData.mCbCrStride,
+           aData.mCrChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
+           mData.mCbCrStride);
+  }
+
+  // Fix picture rect to be correct
+  mData.mPicX = mData.mPicY = 0;
+  mSize = aData.mPicSize;
+
+  mHasData = PR_TRUE;
+}
+
+void
+PlanarYCbCrImageD3D9::AllocateTextures()
+{
+
+
+  D3DLOCKED_RECT lockrect;
+  PRUint8* src;
+  PRUint8* dest;
+  //XXX: ensure correct usage flags
+  mManager->device()->CreateTexture(mData.mYSize.width, mData.mYSize.height,
+                          1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
+                          getter_AddRefs(mYTexture), NULL);
+
+
+  /* lock the entire texture */
+  mYTexture->LockRect(0, &lockrect, NULL, 0);
+
+  src  = mData.mYChannel;
+  //FIX cast
+  dest = (PRUint8*)lockrect.pBits;
+
+  // copy over data
+  for (int h=0; h<mData.mYSize.height; h++) {
+    memcpy(dest, src, mData.mYSize.width);
+    dest += lockrect.Pitch;
+    src += mData.mYStride;
+  }
+
+  mYTexture->UnlockRect(0);
+
+  //XXX: ensure correct usage flags
+  mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
+                          1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
+                          getter_AddRefs(mCbTexture), NULL);
+
+
+  /* lock the entire texture */
+  mCbTexture->LockRect(0, &lockrect, NULL, 0);
+
+  src  = mData.mCbChannel;
+  //FIX cast
+  dest = (PRUint8*)lockrect.pBits;
+
+  // copy over data
+  for (int h=0; h<mData.mCbCrSize.height; h++) {
+    memcpy(dest, src, mData.mCbCrSize.width);
+    dest += lockrect.Pitch;
+    src += mData.mCbCrStride;
+  }
+
+  mCbTexture->UnlockRect(0);
+
+
+  //XXX: ensure correct usage flags
+  mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
+                          1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
+                          getter_AddRefs(mCrTexture), NULL);
+
+
+  /* lock the entire texture */
+  mCrTexture->LockRect(0, &lockrect, NULL, 0);
+
+  src  = mData.mCrChannel;
+  //FIX cast
+  dest = (PRUint8*)lockrect.pBits;
+
+  // copy over data
+  for (int h=0; h<mData.mCbCrSize.height; h++) {
+    memcpy(dest, src, mData.mCbCrSize.width);
+    dest += lockrect.Pitch;
+    src += mData.mCbCrStride;
+  }
+
+  mCrTexture->UnlockRect(0);
+
+}
+
+void
+PlanarYCbCrImageD3D9::FreeTextures()
+{
+}
+
+already_AddRefed<gfxASurface>
+PlanarYCbCrImageD3D9::GetAsSurface()
+{
+  nsRefPtr<gfxImageSurface> imageSurface =
+    new gfxImageSurface(mSize, gfxASurface::ImageFormatRGB24);
+ 
+  // Convert from YCbCr to RGB now
+  gfx::ConvertYCbCrToRGB32(mData.mYChannel,
+                           mData.mCbChannel,
+                           mData.mCrChannel,
+                           imageSurface->Data(),
+                           0,
+                           0,
+                           mSize.width,
+                           mSize.height,
+                           mData.mYStride,
+                           mData.mCbCrStride,
+                           imageSurface->Stride(),
+                           gfx::YV12); 
+
+  return imageSurface.forget().get();
+}
+
+CairoImageD3D9::~CairoImageD3D9()
+{
+}
+
+void
+CairoImageD3D9::SetData(const CairoImage::Data &aData)
+{
+  mSize = aData.mSize;
+
+  nsRefPtr<gfxImageSurface> imageSurface =
+    new gfxImageSurface(aData.mSize, gfxASurface::ImageFormatARGB32);
+
+  nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
+
+  context->SetSource(aData.mSurface);
+  context->Paint();
+
+  //XXX: make sure we're using the correct usage flags
+  mManager->device()->CreateTexture(aData.mSize.width, aData.mSize.height,
+                  1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
+                  getter_AddRefs(mTexture), NULL);
+
+  D3DLOCKED_RECT lockrect;
+  /* lock the entire texture */
+  mTexture->LockRect(0, &lockrect, NULL, 0);
+
+  PRUint8* src  = imageSurface->Data();
+  //FIX cast
+  PRUint8* dest = (PRUint8*)lockrect.pBits;
+
+  // copy over data. If we don't need to do any swaping we can
+  // use memcpy
+  for (int i=0; i<aData.mSize.width*aData.mSize.height; i++) {
+    dest[0] = src[0];
+    dest[1] = src[1];
+    dest[2] = src[2];
+    dest[3] = src[3];
+    dest += 4;
+    src += 4;
+  }
+
+  mTexture->UnlockRect(0);
+}
+
+already_AddRefed<gfxASurface>
+CairoImageD3D9::GetAsSurface()
+{
+  return nsnull;
+}
+
+} /* layers */
+} /* mozilla */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ImageLayerD3D9.h
@@ -0,0 +1,155 @@
+/* -*- 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) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@mozilla.org>
+ *
+ * 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_IMAGELAYERD3D9_H
+#define GFX_IMAGELAYERD3D9_H
+
+#include "LayerManagerD3D9.h"
+#include "ImageLayers.h"
+#include "mozilla/Mutex.h"
+
+namespace mozilla {
+namespace layers {
+
+class THEBES_API ImageContainerD3D9 : public ImageContainer
+{
+public:
+  ImageContainerD3D9(LayerManagerD3D9 *aManager);
+  virtual ~ImageContainerD3D9() {}
+
+  virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
+                                              PRUint32 aNumFormats);
+
+  virtual void SetCurrentImage(Image* aImage);
+
+  virtual already_AddRefed<Image> GetCurrentImage();
+
+  virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSize);
+
+  virtual gfxIntSize GetCurrentSize();
+
+private:
+  typedef mozilla::Mutex Mutex;
+
+  nsRefPtr<Image> mActiveImage;
+
+  Mutex mActiveImageLock;
+};
+
+class THEBES_API ImageLayerD3D9 : public ImageLayer,
+                                  public LayerD3D9
+{
+public:
+  ImageLayerD3D9(LayerManagerD3D9 *aManager)
+    : ImageLayer(aManager, NULL)
+    , LayerD3D9(aManager)
+  { 
+    mImplData = static_cast<LayerD3D9*>(this);
+  }
+
+  // LayerD3D9 Implementation
+  virtual LayerType GetType();
+
+  virtual Layer* GetLayer();
+
+  virtual void RenderLayer();
+};
+
+class THEBES_API ImageD3D9
+{
+public:
+  virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
+};
+
+class THEBES_API PlanarYCbCrImageD3D9 : public PlanarYCbCrImage,
+                                        public ImageD3D9
+{
+public:
+  PlanarYCbCrImageD3D9(LayerManagerD3D9 *aManager);
+
+  virtual void SetData(const Data &aData);
+
+  /*
+   * Upload the data from out mData into our textures. For now we use this to
+   * make sure the textures are created and filled on the main thread.
+   */
+  void AllocateTextures();
+  /*
+   * XXX
+   * Free the textures, we call this from the main thread when we're done
+   * drawing this frame. We cannot free this from the constructor since it may
+   * be destroyed off the main-thread and might not be able to properly clean
+   * up its textures
+   */
+  void FreeTextures();
+  PRBool HasData() { return mHasData; }
+
+  virtual already_AddRefed<gfxASurface> GetAsSurface();
+  
+  nsAutoArrayPtr<PRUint8> mBuffer;
+  LayerManagerD3D9 *mManager;
+  Data mData;
+  gfxIntSize mSize;
+  nsRefPtr<IDirect3DTexture9> mYTexture;
+  nsRefPtr<IDirect3DTexture9> mCrTexture;
+  nsRefPtr<IDirect3DTexture9> mCbTexture;
+  PRPackedBool mHasData;
+};
+
+
+class THEBES_API CairoImageD3D9 : public CairoImage,
+                                  public ImageD3D9
+{
+public:
+  CairoImageD3D9(LayerManagerD3D9 *aManager)
+    : CairoImage(static_cast<ImageD3D9*>(this))
+    , mManager(aManager)
+  { }
+  ~CairoImageD3D9();
+
+  virtual void SetData(const Data &aData);
+
+  virtual already_AddRefed<gfxASurface> GetAsSurface();
+
+  nsRefPtr<IDirect3DTexture9> mTexture;
+  gfxIntSize mSize;
+  LayerManagerD3D9 *mManager;
+};
+
+} /* layers */
+} /* mozilla */
+#endif /* GFX_IMAGELAYERD3D9_H */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp
@@ -0,0 +1,578 @@
+/* -*- 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) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@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 "ThebesLayerD3D9.h"
+#include "ContainerLayerD3D9.h"
+#include "ImageLayerD3D9.h"
+#include "ColorLayerD3D9.h"
+#include "CanvasLayerD3D9.h"
+
+#include "LayerManagerD3D9Shaders.h"
+
+#include "nsIServiceManager.h"
+#include "nsIConsoleService.h"
+#include "nsPrintfCString.h"
+
+namespace mozilla {
+namespace layers {
+
+struct vertex {
+  float x, y;
+};
+
+IDirect3D9 *LayerManagerD3D9::mD3D9 = NULL;
+
+typedef IDirect3D9* (WINAPI*Direct3DCreate9Func)(
+  UINT SDKVersion
+);
+
+
+LayerManagerD3D9::LayerManagerD3D9(nsIWidget *aWidget)
+{
+    mWidget = aWidget;
+    mCurrentCallbackInfo.Callback = NULL;
+    mCurrentCallbackInfo.CallbackData = NULL;
+}
+
+LayerManagerD3D9::~LayerManagerD3D9()
+{
+}
+
+#define HAS_CAP(a, b) (((a) & (b)) == (b))
+#define LACKS_CAP(a, b) !(((a) & (b)) == (b))
+
+PRBool
+LayerManagerD3D9::Initialize()
+{
+  if (!mD3D9) {
+    Direct3DCreate9Func d3d9create = (Direct3DCreate9Func)
+      GetProcAddress(LoadLibraryW(L"d3d9.dll"), "Direct3DCreate9");
+    if (!d3d9create) {
+      return PR_FALSE;
+    }
+
+    mD3D9 = d3d9create(D3D_SDK_VERSION);
+    if (!mD3D9) {
+      return PR_FALSE;
+    }
+  }
+
+  D3DPRESENT_PARAMETERS pp;
+  memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
+
+  pp.BackBufferFormat = D3DFMT_A8R8G8B8;
+  pp.SwapEffect = D3DSWAPEFFECT_COPY;
+  pp.Windowed = TRUE;
+  pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+  pp.hDeviceWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
+
+  HRESULT hr = mD3D9->CreateDevice(D3DADAPTER_DEFAULT,
+                                   D3DDEVTYPE_HAL,
+                                   NULL,
+                                   D3DCREATE_FPU_PRESERVE |
+                                   D3DCREATE_MULTITHREADED |
+                                   D3DCREATE_MIXED_VERTEXPROCESSING,
+                                   &pp,
+                                   getter_AddRefs(mDevice));
+
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  if (!VerifyCaps()) {
+    return PR_FALSE;
+  }
+
+  hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVS,
+                                   getter_AddRefs(mLayerVS));
+
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPS,
+                                  getter_AddRefs(mRGBPS));
+
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPS,
+                                  getter_AddRefs(mYCbCrPS));
+
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPS,
+                                  getter_AddRefs(mSolidColorPS));
+
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  hr = mDevice->CreateVertexBuffer(sizeof(vertex) * 4,
+                                   0,
+                                   0,
+                                   D3DPOOL_MANAGED,
+                                   getter_AddRefs(mVB),
+                                   NULL);
+
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  vertex *vertices;
+  hr = mVB->Lock(0, 0, (void**)&vertices, 0);
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+  
+  vertices[0].x = vertices[0].y = 0;
+  vertices[1].x = 1; vertices[1].y = 0;
+  vertices[2].x = 0; vertices[2].y = 1;
+  vertices[3].x = 1; vertices[3].y = 1;
+
+  mVB->Unlock();
+
+  hr = mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  D3DVERTEXELEMENT9 elements[] = {
+    { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
+      D3DDECLUSAGE_POSITION, 0 },
+    D3DDECL_END()
+  };
+  
+  mDevice->CreateVertexDeclaration(elements, getter_AddRefs(mVD));
+
+  SetupRenderState();
+
+  nsCOMPtr<nsIConsoleService> 
+    console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
+
+  D3DADAPTER_IDENTIFIER9 identifier;
+  mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier);
+
+  if (console) {
+    nsString msg;
+    msg +=
+      NS_LITERAL_STRING("Direct3D 9 LayerManager Initialized Succesfully.\nDriver: ");
+    msg += NS_ConvertUTF8toUTF16(
+      nsDependentCString((const char*)identifier.Driver));
+    msg += NS_LITERAL_STRING("\nDescription: ");
+    msg += NS_ConvertUTF8toUTF16(
+      nsDependentCString((const char*)identifier.Description));
+    msg += NS_LITERAL_STRING("\nVersion: ");
+    msg += NS_ConvertUTF8toUTF16(
+      nsPrintfCString("%d.%d.%d.%d",
+                      HIWORD(identifier.DriverVersion.HighPart),
+                      LOWORD(identifier.DriverVersion.HighPart),
+                      HIWORD(identifier.DriverVersion.LowPart),
+                      LOWORD(identifier.DriverVersion.LowPart)));
+    console->LogStringMessage(msg.get());
+  }
+
+  return PR_TRUE;
+}
+
+void
+LayerManagerD3D9::SetClippingRegion(const nsIntRegion &aClippingRegion)
+{
+  mClippingRegion = aClippingRegion;
+}
+
+void
+LayerManagerD3D9::BeginTransaction()
+{
+}
+
+void
+LayerManagerD3D9::BeginTransactionWithTarget(gfxContext *aTarget)
+{
+  mTarget = aTarget;
+}
+
+void
+LayerManagerD3D9::EndConstruction()
+{
+}
+
+void
+LayerManagerD3D9::EndTransaction(DrawThebesLayerCallback aCallback,
+                                 void* aCallbackData)
+{
+  mCurrentCallbackInfo.Callback = aCallback;
+  mCurrentCallbackInfo.CallbackData = aCallbackData;
+  Render();
+  /* Clean this out for sanity */
+  mCurrentCallbackInfo.Callback = NULL;
+  mCurrentCallbackInfo.CallbackData = NULL;
+}
+
+void
+LayerManagerD3D9::SetRoot(Layer *aLayer)
+{
+  mRootLayer = static_cast<LayerD3D9*>(aLayer->ImplData());
+}
+
+already_AddRefed<ThebesLayer>
+LayerManagerD3D9::CreateThebesLayer()
+{
+  nsRefPtr<ThebesLayer> layer = new ThebesLayerD3D9(this);
+  return layer.forget();
+}
+
+already_AddRefed<ContainerLayer>
+LayerManagerD3D9::CreateContainerLayer()
+{
+  nsRefPtr<ContainerLayer> layer = new ContainerLayerD3D9(this);
+  return layer.forget();
+}
+
+already_AddRefed<ImageLayer>
+LayerManagerD3D9::CreateImageLayer()
+{
+  nsRefPtr<ImageLayer> layer = new ImageLayerD3D9(this);
+  return layer.forget();
+}
+
+already_AddRefed<ColorLayer>
+LayerManagerD3D9::CreateColorLayer()
+{
+  nsRefPtr<ColorLayer> layer = new ColorLayerD3D9(this);
+  return layer.forget();
+}
+
+already_AddRefed<CanvasLayer>
+LayerManagerD3D9::CreateCanvasLayer()
+{
+  nsRefPtr<CanvasLayer> layer = new CanvasLayerD3D9(this);
+  return layer.forget();
+}
+
+already_AddRefed<ImageContainer>
+LayerManagerD3D9::CreateImageContainer()
+{
+  nsRefPtr<ImageContainer> container = new ImageContainerD3D9(this);
+  return container.forget();
+}
+
+void
+LayerManagerD3D9::SetShaderMode(ShaderMode aMode)
+{
+  switch (aMode) {
+    case RGBLAYER:
+      mDevice->SetVertexShader(mLayerVS);
+      mDevice->SetPixelShader(mRGBPS);
+      break;
+    case YCBCRLAYER:
+      mDevice->SetVertexShader(mLayerVS);
+      mDevice->SetPixelShader(mYCbCrPS);
+      break;
+    case SOLIDCOLORLAYER:
+      mDevice->SetVertexShader(mLayerVS);
+      mDevice->SetPixelShader(mSolidColorPS);
+      break;
+  }
+}
+
+void
+LayerManagerD3D9::Render()
+{
+  if (!SetupBackBuffer()) {
+    return;
+  }
+  SetupPipeline();
+  nsIntRect rect;
+  mWidget->GetBounds(rect);
+
+  mDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0, 0);
+
+  mDevice->BeginScene();
+  
+  if (mRootLayer) {
+    const nsIntRect *clipRect = mRootLayer->GetLayer()->GetClipRect();
+    RECT r;
+    if (clipRect) {
+      r.left = (LONG)clipRect->x;
+      r.top = (LONG)clipRect->y;
+      r.right = (LONG)(clipRect->x + clipRect->width);
+      r.bottom = (LONG)(clipRect->y + clipRect->height);
+    } else {
+      r.left = r.top = 0;
+      r.right = rect.width;
+      r.bottom = rect.height;
+    }
+    mDevice->SetScissorRect(&r);
+
+    mRootLayer->RenderLayer();
+  }
+
+  mDevice->EndScene();
+
+  if (!mTarget) {
+    const nsIntRect *r;
+    for (nsIntRegionRectIterator iter(mClippingRegion);
+         (r = iter.Next()) != nsnull;) {
+      RECT rect;
+      rect.left = r->x;
+      rect.top = r->y;
+      rect.right = r->XMost();
+      rect.bottom = r->YMost();
+
+      mDevice->Present(&rect, &rect, NULL, NULL);
+    }
+  } else {
+    PaintToTarget();
+  }
+}
+
+void
+LayerManagerD3D9::SetupPipeline()
+{
+  nsIntRect rect;
+  mWidget->GetBounds(rect);
+
+  float viewMatrix[4][4];
+  /*
+   * Matrix to transform to viewport space ( <-1.0, 1.0> topleft, 
+   * <1.0, -1.0> bottomright)
+   */
+  memset(&viewMatrix, 0, sizeof(viewMatrix));
+  viewMatrix[0][0] = 2.0f / rect.width;
+  viewMatrix[1][1] = -2.0f / rect.height;
+  viewMatrix[2][2] = 1.0f;
+  viewMatrix[3][0] = -1.0f;
+  viewMatrix[3][1] = 1.0f;
+  viewMatrix[3][3] = 1.0f;
+  
+  HRESULT hr = mDevice->SetVertexShaderConstantF(8, &viewMatrix[0][0], 4);
+
+  if (FAILED(hr)) {
+    NS_WARNING("Failed to set projection shader constant!");
+  }
+}
+
+PRBool
+LayerManagerD3D9::SetupBackBuffer()
+{
+  nsRefPtr<IDirect3DSurface9> backBuffer;
+  mDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
+			 getter_AddRefs(backBuffer));
+
+  D3DSURFACE_DESC desc;
+  nsIntRect rect;
+  mWidget->GetBounds(rect);
+  backBuffer->GetDesc(&desc);
+
+  HRESULT hr = mDevice->TestCooperativeLevel();
+
+  /* The device is lost or something else is wrong, failure */
+  if (FAILED(hr) && hr != D3DERR_DEVICENOTRESET) {
+    return PR_FALSE;
+  }
+
+  /*
+   * If the backbuffer is the right size, and the device is not lost, we can
+   * safely render without doing anything.
+   */
+  if ((desc.Width == rect.width && desc.Height == rect.height) &&
+      SUCCEEDED(hr)) {
+    return PR_TRUE;
+  }
+
+  /*
+   * Our device is lost or our backbuffer needs resizing, start by clearing
+   * out all D3DPOOL_DEFAULT surfaces.
+   */
+  for(unsigned int i = 0; i < mThebesLayers.Length(); i++) {
+    mThebesLayers[i]->CleanResources();
+  }
+
+  backBuffer = NULL;
+
+  D3DPRESENT_PARAMETERS pp;
+  memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
+
+  pp.BackBufferFormat = D3DFMT_A8R8G8B8;
+  pp.SwapEffect = D3DSWAPEFFECT_COPY;
+  pp.Windowed = TRUE;
+  pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+  pp.hDeviceWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
+
+  hr = mDevice->Reset(&pp);
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  SetupRenderState();
+
+  return PR_TRUE;
+}
+
+void
+LayerManagerD3D9::PaintToTarget()
+{
+  nsRefPtr<IDirect3DSurface9> backBuff;
+  nsRefPtr<IDirect3DSurface9> destSurf;
+  mDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
+                         getter_AddRefs(backBuff));
+
+  D3DSURFACE_DESC desc;
+  backBuff->GetDesc(&desc);
+
+  mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height,
+                                       D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM,
+                                       getter_AddRefs(destSurf), NULL);
+
+  mDevice->GetRenderTargetData(backBuff, destSurf);
+
+  D3DLOCKED_RECT rect;
+  destSurf->LockRect(&rect, NULL, D3DLOCK_READONLY);
+
+  nsRefPtr<gfxImageSurface> imageSurface =
+    new gfxImageSurface((unsigned char*)rect.pBits,
+                        gfxIntSize(desc.Width, desc.Height),
+                        rect.Pitch,
+                        gfxASurface::ImageFormatARGB32);
+
+  mTarget->SetSource(imageSurface);
+  mTarget->SetOperator(gfxContext::OPERATOR_OVER);
+  mTarget->Paint();
+  destSurf->UnlockRect();
+}
+
+void
+LayerManagerD3D9::SetupRenderState()
+{
+  mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
+  mDevice->SetVertexDeclaration(mVD);
+  mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+  mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+  mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
+  mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
+  mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
+  mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
+  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);
+}
+
+PRBool
+LayerManagerD3D9::VerifyCaps()
+{
+  D3DCAPS9 caps;
+  HRESULT hr = mDevice->GetDeviceCaps(&caps);
+
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  if (LACKS_CAP(caps.DevCaps, D3DDEVCAPS_TEXTUREVIDEOMEMORY)) {
+    return PR_FALSE;
+  }
+
+  if (LACKS_CAP(caps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE)) {
+    return PR_FALSE;
+  }
+
+  if (LACKS_CAP(caps.SrcBlendCaps, D3DPBLENDCAPS_ONE) ||
+      LACKS_CAP(caps.SrcBlendCaps, D3DBLEND_SRCALPHA) ||
+      LACKS_CAP(caps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA)) {
+    return PR_FALSE;
+  }
+
+  if (LACKS_CAP(caps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST)) {
+    return PR_FALSE;
+  }
+
+  if (LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_ALPHA) ||
+      HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_SQUAREONLY) ||
+      (HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_POW2) &&
+       LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL))) {
+    return PR_FALSE;
+  }
+
+  if (LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR) ||
+      LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR)) {
+    return PR_FALSE;
+  }
+
+  if (LACKS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP)) {
+    return PR_FALSE;
+  }
+
+  if (caps.MaxTextureHeight < 4096 ||
+      caps.MaxTextureWidth < 4096) {
+    return PR_FALSE;
+  }
+
+  if ((caps.PixelShaderVersion & 0xffff) < 0x200 ||
+      (caps.VertexShaderVersion & 0xffff) < 0x200) {
+    return PR_FALSE;
+  }
+  return PR_TRUE;
+}
+
+LayerD3D9::LayerD3D9(LayerManagerD3D9 *aManager)
+  : mD3DManager(aManager)
+  , mNextSibling(NULL)
+{
+}
+
+LayerD3D9*
+LayerD3D9::GetNextSibling()
+{
+  return mNextSibling;
+}
+
+void
+LayerD3D9::SetNextSibling(LayerD3D9 *aNextSibling)
+{
+  mNextSibling = aNextSibling;
+}
+
+} /* namespace layers */
+} /* namespace mozilla */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/LayerManagerD3D9.h
@@ -0,0 +1,239 @@
+/* -*- 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) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@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_LAYERMANAGERD3D9_H
+#define GFX_LAYERMANAGERD3D9_H
+
+#include "Layers.h"
+
+#include <windows.h>
+#include <d3d9.h>
+
+#include "gfxContext.h"
+#include "nsIWidget.h"
+
+namespace mozilla {
+namespace layers {
+
+class LayerD3D9;
+class ThebesLayerD3D9;
+
+/*
+ * This is the LayerManager used for Direct3D 9. For now this will render on
+ * the main thread.
+ */
+class THEBES_API LayerManagerD3D9 : public LayerManager {
+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.
+   * This function is not threadsafe.
+   *
+   * \return True is initialization was succesful, false when it was not.
+   */
+  PRBool Initialize();
+
+  /*
+   * Sets the clipping region for this layer manager. This is important on 
+   * windows because using OGL we no longer have GDI's native clipping. Therefor
+   * widget must tell us what part of the screen is being invalidated,
+   * and we should clip to this.
+   *
+   * \param aClippingRegion Region to clip to. Setting an empty region
+   * will disable clipping.
+   */
+  void SetClippingRegion(const nsIntRegion& aClippingRegion);
+
+  /*
+   * LayerManager implementation.
+   */
+  void BeginTransaction();
+
+  void BeginTransactionWithTarget(gfxContext* aTarget);
+
+  void EndConstruction();
+
+  struct CallbackInfo {
+    DrawThebesLayerCallback Callback;
+    void *CallbackData;
+  };
+
+  void EndTransaction(DrawThebesLayerCallback aCallback,
+                      void* aCallbackData);
+
+  const CallbackInfo &GetCallbackInfo() { return mCurrentCallbackInfo; }
+
+  void SetRoot(Layer* aLayer);
+  
+  virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
+
+  virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
+
+  virtual already_AddRefed<ImageLayer> CreateImageLayer();
+
+  virtual already_AddRefed<ColorLayer> CreateColorLayer();
+
+  virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
+
+  virtual already_AddRefed<ImageContainer> CreateImageContainer();
+
+  virtual LayersBackend GetBackendType() { return LAYERS_D3D9; }
+
+  /*
+   * Helper methods.
+   */
+  void SetClippingEnabled(PRBool aEnabled);
+
+  IDirect3DDevice9 *device() const { return mDevice; }
+
+  enum ShaderMode {
+    RGBLAYER,
+    YCBCRLAYER,
+    SOLIDCOLORLAYER
+  };
+
+  void SetShaderMode(ShaderMode aMode);
+
+  nsTArray<ThebesLayerD3D9*> mThebesLayers;
+
+private:
+  /* Direct3D9 instance */
+  static IDirect3D9 *mD3D9;
+
+  /* Widget associated with this layer manager */
+  nsIWidget *mWidget;
+  /* 
+   * Context target, NULL when drawing directly to our swap chain.
+   */
+  nsRefPtr<gfxContext> mTarget;
+
+  nsRefPtr<IDirect3DDevice9> mDevice;
+
+  /* Vertex shader used for layer quads */
+  nsRefPtr<IDirect3DVertexShader9> mLayerVS;
+
+  /* Pixel shader used for RGB textures */
+  nsRefPtr<IDirect3DPixelShader9> mRGBPS;
+
+  /* Pixel shader used for RGB textures */
+  nsRefPtr<IDirect3DPixelShader9> mYCbCrPS;
+
+  /* Pixel shader used for solid colors */
+  nsRefPtr<IDirect3DPixelShader9> mSolidColorPS;
+
+  /* Vertex buffer containing our basic vertex structure */
+  nsRefPtr<IDirect3DVertexBuffer9> mVB;
+
+  /* Our vertex declaration */
+  nsRefPtr<IDirect3DVertexDeclaration9> mVD;
+
+  /* Current root layer. */
+  LayerD3D9 *mRootLayer;
+
+  /* Callback info for current transaction */
+  CallbackInfo mCurrentCallbackInfo;
+  
+  /*
+   * Region we're clipping our current drawing to.
+   */
+  nsIntRegion mClippingRegion;
+  /*
+   * Render the current layer tree to the active target.
+   */
+  void Render();
+  /*
+   * Setup the pipeline.
+   */
+  void SetupPipeline();
+  /*
+   * Setup the backbuffer.
+   *
+   * \return PR_TRUE if setup was succesful
+   */
+  PRBool SetupBackBuffer();
+  /*
+   * Setup the render state for the surface.
+   */
+  void SetupRenderState();
+  /*
+   * Copies the content of our backbuffer to the set transaction target.
+   */
+  void PaintToTarget();
+  /*
+   * Verifies all required device capabilities are present.
+   */
+  PRBool VerifyCaps();
+
+};
+
+/*
+ * General information and tree management for OGL layers.
+ */
+class LayerD3D9
+{
+public:
+  LayerD3D9(LayerManagerD3D9 *aManager);
+
+  enum LayerType { TYPE_THEBES, TYPE_CONTAINER, TYPE_IMAGE, TYPE_COLOR,
+                   TYPE_CANVAS };
+  
+  virtual LayerType GetType() = 0;
+
+  LayerD3D9 *GetNextSibling();
+  virtual LayerD3D9 *GetFirstChildD3D9() { return nsnull; }
+
+  void SetNextSibling(LayerD3D9 *aParent);
+  void SetFirstChild(LayerD3D9 *aParent);
+
+  virtual Layer* GetLayer() = 0;
+
+  virtual void RenderLayer() = 0;
+
+  IDirect3DDevice9 *device() const { return mD3DManager->device(); }
+protected:
+  LayerManagerD3D9 *mD3DManager;
+  LayerD3D9 *mNextSibling;
+};
+
+} /* layers */
+} /* mozilla */
+
+#endif /* GFX_LAYERMANAGERD3D9_H */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/LayerManagerD3D9Shaders.h
@@ -0,0 +1,435 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
+//
+//   fxc LayerManagerD3D9Shaders.hlsl /ELayerQuadVS /nologo
+//    /FhLayerManagerD3D9Shaders.h /VnLayerQuadVS
+//
+//
+// Parameters:
+//
+//   float4x4 mLayerQuadTransform;
+//   float4x4 mLayerTransform;
+//   float4x4 mProjection;
+//   float4 vRenderTargetOffset;
+//
+//
+// Registers:
+//
+//   Name                Reg   Size
+//   ------------------- ----- ----
+//   mLayerQuadTransform c0       4
+//   mLayerTransform     c4       4
+//   mProjection         c8       4
+//   vRenderTargetOffset c12      1
+//
+
+    vs_2_0
+    dcl_position v0
+    mul r0, v0.y, c1
+    mad r0, c0, v0.x, r0
+    mad r0, c2, v0.z, r0
+    mad r0, c3, v0.w, r0
+    mul r1, r0.y, c5
+    mad r1, c4, r0.x, r1
+    mad r1, c6, r0.z, r1
+    mad r0, c7, r0.w, r1
+    add r0, r0, -c12
+    mul r1, r0.y, c9
+    mad r1, c8, r0.x, r1
+    mad r1, c10, r0.z, r1
+    mad oPos, c11, r0.w, r1
+    mov oT0.xy, v0
+
+// approximately 14 instruction slots used
+#endif
+
+const BYTE LayerQuadVS[] =
+{
+      0,   2, 254, 255, 254, 255, 
+     67,   0,  67,  84,  65,  66, 
+     28,   0,   0,   0, 215,   0, 
+      0,   0,   0,   2, 254, 255, 
+      4,   0,   0,   0,  28,   0, 
+      0,   0,   0,   1,   0,   0, 
+    208,   0,   0,   0, 108,   0, 
+      0,   0,   2,   0,   0,   0, 
+      4,   0,   0,   0, 128,   0, 
+      0,   0,   0,   0,   0,   0, 
+    144,   0,   0,   0,   2,   0, 
+      4,   0,   4,   0,   0,   0, 
+    128,   0,   0,   0,   0,   0, 
+      0,   0, 160,   0,   0,   0, 
+      2,   0,   8,   0,   4,   0, 
+      0,   0, 128,   0,   0,   0, 
+      0,   0,   0,   0, 172,   0, 
+      0,   0,   2,   0,  12,   0, 
+      1,   0,   0,   0, 192,   0, 
+      0,   0,   0,   0,   0,   0, 
+    109,  76,  97, 121, 101, 114, 
+     81, 117,  97, 100,  84, 114, 
+     97, 110, 115, 102, 111, 114, 
+    109,   0,   3,   0,   3,   0, 
+      4,   0,   4,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+    109,  76,  97, 121, 101, 114, 
+     84, 114,  97, 110, 115, 102, 
+    111, 114, 109,   0, 109,  80, 
+    114, 111, 106, 101,  99, 116, 
+    105, 111, 110,   0, 118,  82, 
+    101, 110, 100, 101, 114,  84, 
+     97, 114, 103, 101, 116,  79, 
+    102, 102, 115, 101, 116,   0, 
+      1,   0,   3,   0,   1,   0, 
+      4,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0, 118, 115, 
+     95,  50,  95,  48,   0,  77, 
+    105,  99, 114, 111, 115, 111, 
+    102, 116,  32,  40,  82,  41, 
+     32,  72,  76,  83,  76,  32, 
+     83, 104,  97, 100, 101, 114, 
+     32,  67, 111, 109, 112, 105, 
+    108, 101, 114,  32,  57,  46, 
+     50,  55,  46,  57,  53,  50, 
+     46,  51,  48,  50,  50,   0, 
+     31,   0,   0,   2,   0,   0, 
+      0, 128,   0,   0,  15, 144, 
+      5,   0,   0,   3,   0,   0, 
+     15, 128,   0,   0,  85, 144, 
+      1,   0, 228, 160,   4,   0, 
+      0,   4,   0,   0,  15, 128, 
+      0,   0, 228, 160,   0,   0, 
+      0, 144,   0,   0, 228, 128, 
+      4,   0,   0,   4,   0,   0, 
+     15, 128,   2,   0, 228, 160, 
+      0,   0, 170, 144,   0,   0, 
+    228, 128,   4,   0,   0,   4, 
+      0,   0,  15, 128,   3,   0, 
+    228, 160,   0,   0, 255, 144, 
+      0,   0, 228, 128,   5,   0, 
+      0,   3,   1,   0,  15, 128, 
+      0,   0,  85, 128,   5,   0, 
+    228, 160,   4,   0,   0,   4, 
+      1,   0,  15, 128,   4,   0, 
+    228, 160,   0,   0,   0, 128, 
+      1,   0, 228, 128,   4,   0, 
+      0,   4,   1,   0,  15, 128, 
+      6,   0, 228, 160,   0,   0, 
+    170, 128,   1,   0, 228, 128, 
+      4,   0,   0,   4,   0,   0, 
+     15, 128,   7,   0, 228, 160, 
+      0,   0, 255, 128,   1,   0, 
+    228, 128,   2,   0,   0,   3, 
+      0,   0,  15, 128,   0,   0, 
+    228, 128,  12,   0, 228, 161, 
+      5,   0,   0,   3,   1,   0, 
+     15, 128,   0,   0,  85, 128, 
+      9,   0, 228, 160,   4,   0, 
+      0,   4,   1,   0,  15, 128, 
+      8,   0, 228, 160,   0,   0, 
+      0, 128,   1,   0, 228, 128, 
+      4,   0,   0,   4,   1,   0, 
+     15, 128,  10,   0, 228, 160, 
+      0,   0, 170, 128,   1,   0, 
+    228, 128,   4,   0,   0,   4, 
+      0,   0,  15, 192,  11,   0, 
+    228, 160,   0,   0, 255, 128, 
+      1,   0, 228, 128,   1,   0, 
+      0,   2,   0,   0,   3, 224, 
+      0,   0, 228, 144, 255, 255, 
+      0,   0
+};
+
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
+//
+//   fxc LayerManagerD3D9Shaders.hlsl /ERGBShader /nologo /Tps_2_0
+//    /FhLayerManagerD3D9Shaders.h /VnRGBShaderPS
+//
+//
+// Parameters:
+//
+//   float fLayerOpacity;
+//   sampler2D s2D;
+//
+//
+// Registers:
+//
+//   Name          Reg   Size
+//   ------------- ----- ----
+//   fLayerOpacity c0       1
+//   s2D           s0       1
+//
+
+    ps_2_0
+    dcl t0.xy
+    dcl_2d s0
+    texld r0, t0, s0
+    mul r0, r0, c0.x
+    mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+#endif
+
+const BYTE RGBShaderPS[] =
+{
+      0,   2, 255, 255, 254, 255, 
+     45,   0,  67,  84,  65,  66, 
+     28,   0,   0,   0, 127,   0, 
+      0,   0,   0,   2, 255, 255, 
+      2,   0,   0,   0,  28,   0, 
+      0,   0,   0,   1,   0,   0, 
+    120,   0,   0,   0,  68,   0, 
+      0,   0,   2,   0,   0,   0, 
+      1,   0,   0,   0,  84,   0, 
+      0,   0,   0,   0,   0,   0, 
+    100,   0,   0,   0,   3,   0, 
+      0,   0,   1,   0,   0,   0, 
+    104,   0,   0,   0,   0,   0, 
+      0,   0, 102,  76,  97, 121, 
+    101, 114,  79, 112,  97,  99, 
+    105, 116, 121,   0, 171, 171, 
+      0,   0,   3,   0,   1,   0, 
+      1,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0, 115,  50, 
+     68,   0,   4,   0,  12,   0, 
+      1,   0,   1,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+    112, 115,  95,  50,  95,  48, 
+      0,  77, 105,  99, 114, 111, 
+    115, 111, 102, 116,  32,  40, 
+     82,  41,  32,  72,  76,  83, 
+     76,  32,  83, 104,  97, 100, 
+    101, 114,  32,  67, 111, 109, 
+    112, 105, 108, 101, 114,  32, 
+     57,  46,  50,  55,  46,  57, 
+     53,  50,  46,  51,  48,  50, 
+     50,   0,  31,   0,   0,   2, 
+      0,   0,   0, 128,   0,   0, 
+      3, 176,  31,   0,   0,   2, 
+      0,   0,   0, 144,   0,   8, 
+     15, 160,  66,   0,   0,   3, 
+      0,   0,  15, 128,   0,   0, 
+    228, 176,   0,   8, 228, 160, 
+      5,   0,   0,   3,   0,   0, 
+     15, 128,   0,   0, 228, 128, 
+      0,   0,   0, 160,   1,   0, 
+      0,   2,   0,   8,  15, 128, 
+      0,   0, 228, 128, 255, 255, 
+      0,   0
+};
+
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
+//
+//   fxc LayerManagerD3D9Shaders.hlsl /EYCbCrShader /nologo /Tps_2_0
+//    /FhLayerManagerD3D9Shaders.h /VnYCbCrShaderPS
+//
+//
+// Parameters:
+//
+//   float fLayerOpacity;
+//   sampler2D s2DCb;
+//   sampler2D s2DCr;
+//   sampler2D s2DY;
+//
+//
+// Registers:
+//
+//   Name          Reg   Size
+//   ------------- ----- ----
+//   fLayerOpacity c0       1
+//   s2DY          s0       1
+//   s2DCb         s1       1
+//   s2DCr         s2       1
+//
+
+    ps_2_0
+    def c1, -0.5, -0.0625, 1.16400003, 1.59599996
+    def c2, 0.813000023, 0.391000003, 2.01799989, 1
+    dcl t0.xy
+    dcl_2d s0
+    dcl_2d s1
+    dcl_2d s2
+    texld r0, t0, s2
+    texld r1, t0, s0
+    texld r2, t0, s1
+    add r0.x, r0.x, c1.x
+    add r0.y, r1.x, c1.y
+    mul r0.y, r0.y, c1.z
+    mad r0.z, r0.x, -c2.x, r0.y
+    mad r1.x, r0.x, c1.w, r0.y
+    add r0.x, r2.x, c1.x
+    mad r1.y, r0.x, -c2.y, r0.z
+    mad r1.z, r0.x, c2.z, r0.y
+    mov r1.w, c2.w
+    mul r0, r1, c0.x
+    mov oC0, r0
+
+// approximately 14 instruction slots used (3 texture, 11 arithmetic)
+#endif
+
+const BYTE YCbCrShaderPS[] =
+{
+      0,   2, 255, 255, 254, 255, 
+     68,   0,  67,  84,  65,  66, 
+     28,   0,   0,   0, 219,   0, 
+      0,   0,   0,   2, 255, 255, 
+      4,   0,   0,   0,  28,   0, 
+      0,   0,   0,   1,   0,   0, 
+    212,   0,   0,   0, 108,   0, 
+      0,   0,   2,   0,   0,   0, 
+      1,   0,   0,   0, 124,   0, 
+      0,   0,   0,   0,   0,   0, 
+    140,   0,   0,   0,   3,   0, 
+      1,   0,   1,   0,   0,   0, 
+    148,   0,   0,   0,   0,   0, 
+      0,   0, 164,   0,   0,   0, 
+      3,   0,   2,   0,   1,   0, 
+      0,   0, 172,   0,   0,   0, 
+      0,   0,   0,   0, 188,   0, 
+      0,   0,   3,   0,   0,   0, 
+      1,   0,   0,   0, 196,   0, 
+      0,   0,   0,   0,   0,   0, 
+    102,  76,  97, 121, 101, 114, 
+     79, 112,  97,  99, 105, 116, 
+    121,   0, 171, 171,   0,   0, 
+      3,   0,   1,   0,   1,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0, 115,  50,  68,  67, 
+     98,   0, 171, 171,   4,   0, 
+     12,   0,   1,   0,   1,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0, 115,  50,  68,  67, 
+    114,   0, 171, 171,   4,   0, 
+     12,   0,   1,   0,   1,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0, 115,  50,  68,  89, 
+      0, 171, 171, 171,   4,   0, 
+     12,   0,   1,   0,   1,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0, 112, 115,  95,  50, 
+     95,  48,   0,  77, 105,  99, 
+    114, 111, 115, 111, 102, 116, 
+     32,  40,  82,  41,  32,  72, 
+     76,  83,  76,  32,  83, 104, 
+     97, 100, 101, 114,  32,  67, 
+    111, 109, 112, 105, 108, 101, 
+    114,  32,  57,  46,  50,  55, 
+     46,  57,  53,  50,  46,  51, 
+     48,  50,  50,   0,  81,   0, 
+      0,   5,   1,   0,  15, 160, 
+      0,   0,   0, 191,   0,   0, 
+    128, 189, 244, 253, 148,  63, 
+    186,  73, 204,  63,  81,   0, 
+      0,   5,   2,   0,  15, 160, 
+    197,  32,  80,  63,  39,  49, 
+    200,  62, 233,  38,   1,  64, 
+      0,   0, 128,  63,  31,   0, 
+      0,   2,   0,   0,   0, 128, 
+      0,   0,   3, 176,  31,   0, 
+      0,   2,   0,   0,   0, 144, 
+      0,   8,  15, 160,  31,   0, 
+      0,   2,   0,   0,   0, 144, 
+      1,   8,  15, 160,  31,   0, 
+      0,   2,   0,   0,   0, 144, 
+      2,   8,  15, 160,  66,   0, 
+      0,   3,   0,   0,  15, 128, 
+      0,   0, 228, 176,   2,   8, 
+    228, 160,  66,   0,   0,   3, 
+      1,   0,  15, 128,   0,   0, 
+    228, 176,   0,   8, 228, 160, 
+     66,   0,   0,   3,   2,   0, 
+     15, 128,   0,   0, 228, 176, 
+      1,   8, 228, 160,   2,   0, 
+      0,   3,   0,   0,   1, 128, 
+      0,   0,   0, 128,   1,   0, 
+      0, 160,   2,   0,   0,   3, 
+      0,   0,   2, 128,   1,   0, 
+      0, 128,   1,   0,  85, 160, 
+      5,   0,   0,   3,   0,   0, 
+      2, 128,   0,   0,  85, 128, 
+      1,   0, 170, 160,   4,   0, 
+      0,   4,   0,   0,   4, 128, 
+      0,   0,   0, 128,   2,   0, 
+      0, 161,   0,   0,  85, 128, 
+      4,   0,   0,   4,   1,   0, 
+      1, 128,   0,   0,   0, 128, 
+      1,   0, 255, 160,   0,   0, 
+     85, 128,   2,   0,   0,   3, 
+      0,   0,   1, 128,   2,   0, 
+      0, 128,   1,   0,   0, 160, 
+      4,   0,   0,   4,   1,   0, 
+      2, 128,   0,   0,   0, 128, 
+      2,   0,  85, 161,   0,   0, 
+    170, 128,   4,   0,   0,   4, 
+      1,   0,   4, 128,   0,   0, 
+      0, 128,   2,   0, 170, 160, 
+      0,   0,  85, 128,   1,   0, 
+      0,   2,   1,   0,   8, 128, 
+      2,   0, 255, 160,   5,   0, 
+      0,   3,   0,   0,  15, 128, 
+      1,   0, 228, 128,   0,   0, 
+      0, 160,   1,   0,   0,   2, 
+      0,   8,  15, 128,   0,   0, 
+    228, 128, 255, 255,   0,   0
+};
+
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
+//
+//   fxc LayerManagerD3D9Shaders.hlsl /ESolidColorShader /nologo /Tps_2_0
+//    /FhLayerManagerD3D9Shaders.h /VnSolidColorShaderPS
+//
+//
+// Parameters:
+//
+//   float4 fLayerColor;
+//
+//
+// Registers:
+//
+//   Name         Reg   Size
+//   ------------ ----- ----
+//   fLayerColor  c0       1
+//
+
+    ps_2_0
+    mov oC0, c0
+
+// approximately 1 instruction slot used
+#endif
+
+const BYTE SolidColorShaderPS[] =
+{
+      0,   2, 255, 255, 254, 255, 
+     34,   0,  67,  84,  65,  66, 
+     28,   0,   0,   0,  83,   0, 
+      0,   0,   0,   2, 255, 255, 
+      1,   0,   0,   0,  28,   0, 
+      0,   0,   0,   1,   0,   0, 
+     76,   0,   0,   0,  48,   0, 
+      0,   0,   2,   0,   0,   0, 
+      1,   0,   0,   0,  60,   0, 
+      0,   0,   0,   0,   0,   0, 
+    102,  76,  97, 121, 101, 114, 
+     67, 111, 108, 111, 114,   0, 
+      1,   0,   3,   0,   1,   0, 
+      4,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0, 112, 115, 
+     95,  50,  95,  48,   0,  77, 
+    105,  99, 114, 111, 115, 111, 
+    102, 116,  32,  40,  82,  41, 
+     32,  72,  76,  83,  76,  32, 
+     83, 104,  97, 100, 101, 114, 
+     32,  67, 111, 109, 112, 105, 
+    108, 101, 114,  32,  57,  46, 
+     50,  55,  46,  57,  53,  50, 
+     46,  51,  48,  50,  50,   0, 
+      1,   0,   0,   2,   0,   8, 
+     15, 128,   0,   0, 228, 160, 
+    255, 255,   0,   0
+};
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl
@@ -0,0 +1,61 @@
+float4x4 mLayerQuadTransform;
+float4x4 mLayerTransform;
+float4 vRenderTargetOffset;
+float4x4 mProjection;
+
+texture tex0;
+sampler s2D;
+sampler s2DY;
+sampler s2DCb;
+sampler s2DCr;
+
+float fLayerOpacity;
+float4 fLayerColor;
+
+struct VS_INPUT {
+  float4 vPosition : POSITION;
+};
+
+struct VS_OUTPUT {
+  float4 vPosition : POSITION;
+  float2 vTexCoords : TEXCOORD0;
+};
+
+VS_OUTPUT LayerQuadVS(const VS_INPUT aVertex)
+{
+  VS_OUTPUT outp;
+  outp.vPosition = aVertex.vPosition;
+  outp.vPosition = mul(mLayerQuadTransform, outp.vPosition);
+  outp.vPosition = mul(mLayerTransform, outp.vPosition);
+  outp.vPosition = outp.vPosition - vRenderTargetOffset;
+  outp.vPosition = mul(mProjection, outp.vPosition);
+  outp.vTexCoords = aVertex.vPosition.xy;
+  return outp;
+}
+
+float4 RGBShader(const VS_OUTPUT aVertex) : COLOR
+{
+  return tex2D(s2D, aVertex.vTexCoords) * fLayerOpacity;
+}
+
+float4 YCbCrShader(const VS_OUTPUT aVertex) : COLOR
+{
+  float4 yuv;
+  float4 color;
+
+  yuv.r = tex2D(s2DCr, aVertex.vTexCoords).r - 0.5;
+  yuv.g = tex2D(s2DY, aVertex.vTexCoords).r - 0.0625;
+  yuv.b = tex2D(s2DCb, aVertex.vTexCoords).r - 0.5;
+
+  color.r = yuv.g * 1.164 + yuv.r * 1.596;
+  color.g = yuv.g * 1.164 - 0.813 * yuv.r - 0.391 * yuv.b;
+  color.b = yuv.g * 1.164 + yuv.b * 2.018;
+  color.a = 1.0f;
+  
+  return color * fLayerOpacity;
+}
+
+float4 SolidColorShader(const VS_OUTPUT aVertex) : COLOR
+{
+  return fLayerColor;
+}
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp
@@ -0,0 +1,216 @@
+/* -*- 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) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@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 "ThebesLayerD3D9.h"
+#include "gfxPlatform.h"
+
+namespace mozilla {
+namespace layers {
+
+ThebesLayerD3D9::ThebesLayerD3D9(LayerManagerD3D9 *aManager)
+  : ThebesLayer(aManager, NULL)
+  , LayerD3D9(aManager)
+{
+  mImplData = static_cast<LayerD3D9*>(this);
+  aManager->mThebesLayers.AppendElement(this);
+}
+
+ThebesLayerD3D9::~ThebesLayerD3D9()
+{
+  mD3DManager->mThebesLayers.RemoveElement(this);
+}
+
+
+void
+ThebesLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion)
+{
+  if (aRegion.GetBounds() == mVisibleRect) {
+    return;
+  }
+  mVisibleRect = aRegion.GetBounds();
+
+  device()->CreateTexture(mVisibleRect.width, mVisibleRect.height, 1,
+			  D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
+			  D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
+
+  mInvalidatedRect = mVisibleRect;
+}
+
+
+void
+ThebesLayerD3D9::InvalidateRegion(const nsIntRegion &aRegion)
+{
+  nsIntRegion invalidatedRegion;
+  invalidatedRegion.Or(aRegion, mInvalidatedRect);
+  invalidatedRegion.And(invalidatedRegion, mVisibleRect);
+  mInvalidatedRect = invalidatedRegion.GetBounds();
+}
+
+LayerD3D9::LayerType
+ThebesLayerD3D9::GetType()
+{
+  return TYPE_THEBES;
+}
+
+const nsIntRect&
+ThebesLayerD3D9::GetVisibleRect()
+{
+  return mVisibleRect;
+}
+
+void
+ThebesLayerD3D9::RenderLayer()
+{
+  if (!mTexture) {
+    device()->CreateTexture(mVisibleRect.width, mVisibleRect.height, 1,
+			      D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
+			      D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
+    mInvalidatedRect = mVisibleRect;
+  }
+  if (!mInvalidatedRect.IsEmpty()) {
+    nsIntRegion region = mInvalidatedRect;
+
+    gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32;;
+    nsRefPtr<gfxASurface> destinationSurface;
+    nsRefPtr<gfxContext> context;
+
+    destinationSurface =
+      gfxPlatform::GetPlatform()->
+        CreateOffscreenSurface(gfxIntSize(mInvalidatedRect.width,
+                                          mInvalidatedRect.height),
+                               imageFormat);
+
+    context = new gfxContext(destinationSurface);
+    context->Translate(gfxPoint(-mInvalidatedRect.x, -mInvalidatedRect.y));
+    LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
+    cbInfo.Callback(this, context, region, cbInfo.CallbackData);
+    
+    nsRefPtr<IDirect3DTexture9> tmpTexture;
+    device()->CreateTexture(mInvalidatedRect.width, mInvalidatedRect.height, 1,
+			    0, D3DFMT_A8R8G8B8,
+			    D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), NULL);
+
+    D3DLOCKED_RECT r;
+    tmpTexture->LockRect(0, &r, NULL, 0);
+
+    nsRefPtr<gfxImageSurface> imgSurface =
+      new gfxImageSurface((unsigned char *)r.pBits,
+                          gfxIntSize(mInvalidatedRect.width,
+                                     mInvalidatedRect.height),
+                          r.Pitch,
+                          imageFormat);
+
+    context = new gfxContext(imgSurface);
+    context->SetSource(destinationSurface);
+    context->SetOperator(gfxContext::OPERATOR_SOURCE);
+    context->Paint();
+
+    imgSurface = NULL;
+
+    tmpTexture->UnlockRect(0);
+
+    nsRefPtr<IDirect3DSurface9> srcSurface;
+    nsRefPtr<IDirect3DSurface9> dstSurface;
+    
+    mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
+    tmpTexture->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
+    
+    POINT point;
+    point.x = mInvalidatedRect.x - mVisibleRect.x;
+    point.y = mInvalidatedRect.y - mVisibleRect.y;
+    device()->UpdateSurface(srcSurface, NULL, dstSurface, &point);
+  }
+  
+  float quadTransform[4][4];
+  /*
+   * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
+   * and size. To get pixel perfect mapping we offset the quad half a pixel
+   * to the top-left.
+   * 
+   * See: http://msdn.microsoft.com/en-us/library/bb219690%28VS.85%29.aspx
+   */
+  memset(&quadTransform, 0, sizeof(quadTransform));
+  quadTransform[0][0] = (float)GetVisibleRect().width;
+  quadTransform[1][1] = (float)GetVisibleRect().height;
+  quadTransform[2][2] = 1.0f;
+  quadTransform[3][0] = (float)GetVisibleRect().x - 0.5f;
+  quadTransform[3][1] = (float)GetVisibleRect().y - 0.5f;
+  quadTransform[3][3] = 1.0f;
+
+  device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
+  device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
+
+  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] = GetOpacity();
+  device()->SetPixelShaderConstantF(0, opacity, 1);
+
+  mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
+
+  device()->SetTexture(0, mTexture);
+  device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+}
+
+void
+ThebesLayerD3D9::CleanResources()
+{
+  mTexture = nsnull;
+}
+
+const nsIntRect&
+ThebesLayerD3D9::GetInvalidatedRect()
+{
+  return mInvalidatedRect;
+}
+
+Layer*
+ThebesLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+PRBool
+ThebesLayerD3D9::IsEmpty()
+{
+  return !mTexture;
+}
+
+} /* namespace layers */
+} /* namespace mozilla */
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.h
@@ -0,0 +1,92 @@
+/* -*- 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) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@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_THEBESLAYERD3D9_H
+#define GFX_THEBESLAYERD3D9_H
+
+#include "Layers.h"
+#include "LayerManagerD3D9.h"
+#include "gfxImageSurface.h"
+
+
+namespace mozilla {
+namespace layers {
+
+class ThebesLayerD3D9 : public ThebesLayer, 
+                        public LayerD3D9
+{
+public:
+  ThebesLayerD3D9(LayerManagerD3D9 *aManager);
+  virtual ~ThebesLayerD3D9();
+
+  /* Layer implementation */
+  void SetVisibleRegion(const nsIntRegion& aRegion);
+
+  /* ThebesLayer implementation */
+  void InvalidateRegion(const nsIntRegion& aRegion);
+
+  /* LayerD3D9 implementation */
+  LayerType GetType();
+  Layer* GetLayer();
+  virtual PRBool IsEmpty();
+  virtual void RenderLayer();
+  virtual void CleanResources();
+
+  /* ThebesLayerD3D9 */
+  const nsIntRect &GetVisibleRect();
+  const nsIntRect &GetInvalidatedRect();
+
+private:
+  /* 
+   * Visible rectangle, this is used to know the size and position of the quad
+   * when doing the rendering of this layer.
+   */
+  nsIntRect mVisibleRect;
+  /*
+   * Currently invalidated rectangular area.
+   */
+  nsIntRect mInvalidatedRect;
+
+  /*
+   * D3D9 texture
+   */
+  nsRefPtr<IDirect3DTexture9> mTexture;
+};
+
+} /* layers */
+} /* mozilla */
+#endif /* GFX_THEBESLAYERD3D9_H */