summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/texmap
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/graphics/texmap')
-rw-r--r--Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp387
-rw-r--r--Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h107
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapper.h135
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp877
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperNode.h252
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h79
6 files changed, 1837 insertions, 0 deletions
diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
new file mode 100644
index 0000000..4698239
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
@@ -0,0 +1,387 @@
+/*
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "GraphicsLayerTextureMapper.h"
+
+#include "TextureMapperNode.h"
+
+namespace WebCore {
+
+GraphicsLayerTextureMapper::GraphicsLayerTextureMapper(GraphicsLayerClient* client)
+ : GraphicsLayer(client)
+ , m_node(new TextureMapperNode())
+ , m_changeMask(0)
+{
+}
+
+void GraphicsLayerTextureMapper::notifyChange(TextureMapperNode::ChangeMask changeMask)
+{
+ m_changeMask |= changeMask;
+ if (!client())
+ return;
+ client()->notifySyncRequired(this);
+}
+
+void GraphicsLayerTextureMapper::didSynchronize()
+{
+ m_syncQueued = false;
+ m_changeMask = 0;
+ m_pendingContent.needsDisplay = false;
+ m_pendingContent.needsDisplayRect = IntRect();
+}
+
+void GraphicsLayerTextureMapper::setName(const String& name)
+{
+ GraphicsLayer::setName(name);
+}
+
+GraphicsLayerTextureMapper::~GraphicsLayerTextureMapper()
+{
+}
+
+/* \reimp (GraphicsLayer.h): The current size might change, thus we need to update the whole display.
+*/
+void GraphicsLayerTextureMapper::setNeedsDisplay()
+{
+ m_pendingContent.needsDisplay = true;
+ notifyChange(TextureMapperNode::DisplayChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setNeedsDisplayInRect(const FloatRect& rect)
+{
+ if (m_pendingContent.needsDisplay)
+ return;
+ m_pendingContent.needsDisplayRect.unite(IntRect(rect));
+ notifyChange(TextureMapperNode::DisplayChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setParent(GraphicsLayer* layer)
+{
+ notifyChange(TextureMapperNode::ParentChange);
+ GraphicsLayer::setParent(layer);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+bool GraphicsLayerTextureMapper::setChildren(const Vector<GraphicsLayer*>& children)
+{
+ notifyChange(TextureMapperNode::ChildrenChange);
+ return GraphicsLayer::setChildren(children);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::addChild(GraphicsLayer* layer)
+{
+ notifyChange(TextureMapperNode::ChildrenChange);
+ GraphicsLayer::addChild(layer);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::addChildAtIndex(GraphicsLayer* layer, int index)
+{
+ GraphicsLayer::addChildAtIndex(layer, index);
+ notifyChange(TextureMapperNode::ChildrenChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling)
+{
+ GraphicsLayer::addChildAbove(layer, sibling);
+ notifyChange(TextureMapperNode::ChildrenChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling)
+{
+
+ GraphicsLayer::addChildBelow(layer, sibling);
+ notifyChange(TextureMapperNode::ChildrenChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+bool GraphicsLayerTextureMapper::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
+{
+ if (GraphicsLayer::replaceChild(oldChild, newChild)) {
+ notifyChange(TextureMapperNode::ChildrenChange);
+ return true;
+ }
+ return false;
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::removeFromParent()
+{
+ if (!parent())
+ return;
+ notifyChange(TextureMapperNode::ParentChange);
+ GraphicsLayer::removeFromParent();
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setMaskLayer(GraphicsLayer* value)
+{
+ if (value == maskLayer())
+ return;
+ GraphicsLayer::setMaskLayer(value);
+ notifyChange(TextureMapperNode::MaskLayerChange);
+}
+
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setReplicatedByLayer(GraphicsLayer* value)
+{
+ if (value == replicaLayer())
+ return;
+ GraphicsLayer::setReplicatedByLayer(value);
+ notifyChange(TextureMapperNode::ReplicaLayerChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setPosition(const FloatPoint& value)
+{
+ if (value == position())
+ return;
+ GraphicsLayer::setPosition(value);
+ notifyChange(TextureMapperNode::PositionChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setAnchorPoint(const FloatPoint3D& value)
+{
+ if (value == anchorPoint())
+ return;
+ GraphicsLayer::setAnchorPoint(value);
+ notifyChange(TextureMapperNode::AnchorPointChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setSize(const FloatSize& value)
+{
+ if (value == size())
+ return;
+
+ GraphicsLayer::setSize(value);
+ notifyChange(TextureMapperNode::SizeChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setTransform(const TransformationMatrix& value)
+{
+ if (value == transform())
+ return;
+
+ GraphicsLayer::setTransform(value);
+ notifyChange(TextureMapperNode::TransformChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setChildrenTransform(const TransformationMatrix& value)
+{
+ if (value == childrenTransform())
+ return;
+ GraphicsLayer::setChildrenTransform(value);
+ notifyChange(TextureMapperNode::ChildrenTransformChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setPreserves3D(bool value)
+{
+ if (value == preserves3D())
+ return;
+ GraphicsLayer::setPreserves3D(value);
+ notifyChange(TextureMapperNode::Preserves3DChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setMasksToBounds(bool value)
+{
+ if (value == masksToBounds())
+ return;
+ GraphicsLayer::setMasksToBounds(value);
+ notifyChange(TextureMapperNode::MasksToBoundsChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setDrawsContent(bool value)
+{
+ if (value == drawsContent())
+ return;
+ notifyChange(TextureMapperNode::DrawsContentChange);
+ GraphicsLayer::setDrawsContent(value);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setBackgroundColor(const Color& value)
+{
+ if (value == m_pendingContent.backgroundColor)
+ return;
+ m_pendingContent.backgroundColor = value;
+ GraphicsLayer::setBackgroundColor(value);
+ notifyChange(TextureMapperNode::BackgroundColorChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::clearBackgroundColor()
+{
+ if (!m_pendingContent.backgroundColor.isValid())
+ return;
+ m_pendingContent.backgroundColor = Color();
+ GraphicsLayer::clearBackgroundColor();
+ notifyChange(TextureMapperNode::BackgroundColorChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setContentsOpaque(bool value)
+{
+ if (value == contentsOpaque())
+ return;
+ notifyChange(TextureMapperNode::ContentsOpaqueChange);
+ GraphicsLayer::setContentsOpaque(value);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setBackfaceVisibility(bool value)
+{
+ if (value == backfaceVisibility())
+ return;
+ GraphicsLayer::setBackfaceVisibility(value);
+ notifyChange(TextureMapperNode::BackfaceVisibilityChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setOpacity(float value)
+{
+ if (value == opacity())
+ return;
+ GraphicsLayer::setOpacity(value);
+ notifyChange(TextureMapperNode::OpacityChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setContentsRect(const IntRect& value)
+{
+ if (value == contentsRect())
+ return;
+ GraphicsLayer::setContentsRect(value);
+ notifyChange(TextureMapperNode::ContentsRectChange);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setContentsToImage(Image* image)
+{
+ notifyChange(TextureMapperNode::ContentChange);
+ m_pendingContent.contentType = image ? TextureMapperNode::DirectImageContentType : TextureMapperNode::HTMLContentType;
+ m_pendingContent.image = image;
+ GraphicsLayer::setContentsToImage(image);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setContentsBackgroundColor(const Color& color)
+{
+ notifyChange(TextureMapperNode::ContentChange);
+ m_pendingContent.contentType = TextureMapperNode::ColorContentType;
+ m_pendingContent.backgroundColor = color;
+ GraphicsLayer::setContentsBackgroundColor(color);
+}
+
+
+void GraphicsLayerTextureMapper::setContentsToMedia(PlatformLayer* media)
+{
+ GraphicsLayer::setContentsToMedia(media);
+ notifyChange(TextureMapperNode::ContentChange);
+ m_pendingContent.contentType = media ? TextureMapperNode::MediaContentType : TextureMapperNode::HTMLContentType;
+ if (media)
+ m_pendingContent.media = static_cast<TextureMapperVideoLayer*>(media);
+ else
+ m_pendingContent.media = 0;
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::setContentsOrientation(CompositingCoordinatesOrientation orientation)
+{
+ if (contentsOrientation() == orientation)
+ return;
+ notifyChange(TextureMapperNode::ContentsOrientationChange);
+ GraphicsLayer::setContentsOrientation(orientation);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::syncCompositingStateForThisLayerOnly()
+{
+ m_node->syncCompositingState(this, false);
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::syncCompositingState()
+{
+ m_node->syncCompositingState(this, true);
+}
+
+/* \reimp (GraphicsLayer.h)
+ */
+NativeLayer GraphicsLayerTextureMapper::nativeLayer() const
+{
+ return m_node.get();
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+PlatformLayer* GraphicsLayerTextureMapper::platformLayer() const
+{
+ return m_node.get();
+}
+
+PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
+{
+ return new GraphicsLayerTextureMapper(client);
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
new file mode 100644
index 0000000..85fa3ee
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
@@ -0,0 +1,107 @@
+/*
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef GraphicsLayerTextureMapper_h
+#define GraphicsLayerTextureMapper_h
+
+#include "GraphicsContext.h"
+#include "GraphicsLayer.h"
+#include "GraphicsLayerClient.h"
+#include "Image.h"
+#include "TextureMapperNode.h"
+
+#if ENABLE(3D_CANVAS)
+#include "GraphicsContext3D.h"
+#endif
+
+namespace WebCore {
+
+class TextureMapperNode;
+class BitmapTexture;
+class TextureMapper;
+
+class GraphicsLayerTextureMapper : public GraphicsLayer {
+ friend class TextureMapperNode;
+
+public:
+ GraphicsLayerTextureMapper(GraphicsLayerClient*);
+ virtual ~GraphicsLayerTextureMapper();
+
+ // reimps from GraphicsLayer.h
+ virtual void setNeedsDisplay();
+ virtual void setNeedsDisplayInRect(const FloatRect&);
+ virtual void setParent(GraphicsLayer* layer);
+ virtual bool setChildren(const Vector<GraphicsLayer*>&);
+ virtual void addChild(GraphicsLayer*);
+ virtual void addChildAtIndex(GraphicsLayer*, int index);
+ virtual void addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling);
+ virtual void addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling);
+ virtual bool replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild);
+ virtual void removeFromParent();
+ virtual void setMaskLayer(GraphicsLayer* layer);
+ virtual void setPosition(const FloatPoint& p);
+ virtual void setAnchorPoint(const FloatPoint3D& p);
+ virtual void setSize(const FloatSize& size);
+ virtual void setTransform(const TransformationMatrix& t);
+ virtual void setChildrenTransform(const TransformationMatrix& t);
+ virtual void setPreserves3D(bool b);
+ virtual void setMasksToBounds(bool b);
+ virtual void setDrawsContent(bool b);
+ virtual void setBackgroundColor(const Color&);
+ virtual void clearBackgroundColor();
+ virtual void setContentsOpaque(bool b);
+ virtual void setBackfaceVisibility(bool b);
+ virtual void setOpacity(float opacity);
+ virtual void setContentsRect(const IntRect& r);
+ virtual void setReplicatedByLayer(GraphicsLayer*);
+ virtual void setContentsToImage(Image*);
+ virtual void setContentsToMedia(PlatformLayer*);
+ virtual void setContentsBackgroundColor(const Color&);
+#if ENABLE(3D_CANVAS)
+ virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*);
+ virtual void setGraphicsContext3DNeedsDisplay();
+#endif
+ virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation);
+ virtual void syncCompositingState();
+ virtual void syncCompositingStateForThisLayerOnly();
+ virtual void setName(const String& name);
+ virtual NativeLayer nativeLayer() const;
+ virtual PlatformLayer* platformLayer() const;
+
+ virtual bool addAnimation(const KeyframeValueList&, const IntSize& /*boxSize*/, const Animation*, const String& /*keyframesName*/, double /*timeOffset*/) { return false; }
+
+ void notifyChange(TextureMapperNode::ChangeMask changeMask);
+ inline TextureMapperNode::ContentData& pendingContent() { return m_pendingContent; }
+ inline int changeMask() const { return m_changeMask; }
+ void didSynchronize();
+
+private:
+ OwnPtr<TextureMapperNode> m_node;
+ bool m_syncQueued;
+ int m_changeMask;
+ TextureMapperNode::ContentData m_pendingContent;
+};
+
+inline static GraphicsLayerTextureMapper* toGraphicsLayerTextureMapper(GraphicsLayer* layer)
+{
+ return static_cast<GraphicsLayerTextureMapper*>(layer);
+}
+
+}
+#endif // GraphicsLayerTextureMapper_h
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.h b/Source/WebCore/platform/graphics/texmap/TextureMapper.h
new file mode 100644
index 0000000..589fda1
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.h
@@ -0,0 +1,135 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TextureMapper_h
+#define TextureMapper_h
+
+#if USE(ACCELERATED_COMPOSITING)
+#if (defined(QT_OPENGL_LIB))
+ #if defined(QT_OPENGL_ES_2) && !defined(TEXMAP_OPENGL_ES_2)
+ #define TEXMAP_OPENGL_ES_2
+ #endif
+#endif
+
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "IntSize.h"
+#include "TransformationMatrix.h"
+
+/*
+ TextureMapper is a mechanism that enables hardware acceleration of CSS animations (accelerated compositing) without
+ a need for a platform specific scene-graph library like CoreAnimations or QGraphicsView.
+*/
+
+namespace WebCore {
+
+class TextureMapper;
+
+// A 2D texture that can be the target of software or GL rendering.
+class BitmapTexture : public RefCounted<BitmapTexture> {
+public:
+ BitmapTexture() : m_lockCount(0) {}
+ virtual ~BitmapTexture() { }
+
+ virtual bool allowOfflineTextureUpload() const { return false; }
+ virtual void destroy() = 0;
+ virtual IntSize size() const = 0;
+ virtual bool isValid() const = 0;
+ virtual void reset(const IntSize& size, bool opaque = false)
+ {
+ m_isOpaque = opaque;
+ m_contentSize = size;
+ }
+
+ virtual void pack() { }
+ virtual void unpack() { }
+ virtual bool isPacked() const { return false; }
+
+ virtual PlatformGraphicsContext* beginPaint(const IntRect& dirtyRect) = 0;
+ virtual void endPaint() = 0;
+ virtual PlatformGraphicsContext* beginPaintMedia()
+ {
+ return beginPaint(IntRect(0, 0, size().width(), size().height()));
+ }
+ virtual void setContentsToImage(Image*) = 0;
+ virtual bool save(const String& filename) { return false; }
+
+ inline void lock() { ++m_lockCount; }
+ inline void unlock() { --m_lockCount; }
+ inline bool isLocked() { return m_lockCount; }
+ inline IntSize contentSize() const { return m_contentSize; }
+ inline void setOffset(const IntPoint& o) { m_offset = o; }
+ inline IntPoint offset() const { return m_offset; }
+
+protected:
+
+private:
+ int m_lockCount;
+ IntSize m_contentSize;
+ bool m_isOpaque;
+ IntPoint m_offset;
+};
+
+// A "context" class used to encapsulate accelerated texture mapping functions: i.e. drawing a texture
+// onto the screen or into another texture with a specified transform, opacity and mask.
+class TextureMapper {
+ friend class BitmapTexture;
+
+public:
+ static PassOwnPtr<TextureMapper> create(GraphicsContext* graphicsContext = 0);
+ virtual ~TextureMapper() { }
+
+ virtual void drawTexture(const BitmapTexture& texture, const IntRect& target, const TransformationMatrix& matrix = TransformationMatrix(), float opacity = 1.0f, const BitmapTexture* maskTexture = 0) = 0;
+
+ // makes a surface the target for the following drawTexture calls.
+ virtual void bindSurface(BitmapTexture* surface) = 0;
+ virtual void paintToTarget(const BitmapTexture& texture, const IntSize&, const TransformationMatrix& matrix, float opacity, const IntRect& visibleRect)
+ {
+ drawTexture(texture, IntRect(0, 0, texture.contentSize().width(), texture.contentSize().height()), matrix, opacity, 0);
+ }
+
+ virtual void setGraphicsContext(GraphicsContext*) { }
+ virtual void setClip(const IntRect&) = 0;
+ virtual bool allowSurfaceForRoot() const = 0;
+ virtual PassRefPtr<BitmapTexture> createTexture() = 0;
+
+ void setImageInterpolationQuality(InterpolationQuality quality) { m_interpolationQuality = quality; }
+ void setTextDrawingMode(TextDrawingModeFlags mode) { m_textDrawingMode = mode; }
+
+ InterpolationQuality imageInterpolationQuality() const { return m_interpolationQuality; }
+ TextDrawingModeFlags textDrawingMode() const { return m_textDrawingMode; }
+
+ void setViewportSize(const IntSize&);
+
+protected:
+ TextureMapper()
+ : m_interpolationQuality(InterpolationDefault)
+ , m_textDrawingMode(TextModeFill)
+ {}
+
+private:
+ InterpolationQuality m_interpolationQuality;
+ TextDrawingModeFlags m_textDrawingMode;
+};
+
+};
+
+#endif
+
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp
new file mode 100644
index 0000000..09051f9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp
@@ -0,0 +1,877 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "TextureMapperNode.h"
+
+#include "GraphicsLayerTextureMapper.h"
+
+namespace WebCore {
+
+class TextureMapperCache {
+public:
+ void mark(BitmapTexture* texture);
+
+ class Entry {
+ public:
+ RefPtr<BitmapTexture> texture;
+ Entry() : previousCost(0) { }
+ inline int computeCost() const
+ {
+ if (!texture || !texture->isValid() || texture->isPacked())
+ return 0;
+ const IntSize textureSize = texture->size();
+ // An image's cost in bytes is width * height * bytes per pixel (4).
+ return textureSize.width() * textureSize.height() * 4;
+ }
+ Entry(BitmapTexture* newTexture)
+ : texture(newTexture)
+ {
+ }
+ bool operator==(const Entry& other) const { return texture == other.texture; }
+ int previousCost;
+ };
+
+ TextureMapperCache()
+ : m_totalCost(0)
+ {
+ }
+
+ void purge();
+ Vector<Entry> m_data;
+ int m_totalCost;
+#ifndef TEXMAP_TEXTURE_CACHE_KBS
+#define TEXMAP_TEXTURE_CACHE_KBS 24 * 1024
+#endif
+ static const int MaxCost = TEXMAP_TEXTURE_CACHE_KBS * 1024;
+ static const int PurgeAmount = MaxCost / 4;
+};
+
+
+void TextureMapperCache::purge()
+{
+ const int size = m_data.size();
+
+ if (m_totalCost <= TextureMapperCache::MaxCost)
+ return;
+
+ // Ensure that we have the right count. It might be inaccurate if content changed size.
+ // We only do this when we're actually ready to purge.
+ m_totalCost = 0;
+ for (int i = 0; i < size; ++i)
+ m_totalCost += m_data[i].computeCost();
+
+ for (int i = size-1; i >= 0 && m_totalCost > TextureMapperCache::MaxCost - TextureMapperCache::PurgeAmount; --i) {
+ Entry& entry = m_data[i];
+ if (entry.texture->isLocked() || !entry.texture->isValid() || entry.texture->isPacked())
+ continue;
+ m_totalCost -= entry.previousCost;
+ entry.texture->pack();
+ m_data.remove(i);
+ }
+}
+
+void TextureMapperCache::mark(BitmapTexture* texture)
+{
+ if (!texture || !texture->isValid())
+ return;
+
+ Entry entry(texture);
+ size_t index = m_data.find(entry);
+ if (!index)
+ return;
+
+ int previousCost = 0;
+
+ if (index < m_data.size()) {
+ previousCost = m_data[index].previousCost;
+ m_data.remove(index);
+ }
+ const int cost = entry.computeCost();
+ m_totalCost -= previousCost;
+ m_totalCost += (entry.previousCost = cost);
+ m_data.prepend(entry);
+}
+
+class TextureMapperCacheLock {
+public:
+ TextureMapperCacheLock(BitmapTexture* texture) : m_texture(texture)
+ {
+ if (m_texture)
+ m_texture->lock();
+ }
+ ~TextureMapperCacheLock()
+ {
+ if (m_texture)
+ m_texture->unlock();
+ }
+
+private:
+ RefPtr<BitmapTexture> m_texture;
+};
+
+
+TextureMapperCache* TextureMapperNode::cache()
+{
+ TextureMapperNode* root = rootLayer();
+ if (!root)
+ return 0;
+ if (!root->m_cache)
+ root->m_cache = new TextureMapperCache;
+ return root->m_cache;
+}
+
+void TextureMapperNode::setNeedsDisplayInRect(IntRect rect)
+{
+ if (m_platformClient) {
+ if (m_state.hasSurfaceDescendants) {
+ m_platformClient->setNeedsDisplay();
+ return;
+ }
+ rect.intersect(IntRect(0, 0, m_size.width(), m_size.height()));
+ if (rect.isEmpty())
+ return;
+ m_platformClient->setNeedsDisplayInRect(rect);
+ return;
+ }
+
+ if (!m_parent)
+ return;
+
+ m_parent->setNeedsDisplayInRect(rect);
+}
+
+void TextureMapperNode::setNeedsDisplay()
+{
+ if (m_effectTarget)
+ m_effectTarget->setNeedsDisplay();
+ if (m_transforms.targetBoundingRect.isEmpty())
+ return;
+ if (m_state.drawsContent || m_currentContent.contentType != HTMLContentType)
+ setNeedsDisplayInRect(m_transforms.targetBoundingRect);
+}
+
+void TextureMapperNode::setPlatformLayerClient(TextureMapperLayerClient* client)
+{
+ m_platformClient = client;
+}
+
+int TextureMapperNode::compareGraphicsLayersZValue(const void* a, const void* b)
+{
+ typedef const TextureMapperNode* NodePtr;
+ const NodePtr* nodeA = static_cast<const NodePtr*>(a);
+ const NodePtr* nodeB = static_cast<const NodePtr*>(b);
+ return int(((*nodeA)->m_transforms.centerZ - (*nodeB)->m_transforms.centerZ) * 1000);
+}
+
+void TextureMapperNode::sortByZOrder(Vector<TextureMapperNode* >& array, int first, int last)
+{
+ qsort(array.data(), array.size(), sizeof(TextureMapperNode*), TextureMapperNode::compareGraphicsLayersZValue);
+}
+
+bool TextureMapperNode::hasSurfaceDescendants() const
+{
+ if (m_layerType == ClipLayer || m_layerType == TransparencyLayer || m_state.replicaLayer)
+ return true;
+
+ const int size = m_children.size();
+ for (int i = 0; i < size; ++i) {
+ if (TextureMapperNode* child = m_children[i]) {
+ if (child->hasSurfaceDescendants())
+ return true;
+ }
+ }
+ return false;
+}
+
+int TextureMapperNode::countDescendantsWithContent() const
+{
+ if (!m_state.visible || m_state.opacity < 0.001)
+ return 0;
+
+ int descendantsWithContent = (m_state.drawsContent || m_currentContent.contentType != HTMLContentType) ? 1 : 0;
+
+ const int size = m_children.size();
+ for (int i = 0; i < size; ++i) {
+ if (TextureMapperNode* child = m_children[i])
+ descendantsWithContent += child->countDescendantsWithContent();
+ }
+
+ return descendantsWithContent;
+}
+
+TextureMapperNode* TextureMapperNode::toTextureMapperNode(GraphicsLayer* layer)
+{
+ return layer ? static_cast<TextureMapperNode*>(layer->platformLayer()) : 0;
+}
+
+void TextureMapperNode::computeLayerType()
+{
+ const bool selfHasContent = m_state.drawsContent || (m_currentContent.contentType != HTMLContentType);
+ const bool hasDescendantsWithContent = m_state.descendantsWithContent - (selfHasContent ? 1 : 0);
+ const bool hasTransparency = m_state.opacity < 0.99 || m_state.maskLayer;
+ const bool hasReplica = m_state.replicaLayer;
+
+ // DefaultLayer: draws itself and its children directly to the current framebuffer.
+ // any layer that doesn't conform to the other rules is a DefaultLayer.
+ m_layerType = DefaultLayer;
+
+ // RootLayer: the top level. Draws to a framebuffer, and the target texture draws into the viewport.
+ // only one layer is the root layer.
+ if (!m_parent && !m_effectTarget) {
+ m_layerType = RootLayer;
+ return;
+ }
+
+ // A layer with no contents is always a default layer.
+ if (!m_state.descendantsWithContent)
+ return;
+
+ // ClipLayer: creates a new framebuffer, the size of the layer, and then paints it to the enclosing BitmapTexture with the layer's transform/opacity.
+ // A clip layer is a layer that masks to bounds, doesn't preserve 3D, has children, and has a transparency/mask or a non-rectangular transform.
+ if (hasDescendantsWithContent && m_state.maskLayer) {
+ m_layerType = ClipLayer;
+ return;
+ }
+
+ // ScissorLayer: draws to the current framebuffer, and applies an extra scissor before drawing its children.
+ // A scissor layer is a layer with children that masks to bounds, is not a transparency layer, and has a rectangular clip.
+ if (m_state.masksToBounds && hasDescendantsWithContent) {
+ if (hasTransparency || !m_state.transform.isIdentityOrTranslation() || m_parent->m_state.preserves3D)
+ m_layerType = ClipLayer;
+ else
+ m_layerType = ScissorLayer;
+ return;
+ }
+
+ // TransparencyLayer: creates a new framebuffer idetical in size to the current framebuffer. Then draws the fb's texture to the current framebuffer with identity transform.
+ // Used for layers with children and transparency/mask that preserve 3D or don't mask to bounds.
+ if ((hasReplica && hasDescendantsWithContent) || (hasReplica && hasTransparency) || (hasTransparency && m_state.descendantsWithContent > 1))
+ m_layerType = TransparencyLayer;
+}
+
+void TextureMapperNode::initializeTextureMapper(TextureMapper* textureMapper)
+{
+ if (m_texture)
+ return;
+ m_surface = textureMapper->createTexture();
+ m_replicaSurface = textureMapper->createTexture();
+ m_texture = textureMapper->createTexture();
+ cache()->mark(m_texture.get());
+}
+
+TextureMapperNode::TextureMapperNode()
+ : m_layerType(DefaultLayer)
+ , m_surface(0)
+ , m_parent(0)
+ , m_effectTarget(0)
+ , m_platformClient(0)
+ , m_cache(0)
+{
+}
+
+TextureMapperNode* TextureMapperNode::rootLayer()
+{
+ if (m_effectTarget)
+ return m_effectTarget->rootLayer();
+ if (m_parent)
+ return m_parent->rootLayer();
+ return this;
+}
+
+void TextureMapperNode::invalidateTransform()
+{
+ m_transforms.dirty = true;
+ if (m_layerType != ClipLayer)
+ m_state.dirty = true;
+ if (m_state.replicaLayer)
+ m_state.replicaLayer->invalidateTransform();
+ const int size = m_children.size();
+ for (int i = 0; i < size; ++i) {
+ if (TextureMapperNode* layer = m_children[i])
+ layer->invalidateTransform();
+ }
+}
+
+void TextureMapperNode::computeLocalTransform()
+{
+ if (!m_transforms.localDirty)
+ return;
+ const float originX = m_state.anchorPoint.x() * m_size.width();
+ const float originY = m_state.anchorPoint.y() * m_size.height();
+ m_transforms.local =
+ TransformationMatrix()
+ .translate3d(originX + m_state.pos.x(), originY + m_state.pos.y(), m_state.anchorPoint.z())
+ .multLeft(m_state.transform)
+ .translate3d(-originX, -originY, -m_state.anchorPoint.z());
+ m_transforms.localDirty = false;
+}
+
+void TextureMapperNode::flattenTo2DSpaceIfNecessary()
+{
+ if (m_state.preserves3D)
+ return;
+
+ m_transforms.forDescendants.setM13(0);
+ m_transforms.forDescendants.setM23(0);
+ m_transforms.forDescendants.setM31(0);
+ m_transforms.forDescendants.setM32(0);
+ m_transforms.forDescendants.setM33(1);
+ m_transforms.forDescendants.setM34(0);
+ m_transforms.forDescendants.setM43(0);
+}
+
+IntSize TextureMapperNode::nearestSurfaceSize() const
+{
+ if (m_layerType == ClipLayer || m_layerType == RootLayer)
+ return m_surface && !m_surface->size().isEmpty() ? m_surface->size() : m_size;
+ return m_parent->nearestSurfaceSize();
+}
+
+void TextureMapperNode::computeReplicaTransform()
+{
+ if (!m_state.replicaLayer)
+ return;
+
+ m_nearestSurfaceSize = nearestSurfaceSize();
+
+ if (m_layerType != TransparencyLayer) {
+ m_transforms.replica = TransformationMatrix(m_transforms.target).multLeft(m_state.replicaLayer->m_transforms.local);
+ return;
+ }
+
+ const float originX = m_transforms.target.m41();
+ const float originY = m_transforms.target.m42();
+ m_transforms.replica =
+ TransformationMatrix()
+ .translate(originX, originY)
+ .multLeft(m_state.replicaLayer->m_transforms.local)
+ .translate(-originX, -originY);
+}
+
+void TextureMapperNode::computeTransformations()
+{
+ if (!m_transforms.dirty)
+ return;
+
+ m_transforms.dirty = false;
+ if ((m_size.isEmpty() && m_state.masksToBounds))
+ return;
+
+ TextureMapperNode* parent = m_parent;
+ computeLocalTransform();
+
+ m_transforms.target = TransformationMatrix(parent ? parent->m_transforms.forDescendants : TransformationMatrix()).multLeft(m_transforms.local);
+ m_transforms.forDescendants = (m_layerType == ClipLayer ? TransformationMatrix() : m_transforms.target);
+
+ if (m_effectTarget)
+ return;
+
+ m_transforms.targetBoundingRect = IntRect(m_transforms.target.mapRect(entireRect()));
+ if (m_state.replicaLayer)
+ m_state.replicaLayer->computeTransformations();
+
+ flattenTo2DSpaceIfNecessary();
+
+ if (!m_state.backfaceVisibility && m_transforms.target.inverse().m33() < 0) {
+ m_state.visible = false;
+ return;
+ }
+ m_state.visible = true;
+
+ if (parent && parent->m_state.preserves3D)
+ m_transforms.centerZ = m_transforms.target.mapPoint(FloatPoint3D(m_size.width() / 2, m_size.height() / 2, 0)).z();
+
+ if (!m_children.size())
+ return;
+
+ if (m_state.childrenTransform.isIdentity())
+ return;
+
+ const FloatPoint centerPoint = FloatPoint(m_size.width() / 2, m_size.height() / 2);
+ if (m_transforms.perspectiveDirty)
+ m_transforms.perspective = TransformationMatrix()
+ .translate(centerPoint.x(), centerPoint.y())
+ .multLeft(m_state.childrenTransform)
+ .translate(-centerPoint.x(), -centerPoint.y());
+ m_transforms.perspectiveDirty = false;
+ m_transforms.forDescendants.multLeft(m_transforms.perspective);
+}
+
+void TextureMapperNode::uploadTextureFromContent(TextureMapper* textureMapper, const IntRect& visibleRect, GraphicsLayer* layer)
+{
+ if (m_size.isEmpty() || !layer) {
+ m_texture->destroy();
+ return;
+ }
+
+ if (m_currentContent.contentType == DirectImageContentType) {
+ if (m_currentContent.image)
+ m_texture->setContentsToImage(m_currentContent.image.get());
+ return;
+ }
+
+ if (m_currentContent.contentType == MediaContentType) {
+ if (!m_currentContent.media)
+ return;
+ m_texture->reset(m_size, true);
+ PlatformGraphicsContext* platformContext = m_texture->beginPaintMedia();
+ GraphicsContext context(platformContext);
+ m_currentContent.media->paint(&context);
+ m_texture->endPaint();
+ return;
+ }
+
+ const bool needsReset = (m_texture->contentSize() != m_size) || !m_texture->isValid();
+ if ((m_currentContent.contentType != HTMLContentType)
+ || (!m_currentContent.needsDisplay && m_currentContent.needsDisplayRect.isEmpty() && !needsReset))
+ return;
+
+ IntRect dirtyRect = IntRect(0, 0, m_size.width(), m_size.height());
+ if (!needsReset && !m_currentContent.needsDisplay)
+ dirtyRect.intersect(m_currentContent.needsDisplayRect);
+
+ if (needsReset)
+ m_texture->reset(m_size, m_state.contentsOpaque);
+
+ {
+ GraphicsContext context(m_texture->beginPaint(dirtyRect));
+ if (textureMapper) {
+ context.setImageInterpolationQuality(textureMapper->imageInterpolationQuality());
+ context.setTextDrawingMode(textureMapper->textDrawingMode());
+ }
+ layer->paintGraphicsLayerContents(context, dirtyRect);
+ }
+ m_texture->endPaint();
+ m_currentContent.needsDisplay = false;
+}
+
+
+void TextureMapperNode::paint(TextureMapper* textureMapper, const TextureMapperContentLayer::PaintOptions& options)
+{
+ ASSERT(m_layerType == RootLayer);
+ if (m_size.isEmpty())
+ return;
+
+ TexmapPaintOptions opt;
+ opt.opacity = 1;
+ opt.rootLayer = this;
+ opt.scissorRect = options.targetRect;
+ opt.visibleRect = options.visibleRect;
+ opt.textureMapper = textureMapper;
+ opt.surface = 0;
+ opt.cache = m_cache;
+ paintRecursive(opt);
+
+ if (textureMapper->allowSurfaceForRoot() || m_state.hasSurfaceDescendants) {
+ textureMapper->bindSurface(0);
+ textureMapper->paintToTarget(*m_surface.get(), options.viewportSize, options.transform, options.opacity * m_state.opacity, options.targetRect);
+ }
+ m_cache->purge();
+}
+
+void TextureMapperNode::paintSelf(const TexmapPaintOptions& options)
+{
+ if (m_size.isEmpty() || (!m_state.drawsContent && m_currentContent.contentType == HTMLContentType))
+ return;
+
+ RefPtr<BitmapTexture> replicaMaskTexture;
+ m_texture->unpack();
+
+ RefPtr<BitmapTexture> maskTexture = m_state.maskLayer ? m_state.maskLayer->m_texture : 0;
+ if (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer)
+ replicaMaskTexture = m_state.replicaLayer->m_state.maskLayer->m_texture;
+
+ if (maskTexture)
+ maskTexture->unpack();
+
+ if (replicaMaskTexture)
+ replicaMaskTexture->unpack();
+
+ const float opacity = options.isSurface ? 1 : options.opacity;
+
+ if (m_state.replicaLayer && !options.isSurface)
+ options.textureMapper->drawTexture(*m_texture.get(), replicaRect(), m_transforms.replica,
+ opacity * m_state.replicaLayer->m_state.opacity,
+ replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get());
+
+ const IntRect rect = m_layerType == ClipLayer ? entireRect() : targetRect();
+ const TransformationMatrix transform = m_layerType == ClipLayer ? TransformationMatrix() : m_transforms.target;
+ options.textureMapper->drawTexture(*m_texture.get(), rect, transform, opacity, options.isSurface ? 0 : maskTexture.get());
+ options.cache->mark(m_texture.get());
+}
+
+bool TextureMapperNode::paintReplica(const TexmapPaintOptions& options)
+{
+ BitmapTexture& texture = *m_surface.get();
+ TextureMapperNode* replica = m_state.replicaLayer;
+ RefPtr<BitmapTexture> maskTexture;
+ if (TextureMapperNode* mask = m_state.maskLayer)
+ maskTexture = mask->m_texture;
+ RefPtr<BitmapTexture> replicaMaskTexture;
+ if (!replica)
+ return false;
+
+ if (replica && replica->m_state.maskLayer)
+ replicaMaskTexture = replica->m_state.maskLayer->m_texture;
+
+ if (replicaMaskTexture)
+ replicaMaskTexture->unpack();
+ ASSERT(m_replicaSurface);
+ m_replicaSurface->reset(options.surface->size());
+ m_replicaSurface->setOffset(options.surface->offset());
+ options.cache->mark(m_replicaSurface.get());
+ options.textureMapper->bindSurface(m_replicaSurface.get());
+ options.textureMapper->drawTexture(texture, replicaRect(), m_transforms.replica, replica->m_state.opacity, replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get());
+ options.textureMapper->drawTexture(texture, IntRect(IntPoint(0, 0), options.surface->size()), TransformationMatrix(), 1.0f, maskTexture.get());
+ options.textureMapper->bindSurface(options.surface);
+ options.cache->mark(options.surface);
+ options.textureMapper->drawTexture(*m_replicaSurface.get(), IntRect(IntPoint(0, 0), options.surface->size()), TransformationMatrix(), options.opacity, 0);
+ return true;
+}
+
+void TextureMapperNode::paintSurface(const TexmapPaintOptions& options)
+{
+ if (m_layerType == RootLayer || m_layerType == DefaultLayer || m_layerType == ScissorLayer)
+ return;
+
+ RefPtr<BitmapTexture> maskTexture;
+ if (TextureMapperNode* mask = m_state.maskLayer)
+ maskTexture = mask->m_texture;
+
+ ASSERT(m_surface);
+ BitmapTexture& texture = *m_surface.get();
+ if (maskTexture)
+ maskTexture->unpack();
+ texture.unpack();
+
+ if (paintReplica(options))
+ return;
+
+ options.textureMapper->bindSurface(options.surface);
+ options.textureMapper->drawTexture(texture,
+ m_layerType == TransparencyLayer ? IntRect(IntPoint(0, 0), options.surface->size()) :
+ targetRect(),
+ m_layerType == TransparencyLayer ? TransformationMatrix() : m_transforms.target,
+ options.opacity, maskTexture.get());
+ options.cache->mark(&texture);
+}
+
+void TextureMapperNode::paintSelfAndChildren(const TexmapPaintOptions& options, TexmapPaintOptions& optionsForDescendants)
+{
+ bool didPaintSelf = false;
+ if (!m_state.preserves3D || m_children.isEmpty()) {
+ paintSelf(options);
+ didPaintSelf = true;
+ }
+
+ if (m_children.isEmpty() && !options.isSurface)
+ return;
+
+ if (m_layerType == ScissorLayer)
+ optionsForDescendants.scissorRect.intersect(m_transforms.target.mapRect(IntRect(0, 0, m_size.width(), m_size.height())));
+
+ for (int i = 0; i < m_children.size(); ++i) {
+ TextureMapperNode* layer = m_children[i];
+ if (!layer)
+ continue;
+
+ if (!didPaintSelf && layer->m_transforms.centerZ >= 0) {
+ paintSelf(options);
+ didPaintSelf = true;
+ }
+ layer->paintRecursive(optionsForDescendants);
+ if (options.isSurface) {
+ ASSERT(m_surface);
+ options.cache->mark(m_surface.get());
+ options.textureMapper->bindSurface(m_surface.get());
+ }
+ }
+ if (!didPaintSelf) {
+ paintSelf(options);
+ didPaintSelf = true;
+ }
+}
+
+void TextureMapperNode::paintRecursive(TexmapPaintOptions options)
+{
+ bool isDirty = m_state.dirty;
+ m_state.dirty = false;
+
+ if ((m_size.isEmpty() && (m_state.masksToBounds
+ || m_children.isEmpty())) || !m_state.visible || options.opacity < 0.01 || m_state.opacity < 0.01)
+ return;
+
+ computeReplicaTransform();
+
+ if (m_state.maskLayer)
+ m_state.maskLayer->m_state.dirty = false;
+
+ if (m_state.replicaLayer) {
+ m_state.replicaLayer->m_state.dirty = false;
+ if (m_state.replicaLayer->m_state.maskLayer)
+ m_state.replicaLayer->m_state.maskLayer->m_state.dirty = false;
+ }
+
+ const bool isSurface = (m_layerType == ClipLayer
+ || m_layerType == TransparencyLayer
+ || (m_layerType == RootLayer
+ && (options.textureMapper->allowSurfaceForRoot() || m_state.hasSurfaceDescendants)
+ ));
+
+ const IntRect boundingRectfromNearestSurface = m_transforms.targetBoundingRect;
+
+ options.opacity *= m_state.opacity;
+
+ TexmapPaintOptions optionsForDescendants(options);
+ optionsForDescendants.opacity = isSurface ? 1 : options.opacity;
+ options.isSurface = isSurface;
+
+ if (m_layerType == ClipLayer) {
+ optionsForDescendants.visibleRect = TransformationMatrix().translate(-boundingRectfromNearestSurface.x(), -boundingRectfromNearestSurface.y()).mapRect(options.visibleRect);
+ optionsForDescendants.scissorRect = IntRect(0, 0, m_size.width(), m_size.height());
+ }
+
+ if (m_layerType == ScissorLayer)
+ optionsForDescendants.scissorRect.intersect(m_transforms.targetBoundingRect);
+ options.textureMapper->setClip(optionsForDescendants.scissorRect);
+
+ TextureMapperCacheLock(m_texture.get());
+ TextureMapperCacheLock(m_surface.get());
+ TextureMapperCacheLock(m_replicaSurface.get());
+
+ options.cache->purge();
+
+ if (isSurface) {
+ ASSERT(m_surface);
+ if (!m_surface->isValid())
+ isDirty = true;
+ if (m_state.tiled) {
+ m_surface->reset(options.visibleRect.size());
+ m_surface->setOffset(options.visibleRect.location());
+ } else if (isDirty)
+ m_surface->reset(m_layerType == TransparencyLayer ? options.surface->size() : m_size);
+ options.cache->mark(m_surface.get());
+ options.textureMapper->bindSurface(m_surface.get());
+ optionsForDescendants.surface = m_surface.get();
+ } else if (m_surface)
+ m_surface->destroy();
+
+ if (isDirty || !isSurface || m_state.tiled || !m_surface->isValid())
+ paintSelfAndChildren(options, optionsForDescendants);
+
+ paintSurface(options);
+}
+
+TextureMapperNode::~TextureMapperNode()
+{
+ setNeedsDisplay();
+ {
+ const int childrenSize = m_children.size();
+ for (int i = childrenSize-1; i >= 0; --i) {
+ ASSERT(m_children[i]->m_parent == this);
+ m_children[i]->m_parent = 0;
+ }
+ }
+ if (m_parent)
+ m_parent->m_children.remove(m_parent->m_children.find(this));
+ if (m_cache)
+ delete m_cache;
+}
+
+void TextureMapperNode::performPostSyncOperations()
+{
+ const LayerType prevLayerType = m_layerType;
+ computeLayerType();
+ if (prevLayerType != m_layerType)
+ m_state.dirty = true;
+ if (m_transforms.dirty)
+ setNeedsDisplay();
+
+ computeTransformations();
+ if (m_state.maskLayer && !m_state.dirty)
+ m_state.dirty = m_state.maskLayer->m_state.dirty;
+ if (m_state.replicaLayer && !m_state.dirty)
+ m_state.dirty = m_state.replicaLayer->m_state.dirty;
+
+ const int size = m_children.size();
+
+ for (int i = size - 1; i >= 0; --i) {
+ TextureMapperNode* layer = m_children[i];
+
+ layer->performPostSyncOperations();
+ if (!m_state.dirty)
+ m_state.dirty = layer->m_state.dirty;
+ }
+ m_state.hasSurfaceDescendants = hasSurfaceDescendants();
+ if (m_state.dirty)
+ m_state.descendantsWithContent = countDescendantsWithContent();
+
+ if (m_state.preserves3D)
+ sortByZOrder(m_children, 0, size);
+ if (m_state.dirty)
+ setNeedsDisplay();
+}
+
+void TextureMapperNode::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, bool recurse)
+{
+ TextureMapper* textureMapper = rootLayer()->m_platformClient->textureMapper();
+ syncCompositingStateInternal(graphicsLayer, recurse, textureMapper);
+ performPostSyncOperations();
+}
+
+void TextureMapperNode::syncCompositingStateSelf(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper)
+{
+ const int changeMask = graphicsLayer->changeMask();
+ initializeTextureMapper(textureMapper);
+ const TextureMapperNode::ContentData& pendingContent = graphicsLayer->pendingContent();
+ if (changeMask == NoChanges && pendingContent.needsDisplayRect.isEmpty() && !pendingContent.needsDisplay)
+ return;
+
+ setNeedsDisplay();
+ if (m_parent)
+ m_parent->m_state.dirty = true;
+
+ if (m_currentContent.contentType == HTMLContentType && (changeMask & ParentChange)) {
+ // The WebCore compositor manages item ownership. We have to make sure graphicsview doesn't
+ // try to snatch that ownership.
+
+ if (!graphicsLayer->parent())
+ m_parent = 0;
+ else
+ m_parent = toTextureMapperNode(graphicsLayer->parent());
+
+ if (!graphicsLayer->parent() && m_parent) {
+ size_t index = m_parent->m_children.find(this);
+ m_parent->m_children.remove(index);
+ }
+ }
+
+ if (changeMask & ChildrenChange) {
+ m_children.clear();
+ for (size_t i = 0; i < graphicsLayer->children().size(); ++i) {
+ if (TextureMapperNode* child = toTextureMapperNode(graphicsLayer->children()[i])) {
+ if (!child)
+ continue;
+ m_children.append(child);
+ child->m_parent = this;
+ }
+ }
+ m_state.dirty = true;
+ }
+
+ if (changeMask & (SizeChange | ContentsRectChange)) {
+ IntSize wantedSize = IntSize(graphicsLayer->size().width(), graphicsLayer->size().height());
+ if (wantedSize.isEmpty() && pendingContent.contentType == HTMLContentType)
+ wantedSize = IntSize(graphicsLayer->contentsRect().width(), graphicsLayer->contentsRect().height());
+
+ if (wantedSize != m_size) {
+ m_size = IntSize(wantedSize.width(), wantedSize.height());
+ if (m_platformClient)
+ m_platformClient->setSizeChanged(m_size);
+ const bool needsTiling = m_size.width() > 2000 || m_size.height() > 2000;
+ if (m_state.tiled != needsTiling)
+ m_state.tiled = needsTiling;
+ m_state.dirty = true;
+ }
+ }
+
+ if (changeMask & MaskLayerChange) {
+ if (TextureMapperNode* layer = toTextureMapperNode(graphicsLayer->maskLayer()))
+ layer->m_effectTarget = this;
+ }
+
+ if (changeMask & ReplicaLayerChange) {
+ if (TextureMapperNode* layer = toTextureMapperNode(graphicsLayer->replicaLayer()))
+ layer->m_effectTarget = this;
+ }
+
+ if (changeMask & (TransformChange | SizeChange | AnchorPointChange | PositionChange))
+ m_transforms.localDirty = true;
+
+ if (changeMask & (ChildrenTransformChange | SizeChange))
+ m_transforms.perspectiveDirty = true;
+
+ if (changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange | ContentsRectChange | BackfaceVisibilityChange | PositionChange | MaskLayerChange | DrawsContentChange | ContentChange | ReplicaLayerChange)) {
+ // Due to the differences between the way WebCore handles transforms and the way Qt handles transforms,
+ // all these elements affect the transforms of all the descendants.
+ invalidateTransform();
+ }
+
+ if (changeMask & DisplayChange)
+ m_state.dirty = true;
+
+ m_state.maskLayer = toTextureMapperNode(graphicsLayer->maskLayer());
+ m_state.replicaLayer = toTextureMapperNode(graphicsLayer->replicaLayer());
+ m_state.pos = graphicsLayer->position();
+ m_state.anchorPoint = graphicsLayer->anchorPoint();
+ m_state.size = graphicsLayer->size();
+ m_state.transform = graphicsLayer->transform();
+ m_state.contentsRect = graphicsLayer->contentsRect();
+ m_state.opacity = graphicsLayer->opacity();
+ m_state.contentsRect = graphicsLayer->contentsRect();
+ m_state.preserves3D = graphicsLayer->preserves3D();
+ m_state.masksToBounds = graphicsLayer->masksToBounds();
+ m_state.drawsContent = graphicsLayer->drawsContent();
+ m_state.contentsOpaque = graphicsLayer->contentsOpaque();
+ m_state.backfaceVisibility = graphicsLayer->backfaceVisibility();
+ m_state.childrenTransform = graphicsLayer->childrenTransform();
+ m_currentContent.contentType = pendingContent.contentType;
+ m_currentContent.image = pendingContent.image;
+ m_currentContent.media = pendingContent.media;
+ m_currentContent.backgroundColor = pendingContent.backgroundColor;
+ m_currentContent.needsDisplay = m_currentContent.needsDisplay || pendingContent.needsDisplay;
+ m_currentContent.needsDisplayRect.unite(pendingContent.needsDisplayRect);
+
+}
+
+void TextureMapperNode::syncCompositingStateInternal(GraphicsLayerTextureMapper* graphicsLayer, bool recurse, TextureMapper* textureMapper)
+{
+ syncCompositingStateSelf(graphicsLayer, textureMapper);
+
+ graphicsLayer->didSynchronize();
+
+ if (m_state.maskLayer) {
+ m_state.maskLayer->syncCompositingStateInternal(toGraphicsLayerTextureMapper(graphicsLayer->maskLayer()), false, textureMapper);
+ if (m_state.maskLayer->m_size.isEmpty())
+ m_state.maskLayer->m_size = m_size;
+ }
+
+ if (m_state.replicaLayer)
+ m_state.replicaLayer->syncCompositingStateInternal(toGraphicsLayerTextureMapper(graphicsLayer->replicaLayer()), false, textureMapper);
+
+ if (m_state.dirty)
+ uploadTextureFromContent(textureMapper, m_state.visibleRect, graphicsLayer);
+
+ m_currentContent.needsDisplayRect = IntRect();
+ m_currentContent.needsDisplay = false;
+
+ if (!recurse)
+ return;
+
+ Vector<GraphicsLayer*> children = graphicsLayer->children();
+ for (int i = children.size() - 1; i >= 0; --i) {
+ TextureMapperNode* node = toTextureMapperNode(children[i]);
+ if (!node)
+ continue;
+ node->syncCompositingStateInternal(toGraphicsLayerTextureMapper(children[i]), true, textureMapper);
+ }
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h
new file mode 100644
index 0000000..9694043
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h
@@ -0,0 +1,252 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TextureMapperNode_h
+#define TextureMapperNode_h
+
+#include "CurrentTime.h"
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "GraphicsLayer.h"
+#include "HashMap.h"
+#include "Image.h"
+#include "RefCounted.h"
+#include "TextureMapper.h"
+#include "TextureMapperPlatformLayer.h"
+#include "Timer.h"
+#include "TransformOperations.h"
+#include "TranslateTransformOperation.h"
+#include "UnitBezier.h"
+
+namespace WebCore {
+
+class TextureMapperNode;
+class TextureMapperCache;
+class GraphicsLayerTextureMapper;
+
+struct TexmapPaintOptions {
+ BitmapTexture* surface;
+ TextureMapper* textureMapper;
+ TextureMapperNode* rootLayer;
+ float opacity;
+ IntRect scissorRect;
+ IntRect visibleRect;
+ bool isSurface;
+ TextureMapperCache* cache;
+};
+
+class TextureMapperNode : public TextureMapperContentLayer {
+
+public:
+ // This set of flags help us defer which properties of the layer have been
+ // modified by the compositor, so we can know what to look for in the next flush.
+ enum ChangeMask {
+ NoChanges = 0,
+
+ ParentChange = (1L << 0),
+ ChildrenChange = (1L << 1),
+ MaskLayerChange = (1L << 2),
+ PositionChange = (1L << 3),
+
+ AnchorPointChange = (1L << 4),
+ SizeChange = (1L << 5),
+ TransformChange = (1L << 6),
+ ContentChange = (1L << 7),
+
+ ContentsOrientationChange = (1L << 9),
+ OpacityChange = (1L << 10),
+ ContentsRectChange = (1L << 11),
+
+ Preserves3DChange = (1L << 12),
+ MasksToBoundsChange = (1L << 13),
+ DrawsContentChange = (1L << 14),
+ ContentsOpaqueChange = (1L << 15),
+
+ BackfaceVisibilityChange = (1L << 16),
+ ChildrenTransformChange = (1L << 17),
+ DisplayChange = (1L << 18),
+ BackgroundColorChange = (1L << 19),
+
+ ReplicaLayerChange = (1L << 20)
+ };
+ // The compositor lets us special-case images and colors, so we try to do so.
+ enum ContentType { HTMLContentType, DirectImageContentType, ColorContentType, MediaContentType, Canvas3DContentType};
+ struct ContentData {
+ IntRect needsDisplayRect;
+ bool needsDisplay;
+ Color backgroundColor;
+
+ ContentType contentType;
+ RefPtr<Image> image;
+ TextureMapperVideoLayer* media;
+
+ ContentData()
+ : needsDisplay(false)
+ , contentType(HTMLContentType)
+ , image(0)
+ , media(0)
+ {
+ }
+ };
+
+
+ TextureMapperNode();
+ virtual ~TextureMapperNode();
+
+ void syncCompositingState(GraphicsLayerTextureMapper*, bool recursive);
+
+protected:
+ // Reimps from TextureMapperContentLayer
+ virtual IntSize size() const { return m_size; }
+ virtual void setPlatformLayerClient(TextureMapperLayerClient*);
+ virtual void paint(TextureMapper*, const TextureMapperContentLayer::PaintOptions&);
+
+private:
+ TextureMapperNode* rootLayer();
+ void clearDirectImage();
+ void computeTransformations();
+ IntSize nearestSurfaceSize() const;
+ void computeReplicaTransform();
+ void computeLayerType();
+ void computeLocalTransform();
+ void flattenTo2DSpaceIfNecessary();
+ void initializeTextureMapper(TextureMapper*);
+ void invalidateTransform();
+ void notifyChange(ChangeMask);
+ void setNeedsDisplay();
+ void setNeedsDisplayInRect(IntRect);
+ void performPostSyncOperations();
+ void syncCompositingStateInternal(GraphicsLayerTextureMapper*, bool recursive, TextureMapper*);
+ void syncCompositingStateSelf(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper);
+ TextureMapperCache* cache();
+
+ void paintRecursive(TexmapPaintOptions options);
+ bool paintReplica(const TexmapPaintOptions& options);
+ void paintSurface(const TexmapPaintOptions& options);
+ void paintSelf(const TexmapPaintOptions& options);
+ void paintSelfAndChildren(const TexmapPaintOptions& options, TexmapPaintOptions& optionsForDescendants);
+ void uploadTextureFromContent(TextureMapper* textureMapper, const IntRect& visibleRect, GraphicsLayer* layer);
+
+ int countDescendantsWithContent() const;
+ bool hasSurfaceDescendants() const;
+
+ TextureMapper* textureMapper();
+
+
+ static TextureMapperNode* toTextureMapperNode(GraphicsLayer*);
+ static int compareGraphicsLayersZValue(const void* a, const void* b);
+ static void sortByZOrder(Vector<TextureMapperNode* >& array, int first, int last);
+ struct TransformData {
+ TransformationMatrix base, target, replica, forDescendants, perspective, local;
+ IntRect targetBoundingRect;
+ float centerZ;
+ bool dirty, localDirty, perspectiveDirty;
+ IntRect boundingRectFromRoot;
+ TransformData() : dirty(true), localDirty(true), perspectiveDirty(true) { }
+ };
+
+ TransformData m_transforms;
+
+ enum LayerType {
+ DefaultLayer,
+ RootLayer,
+ ScissorLayer,
+ ClipLayer,
+ TransparencyLayer
+ };
+
+ LayerType m_layerType;
+
+ inline IntRect targetRect() const
+ {
+ return m_currentContent.contentType == HTMLContentType ? entireRect() : m_state.contentsRect;
+ }
+
+ inline IntRect entireRect() const
+ {
+ return IntRect(0, 0, m_size.width(), m_size.height());
+ }
+
+ inline IntRect replicaRect() const
+ {
+ return m_layerType == TransparencyLayer ? IntRect(0, 0, m_nearestSurfaceSize.width(), m_nearestSurfaceSize.height()) : entireRect();
+ }
+
+ RefPtr<BitmapTexture> m_texture;
+ RefPtr<BitmapTexture> m_surface, m_replicaSurface;
+
+ ContentData m_currentContent;
+
+ Vector<TextureMapperNode*> m_children;
+ TextureMapperNode* m_parent;
+ TextureMapperNode* m_effectTarget;
+ IntSize m_size, m_nearestSurfaceSize;
+ String m_name;
+ TextureMapperLayerClient* m_platformClient;
+
+ struct State {
+ FloatPoint pos;
+ FloatPoint3D anchorPoint;
+ FloatSize size;
+ TransformationMatrix transform;
+ TransformationMatrix childrenTransform;
+ Color backgroundColor;
+ Color currentColor;
+ GraphicsLayer::CompositingCoordinatesOrientation geoOrientation;
+ GraphicsLayer::CompositingCoordinatesOrientation contentsOrientation;
+ float opacity;
+ IntRect contentsRect;
+ int descendantsWithContent;
+ TextureMapperNode* maskLayer;
+ TextureMapperNode* replicaLayer;
+ bool preserves3D;
+ bool masksToBounds;
+ bool drawsContent;
+ bool contentsOpaque;
+ bool backfaceVisibility;
+ bool visible;
+ bool dirty;
+ bool tiled;
+ bool hasSurfaceDescendants;
+ IntRect visibleRect;
+
+ State()
+ : opacity(1.f)
+ , descendantsWithContent(0)
+ , maskLayer(0)
+ , replicaLayer(0)
+ , preserves3D(false)
+ , masksToBounds(false)
+ , drawsContent(false)
+ , contentsOpaque(false)
+ , backfaceVisibility(false)
+ , visible(true)
+ , dirty(true)
+ , tiled(false)
+ , hasSurfaceDescendants(false)
+ {
+ }
+ };
+
+ State m_state;
+ TextureMapperCache* m_cache;
+};
+
+}
+#endif // TextureMapperNode_h
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
new file mode 100644
index 0000000..2a38b90
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
@@ -0,0 +1,79 @@
+/*
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef TextureMapperPlatformLayer_h
+#define TextureMapperPlatformLayer_h
+
+namespace WebCore {
+
+class GraphicsContext;
+class IntRect;
+class IntSize;
+class TextureMapper;
+class TransformationMatrix;
+
+
+// Glue layer to connect the texmap layer to the platform specific container.
+class TextureMapperLayerClient {
+public:
+ virtual ~TextureMapperLayerClient() {}
+ virtual void setNeedsDisplay() = 0;
+ virtual void setNeedsDisplayInRect(const IntRect& rect) = 0;
+ virtual void setSizeChanged(const IntSize&) = 0;
+ virtual TextureMapper* textureMapper() = 0;
+};
+
+class TextureMapperPlatformLayer {
+public:
+ enum Type {
+ ContentLayer,
+ VideoLayer
+ };
+
+ virtual Type layerType() const = 0;
+ virtual ~TextureMapperPlatformLayer() {}
+};
+
+class TextureMapperContentLayer : public TextureMapperPlatformLayer {
+public:
+ struct PaintOptions {
+ IntRect visibleRect;
+ IntRect targetRect;
+ IntSize viewportSize;
+ TransformationMatrix transform;
+ float opacity;
+ };
+
+ virtual void setPlatformLayerClient(TextureMapperLayerClient*) = 0;
+ virtual void paint(TextureMapper*, const PaintOptions&) {}
+ virtual IntSize size() const = 0;
+ virtual Type layerType() const { return ContentLayer; }
+};
+
+#if ENABLE(VIDEO)
+class TextureMapperVideoLayer : public TextureMapperPlatformLayer {
+public:
+ virtual void paint(GraphicsContext*) = 0;
+ virtual Type layerType() const { return VideoLayer; }
+};
+#endif
+
+}
+
+#endif // TextureMapperPlatformLayer_h