Title: [126892] trunk/Source/WebCore
Revision
126892
Author
[email protected]
Date
2012-08-28 10:48:38 -0700 (Tue, 28 Aug 2012)

Log Message

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):

Modified Paths

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; }
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to