Title: [137481] trunk/Source/WebCore
Revision
137481
Author
[email protected]
Date
2012-12-12 10:32:01 -0800 (Wed, 12 Dec 2012)

Log Message

[Qt] Animation fails on large layers
https://bugs.webkit.org/show_bug.cgi?id=104538

Reviewed by Noam Rosenthal.

The backing tiles had no upper limit defined for the non-GL backend, which could cause them
to allocate pixmaps widier or higher than what the underlying graphics systems can handle.

On top of that GraphicsLayerTextureMapper::prepareBackingStore() would allocate an intermediate
pixmap the size of the dirty rect, which would at least on the first paint be the size of the
entire layer, again causing allocation of pixmaps with dimensions outside of platform bounds.

This patch introduces a limit to the size of image buffer tiles, and adds an alternative path
for painting where the GraphicsLayer paints directly to the tile instead of over an intermediate
pixmap. This alternative path can also be useful later to minimize the amount of pixel copying
happening in full repaints.

* platform/graphics/texmap/GraphicsLayerTextureMapper.cpp:
(WebCore::GraphicsLayerTextureMapper::prepareBackingStore):
* platform/graphics/texmap/GraphicsLayerTextureMapper.h:
(GraphicsLayerTextureMapper):
* platform/graphics/texmap/TextureMapper.cpp:
(WebCore::BitmapTexture::updateContents):
* platform/graphics/texmap/TextureMapper.h:
(BitmapTexture):
(TextureMapper):
* platform/graphics/texmap/TextureMapperBackingStore.cpp:
(WebCore::TextureMapperTile::updateContents):
(WebCore::TextureMapperTiledBackingStore::updateContents):
* platform/graphics/texmap/TextureMapperBackingStore.h:
(TextureMapperTile):
(TextureMapperTiledBackingStore):
* platform/graphics/texmap/TextureMapperImageBuffer.cpp:
(WebCore::BitmapTextureImageBuffer::updateContents):
(WebCore::TextureMapperImageBuffer::maxTextureSize):
* platform/graphics/texmap/TextureMapperImageBuffer.h:
(BitmapTextureImageBuffer):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (137480 => 137481)


--- trunk/Source/WebCore/ChangeLog	2012-12-12 18:30:40 UTC (rev 137480)
+++ trunk/Source/WebCore/ChangeLog	2012-12-12 18:32:01 UTC (rev 137481)
@@ -1,3 +1,43 @@
+2012-12-12  Allan Sandfeld Jensen  <[email protected]>
+
+        [Qt] Animation fails on large layers
+        https://bugs.webkit.org/show_bug.cgi?id=104538
+
+        Reviewed by Noam Rosenthal.
+
+        The backing tiles had no upper limit defined for the non-GL backend, which could cause them
+        to allocate pixmaps widier or higher than what the underlying graphics systems can handle.
+
+        On top of that GraphicsLayerTextureMapper::prepareBackingStore() would allocate an intermediate
+        pixmap the size of the dirty rect, which would at least on the first paint be the size of the
+        entire layer, again causing allocation of pixmaps with dimensions outside of platform bounds.
+
+        This patch introduces a limit to the size of image buffer tiles, and adds an alternative path
+        for painting where the GraphicsLayer paints directly to the tile instead of over an intermediate
+        pixmap. This alternative path can also be useful later to minimize the amount of pixel copying
+        happening in full repaints.
+
+        * platform/graphics/texmap/GraphicsLayerTextureMapper.cpp:
+        (WebCore::GraphicsLayerTextureMapper::prepareBackingStore):
+        * platform/graphics/texmap/GraphicsLayerTextureMapper.h:
+        (GraphicsLayerTextureMapper):
+        * platform/graphics/texmap/TextureMapper.cpp:
+        (WebCore::BitmapTexture::updateContents):
+        * platform/graphics/texmap/TextureMapper.h:
+        (BitmapTexture):
+        (TextureMapper):
+        * platform/graphics/texmap/TextureMapperBackingStore.cpp:
+        (WebCore::TextureMapperTile::updateContents):
+        (WebCore::TextureMapperTiledBackingStore::updateContents):
+        * platform/graphics/texmap/TextureMapperBackingStore.h:
+        (TextureMapperTile):
+        (TextureMapperTiledBackingStore):
+        * platform/graphics/texmap/TextureMapperImageBuffer.cpp:
+        (WebCore::BitmapTextureImageBuffer::updateContents):
+        (WebCore::TextureMapperImageBuffer::maxTextureSize):
+        * platform/graphics/texmap/TextureMapperImageBuffer.h:
+        (BitmapTextureImageBuffer):
+
 2012-12-12  Aaron Colwell  <[email protected]>
 
         Remove MediaSource 'ended' to 'open' transition when seeking.

