Changeset 137481 in webkit


Ignore:
Timestamp:
Dec 12, 2012 10:32:01 AM (11 years ago)
Author:
allan.jensen@digia.com
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):

Location:
trunk/Source/WebCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r137480 r137481  
     12012-12-12  Allan Sandfeld Jensen  <allan.jensen@digia.com>
     2
     3        [Qt] Animation fails on large layers
     4        https://bugs.webkit.org/show_bug.cgi?id=104538
     5
     6        Reviewed by Noam Rosenthal.
     7
     8        The backing tiles had no upper limit defined for the non-GL backend, which could cause them
     9        to allocate pixmaps widier or higher than what the underlying graphics systems can handle.
     10
     11        On top of that GraphicsLayerTextureMapper::prepareBackingStore() would allocate an intermediate
     12        pixmap the size of the dirty rect, which would at least on the first paint be the size of the
     13        entire layer, again causing allocation of pixmaps with dimensions outside of platform bounds.
     14
     15        This patch introduces a limit to the size of image buffer tiles, and adds an alternative path
     16        for painting where the GraphicsLayer paints directly to the tile instead of over an intermediate
     17        pixmap. This alternative path can also be useful later to minimize the amount of pixel copying
     18        happening in full repaints.
     19
     20        * platform/graphics/texmap/GraphicsLayerTextureMapper.cpp:
     21        (WebCore::GraphicsLayerTextureMapper::prepareBackingStore):
     22        * platform/graphics/texmap/GraphicsLayerTextureMapper.h:
     23        (GraphicsLayerTextureMapper):
     24        * platform/graphics/texmap/TextureMapper.cpp:
     25        (WebCore::BitmapTexture::updateContents):
     26        * platform/graphics/texmap/TextureMapper.h:
     27        (BitmapTexture):
     28        (TextureMapper):
     29        * platform/graphics/texmap/TextureMapperBackingStore.cpp:
     30        (WebCore::TextureMapperTile::updateContents):
     31        (WebCore::TextureMapperTiledBackingStore::updateContents):
     32        * platform/graphics/texmap/TextureMapperBackingStore.h:
     33        (TextureMapperTile):
     34        (TextureMapperTiledBackingStore):
     35        * platform/graphics/texmap/TextureMapperImageBuffer.cpp:
     36        (WebCore::BitmapTextureImageBuffer::updateContents):
     37        (WebCore::TextureMapperImageBuffer::maxTextureSize):
     38        * platform/graphics/texmap/TextureMapperImageBuffer.h:
     39        (BitmapTextureImageBuffer):
     40
    1412012-12-12  Aaron Colwell  <acolwell@chromium.org>
    242
  • trunk/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp

    r137362 r137481  
    467467        m_backingStore = TextureMapperTiledBackingStore::create();
    468468
    469     // Paint the entire dirty rect into an image buffer. This ensures we only paint once.
    470     OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(dirtyRect.size());
    471     GraphicsContext* context = imageBuffer->context();
    472     context->setImageInterpolationQuality(textureMapper->imageInterpolationQuality());
    473     context->setTextDrawingMode(textureMapper->textDrawingMode());
    474     context->translate(-dirtyRect.x(), -dirtyRect.y());
    475     paintGraphicsLayerContents(*context, dirtyRect);
    476 
    477     if (isShowingRepaintCounter()) {
     469    ASSERT(dynamic_cast<TextureMapperTiledBackingStore*>(m_backingStore.get()));
     470    TextureMapperTiledBackingStore* backingStore = static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get());
     471
     472    if (isShowingRepaintCounter())
    478473        incrementRepaintCount();
    479         drawRepaintCounter(context);
    480     }
    481 
    482     RefPtr<Image> image = imageBuffer->copyImage(DontCopyBackingStore);
    483 #if PLATFORM(QT)
    484     ASSERT(dynamic_cast<TextureMapperTiledBackingStore*>(m_backingStore.get()));
    485 #endif
    486     TextureMapperTiledBackingStore* backingStore = static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get());
    487     backingStore->updateContents(textureMapper, image.get(), m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData);
     474
     475    // Paint into an intermediate buffer to avoid painting content more than once.
     476    bool paintOnce = true;
     477    const IntSize maxTextureSize = textureMapper->maxTextureSize();
     478    // We need to paint directly if the dirty rect exceeds one of the maximum dimensions.
     479    if (dirtyRect.width() > maxTextureSize.width() || dirtyRect.height() > maxTextureSize.height())
     480        paintOnce = false;
     481
     482    if (paintOnce) {
     483        OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(dirtyRect.size());
     484        GraphicsContext* context = imageBuffer->context();
     485        context->setImageInterpolationQuality(textureMapper->imageInterpolationQuality());
     486        context->setTextDrawingMode(textureMapper->textDrawingMode());
     487        context->translate(-dirtyRect.x(), -dirtyRect.y());
     488        paintGraphicsLayerContents(*context, dirtyRect);
     489
     490        if (isShowingRepaintCounter())
     491            drawRepaintCounter(context);
     492
     493        RefPtr<Image> image = imageBuffer->copyImage(DontCopyBackingStore);
     494        backingStore->updateContents(textureMapper, image.get(), m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData);
     495    } else
     496        backingStore->updateContents(textureMapper, this, m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData);
    488497
    489498    backingStore->setShowDebugBorders(isShowingDebugBorder());
  • trunk/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h

    r136781 r137481  
    9898    bool fixedToViewport() const { return m_fixedToViewport; }
    9999
     100    void drawRepaintCounter(GraphicsContext*);
    100101private:
    101102    virtual void willBeDestroyed();
     
    105106    void prepareBackingStore();
    106107    bool shouldHaveBackingStore() const;
    107     void drawRepaintCounter(GraphicsContext*);
    108108    void animationStartedTimerFired(Timer<GraphicsLayerTextureMapper>*);
    109109
  • trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp

    r137442 r137481  
    2121#include "TextureMapper.h"
    2222
     23#include "GraphicsLayer.h"
    2324#include "TextureMapperImageBuffer.h"
    2425#include "Timer.h"
     
    146147{ }
    147148
     149void BitmapTexture::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const IntRect& targetRect, const IntPoint& offset, UpdateContentsFlag updateContentsFlag)
     150{
     151    OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(targetRect.size());
     152    GraphicsContext* context = imageBuffer->context();
     153    context->setImageInterpolationQuality(textureMapper->imageInterpolationQuality());
     154    context->setTextDrawingMode(textureMapper->textDrawingMode());
     155
     156    IntRect sourceRect(targetRect);
     157    sourceRect.setLocation(offset);
     158    context->translate(-offset.x(), -offset.y());
     159    sourceLayer->paintGraphicsLayerContents(*context, sourceRect);
     160
     161    RefPtr<Image> image = imageBuffer->copyImage(DontCopyBackingStore);
     162
     163    updateContents(image.get(), targetRect, IntPoint(), updateContentsFlag);
    148164}
     165
     166} // namespace
     167
    149168#endif
  • trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.h

    r135056 r137481  
    5050class BitmapTexturePool;
    5151class CustomFilterProgram;
     52class GraphicsLayer;
    5253class TextureMapper;
    5354
    5455// A 2D texture that can be the target of software or GL rendering.
    55 class BitmapTexture  : public RefCounted<BitmapTexture> {
     56class BitmapTexture : public RefCounted<BitmapTexture> {
    5657public:
    5758    enum Flag {
     
    7677    virtual IntSize size() const = 0;
    7778    virtual void updateContents(Image*, const IntRect&, const IntPoint& offset, UpdateContentsFlag) = 0;
     79    virtual void updateContents(TextureMapper*, GraphicsLayer*, const IntRect& target, const IntPoint& offset, UpdateContentsFlag);
    7880    virtual void updateContents(const void*, const IntRect& target, const IntPoint& offset, int bytesPerLine, UpdateContentsFlag) = 0;
    7981    virtual bool isValid() const = 0;
     
    152154    virtual void endPainting() { }
    153155
    154     virtual IntSize maxTextureSize() const { return IntSize(INT_MAX, INT_MAX); }
     156    virtual IntSize maxTextureSize() const = 0;
    155157
    156158    virtual PassRefPtr<BitmapTexture> acquireTextureFromPool(const IntSize&);
  • trunk/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp

    r135517 r137481  
    7979
    8080    m_texture->updateContents(image, targetRect, sourceOffset, updateContentsFlag);
     81}
     82
     83void TextureMapperTile::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
     84{
     85    IntRect targetRect = enclosingIntRect(m_rect);
     86    targetRect.intersect(dirtyRect);
     87    if (targetRect.isEmpty())
     88        return;
     89    IntPoint sourceOffset = targetRect.location();
     90
     91    // Normalize targetRect to the texture's coordinates.
     92    targetRect.move(-m_rect.x(), -m_rect.y());
     93
     94    if (!m_texture) {
     95        m_texture = textureMapper->createTexture();
     96        m_texture->reset(targetRect.size(), BitmapTexture::SupportsAlpha);
     97    }
     98
     99    m_texture->updateContents(textureMapper, sourceLayer, targetRect, sourceOffset, updateContentsFlag);
    81100}
    82101
     
    198217}
    199218
     219void TextureMapperTiledBackingStore::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const FloatSize& totalSize, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
     220{
     221    createOrDestroyTilesIfNeeded(totalSize, textureMapper->maxTextureSize(), true);
     222    for (size_t i = 0; i < m_tiles.size(); ++i)
     223        m_tiles[i].updateContents(textureMapper, sourceLayer, dirtyRect, updateContentsFlag);
     224}
     225
    200226PassRefPtr<BitmapTexture> TextureMapperTiledBackingStore::texture() const
    201227{
  • trunk/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h

    r135517 r137481  
    7474
    7575    void updateContents(TextureMapper*, Image*, const IntRect&, BitmapTexture::UpdateContentsFlag UpdateCanModifyOriginalImageData);
     76    void updateContents(TextureMapper*, GraphicsLayer*, const IntRect&, BitmapTexture::UpdateContentsFlag UpdateCanModifyOriginalImageData);
    7677    virtual void paint(TextureMapper*, const TransformationMatrix&, float, BitmapTexture*, const unsigned exposedEdges);
    7778    virtual ~TextureMapperTile() { }
     
    9596    virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float, BitmapTexture*) OVERRIDE;
    9697    void updateContents(TextureMapper*, Image*, const FloatSize&, const IntRect&, BitmapTexture::UpdateContentsFlag);
     98    void updateContents(TextureMapper*, GraphicsLayer*, const FloatSize&, const IntRect&, BitmapTexture::UpdateContentsFlag);
    9799
    98100    void setContentsToImage(Image* image) { m_image = image; }
  • trunk/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp

    r137463 r137481  
    2222
    2323#include "FilterEffectRenderer.h"
     24#include "GraphicsLayer.h"
    2425#if PLATFORM(QT)
    2526#include "NativeImageQt.h"
     
    2930#if USE(TEXTURE_MAPPER)
    3031namespace WebCore {
     32
     33static const int s_maximumAllowedImageBufferDimension = 4096;
    3134
    3235void BitmapTextureImageBuffer::updateContents(const void* data, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine, UpdateContentsFlag)
     
    5558}
    5659
     60void BitmapTextureImageBuffer::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const IntRect& targetRect, const IntPoint& sourceOffset, UpdateContentsFlag)
     61{
     62    GraphicsContext* context = m_image->context();
     63
     64    context->clearRect(targetRect);
     65
     66    IntRect sourceRect(targetRect);
     67    sourceRect.setLocation(sourceOffset);
     68    context->save();
     69    context->translate(targetRect.x() - sourceOffset.x(), targetRect.y() - sourceOffset.y());
     70    sourceLayer->paintGraphicsLayerContents(*context, sourceRect);
     71    context->restore();
     72}
     73
    5774void BitmapTextureImageBuffer::didReset()
    5875{
     
    6380{
    6481    m_image->context()->drawImage(image, ColorSpaceDeviceRGB, targetRect, IntRect(offset, targetRect.size()), CompositeCopy);
     82}
     83
     84IntSize TextureMapperImageBuffer::maxTextureSize() const
     85{
     86    return IntSize(s_maximumAllowedImageBufferDimension, s_maximumAllowedImageBufferDimension);
    6587}
    6688
  • trunk/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h

    r134671 r137481  
    3636    inline GraphicsContext* graphicsContext() { return m_image ? m_image->context() : 0; }
    3737    virtual void updateContents(Image*, const IntRect&, const IntPoint&, UpdateContentsFlag);
     38    virtual void updateContents(TextureMapper*, GraphicsLayer*, const IntRect& target, const IntPoint& offset, UpdateContentsFlag);
    3839    virtual void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine, UpdateContentsFlag);
    3940#if ENABLE(CSS_FILTERS)
     
    6667    virtual void bindSurface(BitmapTexture* surface) OVERRIDE { m_currentSurface = surface;}
    6768    virtual void endClip() OVERRIDE { graphicsContext()->restore(); }
     69    virtual IntSize maxTextureSize() const;
    6870    virtual PassRefPtr<BitmapTexture> createTexture() OVERRIDE { return BitmapTextureImageBuffer::create(); }
    6971
Note: See TracChangeset for help on using the changeset viewer.