Bug 1044129 - Don't crash if ContainerLayer temporary surface allocation fails. r=jrmuizel, a=sledru
authorMatt Woodrow <mwoodrow@mozilla.com>
Tue, 29 Jul 2014 17:31:00 +1200
changeset 216767 11e34dc2f591
parent 216766 e99eaafdbda1
child 216768 2dbe6d8a5c30
push id3906
push userryanvm@gmail.com
push date2014-09-17 15:11 +0000
treeherdermozilla-beta@62d020eff891 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel, sledru
bugs1044129
milestone33.0
Bug 1044129 - Don't crash if ContainerLayer temporary surface allocation fails. r=jrmuizel, a=sledru
gfx/layers/composite/ContainerLayerComposite.cpp
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -288,25 +288,27 @@ struct PreparedLayer
   nsIntRegion mSavedVisibleRegion;
 };
 
 /* all of the prepared data that we need in RenderLayer() */
 struct PreparedData
 {
   RefPtr<CompositingRenderTarget> mTmpTarget;
   nsAutoTArray<PreparedLayer, 12> mLayers;
+  bool mNeedsSurfaceCopy;
 };
 
 // ContainerPrepare is shared between RefLayer and ContainerLayer
 template<class ContainerT> void
 ContainerPrepare(ContainerT* aContainer,
                  LayerManagerComposite* aManager,
                  const nsIntRect& aClipRect)
 {
   aContainer->mPrepared = MakeUnique<PreparedData>();
+  aContainer->mPrepared->mNeedsSurfaceCopy = false;
 
   /**
    * Determine which layers to draw.
    */
   nsAutoTArray<Layer*, 12> children;
   aContainer->SortChildrenBy3DZOrder(children);
 
   for (uint32_t i = 0; i < children.Length(); i++) {
@@ -357,16 +359,18 @@ ContainerPrepare(ContainerT* aContainer,
   if (aContainer->UseIntermediateSurface()) {
     MOZ_PERFORMANCE_WARNING("gfx", "[%p] Container layer requires intermediate surface\n", aContainer);
     if (!surfaceCopyNeeded) {
       // If we don't need a copy we can render to the intermediate now to avoid
       // unecessary render target switching. This brings a big perf boost on mobile gpus.
       RefPtr<CompositingRenderTarget> surface = CreateTemporaryTarget(aContainer, aManager);
       RenderIntermediate(aContainer, aManager, aClipRect, surface);
       aContainer->mPrepared->mTmpTarget = surface;
+    } else {
+      aContainer->mPrepared->mNeedsSurfaceCopy = true;
     }
   }
 }
 
 template<class ContainerT> void
 RenderLayers(ContainerT* aContainer,
 	     LayerManagerComposite* aManager,
 	     const nsIntRect& aClipRect)
@@ -502,24 +506,29 @@ template<class ContainerT> void
 ContainerRender(ContainerT* aContainer,
                  LayerManagerComposite* aManager,
                  const nsIntRect& aClipRect)
 {
   MOZ_ASSERT(aContainer->mPrepared);
   if (aContainer->UseIntermediateSurface()) {
     RefPtr<CompositingRenderTarget> surface;
 
-    if (!aContainer->mPrepared->mTmpTarget) {
+    if (aContainer->mPrepared->mNeedsSurfaceCopy) {
       // we needed to copy the background so we waited until now to render the intermediate
       surface = CreateTemporaryTargetAndCopyFromBackground(aContainer, aManager);
       RenderIntermediate(aContainer, aManager, aClipRect, surface);
     } else {
       surface = aContainer->mPrepared->mTmpTarget;
     }
 
+    if (!surface) {
+      aContainer->mPrepared = nullptr;
+      return;
+    }
+
     float opacity = aContainer->GetEffectiveOpacity();
 
     nsIntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds();
 #ifdef MOZ_DUMP_PAINTING
     if (gfxUtils::sDumpPainting) {
       RefPtr<gfx::DataSourceSurface> surf = surface->Dump(aManager->GetCompositor());
       if (surf) {
         WriteSnapshotToDumpFile(aContainer, surf);