Bug 1598585 Part 2: Make playback of Moz2D recorded events more robust. r=jrmuizel
authorBob Owen <bobowencode@gmail.com>
Mon, 24 Feb 2020 10:49:36 +0000
changeset 515239 95d4eb6763c254abbc760c5dafe77201cc6fbe72
parent 515238 6b300b00fc72832c6bb183760539c4b059db8479
child 515240 084d739fe6af10f9472e0c8e89bd623bf2331cad
push id37154
push usercsabou@mozilla.com
push dateMon, 24 Feb 2020 16:27:17 +0000
treeherdermozilla-central@8c5f9b08938e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1598585
milestone75.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 1598585 Part 2: Make playback of Moz2D recorded events more robust. r=jrmuizel This is generally around object creation failures and their subsequent lookup, which can happen, for example, during device reset. Differential Revision: https://phabricator.services.mozilla.com/D60888
gfx/2d/RecordedEventImpl.h
gfx/layers/CanvasDrawEventRecorder.cpp
gfx/layers/RecordedCanvasEventImpl.h
gfx/layers/ipc/CanvasTranslator.cpp
--- a/gfx/2d/RecordedEventImpl.h
+++ b/gfx/2d/RecordedEventImpl.h
@@ -1994,21 +1994,26 @@ inline void RecordedCreateSimilarDrawTar
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mRefPtr
                 << "] CreateSimilarDrawTarget (Size: " << mSize.width << "x"
                 << mSize.height << ")";
 }
 
 inline bool RecordedCreateDrawTargetForFilter::PlayEvent(
     Translator* aTranslator) const {
-  IntRect baseRect = aTranslator->LookupDrawTarget(mDT)->GetRect();
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  IntRect baseRect = dt->GetRect();
 
   auto maxRect = IntRect(IntPoint(0, 0), mMaxSize);
 
-  auto clone = aTranslator->LookupDrawTarget(mDT)->GetTransform();
+  auto clone = dt->GetTransform();
   bool invertible = clone.Invert();
   // mSourceRect is in filter space. The filter outputs from mSourceRect need
   // to be drawn at mDestPoint in user space.
   Rect userSpaceSource = Rect(mDestPoint, mSourceRect.Size());
   if (invertible) {
     // Try to reduce the source rect so that it's not much bigger
     // than the draw target. The result is not minimal. Examples
     // are left as an exercise for the reader.
@@ -2020,19 +2025,23 @@ inline bool RecordedCreateDrawTargetForF
   // Compute how much we moved the top-left of the source rect by, and use that
   // to compute the new dest point, and move our intersected source rect back
   // into the (new) filter space.
   Point shift = userSpaceSource.TopLeft() - mDestPoint;
   Rect filterSpaceSource =
       Rect(mSourceRect.TopLeft() + shift, userSpaceSource.Size());
 
   baseRect = RoundedOut(filterSpaceSource);
-  IntRect transformedRect =
-      aTranslator->LookupFilterNode(mFilter)->MapRectToSource(
-          baseRect, maxRect, aTranslator->LookupFilterNode(mSource));
+  FilterNode* filter = aTranslator->LookupFilterNode(mFilter);
+  if (!filter) {
+    return false;
+  }
+
+  IntRect transformedRect = filter->MapRectToSource(
+      baseRect, maxRect, aTranslator->LookupFilterNode(mSource));
 
   // Intersect with maxRect to make sure we didn't end up with something bigger
   transformedRect = transformedRect.Intersect(maxRect);
 
   // If we end up with an empty rect make it 1x1 so that things don't break.
   if (transformedRect.IsEmpty()) {
     transformedRect = IntRect(0, 0, 1, 1);
   }
@@ -2196,18 +2205,22 @@ struct GenericPattern {
   };
 
   PatternStorage* mStorage;
   Pattern* mPattern;
   Translator* mTranslator;
 };
 
 inline bool RecordedFillRect::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->FillRect(
-      mRect, *GenericPattern(mPattern, aTranslator), mOptions);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  dt->FillRect(mRect, *GenericPattern(mPattern, aTranslator), mOptions);
   return true;
 }
 
 template <class S>
 void RecordedFillRect::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   WriteElement(aStream, mRect);
   WriteElement(aStream, mOptions);
