Bug 596451 part D - Hook up asynchronous plugin painting on Windows. This part allows opaque plugins to paint correctly. r=jmathies
authorBenjamin Smedberg <benjamin@smedbergs.us>
Mon, 25 Oct 2010 13:57:13 -0400
changeset 57209 94324cad0457d50276216fec9cd21bdbc191580e
parent 57208 da433c7320abe71c4d2d51bffd6a213ef61e3ac4
child 57210 866e9298ee159c57b2a434b199b39d5a811cc061
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmathies
bugs596451
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 596451 part D - Hook up asynchronous plugin painting on Windows. This part allows opaque plugins to paint correctly. r=jmathies
dom/plugins/PPluginInstance.ipdl
dom/plugins/PluginInstanceChild.cpp
dom/plugins/PluginInstanceParent.cpp
gfx/ipc/Makefile.in
gfx/ipc/SharedDIBSurface.cpp
gfx/ipc/SharedDIBSurface.h
gfx/ipc/SharedDIBWin.cpp
gfx/ipc/SharedDIBWin.h
gfx/thebes/gfxImageSurface.cpp
gfx/thebes/gfxImageSurface.h
gfx/thebes/gfxSharedImageSurface.cpp
modules/plugin/base/src/nsNPAPIPluginInstance.cpp
--- a/dom/plugins/PPluginInstance.ipdl
+++ b/dom/plugins/PPluginInstance.ipdl
@@ -50,29 +50,36 @@ using NPRemoteWindow;
 using NPRemoteEvent;
 using NPRect;
 using NPNURLVariable;
 using NPCoordinateSpace;
 using mozilla::plugins::NativeWindowHandle;
 using mozilla::gfxSurfaceType;
 using gfxIntSize;
 using mozilla::null_t;
+using base::SharedMemoryHandle;
 
 namespace mozilla {
 namespace plugins {
 
 struct SurfaceDescriptorX11 {
   int XID;
   int xrenderPictID;
   gfxIntSize size;
 };
 
+struct SurfaceDescriptorWin {
+  SharedMemoryHandle handle;
+  gfxIntSize size;
+};
+
 union SurfaceDescriptor {
   Shmem;
   SurfaceDescriptorX11;
+  SurfaceDescriptorWin;
   // Descriptor can be null here in case
   // 1) of first Show call (prevSurface is null)
   // 2) when child is going to destroy
   //    and it just want to grab prevSurface
   //     back without giving new surface
   null_t;
 };
 
--- a/dom/plugins/PluginInstanceChild.cpp
+++ b/dom/plugins/PluginInstanceChild.cpp
@@ -43,16 +43,21 @@
 #include "PluginStreamChild.h"
 #include "StreamNotifyChild.h"
 #include "PluginProcessChild.h"
 #include "gfxASurface.h"
 #include "gfxContext.h"
 #ifdef MOZ_X11
 #include "gfxXlibSurface.h"
 #endif
+#ifdef XP_WIN
+#include "mozilla/gfx/SharedDIBSurface.h"
+
+using mozilla::gfx::SharedDIBSurface;
+#endif
 #include "gfxSharedImageSurface.h"
 #include "gfxUtils.h"
 #include "gfxAlphaRecovery.h"
 
 #include "mozilla/ipc/SyncChannel.h"
 
 using mozilla::ipc::ProcessChild;
 using namespace mozilla::plugins;
@@ -1415,17 +1420,17 @@ PluginInstanceChild::SharedSurfaceSetWin
     if (!aWindow.surfaceHandle) {
         if (!mSharedSurfaceDib.IsValid()) {
             return false;
         }
     }
     else {
         // Attach to the new shared surface parent handed us.
         if (NS_FAILED(mSharedSurfaceDib.Attach((SharedDIB::Handle)aWindow.surfaceHandle,
-                                               aWindow.width, aWindow.height, 32)))
+                                               aWindow.width, aWindow.height)))
           return false;
         // Free any alpha extraction resources if needed. This will be reset
         // the next time it's used.
         AlphaExtractCacheRelease();
     }
       
     // NPRemoteWindow's origin is the origin of our shared dib.
     mWindow.x      = 0;
