From 453116079c5b8417f4ee4eb5ba8b924ad74c1655 Mon Sep 17 00:00:00 2001 From: Joe Drew Date: Wed, 26 Sep 2012 11:33:06 -0400 Subject: [PATCH] Bug 786444 - Part 2 - Make imgFrame's lock status a count, not a boolean, so you can lock it multiple times and still be correct. r=jlebar Also add a bunch of NS_ABORT_IF_FALSEs that verify that the lock status is always valid. --HG-- extra : rebase_source : 70cce5ed671586529e7d698e4bcdc86f5c748aa5 --- image/src/imgFrame.cpp | 48 ++++++++++++++++++++++++++++++------------ image/src/imgFrame.h | 5 +++-- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/image/src/imgFrame.cpp b/image/src/imgFrame.cpp index bf7146a1f937..9fab64a1e9cd 100644 --- a/image/src/imgFrame.cpp +++ b/image/src/imgFrame.cpp @@ -109,6 +109,7 @@ imgFrame::imgFrame() : mSinglePixelColor(0), mTimeout(100), mDisposalMethod(0), /* imgIContainer::kDisposeNotSpecified */ + mLockCount(0), mBlendMethod(1), /* imgIContainer::kBlendOver */ mSinglePixel(false), mNeverUseDeviceSurface(false), @@ -118,7 +119,6 @@ imgFrame::imgFrame() : #ifdef USE_WIN_SURFACE mIsDDBSurface(false), #endif - mLocked(false), mInformedDiscardTracker(false) { static bool hasCheckedOptimize = false; @@ -578,6 +578,8 @@ uint32_t imgFrame::GetImageDataLength() const void imgFrame::GetImageData(uint8_t **aData, uint32_t *length) const { + NS_ABORT_IF_FALSE(mLockCount != 0, "Can't GetImageData unless frame is locked"); + if (mImageSurface) *aData = mImageSurface->Data(); else if (mPalettedImageData) @@ -600,6 +602,8 @@ bool imgFrame::GetHasAlpha() const void imgFrame::GetPaletteData(uint32_t **aPalette, uint32_t *length) const { + NS_ABORT_IF_FALSE(mLockCount != 0, "Can't GetPaletteData unless frame is locked"); + if (!mPalettedImageData) { *aPalette = nullptr; *length = 0; @@ -611,14 +615,21 @@ void imgFrame::GetPaletteData(uint32_t **aPalette, uint32_t *length) const nsresult imgFrame::LockImageData() { - if (mPalettedImageData) - return NS_ERROR_NOT_AVAILABLE; - - NS_ABORT_IF_FALSE(!mLocked, "Trying to lock already locked image data."); - if (mLocked) { + NS_ABORT_IF_FALSE(mLockCount >= 0, "Unbalanced locks and unlocks"); + if (mLockCount < 0) { return NS_ERROR_FAILURE; } - mLocked = true; + + mLockCount++; + + // If we are not the first lock, there's nothing to do. + if (mLockCount != 1) { + return NS_OK; + } + + // Paletted images don't have surfaces, so there's nothing to do. + if (mPalettedImageData) + return NS_OK; if ((mOptSurface || mSinglePixel) && !mImageSurface) { // Recover the pixels @@ -659,15 +670,26 @@ nsresult imgFrame::LockImageData() nsresult imgFrame::UnlockImageData() { - if (mPalettedImageData) - return NS_ERROR_NOT_AVAILABLE; - - NS_ABORT_IF_FALSE(mLocked, "Unlocking an unlocked image!"); - if (!mLocked) { + NS_ABORT_IF_FALSE(mLockCount != 0, "Unlocking an unlocked image!"); + if (mLockCount == 0) { return NS_ERROR_FAILURE; } - mLocked = false; + mLockCount--; + + NS_ABORT_IF_FALSE(mLockCount >= 0, "Unbalanced locks and unlocks"); + if (mLockCount < 0) { + return NS_ERROR_FAILURE; + } + + // If we are not the last lock, there's nothing to do. + if (mLockCount != 0) { + return NS_OK; + } + + // Paletted images don't have surfaces, so there's nothing to do. + if (mPalettedImageData) + return NS_OK; // Assume we've been written to. if (mImageSurface) diff --git a/image/src/imgFrame.h b/image/src/imgFrame.h index b6d434239cb9..afad17059513 100644 --- a/image/src/imgFrame.h +++ b/image/src/imgFrame.h @@ -157,6 +157,9 @@ private: // data int32_t mTimeout; // -1 means display forever int32_t mDisposalMethod; + /** Indicates how many readers currently have locked this frame */ + int32_t mLockCount; + gfxASurface::gfxImageFormat mFormat; uint8_t mPaletteDepth; int8_t mBlendMethod; @@ -165,8 +168,6 @@ private: // data bool mFormatChanged; bool mCompositingFailed; bool mNonPremult; - /** Indicates if the image data is currently locked */ - bool mLocked; /** Have we called DiscardTracker::InformAllocation()? */ bool mInformedDiscardTracker;