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 idunknown
push userunknown
push dateunknown
reviewersjmathies
bugs596451
milestone2.0b8pre
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.