@@ -2032,16 +2037,22 @@ PluginInstanceChild::RecvAsyncSetWindow(
     AssertPluginThread();
 
     mWindow.window = reinterpret_cast<void*>(aWindow.window);
     if (mWindow.width != aWindow.width || mWindow.height != aWindow.height) {
         mCurrentSurface = nsnull;
         mHelperSurface = nsnull;
         mPendingForcePaint = true;
     }
+
+#ifdef XP_WIN
+    mPluginOffset.x = aWindow.x;
+    mPluginOffset.y = aWindow.y;
+#endif
+
     mWindow.x = aWindow.x;
     mWindow.y = aWindow.y;
     mWindow.width = aWindow.width;
     mWindow.height = aWindow.height;
     mWindow.clipRect = aWindow.clipRect;
     mWindow.type = aWindow.type;
 
     mLayersRendering = true;
@@ -2093,24 +2104,36 @@ PluginInstanceChild::CreateOptSurface(vo
         mCurrentSurface =
             gfxXlibSurface::Create(screen, xfmt,
                                    gfxIntSize(mWindow.width,
                                               mWindow.height));
         return mCurrentSurface != nsnull;
     }
 #endif
 
+#ifdef XP_WIN
+    if (mSurfaceType == gfxASurface::SurfaceTypeWin32 ||
+        mSurfaceType == gfxASurface::SurfaceTypeD2D) {
+
+        SharedDIBSurface* s = new SharedDIBSurface();
+        if (!s->Create(reinterpret_cast<HDC>(mWindow.window),
+                       mWindow.width, mWindow.height))
+            return false;
+
+        mCurrentSurface = s;
+        return true;
+    }
+
+    NS_RUNTIMEABORT("Shared-memory drawing not expected on Windows.");
+#endif
+
     // Make common shmem implementation working for any platform
     mCurrentSurface = new gfxSharedImageSurface();
-    if (NS_FAILED(static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->
-        Init(this, gfxIntSize(mWindow.width, mWindow.height), format))) {
-        return false;
-    }
-
-    return true;
+    return static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->
+        Init(this, gfxIntSize(mWindow.width, mWindow.height), format);
 }
 
 bool
 PluginInstanceChild::MaybeCreatePlatformHelperSurface(void)
 {
     if (!mCurrentSurface) {
         NS_ERROR("Cannot create helper surface without mCurrentSurface");
         return false;
@@ -2229,18 +2252,34 @@ PluginInstanceChild::UpdateWindowAttribu
             mWsInfo.depth != gfxUtils::ImageFormatToDepth(img->Format()) ||
             mWsInfo.colormap) {
             mWindow.window = nsnull;
             mWsInfo.depth = gfxUtils::ImageFormatToDepth(img->Format());
             mWsInfo.colormap = 0;
             needWindowUpdate = PR_TRUE;
         }
     }
-#endif
-#endif
+#endif // MAEMO
+#endif // MOZ_X11
+#ifdef XP_WIN
+    HDC dc = NULL;
+
+    if (curSurface) {
+        NS_ASSERTION(SharedDIBSurface::IsSharedDIBSurface(curSurface),
+                     "Expected (SharedDIB) image surface.");
+
+        SharedDIBSurface* dibsurf = static_cast<SharedDIBSurface*>(curSurface.get());
+        dc = dibsurf->GetHDC();
+    }
+    if (mWindow.window != dc) {
+        mWindow.window = dc;
+        needWindowUpdate = true;
+    }
+#endif // XP_WIN
+
     if (!needWindowUpdate) {
         return;
     }
 
     // The clip rect is relative to drawable top-left.
     nsIntRect clipRect;
     mWindow.x = mWindow.y = 0;
     clipRect.SetRect(mWindow.x, mWindow.y, mWindow.width, mWindow.height);
@@ -2249,16 +2288,35 @@ PluginInstanceChild::UpdateWindowAttribu
 
     NPRect newClipRect;
     newClipRect.left = clipRect.x;
     newClipRect.top = clipRect.y;
     newClipRect.right = clipRect.XMost();
     newClipRect.bottom = clipRect.YMost();
     mWindow.clipRect = newClipRect;
 
