Diff
Modified: trunk/Source/WebCore/ChangeLog (126891 => 126892)
--- trunk/Source/WebCore/ChangeLog 2012-08-28 17:40:19 UTC (rev 126891)
+++ trunk/Source/WebCore/ChangeLog 2012-08-28 17:48:38 UTC (rev 126892)
@@ -1,3 +1,44 @@
+2012-08-28 Alpha Lam <[email protected]>
+
+ Report frame bytes by platform ImageDecoder
+ https://bugs.webkit.org/show_bug.cgi?id=94241
+
+ Reviewed by James Robinson.
+
+ Decoded frame bytes should be reported by the platform ImageSource and
+ ImageDecoder. BitmapImage used to guess system memory used by a frame
+ but this is no longer true if a frame is backed by an accelerated
+ surface or defer-decoded.
+
+ Adds ImageSource::frameBytesAtIndex and ImageDecoder::frameBytesAtIndex
+ such that platform can report memory usage correctly.
+
+ No new tests. Refactoring without change of behavior.
+ Tested on Chromium port with pixel tests without any crash or failure.
+
+ * platform/graphics/BitmapImage.cpp:
+ (WebCore::BitmapImage::destroyDecodedData):
+ (WebCore::BitmapImage::destroyDecodedDataIfNecessary):
+ (WebCore::BitmapImage::destroyMetadataAndNotify):
+ (WebCore::BitmapImage::cacheFrame):
+ (WebCore::BitmapImage::dataChanged):
+ * platform/graphics/BitmapImage.h:
+ (WebCore::FrameData::FrameData):
+ (FrameData):
+ (BitmapImage):
+ * platform/graphics/ImageSource.cpp:
+ (WebCore::ImageSource::frameBytesAtIndex):
+ (WebCore):
+ * platform/graphics/ImageSource.h:
+ * platform/graphics/cg/ImageSourceCG.cpp:
+ (WebCore::ImageSource::frameBytesAtIndex):
+ (WebCore):
+ * platform/image-decoders/ImageDecoder.cpp:
+ (WebCore::ImageDecoder::frameBytesAtIndex):
+ (WebCore):
+ * platform/image-decoders/ImageDecoder.h:
+ (ImageDecoder):
+
2012-08-28 Gustavo Noronha Silva <[email protected]>
[GTK] Does not regenerate CSS-related sources when configuration changes
Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.cpp (126891 => 126892)
--- trunk/Source/WebCore/platform/graphics/BitmapImage.cpp 2012-08-28 17:40:19 UTC (rev 126891)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.cpp 2012-08-28 17:48:38 UTC (rev 126892)
@@ -38,11 +38,6 @@
namespace WebCore {
-static int frameBytes(const IntSize& frameSize)
-{
- return frameSize.width() * frameSize.height() * 4;
-}
-
BitmapImage::BitmapImage(ImageObserver* observer)
: Image(observer)
, m_currentFrame(0)
@@ -85,17 +80,18 @@
void BitmapImage::destroyDecodedData(bool destroyAll)
{
- int framesCleared = 0;
+ unsigned frameBytesCleared = 0;
const size_t clearBeforeFrame = destroyAll ? m_frames.size() : m_currentFrame;
for (size_t i = 0; i < clearBeforeFrame; ++i) {
// The underlying frame isn't actually changing (we're just trying to
// save the memory for the framebuffer data), so we don't need to clear
// the metadata.
+ unsigned frameBytes = m_frames[i].m_frameBytes;
if (m_frames[i].clear(false))
- ++framesCleared;
+ frameBytesCleared += frameBytes;
}
- destroyMetadataAndNotify(framesCleared);
+ destroyMetadataAndNotify(frameBytesCleared);
m_source.clear(destroyAll, clearBeforeFrame, data(), m_allDataReceived);
return;
@@ -106,24 +102,28 @@
// Animated images >5MB are considered large enough that we'll only hang on
// to one frame at a time.
static const unsigned cLargeAnimationCutoff = 5242880;
- if (m_frames.size() * frameBytes(m_size) > cLargeAnimationCutoff)
+ unsigned allFrameBytes = 0;
+ for (size_t i = 0; i < m_frames.size(); ++i)
+ allFrameBytes += m_frames[i].m_frameBytes;
+
+ if (allFrameBytes > cLargeAnimationCutoff)
destroyDecodedData(destroyAll);
}
-void BitmapImage::destroyMetadataAndNotify(int framesCleared)
+void BitmapImage::destroyMetadataAndNotify(unsigned frameBytesCleared)
{
m_isSolidColor = false;
m_checkedForSolidColor = false;
invalidatePlatformData();
- int deltaBytes = framesCleared * -frameBytes(m_size);
- m_decodedSize += deltaBytes;
- if (framesCleared > 0) {
- deltaBytes -= m_decodedPropertiesSize;
+ ASSERT(m_decodedSize >= frameBytesCleared);
+ m_decodedSize -= frameBytesCleared;
+ if (frameBytesCleared > 0) {
+ frameBytesCleared += m_decodedPropertiesSize;
m_decodedPropertiesSize = 0;
}
- if (deltaBytes && imageObserver())
- imageObserver()->decodedSizeChanged(this, deltaBytes);
+ if (frameBytesCleared && imageObserver())
+ imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesCleared));
}
void BitmapImage::cacheFrame(size_t index)
@@ -144,12 +144,13 @@
if (repetitionCount(false) != cAnimationNone)
m_frames[index].m_duration = m_source.frameDurationAtIndex(index);
m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index);
+ m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index);
const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size);
if (frameSize != m_size)
m_hasUniformFrameSize = false;
if (m_frames[index].m_frame) {
- int deltaBytes = frameBytes(frameSize);
+ int deltaBytes = safeCast<int>(m_frames[index].m_frameBytes);
m_decodedSize += deltaBytes;
// The fully-decoded frame will subsume the partially decoded data used
// to determine image properties.
@@ -236,15 +237,16 @@
// start of the frame data), and any or none of them might be the particular
// frame affected by appending new data here. Thus we have to clear all the
// incomplete frames to be safe.
- int framesCleared = 0;
+ unsigned frameBytesCleared = 0;
for (size_t i = 0; i < m_frames.size(); ++i) {
// NOTE: Don't call frameIsCompleteAtIndex() here, that will try to
// decode any uncached (i.e. never-decoded or
// cleared-on-a-previous-pass) frames!
+ unsigned frameBytes = m_frames[i].m_frameBytes;
if (m_frames[i].m_haveMetadata && !m_frames[i].m_isComplete)
- framesCleared += (m_frames[i].clear(true) ? 1 : 0);
+ frameBytesCleared += (m_frames[i].clear(true) ? frameBytes : 0);
}
- destroyMetadataAndNotify(framesCleared);
+ destroyMetadataAndNotify(frameBytesCleared);
// Feed all the data we've seen so far to the image decoder.
m_allDataReceived = allDataReceived;
Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.h (126891 => 126892)
--- trunk/Source/WebCore/platform/graphics/BitmapImage.h 2012-08-28 17:40:19 UTC (rev 126891)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.h 2012-08-28 17:48:38 UTC (rev 126892)
@@ -75,6 +75,7 @@
, m_haveMetadata(false)
, m_isComplete(false)
, m_hasAlpha(true)
+ , m_frameBytes(0)
{
}
@@ -93,6 +94,7 @@
bool m_haveMetadata : 1;
bool m_isComplete : 1;
bool m_hasAlpha : 1;
+ unsigned m_frameBytes;
};
// =================================================
@@ -234,8 +236,8 @@
// Generally called by destroyDecodedData(), destroys whole-image metadata
// and notifies observers that the memory footprint has (hopefully)
- // decreased by |framesCleared| times the size (in bytes) of a frame.
- void destroyMetadataAndNotify(int framesCleared);
+ // decreased by |frameBytesCleared|.
+ void destroyMetadataAndNotify(unsigned frameBytesCleared);
// Whether or not size is available yet.
bool isSizeAvailable();
Modified: trunk/Source/WebCore/platform/graphics/ImageSource.cpp (126891 => 126892)
--- trunk/Source/WebCore/platform/graphics/ImageSource.cpp 2012-08-28 17:40:19 UTC (rev 126891)
+++ trunk/Source/WebCore/platform/graphics/ImageSource.cpp 2012-08-28 17:48:38 UTC (rev 126892)
@@ -198,4 +198,11 @@
return buffer && buffer->status() == ImageFrame::FrameComplete;
}
+unsigned ImageSource::frameBytesAtIndex(size_t index) const
+{
+ if (!m_decoder)
+ return 0;
+ return m_decoder->frameBytesAtIndex(index);
}
+
+}
Modified: trunk/Source/WebCore/platform/graphics/ImageSource.h (126891 => 126892)
--- trunk/Source/WebCore/platform/graphics/ImageSource.h 2012-08-28 17:40:19 UTC (rev 126891)
+++ trunk/Source/WebCore/platform/graphics/ImageSource.h 2012-08-28 17:48:38 UTC (rev 126892)
@@ -146,6 +146,10 @@
bool frameIsCompleteAtIndex(size_t); // Whether or not the frame is completely decoded.
ImageOrientation orientationAtIndex(size_t) const; // EXIF image orientation
+ // Return the number of bytes in the decoded frame. If the frame is not yet
+ // decoded then return 0.
+ unsigned frameBytesAtIndex(size_t) const;
+
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
static unsigned maxPixelsPerDecodedImage() { return s_maxPixelsPerDecodedImage; }
static void setMaxPixelsPerDecodedImage(unsigned maxPixels) { s_maxPixelsPerDecodedImage = maxPixels; }
Modified: trunk/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp (126891 => 126892)
--- trunk/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp 2012-08-28 17:40:19 UTC (rev 126891)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp 2012-08-28 17:48:38 UTC (rev 126892)
@@ -384,6 +384,12 @@
return true;
}
+unsigned ImageSource::frameBytesAtIndex(size_t index) const
+{
+ IntSize frameSize = frameSizeAtIndex(index, RespectImageOrientation);
+ return frameSize.width() * frameSize.height() * 4;
}
+}
+
#endif // USE(CG)
Modified: trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp (126891 => 126892)
--- trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp 2012-08-28 17:40:19 UTC (rev 126891)
+++ trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp 2012-08-28 17:48:38 UTC (rev 126892)
@@ -286,6 +286,14 @@
return true;
}
+unsigned ImageDecoder::frameBytesAtIndex(size_t index) const
+{
+ if (m_frameBufferCache.size() <= index)
+ return 0;
+ // FIXME: Use the dimension of the requested frame.
+ return m_size.area() * sizeof(ImageFrame::PixelData);
+}
+
void ImageDecoder::prepareScaleDataIfNecessary()
{
m_scaled = false;
Modified: trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h (126891 => 126892)
--- trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h 2012-08-28 17:40:19 UTC (rev 126891)
+++ trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h 2012-08-28 17:48:38 UTC (rev 126892)
@@ -279,6 +279,9 @@
// Make the best effort guess to check if the requested frame has alpha channel.
virtual bool frameHasAlphaAtIndex(size_t) const;
+ // Number of bytes in the decoded frame requested. Return 0 if not yet decoded.
+ virtual unsigned frameBytesAtIndex(size_t) const;
+
void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; }
bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; }