@@ -2226,18 +2239,23 @@ inline void RecordedFillRect::OutputSimp
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] FillRect (" << mRect.X() << ", "
                 << mRect.Y() << " - " << mRect.Width() << " x "
                 << mRect.Height() << ") ";
   OutputSimplePatternInfo(mPattern, aStringStream);
 }
 
 inline bool RecordedStrokeRect::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->StrokeRect(
-      mRect, *GenericPattern(mPattern, aTranslator), mStrokeOptions, mOptions);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  dt->StrokeRect(mRect, *GenericPattern(mPattern, aTranslator), mStrokeOptions,
+                 mOptions);
   return true;
 }
 
 template <class S>
 void RecordedStrokeRect::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   WriteElement(aStream, mRect);
   WriteElement(aStream, mOptions);
@@ -2259,19 +2277,23 @@ inline void RecordedStrokeRect::OutputSi
   aStringStream << "[" << mDT << "] StrokeRect (" << mRect.X() << ", "
                 << mRect.Y() << " - " << mRect.Width() << " x "
                 << mRect.Height()
                 << ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
   OutputSimplePatternInfo(mPattern, aStringStream);
 }
 
 inline bool RecordedStrokeLine::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->StrokeLine(
-      mBegin, mEnd, *GenericPattern(mPattern, aTranslator), mStrokeOptions,
-      mOptions);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  dt->StrokeLine(mBegin, mEnd, *GenericPattern(mPattern, aTranslator),
+                 mStrokeOptions, mOptions);
   return true;
 }
 
 template <class S>
 void RecordedStrokeLine::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   WriteElement(aStream, mBegin);
   WriteElement(aStream, mEnd);
@@ -2294,19 +2316,23 @@ inline void RecordedStrokeLine::OutputSi
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] StrokeLine (" << mBegin.x << ", "
                 << mBegin.y << " - " << mEnd.x << ", " << mEnd.y
                 << ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
   OutputSimplePatternInfo(mPattern, aStringStream);
 }
 
 inline bool RecordedFill::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->Fill(
-      aTranslator->LookupPath(mPath), *GenericPattern(mPattern, aTranslator),
-      mOptions);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  dt->Fill(aTranslator->LookupPath(mPath),
+           *GenericPattern(mPattern, aTranslator), mOptions);
   return true;
 }
 
 template <class S>
 RecordedFill::RecordedFill(S& aStream) : RecordedDrawingEvent(FILL, aStream) {
   ReadElement(aStream, mPath);
   ReadDrawOptions(aStream, mOptions);
   ReadPatternData(aStream, mPattern);
@@ -2324,22 +2350,31 @@ inline void RecordedFill::OutputSimpleEv
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] Fill (" << mPath << ") ";
   OutputSimplePatternInfo(mPattern, aStringStream);
 }
 
 inline RecordedFillGlyphs::~RecordedFillGlyphs() { delete[] mGlyphs; }
 
 inline bool RecordedFillGlyphs::PlayEvent(Translator* aTranslator) const {
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  ScaledFont* scaledFont = aTranslator->LookupScaledFont(mScaledFont);
+  if (!scaledFont) {
+    return false;
+  }
+
   GlyphBuffer buffer;
   buffer.mGlyphs = mGlyphs;
   buffer.mNumGlyphs = mNumGlyphs;
-  aTranslator->LookupDrawTarget(mDT)->FillGlyphs(
-      aTranslator->LookupScaledFont(mScaledFont), buffer,
-      *GenericPattern(mPattern, aTranslator), mOptions);
+  dt->FillGlyphs(scaledFont, buffer, *GenericPattern(mPattern, aTranslator),
+                 mOptions);
   return true;
 }
 
 template <class S>
 RecordedFillGlyphs::RecordedFillGlyphs(S& aStream)
     : RecordedDrawingEvent(FILLGLYPHS, aStream) {
   ReadElement(aStream, mScaledFont);
   ReadDrawOptions(aStream, mOptions);
@@ -2361,19 +2396,23 @@ void RecordedFillGlyphs::Record(S& aStre
 
 inline void RecordedFillGlyphs::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] FillGlyphs (" << mScaledFont << ") ";
   OutputSimplePatternInfo(mPattern, aStringStream);
 }
 
 inline bool RecordedMask::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->Mask(
-      *GenericPattern(mSource, aTranslator),
-      *GenericPattern(mMask, aTranslator), mOptions);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  dt->Mask(*GenericPattern(mSource, aTranslator),
+           *GenericPattern(mMask, aTranslator), mOptions);
   return true;
 }
 
 template <class S>
 RecordedMask::RecordedMask(S& aStream) : RecordedDrawingEvent(MASK, aStream) {
   ReadDrawOptions(aStream, mOptions);
   ReadPatternData(aStream, mSource);
   ReadPatternData(aStream, mMask);
@@ -2391,19 +2430,28 @@ inline void RecordedMask::OutputSimpleEv
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] Mask (Source: ";
   OutputSimplePatternInfo(mSource, aStringStream);
   aStringStream << " Mask: ";
   OutputSimplePatternInfo(mMask, aStringStream);
 }
 
 inline bool RecordedStroke::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->Stroke(
-      aTranslator->LookupPath(mPath), *GenericPattern(mPattern, aTranslator),
-      mStrokeOptions, mOptions);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  Path* path = aTranslator->LookupPath(mPath);
+  if (!path) {
+    return false;
+  }
+
+  dt->Stroke(path, *GenericPattern(mPattern, aTranslator), mStrokeOptions,
+             mOptions);
   return true;
 }
 
 template <class S>
 void RecordedStroke::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   WriteElement(aStream, mPath);
   WriteElement(aStream, mOptions);
