diff options
Diffstat (limited to 'Source')
9 files changed, 143 insertions, 21 deletions
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog index 985529158..e8af73ebf 100644 --- a/Source/WebCore/ChangeLog +++ b/Source/WebCore/ChangeLog @@ -1,4 +1,44 @@ -2012-12-06 Andras Becsi <andras.becsi@digia.com> +2012-12-12 Allan Sandfeld Jensen <allan.jensen@digia.com> + + [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-06 Andras Becsi <andras.becsi@digia.com> [Qt][Mac] Fix libxslt and libxml2 config tests https://bugs.webkit.org/show_bug.cgi?id=104164 diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp index b1e9cb10d..88b3e97bd 100644 --- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp +++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp @@ -452,25 +452,34 @@ void GraphicsLayerTextureMapper::prepareBackingStore() 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); - - 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); + + if (isShowingRepaintCounter()) + incrementRepaintCount(); + + // 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); diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h index af4940943..7051a7d97 100644 --- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h +++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h @@ -95,6 +95,7 @@ public: void setFixedToViewport(bool fixed) { m_fixedToViewport = fixed; } bool fixedToViewport() const { return m_fixedToViewport; } + void drawRepaintCounter(GraphicsContext*); private: virtual void willBeDestroyed(); void didFlushCompositingState(); @@ -102,7 +103,6 @@ private: void updateBackingStore(); void prepareBackingStore(); bool shouldHaveBackingStore() const; - void drawRepaintCounter(GraphicsContext*); void animationStartedTimerFired(Timer<GraphicsLayerTextureMapper>*); OwnPtr<TextureMapperLayer> m_layer; diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp index 7a980a9c5..43fec543c 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp @@ -20,6 +20,7 @@ #include "config.h" #include "TextureMapper.h" +#include "GraphicsLayer.h" #include "TextureMapperImageBuffer.h" #include "Timer.h" #include <wtf/CurrentTime.h> @@ -144,5 +145,23 @@ TextureMapper::TextureMapper(AccelerationMode accelerationMode) 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 diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.h b/Source/WebCore/platform/graphics/texmap/TextureMapper.h index 144209349..22efd5ff7 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapper.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.h @@ -49,10 +49,11 @@ namespace WebCore { 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 @@ public: 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 @@ public: 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&); diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp index 0ced83611..788bb12a1 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp @@ -80,6 +80,25 @@ void TextureMapperTile::updateContents(TextureMapper* textureMapper, Image* imag 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 @@ void TextureMapperTiledBackingStore::updateContents(TextureMapper* textureMapper 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) { diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h index a704ffd23..0dd2df4b1 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h @@ -73,6 +73,7 @@ public: 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 @@ public: 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; } diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp index 48540c48d..7e9e00175 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp @@ -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 @@ void BitmapTextureImageBuffer::updateContents(const void* data, const IntRect& t #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 @@ void BitmapTextureImageBuffer::updateContents(Image* image, const IntRect& targe 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(); diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h index 91ff9b005..9de6d4cbd 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h @@ -35,6 +35,7 @@ public: 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 @@ public: 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() |