+#ifdef XP_WIN
+    // Windowless plugins on Windows need a WM_WINDOWPOSCHANGED event to update
+    // their location... or at least Flash does: Silverlight uses the
+    // window.x/y passed to NPP_SetWindow
+
+    if (mPluginIface->event) {
+        WINDOWPOS winpos = {
+            0, 0,
+            mPluginOffset.x, mPluginOffset.y,
+            mWindow.width, mWindow.height
+        };
+        NPEvent pluginEvent = {
+            WM_WINDOWPOSCHANGED, 0,
+            (LPARAM) &winpos
+        };
+        mPluginIface->event(&mData, &pluginEvent);
+    }
+#endif
+
     if (mPluginIface->setwindow) {
         mPluginIface->setwindow(&mData, &mWindow);
     }
 
     return;
 }
 
 void
@@ -2324,17 +2382,41 @@ PluginInstanceChild::PaintRectToPlatform
     exposeEvent.count = 0;
     // information not set:
     exposeEvent.serial = 0;
     exposeEvent.send_event = False;
     exposeEvent.major_code = 0;
     exposeEvent.minor_code = 0;
     mPluginIface->event(&mData, reinterpret_cast<void*>(&exposeEvent));
     mPendingPluginCall = false;
+    return;
 #endif
+
+#ifdef XP_WIN
+    NS_ASSERTION(SharedDIBSurface::IsSharedDIBSurface(aSurface),
+                 "Expected (SharedDIB) image surface.");
+
+    mPendingPluginCall = true;
+    RECT rect = {
+        aRect.x,
+        aRect.y,
+        aRect.x + aRect.width,
+        aRect.y + aRect.height
+    };
+    NPEvent paintEvent = {
+        WM_PAINT,
+        uintptr_t(mWindow.window),
+        uintptr_t(&rect)
+    };
+    mPluginIface->event(&mData, reinterpret_cast<void*>(&paintEvent));
+    mPendingPluginCall = false;
+    return;
+#endif
+
+    NS_RUNTIMEABORT("Surface type not implemented.");
 }
 
 void
 PluginInstanceChild::PaintRectToSurface(const nsIntRect& aRect,
                                         gfxASurface* aSurface,
                                         const gfxRGBA& aColor)
 {
     // Render using temporary X surface, with copy to image surface
@@ -2488,16 +2570,25 @@ PluginInstanceChild::ShowPluginFrame()
         gfxXlibSurface *xsurf = static_cast<gfxXlibSurface*>(mCurrentSurface.get());
         currSurf = SurfaceDescriptorX11(xsurf->XDrawable(), xsurf->XRenderFormat()->id,
                                         mCurrentSurface->GetSize());
         // Need to sync all pending x-paint requests
         // before giving drawable to another process
         XSync(mWsInfo.display, False);
     } else
 #endif
+#ifdef XP_WIN
+    if (SharedDIBSurface::IsSharedDIBSurface(mCurrentSurface)) {
+        base::SharedMemoryHandle handle = NULL;
+        SharedDIBSurface* s = static_cast<SharedDIBSurface*>(mCurrentSurface.get());
+        s->ShareToProcess(PluginModuleChild::current()->OtherProcess(), &handle);
+        currSurf = SurfaceDescriptorWin(handle, mCurrentSurface->GetSize());
+        s->Flush();
+    } else
+#endif
     if (gfxSharedImageSurface::IsSharedImage(mCurrentSurface)) {
         currSurf = static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->GetShmem();
     } else {
         NS_RUNTIMEABORT("Surface type is not remotable");
         return false;
     }
 
     // Unused, except to possibly return a shmem to us
--- a/dom/plugins/PluginInstanceParent.cpp
+++ b/dom/plugins/PluginInstanceParent.cpp
@@ -54,16 +54,19 @@
 #include "gfxXlibSurface.h"
 #endif
 #include "gfxContext.h"
 #include "gfxColor.h"
 #include "gfxUtils.h"
 
 #if defined(OS_WIN)
 #include <windowsx.h>
+#include "mozilla/gfx/SharedDIBSurface.h"
+
+using mozilla::gfx::SharedDIBSurface;
 
 // Plugin focus event for widget.
 extern const PRUnichar* kOOPPPluginFocusEventId;
 UINT gOOPPPluginFocusEvent =
     RegisterWindowMessage(kOOPPPluginFocusEventId);
 extern const PRUnichar* kFlashFullscreenClass;
 UINT gOOPPSpinNativeLoopEvent =
     RegisterWindowMessage(L"SyncChannel Spin Inner Loop Message");