@@ -2423,17 +2471,22 @@ RecordedStroke::RecordedStroke(S& aStrea
 inline void RecordedStroke::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] Stroke (" << mPath
                 << ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
   OutputSimplePatternInfo(mPattern, aStringStream);
 }
 
 inline bool RecordedClearRect::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->ClearRect(mRect);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  dt->ClearRect(mRect);
   return true;
 }
 
 template <class S>
 void RecordedClearRect::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   WriteElement(aStream, mRect);
 }
@@ -2447,18 +2500,27 @@ RecordedClearRect::RecordedClearRect(S& 
 inline void RecordedClearRect::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] ClearRect (" << mRect.X() << ", "
                 << mRect.Y() << " - " << mRect.Width() << " x "
                 << mRect.Height() << ") ";
 }
 
 inline bool RecordedCopySurface::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->CopySurface(
-      aTranslator->LookupSourceSurface(mSourceSurface), mSourceRect, mDest);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  SourceSurface* surface = aTranslator->LookupSourceSurface(mSourceSurface);
+  if (!surface) {
+    return false;
+  }
+
+  dt->CopySurface(surface, mSourceRect, mDest);
   return true;
 }
 
 template <class S>
 void RecordedCopySurface::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   WriteElement(aStream, mSourceSurface);
   WriteElement(aStream, mSourceRect);
@@ -2474,17 +2536,27 @@ RecordedCopySurface::RecordedCopySurface
 }
 
 inline void RecordedCopySurface::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] CopySurface (" << mSourceSurface << ")";
 }
 
 inline bool RecordedPushClip::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->PushClip(aTranslator->LookupPath(mPath));
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  Path* path = aTranslator->LookupPath(mPath);
+  if (!path) {
+    return false;
+  }
+
+  dt->PushClip(path);
   return true;
 }
 
 template <class S>
 void RecordedPushClip::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   WriteElement(aStream, mPath);
 }
@@ -2496,17 +2568,22 @@ RecordedPushClip::RecordedPushClip(S& aS
 }
 
 inline void RecordedPushClip::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] PushClip (" << mPath << ") ";
 }
 
 inline bool RecordedPushClipRect::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->PushClipRect(mRect);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  dt->PushClipRect(mRect);
   return true;
 }
 
 template <class S>
 void RecordedPushClipRect::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   WriteElement(aStream, mRect);
 }
@@ -2520,17 +2597,22 @@ RecordedPushClipRect::RecordedPushClipRe
 inline void RecordedPushClipRect::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] PushClipRect (" << mRect.X() << ", "
                 << mRect.Y() << " - " << mRect.Width() << " x "
                 << mRect.Height() << ") ";
 }
 
 inline bool RecordedPopClip::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->PopClip();
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  dt->PopClip();
   return true;
 }
 
 template <class S>
 void RecordedPopClip::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
 }
 
