Bug 583053 - Corruption issues when running rdio because windows double-pass rendering events don't win the RPC race, r=bent
authorBenjamin Smedberg <benjamin@smedbergs.us>
Mon, 16 Aug 2010 10:10:25 -0400
changeset 50668 f52342744bda11892aecff44ce6fc9368e97da3b
parent 50667 33ff08c153d410659d511473d5c5115e5461b64f
child 50669 d233936ab3143cd28294c2952960522afcb79ed6
push idunknown
push userunknown
push dateunknown
reviewersbent
bugs583053
milestone2.0b4pre
Bug 583053 - Corruption issues when running rdio because windows double-pass rendering events don't win the RPC race, r=bent
dom/plugins/PluginInstanceChild.cpp
dom/plugins/PluginInstanceChild.h
dom/plugins/PluginInstanceParent.cpp
dom/plugins/PluginMessageUtils.cpp
dom/plugins/PluginMessageUtils.h
layout/generic/Makefile.in
layout/generic/nsObjectFrame.cpp
layout/generic/nsObjectFrame.h
--- a/dom/plugins/PluginInstanceChild.cpp
+++ b/dom/plugins/PluginInstanceChild.cpp
@@ -81,18 +81,16 @@ using mozilla::gfx::SharedDIB;
 #include <windows.h>
 #include <windowsx.h>
 
 // Flash WM_USER message delay time for PostDelayedTask. Borrowed
 // from Chromium's web plugin delegate src. See 'flash msg throttling
 // helpers' section for details.
 const int kFlashWMUSERMessageThrottleDelayMs = 5;
 
-#define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg")
-
 #elif defined(XP_MACOSX)
 #include <ApplicationServices/ApplicationServices.h>
 #endif // defined(XP_MACOSX)
 
 PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
                                          const nsCString& aMimeType)
     : mPluginIface(aPluginIface)
     , mQuirks(0)
@@ -120,17 +118,16 @@ PluginInstanceChild::PluginInstanceChild
     mData.pdata = nsnull;
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     mWindow.ws_info = &mWsInfo;
     memset(&mWsInfo, 0, sizeof(mWsInfo));
     mWsInfo.display = DefaultXDisplay();
 #endif // MOZ_X11 && XP_UNIX && !XP_MACOSX
 #if defined(OS_WIN)
     memset(&mAlphaExtract, 0, sizeof(mAlphaExtract));
-    mAlphaExtract.doublePassEvent = ::RegisterWindowMessage(NS_OOPP_DOUBLEPASS_MSGID);
 #endif // OS_WIN
     InitQuirksModes(aMimeType);
 #if defined(OS_WIN)
     InitPopupMenuHook();
 #endif // OS_WIN
 }
 
 PluginInstanceChild::~PluginInstanceChild()
