Skip to content

Commit

Permalink
Bug 1161859 - Compute the size of animated image frames correctly in …
Browse files Browse the repository at this point in the history
…the SurfaceCache. r=dholbert, a=lmandel

--HG--
branch : GECKO380_2015050320_RELBRANCH
  • Loading branch information
sethfowler committed May 6, 2015
1 parent 3c78f32 commit 46af41c
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 7 deletions.
3 changes: 2 additions & 1 deletion image/src/Decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,8 @@ Decoder::InternalAddFrame(uint32_t aFrameNum,
return RawAccessFrameRef();
}

if (!SurfaceCache::CanHold(aTargetSize.ToIntSize())) {
const uint32_t bytesPerPixel = aPaletteDepth == 0 ? 4 : 1;
if (!SurfaceCache::CanHold(aFrameRect.Size(), bytesPerPixel)) {
NS_WARNING("Trying to add frame that's too large for the SurfaceCache");
return RawAccessFrameRef();
}
Expand Down
11 changes: 6 additions & 5 deletions image/src/SurfaceCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,10 @@ static StaticRefPtr<SurfaceCacheImpl> sInstance;
*/
typedef size_t Cost;

static Cost ComputeCost(const IntSize& aSize)
static Cost ComputeCost(const IntSize& aSize, uint32_t aBytesPerPixel)
{
return aSize.width * aSize.height * 4; // width * height * 4 bytes (32bpp)
MOZ_ASSERT(aBytesPerPixel == 1 || aBytesPerPixel == 4);
return aSize.width * aSize.height * aBytesPerPixel;
}

/**
Expand Down Expand Up @@ -982,18 +983,18 @@ SurfaceCache::Insert(imgFrame* aSurface,
}

MutexAutoLock lock(sInstance->GetMutex());
Cost cost = ComputeCost(aSurfaceKey.Size());
Cost cost = ComputeCost(aSurface->GetSize(), aSurface->GetBytesPerPixel());
return sInstance->Insert(aSurface, cost, aImageKey, aSurfaceKey, aLifetime);
}

/* static */ bool
SurfaceCache::CanHold(const IntSize& aSize)
SurfaceCache::CanHold(const IntSize& aSize, uint32_t aBytesPerPixel /* = 4 */)
{
if (!sInstance) {
return false;
}

Cost cost = ComputeCost(aSize);
Cost cost = ComputeCost(aSize, aBytesPerPixel);
return sInstance->CanHold(cost);
}

Expand Down
5 changes: 4 additions & 1 deletion image/src/SurfaceCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,13 @@ struct SurfaceCache
* for sure the cache can't hold it.
*
* @param aSize The dimensions of a surface in pixels.
* @param aBytesPerPixel How many bytes each pixel of the surface requires.
* Defaults to 4, which is appropriate for RGBA or RGBX
* images.
*
* @return false if the surface cache can't hold a surface of that size.
*/
static bool CanHold(const IntSize& aSize);
static bool CanHold(const IntSize& aSize, uint32_t aBytesPerPixel = 4);
static bool CanHold(size_t aSize);

/**
Expand Down
8 changes: 8 additions & 0 deletions image/src/imgFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,14 @@ class imgFrame
*/
void WaitUntilComplete() const;

/**
* Returns the number of bytes per pixel this imgFrame requires. This is a
* worst-case value that does not take into account the effects of format
* changes caused by Optimize(), since an imgFrame is not optimized throughout
* its lifetime.
*/
uint32_t GetBytesPerPixel() const { return GetIsPaletted() ? 1 : 4; }

IntSize GetImageSize() { return mImageSize; }
nsIntRect GetRect() const;
IntSize GetSize() const { return mSize; }
Expand Down

0 comments on commit 46af41c

Please sign in to comment.