Modified: trunk/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp (137480 => 137481)


--- trunk/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp	2012-12-12 18:30:40 UTC (rev 137480)
+++ trunk/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp	2012-12-12 18:32:01 UTC (rev 137481)
@@ -466,26 +466,35 @@
     if (!m_backingStore)
         m_backingStore = TextureMapperTiledBackingStore::create();
 
-    // Paint the entire dirty rect into an image buffer. This ensures we only paint once.
-    OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(dirtyRect.size());
-    GraphicsContext* context = imageBuffer->context();
-    context->setImageInterpolationQuality(textureMapper->imageInterpolationQuality());
-    context->setTextDrawingMode(textureMapper->textDrawingMode());
-    context->translate(-dirtyRect.x(), -dirtyRect.y());
-    paintGraphicsLayerContents(*context, dirtyRect);
+    ASSERT(dynamic_cast<TextureMapperTiledBackingStore*>(m_backingStore.get()));
+    TextureMapperTiledBackingStore* backingStore = static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get());
 
-    if (isShowingRepaintCounter()) {
+    if (isShowingRepaintCounter())
         incrementRepaintCount();
-        drawRepaintCounter(context);
-    }
 
-    RefPtr<Image> image = imageBuffer->copyImage(DontCopyBackingStore);
-#if PLATFORM(QT)
-    ASSERT(dynamic_cast<TextureMapperTiledBackingStore*>(m_backingStore.get()));
-#endif
-    TextureMapperTiledBackingStore* backingStore = static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get());
-    backingStore->updateContents(textureMapper, image.get(), m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData);
+    // Paint into an intermediate buffer to avoid painting content more than once.
+    bool paintOnce = true;
+    const IntSize maxTextureSize = textureMapper->maxTextureSize();
+    // We need to paint directly if the dirty rect exceeds one of the maximum dimensions.
+    if (dirtyRect.width() > maxTextureSize.width() || dirtyRect.height() > maxTextureSize.height())
+        paintOnce = false;
 
+    if (paintOnce) {
+        OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(dirtyRect.size());
+        GraphicsContext* context = imageBuffer->context();
+        context->setImageInterpolationQuality(textureMapper->imageInterpolationQuality());
+        context->setTextDrawingMode(textureMapper->textDrawingMode());
+        context->translate(-dirtyRect.x(), -dirtyRect.y());
+        paintGraphicsLayerContents(*context, dirtyRect);
+
+        if (isShowingRepaintCounter())
+            drawRepaintCounter(context);
+
+        RefPtr<Image> image = imageBuffer->copyImage(DontCopyBackingStore);
+        backingStore->updateContents(textureMapper, image.get(), m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData);
+    } else
+        backingStore->updateContents(textureMapper, this, m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData);
+
     backingStore->setShowDebugBorders(isShowingDebugBorder());
     backingStore->setDebugBorder(m_debugBorderColor, m_debugBorderWidth);
 

Modified: trunk/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h (137480 => 137481)


--- trunk/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h	2012-12-12 18:30:40 UTC (rev 137480)
+++ trunk/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h	2012-12-12 18:32:01 UTC (rev 137481)
@@ -97,6 +97,7 @@
     void setFixedToViewport(bool fixed) { m_fixedToViewport = fixed; }
     bool fixedToViewport() const { return m_fixedToViewport; }
 
+    void drawRepaintCounter(GraphicsContext*);
 private:
     virtual void willBeDestroyed();
     void didFlushCompositingState();
@@ -104,7 +105,6 @@
     void updateBackingStore();
     void prepareBackingStore();
     bool shouldHaveBackingStore() const;
-    void drawRepaintCounter(GraphicsContext*);
     void animationStartedTimerFired(Timer<GraphicsLayerTextureMapper>*);
 
     OwnPtr<TextureMapperLayer> m_layer;

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp (137480 => 137481)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp	2012-12-12 18:30:40 UTC (rev 137480)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp	2012-12-12 18:32:01 UTC (rev 137481)
@@ -20,6 +20,7 @@
 #include "config.h"
 #include "TextureMapper.h"
 
+#include "GraphicsLayer.h"
 #include "TextureMapperImageBuffer.h"
 #include "Timer.h"
 #include <wtf/CurrentTime.h>
@@ -145,5 +146,23 @@
 TextureMapper::~TextureMapper()
 { }
 
