#include <QtGui/qgraphicseffect.h>
#include <QtGui/qgraphicsitem.h>
#include <QtGui/qgraphicsscene.h>
+#include <QtGui/qgraphicsview.h>
#include <QtGui/qgraphicswidget.h>
#include <QtGui/qpainter.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qpixmapcache.h>
#include <QtGui/qstyleoption.h>
+#if ENABLE(TILED_BACKING_STORE)
+#include "TiledBackingStore.h"
+#include "TiledBackingStoreClient.h"
+
+// The minimum width/height for tiling. We use the same value as the Windows implementation.
+#define GRAPHICS_LAYER_TILING_THRESHOLD 2000
+#endif
+
#define QT_DEBUG_RECACHE 0
#define QT_DEBUG_CACHEDUMP 0
};
#endif // QT_NO_GRAPHICSEFFECT
-class GraphicsLayerQtImpl : public QGraphicsObject {
+class GraphicsLayerQtImpl : public QGraphicsObject
+#if ENABLE(TILED_BACKING_STORE)
+, public virtual TiledBackingStoreClient
+#endif
+{
Q_OBJECT
public:
// ChromeClientQt::scheduleCompositingLayerSync (meaning the sync will happen ASAP)
void flushChanges(bool recursive = true, bool forceTransformUpdate = false);
+#if ENABLE(TILED_BACKING_STORE)
+ // reimplementations from TiledBackingStoreClient
+ virtual void tiledBackingStorePaintBegin();
+ virtual void tiledBackingStorePaint(GraphicsContext*, const IntRect&);
+ virtual void tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea);
+ virtual IntRect tiledBackingStoreContentsRect();
+ virtual IntRect tiledBackingStoreVisibleRect();
+ virtual Color tiledBackingStoreBackgroundColor() const;
+#endif
+
public slots:
// We need to notify the client (ie. the layer compositor) when the animation actually starts.
void notifyAnimationStarted();
int m_changeMask;
+#if ENABLE(TILED_BACKING_STORE)
+ TiledBackingStore* m_tiledBackingStore;
+#endif
+
QSizeF m_size;
struct {
QPixmapCache::Key key;
, m_opacityAnimationRunning(false)
, m_blockNotifySyncRequired(false)
, m_changeMask(NoChanges)
+#if ENABLE(TILED_BACKING_STORE)
+ , m_tiledBackingStore(0)
+#endif
#if ENABLE(3D_CANVAS)
, m_gc3D(0)
#endif
item->setParentItem(0);
}
}
-
+#if ENABLE(TILED_BACKING_STORE)
+ delete m_tiledBackingStore;
+#endif
#ifndef QT_NO_ANIMATION
// We do, however, own the animations.
QList<QWeakPointer<QAbstractAnimation> >::iterator it;
if (!m_layer->drawsContent() || m_size.isEmpty() || !m_size.isValid())
return QPixmap();
+#if ENABLE(TILED_BACKING_STORE)
+ const bool requiresTiling = (m_state.drawsContent && m_currentContent.contentType == HTMLContentType) && (m_size.width() > GRAPHICS_LAYER_TILING_THRESHOLD || m_size.height() > GRAPHICS_LAYER_TILING_THRESHOLD);
+ if (requiresTiling && !m_tiledBackingStore) {
+ m_tiledBackingStore = new TiledBackingStore(this);
+ m_tiledBackingStore->setTileCreationDelay(0);
+ setFlag(ItemUsesExtendedStyleOption, true);
+ } else if (!requiresTiling && m_tiledBackingStore) {
+ delete m_tiledBackingStore;
+ m_tiledBackingStore = 0;
+ setFlag(ItemUsesExtendedStyleOption, false);
+ }
+
+ if (m_tiledBackingStore) {
+ m_tiledBackingStore->adjustVisibleRect();
+ const QVector<QRect> rects = regionToUpdate.rects();
+ for (int i = 0; i < rects.size(); ++i)
+ m_tiledBackingStore->invalidate(rects[i]);
+ return QPixmap();
+ }
+#endif
+
QPixmap pixmap;
QRegion region = regionToUpdate;
if (QPixmapCache::find(m_backingStore.key, &pixmap)) {
void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
+#if ENABLE(TILED_BACKING_STORE)
+ // FIXME: There's currently no Qt API to know if a new region of an item is exposed outside of the paint event.
+ // Suggested for Qt: http://bugreports.qt.nokia.com/browse/QTBUG-14877.
+ if (m_tiledBackingStore)
+ m_tiledBackingStore->adjustVisibleRect();
+#endif
+
if (m_currentContent.backgroundColor.isValid())
- painter->fillRect(option->rect, QColor(m_currentContent.backgroundColor));
+ painter->fillRect(option->exposedRect, QColor(m_currentContent.backgroundColor));
switch (m_currentContent.contentType) {
case HTMLContentType:
}
}
+#if ENABLE(TILED_BACKING_STORE)
+/* \reimp (TiledBackingStoreClient.h)
+*/
+void GraphicsLayerQtImpl::tiledBackingStorePaintBegin()
+{
+}
+
+/* \reimp (TiledBackingStoreClient.h)
+*/
+void GraphicsLayerQtImpl::tiledBackingStorePaint(GraphicsContext* gc, const IntRect& rect)
+{
+ m_layer->paintGraphicsLayerContents(*gc, rect);
+}
+
+/* \reimp (TiledBackingStoreClient.h)
+*/
+void GraphicsLayerQtImpl::tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea)
+{
+ for (int i = 0; i < paintedArea.size(); ++i)
+ update(QRectF(paintedArea[i]));
+}
+
+/* \reimp (TiledBackingStoreClient.h)
+*/
+IntRect GraphicsLayerQtImpl::tiledBackingStoreContentsRect()
+{
+ return m_layer->contentsRect();
+}
+
+/* \reimp (TiledBackingStoreClient.h)
+*/
+Color GraphicsLayerQtImpl::tiledBackingStoreBackgroundColor() const
+{
+ if (m_currentContent.contentType == PixmapContentType && !m_currentContent.pixmap.hasAlphaChannel())
+ return Color(0, 0, 0);
+ // We return a transparent color so that the tiles initialize with alpha.
+ return Color(0, 0, 0, 0);
+}
+
+IntRect GraphicsLayerQtImpl::tiledBackingStoreVisibleRect()
+{
+ const QGraphicsView* view = scene()->views().isEmpty() ? 0 : scene()->views().first();
+ if (!view)
+ return mapFromScene(scene()->sceneRect()).boundingRect().toAlignedRect();
+
+ // All we get is the viewport's visible region. We have to map it to the scene and then to item coordinates.
+ return mapFromScene(view->mapToScene(view->viewport()->visibleRegion().boundingRect()).boundingRect()).boundingRect().toAlignedRect();
+}
+#endif
+
void GraphicsLayerQtImpl::notifyAnimationStarted()
{
// WebCore notifies javascript when the animation starts. Here we're letting it know.