Bug 1072404: Firefox may crash when the D3D device is removed while rendering. r=mattwoodrow a=sylvestre
authorBas Schouten <bschouten@mozilla.com>
Wed, 24 Sep 2014 17:12:10 +0000
changeset 216870 3d41bbe16481
parent 216869 2a8947c986ed
child 216871 b9e8ce2a141b
push id3947
push userbschouten@mozilla.com
push date2014-09-29 03:00 +0000
treeherdermozilla-beta@3d41bbe16481 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow, sylvestre
bugs1072404
milestone33.0
Bug 1072404: Firefox may crash when the D3D device is removed while rendering. r=mattwoodrow a=sylvestre
gfx/layers/client/ClientLayerManager.cpp
gfx/thebes/gfxContext.cpp
gfx/thebes/gfxPlatform.h
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -23,16 +23,17 @@
 #include "mozilla/layers/SimpleTextureClientPool.h" // for SimpleTextureClientPool
 #include "nsAString.h"
 #include "nsIWidget.h"                  // for nsIWidget
 #include "nsIWidgetListener.h"
 #include "nsTArray.h"                   // for AutoInfallibleTArray
 #include "nsXULAppAPI.h"                // for XRE_GetProcessType, etc
 #include "TiledLayerBuffer.h"
 #include "mozilla/dom/WindowBinding.h"  // for Overfill Callback
+#include "FrameLayerBuilder.h"          // for FrameLayerbuilder
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidBridge.h"
 #endif
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
@@ -218,16 +219,20 @@ ClientLayerManager::EndTransactionIntern
 
   // Go back to the construction phase if the transaction isn't complete.
   // Layout will update the layer tree and call EndTransaction().
   mPhase = mTransactionIncomplete ? PHASE_CONSTRUCTION : PHASE_NONE;
 
   NS_ASSERTION(!aCallback || !mTransactionIncomplete,
                "If callback is not null, transaction must be complete");
 
+  if (gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
+    FrameLayerBuilder::InvalidateAllLayers(this);
+  }
+
   return !mTransactionIncomplete;
 }
 
 void
 ClientLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
                                    void* aCallbackData,
                                    EndTransactionFlags aFlags)
 {
--- a/gfx/thebes/gfxContext.cpp
+++ b/gfx/thebes/gfxContext.cpp
@@ -1078,19 +1078,23 @@ gfxContext::Paint(gfxFloat alpha)
   }
 }
 
 // groups
 
 void
 gfxContext::PushGroup(gfxContentType content)
 {
+  DrawTarget* oldDT = mDT;
+
   PushNewDT(content);
 
-  PushClipsToDT(mDT);
+  if (oldDT != mDT) {
+    PushClipsToDT(mDT);
+  }
   mDT->SetTransform(GetDTTransform());
 }
 
 static gfxRect
 GetRoundOutDeviceClipExtents(gfxContext* aCtx)
 {
   gfxContextMatrixAutoSaveRestore save(aCtx);
   aCtx->IdentityMatrix();
@@ -1111,16 +1115,21 @@ gfxContext::PushGroupAndCopyBackground(g
        mDT->GetOpaqueRect().Contains(clipExtents)) &&
       !mDT->GetUserData(&sDontUseAsSourceKey)) {
     DrawTarget *oldDT = mDT;
     RefPtr<SourceSurface> source = mDT->Snapshot();
     Point oldDeviceOffset = CurrentState().deviceOffset;
 
     PushNewDT(gfxContentType::COLOR);
 
+    if (oldDT == mDT) {
+      // Creating new DT failed.
+      return;
+    }
+
     Point offset = CurrentState().deviceOffset - oldDeviceOffset;
     Rect surfRect(0, 0, Float(mDT->GetSize().width), Float(mDT->GetSize().height));
     Rect sourceRect = surfRect;
     sourceRect.x += offset.x;
     sourceRect.y += offset.y;
 
     mDT->SetTransform(Matrix());
     mDT->DrawSurface(source, surfRect, sourceRect);
@@ -1627,18 +1636,21 @@ gfxContext::PushNewDT(gfxContentType con
     mDT->CreateSimilarDrawTarget(IntSize(int32_t(clipBounds.width), int32_t(clipBounds.height)),
                                  format);
 
   if (!newDT) {
     NS_WARNING("Failed to create DrawTarget of sufficient size.");
     newDT = mDT->CreateSimilarDrawTarget(IntSize(64, 64), format);
 
     if (!newDT) {
-      // If even this fails.. we're most likely just out of memory!
-      NS_ABORT_OOM(BytesPerPixel(format) * 64 * 64);
+      if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
+        // If even this fails.. we're most likely just out of memory!
+        NS_ABORT_OOM(BytesPerPixel(format) * 64 * 64);
+      }
+      newDT = CurrentState().drawTarget;
     }
   }
 
   Save();
 
   CurrentState().drawTarget = newDT;
   CurrentState().deviceOffset = clipBounds.TopLeft();
 
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -391,16 +391,18 @@ public:
      * Whether to use the SIL Graphite rendering engine
      * (for fonts that include Graphite tables)
      */
     bool UseGraphiteShaping();
 
     // check whether format is supported on a platform or not (if unclear, returns true)
     virtual bool IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags) { return false; }
 
+    virtual bool DidRenderingDeviceReset() { return false; }
+
     void GetPrefFonts(nsIAtom *aLanguage, nsString& array, bool aAppendUnicode = true);
 
     // in some situations, need to make decisions about ambiguous characters, may need to look at multiple pref langs
     void GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang);
     
     /**
      * Iterate over pref fonts given a list of lang groups.  For a single lang
      * group, multiple pref fonts are possible.  If error occurs, returns false,
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -943,16 +943,22 @@ gfxWindowsPlatform::IsFontFormatSupporte
     if (aFormatFlags != 0) {
         return false;
     }
 
     // no format hint set, need to look at data
     return true;
 }
 
+bool
+gfxWindowsPlatform::DidRenderingDeviceReset()
+{
+  return GetD3D10Device() && GetD3D10Device()->GetDeviceRemovedReason() != S_OK;
+}
+
 gfxFontFamily *
 gfxWindowsPlatform::FindFontFamily(const nsAString& aName)
 {
     return gfxPlatformFontList::PlatformFontList()->FindFamily(aName);
 }
 
 gfxFontEntry *
 gfxWindowsPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle)
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -208,16 +208,18 @@ public:
                                            const uint8_t *aFontData,
                                            uint32_t aLength);
 
     /**
      * Check whether format is supported on a platform or not (if unclear, returns true)
      */
     virtual bool IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags);
 
+    virtual bool DidRenderingDeviceReset();
+
     /* Find a FontFamily/FontEntry object that represents a font on your system given a name */
     gfxFontFamily *FindFontFamily(const nsAString& aName);
     gfxFontEntry *FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle);
 
     bool GetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<gfxFontEntry> > *array);
     void SetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<gfxFontEntry> >& array);
 
     void ClearPrefFonts() { mPrefFonts.Clear(); }