@@ -2539,20 +2621,25 @@ RecordedPopClip::RecordedPopClip(S& aStr
     : RecordedDrawingEvent(POPCLIP, aStream) {}
 
 inline void RecordedPopClip::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] PopClip";
 }
 
 inline bool RecordedPushLayer::PlayEvent(Translator* aTranslator) const {
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
   SourceSurface* mask =
       mMask ? aTranslator->LookupSourceSurface(mMask) : nullptr;
-  aTranslator->LookupDrawTarget(mDT)->PushLayer(
-      mOpaque, mOpacity, mask, mMaskTransform, mBounds, mCopyBackground);
+  dt->PushLayer(mOpaque, mOpacity, mask, mMaskTransform, mBounds,
+                mCopyBackground);
   return true;
 }
 
 template <class S>
 void RecordedPushLayer::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   WriteElement(aStream, mOpaque);
   WriteElement(aStream, mOpacity);
@@ -2576,21 +2663,25 @@ RecordedPushLayer::RecordedPushLayer(S& 
 inline void RecordedPushLayer::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] PushPLayer (Opaque=" << mOpaque
                 << ", Opacity=" << mOpacity << ", Mask Ref=" << mMask << ") ";
 }
 
 inline bool RecordedPushLayerWithBlend::PlayEvent(
     Translator* aTranslator) const {
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
   SourceSurface* mask =
       mMask ? aTranslator->LookupSourceSurface(mMask) : nullptr;
-  aTranslator->LookupDrawTarget(mDT)->PushLayerWithBlend(
-      mOpaque, mOpacity, mask, mMaskTransform, mBounds, mCopyBackground,
-      mCompositionOp);
+  dt->PushLayerWithBlend(mOpaque, mOpacity, mask, mMaskTransform, mBounds,
+                         mCopyBackground, mCompositionOp);
   return true;
 }
 
 template <class S>
 void RecordedPushLayerWithBlend::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   WriteElement(aStream, mOpaque);
   WriteElement(aStream, mOpacity);
@@ -2616,17 +2707,22 @@ RecordedPushLayerWithBlend::RecordedPush
 
 inline void RecordedPushLayerWithBlend::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] PushLayerWithBlend (Opaque=" << mOpaque
                 << ", Opacity=" << mOpacity << ", Mask Ref=" << mMask << ") ";
 }
 
 inline bool RecordedPopLayer::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->PopLayer();
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  dt->PopLayer();
   return true;
 }
 
 template <class S>
 void RecordedPopLayer::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
 }
 
@@ -2635,17 +2731,22 @@ RecordedPopLayer::RecordedPopLayer(S& aS
     : RecordedDrawingEvent(POPLAYER, aStream) {}
 
 inline void RecordedPopLayer::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] PopLayer";
 }
 
 inline bool RecordedSetTransform::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->SetTransform(mTransform);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  dt->SetTransform(mTransform);
   return true;
 }
 
 template <class S>
 void RecordedSetTransform::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   WriteElement(aStream, mTransform);
 }
@@ -2660,19 +2761,27 @@ inline void RecordedSetTransform::Output
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] SetTransform [ " << mTransform._11 << " "
                 << mTransform._12 << " ; " << mTransform._21 << " "
                 << mTransform._22 << " ; " << mTransform._31 << " "
                 << mTransform._32 << " ]";
 }
 
 inline bool RecordedDrawSurface::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->DrawSurface(
-      aTranslator->LookupSourceSurface(mRefSource), mDest, mSource, mDSOptions,
-      mOptions);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  SourceSurface* surface = aTranslator->LookupSourceSurface(mRefSource);
+  if (!surface) {
+    return false;
+  }
+
+  dt->DrawSurface(surface, mDest, mSource, mDSOptions, mOptions);
   return true;
 }
 
 template <class S>
 void RecordedDrawSurface::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   WriteElement(aStream, mRefSource);
   WriteElement(aStream, mDest);