+void BitmapTexture::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const IntRect& targetRect, const IntPoint& offset, UpdateContentsFlag updateContentsFlag)
+{
+    OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(targetRect.size());
+    GraphicsContext* context = imageBuffer->context();
+    context->setImageInterpolationQuality(textureMapper->imageInterpolationQuality());
+    context->setTextDrawingMode(textureMapper->textDrawingMode());
+
+    IntRect sourceRect(targetRect);
+    sourceRect.setLocation(offset);
+    context->translate(-offset.x(), -offset.y());
+    sourceLayer->paintGraphicsLayerContents(*context, sourceRect);
+
+    RefPtr<Image> image = imageBuffer->copyImage(DontCopyBackingStore);
+
+    updateContents(image.get(), targetRect, IntPoint(), updateContentsFlag);
 }
+
+} // namespace
+
 #endif

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.h (137480 => 137481)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.h	2012-12-12 18:30:40 UTC (rev 137480)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.h	2012-12-12 18:32:01 UTC (rev 137481)
@@ -49,10 +49,11 @@
 
 class BitmapTexturePool;
 class CustomFilterProgram;
+class GraphicsLayer;
 class TextureMapper;
 
 // A 2D texture that can be the target of software or GL rendering.
-class BitmapTexture  : public RefCounted<BitmapTexture> {
+class BitmapTexture : public RefCounted<BitmapTexture> {
 public:
     enum Flag {
         SupportsAlpha = 0x01
@@ -75,6 +76,7 @@
 
     virtual IntSize size() const = 0;
     virtual void updateContents(Image*, const IntRect&, const IntPoint& offset, UpdateContentsFlag) = 0;
+    virtual void updateContents(TextureMapper*, GraphicsLayer*, const IntRect& target, const IntPoint& offset, UpdateContentsFlag);
     virtual void updateContents(const void*, const IntRect& target, const IntPoint& offset, int bytesPerLine, UpdateContentsFlag) = 0;
     virtual bool isValid() const = 0;
     inline Flags flags() const { return m_flags; }
@@ -151,7 +153,7 @@
     virtual void beginPainting(PaintFlags = 0) { }
     virtual void endPainting() { }
 
-    virtual IntSize maxTextureSize() const { return IntSize(INT_MAX, INT_MAX); }
+    virtual IntSize maxTextureSize() const = 0;
 
     virtual PassRefPtr<BitmapTexture> acquireTextureFromPool(const IntSize&);
 

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp (137480 => 137481)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp	2012-12-12 18:30:40 UTC (rev 137480)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp	2012-12-12 18:32:01 UTC (rev 137481)
@@ -80,6 +80,25 @@
     m_texture->updateContents(image, targetRect, sourceOffset, updateContentsFlag);
 }
 
+void TextureMapperTile::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
+{
+    IntRect targetRect = enclosingIntRect(m_rect);
+    targetRect.intersect(dirtyRect);
+    if (targetRect.isEmpty())
+        return;
+    IntPoint sourceOffset = targetRect.location();
+
+    // Normalize targetRect to the texture's coordinates.
+    targetRect.move(-m_rect.x(), -m_rect.y());
+
+    if (!m_texture) {
+        m_texture = textureMapper->createTexture();
+        m_texture->reset(targetRect.size(), BitmapTexture::SupportsAlpha);
+    }
+
+    m_texture->updateContents(textureMapper, sourceLayer, targetRect, sourceOffset, updateContentsFlag);
+}
+
 void TextureMapperTile::paint(TextureMapper* textureMapper, const TransformationMatrix& transform, float opacity, BitmapTexture* mask, const unsigned exposedEdges)
 {
     if (texture().get())
@@ -197,6 +216,13 @@
         m_tiles[i].updateContents(textureMapper, image, dirtyRect, updateContentsFlag);
 }
 
+void TextureMapperTiledBackingStore::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const FloatSize& totalSize, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
+{
+    createOrDestroyTilesIfNeeded(totalSize, textureMapper->maxTextureSize(), true);
+    for (size_t i = 0; i < m_tiles.size(); ++i)
+        m_tiles[i].updateContents(textureMapper, sourceLayer, dirtyRect, updateContentsFlag);
+}
+
 PassRefPtr<BitmapTexture> TextureMapperTiledBackingStore::texture() const
 {
     for (size_t i = 0; i < m_tiles.size(); ++i) {

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h (137480 => 137481)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h	2012-12-12 18:30:40 UTC (rev 137480)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h	2012-12-12 18:32:01 UTC (rev 137481)
@@ -73,6 +73,7 @@
     inline void setRect(const FloatRect& rect) { m_rect = rect; }
 
     void updateContents(TextureMapper*, Image*, const IntRect&, BitmapTexture::UpdateContentsFlag UpdateCanModifyOriginalImageData);
+    void updateContents(TextureMapper*, GraphicsLayer*, const IntRect&, BitmapTexture::UpdateContentsFlag UpdateCanModifyOriginalImageData);
     virtual void paint(TextureMapper*, const TransformationMatrix&, float, BitmapTexture*, const unsigned exposedEdges);
     virtual ~TextureMapperTile() { }
 
@@ -94,6 +95,7 @@
     virtual PassRefPtr<BitmapTexture> texture() const OVERRIDE;
     virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float, BitmapTexture*) OVERRIDE;
     void updateContents(TextureMapper*, Image*, const FloatSize&, const IntRect&, BitmapTexture::UpdateContentsFlag);
+    void updateContents(TextureMapper*, GraphicsLayer*, const FloatSize&, const IntRect&, BitmapTexture::UpdateContentsFlag);
 
     void setContentsToImage(Image* image) { m_image = image; }
     void setShowDebugBorders(bool drawsDebugBorders) { m_drawsDebugBorders = drawsDebugBorders; }

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp (137480 => 137481)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp	2012-12-12 18:30:40 UTC (rev 137480)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp	2012-12-12 18:32:01 UTC (rev 137481)
@@ -21,6 +21,7 @@
 #include "TextureMapperImageBuffer.h"
 
 #include "FilterEffectRenderer.h"
+#include "GraphicsLayer.h"
 #if PLATFORM(QT)
 #include "NativeImageQt.h"
 #endif
@@ -29,6 +30,8 @@
 #if USE(TEXTURE_MAPPER)
 namespace WebCore {
 
+static const int s_maximumAllowedImageBufferDimension = 4096;
+
 void BitmapTextureImageBuffer::updateContents(const void* data, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine, UpdateContentsFlag)
 {
 #if PLATFORM(QT)
@@ -54,6 +57,20 @@
 #endif
 }
 
+void BitmapTextureImageBuffer::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const IntRect& targetRect, const IntPoint& sourceOffset, UpdateContentsFlag)
+{
+    GraphicsContext* context = m_image->context();
+
+    context->clearRect(targetRect);
+
+    IntRect sourceRect(targetRect);
+    sourceRect.setLocation(sourceOffset);
+    context->save();
+    context->translate(targetRect.x() - sourceOffset.x(), targetRect.y() - sourceOffset.y());
+    sourceLayer->paintGraphicsLayerContents(*context, sourceRect);
+    context->restore();
+}
+
 void BitmapTextureImageBuffer::didReset()
 {
     m_image = ImageBuffer::create(contentSize());
@@ -64,6 +81,11 @@
     m_image->context()->drawImage(image, ColorSpaceDeviceRGB, targetRect, IntRect(offset, targetRect.size()), CompositeCopy);
 }
 
+IntSize TextureMapperImageBuffer::maxTextureSize() const
+{
+    return IntSize(s_maximumAllowedImageBufferDimension, s_maximumAllowedImageBufferDimension);
+}
+
 void TextureMapperImageBuffer::beginClip(const TransformationMatrix& matrix, const FloatRect& rect)
 {
     GraphicsContext* context = currentContext();

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h (137480 => 137481)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h	2012-12-12 18:30:40 UTC (rev 137480)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h	2012-12-12 18:32:01 UTC (rev 137481)
@@ -35,6 +35,7 @@
     virtual bool isValid() const { return m_image; }
     inline GraphicsContext* graphicsContext() { return m_image ? m_image->context() : 0; }
     virtual void updateContents(Image*, const IntRect&, const IntPoint&, UpdateContentsFlag);
+    virtual void updateContents(TextureMapper*, GraphicsLayer*, const IntRect& target, const IntPoint& offset, UpdateContentsFlag);
     virtual void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine, UpdateContentsFlag);
 #if ENABLE(CSS_FILTERS)
     PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const BitmapTexture&, const FilterOperations&);
@@ -65,6 +66,7 @@
     virtual void beginClip(const TransformationMatrix&, const FloatRect&) OVERRIDE;
     virtual void bindSurface(BitmapTexture* surface) OVERRIDE { m_currentSurface = surface;}
     virtual void endClip() OVERRIDE { graphicsContext()->restore(); }
+    virtual IntSize maxTextureSize() const;
     virtual PassRefPtr<BitmapTexture> createTexture() OVERRIDE { return BitmapTextureImageBuffer::create(); }
 
     inline GraphicsContext* currentContext()
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to