Bug 1072404: Firefox may crash when the D3D device is removed while rendering. r=mattwoodrow a=sylvestre
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -24,16 +24,17 @@
#include "ClientReadbackLayer.h" // for ClientReadbackLayer
#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
#include "gfxPrefs.h"
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#include "LayerMetricsWrapper.h"
#endif
namespace mozilla {
namespace layers {
@@ -276,16 +277,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
@@ -388,16 +388,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
@@ -944,16 +944,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
@@ -209,16 +209,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(); }