@@ -491,16 +494,24 @@ PluginInstanceParent::RecvShow(const NPR
         pf.id = xdesc.xrenderPictID();
         XRenderPictFormat *incFormat =
             XRenderFindFormat(DefaultXDisplay(), PictFormatID, &pf, 0);
         surface =
             new gfxXlibSurface(DefaultScreenOfDisplay(DefaultXDisplay()),
                                xdesc.XID(), incFormat, xdesc.size());
     }
 #endif
+#ifdef XP_WIN
+    else if (newSurface.type() == SurfaceDescriptor::TSurfaceDescriptorWin) {
+        SurfaceDescriptorWin windesc = newSurface.get_SurfaceDescriptorWin();
+        SharedDIBSurface* dibsurf = new SharedDIBSurface();
+        if (dibsurf->Attach(windesc.handle(), windesc.size().width, windesc.size().height))
+            surface = dibsurf;
+    }
+#endif
 
     mSentPaintNotification = PR_FALSE;
 
 #ifdef MOZ_X11
     if (mFrontSurface &&
         mFrontSurface->GetType() == gfxASurface::SurfaceTypeXlib)
         XSync(DefaultXDisplay(), False);
 #endif
@@ -1327,17 +1338,17 @@ PluginInstanceParent::SharedSurfaceSetWi
       // ok to paint
       aRemoteWindow.surfaceHandle = 0;
       return true;
     }
 
     // allocate a new shared surface
     SharedSurfaceRelease();
     if (NS_FAILED(mSharedSurfaceDib.Create(reinterpret_cast<HDC>(aWindow->window),
-                                           newPort.width, newPort.height, 32)))
+                                           newPort.width, newPort.height)))
       return false;
 
     // save the new shared surface size we just allocated
     mSharedSize = newPort;
 
     base::SharedMemoryHandle handle;
     if (NS_FAILED(mSharedSurfaceDib.ShareToProcess(mParent->ChildProcessHandle(), &handle)))
       return false;
--- a/gfx/ipc/Makefile.in
+++ b/gfx/ipc/Makefile.in
@@ -56,18 +56,27 @@ EXPORTS_mozilla/gfx = \
         SharedDIB.h   \
         $(NULL)
 
 CPPSRCS = SharedDIB.cpp
 
 ENABLE_CXX_EXCEPTIONS	= 1
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
-CPPSRCS += SharedDIBWin.cpp
-EXPORTS_mozilla/gfx += SharedDIBWin.h
+EXPORTS_mozilla/gfx += \
+  SharedDIBWin.h \
+  SharedDIBSurface.h \
+  $(NULL)
+
+CPPSRCS += \
+  SharedDIBWin.cpp \
+  SharedDIBSurface.cpp \
+  $(NULL)
 endif
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 endif
 
 include $(topsrcdir)/config/rules.mk