@@ -2693,20 +2802,28 @@ RecordedDrawSurface::RecordedDrawSurface
 
 inline void RecordedDrawSurface::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] DrawSurface (" << mRefSource << ")";
 }
 
 inline bool RecordedDrawDependentSurface::PlayEvent(
     Translator* aTranslator) const {
-  RefPtr<SourceSurface> surface(aTranslator->LookupExternalSurface(mId));
-  aTranslator->LookupDrawTarget(mDT)->DrawSurface(
-      surface, mDest, Rect(Point(), Size(surface->GetSize())), mDSOptions,
-      mOptions);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  RefPtr<SourceSurface> surface = aTranslator->LookupExternalSurface(mId);
+  if (!surface) {
+    return false;
+  }
+
+  dt->DrawSurface(surface, mDest, Rect(Point(), Size(surface->GetSize())),
+                  mDSOptions, mOptions);
   return true;
 }
 
 template <class S>
 void RecordedDrawDependentSurface::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   WriteElement(aStream, mId);
   WriteElement(aStream, mDest);
@@ -2724,18 +2841,27 @@ RecordedDrawDependentSurface::RecordedDr
 }
 
 inline void RecordedDrawDependentSurface::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] DrawDependentSurface (" << mId << ")";
 }
 
 inline bool RecordedDrawFilter::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->DrawFilter(
-      aTranslator->LookupFilterNode(mNode), mSourceRect, mDestPoint, mOptions);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  FilterNode* filter = aTranslator->LookupFilterNode(mNode);
+  if (!filter) {
+    return false;
+  }
+
+  dt->DrawFilter(filter, mSourceRect, mDestPoint, mOptions);
   return true;
 }
 
 template <class S>
 void RecordedDrawFilter::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   WriteElement(aStream, mNode);
   WriteElement(aStream, mSourceRect);
@@ -2754,19 +2880,27 @@ RecordedDrawFilter::RecordedDrawFilter(S
 
 inline void RecordedDrawFilter::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] DrawFilter (" << mNode << ")";
 }
 
 inline bool RecordedDrawSurfaceWithShadow::PlayEvent(
     Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->DrawSurfaceWithShadow(
-      aTranslator->LookupSourceSurface(mRefSource), mDest, mColor, mOffset,
-      mSigma, mOp);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  SourceSurface* surface = aTranslator->LookupSourceSurface(mRefSource);
+  if (!surface) {
+    return false;
+  }
+
+  dt->DrawSurfaceWithShadow(surface, mDest, mColor, mOffset, mSigma, mOp);
   return true;
 }
 
 template <class S>
 void RecordedDrawSurfaceWithShadow::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   WriteElement(aStream, mRefSource);
   WriteElement(aStream, mDest);
@@ -2937,20 +3071,28 @@ RecordedSourceSurfaceDestruction::Record
 
 inline void RecordedSourceSurfaceDestruction::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mRefPtr << "] SourceSurface Destroyed";
 }
 
 inline bool RecordedOptimizeSourceSurface::PlayEvent(
     Translator* aTranslator) const {
-  RefPtr<SourceSurface> src =
-      aTranslator->LookupDrawTarget(mDT)->OptimizeSourceSurface(
-          aTranslator->LookupSourceSurface(mSurface));
-  aTranslator->AddSourceSurface(mOptimizedSurface, src);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  SourceSurface* surface = aTranslator->LookupSourceSurface(mSurface);
+  if (!surface) {
+    return false;
+  }
+
+  RefPtr<SourceSurface> optimizedSurface = dt->OptimizeSourceSurface(surface);
+  aTranslator->AddSourceSurface(mOptimizedSurface, optimizedSurface);
   return true;
 }
 
 template <class S>
 void RecordedOptimizeSourceSurface::Record(S& aStream) const {
   WriteElement(aStream, mSurface);
   WriteElement(aStream, mDT);
   WriteElement(aStream, mOptimizedSurface);
@@ -3111,19 +3253,22 @@ RecordedGradientStopsDestruction::Record
 
 inline void RecordedGradientStopsDestruction::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mRefPtr << "] GradientStops Destroyed";
 }
 
 inline bool RecordedIntoLuminanceSource::PlayEvent(
     Translator* aTranslator) const {
-  RefPtr<SourceSurface> src =
-      aTranslator->LookupDrawTarget(mDT)->IntoLuminanceSource(mLuminanceType,
-                                                              mOpacity);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  RefPtr<SourceSurface> src = dt->IntoLuminanceSource(mLuminanceType, mOpacity);
   aTranslator->AddSourceSurface(mRefPtr, src);
   return true;
 }
 
 template <class S>
 void RecordedIntoLuminanceSource::Record(S& aStream) const {
   WriteElement(aStream, mRefPtr);
   WriteElement(aStream, mDT);
@@ -3143,17 +3288,22 @@ RecordedIntoLuminanceSource::RecordedInt
 
 inline void RecordedIntoLuminanceSource::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mRefPtr << "] Into Luminance Source (DT: " << mDT
                 << ")";
 }
 
 inline bool RecordedFlush::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->Flush();
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  dt->Flush();
   return true;
 }
 
 template <class S>
 void RecordedFlush::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
 }
 
