summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform/graphics/texmap
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2013-01-15 16:12:51 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-01-16 18:00:29 +0100
commitc10f01da1e92328959cd6cf7c8951888c86ad5dc (patch)
tree8f78e4743adf3fa92ea0f409dce9d300cfcb2494 /Source/WebCore/platform/graphics/texmap
parentb43a47702cc5073a88b9a71faf9979825a23c806 (diff)
downloadqtwebkit-c10f01da1e92328959cd6cf7c8951888c86ad5dc.tar.gz
CSS Animation fails on large layers
https://bugs.webkit.org/show_bug.cgi?id=104538 Accelerated compositing was in some cases causing pixmaps to be allocated that were larger than allowed. This patch changes the non GL Texture Mapper to also using tiles, to ensure we don't try to allocate invalid pixmaps. Change-Id: I4e0681ec77a2868b2f61efecbf74aa1e1db8f652 Reviewed-by: Zeno Albisser <zeno.albisser@digia.com> Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Diffstat (limited to 'Source/WebCore/platform/graphics/texmap')
-rw-r--r--Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp43
-rw-r--r--Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h2
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapper.cpp19
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapper.h6
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp26
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h2
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp22
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h2
8 files changed, 102 insertions, 20 deletions
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()