Bug 1522415: Properly track initialization state in case a device reset occurs during initialization. r=rhunt
authorBas Schouten <bschouten@mozilla.com>
Thu, 24 Jan 2019 12:37:28 +0100
changeset 515414 448d2641ef7d55fe7cfa2c6ebcb13c76105468e2
parent 515413 0d747e05337bdedc46a153a7ae710cda95913c62
child 515435 88420eeebda0c49c945ef719128208f33b5f0d6c
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrhunt
bugs1522415
milestone66.0a1
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 1522415: Properly track initialization state in case a device reset occurs during initialization. r=rhunt This fixes a situation where a Device Reset occurs during initialization, after mDC has already been created but before mBitmap is created. In this case IsValid and EnsureInitialized would previously return 'true' in subsequent calls, since they were only checking for the DC. This patch makes us properly store the full result of initialization for checking with IsValid and re-runs of EnsureInitialized. Differential Revision: https://phabricator.services.mozilla.com/D17486
gfx/2d/DrawTargetD2D1.cpp
gfx/2d/DrawTargetD2D1.h
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -40,17 +40,17 @@ RefPtr<ID2D1Factory1> D2DFactory() { ret
 
 DrawTargetD2D1::DrawTargetD2D1()
     : mPushedLayers(1),
       mSnapshotLock(make_shared<Mutex>("DrawTargetD2D1::mSnapshotLock")),
       mUsedCommandListsSincePurge(0),
       mTransformedGlyphsSinceLastPurge(0),
       mComplexBlendsWithListInList(0),
       mDeviceSeq(0),
-      mIsInitialized(false) {}
+      mInitState(InitState::Uninitialized) {}
 
 DrawTargetD2D1::~DrawTargetD2D1() {
   PopAllClips();
 
   if (mSnapshot) {
     MutexAutoLock lock(*mSnapshotLock);
     // We may hold the only reference. MarkIndependent will clear mSnapshot;
     // keep the snapshot object alive so it doesn't get destroyed while
@@ -85,17 +85,17 @@ DrawTargetD2D1::~DrawTargetD2D1() {
       (*iter)->mDependentTargets.erase(this);
     }
   }
 }
 
 bool DrawTargetD2D1::IsValid() const {
   if (NS_IsMainThread()) {
     // Uninitialized DTs are considered valid.
-    return !mIsInitialized || mDC;
+    return mInitState != InitState::Failure;
   } else {
     return const_cast<DrawTargetD2D1 *>(this)->EnsureInitialized();
   }
 }
 
 already_AddRefed<SourceSurface> DrawTargetD2D1::Snapshot() {
   if (!EnsureInitialized()) {
     return nullptr;
@@ -1310,22 +1310,22 @@ void DrawTargetD2D1::FlushInternal(bool 
   for (TargetSet::iterator iter = mDependingOnTargets.begin();
        iter != mDependingOnTargets.end(); iter++) {
     (*iter)->mDependentTargets.erase(this);
   }
   mDependingOnTargets.clear();
 }
 
 bool DrawTargetD2D1::EnsureInitialized() {
-  if (mIsInitialized) {
-    return !!mDC;
+  if (mInitState != InitState::Uninitialized) {
+    return mInitState == InitState::Success;
   }
 
   // Don't retry.
-  mIsInitialized = true;
+  mInitState = InitState::Failure;
 
   HRESULT hr;
 
   RefPtr<ID2D1Device> device = Factory::GetD2D1Device(&mDeviceSeq);
   if (!device) {
     gfxCriticalNote << "[D2D1.1] Failed to obtain a device for "
                        "DrawTargetD2D1::EnsureInitialized().";
     return false;
@@ -1395,16 +1395,18 @@ bool DrawTargetD2D1::EnsureInitialized()
   mDC->BeginDraw();
 
   CurrentLayer().mIsOpaque = mFormat == SurfaceFormat::B8G8R8X8;
 
   if (!mSurface) {
     mDC->Clear();
   }
 
+  mInitState = InitState::Success;
+
   return true;
 }
 
 void DrawTargetD2D1::MarkChanged() {
   if (mSnapshot) {
     MutexAutoLock lock(*mSnapshotLock);
     if (mSnapshot->hasOneRef()) {
       // Just destroy it, since no-one else knows about it.
--- a/gfx/2d/DrawTargetD2D1.h
+++ b/gfx/2d/DrawTargetD2D1.h
@@ -313,16 +313,21 @@ class DrawTargetD2D1 : public DrawTarget
   // This value is uesed to verify if the DrawTarget is created by a stale
   // device.
   uint32_t mDeviceSeq;
 
   // List of effects we use
   bool EnsureLuminanceEffect();
   RefPtr<ID2D1Effect> mLuminanceEffect;
 
-  bool mIsInitialized;
+  enum class InitState {
+    Uninitialized,
+    Success,
+    Failure
+  };
+  InitState mInitState;
   RefPtr<IDXGISurface> mSurface;
 };
 
 }  // namespace gfx
 }  // namespace mozilla
 
 #endif /* MOZILLA_GFX_DRAWTARGETD2D_H_ */