@@ -560,17 +557,17 @@ PluginInstanceChild::AnswerNPP_HandleEve
         return true;
 
     // Painting for win32. SharedSurfacePaint handles everything.
     if (mWindow.type == NPWindowTypeDrawable) {
        if (evcopy.event == WM_PAINT) {
           *handled = SharedSurfacePaint(evcopy);
           return true;
        }
-       else if (evcopy.event == mAlphaExtract.doublePassEvent) {
+       else if (DoublePassRenderingEvent() == evcopy.event) {
             // We'll render to mSharedSurfaceDib first, then render to a cached bitmap
             // we store locally. The two passes are for alpha extraction, so the second
             // pass must be to a flat white surface in order for things to work.
             mAlphaExtract.doublePass = RENDER_BACK_ONE;
             *handled = true;
             return true;
        }
     }
--- a/dom/plugins/PluginInstanceChild.h
+++ b/dom/plugins/PluginInstanceChild.h
@@ -347,17 +347,16 @@ private:
 private:
     enum {
       RENDER_NATIVE,
       RENDER_BACK_ONE,
       RENDER_BACK_TWO 
     };
     gfx::SharedDIBWin mSharedSurfaceDib;
     struct {
-      PRUint32        doublePassEvent;
       PRUint16        doublePass;
       HDC             hdc;
       HBITMAP         bmp;
     } mAlphaExtract;
 #endif // defined(OS_WIN)
 #if defined(OS_MACOSX)
 private:
     CGColorSpaceRef       mShColorSpace;
--- a/dom/plugins/PluginInstanceParent.cpp
+++ b/dom/plugins/PluginInstanceParent.cpp
@@ -633,17 +633,22 @@ PluginInstanceParent::NPP_HandleEvent(vo
     NPEvent* npevent = reinterpret_cast<NPEvent*>(event);
 #endif
     NPRemoteEvent npremoteevent;
     npremoteevent.event = *npevent;
     int16_t handled = 0;
 
 #if defined(OS_WIN)
     if (mWindowType == NPWindowTypeDrawable) {
-        switch(npevent->event) {
+        if (DoublePassRenderingEvent() == npevent->event) {
+            CallPaint(npremoteevent, &handled);
+            return handled;
+        }
+
+        switch (npevent->event) {
             case WM_PAINT:
             {
                 RECT rect;
                 SharedSurfaceBeforePaint(rect, npremoteevent);
                 CallPaint(npremoteevent, &handled);
                 SharedSurfaceAfterPaint(npevent);
                 return handled;
             }
--- a/dom/plugins/PluginMessageUtils.cpp
+++ b/dom/plugins/PluginMessageUtils.cpp
@@ -157,10 +157,23 @@ void DeferNPVariantLastRelease(const NPN
   if (!NPVARIANT_IS_OBJECT(*v)) {
     f->releasevariantvalue(v);
     return;
   }
   DeferNPObjectLastRelease(f, v->value.objectValue);
   VOID_TO_NPVARIANT(*v);
 }
 
+#ifdef XP_WIN
+
+// The private event used for double-pass widgetless plugin rendering.
+UINT DoublePassRenderingEvent()
+{
+  static UINT gEventID = 0;
+  if (!gEventID)
+    gEventID = ::RegisterWindowMessage(L"MozDoublePassMsg");
+  return gEventID;
+}
+
+#endif
+
 } // namespace plugins
 } // namespace mozilla
--- a/dom/plugins/PluginMessageUtils.h
+++ b/dom/plugins/PluginMessageUtils.h
@@ -266,16 +266,21 @@ struct DeletingObjectEntry : public nsPt
   DeletingObjectEntry(const NPObject* key)
     : nsPtrHashKey<NPObject>(key)
     , mDeleted(false)
   { }
 
   bool mDeleted;
 };
 
+#ifdef XP_WIN
+// The private event used for double-pass widgetless plugin rendering.
+UINT DoublePassRenderingEvent();
+#endif
+
 } /* namespace plugins */
 
 } /* namespace mozilla */
 
 namespace IPC {
 
 template <>
 struct ParamTraits<NPRect>
--- a/layout/generic/Makefile.in
+++ b/layout/generic/Makefile.in
@@ -139,16 +139,18 @@ CMMSRCS		+= \
 endif
 
 RESOURCES_HTML = \
 		$(srcdir)/folder.png \
 		$(NULL)
 
 FORCE_STATIC_LIB = 1
 
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
 		-I$(srcdir) \
 		-I$(srcdir)/../base \
 		-I$(srcdir)/../forms \
 		-I$(srcdir)/../tables \
 		-I$(srcdir)/../xul/base/src \
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -41,16 +41,20 @@
  * 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 ***** */
 
 /* rendering objects for replaced elements implemented by a plugin */
 
+#ifdef MOZ_IPC
+#include "mozilla/plugins/PluginMessageUtils.h"
+#endif
+
 #ifdef MOZ_WIDGET_QT
 #include <QWidget>
 #include <QKeyEvent>
 #ifdef MOZ_X11
 #include <QX11Info>
 #endif
 #endif
 
@@ -202,19 +206,16 @@ enum { XKeyPress = KeyPress };
 #ifdef MOZ_X11
 #include "mozilla/X11Util.h"
 using mozilla::DefaultXDisplay;
 #endif
 
 #ifdef XP_WIN
 #include <wtypes.h>
 #include <winuser.h>
-#ifdef MOZ_IPC
-#define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg")
-#endif
 #endif
 
 #ifdef XP_OS2
 #define INCL_PM
 #define INCL_GPI
 #include <os2.h>
 #endif
 
@@ -619,20 +620,16 @@ nsObjectFrame::Init(nsIContent*      aCo
   mPreventInstantiation =
     (aContent->GetCurrentDoc()->GetDisplayDocument() != nsnull);
 
   PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
          ("Initializing nsObjectFrame %p for content %p\n", this, aContent));
 
   nsresult rv = nsObjectFrameSuper::Init(aContent, aParent, aPrevInFlow);
 
-#ifdef XP_WIN
-  mDoublePassEvent = 0;
-#endif
-
   return rv;
 }
 
 void
 nsObjectFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   NS_ASSERTION(!mPreventInstantiation ||
                (mContent && mContent->GetCurrentDoc()->GetDisplayDocument()),
@@ -1721,25 +1718,22 @@ nsObjectFrame::PaintPlugin(nsIRenderingC
       nsPoint origin;
 
       gfxWindowsNativeDrawing nativeDraw(ctx, frameGfxRect);
 #ifdef MOZ_IPC
       if (nativeDraw.IsDoublePass()) {
         // OOP plugin specific: let the shim know before we paint if we are doing a
         // double pass render. If this plugin isn't oop, the register window message
         // will be ignored.
-        if (!mDoublePassEvent)
-          mDoublePassEvent = ::RegisterWindowMessage(NS_OOPP_DOUBLEPASS_MSGID);
-        if (mDoublePassEvent) {
-          NPEvent pluginEvent;
-          pluginEvent.event = mDoublePassEvent;
-          pluginEvent.wParam = 0;
-          pluginEvent.lParam = 0;
+        NPEvent pluginEvent;
+        pluginEvent.event = mozilla::plugins::DoublePassRenderingEvent();
+        pluginEvent.wParam = 0;
+        pluginEvent.lParam = 0;
+        if (pluginEvent.event)
           inst->HandleEvent(&pluginEvent, nsnull);
-        }
       }
 #endif
       do {
         HDC hdc = nativeDraw.BeginNativeDrawing();
         if (!hdc)
           return;
 
         RECT dest;
--- a/layout/generic/nsObjectFrame.h
+++ b/layout/generic/nsObjectFrame.h
@@ -247,19 +247,16 @@ private:
   private:
     nsString mEventType;
   };
   
   nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
   nsIView*                        mInnerView;
   nsCOMPtr<nsIWidget>             mWidget;
   nsIntRect                       mWindowlessRect;
-#ifdef XP_WIN
-  PRUint32                        mDoublePassEvent;
-#endif
 
   // For assertions that make it easier to determine if a crash is due
   // to the underlying problem described in bug 136927, and to prevent
   // reentry into instantiation.
   PRBool mPreventInstantiation;
 };
 
 class nsDisplayPlugin : public nsDisplayItem {