@@ -3163,17 +3313,22 @@ RecordedFlush::RecordedFlush(S& aStream)
 
 inline void RecordedFlush::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] Flush";
 }
 
 inline bool RecordedDetachAllSnapshots::PlayEvent(
     Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->DetachAllSnapshots();
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  dt->DetachAllSnapshots();
   return true;
 }
 
 template <class S>
 void RecordedDetachAllSnapshots::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
 }
 
@@ -3182,16 +3337,21 @@ RecordedDetachAllSnapshots::RecordedDeta
     : RecordedDrawingEvent(DETACHALLSNAPSHOTS, aStream) {}
 
 inline void RecordedDetachAllSnapshots::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mDT << "] DetachAllSnapshots";
 }
 
 inline bool RecordedSnapshot::PlayEvent(Translator* aTranslator) const {
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
   RefPtr<SourceSurface> src = aTranslator->LookupDrawTarget(mDT)->Snapshot();
   aTranslator->AddSourceSurface(mRefPtr, src);
   return true;
 }
 
 template <class S>
 void RecordedSnapshot::Record(S& aStream) const {
   WriteElement(aStream, mRefPtr);
@@ -3484,19 +3644,28 @@ RecordedScaledFontDestruction::RecordedS
 }
 
 inline void RecordedScaledFontDestruction::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mRefPtr << "] ScaledFont Destroyed";
 }
 
 inline bool RecordedMaskSurface::PlayEvent(Translator* aTranslator) const {
-  aTranslator->LookupDrawTarget(mDT)->MaskSurface(
-      *GenericPattern(mPattern, aTranslator),
-      aTranslator->LookupSourceSurface(mRefMask), mOffset, mOptions);
+  DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+  if (!dt) {
+    return false;
+  }
+
+  SourceSurface* surface = aTranslator->LookupSourceSurface(mRefMask);
+  if (!surface) {
+    return false;
+  }
+
+  dt->MaskSurface(*GenericPattern(mPattern, aTranslator), surface, mOffset,
+                  mOptions);
   return true;
 }
 
 template <class S>
 void RecordedMaskSurface::Record(S& aStream) const {
   RecordedDrawingEvent::Record(aStream);
   RecordPatternData(aStream, mPattern);
   WriteElement(aStream, mRefMask);
@@ -3522,20 +3691,24 @@ inline void RecordedMaskSurface::OutputS
 
 template <typename T>
 void ReplaySetAttribute(FilterNode* aNode, uint32_t aIndex, T aValue) {
   aNode->SetAttribute(aIndex, aValue);
 }
 
 inline bool RecordedFilterNodeSetAttribute::PlayEvent(
     Translator* aTranslator) const {
-#define REPLAY_SET_ATTRIBUTE(type, argtype)                          \
-  case ARGTYPE_##argtype:                                            \
-    ReplaySetAttribute(aTranslator->LookupFilterNode(mNode), mIndex, \
-                       *(type*)&mPayload.front());                   \
+  FilterNode* node = aTranslator->LookupFilterNode(mNode);
+  if (!node) {
+    return false;
+  }
+
+#define REPLAY_SET_ATTRIBUTE(type, argtype)                      \
+  case ARGTYPE_##argtype:                                        \
+    ReplaySetAttribute(node, mIndex, *(type*)&mPayload.front()); \
     break
 
   switch (mArgType) {
     REPLAY_SET_ATTRIBUTE(bool, BOOL);
     REPLAY_SET_ATTRIBUTE(uint32_t, UINT32);
     REPLAY_SET_ATTRIBUTE(Float, FLOAT);
     REPLAY_SET_ATTRIBUTE(Size, SIZE);
     REPLAY_SET_ATTRIBUTE(IntSize, INTSIZE);
@@ -3543,19 +3716,19 @@ inline bool RecordedFilterNodeSetAttribu
     REPLAY_SET_ATTRIBUTE(Rect, RECT);
     REPLAY_SET_ATTRIBUTE(IntRect, INTRECT);
     REPLAY_SET_ATTRIBUTE(Point, POINT);
     REPLAY_SET_ATTRIBUTE(Matrix, MATRIX);
     REPLAY_SET_ATTRIBUTE(Matrix5x4, MATRIX5X4);
     REPLAY_SET_ATTRIBUTE(Point3D, POINT3D);
     REPLAY_SET_ATTRIBUTE(Color, COLOR);
     case ARGTYPE_FLOAT_ARRAY:
-      aTranslator->LookupFilterNode(mNode)->SetAttribute(
-          mIndex, reinterpret_cast<const Float*>(&mPayload.front()),
-          mPayload.size() / sizeof(Float));
+      node->SetAttribute(mIndex,
+                         reinterpret_cast<const Float*>(&mPayload.front()),
+                         mPayload.size() / sizeof(Float));
       break;
   }
 
   return true;
 }
 
 template <class S>
 void RecordedFilterNodeSetAttribute::Record(S& aStream) const {
@@ -3581,22 +3754,25 @@ RecordedFilterNodeSetAttribute::Recorded
 
 inline void RecordedFilterNodeSetAttribute::OutputSimpleEventInfo(
     std::stringstream& aStringStream) const {
   aStringStream << "[" << mNode << "] SetAttribute (" << mIndex << ")";
 }
 
 inline bool RecordedFilterNodeSetInput::PlayEvent(
     Translator* aTranslator) const {
+  FilterNode* node = aTranslator->LookupFilterNode(mNode);
+  if (!node) {
+    return false;
+  }
+
   if (mInputFilter) {
-    aTranslator->LookupFilterNode(mNode)->SetInput(
-        mIndex, aTranslator->LookupFilterNode(mInputFilter));
+    node->SetInput(mIndex, aTranslator->LookupFilterNode(mInputFilter));
   } else {
-    aTranslator->LookupFilterNode(mNode)->SetInput(
-        mIndex, aTranslator->LookupSourceSurface(mInputSurface));
+    node->SetInput(mIndex, aTranslator->LookupSourceSurface(mInputSurface));
   }
 
   return true;
 }
 
 template <class S>
 void RecordedFilterNodeSetInput::Record(S& aStream) const {
   WriteElement(aStream, mNode);
--- a/gfx/layers/CanvasDrawEventRecorder.cpp
+++ b/gfx/layers/CanvasDrawEventRecorder.cpp
@@ -441,33 +441,42 @@ void CanvasEventRingBuffer::ReturnWrite(
   }
 
   memcpy(mBuf + bufPos, aData, aSize);
   writeCount += aSize;
   mRead->returnCount = writeCount;
 }
 
 void CanvasEventRingBuffer::ReturnRead(char* aOut, size_t aSize) {
+  // First wait for the event returning the data to be read.
+  WaitForCheckpoint(mOurCount);
   uint32_t readCount = mWrite->returnCount;
+
+  // If the event sending back data fails to play then it will ReturnWrite
+  // nothing. So, wait until something has been written or the reader has
+  // stopped processing.
+  while (readCount == mRead->returnCount) {
+    if (mRead->state != State::Processing) {
+      return;
+    }
+  }
+
   uint32_t bufPos = readCount % kStreamSize;
   uint32_t bufRemaining = kStreamSize - bufPos;
   uint32_t availableToRead =
       std::min(bufRemaining, (mRead->returnCount - readCount));
   while (availableToRead < aSize) {
     if (availableToRead) {
       memcpy(aOut, mBuf + bufPos, availableToRead);
       readCount += availableToRead;
       mWrite->returnCount = readCount;
       bufPos = readCount % kStreamSize;
       bufRemaining = kStreamSize - bufPos;
       aOut += availableToRead;
       aSize -= availableToRead;
-    } else {
-      // Double-check that the reader isn't waiting.
-      CheckAndSignalReader();
     }
 
     availableToRead = std::min(bufRemaining, (mRead->returnCount - readCount));
   }
 
   memcpy(aOut, mBuf + bufPos, aSize);
   readCount += aSize;
   mWrite->returnCount = readCount;
--- a/gfx/layers/RecordedCanvasEventImpl.h
+++ b/gfx/layers/RecordedCanvasEventImpl.h
@@ -236,18 +236,20 @@ class RecordedCacheDataSurface final
   std::string GetName() const final { return "RecordedCacheDataSurface"; }
 
  private:
   ReferencePtr mSurface;
 };
 
 inline bool RecordedCacheDataSurface::PlayCanvasEvent(
     CanvasTranslator* aTranslator) const {
-  RefPtr<gfx::SourceSurface> surface =
-      aTranslator->LookupSourceSurface(mSurface);
+  gfx::SourceSurface* surface = aTranslator->LookupSourceSurface(mSurface);
+  if (!surface) {
+    return false;
+  }
 
   RefPtr<gfx::DataSourceSurface> dataSurface = surface->GetDataSurface();
 
   aTranslator->AddDataSurface(mSurface, std::move(dataSurface));
   return true;
 }
 
 template <class S>
@@ -281,18 +283,17 @@ class RecordedPrepareDataForSurface fina
   ReferencePtr mSurface;
 };
 
 inline bool RecordedPrepareDataForSurface::PlayCanvasEvent(
     CanvasTranslator* aTranslator) const {
   RefPtr<gfx::DataSourceSurface> dataSurface =
       aTranslator->LookupDataSurface(mSurface);
   if (!dataSurface) {
-    RefPtr<gfx::SourceSurface> surface =
-        aTranslator->LookupSourceSurface(mSurface);
+    gfx::SourceSurface* surface = aTranslator->LookupSourceSurface(mSurface);
     if (!surface) {
       return false;
     }
 
     dataSurface = surface->GetDataSurface();
     if (!dataSurface) {
       return false;
     }
@@ -333,24 +334,26 @@ class RecordedGetDataForSurface final
   std::string GetName() const final { return "RecordedGetDataForSurface"; }
 
  private:
   ReferencePtr mSurface;
 };
 
 inline bool RecordedGetDataForSurface::PlayCanvasEvent(
     CanvasTranslator* aTranslator) const {
-  RefPtr<gfx::SourceSurface> surface =
-      aTranslator->LookupSourceSurface(mSurface);
+  gfx::SourceSurface* surface = aTranslator->LookupSourceSurface(mSurface);
   if (!surface) {
     return false;
   }
 
   UniquePtr<gfx::DataSourceSurface::ScopedMap> map =
       aTranslator->GetPreparedMap(mSurface);
+  if (!map) {
+    return false;
+  }
 
   gfx::IntSize ssSize = surface->GetSize();
   size_t dataFormatWidth = ssSize.width * BytesPerPixel(surface->GetFormat());
   int32_t srcStride = map->GetStride();
   char* src = reinterpret_cast<char*>(map->GetData());
   char* endSrc = src + (ssSize.height * srcStride);
   while (src < endSrc) {
     aTranslator->ReturnWrite(src, dataFormatWidth);
--- a/gfx/layers/ipc/CanvasTranslator.cpp
+++ b/gfx/layers/ipc/CanvasTranslator.cpp
@@ -337,16 +337,21 @@ void CanvasTranslator::SetPreparedMap(
     gfx::ReferencePtr aSurface,
     UniquePtr<gfx::DataSourceSurface::ScopedMap> aMap) {
   mMappedSurface = aSurface;
   mPreparedMap = std::move(aMap);
 }
 
 UniquePtr<gfx::DataSourceSurface::ScopedMap> CanvasTranslator::GetPreparedMap(
     gfx::ReferencePtr aSurface) {
+  if (!mPreparedMap) {
+    // We might fail to set the map during, for example, device resets.
+    return nullptr;
+  }
+
   MOZ_RELEASE_ASSERT(mMappedSurface == aSurface,
                      "aSurface must match previously stored surface.");
 
   mMappedSurface = nullptr;
   return std::move(mPreparedMap);
 }
 
 }  // namespace layers