+
+CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS)
new file mode 100644
--- /dev/null
+++ b/gfx/ipc/SharedDIBSurface.cpp
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Firefox.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation <http://www.mozilla.org>.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 "SharedDIBSurface.h"
+
+#include "cairo.h"
+
+namespace mozilla {
+namespace gfx {
+
+static const cairo_user_data_key_t SHAREDDIB_KEY;
+
+static const long kBytesPerPixel = 4;
+
+bool
+SharedDIBSurface::Create(HDC adc, PRUint32 aWidth, PRUint32 aHeight)
+{
+  nsresult rv = mSharedDIB.Create(adc, aWidth, aHeight);
+  if (NS_FAILED(rv) || !mSharedDIB.IsValid())
+    return false;
+
+  InitSurface(aWidth, aHeight);
+  return true;
+}
+
+bool
+SharedDIBSurface::Attach(Handle aHandle, PRUint32 aWidth, PRUint32 aHeight)
+{
+  nsresult rv = mSharedDIB.Attach(aHandle, aWidth, aHeight);
+  if (NS_FAILED(rv) || !mSharedDIB.IsValid())
+    return false;
+
+  InitSurface(aWidth, aHeight);
+  return true;
+}
+
+void
+SharedDIBSurface::InitSurface(PRUint32 aWidth, PRUint32 aHeight)
+{
+  // Windows DIBs are bottom-to-top by default, so the stride is negative
+  // and the data is the beginning of the last row.
+  long stride = -long(aWidth * kBytesPerPixel);
+  unsigned char* data = reinterpret_cast<unsigned char*>(mSharedDIB.GetBits());
+  data -= (aHeight - 1) * stride;
+
+  gfxImageSurface::InitWithData(data, gfxIntSize(aWidth, aHeight),
+                                stride, ImageFormatRGB24);
+
+  cairo_surface_set_user_data(mSurface, &SHAREDDIB_KEY, this, NULL);
+}
+
+bool
+SharedDIBSurface::IsSharedDIBSurface(gfxASurface* aSurface)
+{
+  return aSurface &&
+    aSurface->GetType() == gfxASurface::SurfaceTypeImage &&
+    aSurface->GetData(&SHAREDDIB_KEY);
+}
+
+} // namespace gfx
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/ipc/SharedDIBSurface.h
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Firefox.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation <http://www.mozilla.org>.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 mozilla_gfx_SharedDIBSurface_h
+#define mozilla_gfx_SharedDIBSurface_h
+
+#include "gfxImageSurface.h"
+#include "SharedDIBWin.h"
+
+#include <windows.h>
+
+namespace mozilla {
+namespace gfx {
+
+/**
+ * A SharedDIBSurface owns an underlying SharedDIBWin.
+ */
+class SharedDIBSurface : public gfxImageSurface
+{
+public:
+  typedef base::SharedMemoryHandle Handle;
+
+  SharedDIBSurface() { }
+  ~SharedDIBSurface() { }
+
+  /**
+   * Create this image surface backed by shared memory.
+   */
+  bool Create(HDC adc, PRUint32 aWidth, PRUint32 aHeight);
+
+  /**
+   * Attach this surface to shared memory from another process.
+   */
+  bool Attach(Handle aHandle, PRUint32 aWidth, PRUint32 aHeight);
+
+  /**
+   * After drawing to a surface via GDI, GDI must be flushed before the bitmap
+   * is valid.
+   */
+  void Flush() { ::GdiFlush(); }
+
+  HDC GetHDC() { return mSharedDIB.GetHDC(); }
+
+  nsresult ShareToProcess(base::ProcessHandle aChildProcess, Handle* aChildHandle) {
+    return mSharedDIB.ShareToProcess(aChildProcess, aChildHandle);
+  }
+
+  static bool IsSharedDIBSurface(gfxASurface* aSurface);
+
+private:
+  SharedDIBWin mSharedDIB;
+
+  void InitSurface(PRUint32 aWidth, PRUint32 aHeight);
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif // mozilla_gfx_SharedDIBSurface_h
--- a/gfx/ipc/SharedDIBWin.cpp
+++ b/gfx/ipc/SharedDIBWin.cpp
@@ -38,16 +38,18 @@
 
 #include "SharedDIBWin.h"
 #include "nsMathUtils.h"
 #include "nsDebug.h"
 
 namespace mozilla {
 namespace gfx {
 
+static const PRUint32 kBytesPerPixel = 4;
+
 SharedDIBWin::SharedDIBWin() :
     mSharedHdc(nsnull)
   , mSharedBmp(nsnull)
   , mOldObj(nsnull)
 {
 }
 
 SharedDIBWin::~SharedDIBWin()
@@ -71,86 +73,82 @@ SharedDIBWin::Close()
   mOldObj = mSharedBmp = NULL;
 
   SharedDIB::Close();
 
   return NS_OK;
 }
 
 nsresult
-SharedDIBWin::Create(HDC aHdc, PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth)
+SharedDIBWin::Create(HDC aHdc, PRUint32 aWidth, PRUint32 aHeight)
 {
   Close();
 
   // create the offscreen shared dib
   BITMAPINFOHEADER bmih;
-  PRUint32 size = SetupBitmapHeader(aWidth, aHeight, aDepth, &bmih);
+  PRUint32 size = SetupBitmapHeader(aWidth, aHeight, &bmih);
 
   nsresult rv = SharedDIB::Create(size);
   if (NS_FAILED(rv))
     return rv;
 
   if (NS_FAILED(SetupSurface(aHdc, &bmih))) {
     Close();
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult
-SharedDIBWin::Attach(Handle aHandle, PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth)
+SharedDIBWin::Attach(Handle aHandle, PRUint32 aWidth, PRUint32 aHeight)
 {
   Close();
 
   BITMAPINFOHEADER bmih;
-  SetupBitmapHeader(aWidth, aHeight, aDepth, &bmih);
+  SetupBitmapHeader(aWidth, aHeight, &bmih);
 
   nsresult rv = SharedDIB::Attach(aHandle, 0);
   if (NS_FAILED(rv))
     return rv;
 
   if (NS_FAILED(SetupSurface(NULL, &bmih))) {
     Close();
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 PRUint32
-SharedDIBWin::SetupBitmapHeader(PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth, BITMAPINFOHEADER *aHeader)
+SharedDIBWin::SetupBitmapHeader(PRUint32 aWidth, PRUint32 aHeight, BITMAPINFOHEADER *aHeader)
 {
-  NS_ASSERTION(aDepth == 32, "Invalid SharedDIBWin depth");
-
   memset((void*)aHeader, 0, sizeof(BITMAPINFOHEADER));
   aHeader->biSize        = sizeof(BITMAPINFOHEADER);
   aHeader->biWidth       = aWidth;
   aHeader->biHeight      = aHeight;
   aHeader->biPlanes      = 1;
-  aHeader->biBitCount    = aDepth;
+  aHeader->biBitCount    = 32;
   aHeader->biCompression = BI_RGB;
 
-  // deal better with varying depths. (we currently only ask for 32 bit)
-  return (sizeof(BITMAPINFOHEADER) + (aHeader->biHeight * aHeader->biWidth * (PRUint32)NS_ceil(aDepth/8)));
+  return (sizeof(BITMAPINFOHEADER) + (aHeader->biHeight * aHeader->biWidth * kBytesPerPixel));
 }
 
 nsresult
 SharedDIBWin::SetupSurface(HDC aHdc, BITMAPINFOHEADER *aHdr)
 {
   mSharedHdc = ::CreateCompatibleDC(aHdc);
 
   if (!mSharedHdc)
     return NS_ERROR_FAILURE;
 
-  void* ppvBits = nsnull;
   mSharedBmp = ::CreateDIBSection(mSharedHdc,
                                   (BITMAPINFO*)aHdr,
                                   DIB_RGB_COLORS,
-                                  (void**)&ppvBits,
+                                  &mBitmapBits,
                                   mShMem->handle(),
                                   (unsigned long)sizeof(BITMAPINFOHEADER));
   if (!mSharedBmp)
     return NS_ERROR_FAILURE;
 
   mOldObj = SelectObject(mSharedHdc, mSharedBmp);
 
   return NS_OK;
--- a/gfx/ipc/SharedDIBWin.h
+++ b/gfx/ipc/SharedDIBWin.h
@@ -49,34 +49,38 @@ namespace gfx {
 class SharedDIBWin : public SharedDIB
 {
 public:
   SharedDIBWin();
   ~SharedDIBWin();
 
   // Allocate a new win32 dib section compatible with an hdc. The dib will
   // be selected into the hdc on return.
-  nsresult Create(HDC aHdc, PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth);
+  nsresult Create(HDC aHdc, PRUint32 aWidth, PRUint32 aHeight);
 
   // Wrap a dib section around an existing shared memory object. aHandle should
   // point to a section large enough for the dib's memory, otherwise this call
   // will fail.
-  nsresult Attach(Handle aHandle, PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth);
+  nsresult Attach(Handle aHandle, PRUint32 aWidth, PRUint32 aHeight);
 
   // Destroy or release resources associated with this dib.
   nsresult Close();
 
   // Return the HDC of the shared dib.
   HDC GetHDC() { return mSharedHdc; }
 
+  // Return the bitmap bits.
+  void* GetBits() { return mBitmapBits; }
+
 private:
   HDC                 mSharedHdc;
   HBITMAP             mSharedBmp;
   HGDIOBJ             mOldObj;
+  void*               mBitmapBits;
 
-  PRUint32 SetupBitmapHeader(PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth, BITMAPINFOHEADER *aHeader);
+  PRUint32 SetupBitmapHeader(PRUint32 aWidth, PRUint32 aHeight, BITMAPINFOHEADER *aHeader);
   nsresult SetupSurface(HDC aHdc, BITMAPINFOHEADER *aHdr);
 };
 
 } // gfx
 } // mozilla
 
 #endif
--- a/gfx/thebes/gfxImageSurface.cpp
+++ b/gfx/thebes/gfxImageSurface.cpp
@@ -59,22 +59,30 @@ gfxImageSurface::InitFromSurface(cairo_s
     mOwnsData = PR_FALSE;
     mStride = cairo_image_surface_get_stride(csurf);
 
     Init(csurf, PR_TRUE);
 }
 
 gfxImageSurface::gfxImageSurface(unsigned char *aData, const gfxIntSize& aSize,
                                  long aStride, gfxImageFormat aFormat)
-  : mSize(aSize)
-  , mOwnsData(PR_FALSE)
-  , mData(aData)
-  , mFormat(aFormat)
-  , mStride(aStride)
 {
+    InitWithData(aData, aSize, aStride, aFormat);
+}
+
+void
+gfxImageSurface::InitWithData(unsigned char *aData, const gfxIntSize& aSize,
+                              long aStride, gfxImageFormat aFormat)
+{
+    mSize = aSize;
+    mOwnsData = PR_FALSE;
+    mData = aData;
+    mFormat = aFormat;
+    mStride = aStride;
+
     if (!CheckSurfaceSize(aSize))
         return;
 
     cairo_surface_t *surface =
         cairo_image_surface_create_for_data((unsigned char*)mData,
                                             (cairo_format_t)mFormat,
                                             mSize.width,
                                             mSize.height,
--- a/gfx/thebes/gfxImageSurface.h
+++ b/gfx/thebes/gfxImageSurface.h
@@ -103,16 +103,18 @@ public:
 
     /* return new Subimage with pointing to original image starting from aRect.pos
      * and size of aRect.size. New subimage keeping current image reference
      */
     already_AddRefed<gfxSubimageSurface> GetSubimage(const gfxRect& aRect);
 
 protected:
     gfxImageSurface();
+    void InitWithData(unsigned char *aData, const gfxIntSize& aSize,
+                      long aStride, gfxImageFormat aFormat);
     void InitFromSurface(cairo_surface_t *csurf);
     long ComputeStride() const;
 
     gfxIntSize mSize;
     PRBool mOwnsData;
     unsigned char *mData;
     gfxImageFormat mFormat;
     long mStride;
--- a/gfx/thebes/gfxSharedImageSurface.cpp
+++ b/gfx/thebes/gfxSharedImageSurface.cpp
@@ -39,17 +39,17 @@
 #include "base/basictypes.h"
 #include "gfxSharedImageSurface.h"
 #include "cairo.h"
 
 #define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3)
 
 using mozilla::ipc::SharedMemory;
 
-static cairo_user_data_key_t SHM_KEY;
+static const cairo_user_data_key_t SHM_KEY;
 
 typedef struct _SharedImageInfo
 {
     PRInt32 width;
     PRInt32 height;
     PRInt32 format;
 } SharedImageInfo;
 
--- a/modules/plugin/base/src/nsNPAPIPluginInstance.cpp
+++ b/modules/plugin/base/src/nsNPAPIPluginInstance.cpp
@@ -80,17 +80,17 @@ nsNPAPIPluginInstance::nsNPAPIPluginInst
     mTransparent(PR_FALSE),
     mCached(PR_FALSE),
     mWantsAllNetworkStreams(PR_FALSE),
     mInPluginInitCall(PR_FALSE),
     mPlugin(plugin),
     mMIMEType(nsnull),
     mOwner(nsnull),
     mCurrentPluginEvent(nsnull),
-#ifdef MOZ_X11
+#if defined(MOZ_X11) || defined(XP_WIN)
     mUsePluginLayersPref(PR_TRUE)
 #else
     mUsePluginLayersPref(PR_FALSE)
 #endif
 {
   NS_ASSERTION(mPlugin != NULL, "Plugin is required when creating an instance.");
 
   // Initialize the NPP structure.