Merge last green changeset from mozilla-inbound to mozilla-central
authorMarco Bonardo <mbonardo@mozilla.com>
Mon, 04 Jul 2011 20:26:29 +0200
changeset 72289 ca5dd1bd60f3030d39d9b4946506a5bd13cf189c
parent 72278 7281d9de99eb9dc123043a20e3c40857bddcfeb7 (current diff)
parent 72288 c97d7a25a9219d6698f03e167101ff84f4ad3b3e (diff)
child 72290 320e5abc6f5aeb067b537f9b357c81dbd00d8751
push id20688
push usermak77@bonardo.net
push dateMon, 04 Jul 2011 18:26:59 +0000
treeherdermozilla-central@ca5dd1bd60f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone7.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge last green changeset from mozilla-inbound to mozilla-central
browser/themes/gnomestripe/browser/sync-24.png
browser/themes/pinstripe/browser/sync-24.png
browser/themes/winstripe/browser/sync-24.png
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -1417,17 +1417,17 @@ richlistitem[type~="action"][actiontype=
 .panel-promo-box {
   margin: 8px -10px -10px -10px;
   padding: 8px 10px;
   border-top: 1px solid ThreeDShadow;
   background-image: -moz-linear-gradient(hsla(0,0%,0%,.15), hsla(0,0%,0%,.08) 6px);
 }
 
 .panel-promo-icon {
-  list-style-image: url("chrome://browser/skin/sync-24.png");
+  list-style-image: url("chrome://browser/skin/sync-notification-24.png");
   -moz-margin-end: 10px;
   vertical-align: middle;
 }
 
 .panel-promo-closebutton {
   list-style-image: url("moz-icon://stock/gtk-close?size=menu");
   margin-top: 0;
   margin-bottom: 0;
--- a/browser/themes/gnomestripe/browser/jar.mn
+++ b/browser/themes/gnomestripe/browser/jar.mn
@@ -83,18 +83,18 @@ browser.jar:
   skin/classic/browser/tabview/new-tab.png            (tabview/new-tab.png)
   skin/classic/browser/tabview/search.png             (tabview/search.png)  
   skin/classic/browser/tabview/stack-expander.png     (tabview/stack-expander.png)
   skin/classic/browser/tabview/tabview.png            (tabview/tabview.png)
   skin/classic/browser/tabview/tabview.css            (tabview/tabview.css)
 #ifdef MOZ_SERVICES_SYNC
   skin/classic/browser/sync-16-throbber.png
   skin/classic/browser/sync-16.png
-  skin/classic/browser/sync-24.png
   skin/classic/browser/sync-24-throbber.png
   skin/classic/browser/sync-32.png
   skin/classic/browser/sync-bg.png
   skin/classic/browser/sync-desktopIcon.png
   skin/classic/browser/sync-mobileIcon.png
+  skin/classic/browser/sync-notification-24.png
   skin/classic/browser/syncSetup.css
   skin/classic/browser/syncCommon.css
   skin/classic/browser/syncQuota.css
 #endif
rename from browser/themes/gnomestripe/browser/sync-24.png
rename to browser/themes/gnomestripe/browser/sync-notification-24.png
--- a/browser/themes/pinstripe/browser/browser.css
+++ b/browser/themes/pinstripe/browser/browser.css
@@ -1407,24 +1407,25 @@ richlistitem[type~="action"][actiontype=
 .panel-promo-box {
   margin: 8px -16px -16px -16px;
   padding: 8px 16px;
   background-color: hsla(0,0%,7%,.3);
   border-top: 1px solid hsla(0,0%,100%,.1);
   border-bottom-left-radius: 6px;
   border-bottom-right-radius: 6px;
   box-shadow: 0 1px 1px hsla(0,0%,0%,.25) inset;
+  color: hsl(0,0%,60%);
 }
 
 .panel-promo-message > .text-link {
   color: hsl(210,100%,75%);
 }
 
 .panel-promo-icon {
-  list-style-image: url("chrome://browser/skin/sync-24.png");
+  list-style-image: url("chrome://browser/skin/sync-notification-24.png");
   -moz-margin-end: 10px;
   vertical-align: middle;
 }
 
 .panel-promo-closebutton {
   list-style-image: url("chrome://global/skin/notification/close.png");
   -moz-image-region: rect(0, 16px, 16px, 0);
   border: none;
--- a/browser/themes/pinstripe/browser/jar.mn
+++ b/browser/themes/pinstripe/browser/jar.mn
@@ -121,17 +121,17 @@ browser.jar:
   skin/classic/browser/tabview/new-tab.png                  (tabview/new-tab.png)
   skin/classic/browser/tabview/search.png                   (tabview/search.png)
   skin/classic/browser/tabview/stack-expander.png           (tabview/stack-expander.png)
   skin/classic/browser/tabview/tabview.png                  (tabview/tabview.png)
   skin/classic/browser/tabview/tabview.css                  (tabview/tabview.css)
 #ifdef MOZ_SERVICES_SYNC
   skin/classic/browser/sync-throbber.png
   skin/classic/browser/sync-16.png
-  skin/classic/browser/sync-24.png
   skin/classic/browser/sync-32.png
   skin/classic/browser/sync-bg.png
   skin/classic/browser/sync-desktopIcon.png
   skin/classic/browser/sync-mobileIcon.png
+  skin/classic/browser/sync-notification-24.png
   skin/classic/browser/syncSetup.css
   skin/classic/browser/syncCommon.css
   skin/classic/browser/syncQuota.css
 #endif
deleted file mode 100644
index d67eb47ac4a3563e87ef78f88d0dfdd63b007340..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..77f973f91f180f7a840d896f687539b516de65e1
GIT binary patch
literal 1146
zc$@)x1cm#FP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$97#k$RCwC7R!c}@R~XK{iAl^DV<xTb
z_-I52p@?Wkq#$lAK5!8gsT-##h>y(-f-4s;1UI@-K?~wy2DIqHt*<T|H;RmDouM+e
zOh-qecH$(C(PZ*YZofaABX@4op&Kv!-1BqJ`M>}BU-t@<B&lxm5pEqosjsZ8d{b9f
z_c$#rO%FYx*iRD#VIUL==^$#K&lg)=UG?|%^~L`$fEr?MYHG4AE-qFX3<f1V9RPlc
zL?Q_|kPbZ~8jTvx&(A&i`T1{CIHVF4y42m>tsfZ~DTi^|lTt`}JRT=@1dtA(jJ&+O
z2bY(Z_R-N%gVJfaB6M|iWsHxHKQft2bTGsWDjED73<h<2z5Wh#BZR-r0Ezea_dlJV
zpAV)2&>kKh{#aO8n2&WtW?W!Gx)uP7gM))YadGjz_V#v*PNyShG8j;n)9F01TCGp8
zj><zM&dki*FDNLmVom5V9#6mDubG&b5Z!LKnt>z`iVLuHRaRDdcXxL=0}7dlaM>0X
z7QW@SIe-?2zY|5#FEcJ}Y;1_7rKP6>0|T#GTU*})i~y)&t{{K!@9!TqG&H=yLpdSQ
zz(%0Fy!?BzDF-ls)>n)c8A#x=h-x}GK0ba9-LbW`^=of$uY=`=&iNqkyk76o^z`&Q
z$`5lanwy(TVK&?V<mBYsu~;l|=6$lJr>3Udfk5CDmPcd=@&={*0`F^HagZ>?y|lFS
z2h)=_GBYz(V3A3=BLJbStjx#~8{;8D!~IENU>?&&3ZIANNF@UaBoc`avb!Xa>gwt*
zZU7t(2akK4Nd%0%%tQY0{eLyn(9qC58T+K5BIzwAo5|zxL{Cmm_$C<*p#9A$`ap2G
zT-mbn7Ft?bjBRag)$Cpp<ofzLwzjrLj3wT!k<HCbo;(VH9~W~gDk{<y0D808{2246
zkh~in9yTIZ9ogB0dBZ^3-rn{xzy$ZiTw7aPxxT)BSFKhD*kS4H>@18@-R<n`{Ky>1
z4u`|Nh`A0Scv)0b^Z*?lW==_rnYN>&<2AbZ8P*pZfJ)3dJ3Cw2)6?^jp%WVk!%RST
zx?tE-Qc_~Vcz?+Dh+TkJ9W$<8US3w&?e<@={)>PG+0erXG8KWorK+lmQ{<JE9CR2H
zF#xnGlFyBc2L}f_G~Vy0r>DPB`BI2PS%vtnuCAQav2$~CD&{4p?_>2Zva?E&_V)HP
zxO)iWRNj}o+609c8a7w58XFt+larGn3^ktoI2hao13T-Dn+M_3)YQ~m?Ck82=T7+~
z7E)1VIng6z+UDkFslL8GYO~p*$ibHY_<@D)lMfX}hH-3cYz~9)Sl%nbXTEeIW5mNq
zxuEVWgM6(xA7q}tmWSta0ROd5%(B?zR4GPAh~?>%57n*zRs18s06uHp{s^~7t^fc4
M07*qoM6N<$g2~btIRF3v
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -1533,17 +1533,17 @@ richlistitem[type~="action"][actiontype=
 %ifndef WINSTRIPE_AERO
   border-bottom-left-radius: 6px;
   border-bottom-right-radius: 6px;
 %endif
   box-shadow: 0px 1px 2px rgb(204,214,234) inset;
 }
 
 .panel-promo-icon {
-  list-style-image: url("chrome://browser/skin/sync-24.png");
+  list-style-image: url("chrome://browser/skin/sync-notification-24.png");
   -moz-margin-end: 10px;
   vertical-align: middle;
 }
 
 .panel-promo-closebutton {
   -moz-appearance: none;
   list-style-image: url("chrome://global/skin/icons/close.png");
   -moz-image-region: rect(0, 16px, 16px, 0);
--- a/browser/themes/winstripe/browser/jar.mn
+++ b/browser/themes/winstripe/browser/jar.mn
@@ -100,21 +100,21 @@ browser.jar:
         skin/classic/browser/tabview/new-tab.png                    (tabview/new-tab.png)
         skin/classic/browser/tabview/search.png                     (tabview/search.png)
         skin/classic/browser/tabview/stack-expander.png             (tabview/stack-expander.png)
         skin/classic/browser/tabview/tabview.png                    (tabview/tabview.png)
         skin/classic/browser/tabview/tabview.css                    (tabview/tabview.css)
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/browser/sync-throbber.png
         skin/classic/browser/sync-16.png
-        skin/classic/browser/sync-24.png
         skin/classic/browser/sync-32.png
         skin/classic/browser/sync-bg.png
         skin/classic/browser/sync-desktopIcon.png
         skin/classic/browser/sync-mobileIcon.png
+        skin/classic/browser/sync-notification-24.png
         skin/classic/browser/syncSetup.css
         skin/classic/browser/syncCommon.css
         skin/classic/browser/syncQuota.css
 #endif
 
 #ifdef XP_WIN
 browser.jar:
 % skin browser classic/1.0 %skin/classic/aero/browser/ os=WINNT osversion>=6
@@ -216,18 +216,18 @@ browser.jar:
         skin/classic/aero/browser/tabview/new-tab.png                (tabview/new-tab.png)
         skin/classic/aero/browser/tabview/search.png                 (tabview/search.png)
         skin/classic/aero/browser/tabview/stack-expander.png         (tabview/stack-expander.png)
         skin/classic/aero/browser/tabview/tabview.png                (tabview/tabview.png)
         skin/classic/aero/browser/tabview/tabview.css                (tabview/tabview.css)
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/aero/browser/sync-throbber.png
         skin/classic/aero/browser/sync-16.png
-        skin/classic/aero/browser/sync-24.png
         skin/classic/aero/browser/sync-32.png
         skin/classic/aero/browser/sync-bg.png
         skin/classic/aero/browser/sync-desktopIcon.png
         skin/classic/aero/browser/sync-mobileIcon.png
+        skin/classic/aero/browser/sync-notification-24.png
         skin/classic/aero/browser/syncSetup.css
         skin/classic/aero/browser/syncCommon.css
         skin/classic/aero/browser/syncQuota.css
 #endif
 #endif
deleted file mode 100644
index d67eb47ac4a3563e87ef78f88d0dfdd63b007340..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fc9a4e63d2e6ad2078163ddd52498c360250b33e
GIT binary patch
literal 1119
zc$@)W1fctgP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv000CgNkl<Zc-pmA
zTS!xJ7|&U{)UxPe*$ulOM64bPx==4c&_gdlK^F+=DMBMDv#7k~HmAE^oX2_GTxL^C
z<Lo|lZf)kwh#-CH23bKyU=Q_Ruzp|7wVi1_`S9a^cK+Y@{l5Fzf@m~4ub6*=i#1#l
zlx$z2#@zqGcrO@bY@ukgEgXl=>W@N3Al7qBB}T`pS{;{Ht>My1Zw{moqyZTcqjwM6
zJ^a=BXmmOeAeqL!P{sPzm^z0F;lxo@tM3#DcaiS@34l7rm#4E1+RP6l-(fTfi0B7o
zvNe{0O>MnTMZhu0oi}y_OJt1eOqJFy{3n5|*_(|t1mXQRC{Mv?5<u_`aybf<X9prU
zVCi{!0`D(E_DXYSxT2nM7vEOdGv*=?s9XD0Fg^*T&ohAXXY<36NjjPPp)W*Gt##y!
z8=brLcL$3ge;s#KfP}Gy)pbT^5v41Ipuyx7!N7Y6zK7x8XX}H=L{rD(*DAAL-qaBq
zZ@d@$L<B$vo!8~|O$w9uQcKs68uD61)MRK6Sj7hCRz871!S;#a%^MhhMWAQoy6dLW
zCBprh8lC$viaUnq#Uu|b1hOtm?Q2!$emR`6K(DQ(>q&=<ahH%xBEcfPbua)A#vt?(
zDH+3WSE<y#4tGlcA&@I>bnnNRnUL0WBDrI59z_j$q1$EY8R^zq2CQT=PEam)E<q=}
zfWRmL1$-_sdX7`a#5_rhc?{zzeZTOk%#jCuFLXHqQt7*)aOB1bYILp*$n^*=Lj=?!
zQZ9GolkzNck}^AG^^RrG4?x#PpyyhHdmG)y1u!(hxWN6#1GiMp)w3H+C8%q1A3%zR
zXB;GFt97o8bT=cEg@W3UKMJwO)ERyxHM$PXMj$tNHzfYPV{m8d+Wg%ZxM!4Jbkj3^
zdmv2dO(YP)i!11WP6$~cY|)qpq&Jn0OddhHlJ)u<OrF9&Q}4-voE9B7PR&7ReK0((
zV0~KZwxlkq)Hp?r?Ewoq$p|krAk!#WUoj%dO(4j`aE+m$qgso<1jQVsc82`#)}|BF
z{uT{#m}Vtu4uBjOyMXj4X)1vlw);sH43^h3uDzJhm6S^4_ajm{fhZ^Fq@kPv$R<>5
zpBZvXDO&!jSX3(IRyQ<zu7acj1lOQc3M0jc<|I;ckO*j9&<f!LgEomJ8M&c!ZH~2b
zTFNd0gk>^r9U?i4t}2Dn1rQa%z!AOGFQO=E;qjLs26IYxHxQ}Rx_6QjWGiV^@JWDW
z6>9q~WsC0|QgRxp+J}!&0d)qgZ2lTYVW(;h-b3U7e-LNw>)4oQUzTtyE7ja~L{xx}
z$_l)rmi)=!!}AxRX%zjZ+T8!H!PK{f^!WsHkqC$=hV<AwA+QQq&qF@29LV@D0UtaC
lL9BpTJS?7LPtE_oieL0<67uvK6N3N%002ovPDHLkV1jN80&f5S
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -97,16 +97,17 @@ EXPORTS += \
 
 CPPSRCS += \
         LayerManagerD3D9.cpp \
         ThebesLayerD3D9.cpp \
         ContainerLayerD3D9.cpp \
         ImageLayerD3D9.cpp \
         ColorLayerD3D9.cpp \
         CanvasLayerD3D9.cpp \
+        ShadowBufferD3D9.cpp \
         DeviceManagerD3D9.cpp \
         Nv3DVUtils.cpp \
         $(NULL)
 endif
 ifdef MOZ_ENABLE_D3D10_LAYER
 EXPORTS += \
         LayerManagerD3D10.h \
         ReadbackManagerD3D10.h \
--- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp
@@ -31,22 +31,27 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include "CanvasLayerD3D9.h"
+
+#include "mozilla/layers/PLayers.h"
+#include "mozilla/layers/ShadowLayers.h"
+#include "ShadowBufferD3D9.h"
 
 #include "gfxImageSurface.h"
 #include "gfxWindowsSurface.h"
 #include "gfxWindowsPlatform.h"
 
+#include "CanvasLayerD3D9.h"
+
 namespace mozilla {
 namespace layers {
 
 CanvasLayerD3D9::~CanvasLayerD3D9()
 {
   if (mD3DManager) {
     mD3DManager->deviceManager()->mLayersWithResources.RemoveElement(this);
   }
@@ -88,24 +93,24 @@ CanvasLayerD3D9::UpdateSurface()
   if (!mTexture) {
     CreateTexture();
     NS_WARNING("CanvasLayerD3D9::Updated called but no texture present!");
     return;
   }
 
   if (mGLContext) {
     // WebGL reads entire surface.
-    D3DLOCKED_RECT r;
-    HRESULT hr = mTexture->LockRect(0, &r, NULL, 0);
-
-    if (FAILED(hr)) {
+    LockTextureRectD3D9 textureLock(mTexture);
+    if (!textureLock.HasLock()) {
       NS_WARNING("Failed to lock CanvasLayer texture.");
       return;
     }
 
+    D3DLOCKED_RECT r = textureLock.GetLockRect();
+
     PRUint8 *destination;
     if (r.Pitch != mBounds.width * 4) {
       destination = new PRUint8[mBounds.width * mBounds.height * 4];
     } else {
       destination = (PRUint8*)r.pBits;
     }
 
     // We have to flush to ensure that any buffered GL operations are
@@ -138,42 +143,40 @@ CanvasLayerD3D9::UpdateSurface()
     if (r.Pitch != mBounds.width * 4) {
       for (int y = 0; y < mBounds.height; y++) {
         memcpy((PRUint8*)r.pBits + r.Pitch * y,
                destination + mBounds.width * 4 * y,
                mBounds.width * 4);
       }
       delete [] destination;
     }
-    mTexture->UnlockRect(0);
   } else if (mSurface) {
     RECT r;
     r.left = mBounds.x;
     r.top = mBounds.y;
     r.right = mBounds.XMost();
     r.bottom = mBounds.YMost();
 
-    D3DLOCKED_RECT lockedRect;
-    HRESULT hr = mTexture->LockRect(0, &lockedRect, &r, 0);
-
-    if (FAILED(hr)) {
+    LockTextureRectD3D9 textureLock(mTexture);
+    if (!textureLock.HasLock()) {
       NS_WARNING("Failed to lock CanvasLayer texture.");
       return;
     }
 
+    D3DLOCKED_RECT lockedRect = textureLock.GetLockRect();
+
     nsRefPtr<gfxImageSurface> sourceSurface;
 
     if (mSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
       sourceSurface = mSurface->GetAsImageSurface();
     } else if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) {
       sourceSurface = static_cast<gfxImageSurface*>(mSurface.get());
       if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32 &&
           sourceSurface->Format() != gfxASurface::ImageFormatRGB24)
       {
-        mTexture->UnlockRect(0);
         return;
       }
     } else {
       sourceSurface = new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height),
                                           gfxASurface::ImageFormatARGB32);
       nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface);
       ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
       ctx->SetSource(mSurface);
@@ -190,17 +193,16 @@ CanvasLayerD3D9::UpdateSurface()
     }
 
     for (int y = 0; y < mBounds.height; y++) {
       memcpy((PRUint8*)lockedRect.pBits + lockedRect.Pitch * y,
              startBits + sourceStride * y,
              mBounds.width * 4);
     }
 
-    mTexture->UnlockRect(0);
   }
 }
 
 Layer*
 CanvasLayerD3D9::GetLayer()
 {
   return this;
 }
@@ -282,10 +284,104 @@ CanvasLayerD3D9::CreateTexture()
     // D3DPOOL_MANAGED is fine here since we require Dynamic Textures for D3D9Ex
     // devices.
     device()->CreateTexture(mBounds.width, mBounds.height, 1, 0,
                             D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
                             getter_AddRefs(mTexture), NULL);
   }
 }
 
+ShadowCanvasLayerD3D9::ShadowCanvasLayerD3D9(LayerManagerD3D9* aManager)
+  : ShadowCanvasLayer(aManager, nsnull)
+  , LayerD3D9(aManager)
+  , mNeedsYFlip(PR_FALSE)
+{
+  mImplData = static_cast<LayerD3D9*>(this);
+}
+ 
+ShadowCanvasLayerD3D9::~ShadowCanvasLayerD3D9()
+{}
+
+void
+ShadowCanvasLayerD3D9::Initialize(const Data& aData)
+{
+  NS_RUNTIMEABORT("Non-shadow layer API unexpectedly used for shadow layer");
+}
+
+void
+ShadowCanvasLayerD3D9::Init(const SurfaceDescriptor& aNewFront, 
+                            const nsIntSize& aSize, bool needYFlip)
+{
+
+  if (!mBuffer) {
+    mBuffer = new ShadowBufferD3D9(this);
+  }
+
+  mNeedsYFlip = needYFlip;
+}
+
+void
+ShadowCanvasLayerD3D9::Swap(const SurfaceDescriptor& aNewFront,
+                           SurfaceDescriptor* aNewBack)
+{
+  NS_ASSERTION(aNewFront.type() == SharedImage::TSurfaceDescriptor, 
+    "ShadowCanvasLayerD3D9::Swap expected SharedImage surface");
+
+  nsRefPtr<gfxASurface> surf = 
+    ShadowLayerForwarder::OpenDescriptor(aNewFront);
+   
+  if (mBuffer) {
+    mBuffer->Upload(surf, GetVisibleRegion().GetBounds());
+  }
+
+  *aNewBack = aNewFront;
+}
+
+void
+ShadowCanvasLayerD3D9::DestroyFrontBuffer()
+{
+  Destroy();
+}
+
+void
+ShadowCanvasLayerD3D9::Disconnect()
+{
+  Destroy();
+}
+
+void
+ShadowCanvasLayerD3D9::Destroy()
+{
+  mBuffer = nsnull;
+}
+
+void
+ShadowCanvasLayerD3D9::CleanResources()
+{
+  Destroy();
+}
+
+void
+ShadowCanvasLayerD3D9::LayerManagerDestroyed()
+{
+  mD3DManager->deviceManager()->mLayersWithResources.RemoveElement(this);
+  mD3DManager = nsnull;
+}
+
+Layer*
+ShadowCanvasLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+void
+ShadowCanvasLayerD3D9::RenderLayer()
+{
+  if (!mBuffer) {
+    return;
+  }
+
+  mBuffer->RenderTo(mD3DManager, GetEffectiveVisibleRegion());
+}
+
+
 } /* namespace layers */
 } /* namespace mozilla */
--- a/gfx/layers/d3d9/CanvasLayerD3D9.h
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.h
@@ -34,23 +34,25 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef GFX_CANVASLAYERD3D9_H
 #define GFX_CANVASLAYERD3D9_H
 
-#include "LayerManagerD3D9.h"
-#include "GLContext.h"
-#include "gfxASurface.h"
+#include "LayerManagerD3D9.h"
+#include "GLContext.h"
+#include "gfxASurface.h"
 
 namespace mozilla {
 namespace layers {
 
+class ShadowBufferD3D9;
+
 class THEBES_API CanvasLayerD3D9 :
   public CanvasLayer,
   public LayerD3D9
 {
 public:
   CanvasLayerD3D9(LayerManagerD3D9 *aManager)
     : CanvasLayer(aManager, NULL)
     , LayerD3D9(aManager)
@@ -86,11 +88,47 @@ protected:
 
   PRUint32 mCanvasFramebuffer;
 
   PRPackedBool mDataIsPremultiplied;
   PRPackedBool mNeedsYFlip;
   PRPackedBool mHasAlpha;
 };
 
+// NB: eventually we'll have separate shadow canvas2d and shadow
+// canvas3d layers, but currently they look the same from the
+// perspective of the compositor process
+class ShadowCanvasLayerD3D9 : public ShadowCanvasLayer,
+                             public LayerD3D9
+{
+public:
+  ShadowCanvasLayerD3D9(LayerManagerD3D9* aManager);
+  virtual ~ShadowCanvasLayerD3D9();
+
+  // CanvasLayer impl
+  virtual void Initialize(const Data& aData);
+  virtual void Init(const SurfaceDescriptor& aNewFront, const nsIntSize& aSize, bool needYFlip);
+
+  // This isn't meaningful for shadow canvas.
+  virtual void Updated(const nsIntRect&) {}
+
+  // ShadowCanvasLayer impl
+  virtual void Swap(const SurfaceDescriptor& aNewFront,
+                    SurfaceDescriptor* aNewBack);
+  virtual void DestroyFrontBuffer();
+  virtual void Disconnect();
+
+  virtual void Destroy();
+
+  // LayerD3D9 implementation
+  virtual Layer* GetLayer();
+  virtual void RenderLayer();
+  virtual void CleanResources();
+  virtual void LayerManagerDestroyed();
+
+private:
+  PRPackedBool mNeedsYFlip;
+  nsRefPtr<ShadowBufferD3D9> mBuffer;
+};
+
 } /* layers */
 } /* mozilla */
 #endif /* GFX_CANVASLAYERD3D9_H */
--- a/gfx/layers/d3d9/ColorLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ColorLayerD3D9.cpp
@@ -42,45 +42,58 @@ namespace mozilla {
 namespace layers {
 
 Layer*
 ColorLayerD3D9::GetLayer()
 {
   return this;
 }
 
-void
-ColorLayerD3D9::RenderLayer()
+static void
+RenderColorLayerD3D9(ColorLayer* aLayer, LayerManagerD3D9 *aManager)
 {
   // XXX we might be able to improve performance by using
   // IDirect3DDevice9::Clear
 
-  nsIntRect visibleRect = mVisibleRegion.GetBounds();
+  nsIntRect visibleRect = aLayer->GetEffectiveVisibleRegion().GetBounds();
 
-  device()->SetVertexShaderConstantF(
+  aManager->device()->SetVertexShaderConstantF(
     CBvLayerQuad,
     ShaderConstantRect(visibleRect.x,
                        visibleRect.y,
                        visibleRect.width,
                        visibleRect.height),
     1);
 
-  const gfx3DMatrix& transform = GetEffectiveTransform();
-  device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4);
+  const gfx3DMatrix& transform = aLayer->GetEffectiveTransform();
+  aManager->device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4);
 
+  gfxRGBA layerColor(aLayer->GetColor());
   float color[4];
-  float opacity = GetEffectiveOpacity() * mColor.a;
+  float opacity = aLayer->GetEffectiveOpacity() * layerColor.a;
   // output color is premultiplied, so we need to adjust all channels.
   // mColor is not premultiplied.
-  color[0] = (float)(mColor.r * opacity);
-  color[1] = (float)(mColor.g * opacity);
-  color[2] = (float)(mColor.b * opacity);
+  color[0] = (float)(layerColor.r * opacity);
+  color[1] = (float)(layerColor.g * opacity);
+  color[2] = (float)(layerColor.b * opacity);
   color[3] = (float)(opacity);
 
-  device()->SetPixelShaderConstantF(0, color, 1);
+  aManager->device()->SetPixelShaderConstantF(0, color, 1);
+
+  aManager->SetShaderMode(DeviceManagerD3D9::SOLIDCOLORLAYER);
+
+  aManager->device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+}
 
-  mD3DManager->SetShaderMode(DeviceManagerD3D9::SOLIDCOLORLAYER);
+void
+ColorLayerD3D9::RenderLayer()
+{
+  return RenderColorLayerD3D9(this, mD3DManager);
+}
 
-  device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+void
+ShadowColorLayerD3D9::RenderLayer()
+{
+  return RenderColorLayerD3D9(this, mD3DManager);
 }
 
 } /* layers */
 } /* mozilla */
--- a/gfx/layers/d3d9/ColorLayerD3D9.h
+++ b/gfx/layers/d3d9/ColorLayerD3D9.h
@@ -56,12 +56,32 @@ public:
   }
 
   // LayerD3D9 Implementation
   virtual Layer* GetLayer();
 
   virtual void RenderLayer();
 };
 
+class ShadowColorLayerD3D9 : public ShadowColorLayer,
+                            public LayerD3D9
+{
+public:
+  ShadowColorLayerD3D9(LayerManagerD3D9 *aManager)
+    : ShadowColorLayer(aManager, NULL)
+    , LayerD3D9(aManager)
+  { 
+    mImplData = static_cast<LayerD3D9*>(this);
+  }
+  ~ShadowColorLayerD3D9() { Destroy(); }
+
+  // LayerOGL Implementation
+  virtual Layer* GetLayer() { return this; }
+
+  virtual void Destroy() { }
+
+  virtual void RenderLayer();
+};
+
 } /* layers */
 } /* mozilla */
 
 #endif /* GFX_COLORLAYERD3D9_H */
--- a/gfx/layers/d3d9/ContainerLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ContainerLayerD3D9.cpp
@@ -39,231 +39,223 @@
 #include "gfxUtils.h"
 #include "nsRect.h"
 #include "ThebesLayerD3D9.h"
 #include "ReadbackProcessor.h"
 
 namespace mozilla {
 namespace layers {
 
-ContainerLayerD3D9::ContainerLayerD3D9(LayerManagerD3D9 *aManager)
-  : ContainerLayer(aManager, NULL)
-  , LayerD3D9(aManager)
-{
-  mImplData = static_cast<LayerD3D9*>(this);
-}
-
-ContainerLayerD3D9::~ContainerLayerD3D9()
+template<class Container>
+static void
+ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter)
 {
-  while (mFirstChild) {
-    RemoveChild(mFirstChild);
-  }
-}
-
-void
-ContainerLayerD3D9::InsertAfter(Layer* aChild, Layer* aAfter)
-{
-  aChild->SetParent(this);
+  aChild->SetParent(aContainer);
   if (!aAfter) {
-    Layer *oldFirstChild = GetFirstChild();
-    mFirstChild = aChild;
+    Layer *oldFirstChild = aContainer->GetFirstChild();
+    aContainer->mFirstChild = aChild;
     aChild->SetNextSibling(oldFirstChild);
     aChild->SetPrevSibling(nsnull);
     if (oldFirstChild) {
       oldFirstChild->SetPrevSibling(aChild);
     } else {
-      mLastChild = aChild;
+      aContainer->mLastChild = aChild;
     }
     NS_ADDREF(aChild);
-    DidInsertChild(aChild);
+    aContainer->DidInsertChild(aChild);
     return;
   }
-  for (Layer *child = GetFirstChild();
+  for (Layer *child = aContainer->GetFirstChild(); 
        child; child = child->GetNextSibling()) {
     if (aAfter == child) {
       Layer *oldNextSibling = child->GetNextSibling();
       child->SetNextSibling(aChild);
       aChild->SetNextSibling(oldNextSibling);
       if (oldNextSibling) {
         oldNextSibling->SetPrevSibling(aChild);
       } else {
-        mLastChild = aChild;
+        aContainer->mLastChild = aChild;
       }
       aChild->SetPrevSibling(child);
       NS_ADDREF(aChild);
-      DidInsertChild(aChild);
+      aContainer->DidInsertChild(aChild);
       return;
     }
   }
   NS_WARNING("Failed to find aAfter layer!");
 }
 
-void
-ContainerLayerD3D9::RemoveChild(Layer *aChild)
+template<class Container>
+static void
+ContainerRemoveChild(Container* aContainer, Layer* aChild)
 {
-  if (GetFirstChild() == aChild) {
-    mFirstChild = GetFirstChild()->GetNextSibling();
-    if (mFirstChild) {
-      mFirstChild->SetPrevSibling(nsnull);
+  if (aContainer->GetFirstChild() == aChild) {
+    aContainer->mFirstChild = aContainer->GetFirstChild()->GetNextSibling();
+    if (aContainer->mFirstChild) {
+      aContainer->mFirstChild->SetPrevSibling(nsnull);
     } else {
-      mLastChild = nsnull;
+      aContainer->mLastChild = nsnull;
     }
     aChild->SetNextSibling(nsnull);
     aChild->SetPrevSibling(nsnull);
     aChild->SetParent(nsnull);
-    DidRemoveChild(aChild);
+    aContainer->DidRemoveChild(aChild);
     NS_RELEASE(aChild);
     return;
   }
   Layer *lastChild = nsnull;
-  for (Layer *child = GetFirstChild(); child;
+  for (Layer *child = aContainer->GetFirstChild(); child; 
        child = child->GetNextSibling()) {
     if (child == aChild) {
       // We're sure this is not our first child. So lastChild != NULL.
       lastChild->SetNextSibling(child->GetNextSibling());
       if (child->GetNextSibling()) {
         child->GetNextSibling()->SetPrevSibling(lastChild);
       } else {
-        mLastChild = lastChild;
+        aContainer->mLastChild = lastChild;
       }
       child->SetNextSibling(nsnull);
       child->SetPrevSibling(nsnull);
       child->SetParent(nsnull);
-      DidRemoveChild(aChild);
+      aContainer->DidRemoveChild(aChild);
       NS_RELEASE(aChild);
       return;
     }
     lastChild = child;
   }
 }
 
-Layer*
-ContainerLayerD3D9::GetLayer()
-{
-  return this;
-}
-
-LayerD3D9*
-ContainerLayerD3D9::GetFirstChildD3D9()
-{
-  if (!mFirstChild) {
-    return nsnull;
-  }
-  return static_cast<LayerD3D9*>(mFirstChild->ImplData());
-}
-
 static inline LayerD3D9*
-GetNextSiblingD3D9(LayerD3D9* aLayer)
+GetNextSibling(LayerD3D9* aLayer)
 {
    Layer* layer = aLayer->GetLayer()->GetNextSibling();
    return layer ? static_cast<LayerD3D9*>(layer->
-                                          ImplData())
+                                         ImplData())
                  : nsnull;
 }
 
 static PRBool
 HasOpaqueAncestorLayer(Layer* aLayer)
 {
   for (Layer* l = aLayer->GetParent(); l; l = l->GetParent()) {
     if (l->GetContentFlags() & Layer::CONTENT_OPAQUE)
       return PR_TRUE;
   }
   return PR_FALSE;
 }
 
-void
-ContainerLayerD3D9::RenderLayer()
+static inline LayerD3D9*
+GetNextSiblingD3D9(LayerD3D9* aLayer)
+{
+   Layer* layer = aLayer->GetLayer()->GetNextSibling();
+   return layer ? static_cast<LayerD3D9*>(layer->
+                                          ImplData())
+                 : nsnull;
+}
+
+template<class Container>
+static void
+ContainerRender(Container* aContainer,
+                LayerManagerD3D9* aManager)
 {
   nsRefPtr<IDirect3DSurface9> previousRenderTarget;
   nsRefPtr<IDirect3DTexture9> renderTexture;
   float previousRenderTargetOffset[4];
   float renderTargetOffset[] = { 0, 0, 0, 0 };
   float oldViewMatrix[4][4];
 
   RECT containerD3D9ClipRect; 
-  device()->GetScissorRect(&containerD3D9ClipRect);
+  aManager->device()->GetScissorRect(&containerD3D9ClipRect);
   // Convert scissor to an nsIntRect. RECT's are exclusive on the bottom and
   // right values.
   nsIntRect oldScissor(containerD3D9ClipRect.left, 
                        containerD3D9ClipRect.top,
                        containerD3D9ClipRect.right - containerD3D9ClipRect.left,
                        containerD3D9ClipRect.bottom - containerD3D9ClipRect.top);
 
   ReadbackProcessor readback;
-  readback.BuildUpdates(this);
+  readback.BuildUpdates(aContainer);
 
-  nsIntRect visibleRect = mVisibleRegion.GetBounds();
-  PRBool useIntermediate = UseIntermediateSurface();
+  nsIntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds();
+  PRBool useIntermediate = aContainer->UseIntermediateSurface();
 
-  mSupportsComponentAlphaChildren = PR_FALSE;
+  aContainer->mSupportsComponentAlphaChildren = PR_FALSE;
   if (useIntermediate) {
-    device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget));
-    device()->CreateTexture(visibleRect.width, visibleRect.height, 1,
+    aManager->device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget));
+    aManager->device()->CreateTexture(visibleRect.width, visibleRect.height, 1,
                             D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
                             D3DPOOL_DEFAULT, getter_AddRefs(renderTexture),
                             NULL);
     nsRefPtr<IDirect3DSurface9> renderSurface;
     renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface));
-    device()->SetRenderTarget(0, renderSurface);
+    aManager->device()->SetRenderTarget(0, renderSurface);
 
-    if (mVisibleRegion.GetNumRects() == 1 && (GetContentFlags() & CONTENT_OPAQUE)) {
+    if (aContainer->mVisibleRegion.GetNumRects() == 1 && 
+        (aContainer->GetContentFlags() & aContainer->CONTENT_OPAQUE)) {
       // don't need a background, we're going to paint all opaque stuff
-      mSupportsComponentAlphaChildren = PR_TRUE;
+      aContainer->mSupportsComponentAlphaChildren = PR_TRUE;
     } else {
-      const gfx3DMatrix& transform3D = GetEffectiveTransform();
+      const gfx3DMatrix& transform3D = aContainer->GetEffectiveTransform();
       gfxMatrix transform;
       // If we have an opaque ancestor layer, then we can be sure that
       // all the pixels we draw into are either opaque already or will be
       // covered by something opaque. Otherwise copying up the background is
       // not safe.
       HRESULT hr = E_FAIL;
-      if (HasOpaqueAncestorLayer(this) &&
+      if (HasOpaqueAncestorLayer(aContainer) &&
           transform3D.Is2D(&transform) && !transform.HasNonIntegerTranslation()) {
         // Copy background up from below
         RECT dest = { 0, 0, visibleRect.width, visibleRect.height };
         RECT src = dest;
         ::OffsetRect(&src,
                      visibleRect.x + PRInt32(transform.x0),
                      visibleRect.y + PRInt32(transform.y0));
-        hr = device()->
+        hr = aManager->device()->
           StretchRect(previousRenderTarget, &src, renderSurface, &dest, D3DTEXF_NONE);
       }
       if (hr == S_OK) {
-        mSupportsComponentAlphaChildren = PR_TRUE;
+        aContainer->mSupportsComponentAlphaChildren = PR_TRUE;
       } else {
-        device()->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0);
+        aManager->device()->
+          Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0);
       }
     }
 
-    device()->GetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1);
+    aManager->device()->
+      GetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1);
     renderTargetOffset[0] = (float)visibleRect.x;
     renderTargetOffset[1] = (float)visibleRect.y;
-    device()->SetVertexShaderConstantF(CBvRenderTargetOffset, renderTargetOffset, 1);
+    aManager->device()->
+      SetVertexShaderConstantF(CBvRenderTargetOffset, renderTargetOffset, 1);
 
     gfx3DMatrix viewMatrix;
     /*
      * Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
      * <1.0, -1.0> bottomright)
      */
     viewMatrix._11 = 2.0f / visibleRect.width;
     viewMatrix._22 = -2.0f / visibleRect.height;
     viewMatrix._41 = -1.0f;
     viewMatrix._42 = 1.0f;
 
-    device()->GetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4);
-    device()->SetVertexShaderConstantF(CBmProjection, &viewMatrix._11, 4);
+    aManager->device()->
+      GetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4);
+    aManager->device()->
+      SetVertexShaderConstantF(CBmProjection, &viewMatrix._11, 4);
   } else {
-    mSupportsComponentAlphaChildren = (GetContentFlags() & CONTENT_OPAQUE) ||
-        (mParent && mParent->SupportsComponentAlphaChildren());
+    aContainer->mSupportsComponentAlphaChildren = 
+        (aContainer->GetContentFlags() & aContainer->CONTENT_OPAQUE) ||
+        (aContainer->mParent && 
+         aContainer->mParent->SupportsComponentAlphaChildren());
   }
 
   /*
    * Render this container's contents.
    */
-  for (LayerD3D9* layerToRender = GetFirstChildD3D9();
+  for (LayerD3D9* layerToRender = aContainer->GetFirstChildD3D9();
        layerToRender != nsnull;
        layerToRender = GetNextSiblingD3D9(layerToRender)) {
 
     if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) {
       continue;
     }
     
     nsIntRect scissorRect =
@@ -272,51 +264,146 @@ ContainerLayerD3D9::RenderLayer()
       continue;
     }
 
     RECT d3drect;
     d3drect.left = scissorRect.x;
     d3drect.top = scissorRect.y;
     d3drect.right = scissorRect.x + scissorRect.width;
     d3drect.bottom = scissorRect.y + scissorRect.height;
-    device()->SetScissorRect(&d3drect);
+    aManager->device()->SetScissorRect(&d3drect);
 
-    if (layerToRender->GetLayer()->GetType() == TYPE_THEBES) {
+    if (layerToRender->GetLayer()->GetType() == aContainer->TYPE_THEBES) {
       static_cast<ThebesLayerD3D9*>(layerToRender)->RenderThebesLayer(&readback);
     } else {
       layerToRender->RenderLayer();
     }
   }
     
-  device()->SetScissorRect(&containerD3D9ClipRect);
+  aManager->device()->SetScissorRect(&containerD3D9ClipRect);
 
   if (useIntermediate) {
-    device()->SetRenderTarget(0, previousRenderTarget);
-    device()->SetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1);
-    device()->SetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4);
+    aManager->device()->SetRenderTarget(0, previousRenderTarget);
+    aManager->device()->SetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1);
+    aManager->device()->SetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4);
 
-    device()->SetVertexShaderConstantF(CBvLayerQuad,
+    aManager->device()->SetVertexShaderConstantF(CBvLayerQuad,
                                        ShaderConstantRect(visibleRect.x,
                                                           visibleRect.y,
                                                           visibleRect.width,
                                                           visibleRect.height),
                                        1);
 
-    SetShaderTransformAndOpacity();
+    aContainer->SetShaderTransformAndOpacity();
+
+    aManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER);
+
+    aManager->device()->SetTexture(0, renderTexture);
+    aManager->device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+  }
+}
+
 
-    mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER);
+ContainerLayerD3D9::ContainerLayerD3D9(LayerManagerD3D9 *aManager)
+  : ContainerLayer(aManager, NULL)
+  , LayerD3D9(aManager)
+{
+  mImplData = static_cast<LayerD3D9*>(this);
+}
+
+ContainerLayerD3D9::~ContainerLayerD3D9()
+{
+  while (mFirstChild) {
+    RemoveChild(mFirstChild);
+  }
+}
 
-    device()->SetTexture(0, renderTexture);
-    device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+void
+ContainerLayerD3D9::InsertAfter(Layer* aChild, Layer* aAfter)
+{
+  ContainerInsertAfter(this, aChild, aAfter);
+}
+
+void
+ContainerLayerD3D9::RemoveChild(Layer *aChild)
+{
+  ContainerRemoveChild(this, aChild);
+}
+
+Layer*
+ContainerLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+LayerD3D9*
+ContainerLayerD3D9::GetFirstChildD3D9()
+{
+  if (!mFirstChild) {
+    return nsnull;
   }
+  return static_cast<LayerD3D9*>(mFirstChild->ImplData());
+}
+
+void
+ContainerLayerD3D9::RenderLayer()
+{
+  ContainerRender(this, mD3DManager);
 }
 
 void
 ContainerLayerD3D9::LayerManagerDestroyed()
 {
   while (mFirstChild) {
     GetFirstChildD3D9()->LayerManagerDestroyed();
     RemoveChild(mFirstChild);
   }
 }
 
+ShadowContainerLayerD3D9::ShadowContainerLayerD3D9(LayerManagerD3D9 *aManager)
+  : ShadowContainerLayer(aManager, NULL)
+  , LayerD3D9(aManager)
+{
+  mImplData = static_cast<LayerD3D9*>(this);
+}
+ 
+ShadowContainerLayerD3D9::~ShadowContainerLayerD3D9()
+{
+  Destroy();
+}
+
+void
+ShadowContainerLayerD3D9::InsertAfter(Layer* aChild, Layer* aAfter)
+{
+  ContainerInsertAfter(this, aChild, aAfter);
+}
+
+void
+ShadowContainerLayerD3D9::RemoveChild(Layer *aChild)
+{
+  ContainerRemoveChild(this, aChild);
+}
+
+void
+ShadowContainerLayerD3D9::Destroy()
+{
+  while (mFirstChild) {
+    RemoveChild(mFirstChild);
+  }
+}
+
+LayerD3D9*
+ShadowContainerLayerD3D9::GetFirstChildD3D9()
+{
+  if (!mFirstChild) {
+    return nsnull;
+   }
+  return static_cast<LayerD3D9*>(mFirstChild->ImplData());
+}
+ 
+void
+ShadowContainerLayerD3D9::RenderLayer()
+{
+  ContainerRender(this, mD3DManager);
+}
+
 } /* layers */
 } /* mozilla */
--- a/gfx/layers/d3d9/ContainerLayerD3D9.h
+++ b/gfx/layers/d3d9/ContainerLayerD3D9.h
@@ -38,20 +38,34 @@
 #ifndef GFX_CONTAINERLAYERD3D9_H
 #define GFX_CONTAINERLAYERD3D9_H
 
 #include "Layers.h"
 #include "LayerManagerD3D9.h"
 
 namespace mozilla {
 namespace layers {
+  
+template<class Container>
+static void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter);
+template<class Container>
+static void ContainerRemoveChild(Container* aContainer, Layer* aChild);
+template<class Container>
+static void ContainerRender(Container* aContainer, LayerManagerD3D9* aManager);
 
 class ContainerLayerD3D9 : public ContainerLayer,
                            public LayerD3D9
 {
+  template<class Container>
+  friend void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter);
+  template<class Container>
+  friend void ContainerRemoveChild(Container* aContainer, Layer* aChild);
+  template<class Container>
+  friend void ContainerRender(Container* aContainer, LayerManagerD3D9* aManager);
+
 public:
   ContainerLayerD3D9(LayerManagerD3D9 *aManager);
   ~ContainerLayerD3D9();
 
   nsIntRect GetVisibleRect() { return mVisibleRegion.GetBounds(); }
 
   /* ContainerLayer implementation */
   virtual void InsertAfter(Layer* aChild, Layer* aAfter);
@@ -70,12 +84,45 @@ public:
   virtual void LayerManagerDestroyed();
 
   virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
   {
     DefaultComputeEffectiveTransforms(aTransformToSurface);
   }
 };
 
+class ShadowContainerLayerD3D9 : public ShadowContainerLayer,
+                                public LayerD3D9
+{
+  template<class Container>
+  friend void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter);
+  template<class Container>
+  friend void ContainerRemoveChild(Container* aContainer, Layer* aChild);
+  template<class Container>
+  friend void ContainerRender(Container* aContainer, LayerManagerD3D9* aManager);
+
+public:
+  ShadowContainerLayerD3D9(LayerManagerD3D9 *aManager);
+  ~ShadowContainerLayerD3D9();
+
+  void InsertAfter(Layer* aChild, Layer* aAfter);
+
+  void RemoveChild(Layer* aChild);
+
+  // LayerD3D9 Implementation
+  virtual Layer* GetLayer() { return this; }
+
+  virtual void Destroy();
+
+  LayerD3D9* GetFirstChildD3D9();
+
+  virtual void RenderLayer();
+
+  virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
+  {
+    DefaultComputeEffectiveTransforms(aTransformToSurface);
+  }
+};
+
 } /* layers */
 } /* mozilla */
 
 #endif /* GFX_CONTAINERLAYERD3D9_H */
--- a/gfx/layers/d3d9/ImageLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -30,17 +30,24 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "mozilla/layers/PLayers.h"
+#include "mozilla/layers/ShadowLayers.h"
+#include "ShadowBufferD3D9.h"
+#include "gfxSharedImageSurface.h"
+
 #include "ImageLayerD3D9.h"
+#include "ThebesLayerD3D9.h"
+#include "gfxPlatform.h"
 #include "gfxImageSurface.h"
 #include "yuv_convert.h"
 #include "nsIServiceManager.h" 
 #include "nsIConsoleService.h" 
 #include "nsPrintfCString.h" 
 #include "Nv3DVUtils.h"
 
 namespace mozilla {
@@ -638,10 +645,152 @@ CairoImageD3D9::GetOrCreateTexture()
 
 already_AddRefed<gfxASurface>
 CairoImageD3D9::GetAsSurface()
 {
   nsRefPtr<gfxASurface> surface = mCachedSurface;
   return surface.forget();
 }
 
+ShadowImageLayerD3D9::ShadowImageLayerD3D9(LayerManagerD3D9* aManager)
+  : ShadowImageLayer(aManager, nsnull)
+  , LayerD3D9(aManager)
+{
+  mImplData = static_cast<LayerD3D9*>(this);
+}  
+
+ShadowImageLayerD3D9::~ShadowImageLayerD3D9()
+{}
+
+PRBool
+ShadowImageLayerD3D9::Init(const SharedImage& aFront,
+                          const nsIntSize& aSize)
+{
+   if (aFront.type() == SharedImage::TSurfaceDescriptor) {
+    SurfaceDescriptor desc = aFront.get_SurfaceDescriptor();
+    nsRefPtr<gfxASurface> surf = 
+      ShadowLayerForwarder::OpenDescriptor(desc);
+    
+    if (!mBuffer) {
+      mBuffer = new ShadowBufferD3D9(this);
+    }
+    return !!mBuffer;
+  } else {
+    if (!mYCbCrImage) {
+      mYCbCrImage = new PlanarYCbCrImageD3D9();
+    }
+    return !!mYCbCrImage;
+  }
+}
+
+void
+ShadowImageLayerD3D9::Swap(const SharedImage& aNewFront, SharedImage* aNewBack)
+{
+  
+  if (aNewFront.type() == SharedImage::TSurfaceDescriptor) {
+    nsRefPtr<gfxASurface> surf = 
+      ShadowLayerForwarder::OpenDescriptor(aNewFront.get_SurfaceDescriptor());
+   
+    if (mBuffer) {
+      mBuffer->Upload(surf, GetVisibleRegion().GetBounds());
+    }
+  } else {
+
+    const YUVImage& yuv = aNewFront.get_YUVImage();
+
+    nsRefPtr<gfxSharedImageSurface> surfY =
+      gfxSharedImageSurface::Open(yuv.Ydata());
+    nsRefPtr<gfxSharedImageSurface> surfU =
+      gfxSharedImageSurface::Open(yuv.Udata());
+    nsRefPtr<gfxSharedImageSurface> surfV =
+      gfxSharedImageSurface::Open(yuv.Vdata());
+
+    PlanarYCbCrImage::Data data;
+    data.mYChannel = surfY->Data();
+    data.mYStride = surfY->Stride();
+    data.mYSize = surfY->GetSize();
+    data.mCbChannel = surfU->Data();
+    data.mCrChannel = surfV->Data();
+    data.mCbCrStride = surfU->Stride();
+    data.mCbCrSize = surfU->GetSize();
+    data.mPicSize = surfY->GetSize();
+    data.mPicX = 0;
+    data.mPicY = 0;
+
+    mYCbCrImage->SetData(data);
+
+  }
+  
+  *aNewBack = aNewFront;
+}
+
+void
+ShadowImageLayerD3D9::DestroyFrontBuffer()
+{
+  Destroy();
+}
+
+void
+ShadowImageLayerD3D9::Disconnect()
+{
+  Destroy();
+}
+
+void
+ShadowImageLayerD3D9::Destroy()
+{
+  mBuffer = nsnull;
+  mYCbCrImage = nsnull;
+}
+
+Layer*
+ShadowImageLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+void
+ShadowImageLayerD3D9::RenderLayer()
+{
+  if (mBuffer) {
+    mBuffer->RenderTo(mD3DManager, GetEffectiveVisibleRegion());
+  } else if (mYCbCrImage) {
+    if (!mYCbCrImage->HasData()) {
+      return;
+    }
+    
+    mYCbCrImage->AllocateTextures(device());
+
+    SetShaderTransformAndOpacity();
+
+    device()->SetVertexShaderConstantF(CBvLayerQuad,
+                                       ShaderConstantRect(0,
+                                                          0,
+                                                          mYCbCrImage->mSize.width,
+                                                          mYCbCrImage->mSize.height),
+                                       1);
+
+    mD3DManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER);
+
+    /*
+     * Send 3d control data and metadata
+     */
+    if (mD3DManager->GetNv3DVUtils()) {
+      // TODO Add 3D support
+    }
+
+    // Linear scaling is default here, adhering to mFilter is difficult since
+    // presumably even with point filtering we'll still want chroma upsampling
+    // to be linear. In the current approach we can't.
+    device()->SetTexture(0, mYCbCrImage->mYTexture);
+    device()->SetTexture(1, mYCbCrImage->mCbTexture);
+    device()->SetTexture(2, mYCbCrImage->mCrTexture);
+
+    device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+  } else {
+    NS_ERROR("Unexpected image format.");
+  }
+
+}
+
+
 } /* layers */
 } /* mozilla */
--- a/gfx/layers/d3d9/ImageLayerD3D9.h
+++ b/gfx/layers/d3d9/ImageLayerD3D9.h
@@ -40,16 +40,18 @@
 
 #include "LayerManagerD3D9.h"
 #include "ImageLayers.h"
 #include "yuv_convert.h"
 
 namespace mozilla {
 namespace layers {
 
+class ShadowBufferD3D9;
+
 class THEBES_API ImageContainerD3D9 : public ImageContainer
 {
 public:
   ImageContainerD3D9(IDirect3DDevice9 *aDevice);
   virtual ~ImageContainerD3D9() {}
 
   virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
                                               PRUint32 aNumFormats);
@@ -168,11 +170,39 @@ public:
 private:
   gfxIntSize mSize;
   nsRefPtr<gfxASurface> mCachedSurface;
   nsRefPtr<IDirect3DDevice9> mDevice;
   nsRefPtr<IDirect3DTexture9> mTexture;
   LayerManagerD3D9 *mManager;
 };
 
+class ShadowImageLayerD3D9 : public ShadowImageLayer,
+                            public LayerD3D9
+{
+public:
+  ShadowImageLayerD3D9(LayerManagerD3D9* aManager);
+  virtual ~ShadowImageLayerD3D9();
+
+  // ShadowImageLayer impl
+  virtual PRBool Init(const SharedImage& aFront, const nsIntSize& aSize);
+
+  virtual void Swap(const SharedImage& aFront, SharedImage* aNewBack);
+
+  virtual void DestroyFrontBuffer();
+
+  virtual void Disconnect();
+
+  // LayerD3D9 impl
+  virtual void Destroy();
+
+  virtual Layer* GetLayer();
+
+  virtual void RenderLayer();
+
+private:
+  nsRefPtr<ShadowBufferD3D9> mBuffer;
+  nsRefPtr<PlanarYCbCrImageD3D9> mYCbCrImage;
+};
+
 } /* layers */
 } /* mozilla */
 #endif /* GFX_IMAGELAYERD3D9_H */
--- a/gfx/layers/d3d9/LayerManagerD3D9.cpp
+++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp
@@ -240,16 +240,66 @@ LayerManagerD3D9::CreateReadbackLayer()
 
 already_AddRefed<ImageContainer>
 LayerManagerD3D9::CreateImageContainer()
 {
   nsRefPtr<ImageContainer> container = new ImageContainerD3D9(device());
   return container.forget();
 }
 
+already_AddRefed<ShadowThebesLayer>
+LayerManagerD3D9::CreateShadowThebesLayer()
+{
+  if (LayerManagerD3D9::mDestroyed) {
+    NS_WARNING("Call on destroyed layer manager");
+    return nsnull;
+  }
+  return nsRefPtr<ShadowThebesLayerD3D9>(new ShadowThebesLayerD3D9(this)).forget();
+}
+
+already_AddRefed<ShadowContainerLayer>
+LayerManagerD3D9::CreateShadowContainerLayer()
+{
+  if (LayerManagerD3D9::mDestroyed) {
+    NS_WARNING("Call on destroyed layer manager");
+    return nsnull;
+  }
+  return nsRefPtr<ShadowContainerLayerD3D9>(new ShadowContainerLayerD3D9(this)).forget();
+}
+
+already_AddRefed<ShadowImageLayer>
+LayerManagerD3D9::CreateShadowImageLayer()
+{
+  if (LayerManagerD3D9::mDestroyed) {
+    NS_WARNING("Call on destroyed layer manager");
+    return nsnull;
+  }
+  return nsRefPtr<ShadowImageLayerD3D9>(new ShadowImageLayerD3D9(this)).forget();
+}
+
+already_AddRefed<ShadowColorLayer>
+LayerManagerD3D9::CreateShadowColorLayer()
+{
+  if (LayerManagerD3D9::mDestroyed) {
+    NS_WARNING("Call on destroyed layer manager");
+    return nsnull;
+  }
+  return nsRefPtr<ShadowColorLayerD3D9>(new ShadowColorLayerD3D9(this)).forget();
+}
+
+already_AddRefed<ShadowCanvasLayer>
+LayerManagerD3D9::CreateShadowCanvasLayer()
+{
+  if (LayerManagerD3D9::mDestroyed) {
+    NS_WARNING("Call on destroyed layer manager");
+    return nsnull;
+  }
+  return nsRefPtr<ShadowCanvasLayerD3D9>(new ShadowCanvasLayerD3D9(this)).forget();
+}
+
 void ReleaseTexture(void *texture)
 {
   static_cast<IDirect3DTexture9*>(texture)->Release();
 }
 
 void
 LayerManagerD3D9::ReportFailure(const nsACString &aMsg, HRESULT aCode)
 {
--- a/gfx/layers/d3d9/LayerManagerD3D9.h
+++ b/gfx/layers/d3d9/LayerManagerD3D9.h
@@ -35,16 +35,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef GFX_LAYERMANAGERD3D9_H
 #define GFX_LAYERMANAGERD3D9_H
 
 #include "Layers.h"
 
+#include "mozilla/layers/ShadowLayers.h"
+
 #include <windows.h>
 #include <d3d9.h>
 
 #include "gfxContext.h"
 #include "nsIWidget.h"
 
 #include "DeviceManagerD3D9.h"
 
@@ -83,17 +85,17 @@ struct ShaderConstantRect
   // For easy passing to SetVertexShaderConstantF.
   operator float* () { return &mX; }
 };
 
 /*
  * This is the LayerManager used for Direct3D 9. For now this will render on
  * the main thread.
  */
-class THEBES_API LayerManagerD3D9 : public LayerManager {
+class THEBES_API LayerManagerD3D9 : public ShadowLayerManager {
 public:
   LayerManagerD3D9(nsIWidget *aWidget);
   virtual ~LayerManagerD3D9();
 
   /*
    * Initializes the layer manager, this is when the layer manager will
    * actually access the device and attempt to create the swap chain used
    * to draw to the window. If this method fails the device cannot be used.
@@ -148,16 +150,22 @@ public:
   virtual already_AddRefed<ColorLayer> CreateColorLayer();
 
   virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
 
   virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer();
 
   virtual already_AddRefed<ImageContainer> CreateImageContainer();
 
+  virtual already_AddRefed<ShadowThebesLayer> CreateShadowThebesLayer();
+  virtual already_AddRefed<ShadowContainerLayer> CreateShadowContainerLayer();
+  virtual already_AddRefed<ShadowImageLayer> CreateShadowImageLayer();
+  virtual already_AddRefed<ShadowColorLayer> CreateShadowColorLayer();
+  virtual already_AddRefed<ShadowCanvasLayer> CreateShadowCanvasLayer();
+
   virtual LayersBackend GetBackendType() { return LAYERS_D3D9; }
   virtual void GetBackendName(nsAString& name) { name.AssignLiteral("Direct3D 9"); }
   bool DeviceWasRemoved() { return deviceManager()->DeviceWasRemoved(); }
 
   /*
    * Helper methods.
    */
   void SetClippingEnabled(PRBool aEnabled);
@@ -278,12 +286,46 @@ public:
     opacity[0] = layer->GetEffectiveOpacity();
     device()->SetPixelShaderConstantF(CBfLayerOpacity, opacity, 1);
   }
 
 protected:
   LayerManagerD3D9 *mD3DManager;
 };
 
+/*
+ * RAII helper for locking D3D9 textures.
+ */
+class LockTextureRectD3D9 
+{
+public:
+  LockTextureRectD3D9(IDirect3DTexture9* aTexture) 
+    : mTexture(aTexture)
+  {
+    mLockResult = mTexture->LockRect(0, &mR, NULL, 0);
+  }
+
+  ~LockTextureRectD3D9()
+  {
+    mTexture->UnlockRect(0);
+  }
+
+  bool HasLock() {
+    return SUCCEEDED(mLockResult);
+  }
+
+  D3DLOCKED_RECT GetLockRect() 
+  {
+    return mR;
+  }
+private:
+  LockTextureRectD3D9 (const LockTextureRectD3D9&);
+  LockTextureRectD3D9& operator= (const LockTextureRectD3D9&);
+
+  IDirect3DTexture9* mTexture;
+  D3DLOCKED_RECT mR;
+  HRESULT mLockResult;
+};
+
 } /* layers */
 } /* mozilla */
 
 #endif /* GFX_LAYERMANAGERD3D9_H */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ShadowBufferD3D9.cpp
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Benoit Girard <bgirard@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "LayerManagerD3D9.h"
+#include "ShadowBufferD3D9.h"
+
+#include "gfxWindowsSurface.h"
+#include "gfxWindowsPlatform.h"
+
+
+namespace mozilla {
+namespace layers {
+
+void 
+ShadowBufferD3D9::Upload(gfxASurface* aUpdate, 
+                         const nsIntRect& aVisibleRect)
+{
+
+  gfxIntSize size = aUpdate->GetSize();
+
+  if (GetSize() != nsIntSize(size.width, size.height)) {
+    mLayer->device()->CreateTexture(size.width, size.height, 1,
+                          D3DUSAGE_DYNAMIC,
+                          D3DFMT_A8R8G8B8,
+                          D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
+
+    mTextureRect = aVisibleRect;
+  }
+
+  LockTextureRectD3D9 textureLock(mTexture);
+  if (!textureLock.HasLock()) {
+    NS_WARNING("Failed to lock ShadowBufferD3D9 texture.");
+    return;
+  }
+
+  D3DLOCKED_RECT r = textureLock.GetLockRect();
+
+  nsRefPtr<gfxImageSurface> imgSurface =
+    new gfxImageSurface((unsigned char *)r.pBits,
+                        GetSize(),
+                        r.Pitch,
+                        gfxASurface::ImageFormatARGB32);
+
+  nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
+  context->SetSource(aUpdate);
+  context->SetOperator(gfxContext::OPERATOR_SOURCE);
+  context->Paint();
+
+  imgSurface = NULL;
+}
+
+void 
+ShadowBufferD3D9::RenderTo(LayerManagerD3D9 *aD3DManager, 
+                           const nsIntRegion& aVisibleRegion)
+{
+  mLayer->SetShaderTransformAndOpacity();
+
+  aD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER);
+  mLayer->device()->SetTexture(0, mTexture);
+
+  nsIntRegionRectIterator iter(aVisibleRegion);
+
+  const nsIntRect *iterRect;
+  while ((iterRect = iter.Next())) {
+    mLayer->device()->SetVertexShaderConstantF(CBvLayerQuad,
+                                       ShaderConstantRect(iterRect->x,
+                                                          iterRect->y,
+                                                          iterRect->width,
+                                                          iterRect->height),
+                                       1);
+
+    mLayer->device()->SetVertexShaderConstantF(CBvTextureCoords,
+      ShaderConstantRect(
+        (float)(iterRect->x - mTextureRect.x) / (float)mTextureRect.width,
+        (float)(iterRect->y - mTextureRect.y) / (float)mTextureRect.height,
+        (float)iterRect->width / (float)mTextureRect.width,
+        (float)iterRect->height / (float)mTextureRect.height), 1);
+
+    mLayer->device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+  }
+}
+
+} /* namespace layers */
+} /* namespace mozilla */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ShadowBufferD3D9.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Benoit Girard <bgirard@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef GFX_SHADOWBUFFERD3D9_H
+#define GFX_SHADOWBUFFERD3D9_H
+
+#include "LayerManagerD3D9.h"
+
+namespace mozilla {
+namespace layers {
+
+class LayerManagerD3D9;
+class LayerD3D9;
+
+class ShadowBufferD3D9
+{
+  NS_INLINE_DECL_REFCOUNTING(ShadowBufferD3D9)
+public:
+
+  ShadowBufferD3D9(LayerD3D9* aLayer)
+    : mLayer(aLayer)
+  {
+  }
+  virtual ~ShadowBufferD3D9() {}
+  
+  void Upload(gfxASurface* aUpdate, const nsIntRect& aVisibleRect);
+
+  void RenderTo(LayerManagerD3D9 *aD3DManager, const nsIntRegion& aVisibleRegion);
+
+  nsIntSize GetSize() {
+    if (mTexture)
+      return nsIntSize(mTextureRect.Width(), mTextureRect.Height());
+    return nsIntSize(0, 0);
+  }
+protected:
+  nsRefPtr<IDirect3DTexture9> mTexture;
+  nsIntRect mTextureRect;
+  LayerD3D9* mLayer;
+};
+
+} /* layers */
+} /* mozilla */
+#endif /* GFX_SHADOWBUFFERD3D9_H */
--- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp
@@ -30,16 +30,20 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "mozilla/layers/PLayers.h"
+#include "mozilla/layers/ShadowLayers.h"
+#include "ShadowBufferD3D9.h"
+
 #include "ThebesLayerD3D9.h"
 #include "gfxPlatform.h"
 
 #include "gfxWindowsPlatform.h"
 #include "gfxTeeSurface.h"
 #include "gfxUtils.h"
 #include "ReadbackProcessor.h"
 
@@ -511,36 +515,39 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion 
   {
     case SURFACE_OPAQUE:
       opaqueRenderer.End();
       srcTextures.AppendElement(opaqueRenderer.GetTexture());
       destTextures.AppendElement(mTexture);
       break;
 
     case SURFACE_SINGLE_CHANNEL_ALPHA: {
-      D3DLOCKED_RECT r;
-      tmpTexture->LockRect(0, &r, NULL, 0);
+      LockTextureRectD3D9 textureLock(tmpTexture);
+      if (!textureLock.HasLock()) {
+        NS_WARNING("Failed to lock ThebesLayer tmpTexture texture.");
+        return;
+      }
+
+      D3DLOCKED_RECT r = textureLock.GetLockRect();
 
       nsRefPtr<gfxImageSurface> imgSurface =
         new gfxImageSurface((unsigned char *)r.pBits,
                             bounds.Size(),
                             r.Pitch,
                             gfxASurface::ImageFormatARGB32);
 
       if (destinationSurface) {
         nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
         context->SetSource(destinationSurface);
         context->SetOperator(gfxContext::OPERATOR_SOURCE);
         context->Paint();
       }
 
       imgSurface = NULL;
 
-      tmpTexture->UnlockRect(0);
-
       srcTextures.AppendElement(tmpTexture);
       destTextures.AppendElement(mTexture);
       break;
     }
 
     case SURFACE_COMPONENT_ALPHA: {
       opaqueRenderer.End();
       opaqueRendererOnWhite.End();
@@ -596,10 +603,100 @@ ThebesLayerD3D9::CreateNewTextures(const
   if (aMode == SURFACE_COMPONENT_ALPHA) {
     device()->CreateTexture(aSize.width, aSize.height, 1,
                             D3DUSAGE_RENDERTARGET,
                             D3DFMT_X8R8G8B8,
                             D3DPOOL_DEFAULT, getter_AddRefs(mTextureOnWhite), NULL);
   }
 }
 
+ShadowThebesLayerD3D9::ShadowThebesLayerD3D9(LayerManagerD3D9 *aManager)
+  : ShadowThebesLayer(aManager, nsnull)
+  , LayerD3D9(aManager)
+{
+  mImplData = static_cast<LayerD3D9*>(this);
+}
+
+ShadowThebesLayerD3D9::~ShadowThebesLayerD3D9()
+{}
+
+void
+ShadowThebesLayerD3D9::SetFrontBuffer(const OptionalThebesBuffer& aNewFront,
+                                     const nsIntRegion& aValidRegion)
+{
+  if (!mBuffer) {
+    mBuffer = new ShadowBufferD3D9(this);
+  }
+
+  NS_ASSERTION(OptionalThebesBuffer::Tnull_t == aNewFront.type(),
+               "Only one system-memory buffer expected");
+}
+
+void
+ShadowThebesLayerD3D9::Swap(const ThebesBuffer& aNewFront,
+                           const nsIntRegion& aUpdatedRegion,
+                           ThebesBuffer* aNewBack,
+                           nsIntRegion* aNewBackValidRegion,
+                           OptionalThebesBuffer* aReadOnlyFront,
+                           nsIntRegion* aFrontUpdatedRegion)
+{
+  if (mBuffer) {
+    nsRefPtr<gfxASurface> surf = ShadowLayerForwarder::OpenDescriptor(aNewFront.buffer());
+    mBuffer->Upload(surf, GetVisibleRegion().GetBounds());
+  }
+
+  *aNewBack = aNewFront;
+  *aNewBackValidRegion = mValidRegion;
+  *aReadOnlyFront = null_t();
+  aFrontUpdatedRegion->SetEmpty();
+}
+
+void
+ShadowThebesLayerD3D9::DestroyFrontBuffer()
+{
+  mBuffer = nsnull;
+}
+
+void
+ShadowThebesLayerD3D9::Disconnect()
+{
+  mBuffer = nsnull;
+}
+
+Layer*
+ShadowThebesLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+PRBool
+ShadowThebesLayerD3D9::IsEmpty()
+{
+  return !mBuffer;
+}
+
+void
+ShadowThebesLayerD3D9::RenderThebesLayer()
+{
+  if (!mBuffer) {
+    return;
+  }
+  NS_ABORT_IF_FALSE(mBuffer, "should have a buffer here");
+
+  mBuffer->RenderTo(mD3DManager, GetEffectiveVisibleRegion());
+}
+
+void
+ShadowThebesLayerD3D9::CleanResources()
+{
+  mBuffer = nsnull;
+  mValidRegion.SetEmpty();
+}
+
+void
+ShadowThebesLayerD3D9::LayerManagerDestroyed()
+{
+  mD3DManager->deviceManager()->mLayersWithResources.RemoveElement(this);
+  mD3DManager = nsnull;
+}
+
 } /* namespace layers */
 } /* namespace mozilla */
--- a/gfx/layers/d3d9/ThebesLayerD3D9.h
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.h
@@ -42,16 +42,17 @@
 #include "LayerManagerD3D9.h"
 #include "gfxImageSurface.h"
 #include "ReadbackProcessor.h"
 
 namespace mozilla {
 namespace layers {
 
 class ReadbackProcessor;
+class ShadowBufferD3D9;
 
 class ThebesLayerD3D9 : public ThebesLayer,
                         public LayerD3D9
 {
 public:
   ThebesLayerD3D9(LayerManagerD3D9 *aManager);
   virtual ~ThebesLayerD3D9();
 
@@ -107,11 +108,42 @@ private:
   /* Create a new texture */
   void CreateNewTextures(const gfxIntSize &aSize, SurfaceMode aMode);
 
   void CopyRegion(IDirect3DTexture9* aSrc, const nsIntPoint &aSrcOffset,
                   IDirect3DTexture9* aDest, const nsIntPoint &aDestOffset,
                   const nsIntRegion &aCopyRegion, nsIntRegion* aValidRegion);
 };
 
+class ShadowThebesLayerD3D9 : public ShadowThebesLayer,
+                              public LayerD3D9
+{
+public:
+  ShadowThebesLayerD3D9(LayerManagerD3D9 *aManager);
+  virtual ~ShadowThebesLayerD3D9();
+
+  // ShadowThebesLayer impl
+  virtual void SetFrontBuffer(const OptionalThebesBuffer& aNewFront,
+                              const nsIntRegion& aValidRegion);
+  virtual void
+  Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion,
+       ThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion,
+       OptionalThebesBuffer* aReadOnlyFront, nsIntRegion* aFrontUpdatedRegion);
+  virtual void DestroyFrontBuffer();
+
+  virtual void Disconnect();
+
+  // LayerD3D9 impl
+  Layer* GetLayer();
+  virtual PRBool IsEmpty();
+  virtual void RenderLayer() { RenderThebesLayer(); }
+  virtual void CleanResources();
+  virtual void LayerManagerDestroyed();
+
+  void RenderThebesLayer();
+
+private:
+  nsRefPtr<ShadowBufferD3D9> mBuffer;
+};
+
 } /* layers */
 } /* mozilla */
 #endif /* GFX_THEBESLAYERD3D9_H */
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -30,16 +30,19 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "mozilla/layers/PLayers.h"
+#include "mozilla/layers/ShadowLayers.h"
+
 #include "gfxSharedImageSurface.h"
 
 #include "CanvasLayerOGL.h"
 
 #include "gfxImageSurface.h"
 #include "gfxContext.h"
 #include "GLContextProvider.h"
 
--- a/gfx/layers/opengl/CanvasLayerOGL.h
+++ b/gfx/layers/opengl/CanvasLayerOGL.h
@@ -33,18 +33,16 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef GFX_CANVASLAYEROGL_H
 #define GFX_CANVASLAYEROGL_H
 
-#include "mozilla/layers/PLayers.h"
-#include "mozilla/layers/ShadowLayers.h"
 
 #include "LayerManagerOGL.h"
 #include "gfxASurface.h"
 #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
 #include "GLXLibrary.h"
 #include "mozilla/X11Util.h"
 #endif
 
--- a/gfx/layers/opengl/ImageLayerOGL.cpp
+++ b/gfx/layers/opengl/ImageLayerOGL.cpp
@@ -574,16 +574,20 @@ ImageLayerOGL::RenderLayer(int,
        // If its an empty transaction we still need to update
        // the plugin IO Surface and make sure we grab the
        // new image
        ioImage->Update(GetContainer());
        image = GetContainer()->GetCurrentImage();
        gl()->MakeCurrent();
        ioImage = static_cast<MacIOSurfaceImageOGL*>(image.get());
      }
+
+     if (!ioImage) {
+       return;
+     }
      
      gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
      gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, ioImage->mTexture.GetTextureID());
 
      ColorTextureLayerProgram *program = 
        mOGLManager->GetRGBARectLayerProgram();
      
      program->Activate();
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2825,16 +2825,28 @@ nsLayoutUtils::GetTextColor(nsIFrame* aF
 {
   nscolor color = aFrame->GetVisitedDependentColor(eCSSProperty_color);
   if (ShouldDarkenColors(aFrame->PresContext())) {
     color = DarkenColor(color);
   }
   return color;
 }
 
+gfxFloat
+nsLayoutUtils::GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext,
+                                   nscoord aY, nscoord aAscent)
+{
+  gfxFloat appUnitsPerDevUnit = aFrame->PresContext()->AppUnitsPerDevPixel();
+  gfxFloat baseline = gfxFloat(aY) + aAscent;
+  gfxRect putativeRect(0, baseline/appUnitsPerDevUnit, 1, 1);
+  if (!aContext->UserToDevicePixelSnapped(putativeRect, PR_TRUE))
+    return baseline;
+  return aContext->DeviceToUser(putativeRect.TopLeft()).y * appUnitsPerDevUnit;
+}
+
 void
 nsLayoutUtils::DrawString(const nsIFrame*      aFrame,
                           nsRenderingContext* aContext,
                           const PRUnichar*     aString,
                           PRInt32              aLength,
                           nsPoint              aPoint,
                           PRUint8              aDirection)
 {
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -929,16 +929,20 @@ public:
 
   // Implement nsIFrame::GetMinWidth in terms of nsIFrame::AddInlineMinWidth
   static nscoord MinWidthFromInline(nsIFrame* aFrame,
                                     nsRenderingContext* aRenderingContext);
 
   // Get a suitable foreground color for painting text for the frame.
   static nscolor GetTextColor(nsIFrame* aFrame);
 
+  // Get a baseline y position in app units that is snapped to device pixels.
+  static gfxFloat GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext,
+                                      nscoord aY, nscoord aAscent);
+
   static void DrawString(const nsIFrame*      aFrame,
                          nsRenderingContext* aContext,
                          const PRUnichar*     aString,
                          PRInt32              aLength,
                          nsPoint              aPoint,
                          PRUint8              aDirection = NS_STYLE_DIRECTION_INHERIT);
 
   static nscoord GetStringWidth(const nsIFrame*      aFrame,
--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -82,24 +82,19 @@ GetSelfOrNearestBlock(nsIFrame* aFrame)
 // Return true if the frame is an atomic inline-level element.
 // It's not supposed to be called for block frames since we never
 // process block descendants for text-overflow.
 static bool
 IsAtomicElement(nsIFrame* aFrame, const nsIAtom* aFrameType)
 {
   NS_PRECONDITION(!aFrame->GetStyleDisplay()->IsBlockOutside(),
                   "unexpected block frame");
-
-  if (aFrame->IsFrameOfType(nsIFrame::eReplaced)) {
-    if (aFrameType != nsGkAtoms::textFrame &&
-        aFrameType != nsGkAtoms::brFrame) {
-      return true;
-    }
-  }
-  return aFrame->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_INLINE;
+  NS_PRECONDITION(aFrameType != nsGkAtoms::placeholderFrame,
+                  "unexpected placeholder frame");
+  return !aFrame->IsFrameOfType(nsIFrame::eLineParticipant);
 }
 
 static bool
 IsFullyClipped(nsTextFrame* aFrame, nscoord aLeft, nscoord aRight,
                nscoord* aSnappedLeft, nscoord* aSnappedRight)
 {
   *aSnappedLeft = aLeft;
   *aSnappedRight = aRight;
@@ -235,31 +230,29 @@ nsDisplayTextOverflowMarker::Paint(nsDis
                                    nsRenderingContext*   aCtx)
 {
   nscolor foregroundColor = nsLayoutUtils::GetTextColor(mFrame);
 
   // Paint the text-shadows for the overflow marker
   nsLayoutUtils::PaintTextShadow(mFrame, aCtx, mRect, mVisibleRect,
                                  foregroundColor, PaintTextShadowCallback,
                                  (void*)this);
-
   aCtx->SetColor(foregroundColor);
   PaintTextToContext(aCtx, nsPoint(0, 0));
 }
 
 void
 nsDisplayTextOverflowMarker::PaintTextToContext(nsRenderingContext* aCtx,
                                                 nsPoint aOffsetFromRect)
 {
   nsStyleContext* sc = mFrame->GetStyleContext();
   nsLayoutUtils::SetFontFromStyle(aCtx, sc);
-
-  nsPoint baselinePt = mRect.TopLeft();
-  baselinePt.y += mAscent;
-
+  gfxFloat y = nsLayoutUtils::GetSnappedBaselineY(mFrame, aCtx->ThebesContext(),
+                                                  mRect.y, mAscent);
+  nsPoint baselinePt(mRect.x, NSToCoordFloor(y));
   nsLayoutUtils::DrawString(mFrame, aCtx, mString.get(),
                             mString.Length(), baselinePt + aOffsetFromRect);
 }
 
 /* static */ TextOverflow*
 TextOverflow::WillProcessLines(nsDisplayListBuilder*   aBuilder,
                                const nsDisplayListSet& aLists,
                                nsIFrame*               aBlockFrame)
@@ -312,17 +305,18 @@ TextOverflow::DidProcessLines()
 void
 TextOverflow::ExamineFrameSubtree(nsIFrame*       aFrame,
                                   const nsRect&   aContentArea,
                                   const nsRect&   aInsideMarkersArea,
                                   FrameHashtable* aFramesToHide,
                                   AlignmentEdges* aAlignmentEdges)
 {
   const nsIAtom* frameType = aFrame->GetType();
-  if (frameType == nsGkAtoms::brFrame) {
+  if (frameType == nsGkAtoms::brFrame ||
+      frameType == nsGkAtoms::placeholderFrame) {
     return;
   }
   const bool isAtomic = IsAtomicElement(aFrame, frameType);
   if (aFrame->GetStyleVisibility()->IsVisible()) {
     nsRect childRect = aFrame->GetScrollableOverflowRect() +
                        aFrame->GetOffsetTo(mBlock);
     bool overflowLeft = childRect.x < aContentArea.x;
     bool overflowRight = childRect.XMost() > aContentArea.XMost();
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -266,18 +266,16 @@ public:
 
   nsOverflowAreas RecomputeOverflow();
 
   void AddInlineMinWidthForFlow(nsRenderingContext *aRenderingContext,
                                 nsIFrame::InlineMinWidthData *aData);
   void AddInlinePrefWidthForFlow(nsRenderingContext *aRenderingContext,
                                  InlinePrefWidthData *aData);
 
-  gfxFloat GetSnappedBaselineY(gfxContext* aContext, gfxFloat aY);
-
   /**
    * Calculate the horizontal bounds of the grapheme clusters that fit entirely
    * inside the given left/right edges (which are positive lengths from the
    * respective frame edge).  If an input value is zero it is ignored and the
    * result for that edge is zero.  All out parameter values are undefined when
    * the method returns false.
    * @return true if at least one whole grapheme cluster fit between the edges
    */
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -5116,27 +5116,16 @@ static PRUint32
 ComputeTransformedLength(PropertyProvider& aProvider)
 {
   gfxSkipCharsIterator iter(aProvider.GetStart());
   PRUint32 start = iter.GetSkippedOffset();
   iter.AdvanceOriginal(aProvider.GetOriginalLength());
   return iter.GetSkippedOffset() - start;
 }
 
-gfxFloat
-nsTextFrame::GetSnappedBaselineY(gfxContext* aContext, gfxFloat aY)
-{
-  gfxFloat appUnitsPerDevUnit = mTextRun->GetAppUnitsPerDevUnit();
-  gfxFloat baseline = aY + mAscent;
-  gfxRect putativeRect(0, baseline/appUnitsPerDevUnit, 1, 1);
-  if (!aContext->UserToDevicePixelSnapped(putativeRect, PR_TRUE))
-    return baseline;
-  return aContext->DeviceToUser(putativeRect.TopLeft()).y*appUnitsPerDevUnit;
-}
-
 bool
 nsTextFrame::MeasureCharClippedText(gfxContext* aCtx,
                                     nscoord aLeftEdge, nscoord aRightEdge,
                                     nscoord* aSnappedLeftEdge,
                                     nscoord* aSnappedRightEdge)
 {
   // Don't pass in aRenderingContext here, because we need a *reference*
   // context and aRenderingContext might have some transform in it
@@ -5253,17 +5242,17 @@ nsTextFrame::PaintText(nsRenderingContex
   // Trim trailing whitespace
   provider.InitializeForDisplay(PR_TRUE);
 
   gfxContext* ctx = aRenderingContext->ThebesContext();
   const PRBool rtl = mTextRun->IsRightToLeft();
   const nscoord frameWidth = GetSize().width;
   gfxPoint framePt(aPt.x, aPt.y);
   gfxPoint textBaselinePt(rtl ? gfxFloat(aPt.x + frameWidth) : framePt.x,
-                          GetSnappedBaselineY(ctx, aPt.y));
+             nsLayoutUtils::GetSnappedBaselineY(this, ctx, aPt.y, mAscent));
   PRUint32 startOffset = provider.GetStart().GetSkippedOffset();
   PRUint32 maxLength = ComputeTransformedLength(provider);
   nscoord snappedLeftEdge, snappedRightEdge;
   if (!MeasureCharClippedText(ctx, provider, aItem.mLeftEdge, aItem.mRightEdge,
          &startOffset, &maxLength, &snappedLeftEdge, &snappedRightEdge)) {
     return;
   }
   textBaselinePt.x += rtl ? -snappedRightEdge : snappedLeftEdge;
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -37,16 +37,19 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/layers/ShadowLayersParent.h"
 
 #include "BasicLayers.h"
 #include "LayerManagerOGL.h"
+#ifdef MOZ_ENABLE_D3D9_LAYER
+#include "LayerManagerD3D9.h"
+#endif //MOZ_ENABLE_D3D9_LAYER
 #include "RenderFrameParent.h"
 
 #include "gfx3DMatrix.h"
 #include "nsFrameLoader.h"
 #include "nsViewportFrame.h"
 #include "nsSubDocumentFrame.h"
 #include "nsIObserver.h"
 
@@ -718,16 +721,22 @@ RenderFrameParent::AllocPLayers()
   case LayerManager::LAYERS_BASIC: {
     BasicShadowLayerManager* bslm = static_cast<BasicShadowLayerManager*>(lm);
     return new ShadowLayersParent(bslm);
   }
   case LayerManager::LAYERS_OPENGL: {
     LayerManagerOGL* lmo = static_cast<LayerManagerOGL*>(lm);
     return new ShadowLayersParent(lmo);
   }
+#ifdef MOZ_ENABLE_D3D9_LAYER
+  case LayerManager::LAYERS_D3D9: {
+    LayerManagerD3D9* lmd3d9 = static_cast<LayerManagerD3D9*>(lm);
+    return new ShadowLayersParent(lmd3d9);
+  }
+#endif //MOZ_ENABLE_D3D9_LAYER
   default: {
     NS_WARNING("shadow layers no sprechen D3D backend yet");
     return nsnull;
   }
   }
 }
 
 bool
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text-overflow/aligned-baseline-ref.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Testcase for bug 668919</title>
+
+<style>
+.tab-title {
+  overflow:hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  width: 5em;
+  height:25px;
+}
+
+.c1 { font-size: 14px; }
+.c2 { font-size: 15px; }
+.c3 { font-size: 16px; }
+.c4 { font-size: 17px; }
+.c5 { font-size: 18px; }
+.c6 { font-size: 19px; }
+.c7 { font-size: 20px; }
+.c8 { font-size: 24px; }
+.c9 { font-size: 28px; }
+.c10 { font-size: 32px; }
+.c11 { font-size: 36px; }
+
+.p0  { padding-top:0; }
+.p1  { padding-top:0px; }
+.p2  { padding-top:0px; }
+
+.col2 .tab-title { text-shadow: 1px 1px 1px blue; }
+</style>
+    </head>
+<body>
+
+<div style="position:absolute; top: 0px;">
+<div class="tab-title c1 p0">CSS is awesome</div>
+<div class="tab-title c1 p2">CSS is awesome</div>
+<div class="tab-title c1 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 100px;">
+<div class="tab-title c2 p0">CSS is awesome</div>
+<div class="tab-title c2 p2">CSS is awesome</div>
+<div class="tab-title c2 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 200px;">
+<div class="tab-title c3 p0">CSS is awesome</div>
+<div class="tab-title c3 p2">CSS is awesome</div>
+<div class="tab-title c3 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 300px;">
+<div class="tab-title c4 p0">CSS is awesome</div>
+<div class="tab-title c4 p2">CSS is awesome</div>
+<div class="tab-title c4 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 400px;">
+<div class="tab-title c5 p0">CSS is awesome</div>
+<div class="tab-title c5 p2">CSS is awesome</div>
+<div class="tab-title c5 p3">CSS is awesome</div>
+</div>
+
+<div class="col2" style="position:absolute; top: 0px; left:8em;">
+<div style="position:absolute; top: 0px;">
+<div class="tab-title c1 p0">CSS is awesome</div>
+<div class="tab-title c1 p2">CSS is awesome</div>
+<div class="tab-title c1 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 100px;">
+<div class="tab-title c2 p0">CSS is awesome</div>
+<div class="tab-title c2 p2">CSS is awesome</div>
+<div class="tab-title c2 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 200px;">
+<div class="tab-title c3 p0">CSS is awesome</div>
+<div class="tab-title c3 p2">CSS is awesome</div>
+<div class="tab-title c3 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 300px;">
+<div class="tab-title c4 p0">CSS is awesome</div>
+<div class="tab-title c4 p2">CSS is awesome</div>
+<div class="tab-title c4 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 400px;">
+<div class="tab-title c5 p0">CSS is awesome</div>
+<div class="tab-title c5 p2">CSS is awesome</div>
+<div class="tab-title c5 p3">CSS is awesome</div>
+</div>
+</div>
+
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text-overflow/aligned-baseline.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Testcase for bug 668919</title>
+
+<style>
+.tab-title {
+  overflow:hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  width: 5em;
+  height:25px;
+}
+
+.c1 { font-size: 14px; }
+.c2 { font-size: 15px; }
+.c3 { font-size: 16px; }
+.c4 { font-size: 17px; }
+.c5 { font-size: 18px; }
+.c6 { font-size: 19px; }
+.c7 { font-size: 20px; }
+.c8 { font-size: 24px; }
+.c9 { font-size: 28px; }
+.c10 { font-size: 32px; }
+.c11 { font-size: 36px; }
+
+.p0  { padding-top:0; }
+.p1  { padding-top:0.1px; }
+.p2  { padding-top:0.2px; }
+
+.col2 .tab-title { text-shadow: 1px 1px 1px blue; }
+</style>
+    </head>
+<body>
+
+<div style="position:absolute; top: 0px;">
+<div class="tab-title c1 p0">CSS is awesome</div>
+<div class="tab-title c1 p2">CSS is awesome</div>
+<div class="tab-title c1 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 100px;">
+<div class="tab-title c2 p0">CSS is awesome</div>
+<div class="tab-title c2 p2">CSS is awesome</div>
+<div class="tab-title c2 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 200px;">
+<div class="tab-title c3 p0">CSS is awesome</div>
+<div class="tab-title c3 p2">CSS is awesome</div>
+<div class="tab-title c3 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 300px;">
+<div class="tab-title c4 p0">CSS is awesome</div>
+<div class="tab-title c4 p2">CSS is awesome</div>
+<div class="tab-title c4 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 400px;">
+<div class="tab-title c5 p0">CSS is awesome</div>
+<div class="tab-title c5 p2">CSS is awesome</div>
+<div class="tab-title c5 p3">CSS is awesome</div>
+</div>
+
+<div class="col2" style="position:absolute; top: 0px; left:8em;">
+<div style="position:absolute; top: 0px;">
+<div class="tab-title c1 p0">CSS is awesome</div>
+<div class="tab-title c1 p2">CSS is awesome</div>
+<div class="tab-title c1 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 100px;">
+<div class="tab-title c2 p0">CSS is awesome</div>
+<div class="tab-title c2 p2">CSS is awesome</div>
+<div class="tab-title c2 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 200px;">
+<div class="tab-title c3 p0">CSS is awesome</div>
+<div class="tab-title c3 p2">CSS is awesome</div>
+<div class="tab-title c3 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 300px;">
+<div class="tab-title c4 p0">CSS is awesome</div>
+<div class="tab-title c4 p2">CSS is awesome</div>
+<div class="tab-title c4 p3">CSS is awesome</div>
+</div>
+
+<div style="position:absolute; top: 400px;">
+<div class="tab-title c5 p0">CSS is awesome</div>
+<div class="tab-title c5 p2">CSS is awesome</div>
+<div class="tab-title c5 p3">CSS is awesome</div>
+</div>
+</div>
+
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text-overflow/clipped-elements-ref.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html><html>
+<head><style>
+html,body {
+    color:black; background-color:white; font-size:16px; padding:0; margin:0;
+}
+.test { 
+  overflow: hidden; 
+  text-align:right;
+  width: 50px;
+  margin-bottom:1em;
+  height: 20px;
+  white-space:nowrap;
+/*border:1px solid red;width: 500px;*/
+}
+.rel { position:relative; text-align:left;}
+input,select,fieldset,textarea,hr,span {
+ border:1px solid black;
+ background: white;
+ color: black;
+ padding:0 40px;
+}
+iframe,img { width: 80px; height:10px; }
+select[size="4"],iframe,textarea,hr { height:10px; margin:0; }
+</style></head>
+<body>
+
+<div style="position:absolute; top:0; left:0;">
+  <div class="test">&#x2026;</div>
+  <div class="test">&#x2026;</div>
+  <div class="test"><fieldset style="display:block;"></fieldset></div>
+
+  <div class="test">&#x2026;</div>
+  <div class="test">&#x2026;</div>
+  <div class="test"><input type="button" style="display:list-item;"></div>
+  <div class="test"><input type="button" style="display:block;"></div>
+
+  <div class="test">&#x2026;</div>
+  <div class="test">&#x2026;</div>
+  <div class="test"><input type="text" style="display:block;"></div>
+
+  <div class="test">&#x2026;</div>
+  <div class="test">&#x2026;</div>
+  <div class="test"><textarea style="display:block;"></textarea></div>
+
+  <div class="test">&#x2026;</div>
+  <div class="test"><select size="1" style="display:block;"><option>&nbsp;<option>&nbsp;</select></div>
+
+  <div class="test">&#x2026;</div>
+  <div class="test"><select size="4" style="display:block;"><option>&nbsp;<option>&nbsp;</select></div>
+</div>
+
+<div style="position:absolute; top:0; left:100px;">
+  <div class="test">&#x2026;</div>
+  <div class="test"><iframe src="about:blank" style="display:block"></iframe></div>
+
+  <div class="test" style="text-align:left">&nbsp;&#x2026;</div>
+  <div class="test" style="text-align:left">&nbsp;&#x2026;</div>
+  <div class="test"><img style="display:block;" src="../image/big.png"></div>
+
+  <div class="test"><x style="display:inline-block; height:100px; width:100%; background:lime">&#x2026;</x></div>
+  <div class="test">&#x2026;</div>
+  <div class="test"><hr style="display:block;"></div>
+
+  <div class="test">&#x2026;</div>
+  <div class="test">&#x2026;</div>
+  <div class="test">&#x2026;</div>
+  <div class="test"><span style="display:list-item;"></span></div>
+  <div class="test"><span style="display:block;"></span></div>
+  <div class="test rel">1<span style="position:relative;"></span></div>
+  <div class="test rel">2<span style="position:absolute;"></span></div>
+  <div class="test rel">3</div>
+  <div class="test rel">4</div>
+  <div class="test"><span style="float:left"></span></div>
+  <div class="test"><span style="float:left; margin-left:-10px"></span></div>
+  <div class="test"><span style="float:right; margin-right:-10px"></span></div>
+</div>
+
+</body></html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text-overflow/clipped-elements.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html><html>
+<head><style>
+html,body {
+    color:black; background-color:white; font-size:16px; padding:0; margin:0;
+}
+.test { 
+  overflow: hidden; 
+  text-overflow: ellipsis;
+  width: 50px;
+  margin-bottom:1em;
+  height: 20px;
+  white-space:nowrap;
+/*border:1px solid red;width: 500px;*/
+}
+.rel { position:relative;}
+input,select,fieldset,textarea,hr,span {
+ border:1px solid black;
+ background: white;
+ color: black;
+ padding:0 40px;
+}
+iframe,img { width: 80px; height:10px; }
+select[size="4"],iframe,textarea,hr { height:10px; margin:0; }
+
+x {visibility:hidden;display:inline-block;margin-left:-10px;width:1000px;}
+</style></head>
+<body>
+
+<div style="position:absolute; top:0; left:0;">
+  <div class="test"><fieldset style="display:inline;"></fieldset></div>
+  <div class="test"><fieldset style="display:inline-block;"></fieldset></div>
+  <div class="test"><fieldset style="display:block;"></fieldset></div>
+
+  <div class="test"><input type="button"></div>
+  <div class="test"><input type="button" style="display:inline-block;"></div>
+  <div class="test"><input type="button" style="display:list-item;"></div>
+  <div class="test"><input type="button" style="display:block;"></div>
+
+  <div class="test"><input type="text"></div>
+  <div class="test"><input type="text" style="display:inline-block;"></div>
+  <div class="test"><input type="text" style="display:block;"></div>
+
+  <div class="test"><textarea></textarea></div>
+  <div class="test"><textarea style="display:inline-block;"></textarea></div>
+  <div class="test"><textarea style="display:block;"></textarea></div>
+
+  <div class="test"><select size="1" style=""><option>&nbsp;<option>&nbsp;</select></div>
+  <div class="test"><select size="1" style="display:block;"><option>&nbsp;<option>&nbsp;</select></div>
+
+  <div class="test"><select size="4" style=""><option>&nbsp;<option>&nbsp;</select></div>
+  <div class="test"><select size="4" style="display:block;"><option>&nbsp;<option>&nbsp;</select></div>
+</div>
+
+<div style="position:absolute; top:0; left:100px;">
+  <div class="test"><iframe src="about:blank" style=""></iframe></div>
+  <div class="test"><iframe src="about:blank" style="display:block"></iframe></div>
+
+  <div class="test">&nbsp;<img src="../image/big.png"></div>
+  <div class="test">&nbsp;<img style="display:inline-block;" src="../image/big.png"></div>
+  <div class="test"><img style="display:block;" src="../image/big.png"></div>
+
+  <div class="test"><hr style="display:inline;background:lime;vertical-align:top;padding-top:100px;padding-bottom:100px; border-width:0"></div>
+  <div class="test"><hr style="display:inline-block;vertical-align:top"></div>
+  <div class="test"><hr style="display:block;"></div>
+
+  <div class="test"><span style="border-width:0"></span></div>
+  <div class="test"><span style="display:inline-block;"></span></div>
+  <div class="test"><span style="display:inline-table;"></span></div>
+  <div class="test"><span style="display:list-item;"></span></div>
+  <div class="test"><span style="display:block;"></span></div>
+  <div class="test rel">1<span style="position:relative;"></span></div>
+  <div class="test rel">2<span style="position:absolute"></span></div>
+  <div class="test rel">3<span style="position:absolute; left:60px"></span></div>
+  <div class="test rel">4<x></x><span style="position:absolute;">abs4</span></div>
+  <div class="test"><span style="float:left"></span></div>
+  <div class="test"><span style="float:left; margin-left:-10px"></span></div>
+  <div class="test"><span style="float:right; margin-right:-10px"></span></div>
+</div>
+
+</body></html>
--- a/layout/reftests/text-overflow/reftest.list
+++ b/layout/reftests/text-overflow/reftest.list
@@ -9,8 +9,10 @@ HTTP(..) == false-marker-overlap.html fa
 HTTP(..) == visibility-hidden.html visibility-hidden-ref.html
 HTTP(..) == block-padding.html block-padding-ref.html
 HTTP(..) == quirks-decorations.html quirks-decorations-ref.html
 HTTP(..) == quirks-line-height.html quirks-line-height-ref.html
 HTTP(..) == standards-decorations.html standards-decorations-ref.html
 HTTP(..) == standards-line-height.html standards-line-height-ref.html
 HTTP(..) == selection.html selection-ref.html
 HTTP(..) == marker-shadow.html marker-shadow-ref.html
+== aligned-baseline.html aligned-baseline-ref.html
+skip-if(Android) == clipped-elements.html clipped-elements-ref.html
--- a/toolkit/components/telemetry/TelemetryHistograms.h
+++ b/toolkit/components/telemetry/TelemetryHistograms.h
@@ -34,30 +34,34 @@
  * 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 ***** */
 
 /**
  * This file lists Telemetry histograms collected by Firefox.  The format is
  *
- *    HISTOGRAM(id, minium, maximum, bucket count, histogram kind,
+ *    HISTOGRAM(id, minimum, maximum, bucket count, histogram kind,
  *              human-readable description for about:telemetry)
  *
  */
 
 HISTOGRAM(CYCLE_COLLECTOR, 1, 10000, 50, EXPONENTIAL, "Time spent on one cycle collection (ms)")
 HISTOGRAM(CYCLE_COLLECTOR_VISITED_REF_COUNTED, 1, 300000, 50, EXPONENTIAL, "Number of ref counted objects visited by the cycle collector")
 HISTOGRAM(CYCLE_COLLECTOR_VISITED_GCED, 1, 300000, 50, EXPONENTIAL, "Number of JS objects visited by the cycle collector")
 HISTOGRAM(CYCLE_COLLECTOR_COLLECTED, 1, 100000, 50, EXPONENTIAL, "Number of objects collected by the cycle collector")
 HISTOGRAM(TELEMETRY_PING, 1, 3000, 10, EXPONENTIAL, "Time taken to submit telemetry info (ms)")
 HISTOGRAM(TELEMETRY_SUCCESS, 0, 1, 2, BOOLEAN,  "Successful telemetry submission")
 HISTOGRAM(MEMORY_JS_GC_HEAP, 1024, 512 * 1024, 10, EXPONENTIAL, "Memory used by the garbage-collected JavaScript heap (KB)")
 HISTOGRAM(MEMORY_RESIDENT, 32 * 1024, 1024 * 1024, 10, EXPONENTIAL, "Resident memory size (KB)")
 HISTOGRAM(MEMORY_LAYOUT_ALL, 1024, 64 * 1024, 10, EXPONENTIAL, "Memory used by layout (KB)")
+HISTOGRAM(MEMORY_IMAGES_CONTENT_USED_UNCOMPRESSED, 1024, 1024 * 1024, 10, EXPONENTIAL, "Memory used for uncompressed, in-use content images (KB)")
+HISTOGRAM(MEMORY_HEAP_USED, 1024, 1024 * 1024, 10, EXPONENTIAL, "Heap memory used (KB)")
+// XXX: bug 660731 will enable this
+//HISTOGRAM(MEMORY_EXPLICIT, 1024, 1024 * 1024, 10, EXPONENTIAL, "Explicit memory allocations (KB)")
 #if defined(XP_WIN)
 HISTOGRAM(EARLY_GLUESTARTUP_READ_OPS, 1, 100, 12, LINEAR, "ProcessIoCounters.ReadOperationCount before glue startup")
 HISTOGRAM(EARLY_GLUESTARTUP_READ_TRANSFER, 1, 50 * 1024, 12, EXPONENTIAL, "ProcessIoCounters.ReadTransferCount before glue startup (KB)")
 HISTOGRAM(GLUESTARTUP_READ_OPS, 1, 100, 12, LINEAR, "ProcessIoCounters.ReadOperationCount after glue startup")
 HISTOGRAM(GLUESTARTUP_READ_TRANSFER, 1, 50 * 1024, 12, EXPONENTIAL, "ProcessIoCounters.ReadTransferCount after glue startup (KB)")
 #elif defined(XP_UNIX)
 HISTOGRAM(EARLY_GLUESTARTUP_HARD_FAULTS, 1, 100, 12, LINEAR, "Hard faults count before glue startup")
 HISTOGRAM(GLUESTARTUP_HARD_FAULTS, 1, 500, 12, EXPONENTIAL, "Hard faults count after glue startup")
--- a/toolkit/components/telemetry/TelemetryPing.js
+++ b/toolkit/components/telemetry/TelemetryPing.js
@@ -52,16 +52,19 @@ const PREF_ENABLED = "toolkit.telemetry.
 const TELEMETRY_INTERVAL = 60;
 // Delay before intializing telemetry (ms)
 const TELEMETRY_DELAY = 60000;
 // about:memory values to turn into histograms
 const MEM_HISTOGRAMS = {
   "js-gc-heap": "MEMORY_JS_GC_HEAP",
   "resident": "MEMORY_RESIDENT",
   "explicit/layout/all": "MEMORY_LAYOUT_ALL",
+  "explicit/images/content/used/uncompressed":
+    "MEMORY_IMAGES_CONTENT_USED_UNCOMPRESSED",
+  "heap-used": "MEMORY_HEAP_USED",
   "hard-page-faults": "HARD_PAGE_FAULTS"
 };
 
 XPCOMUtils.defineLazyGetter(this, "Telemetry", function () {
   return Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
 });
 
 /**
@@ -186,31 +189,39 @@ function getSimpleMeasurements() {
 
 function TelemetryPing() {}
 
 TelemetryPing.prototype = {
   _histograms: {},
   _initialized: false,
   _prevValues: {},
 
+  addValue: function addValue(name, id, val) {
+    let h = this._histograms[name];
+    if (!h) {
+      h = Telemetry.getHistogramById(id);
+      this._histograms[name] = h;
+    }
+    h.add(val);
+  },
+
   /**
    * Pull values from about:memory into corresponding histograms
    */
   gatherMemory: function gatherMemory() {
     let mgr;
     try {
       mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
             getService(Ci.nsIMemoryReporterManager);
     } catch (e) {
       // OK to skip memory reporters in xpcshell
       return;
     }
 
     let e = mgr.enumerateReporters();
-    let memReporters = {};
     while (e.hasMoreElements()) {
       let mr = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
       let id = MEM_HISTOGRAMS[mr.path];
       if (!id || mr.amount == -1) {
         continue;
       }
 
       let val;
@@ -233,25 +244,21 @@ TelemetryPing.prototype = {
 
         val = curVal - this._prevValues[mr.path];
         this._prevValues[mr.path] = curVal;
       }
       else {
         NS_ASSERT(false, "Can't handle memory reporter with units " + mr.units);
         continue;
       }
-
-      let h = this._histograms[mr.path];
-      if (!h) {
-        h = Telemetry.getHistogramById(id);
-        this._histograms[mr.path] = h;
-      }
-      h.add(val);
+      this.addValue(mr.path, id, val);
     }
-    return memReporters;
+    // XXX: bug 660731 will enable this
+    // "explicit" is found differently.
+    //this.addValue("explicit", "MEMORY_EXPLICIT", Math.floor(mgr.explicit / 1024));
   },
   
   /**
    * Send data to the server. Record success/send-time in histograms
    */
   send: function send(reason, server) {
     // populate histograms one last time
     this.gatherMemory();