Bug 1262681 - Draw target also has to be valid for us to demand a snapshot. r=bas
authorMilan Sreckovic <milan@mozilla.com>
Wed, 13 Apr 2016 09:56:00 +0200
changeset 293345 7ed46b45eef8e576ad9f99def3c24cabfcfe89ab
parent 293344 2377dfe9e73cf6754c3ae1296869a4d31232ef79
child 293346 a841c9e635bb263de14ed1c1448eaf786f4bc79d
push id30178
push usercbook@mozilla.com
push dateFri, 15 Apr 2016 09:42:06 +0000
treeherdermozilla-central@afd82f887093 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbas
bugs1262681
milestone48.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 1262681 - Draw target also has to be valid for us to demand a snapshot. r=bas
gfx/layers/RotatedBuffer.cpp
gfx/layers/RotatedBuffer.h
--- a/gfx/layers/RotatedBuffer.cpp
+++ b/gfx/layers/RotatedBuffer.cpp
@@ -94,16 +94,21 @@ RotatedBuffer::DrawBufferQuadrant(gfx::D
   if (!fillRect.IntersectRect(mBufferRect, quadrantRect))
     return;
 
   gfx::Point quadrantTranslation(quadrantRect.x, quadrantRect.y);
 
   MOZ_ASSERT(aSource != BUFFER_BOTH);
   RefPtr<SourceSurface> snapshot = GetSourceSurface(aSource);
 
+  if (!snapshot) {
+    gfxCriticalError() << "Invalid snapshot in RotatedBuffer::DrawBufferQuadrant";
+    return;
+  }
+
   // direct2d is much slower when using OP_SOURCE so use OP_OVER and
   // (maybe) a clear instead. Normally we need to draw in a single operation
   // (to avoid flickering) but direct2d is ok since it defers rendering.
   // We should try abstract this logic in a helper when we have other use
   // cases.
   if ((aTarget->GetBackendType() == BackendType::DIRECT2D ||
        aTarget->GetBackendType() == BackendType::DIRECT2D1_1) &&
       aOperator == CompositionOp::OP_SOURCE) {
@@ -270,17 +275,17 @@ RotatedContentBuffer::BorrowDrawTargetFo
     return nullptr;
   }
 
   MOZ_ASSERT(!mLoanedDrawTarget, "draw target has been borrowed and not returned");
   if (aSource == BUFFER_BOTH && HaveBufferOnWhite()) {
     if (!EnsureBufferOnWhite()) {
       return nullptr;
     }
-    MOZ_ASSERT(mDTBuffer && mDTBufferOnWhite);
+    MOZ_ASSERT(mDTBuffer && mDTBuffer->IsValid() && mDTBufferOnWhite && mDTBufferOnWhite->IsValid());
     mLoanedDrawTarget = Factory::CreateDualDrawTarget(mDTBuffer, mDTBufferOnWhite);
   } else if (aSource == BUFFER_WHITE) {
     if (!EnsureBufferOnWhite()) {
       return nullptr;
     }
     mLoanedDrawTarget = mDTBufferOnWhite;
   } else {
     // BUFFER_BLACK, or BUFFER_BOTH with a single buffer.
@@ -313,22 +318,22 @@ BorrowDrawTarget::ReturnDrawTarget(gfx::
     mLoanedDrawTarget = nullptr;
   }
   aReturned = nullptr;
 }
 
 gfxContentType
 RotatedContentBuffer::BufferContentType()
 {
-  if (mBufferProvider || mDTBuffer) {
-    SurfaceFormat format;
+  if (mBufferProvider || (mDTBuffer && mDTBuffer->IsValid())) {
+    SurfaceFormat format = SurfaceFormat::B8G8R8A8;
 
     if (mBufferProvider) {
       format = mBufferProvider->GetFormat();
-    } else if (mDTBuffer) {
+    } else if (mDTBuffer && mDTBuffer->IsValid()) {
       format = mDTBuffer->GetFormat();
     }
 
     return ContentForFormat(format);
   }
   return gfxContentType::SENTINEL;
 }
 
@@ -339,23 +344,23 @@ RotatedContentBuffer::BufferSizeOkFor(co
           (SizedToVisibleBounds != mBufferSizePolicy &&
            aSize < mBufferRect.Size()));
 }
 
 bool
 RotatedContentBuffer::EnsureBuffer()
 {
   NS_ASSERTION(!mLoanedDrawTarget, "Loaned draw target must be returned");
-  if (!mDTBuffer) {
+  if (!mDTBuffer || !mDTBuffer->IsValid()) {
     if (mBufferProvider) {
       mDTBuffer = mBufferProvider->BorrowDrawTarget();
     }
   }
 
-  NS_WARN_IF_FALSE(mDTBuffer, "no buffer");
+  NS_WARN_IF_FALSE(mDTBuffer && mDTBuffer->IsValid(), "no buffer");
   return !!mDTBuffer;
 }
 
 bool
 RotatedContentBuffer::EnsureBufferOnWhite()
 {
   NS_ASSERTION(!mLoanedDrawTarget, "Loaned draw target must be returned");
   if (!mDTBufferOnWhite) {
@@ -367,23 +372,23 @@ RotatedContentBuffer::EnsureBufferOnWhit
 
   NS_WARN_IF_FALSE(mDTBufferOnWhite, "no buffer");
   return !!mDTBufferOnWhite;
 }
 
 bool
 RotatedContentBuffer::HaveBuffer() const
 {
-  return mDTBuffer || mBufferProvider;
+  return mBufferProvider || (mDTBuffer && mDTBuffer->IsValid());
 }
 
 bool
 RotatedContentBuffer::HaveBufferOnWhite() const
 {
-  return mDTBufferOnWhite || mBufferProviderOnWhite;
+  return mBufferProviderOnWhite || (mDTBufferOnWhite && mDTBufferOnWhite->IsValid());
 }
 
 static void
 WrapRotationAxis(int32_t* aRotationPoint, int32_t aSize)
 {
   if (*aRotationPoint < 0) {
     *aRotationPoint += aSize;
   } else if (*aRotationPoint >= aSize) {
@@ -586,23 +591,23 @@ RotatedContentBuffer::BeginPaint(Painted
           (newRotation != IntPoint(0,0) && !canHaveRotation)) {
         // The stuff we need to redraw will wrap around an edge of the
         // buffer (and the caller doesn't know how to support that), so
         // move the pixels we can keep into a position that lets us
         // redraw in just one quadrant.
         if (mBufferRotation == IntPoint(0,0)) {
           IntRect srcRect(IntPoint(0, 0), mBufferRect.Size());
           IntPoint dest = mBufferRect.TopLeft() - destBufferRect.TopLeft();
-          MOZ_ASSERT(mDTBuffer);
+          MOZ_ASSERT(mDTBuffer && mDTBuffer->IsValid());
           mDTBuffer->CopyRect(srcRect, dest);
           if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
             if (!EnsureBufferOnWhite()) {
               return result;
             }
-            MOZ_ASSERT(mDTBufferOnWhite);
+            MOZ_ASSERT(mDTBufferOnWhite && mDTBufferOnWhite->IsValid());
             mDTBufferOnWhite->CopyRect(srcRect, dest);
           }
           result.mDidSelfCopy = true;
           mDidSelfCopy = true;
           // Don't set destBuffer; we special-case self-copies, and
           // just did the necessary work above.
           mBufferRect = destBufferRect;
         } else {
@@ -620,17 +625,17 @@ RotatedContentBuffer::BeginPaint(Painted
                            size.height, stride,
                            newRotation.x * bytesPerPixel, newRotation.y);
             mDTBuffer->ReleaseBits(data);
 
             if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
               if (!EnsureBufferOnWhite()) {
                 return result;
               }
-              MOZ_ASSERT(mDTBufferOnWhite);
+              MOZ_ASSERT(mDTBufferOnWhite && mDTBufferOnWhite->IsValid());
               mDTBufferOnWhite->LockBits(&data, &size, &stride, &format);
               uint8_t bytesPerPixel = BytesPerPixel(format);
               BufferUnrotate(data,
                              size.width * bytesPerPixel,
                              size.height, stride,
                              newRotation.x * bytesPerPixel, newRotation.y);
               mDTBufferOnWhite->ReleaseBits(data);
             }
@@ -687,25 +692,25 @@ RotatedContentBuffer::BeginPaint(Painted
     if (!isClear && (mode != SurfaceMode::SURFACE_COMPONENT_ALPHA || HaveBufferOnWhite())) {
       // Copy the bits
       IntPoint offset = -destBufferRect.TopLeft();
       Matrix mat = Matrix::Translation(offset.x, offset.y);
       destDTBuffer->SetTransform(mat);
       if (!EnsureBuffer()) {
         return result;
       }
-       MOZ_ASSERT(mDTBuffer, "Have we got a Thebes buffer for some reason?");
+      MOZ_ASSERT(mDTBuffer && mDTBuffer->IsValid(), "Have we got a Thebes buffer for some reason?");
       DrawBufferWithRotation(destDTBuffer, BUFFER_BLACK, 1.0, CompositionOp::OP_SOURCE);
       destDTBuffer->SetTransform(Matrix());
 
       if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
         if (!destDTBufferOnWhite || !EnsureBufferOnWhite()) {
           return result;
         }
-        MOZ_ASSERT(mDTBufferOnWhite, "Have we got a Thebes buffer for some reason?");
+        MOZ_ASSERT(mDTBufferOnWhite && mDTBufferOnWhite->IsValid(), "Have we got a Thebes buffer for some reason?");
         destDTBufferOnWhite->SetTransform(mat);
         DrawBufferWithRotation(destDTBufferOnWhite, BUFFER_WHITE, 1.0, CompositionOp::OP_SOURCE);
         destDTBufferOnWhite->SetTransform(Matrix());
       }
     }
 
     mDTBuffer = destDTBuffer.forget();
     mDTBufferOnWhite = destDTBufferOnWhite.forget();
@@ -748,17 +753,18 @@ RotatedContentBuffer::BorrowDrawTargetFo
   if (result->GetBackendType() == BackendType::DIRECT2D ||
       result->GetBackendType() == BackendType::DIRECT2D1_1) {
     // Simplify the draw region to avoid hitting expensive drawing paths
     // for complex regions.
     drawPtr->SimplifyOutwardByArea(100 * 100);
   }
 
   if (aPaintState.mMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
-    if (!mDTBuffer || !mDTBufferOnWhite) {
+    if (!mDTBuffer || !mDTBuffer->IsValid() ||
+        !mDTBufferOnWhite || !mDTBufferOnWhite->IsValid()) {
       // This can happen in release builds if allocating one of the two buffers
       // failed. This in turn can happen if unreasonably large textures are
       // requested.
       return nullptr;
     }
     for (auto iter = drawPtr->RectIter(); !iter.Done(); iter.Next()) {
       const IntRect& rect = iter.Get();
       mDTBuffer->FillRect(Rect(rect.x, rect.y, rect.width, rect.height),
@@ -775,21 +781,28 @@ RotatedContentBuffer::BorrowDrawTargetFo
   }
 
   return result;
 }
 
 already_AddRefed<SourceSurface>
 RotatedContentBuffer::GetSourceSurface(ContextSource aSource) const
 {
-  MOZ_ASSERT(mDTBuffer);
+  if (!mDTBuffer || !mDTBuffer->IsValid()) {
+    gfxCriticalNote << "Invalid buffer in RotatedContentBuffer::GetSourceSurface " << gfx::hexa(mDTBuffer);
+    return nullptr;
+  }
+
   if (aSource == BUFFER_BLACK) {
     return mDTBuffer->Snapshot();
   } else {
-    MOZ_ASSERT(mDTBufferOnWhite);
+    if (!mDTBufferOnWhite || !mDTBufferOnWhite->IsValid()) {
+    gfxCriticalNote << "Invalid buffer on white in RotatedContentBuffer::GetSourceSurface " << gfx::hexa(mDTBufferOnWhite);
+      return nullptr;
+    }
     MOZ_ASSERT(aSource == BUFFER_WHITE);
     return mDTBufferOnWhite->Snapshot();
   }
 }
 
 } // namespace layers
 } // namespace mozilla
 
--- a/gfx/layers/RotatedBuffer.h
+++ b/gfx/layers/RotatedBuffer.h
@@ -334,29 +334,29 @@ public:
               const gfx::Matrix* aMaskTransform);
 
 protected:
   // new texture client versions
   void SetBufferProvider(TextureClient* aClient)
   {
     // Only this buffer provider can give us a buffer.  If we
     // already have one, something has gone wrong.
-    MOZ_ASSERT(!aClient || !mDTBuffer);
+    MOZ_ASSERT(!aClient || !mDTBuffer || !mDTBuffer->IsValid());
 
     mBufferProvider = aClient;
     if (!mBufferProvider) {
       mDTBuffer = nullptr;
     }
   }
 
   void SetBufferProviderOnWhite(TextureClient* aClient)
   {
     // Only this buffer provider can give us a buffer.  If we
     // already have one, something has gone wrong.
-    MOZ_ASSERT(!aClient || !mDTBufferOnWhite);
+    MOZ_ASSERT(!aClient || !mDTBufferOnWhite || !mDTBufferOnWhite->IsValid());
 
     mBufferProviderOnWhite = aClient;
     if (!mBufferProviderOnWhite) {
       mDTBufferOnWhite = nullptr;
     }
   }
 
   /**