summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform/graphics/texmap
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2013-09-13 12:51:20 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-19 20:50:05 +0200
commitd441d6f39bb846989d95bcf5caf387b42414718d (patch)
treee367e64a75991c554930278175d403c072de6bb8 /Source/WebCore/platform/graphics/texmap
parent0060b2994c07842f4c59de64b5e3e430525c4b90 (diff)
downloadqtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit. Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/WebCore/platform/graphics/texmap')
-rw-r--r--Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp431
-rw-r--r--Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h103
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapper.cpp6
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapper.h43
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp195
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h75
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.cpp67
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.h54
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp985
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperGL.h92
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp47
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h15
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp809
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h226
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h27
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp533
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.cpp382
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h (renamed from Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h)85
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.cpp54
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.h55
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperTile.cpp79
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperTile.h60
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.cpp162
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.h64
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/AreaAllocator.cpp335
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/AreaAllocator.h112
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CompositingCoordinator.cpp434
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CompositingCoordinator.h168
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedBackingStore.cpp194
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedBackingStore.h90
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedCustomFilterOperation.h66
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedCustomFilterProgram.h67
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp1255
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.h264
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsScene.cpp781
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsScene.h209
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsState.h212
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.cpp182
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.h95
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.cpp54
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.h76
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedTile.cpp144
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedTile.h99
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/SurfaceUpdateInfo.h51
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/ThreadSafeCoordinatedSurface.cpp76
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/ThreadSafeCoordinatedSurface.h54
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/UpdateAtlas.cpp116
-rw-r--r--Source/WebCore/platform/graphics/texmap/coordinated/UpdateAtlas.h78
48 files changed, 7866 insertions, 1995 deletions
diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
index 5ba109066..bfca0bf17 100644
--- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
+++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
@@ -24,16 +24,17 @@
#include "GraphicsLayerAnimation.h"
#include "GraphicsLayerFactory.h"
#include "ImageBuffer.h"
-#include "NotImplemented.h"
#include <wtf/CurrentTime.h>
-#if USE(CAIRO)
-#include "CairoUtilities.h"
-#include <wtf/text/CString.h>
-#endif
+#if USE(TEXTURE_MAPPER)
namespace WebCore {
+TextureMapperLayer* toTextureMapperLayer(GraphicsLayer* layer)
+{
+ return layer ? toGraphicsLayerTextureMapper(layer)->layer() : 0;
+}
+
PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client)
{
if (!factory)
@@ -44,8 +45,6 @@ PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, G
PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
{
- if (s_graphicsLayerFactory)
- return (*s_graphicsLayerFactory)(client);
return adoptPtr(new GraphicsLayerTextureMapper(client));
}
@@ -53,18 +52,17 @@ GraphicsLayerTextureMapper::GraphicsLayerTextureMapper(GraphicsLayerClient* clie
: GraphicsLayer(client)
, m_layer(adoptPtr(new TextureMapperLayer()))
, m_compositedNativeImagePtr(0)
- , m_changeMask(0)
+ , m_changeMask(NoChanges)
, m_needsDisplay(false)
- , m_hasOwnBackingStore(true)
, m_fixedToViewport(false)
, m_debugBorderWidth(0)
, m_contentsLayer(0)
- , m_animationStartedTimer(this, &GraphicsLayerTextureMapper::animationStartedTimerFired)
, m_animationStartTime(0)
+ , m_isScrollable(false)
{
}
-void GraphicsLayerTextureMapper::notifyChange(TextureMapperLayer::ChangeMask changeMask)
+void GraphicsLayerTextureMapper::notifyChange(ChangeMask changeMask)
{
m_changeMask |= changeMask;
if (!client())
@@ -79,6 +77,9 @@ void GraphicsLayerTextureMapper::setName(const String& name)
GraphicsLayerTextureMapper::~GraphicsLayerTextureMapper()
{
+ if (m_contentsLayer)
+ m_contentsLayer->setClient(0);
+
willBeDestroyed();
}
@@ -91,11 +92,11 @@ void GraphicsLayerTextureMapper::willBeDestroyed()
*/
void GraphicsLayerTextureMapper::setNeedsDisplay()
{
- if (!m_hasOwnBackingStore)
+ if (!drawsContent())
return;
m_needsDisplay = true;
- notifyChange(TextureMapperLayer::DisplayChange);
+ notifyChange(DisplayChange);
addRepaintRect(FloatRect(FloatPoint(), m_size));
}
@@ -103,7 +104,7 @@ void GraphicsLayerTextureMapper::setNeedsDisplay()
*/
void GraphicsLayerTextureMapper::setContentsNeedsDisplay()
{
- notifyChange(TextureMapperLayer::DisplayChange);
+ notifyChange(DisplayChange);
addRepaintRect(contentsRect());
}
@@ -111,37 +112,32 @@ void GraphicsLayerTextureMapper::setContentsNeedsDisplay()
*/
void GraphicsLayerTextureMapper::setNeedsDisplayInRect(const FloatRect& rect)
{
- if (!m_hasOwnBackingStore)
+ if (!drawsContent())
return;
if (m_needsDisplay)
return;
m_needsDisplayRect.unite(rect);
- notifyChange(TextureMapperLayer::DisplayChange);
+ notifyChange(DisplayChange);
addRepaintRect(rect);
}
/* \reimp (GraphicsLayer.h)
*/
-void GraphicsLayerTextureMapper::setParent(GraphicsLayer* layer)
-{
- notifyChange(TextureMapperLayer::ParentChange);
- GraphicsLayer::setParent(layer);
-}
-
-/* \reimp (GraphicsLayer.h)
-*/
bool GraphicsLayerTextureMapper::setChildren(const Vector<GraphicsLayer*>& children)
{
- notifyChange(TextureMapperLayer::ChildrenChange);
- return GraphicsLayer::setChildren(children);
+ if (GraphicsLayer::setChildren(children)) {
+ notifyChange(ChildrenChange);
+ return true;
+ }
+ return false;
}
/* \reimp (GraphicsLayer.h)
*/
void GraphicsLayerTextureMapper::addChild(GraphicsLayer* layer)
{
- notifyChange(TextureMapperLayer::ChildrenChange);
+ notifyChange(ChildrenChange);
GraphicsLayer::addChild(layer);
}
@@ -150,15 +146,15 @@ void GraphicsLayerTextureMapper::addChild(GraphicsLayer* layer)
void GraphicsLayerTextureMapper::addChildAtIndex(GraphicsLayer* layer, int index)
{
GraphicsLayer::addChildAtIndex(layer, index);
- notifyChange(TextureMapperLayer::ChildrenChange);
+ notifyChange(ChildrenChange);
}
/* \reimp (GraphicsLayer.h)
*/
void GraphicsLayerTextureMapper::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling)
{
- GraphicsLayer::addChildAbove(layer, sibling);
- notifyChange(TextureMapperLayer::ChildrenChange);
+ GraphicsLayer::addChildAbove(layer, sibling);
+ notifyChange(ChildrenChange);
}
/* \reimp (GraphicsLayer.h)
@@ -166,7 +162,7 @@ void GraphicsLayerTextureMapper::addChildAbove(GraphicsLayer* layer, GraphicsLay
void GraphicsLayerTextureMapper::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling)
{
GraphicsLayer::addChildBelow(layer, sibling);
- notifyChange(TextureMapperLayer::ChildrenChange);
+ notifyChange(ChildrenChange);
}
/* \reimp (GraphicsLayer.h)
@@ -174,7 +170,7 @@ void GraphicsLayerTextureMapper::addChildBelow(GraphicsLayer* layer, GraphicsLay
bool GraphicsLayerTextureMapper::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
{
if (GraphicsLayer::replaceChild(oldChild, newChild)) {
- notifyChange(TextureMapperLayer::ChildrenChange);
+ notifyChange(ChildrenChange);
return true;
}
return false;
@@ -182,22 +178,12 @@ bool GraphicsLayerTextureMapper::replaceChild(GraphicsLayer* oldChild, GraphicsL
/* \reimp (GraphicsLayer.h)
*/
-void GraphicsLayerTextureMapper::removeFromParent()
-{
- if (!parent())
- return;
- notifyChange(TextureMapperLayer::ParentChange);
- GraphicsLayer::removeFromParent();
-}
-
-/* \reimp (GraphicsLayer.h)
-*/
void GraphicsLayerTextureMapper::setMaskLayer(GraphicsLayer* value)
{
if (value == maskLayer())
return;
GraphicsLayer::setMaskLayer(value);
- notifyChange(TextureMapperLayer::MaskLayerChange);
+ notifyChange(MaskLayerChange);
if (!value)
return;
@@ -213,7 +199,7 @@ void GraphicsLayerTextureMapper::setReplicatedByLayer(GraphicsLayer* value)
if (value == replicaLayer())
return;
GraphicsLayer::setReplicatedByLayer(value);
- notifyChange(TextureMapperLayer::ReplicaLayerChange);
+ notifyChange(ReplicaLayerChange);
}
/* \reimp (GraphicsLayer.h)
@@ -223,7 +209,7 @@ void GraphicsLayerTextureMapper::setPosition(const FloatPoint& value)
if (value == position())
return;
GraphicsLayer::setPosition(value);
- notifyChange(TextureMapperLayer::PositionChange);
+ notifyChange(PositionChange);
}
/* \reimp (GraphicsLayer.h)
@@ -233,7 +219,7 @@ void GraphicsLayerTextureMapper::setAnchorPoint(const FloatPoint3D& value)
if (value == anchorPoint())
return;
GraphicsLayer::setAnchorPoint(value);
- notifyChange(TextureMapperLayer::AnchorPointChange);
+ notifyChange(AnchorPointChange);
}
/* \reimp (GraphicsLayer.h)
@@ -246,7 +232,7 @@ void GraphicsLayerTextureMapper::setSize(const FloatSize& value)
GraphicsLayer::setSize(value);
if (maskLayer())
maskLayer()->setSize(value);
- notifyChange(TextureMapperLayer::SizeChange);
+ notifyChange(SizeChange);
}
/* \reimp (GraphicsLayer.h)
@@ -257,7 +243,7 @@ void GraphicsLayerTextureMapper::setTransform(const TransformationMatrix& value)
return;
GraphicsLayer::setTransform(value);
- notifyChange(TextureMapperLayer::TransformChange);
+ notifyChange(TransformChange);
}
/* \reimp (GraphicsLayer.h)
@@ -267,7 +253,7 @@ void GraphicsLayerTextureMapper::setChildrenTransform(const TransformationMatrix
if (value == childrenTransform())
return;
GraphicsLayer::setChildrenTransform(value);
- notifyChange(TextureMapperLayer::ChildrenTransformChange);
+ notifyChange(ChildrenTransformChange);
}
/* \reimp (GraphicsLayer.h)
@@ -277,7 +263,7 @@ void GraphicsLayerTextureMapper::setPreserves3D(bool value)
if (value == preserves3D())
return;
GraphicsLayer::setPreserves3D(value);
- notifyChange(TextureMapperLayer::Preserves3DChange);
+ notifyChange(Preserves3DChange);
}
/* \reimp (GraphicsLayer.h)
@@ -287,7 +273,7 @@ void GraphicsLayerTextureMapper::setMasksToBounds(bool value)
if (value == masksToBounds())
return;
GraphicsLayer::setMasksToBounds(value);
- notifyChange(TextureMapperLayer::MasksToBoundsChange);
+ notifyChange(MasksToBoundsChange);
}
/* \reimp (GraphicsLayer.h)
@@ -296,8 +282,11 @@ void GraphicsLayerTextureMapper::setDrawsContent(bool value)
{
if (value == drawsContent())
return;
- notifyChange(TextureMapperLayer::DrawsContentChange);
GraphicsLayer::setDrawsContent(value);
+ notifyChange(DrawsContentChange);
+
+ if (value)
+ setNeedsDisplay();
}
/* \reimp (GraphicsLayer.h)
@@ -306,7 +295,7 @@ void GraphicsLayerTextureMapper::setContentsVisible(bool value)
{
if (value == contentsAreVisible())
return;
- notifyChange(TextureMapperLayer::ContentsVisibleChange);
+ notifyChange(ContentsVisibleChange);
GraphicsLayer::setContentsVisible(value);
if (maskLayer())
maskLayer()->setContentsVisible(value);
@@ -318,7 +307,7 @@ void GraphicsLayerTextureMapper::setContentsOpaque(bool value)
{
if (value == contentsOpaque())
return;
- notifyChange(TextureMapperLayer::ContentsOpaqueChange);
+ notifyChange(ContentsOpaqueChange);
GraphicsLayer::setContentsOpaque(value);
}
@@ -329,7 +318,7 @@ void GraphicsLayerTextureMapper::setBackfaceVisibility(bool value)
if (value == backfaceVisibility())
return;
GraphicsLayer::setBackfaceVisibility(value);
- notifyChange(TextureMapperLayer::BackfaceVisibilityChange);
+ notifyChange(BackfaceVisibilityChange);
}
/* \reimp (GraphicsLayer.h)
@@ -339,7 +328,7 @@ void GraphicsLayerTextureMapper::setOpacity(float value)
if (value == opacity())
return;
GraphicsLayer::setOpacity(value);
- notifyChange(TextureMapperLayer::OpacityChange);
+ notifyChange(OpacityChange);
}
/* \reimp (GraphicsLayer.h)
@@ -349,9 +338,19 @@ void GraphicsLayerTextureMapper::setContentsRect(const IntRect& value)
if (value == contentsRect())
return;
GraphicsLayer::setContentsRect(value);
- notifyChange(TextureMapperLayer::ContentsRectChange);
+ notifyChange(ContentsRectChange);
}
+void GraphicsLayerTextureMapper::setContentsToSolidColor(const Color& color)
+{
+ if (color == m_solidColor)
+ return;
+
+ m_solidColor = color;
+ notifyChange(BackgroundColorChange);
+}
+
+
/* \reimp (GraphicsLayer.h)
*/
void GraphicsLayerTextureMapper::setContentsToImage(Image* image)
@@ -377,7 +376,7 @@ void GraphicsLayerTextureMapper::setContentsToImage(Image* image)
}
setContentsToMedia(m_compositedImage.get());
- notifyChange(TextureMapperLayer::ContentChange);
+ notifyChange(ContentChange);
GraphicsLayer::setContentsToImage(image);
}
@@ -387,62 +386,227 @@ void GraphicsLayerTextureMapper::setContentsToMedia(TextureMapperPlatformLayer*
return;
GraphicsLayer::setContentsToMedia(media);
- notifyChange(TextureMapperLayer::ContentChange);
+ notifyChange(ContentChange);
+
+ if (m_contentsLayer)
+ m_contentsLayer->setClient(0);
+
m_contentsLayer = media;
+
+ if (m_contentsLayer)
+ m_contentsLayer->setClient(this);
+}
+
+void GraphicsLayerTextureMapper::setShowDebugBorder(bool show)
+{
+ if (isShowingDebugBorder() == show)
+ return;
+
+ GraphicsLayer::setShowDebugBorder(show);
+ notifyChange(DebugVisualsChange);
+}
+
+void GraphicsLayerTextureMapper::setShowRepaintCounter(bool show)
+{
+ if (isShowingRepaintCounter() == show)
+ return;
+
+ GraphicsLayer::setShowRepaintCounter(show);
+ notifyChange(DebugVisualsChange);
+}
+
+void GraphicsLayerTextureMapper::didCommitScrollOffset(const IntSize& offset)
+{
+ if (offset.isZero())
+ return;
+
+ m_committedScrollOffset = offset;
+ notifyChange(CommittedScrollOffsetChange);
+}
+
+void GraphicsLayerTextureMapper::setIsScrollable(bool isScrollable)
+{
+ if (m_isScrollable == isScrollable)
+ return;
+
+ m_isScrollable = isScrollable;
+ notifyChange(IsScrollableChange);
}
/* \reimp (GraphicsLayer.h)
*/
void GraphicsLayerTextureMapper::flushCompositingStateForThisLayerOnly()
{
- m_layer->flushCompositingState(this);
- didFlushCompositingState();
+ prepareBackingStoreIfNeeded();
+ commitLayerChanges();
+ m_layer->syncAnimations();
+ updateBackingStoreIfNeeded();
}
-/* \reimp (GraphicsLayer.h)
-*/
-void GraphicsLayerTextureMapper::flushCompositingState(const FloatRect&)
+void GraphicsLayerTextureMapper::prepareBackingStoreIfNeeded()
{
- m_layer->flushCompositingState(this, TextureMapperLayer::TraverseDescendants);
- didFlushCompositingStateRecursive();
+ if (!shouldHaveBackingStore()) {
+ m_backingStore.clear();
+ m_changeMask |= BackingStoreChange;
+ } else {
+ if (!m_backingStore) {
+ m_backingStore = TextureMapperTiledBackingStore::create();
+ m_changeMask |= BackingStoreChange;
+ }
+ }
+
+ updateDebugBorderAndRepaintCount();
}
-void GraphicsLayerTextureMapper::didFlushCompositingState()
+void GraphicsLayerTextureMapper::updateDebugBorderAndRepaintCount()
{
- updateBackingStore();
- m_changeMask = 0;
+ if (isShowingDebugBorder())
+ updateDebugIndicators();
+
+ // When this has its own backing store (e.g. Qt WK1), update the repaint count before calling TextureMapperLayer::flushCompositingStateForThisLayerOnly().
+ bool needsToRepaint = shouldHaveBackingStore() && (m_needsDisplay || !m_needsDisplayRect.isEmpty());
+ if (isShowingRepaintCounter() && needsToRepaint) {
+ incrementRepaintCount();
+ m_changeMask |= RepaintCountChange;
+ }
}
-void GraphicsLayerTextureMapper::didFlushCompositingStateRecursive()
+void GraphicsLayerTextureMapper::setDebugBorder(const Color& color, float width)
{
- didFlushCompositingState();
- for (size_t i = 0; i < children().size(); ++i)
- toGraphicsLayerTextureMapper(children()[i])->didFlushCompositingStateRecursive();
- if (maskLayer())
- toGraphicsLayerTextureMapper(maskLayer())->didFlushCompositingStateRecursive();
- if (replicaLayer())
- toGraphicsLayerTextureMapper(replicaLayer())->didFlushCompositingStateRecursive();
+ m_debugBorderColor = color;
+ m_debugBorderWidth = width;
+ m_changeMask |= DebugVisualsChange;
+}
+
+static void toTextureMapperLayerVector(const Vector<GraphicsLayer*>& layers, Vector<TextureMapperLayer*>& texmapLayers)
+{
+ texmapLayers.reserveCapacity(layers.size());
+ for (size_t i = 0; i < layers.size(); ++i)
+ texmapLayers.append(toTextureMapperLayer(layers[i]));
}
-void GraphicsLayerTextureMapper::updateBackingStore()
+void GraphicsLayerTextureMapper::commitLayerChanges()
{
- if (!m_hasOwnBackingStore)
+ if (m_changeMask == NoChanges)
return;
- prepareBackingStore();
- m_layer->setBackingStore(m_backingStore);
+ if (m_changeMask & ChildrenChange) {
+ Vector<TextureMapperLayer*> textureMapperLayerChildren;
+ toTextureMapperLayerVector(children(), textureMapperLayerChildren);
+ m_layer->setChildren(textureMapperLayerChildren);
+ }
+
+ if (m_changeMask & MaskLayerChange)
+ m_layer->setMaskLayer(toTextureMapperLayer(maskLayer()));
+
+ if (m_changeMask & ReplicaLayerChange)
+ m_layer->setReplicaLayer(toTextureMapperLayer(replicaLayer()));
+
+ if (m_changeMask & PositionChange)
+ m_layer->setPosition(position());
+
+ if (m_changeMask & AnchorPointChange)
+ m_layer->setAnchorPoint(anchorPoint());
+
+ if (m_changeMask & SizeChange)
+ m_layer->setSize(size());
+
+ if (m_changeMask & TransformChange)
+ m_layer->setTransform(transform());
+
+ if (m_changeMask & ChildrenTransformChange)
+ m_layer->setChildrenTransform(childrenTransform());
+
+ if (m_changeMask & Preserves3DChange)
+ m_layer->setPreserves3D(preserves3D());
+
+ if (m_changeMask & ContentsRectChange)
+ m_layer->setContentsRect(contentsRect());
+
+ if (m_changeMask & MasksToBoundsChange)
+ m_layer->setMasksToBounds(masksToBounds());
+
+ if (m_changeMask & DrawsContentChange)
+ m_layer->setDrawsContent(drawsContent());
+
+ if (m_changeMask & ContentsVisibleChange)
+ m_layer->setContentsVisible(contentsAreVisible());
+
+ if (m_changeMask & ContentsOpaqueChange)
+ m_layer->setContentsOpaque(contentsOpaque());
+
+ if (m_changeMask & BackfaceVisibilityChange)
+ m_layer->setBackfaceVisibility(backfaceVisibility());
+
+ if (m_changeMask & OpacityChange)
+ m_layer->setOpacity(opacity());
+
+ if (m_changeMask & BackgroundColorChange)
+ m_layer->setSolidColor(solidColor());
+
+#if ENABLE(CSS_FILTERS)
+ if (m_changeMask & FilterChange)
+ m_layer->setFilters(filters());
+#endif
+
+ if (m_changeMask & BackingStoreChange)
+ m_layer->setBackingStore(m_backingStore);
+
+ if (m_changeMask & DebugVisualsChange)
+ m_layer->setDebugVisuals(isShowingDebugBorder(), debugBorderColor(), debugBorderWidth(), isShowingRepaintCounter());
+
+ if (m_changeMask & RepaintCountChange)
+ m_layer->setRepaintCount(repaintCount());
+
+ if (m_changeMask & ContentChange)
+ m_layer->setContentsLayer(platformLayer());
+
+ if (m_changeMask & AnimationChange)
+ m_layer->setAnimations(m_animations);
+
+ if (m_changeMask & AnimationStarted)
+ client()->notifyAnimationStarted(this, m_animationStartTime);
+
+ if (m_changeMask & FixedToViewporChange)
+ m_layer->setFixedToViewport(fixedToViewport());
+
+ if (m_changeMask & IsScrollableChange)
+ m_layer->setIsScrollable(isScrollable());
+
+ if (m_changeMask & CommittedScrollOffsetChange)
+ m_layer->didCommitScrollOffset(m_committedScrollOffset);
+
+ m_changeMask = NoChanges;
+}
+
+/* \reimp (GraphicsLayer.h)
+*/
+void GraphicsLayerTextureMapper::flushCompositingState(const FloatRect& rect)
+{
+ if (!m_layer->textureMapper())
+ return;
+
+ flushCompositingStateForThisLayerOnly();
+
+ if (maskLayer())
+ maskLayer()->flushCompositingState(rect);
+ if (replicaLayer())
+ replicaLayer()->flushCompositingState(rect);
+ for (size_t i = 0; i < children().size(); ++i)
+ children()[i]->flushCompositingState(rect);
}
-void GraphicsLayerTextureMapper::prepareBackingStore()
+void GraphicsLayerTextureMapper::updateBackingStoreIfNeeded()
{
TextureMapper* textureMapper = m_layer->textureMapper();
if (!textureMapper)
return;
if (!shouldHaveBackingStore()) {
- m_backingStore.clear();
+ ASSERT(!m_backingStore);
return;
}
+ ASSERT(m_backingStore);
IntRect dirtyRect = enclosingIntRect(FloatRect(FloatPoint::zero(), m_size));
if (!m_needsDisplay)
@@ -450,42 +614,12 @@ void GraphicsLayerTextureMapper::prepareBackingStore()
if (dirtyRect.isEmpty())
return;
- if (!m_backingStore)
- m_backingStore = TextureMapperTiledBackingStore::create();
-
-#ifndef QT_NO_DYNAMIC_CAST
+#if PLATFORM(QT) && !defined(QT_NO_DYNAMIC_CAST)
ASSERT(dynamic_cast<TextureMapperTiledBackingStore*>(m_backingStore.get()));
#endif
TextureMapperTiledBackingStore* backingStore = static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get());
- 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);
+ backingStore->updateContents(textureMapper, this, m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData);
m_needsDisplay = false;
m_needsDisplayRect = IntRect();
@@ -496,40 +630,6 @@ bool GraphicsLayerTextureMapper::shouldHaveBackingStore() const
return drawsContent() && contentsAreVisible() && !m_size.isEmpty();
}
-#if USE(CAIRO)
-void GraphicsLayerTextureMapper::drawRepaintCounter(GraphicsContext* context)
-{
- cairo_t* cr = context->platformContext()->cr();
- cairo_save(cr);
-
- CString repaintCount = String::format("%i", this->repaintCount()).utf8();
- cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
- cairo_set_font_size(cr, 18);
-
- cairo_text_extents_t repaintTextExtents;
- cairo_text_extents(cr, repaintCount.data(), &repaintTextExtents);
-
- static const int repaintCountBorderWidth = 10;
- setSourceRGBAFromColor(cr, isShowingDebugBorder() ? m_debugBorderColor : Color(0, 255, 0, 127));
- cairo_rectangle(cr, 0, 0,
- repaintTextExtents.width + (repaintCountBorderWidth * 2),
- repaintTextExtents.height + (repaintCountBorderWidth * 2));
- cairo_fill(cr);
-
- cairo_set_source_rgb(cr, 1, 1, 1);
- cairo_move_to(cr, repaintCountBorderWidth, repaintTextExtents.height + repaintCountBorderWidth);
- cairo_show_text(cr, repaintCount.data());
-
- cairo_restore(cr);
-}
-#else
-void GraphicsLayerTextureMapper::drawRepaintCounter(GraphicsContext* context)
-{
- notImplemented();
-}
-
-#endif
-
bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
{
ASSERT(!keyframesName.isEmpty());
@@ -550,15 +650,15 @@ bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList
m_animationStartTime = currentTime;
else
m_animationStartTime = currentTime - timeOffset;
- notifyChange(TextureMapperLayer::AnimationChange);
- m_animationStartedTimer.startOneShot(0);
+ notifyChange(AnimationChange);
+ notifyChange(AnimationStarted);
return true;
}
void GraphicsLayerTextureMapper::setAnimations(const GraphicsLayerAnimations& animations)
{
m_animations = animations;
- notifyChange(TextureMapperLayer::AnimationChange);
+ notifyChange(AnimationChange);
}
@@ -572,25 +672,28 @@ void GraphicsLayerTextureMapper::removeAnimation(const String& animationName)
m_animations.remove(animationName);
}
-void GraphicsLayerTextureMapper::animationStartedTimerFired(Timer<GraphicsLayerTextureMapper>*)
+#if ENABLE(CSS_FILTERS)
+bool GraphicsLayerTextureMapper::setFilters(const FilterOperations& filters)
{
- client()->notifyAnimationStarted(this, m_animationStartTime);
+ notifyChange(FilterChange);
+ return GraphicsLayer::setFilters(filters);
}
+#endif
-void GraphicsLayerTextureMapper::setDebugBorder(const Color& color, float width)
+void GraphicsLayerTextureMapper::setFixedToViewport(bool fixed)
{
- // The default values for GraphicsLayer debug borders are a little
- // hard to see (some less than one pixel wide), so we double their size here.
- m_debugBorderColor = color;
- m_debugBorderWidth = width * 2;
+ if (m_fixedToViewport == fixed)
+ return;
+
+ m_fixedToViewport = fixed;
+ notifyChange(FixedToViewporChange);
}
-#if ENABLE(CSS_FILTERS)
-bool GraphicsLayerTextureMapper::setFilters(const FilterOperations& filters)
+void GraphicsLayerTextureMapper::setRepaintCount(int repaintCount)
{
- notifyChange(TextureMapperLayer::FilterChange);
- return GraphicsLayer::setFilters(filters);
+ m_repaintCount = repaintCount;
+ notifyChange(RepaintCountChange);
}
-#endif
}
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
index 00b0fe7c1..61ddfb92a 100644
--- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
+++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h
@@ -20,36 +20,36 @@
#ifndef GraphicsLayerTextureMapper_h
#define GraphicsLayerTextureMapper_h
-#include "GraphicsContext.h"
+#if USE(TEXTURE_MAPPER)
+
#include "GraphicsLayer.h"
#include "GraphicsLayerClient.h"
#include "Image.h"
#include "TextureMapperLayer.h"
+#include "TextureMapperPlatformLayer.h"
+#include "TextureMapperTiledBackingStore.h"
#include "Timer.h"
namespace WebCore {
-class TextureMapper;
-
-class GraphicsLayerTextureMapper : public GraphicsLayer {
- friend class TextureMapperLayer;
-
+class GraphicsLayerTextureMapper : public GraphicsLayer, public TextureMapperPlatformLayer::Client {
public:
explicit GraphicsLayerTextureMapper(GraphicsLayerClient*);
virtual ~GraphicsLayerTextureMapper();
+ void setScrollClient(TextureMapperLayer::ScrollingClient* client) { m_layer->setScrollClient(client); }
+ void setID(uint32_t id) { m_layer->setID(id); }
+
// reimps from GraphicsLayer.h
virtual void setNeedsDisplay();
virtual void setContentsNeedsDisplay();
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);
@@ -66,14 +66,19 @@ public:
virtual void setContentsRect(const IntRect& r);
virtual void setReplicatedByLayer(GraphicsLayer*);
virtual void setContentsToImage(Image*);
+ virtual void setContentsToSolidColor(const Color&);
+ Color solidColor() const { return m_solidColor; }
virtual void setContentsToMedia(PlatformLayer*);
virtual void setContentsToCanvas(PlatformLayer* canvas) { setContentsToMedia(canvas); }
+ virtual void setShowDebugBorder(bool) OVERRIDE;
+ virtual void setDebugBorder(const Color&, float width) OVERRIDE;
+ virtual void setShowRepaintCounter(bool) OVERRIDE;
virtual void flushCompositingState(const FloatRect&);
virtual void flushCompositingStateForThisLayerOnly();
virtual void setName(const String& name);
+ virtual bool hasContentsLayer() const { return m_contentsLayer; }
virtual PlatformLayer* platformLayer() const { return m_contentsLayer; }
- void notifyChange(TextureMapperLayer::ChangeMask);
inline int changeMask() const { return m_changeMask; }
virtual bool addAnimation(const KeyframeValueList&, const IntSize&, const Animation*, const String&, double);
@@ -83,27 +88,76 @@ public:
TextureMapperLayer* layer() const { return m_layer.get(); }
- virtual void setDebugBorder(const Color&, float width);
+ void didCommitScrollOffset(const IntSize&);
+ void setIsScrollable(bool);
+ bool isScrollable() const { return m_isScrollable; }
#if ENABLE(CSS_FILTERS)
virtual bool setFilters(const FilterOperations&);
#endif
- // FIXME: It will be removed after removing dependency of LayerTreeRenderer on GraphicsLayerTextureMapper.
- void setHasOwnBackingStore(bool b) { m_hasOwnBackingStore = b; }
-
- void setFixedToViewport(bool fixed) { m_fixedToViewport = fixed; }
+ void setFixedToViewport(bool);
bool fixedToViewport() const { return m_fixedToViewport; }
- void drawRepaintCounter(GraphicsContext*);
+ Color debugBorderColor() const { return m_debugBorderColor; }
+ float debugBorderWidth() const { return m_debugBorderWidth; }
+ void setRepaintCount(int);
+
private:
virtual void willBeDestroyed();
- void didFlushCompositingState();
- void didFlushCompositingStateRecursive();
- void updateBackingStore();
- void prepareBackingStore();
+
+ void commitLayerChanges();
+ void updateDebugBorderAndRepaintCount();
+ void updateBackingStoreIfNeeded();
+ void prepareBackingStoreIfNeeded();
bool shouldHaveBackingStore() const;
- void animationStartedTimerFired(Timer<GraphicsLayerTextureMapper>*);
+
+ virtual void setPlatformLayerNeedsDisplay() OVERRIDE { setContentsNeedsDisplay(); }
+
+ // 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,
+
+ ChildrenChange = (1L << 1),
+ MaskLayerChange = (1L << 2),
+ ReplicaLayerChange = (1L << 3),
+
+ ContentChange = (1L << 4),
+ ContentsRectChange = (1L << 5),
+ ContentsVisibleChange = (1L << 6),
+ ContentsOpaqueChange = (1L << 7),
+
+ PositionChange = (1L << 8),
+ AnchorPointChange = (1L << 9),
+ SizeChange = (1L << 10),
+ TransformChange = (1L << 11),
+ ChildrenTransformChange = (1L << 12),
+ Preserves3DChange = (1L << 13),
+
+ MasksToBoundsChange = (1L << 14),
+ DrawsContentChange = (1L << 15),
+ OpacityChange = (1L << 16),
+ BackfaceVisibilityChange = (1L << 17),
+
+ BackingStoreChange = (1L << 18),
+ DisplayChange = (1L << 19),
+ ContentsDisplayChange = (1L << 20),
+ BackgroundColorChange = (1L << 21),
+
+ AnimationChange = (1L << 22),
+ FilterChange = (1L << 23),
+
+ DebugVisualsChange = (1L << 24),
+ RepaintCountChange = (1L << 25),
+
+ FixedToViewporChange = (1L << 26),
+ AnimationStarted = (1L << 27),
+
+ CommittedScrollOffsetChange = (1L << 28),
+ IsScrollableChange = (1L << 29)
+ };
+ void notifyChange(ChangeMask);
OwnPtr<TextureMapperLayer> m_layer;
RefPtr<TextureMapperTiledBackingStore> m_compositedImage;
@@ -114,6 +168,7 @@ private:
bool m_needsDisplay;
bool m_hasOwnBackingStore;
bool m_fixedToViewport;
+ Color m_solidColor;
Color m_debugBorderColor;
float m_debugBorderWidth;
@@ -121,8 +176,10 @@ private:
TextureMapperPlatformLayer* m_contentsLayer;
FloatRect m_needsDisplayRect;
GraphicsLayerAnimations m_animations;
- Timer<GraphicsLayerTextureMapper> m_animationStartedTimer;
double m_animationStartTime;
+
+ IntSize m_committedScrollOffset;
+ bool m_isScrollable;
};
inline static GraphicsLayerTextureMapper* toGraphicsLayerTextureMapper(GraphicsLayer* layer)
@@ -130,5 +187,9 @@ inline static GraphicsLayerTextureMapper* toGraphicsLayerTextureMapper(GraphicsL
return static_cast<GraphicsLayerTextureMapper*>(layer);
}
+TextureMapperLayer* toTextureMapperLayer(GraphicsLayer*);
+
}
+#endif
+
#endif // GraphicsLayerTextureMapper_h
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp
index 43fec543c..12b04ba42 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 "FilterOperations.h"
#include "GraphicsLayer.h"
#include "TextureMapperImageBuffer.h"
#include "Timer.h"
@@ -136,10 +137,13 @@ PassOwnPtr<TextureMapper> TextureMapper::create(AccelerationMode mode)
}
TextureMapper::TextureMapper(AccelerationMode accelerationMode)
- : m_interpolationQuality(InterpolationDefault)
+ : m_context(0)
+ , m_interpolationQuality(InterpolationDefault)
, m_textDrawingMode(TextModeFill)
, m_texturePool(adoptPtr(new BitmapTexturePool()))
, m_accelerationMode(accelerationMode)
+ , m_isMaskMode(false)
+ , m_wrapMode(StretchWrap)
{ }
TextureMapper::~TextureMapper()
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.h b/Source/WebCore/platform/graphics/texmap/TextureMapper.h
index 22efd5ff7..6ec675794 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapper.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.h
@@ -20,7 +20,7 @@
#ifndef TextureMapper_h
#define TextureMapper_h
-#if USE(ACCELERATED_COMPOSITING)
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
#if PLATFORM(QT)
#include <qglobal.h>
@@ -28,17 +28,14 @@
#define TEXMAP_OPENGL_ES_2
#endif
#endif
-#if PLATFORM(GTK) && USE(OPENGL_ES_2)
+#if (PLATFORM(GTK) || PLATFORM(EFL)) && USE(OPENGL_ES_2)
#define TEXMAP_OPENGL_ES_2
#endif
-#include "FilterOperations.h"
#include "GraphicsContext.h"
#include "IntRect.h"
#include "IntSize.h"
-#include "TextureMapperPlatformLayer.h"
#include "TransformationMatrix.h"
-#include <wtf/UnusedParam.h>
/*
TextureMapper is a mechanism that enables hardware acceleration of CSS animations (accelerated compositing) without
@@ -51,6 +48,7 @@ class BitmapTexturePool;
class CustomFilterProgram;
class GraphicsLayer;
class TextureMapper;
+class FilterOperations;
// A 2D texture that can be the target of software or GL rendering.
class BitmapTexture : public RefCounted<BitmapTexture> {
@@ -96,7 +94,7 @@ public:
inline bool isOpaque() const { return !(m_flags & SupportsAlpha); }
#if ENABLE(CSS_FILTERS)
- virtual PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const BitmapTexture& contentTexture, const FilterOperations&) { return this; }
+ virtual PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const FilterOperations&) { return this; }
#endif
protected:
@@ -116,6 +114,12 @@ public:
enum PaintFlag {
PaintingMirrored = 1 << 0,
};
+
+ enum WrapMode {
+ StretchWrap,
+ RepeatWrap
+ };
+
typedef unsigned PaintFlags;
static PassOwnPtr<TextureMapper> create(AccelerationMode newMode = SoftwareMode);
@@ -130,17 +134,19 @@ public:
AllEdges = LeftEdge | RightEdge | TopEdge | BottomEdge,
};
- virtual void drawBorder(const Color&, float borderWidth, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix = TransformationMatrix()) = 0;
- virtual void drawRepaintCounter(int value, int pointSize, const FloatPoint&, const TransformationMatrix& modelViewMatrix = TransformationMatrix()) = 0;
- virtual void drawTexture(const BitmapTexture&, const FloatRect& target, const TransformationMatrix& modelViewMatrix = TransformationMatrix(), float opacity = 1.0f, const BitmapTexture* maskTexture = 0, unsigned exposedEdges = AllEdges) = 0;
+ virtual void drawBorder(const Color&, float borderWidth, const FloatRect&, const TransformationMatrix&) = 0;
+ virtual void drawNumber(int number, const Color&, const FloatPoint&, const TransformationMatrix&) = 0;
+
+ virtual void drawTexture(const BitmapTexture&, const FloatRect& target, const TransformationMatrix& modelViewMatrix = TransformationMatrix(), float opacity = 1.0f, unsigned exposedEdges = AllEdges) = 0;
virtual void drawSolidColor(const FloatRect&, const TransformationMatrix&, const Color&) = 0;
// makes a surface the target for the following drawTexture calls.
virtual void bindSurface(BitmapTexture* surface) = 0;
- virtual void setGraphicsContext(GraphicsContext* context) { m_context = context; }
- virtual GraphicsContext* graphicsContext() { return m_context; }
+ void setGraphicsContext(GraphicsContext* context) { m_context = context; }
+ GraphicsContext* graphicsContext() { return m_context; }
virtual void beginClip(const TransformationMatrix&, const FloatRect&) = 0;
virtual void endClip() = 0;
+ virtual IntRect clipBounds() = 0;
virtual PassRefPtr<BitmapTexture> createTexture() = 0;
void setImageInterpolationQuality(InterpolationQuality quality) { m_interpolationQuality = quality; }
@@ -153,6 +159,8 @@ public:
virtual void beginPainting(PaintFlags = 0) { }
virtual void endPainting() { }
+ void setMaskMode(bool m) { m_isMaskMode = m; }
+
virtual IntSize maxTextureSize() const = 0;
virtual PassRefPtr<BitmapTexture> acquireTextureFromPool(const IntSize&);
@@ -161,9 +169,18 @@ public:
virtual void removeCachedCustomFilterProgram(CustomFilterProgram*) { }
#endif
+ void setPatternTransform(const TransformationMatrix& p) { m_patternTransform = p; }
+ void setWrapMode(WrapMode m) { m_wrapMode = m; }
+
protected:
explicit TextureMapper(AccelerationMode);
+ GraphicsContext* m_context;
+
+ bool isInMaskMode() const { return m_isMaskMode; }
+ WrapMode wrapMode() const { return m_wrapMode; }
+ const TransformationMatrix& patternTransform() const { return m_patternTransform; }
+
private:
#if USE(TEXTURE_MAPPER_GL)
static PassOwnPtr<TextureMapper> platformCreateAccelerated();
@@ -176,8 +193,10 @@ private:
InterpolationQuality m_interpolationQuality;
TextDrawingModeFlags m_textDrawingMode;
OwnPtr<BitmapTexturePool> m_texturePool;
- GraphicsContext* m_context;
AccelerationMode m_accelerationMode;
+ bool m_isMaskMode;
+ TransformationMatrix m_patternTransform;
+ WrapMode m_wrapMode;
};
}
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp
index 788bb12a1..e68bc0914 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp
@@ -19,7 +19,7 @@
#include "config.h"
-#if USE(ACCELERATED_COMPOSITING)
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
#include "TextureMapperBackingStore.h"
#include "GraphicsLayer.h"
@@ -33,92 +33,6 @@
namespace WebCore {
-#if USE(GRAPHICS_SURFACE)
-void TextureMapperSurfaceBackingStore::setGraphicsSurface(PassRefPtr<GraphicsSurface> surface)
-{
- m_graphicsSurface = surface;
-}
-
-void TextureMapperSurfaceBackingStore::swapBuffersIfNeeded(uint32_t frontBuffer)
-{
- if (m_graphicsSurface && m_graphicsSurface->frontBuffer() != frontBuffer)
- m_graphicsSurface->swapBuffers();
-}
-
-PassRefPtr<BitmapTexture> TextureMapperSurfaceBackingStore::texture() const
-{
- // FIXME: Instead of just returning an empty texture, we should wrap the texture contents into a BitmapTexture.
- RefPtr<BitmapTexture> emptyTexture;
- return emptyTexture;
-}
-
-void TextureMapperSurfaceBackingStore::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity, BitmapTexture* mask)
-{
- if (m_graphicsSurface)
- m_graphicsSurface->paintToTextureMapper(textureMapper, targetRect, transform, opacity, mask);
-}
-#endif
-
-void TextureMapperTile::updateContents(TextureMapper* textureMapper, Image* image, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
-{
- IntRect targetRect = enclosingIntRect(m_rect);
- targetRect.intersect(dirtyRect);
- if (targetRect.isEmpty())
- return;
- IntPoint sourceOffset = targetRect.location();
-
- // Normalize sourceRect to the buffer's coordinates.
- sourceOffset.move(-dirtyRect.x(), -dirtyRect.y());
-
- // 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(), image->currentFrameHasAlpha() ? BitmapTexture::SupportsAlpha : 0);
- }
-
- 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())
- textureMapper->drawTexture(*texture().get(), rect(), transform, opacity, mask, exposedEdges);
-}
-
-TextureMapperTiledBackingStore::TextureMapperTiledBackingStore()
- : m_drawsDebugBorders(false)
-{
-}
-
-void TextureMapperTiledBackingStore::updateContentsFromImageIfNeeded(TextureMapper* textureMapper)
-{
- if (!m_image)
- return;
-
- updateContents(textureMapper, m_image.get(), m_image->size(), m_image->rect(), BitmapTexture::UpdateCannotModifyOriginalImageData);
- m_image.clear();
-}
-
unsigned TextureMapperBackingStore::calculateExposedTileEdges(const FloatRect& totalRect, const FloatRect& tileRect)
{
unsigned exposedEdges = TextureMapper::NoEdges;
@@ -133,112 +47,5 @@ unsigned TextureMapperBackingStore::calculateExposedTileEdges(const FloatRect& t
return exposedEdges;
}
-void TextureMapperTiledBackingStore::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity, BitmapTexture* mask)
-{
- updateContentsFromImageIfNeeded(textureMapper);
- TransformationMatrix adjustedTransform = transform;
- adjustedTransform.multiply(TransformationMatrix::rectToRect(rect(), targetRect));
- for (size_t i = 0; i < m_tiles.size(); ++i) {
- m_tiles[i].paint(textureMapper, adjustedTransform, opacity, mask, calculateExposedTileEdges(rect(), m_tiles[i].rect()));
- if (m_drawsDebugBorders)
- textureMapper->drawBorder(m_debugBorderColor, m_debugBorderWidth, m_tiles[i].rect(), adjustedTransform);
- }
-}
-
-void TextureMapperTiledBackingStore::createOrDestroyTilesIfNeeded(const FloatSize& size, const IntSize& tileSize, bool hasAlpha)
-{
- if (size == m_size)
- return;
-
- m_size = size;
-
- Vector<FloatRect> tileRectsToAdd;
- Vector<int> tileIndicesToRemove;
- static const size_t TileEraseThreshold = 6;
-
- // This method recycles tiles. We check which tiles we need to add, which to remove, and use as many
- // removable tiles as replacement for new tiles when possible.
- for (float y = 0; y < m_size.height(); y += tileSize.height()) {
- for (float x = 0; x < m_size.width(); x += tileSize.width()) {
- FloatRect tileRect(x, y, tileSize.width(), tileSize.height());
- tileRect.intersect(rect());
- tileRectsToAdd.append(tileRect);
- }
- }
-
- // Check which tiles need to be removed, and which already exist.
- for (int i = m_tiles.size() - 1; i >= 0; --i) {
- FloatRect oldTile = m_tiles[i].rect();
- bool existsAlready = false;
-
- for (int j = tileRectsToAdd.size() - 1; j >= 0; --j) {
- FloatRect newTile = tileRectsToAdd[j];
- if (oldTile != newTile)
- continue;
-
- // A tile that we want to add already exists, no need to add or remove it.
- existsAlready = true;
- tileRectsToAdd.remove(j);
- break;
- }
-
- // This tile is not needed.
- if (!existsAlready)
- tileIndicesToRemove.append(i);
- }
-
- // Recycle removable tiles to be used for newly requested tiles.
- for (size_t i = 0; i < tileRectsToAdd.size(); ++i) {
- if (!tileIndicesToRemove.isEmpty()) {
- // We recycle an existing tile for usage with a new tile rect.
- TextureMapperTile& tile = m_tiles[tileIndicesToRemove.last()];
- tileIndicesToRemove.removeLast();
- tile.setRect(tileRectsToAdd[i]);
-
- if (tile.texture())
- tile.texture()->reset(enclosingIntRect(tile.rect()).size(), hasAlpha ? BitmapTexture::SupportsAlpha : 0);
- continue;
- }
-
- m_tiles.append(TextureMapperTile(tileRectsToAdd[i]));
- }
-
- // Remove unnecessary tiles, if they weren't recycled.
- // We use a threshold to make sure we don't create/destroy tiles too eagerly.
- for (size_t i = 0; i < tileIndicesToRemove.size() && m_tiles.size() > TileEraseThreshold; ++i)
- m_tiles.remove(tileIndicesToRemove[i]);
-}
-
-void TextureMapperTiledBackingStore::updateContents(TextureMapper* textureMapper, Image* image, const FloatSize& totalSize, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
-{
- createOrDestroyTilesIfNeeded(totalSize, textureMapper->maxTextureSize(), image->currentFrameHasAlpha());
- for (size_t i = 0; i < m_tiles.size(); ++i)
- 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) {
- RefPtr<BitmapTexture> texture = m_tiles[i].texture();
- if (texture)
- return texture;
- }
-
- return PassRefPtr<BitmapTexture>();
-}
-
-void TextureMapperTiledBackingStore::setDebugBorder(const Color& color, float width)
-{
- m_debugBorderColor = color;
- m_debugBorderWidth = width;
-}
-
}
#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h
index 0dd2df4b1..4bae45b4f 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h
@@ -20,7 +20,7 @@
#ifndef TextureMapperBackingStore_h
#define TextureMapperBackingStore_h
-#if USE(ACCELERATED_COMPOSITING)
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
#include "FloatRect.h"
#include "Image.h"
@@ -39,83 +39,14 @@ class GraphicsLayer;
class TextureMapperBackingStore : public TextureMapperPlatformLayer, public RefCounted<TextureMapperBackingStore> {
public:
virtual PassRefPtr<BitmapTexture> texture() const = 0;
- virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float, BitmapTexture*) = 0;
+ virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float) = 0;
+ virtual void drawRepaintCounter(TextureMapper*, int /* repaintCount */, const Color&, const FloatRect&, const TransformationMatrix&) { }
virtual ~TextureMapperBackingStore() { }
protected:
static unsigned calculateExposedTileEdges(const FloatRect& totalRect, const FloatRect& tileRect);
};
-#if USE(GRAPHICS_SURFACE)
-class TextureMapperSurfaceBackingStore : public TextureMapperBackingStore {
-public:
- static PassRefPtr<TextureMapperSurfaceBackingStore> create() { return adoptRef(new TextureMapperSurfaceBackingStore); }
- void setGraphicsSurface(PassRefPtr<GraphicsSurface>);
- void swapBuffersIfNeeded(uint32_t frontBuffer);
- virtual PassRefPtr<BitmapTexture> texture() const;
- virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float, BitmapTexture*);
- virtual ~TextureMapperSurfaceBackingStore() { }
-
-private:
- TextureMapperSurfaceBackingStore()
- : TextureMapperBackingStore()
- { }
-
- RefPtr<GraphicsSurface> m_graphicsSurface;
-};
-#endif
-
-class TextureMapperTile {
-public:
- inline PassRefPtr<BitmapTexture> texture() const { return m_texture; }
- inline FloatRect rect() const { return m_rect; }
- inline void setTexture(BitmapTexture* texture) { m_texture = texture; }
- 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() { }
-
- explicit TextureMapperTile(const FloatRect& rect)
- : m_rect(rect)
- {
- }
-
-private:
- RefPtr<BitmapTexture> m_texture;
- FloatRect m_rect;
-};
-
-class TextureMapperTiledBackingStore : public TextureMapperBackingStore {
-public:
- static PassRefPtr<TextureMapperTiledBackingStore> create() { return adoptRef(new TextureMapperTiledBackingStore); }
- virtual ~TextureMapperTiledBackingStore() { }
-
- 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; }
- void setDebugBorder(const Color&, float width);
-
-private:
- TextureMapperTiledBackingStore();
- void createOrDestroyTilesIfNeeded(const FloatSize& backingStoreSize, const IntSize& tileSize, bool hasAlpha);
- void updateContentsFromImageIfNeeded(TextureMapper*);
- inline FloatRect rect() const { return FloatRect(FloatPoint::zero(), m_size); }
-
- Vector<TextureMapperTile> m_tiles;
- FloatSize m_size;
- RefPtr<Image> m_image;
-
- bool m_drawsDebugBorders;
- Color m_debugBorderColor;
- float m_debugBorderWidth;
-};
-
}
#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.cpp
new file mode 100644
index 000000000..1704f477d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.cpp
@@ -0,0 +1,67 @@
+/*
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2012, 2013 Company 100, Inc.
+ Copyright (C) 2012, 2013 basysKom GmbH
+
+ 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"
+
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
+
+#include "TextureMapperFPSCounter.h"
+
+#include "TextureMapper.h"
+#include <wtf/CurrentTime.h>
+
+namespace WebCore {
+
+TextureMapperFPSCounter::TextureMapperFPSCounter()
+ : m_isShowingFPS(false)
+ , m_fpsInterval(0)
+ , m_fpsTimestamp(0)
+ , m_lastFPS(0)
+ , m_frameCount(0)
+{
+ String showFPSEnvironment = getenv("WEBKIT_SHOW_FPS");
+ bool ok = false;
+ m_fpsInterval = showFPSEnvironment.toDouble(&ok);
+ if (ok && m_fpsInterval) {
+ m_isShowingFPS = true;
+ m_fpsTimestamp = WTF::currentTime();
+ }
+}
+
+void TextureMapperFPSCounter::updateFPSAndDisplay(TextureMapper* textureMapper, const FloatPoint& location, const TransformationMatrix& matrix)
+{
+ if (!m_isShowingFPS)
+ return;
+
+ m_frameCount++;
+ double delta = WTF::currentTime() - m_fpsTimestamp;
+ if (delta >= m_fpsInterval) {
+ m_lastFPS = int(m_frameCount / delta);
+ m_frameCount = 0;
+ m_fpsTimestamp += delta;
+ }
+
+ textureMapper->drawNumber(m_lastFPS, Color::black, location, matrix);
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.h b/Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.h
new file mode 100644
index 000000000..006237383
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperFPSCounter.h
@@ -0,0 +1,54 @@
+/*
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2012, 2013 Company 100, Inc.
+ Copyright (C) 2012, 2013 basysKom GmbH
+
+ 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 TextureMapperFPSCounter_h
+#define TextureMapperFPSCounter_h
+
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
+#include "FloatPoint.h"
+#include "TransformationMatrix.h"
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+class TextureMapper;
+
+class TextureMapperFPSCounter {
+ WTF_MAKE_NONCOPYABLE(TextureMapperFPSCounter);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ TextureMapperFPSCounter();
+ void updateFPSAndDisplay(TextureMapper*, const FloatPoint& = FloatPoint::zero(), const TransformationMatrix& = TransformationMatrix());
+
+private:
+ bool m_isShowingFPS;
+ double m_fpsInterval;
+ double m_fpsTimestamp;
+ int m_lastFPS;
+ int m_frameCount;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // TextureMapperFPSCounter_h
+
+
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp
index 2a6f29fdf..55c0b6aca 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp
@@ -22,17 +22,20 @@
#include "config.h"
#include "TextureMapperGL.h"
+#include "Extensions3D.h"
+#include "FilterOperations.h"
#include "GraphicsContext.h"
#include "Image.h"
#include "LengthFunctions.h"
#include "NotImplemented.h"
-#include "TextureMapperShaderManager.h"
+#include "TextureMapperShaderProgram.h"
#include "Timer.h"
#include <wtf/HashMap.h>
#include <wtf/OwnArrayPtr.h>
#include <wtf/PassOwnArrayPtr.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
+#include <wtf/TemporaryChange.h>
#if PLATFORM(QT)
#include "NativeImageQt.h"
@@ -56,13 +59,14 @@
#if !USE(TEXMAP_OPENGL_ES_2)
// FIXME: Move to Extensions3D.h.
-#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
#define GL_UNPACK_ROW_LENGTH 0x0CF2
#define GL_UNPACK_SKIP_PIXELS 0x0CF4
#define GL_UNPACK_SKIP_ROWS 0x0CF3
#endif
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
+
namespace WebCore {
struct TextureMapperGLData {
WTF_MAKE_FAST_ALLOCATED;
@@ -85,12 +89,20 @@ public:
return adoptRef(new SharedGLData(context));
}
+ PassRefPtr<TextureMapperShaderProgram> getShaderProgram(TextureMapperShaderProgram::Options options)
+ {
+ HashMap<TextureMapperShaderProgram::Options, RefPtr<TextureMapperShaderProgram> >::AddResult result = m_programs.add(options, 0);
+ if (result.isNewEntry)
+ result.iterator->value = TextureMapperShaderProgram::create(m_context, options);
+ return result.iterator->value;
+ }
- TextureMapperShaderManager textureMapperShaderManager;
+ HashMap<TextureMapperShaderProgram::Options, RefPtr<TextureMapperShaderProgram> > m_programs;
+ RefPtr<GraphicsContext3D> m_context;
explicit SharedGLData(GraphicsContext3D* context)
- : textureMapperShaderManager(context)
+ : m_context(context)
{
glContextDataMap().add(context->platformGraphicsContext3D(), this);
}
@@ -111,7 +123,7 @@ public:
SharedGLData& sharedGLData() const
{
- return *m_sharedGLData;
+ return *sharedData;
}
void initializeStencil();
@@ -124,9 +136,15 @@ public:
, didModifyStencil(false)
, previousScissorState(0)
, previousDepthState(0)
- , m_sharedGLData(TextureMapperGLData::SharedGLData::currentSharedGLData(this->context))
+ , sharedData(TextureMapperGLData::SharedGLData::currentSharedGLData(this->context))
+#if ENABLE(CSS_FILTERS)
+ , filterInfo(0)
+#endif
{ }
+ ~TextureMapperGLData();
+ Platform3DObject getStaticVBO(GC3Denum target, GC3Dsizeiptr, const void* data);
+
GraphicsContext3D* context;
TransformationMatrix projectionMatrix;
TextureMapper::PaintFlags PaintFlags;
@@ -137,19 +155,59 @@ public:
GC3Dint previousDepthState;
GC3Dint viewport[4];
GC3Dint previousScissor[4];
- RefPtr<SharedGLData> m_sharedGLData;
+ RefPtr<SharedGLData> sharedData;
RefPtr<BitmapTexture> currentSurface;
+ HashMap<const void*, Platform3DObject> vbos;
+#if ENABLE(CSS_FILTERS)
+ const BitmapTextureGL::FilterInfo* filterInfo;
+#endif
};
-void TextureMapperGL::ClipStack::init(const IntRect& rect)
+Platform3DObject TextureMapperGLData::getStaticVBO(GC3Denum target, GC3Dsizeiptr size, const void* data)
+{
+ HashMap<const void*, Platform3DObject>::AddResult result = vbos.add(data, 0);
+ if (result.isNewEntry) {
+ Platform3DObject vbo = context->createBuffer();
+ context->bindBuffer(target, vbo);
+ context->bufferData(target, size, data, GraphicsContext3D::STATIC_DRAW);
+ result.iterator->value = vbo;
+ }
+
+ return result.iterator->value;
+}
+
+TextureMapperGLData::~TextureMapperGLData()
+{
+ HashMap<const void*, Platform3DObject>::iterator end = vbos.end();
+ for (HashMap<const void*, Platform3DObject>::iterator it = vbos.begin(); it != end; ++it)
+ context->deleteBuffer(it->value);
+}
+
+void TextureMapperGL::ClipStack::reset(const IntRect& rect, TextureMapperGL::ClipStack::YAxisMode mode)
{
clipStack.clear();
+ size = rect.size();
+ yAxisMode = mode;
clipState = TextureMapperGL::ClipState(rect);
+ clipStateDirty = true;
+}
+
+void TextureMapperGL::ClipStack::intersect(const IntRect& rect)
+{
+ clipState.scissorBox.intersect(rect);
+ clipStateDirty = true;
+}
+
+void TextureMapperGL::ClipStack::setStencilIndex(int stencilIndex)
+{
+ clipState.stencilIndex = stencilIndex;
+ clipStateDirty = true;
}
void TextureMapperGL::ClipStack::push()
{
clipStack.append(clipState);
+ clipStateDirty = true;
}
void TextureMapperGL::ClipStack::pop()
@@ -158,21 +216,17 @@ void TextureMapperGL::ClipStack::pop()
return;
clipState = clipStack.last();
clipStack.removeLast();
+ clipStateDirty = true;
}
-static void scissorClip(GraphicsContext3D* context, const IntRect& rect)
+void TextureMapperGL::ClipStack::apply(GraphicsContext3D* context)
{
- if (rect.isEmpty())
+ if (clipState.scissorBox.isEmpty())
return;
- GC3Dint viewport[4];
- context->getIntegerv(GraphicsContext3D::VIEWPORT, viewport);
- context->scissor(rect.x(), viewport[3] - rect.maxY(), rect.width(), rect.height());
-}
-
-void TextureMapperGL::ClipStack::apply(GraphicsContext3D* context)
-{
- scissorClip(context, clipState.scissorBox);
+ context->scissor(clipState.scissorBox.x(),
+ (yAxisMode == InvertedYAxis) ? size.height() - clipState.scissorBox.maxY() : clipState.scissorBox.y(),
+ clipState.scissorBox.width(), clipState.scissorBox.height());
context->stencilOp(GraphicsContext3D::KEEP, GraphicsContext3D::KEEP, GraphicsContext3D::KEEP);
context->stencilFunc(GraphicsContext3D::EQUAL, clipState.stencilIndex - 1, clipState.stencilIndex - 1);
if (clipState.stencilIndex == 1)
@@ -181,6 +235,14 @@ void TextureMapperGL::ClipStack::apply(GraphicsContext3D* context)
context->enable(GraphicsContext3D::STENCIL_TEST);
}
+void TextureMapperGL::ClipStack::applyIfNeeded(GraphicsContext3D* context)
+{
+ if (!clipStateDirty)
+ return;
+
+ clipStateDirty = false;
+ apply(context);
+}
void TextureMapperGLData::initializeStencil()
{
@@ -207,7 +269,6 @@ BitmapTextureGL* toBitmapTextureGL(BitmapTexture* texture)
TextureMapperGL::TextureMapperGL()
: TextureMapper(OpenGLMode)
- , m_context(0)
, m_enableEdgeDistanceAntialiasing(false)
{
m_context3D = GraphicsContext3D::createForCurrentGLContext();
@@ -237,7 +298,7 @@ void TextureMapperGL::beginPainting(PaintFlags flags)
m_context3D->depthMask(0);
m_context3D->getIntegerv(GraphicsContext3D::VIEWPORT, data().viewport);
m_context3D->getIntegerv(GraphicsContext3D::SCISSOR_BOX, data().previousScissor);
- m_clipStack.init(IntRect(0, 0, data().viewport[2], data().viewport[3]));
+ m_clipStack.reset(IntRect(0, 0, data().viewport[2], data().viewport[3]), ClipStack::InvertedYAxis);
m_context3D->getIntegerv(GraphicsContext3D::FRAMEBUFFER_BINDING, &data().targetFrameBuffer);
data().PaintFlags = flags;
bindSurface(0);
@@ -272,62 +333,28 @@ void TextureMapperGL::endPainting()
#endif
}
-void TextureMapperGL::drawQuad(const DrawQuad& quadToDraw, const TransformationMatrix& modelViewMatrix, TextureMapperShaderProgram* shaderProgram, GC3Denum drawingMode, bool needsBlending)
-{
- m_context3D->enableVertexAttribArray(shaderProgram->vertexLocation());
- m_context3D->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
-
- const GC3Dfloat quad[] = {
- quadToDraw.targetRectMappedToUnitSquare.p1().x(), quadToDraw.targetRectMappedToUnitSquare.p1().y(),
- quadToDraw.targetRectMappedToUnitSquare.p2().x(), quadToDraw.targetRectMappedToUnitSquare.p2().y(),
- quadToDraw.targetRectMappedToUnitSquare.p3().x(), quadToDraw.targetRectMappedToUnitSquare.p3().y(),
- quadToDraw.targetRectMappedToUnitSquare.p4().x(), quadToDraw.targetRectMappedToUnitSquare.p4().y()
- };
- m_context3D->vertexAttribPointer(shaderProgram->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(quad));
-
- TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix).multiply(modelViewMatrix).multiply(TransformationMatrix(
- quadToDraw.originalTargetRect.width(), 0, 0, 0,
- 0, quadToDraw.originalTargetRect.height(), 0, 0,
- 0, 0, 1, 0,
- quadToDraw.originalTargetRect.x(), quadToDraw.originalTargetRect.y(), 0, 1));
- GC3Dfloat m4[] = {
- matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
- matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
- matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
- matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()
- };
- m_context3D->uniformMatrix4fv(shaderProgram->matrixLocation(), 1, false, m4);
-
- if (needsBlending) {
- m_context3D->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
- m_context3D->enable(GraphicsContext3D::BLEND);
- } else
- m_context3D->disable(GraphicsContext3D::BLEND);
-
- m_context3D->drawArrays(drawingMode, 0, 4);
- m_context3D->disableVertexAttribArray(shaderProgram->vertexLocation());
-}
-
void TextureMapperGL::drawBorder(const Color& color, float width, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix)
{
- if (clipStack().current().scissorBox.isEmpty())
+ if (clipStack().isCurrentScissorBoxEmpty())
return;
- RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::SolidColor);
+ RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().getShaderProgram(TextureMapperShaderProgram::SolidColor);
m_context3D->useProgram(program->programID());
float r, g, b, a;
- color.getRGBA(r, g, b, a);
+ Color(premultipliedARGBFromColor(color)).getRGBA(r, g, b, a);
m_context3D->uniform4f(program->colorLocation(), r, g, b, a);
m_context3D->lineWidth(width);
- drawQuad(targetRect, modelViewMatrix, program.get(), GraphicsContext3D::LINE_LOOP, color.hasAlpha());
+ draw(targetRect, modelViewMatrix, program.get(), GraphicsContext3D::LINE_LOOP, color.hasAlpha() ? ShouldBlend : 0);
}
-void TextureMapperGL::drawRepaintCounter(int value, int pointSize, const FloatPoint& targetPoint, const TransformationMatrix& modelViewMatrix)
+// FIXME: drawNumber() should save a number texture-atlas and re-use whenever possible.
+void TextureMapperGL::drawNumber(int number, const Color& color, const FloatPoint& targetPoint, const TransformationMatrix& modelViewMatrix)
{
+ int pointSize = 8;
#if PLATFORM(QT)
- QString counterString = QString::number(value);
+ QString counterString = QString::number(number);
QFont font(QString::fromLatin1("Monospace"), pointSize, QFont::Bold);
font.setStyleHint(QFont::TypeWriter);
@@ -342,7 +369,7 @@ void TextureMapperGL::drawRepaintCounter(int value, int pointSize, const FloatPo
QImage image(size, NativeImageQt::defaultFormatForAlphaEnabledImages());
QPainter painter(&image);
- painter.fillRect(sourceRect, Qt::blue); // Since we won't swap R+B for speed, this will paint red.
+ painter.fillRect(sourceRect, Color::createUnchecked(color.blue(), color.green(), color.red())); // Since we won't swap R+B when uploading a texture, paint with the swapped R+B color.
painter.setFont(font);
painter.setPen(Qt::white);
painter.drawText(2, height * 0.85, counterString);
@@ -350,10 +377,10 @@ void TextureMapperGL::drawRepaintCounter(int value, int pointSize, const FloatPo
RefPtr<BitmapTexture> texture = acquireTextureFromPool(size);
const uchar* bits = image.bits();
static_cast<BitmapTextureGL*>(texture.get())->updateContentsNoSwizzle(bits, sourceRect, IntPoint::zero(), image.bytesPerLine());
- drawTexture(*texture, targetRect, modelViewMatrix, 1.0f, 0, AllEdges);
+ drawTexture(*texture, targetRect, modelViewMatrix, 1.0f, AllEdges);
#elif USE(CAIRO)
- CString counterString = String::number(value).ascii();
+ CString counterString = String::number(number).ascii();
// cairo_text_extents() requires a cairo_t, so dimensions need to be guesstimated.
int width = counterString.length() * pointSize * 1.2;
int height = pointSize * 1.5;
@@ -361,7 +388,9 @@ void TextureMapperGL::drawRepaintCounter(int value, int pointSize, const FloatPo
cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
cairo_t* cr = cairo_create(surface);
- cairo_set_source_rgb(cr, 0, 0, 1); // Since we won't swap R+B for speed, this will paint red.
+ float r, g, b, a;
+ color.getRGBA(r, g, b, a);
+ cairo_set_source_rgba(cr, b, g, r, a); // Since we won't swap R+B when uploading a texture, paint with the swapped R+B color.
cairo_rectangle(cr, 0, 0, width, height);
cairo_fill(cr);
@@ -379,13 +408,13 @@ void TextureMapperGL::drawRepaintCounter(int value, int pointSize, const FloatPo
const unsigned char* bits = cairo_image_surface_get_data(surface);
int stride = cairo_image_surface_get_stride(surface);
static_cast<BitmapTextureGL*>(texture.get())->updateContentsNoSwizzle(bits, sourceRect, IntPoint::zero(), stride);
- drawTexture(*texture, targetRect, modelViewMatrix, 1.0f, 0, AllEdges);
+ drawTexture(*texture, targetRect, modelViewMatrix, 1.0f, AllEdges);
cairo_surface_destroy(surface);
cairo_destroy(cr);
#else
- UNUSED_PARAM(value);
+ UNUSED_PARAM(number);
UNUSED_PARAM(pointSize);
UNUSED_PARAM(targetPoint);
UNUSED_PARAM(modelViewMatrix);
@@ -393,229 +422,337 @@ void TextureMapperGL::drawRepaintCounter(int value, int pointSize, const FloatPo
#endif
}
-void TextureMapperGL::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* mask, unsigned exposedEdges)
-{
- if (!texture.isValid())
- return;
+#if ENABLE(CSS_FILTERS)
- if (clipStack().current().scissorBox.isEmpty())
- return;
+static TextureMapperShaderProgram::Options optionsForFilterType(FilterOperation::OperationType type, unsigned pass)
+{
+ switch (type) {
+ case FilterOperation::GRAYSCALE:
+ return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::GrayscaleFilter;
+ case FilterOperation::SEPIA:
+ return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::SepiaFilter;
+ case FilterOperation::SATURATE:
+ return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::SaturateFilter;
+ case FilterOperation::HUE_ROTATE:
+ return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::HueRotateFilter;
+ case FilterOperation::INVERT:
+ return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::InvertFilter;
+ case FilterOperation::BRIGHTNESS:
+ return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::BrightnessFilter;
+ case FilterOperation::CONTRAST:
+ return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::ContrastFilter;
+ case FilterOperation::OPACITY:
+ return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::OpacityFilter;
+ case FilterOperation::BLUR:
+ return TextureMapperShaderProgram::BlurFilter;
+ case FilterOperation::DROP_SHADOW:
+ return TextureMapperShaderProgram::AlphaBlur
+ | (pass ? TextureMapperShaderProgram::ContentTexture | TextureMapperShaderProgram::SolidColor: 0);
+ default:
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+}
- const BitmapTextureGL& textureGL = static_cast<const BitmapTextureGL&>(texture);
- drawTexture(textureGL.id(), textureGL.isOpaque() ? 0 : SupportsBlending, textureGL.size(), targetRect, matrix, opacity, mask, exposedEdges);
+static unsigned getPassesRequiredForFilter(FilterOperation::OperationType type)
+{
+ switch (type) {
+ case FilterOperation::GRAYSCALE:
+ case FilterOperation::SEPIA:
+ case FilterOperation::SATURATE:
+ case FilterOperation::HUE_ROTATE:
+ case FilterOperation::INVERT:
+ case FilterOperation::BRIGHTNESS:
+ case FilterOperation::CONTRAST:
+ case FilterOperation::OPACITY:
+#if ENABLE(CSS_SHADERS)
+ case FilterOperation::CUSTOM:
+ case FilterOperation::VALIDATED_CUSTOM:
+#endif
+ return 1;
+ case FilterOperation::BLUR:
+ case FilterOperation::DROP_SHADOW:
+ // We use two-passes (vertical+horizontal) for blur and drop-shadow.
+ return 2;
+ default:
+ return 0;
+ }
}
-#if !USE(TEXMAP_OPENGL_ES_2)
-void TextureMapperGL::drawTextureRectangleARB(uint32_t texture, Flags flags, const IntSize& textureSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture)
+// Create a normal distribution of 21 values between -2 and 2.
+static const unsigned GaussianKernelHalfWidth = 11;
+static const float GaussianKernelStep = 0.2;
+
+static inline float gauss(float x)
{
- RefPtr<TextureMapperShaderProgram> program;
- if (maskTexture)
- program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::MaskedRect);
- else
- program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Rect);
- m_context3D->useProgram(program->programID());
+ return exp(-(x * x) / 2.);
+}
- m_context3D->enableVertexAttribArray(program->vertexLocation());
- m_context3D->activeTexture(GraphicsContext3D::TEXTURE0);
- m_context3D->bindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
- m_context3D->uniform1i(program->samplerLocation(), 0);
+static float* gaussianKernel()
+{
+ static bool prepared = false;
+ static float kernel[GaussianKernelHalfWidth] = {0, };
- m_context3D->uniform1f(program->flipLocation(), !!(flags & ShouldFlipTexture));
- m_context3D->uniform2f(program->samplerSizeLocation(), textureSize.width(), textureSize.height());
- m_context3D->uniform1f(program->opacityLocation(), opacity);
+ if (prepared)
+ return kernel;
- if (maskTexture && maskTexture->isValid()) {
- const BitmapTextureGL* maskTextureGL = static_cast<const BitmapTextureGL*>(maskTexture);
- m_context3D->activeTexture(GraphicsContext3D::TEXTURE1);
- m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, maskTextureGL->id());
- m_context3D->uniform1i(program->maskLocation(), 1);
- m_context3D->activeTexture(GraphicsContext3D::TEXTURE0);
+ kernel[0] = gauss(0);
+ float sum = kernel[0];
+ for (unsigned i = 1; i < GaussianKernelHalfWidth; ++i) {
+ kernel[i] = gauss(i * GaussianKernelStep);
+ sum += 2 * kernel[i];
}
- bool needsBlending = (flags & SupportsBlending) || opacity < 0.99 || maskTexture;
- drawQuad(targetRect, modelViewMatrix, program.get(), GraphicsContext3D::TRIANGLE_FAN, needsBlending);
+ // Normalize the kernel.
+ float scale = 1 / sum;
+ for (unsigned i = 0; i < GaussianKernelHalfWidth; ++i)
+ kernel[i] *= scale;
+
+ prepared = true;
+ return kernel;
}
-#endif // !USE(TEXMAP_OPENGL_ES_2)
-void TextureMapperGL::drawTexture(uint32_t texture, Flags flags, const IntSize& /* textureSize */, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture, unsigned exposedEdges)
+static void prepareFilterProgram(TextureMapperShaderProgram* program, const FilterOperation& operation, unsigned pass, const IntSize& size, GC3Duint contentTexture)
{
- bool needsAntialiasing = m_enableEdgeDistanceAntialiasing && !modelViewMatrix.isIntegerTranslation();
- if (needsAntialiasing && drawTextureWithAntialiasing(texture, flags, targetRect, modelViewMatrix, opacity, maskTexture, exposedEdges))
- return;
+ RefPtr<GraphicsContext3D> context = program->context();
+ context->useProgram(program->programID());
- RefPtr<TextureMapperShaderProgram> program;
- if (maskTexture)
- program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Masked);
- else
- program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Default);
- m_context3D->useProgram(program->programID());
+ switch (operation.getOperationType()) {
+ case FilterOperation::GRAYSCALE:
+ case FilterOperation::SEPIA:
+ case FilterOperation::SATURATE:
+ case FilterOperation::HUE_ROTATE:
+ context->uniform1f(program->filterAmountLocation(), static_cast<const BasicColorMatrixFilterOperation&>(operation).amount());
+ break;
+ case FilterOperation::INVERT:
+ case FilterOperation::BRIGHTNESS:
+ case FilterOperation::CONTRAST:
+ case FilterOperation::OPACITY:
+ context->uniform1f(program->filterAmountLocation(), static_cast<const BasicComponentTransferFilterOperation&>(operation).amount());
+ break;
+ case FilterOperation::BLUR: {
+ const BlurFilterOperation& blur = static_cast<const BlurFilterOperation&>(operation);
+ FloatSize radius;
- drawTexturedQuadWithProgram(program.get(), texture, flags, targetRect, modelViewMatrix, opacity, maskTexture);
+ // Blur is done in two passes, first horizontally and then vertically. The same shader is used for both.
+ if (pass)
+ radius.setHeight(floatValueForLength(blur.stdDeviation(), size.height()) / size.height());
+ else
+ radius.setWidth(floatValueForLength(blur.stdDeviation(), size.width()) / size.width());
+
+ context->uniform2f(program->blurRadiusLocation(), radius.width(), radius.height());
+ context->uniform1fv(program->gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel());
+ break;
+ }
+ case FilterOperation::DROP_SHADOW: {
+ const DropShadowFilterOperation& shadow = static_cast<const DropShadowFilterOperation&>(operation);
+ context->uniform1fv(program->gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel());
+ switch (pass) {
+ case 0:
+ // First pass: horizontal alpha blur.
+ context->uniform2f(program->blurRadiusLocation(), shadow.stdDeviation() / float(size.width()), 0);
+ context->uniform2f(program->shadowOffsetLocation(), float(shadow.location().x()) / float(size.width()), float(shadow.location().y()) / float(size.height()));
+ break;
+ case 1:
+ // Second pass: we need the shadow color and the content texture for compositing.
+ float r, g, b, a;
+ Color(premultipliedARGBFromColor(shadow.color())).getRGBA(r, g, b, a);
+ context->uniform4f(program->colorLocation(), r, g, b, a);
+ context->uniform2f(program->blurRadiusLocation(), 0, shadow.stdDeviation() / float(size.height()));
+ context->uniform2f(program->shadowOffsetLocation(), 0, 0);
+ context->activeTexture(GraphicsContext3D::TEXTURE1);
+ context->bindTexture(GraphicsContext3D::TEXTURE_2D, contentTexture);
+ context->uniform1i(program->contentTextureLocation(), 1);
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
}
+#endif
-void TextureMapperGL::drawSolidColor(const FloatRect& rect, const TransformationMatrix& matrix, const Color& color)
+void TextureMapperGL::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, unsigned exposedEdges)
{
- RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::SolidColor);
- m_context3D->useProgram(program->programID());
+ if (!texture.isValid())
+ return;
- float r, g, b, a;
- color.getRGBA(r, g, b, a);
- m_context3D->uniform4f(program->colorLocation(), r, g, b, a);
+ if (clipStack().isCurrentScissorBoxEmpty())
+ return;
- drawQuad(rect, matrix, program.get(), GraphicsContext3D::TRIANGLE_FAN, false);
+ const BitmapTextureGL& textureGL = static_cast<const BitmapTextureGL&>(texture);
+#if ENABLE(CSS_FILTERS)
+ TemporaryChange<const BitmapTextureGL::FilterInfo*> filterInfo(data().filterInfo, textureGL.filterInfo());
+#endif
+
+ drawTexture(textureGL.id(), textureGL.isOpaque() ? 0 : ShouldBlend, textureGL.size(), targetRect, matrix, opacity, exposedEdges);
}
-static TransformationMatrix viewportMatrix(GraphicsContext3D* context3D)
+void TextureMapperGL::drawTexture(Platform3DObject texture, Flags flags, const IntSize& textureSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, unsigned exposedEdges)
{
- GC3Dint viewport[4];
- context3D->getIntegerv(GraphicsContext3D::VIEWPORT, viewport);
+ bool useRect = flags & ShouldUseARBTextureRect;
+ bool useAntialiasing = m_enableEdgeDistanceAntialiasing
+ && exposedEdges == AllEdges
+ && !modelViewMatrix.mapQuad(targetRect).isRectilinear();
+
+ TextureMapperShaderProgram::Options options = TextureMapperShaderProgram::Texture;
+ if (useRect)
+ options |= TextureMapperShaderProgram::Rect;
+ if (opacity < 1)
+ options |= TextureMapperShaderProgram::Opacity;
+ if (useAntialiasing) {
+ options |= TextureMapperShaderProgram::Antialiasing;
+ flags |= ShouldAntialias;
+ }
- TransformationMatrix matrix;
- matrix.translate3d(viewport[0], viewport[1], 0);
- matrix.scale3d(viewport[2], viewport[3], 0);
+#if ENABLE(CSS_FILTERS)
+ RefPtr<FilterOperation> filter = data().filterInfo ? data().filterInfo->filter: 0;
+ GC3Duint filterContentTextureID = 0;
+
+ if (filter) {
+ if (data().filterInfo->contentTexture)
+ filterContentTextureID = toBitmapTextureGL(data().filterInfo->contentTexture.get())->id();
+ options |= optionsForFilterType(filter->getOperationType(), data().filterInfo->pass);
+ if (filter->affectsOpacity())
+ flags |= ShouldBlend;
+ }
+#endif
- // Map x, y and z to unit square from OpenGL normalized device
- // coordinates which are -1 to 1 on every axis.
- matrix.translate3d(0.5, 0.5, 0.5);
- matrix.scale3d(0.5, 0.5, 0.5);
+ if (useAntialiasing || opacity < 1)
+ flags |= ShouldBlend;
- return matrix;
-}
+ RefPtr<TextureMapperShaderProgram> program;
+ program = data().sharedGLData().getShaderProgram(options);
-static void scaleLineEquationCoeffecientsToOptimizeDistanceCalculation(float* coeffecients)
-{
- // In the fragment shader we want to calculate the distance from this
- // line to a point (p), which is given by the formula:
- // (A*p.x + B*p.y + C) / sqrt (a^2 + b^2)
- // We can do a small amount of precalculation here to reduce the
- // amount of math in the shader by scaling the coeffecients now.
- float scale = 1.0 / FloatPoint(coeffecients[0], coeffecients[1]).length();
- coeffecients[0] = coeffecients[0] * scale;
- coeffecients[1] = coeffecients[1] * scale;
- coeffecients[2] = coeffecients[2] * scale;
-}
+#if ENABLE(CSS_FILTERS)
+ if (filter)
+ prepareFilterProgram(program.get(), *filter.get(), data().filterInfo->pass, textureSize, filterContentTextureID);
+#endif
-static void getStandardEquationCoeffecientsForLine(const FloatPoint& p1, const FloatPoint& p2, float* coeffecients)
-{
- // Given two points, the standard equation of a line (Ax + By + C = 0)
- // can be calculated via the formula:
- // (p1.y – p2.y)x + (p1.x – p2.x)y + ((p1.x*p2.y) – (p2.x*p1.y)) = 0
- coeffecients[0] = p1.y() - p2.y();
- coeffecients[1] = p2.x() - p1.x();
- coeffecients[2] = p1.x() * p2.y() - p2.x() * p1.y();
- scaleLineEquationCoeffecientsToOptimizeDistanceCalculation(coeffecients);
+ drawTexturedQuadWithProgram(program.get(), texture, flags, textureSize, targetRect, modelViewMatrix, opacity);
}
-static void quadToEdgeArray(const FloatQuad& quad, float* edgeArray)
+void TextureMapperGL::drawSolidColor(const FloatRect& rect, const TransformationMatrix& matrix, const Color& color)
{
- if (quad.isCounterclockwise()) {
- getStandardEquationCoeffecientsForLine(quad.p4(), quad.p3(), edgeArray);
- getStandardEquationCoeffecientsForLine(quad.p3(), quad.p2(), edgeArray + 3);
- getStandardEquationCoeffecientsForLine(quad.p2(), quad.p1(), edgeArray + 6);
- getStandardEquationCoeffecientsForLine(quad.p1(), quad.p4(), edgeArray + 9);
- return;
+ Flags flags = 0;
+ TextureMapperShaderProgram::Options options = TextureMapperShaderProgram::SolidColor;
+ if (!matrix.mapQuad(rect).isRectilinear()) {
+ options |= TextureMapperShaderProgram::Antialiasing;
+ flags |= ShouldBlend | ShouldAntialias;
}
- getStandardEquationCoeffecientsForLine(quad.p4(), quad.p1(), edgeArray);
- getStandardEquationCoeffecientsForLine(quad.p1(), quad.p2(), edgeArray + 3);
- getStandardEquationCoeffecientsForLine(quad.p2(), quad.p3(), edgeArray + 6);
- getStandardEquationCoeffecientsForLine(quad.p3(), quad.p4(), edgeArray + 9);
-}
-static FloatSize scaledVectorDifference(const FloatPoint& point1, const FloatPoint& point2, float scale)
-{
- FloatSize vector = point1 - point2;
- if (vector.diagonalLengthSquared())
- vector.scale(1.0 / vector.diagonalLength());
+ RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().getShaderProgram(options);
+ m_context3D->useProgram(program->programID());
+
+ float r, g, b, a;
+ Color(premultipliedARGBFromColor(color)).getRGBA(r, g, b, a);
+ m_context3D->uniform4f(program->colorLocation(), r, g, b, a);
+ if (a < 1)
+ flags |= ShouldBlend;
- vector.scale(scale);
- return vector;
+ draw(rect, matrix, program.get(), GraphicsContext3D::TRIANGLE_FAN, flags);
}
-static FloatQuad inflateQuad(const FloatQuad& quad, float distance)
+void TextureMapperGL::drawEdgeTriangles(TextureMapperShaderProgram* program)
{
- FloatQuad expandedQuad = quad;
- expandedQuad.setP1(expandedQuad.p1() + scaledVectorDifference(quad.p1(), quad.p2(), distance));
- expandedQuad.setP4(expandedQuad.p4() + scaledVectorDifference(quad.p4(), quad.p3(), distance));
-
- expandedQuad.setP1(expandedQuad.p1() + scaledVectorDifference(quad.p1(), quad.p4(), distance));
- expandedQuad.setP2(expandedQuad.p2() + scaledVectorDifference(quad.p2(), quad.p3(), distance));
-
- expandedQuad.setP2(expandedQuad.p2() + scaledVectorDifference(quad.p2(), quad.p1(), distance));
- expandedQuad.setP3(expandedQuad.p3() + scaledVectorDifference(quad.p3(), quad.p4(), distance));
+ const GC3Dfloat left = 0;
+ const GC3Dfloat top = 0;
+ const GC3Dfloat right = 1;
+ const GC3Dfloat bottom = 1;
+ const GC3Dfloat center = 0.5;
+
+// Each 4d triangle consists of a center point and two edge points, where the zw coordinates
+// of each vertex equals the nearest point to the vertex on the edge.
+#define SIDE_TRIANGLE_DATA(x1, y1, x2, y2) \
+ x1, y1, x1, y1, \
+ x2, y2, x2, y2, \
+ center, center, (x1 + x2) / 2, (y1 + y2) / 2
+
+ static const GC3Dfloat unitRectSideTriangles[] = {
+ SIDE_TRIANGLE_DATA(left, top, right, top),
+ SIDE_TRIANGLE_DATA(left, top, left, bottom),
+ SIDE_TRIANGLE_DATA(right, top, right, bottom),
+ SIDE_TRIANGLE_DATA(left, bottom, right, bottom)
+ };
+#undef SIDE_TRIANGLE_DATA
- expandedQuad.setP3(expandedQuad.p3() + scaledVectorDifference(quad.p3(), quad.p2(), distance));
- expandedQuad.setP4(expandedQuad.p4() + scaledVectorDifference(quad.p4(), quad.p1(), distance));
+ Platform3DObject vbo = data().getStaticVBO(GraphicsContext3D::ARRAY_BUFFER, sizeof(GC3Dfloat) * 48, unitRectSideTriangles);
+ m_context3D->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, vbo);
+ m_context3D->vertexAttribPointer(program->vertexLocation(), 4, GraphicsContext3D::FLOAT, false, 0, 0);
+ m_context3D->drawArrays(GraphicsContext3D::TRIANGLES, 0, 12);
+ m_context3D->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
+}
- return expandedQuad;
+void TextureMapperGL::drawUnitRect(TextureMapperShaderProgram* program, GC3Denum drawingMode)
+{
+ static const GC3Dfloat unitRect[] = { 0, 0, 1, 0, 1, 1, 0, 1 };
+ Platform3DObject vbo = data().getStaticVBO(GraphicsContext3D::ARRAY_BUFFER, sizeof(GC3Dfloat) * 8, unitRect);
+ m_context3D->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, vbo);
+ m_context3D->vertexAttribPointer(program->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, 0);
+ m_context3D->drawArrays(drawingMode, 0, 4);
+ m_context3D->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
}
-bool TextureMapperGL::drawTextureWithAntialiasing(uint32_t texture, Flags flags, const FloatRect& originalTargetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture, unsigned exposedEdges)
+void TextureMapperGL::draw(const FloatRect& rect, const TransformationMatrix& modelViewMatrix, TextureMapperShaderProgram* shaderProgram, GC3Denum drawingMode, Flags flags)
{
- // The antialiasing path does not support mask textures at the moment.
- if (maskTexture)
- return false;
+ TransformationMatrix matrix =
+ TransformationMatrix(modelViewMatrix).multiply(TransformationMatrix::rectToRect(FloatRect(0, 0, 1, 1), rect));
- // For now we punt on rendering tiled layers with antialiasing. It's quite hard
- // to render them without seams.
- if (exposedEdges != AllEdges)
- return false;
+ m_context3D->enableVertexAttribArray(shaderProgram->vertexLocation());
+ shaderProgram->setMatrix(shaderProgram->modelViewMatrixLocation(), matrix);
+ shaderProgram->setMatrix(shaderProgram->projectionMatrixLocation(), data().projectionMatrix);
- // The goal here is render a slightly larger (0.75 pixels in screen space) quad and to
- // gradually taper off the alpha values to do a simple version of edge distance
- // antialiasing. Note here that we are also including the viewport matrix (which
- // translates from normalized device coordinates to screen coordinates), because these
- // values are consumed in the fragment shader, which works in screen coordinates.
- TransformationMatrix screenSpaceTransform = viewportMatrix(m_context3D.get()).multiply(TransformationMatrix(data().projectionMatrix)).multiply(modelViewMatrix).to2dTransform();
- if (!screenSpaceTransform.isInvertible())
- return false;
- FloatQuad quadInScreenSpace = screenSpaceTransform.mapQuad(originalTargetRect);
-
- const float inflationDistance = 0.75;
- FloatQuad expandedQuadInScreenSpace = inflateQuad(quadInScreenSpace, inflationDistance);
-
- // In the non-antialiased case the vertices passed are the unit rectangle and double
- // as the texture coordinates (0,0 1,0, 1,1 and 0,1). Here we map the expanded quad
- // coordinates in screen space back to the original rect's texture coordinates.
- // This has the effect of slightly increasing the size of the original quad's geometry
- // in the vertex shader.
- FloatQuad expandedQuadInTextureCoordinates = screenSpaceTransform.inverse().mapQuad(expandedQuadInScreenSpace);
- expandedQuadInTextureCoordinates.move(-originalTargetRect.x(), -originalTargetRect.y());
- expandedQuadInTextureCoordinates.scale(1 / originalTargetRect.width(), 1 / originalTargetRect.height());
-
- // We prepare both the expanded quad for the fragment shader as well as the rectangular bounding
- // box of that quad, as that seems necessary to properly antialias backfacing quads.
- float targetQuadEdges[24];
- quadToEdgeArray(expandedQuadInScreenSpace, targetQuadEdges);
- quadToEdgeArray(inflateQuad(quadInScreenSpace.boundingBox(), inflationDistance), targetQuadEdges + 12);
-
- RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Antialiased);
- m_context3D->useProgram(program->programID());
- m_context3D->uniform3fv(program->expandedQuadEdgesInScreenSpaceLocation(), 8, targetQuadEdges);
+ if (isInMaskMode()) {
+ m_context3D->blendFunc(GraphicsContext3D::ZERO, GraphicsContext3D::SRC_ALPHA);
+ m_context3D->enable(GraphicsContext3D::BLEND);
+ } else {
+ if (flags & ShouldBlend) {
+ m_context3D->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
+ m_context3D->enable(GraphicsContext3D::BLEND);
+ } else
+ m_context3D->disable(GraphicsContext3D::BLEND);
+ }
- drawTexturedQuadWithProgram(program.get(), texture, flags, DrawQuad(originalTargetRect, expandedQuadInTextureCoordinates), modelViewMatrix, opacity, 0 /* maskTexture */);
- return true;
+ if (flags & ShouldAntialias)
+ drawEdgeTriangles(shaderProgram);
+ else
+ drawUnitRect(shaderProgram, drawingMode);
+
+ m_context3D->disableVertexAttribArray(shaderProgram->vertexLocation());
+ m_context3D->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
+ m_context3D->enable(GraphicsContext3D::BLEND);
}
-void TextureMapperGL::drawTexturedQuadWithProgram(TextureMapperShaderProgram* program, uint32_t texture, Flags flags, const DrawQuad& quadToDraw, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture)
+void TextureMapperGL::drawTexturedQuadWithProgram(TextureMapperShaderProgram* program, uint32_t texture, Flags flags, const IntSize& size, const FloatRect& rect, const TransformationMatrix& modelViewMatrix, float opacity)
{
- m_context3D->enableVertexAttribArray(program->vertexLocation());
+ m_context3D->useProgram(program->programID());
m_context3D->activeTexture(GraphicsContext3D::TEXTURE0);
- m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, texture);
+ GC3Denum target = flags & ShouldUseARBTextureRect ? GC3Denum(Extensions3D::TEXTURE_RECTANGLE_ARB) : GC3Denum(GraphicsContext3D::TEXTURE_2D);
+ m_context3D->bindTexture(target, texture);
m_context3D->uniform1i(program->samplerLocation(), 0);
+ if (wrapMode() == RepeatWrap) {
+ m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::REPEAT);
+ m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::REPEAT);
+ }
+
+ TransformationMatrix patternTransform = this->patternTransform();
+ if (flags & ShouldFlipTexture)
+ patternTransform.flipY();
+ if (flags & ShouldUseARBTextureRect)
+ patternTransform.scaleNonUniform(size.width(), size.height());
+ if (flags & ShouldFlipTexture)
+ patternTransform.translate(0, -1);
- m_context3D->uniform1f(program->flipLocation(), !!(flags & ShouldFlipTexture));
+ program->setMatrix(program->textureSpaceMatrixLocation(), patternTransform);
m_context3D->uniform1f(program->opacityLocation(), opacity);
- if (maskTexture && maskTexture->isValid()) {
- const BitmapTextureGL* maskTextureGL = static_cast<const BitmapTextureGL*>(maskTexture);
- m_context3D->activeTexture(GraphicsContext3D::TEXTURE1);
- m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, maskTextureGL->id());
- m_context3D->uniform1i(program->maskLocation(), 1);
- m_context3D->activeTexture(GraphicsContext3D::TEXTURE0);
- }
+ if (opacity < 1)
+ flags |= ShouldBlend;
- bool needsBlending = (flags & SupportsBlending) || opacity < 0.99 || maskTexture;
- drawQuad(quadToDraw, modelViewMatrix, program, GraphicsContext3D::TRIANGLE_FAN, needsBlending);
+ draw(rect, modelViewMatrix, program, GraphicsContext3D::TRIANGLE_FAN, flags);
+ m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
+ m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
}
BitmapTextureGL::BitmapTextureGL(TextureMapperGL* textureMapper)
@@ -649,24 +786,26 @@ static void swizzleBGRAToRGBA(uint32_t* data, const IntRect& rect, int stride =
}
}
-static bool driverSupportsBGRASwizzling()
+// If GL_EXT_texture_format_BGRA8888 is supported in the OpenGLES
+// internal and external formats need to be BGRA
+static bool driverSupportsExternalTextureBGRA(GraphicsContext3D* context)
{
-#if defined(TEXMAP_OPENGL_ES_2)
- // FIXME: Implement reliable detection. See also https://bugs.webkit.org/show_bug.cgi?id=81103.
- return false;
-#else
+ if (context->isGLES2Compliant()) {
+ static bool supportsExternalTextureBGRA = context->getExtensions()->supports("GL_EXT_texture_format_BGRA8888");
+ return supportsExternalTextureBGRA;
+ }
+
return true;
-#endif
}
-static bool driverSupportsSubImage()
+static bool driverSupportsSubImage(GraphicsContext3D* context)
{
-#if defined(TEXMAP_OPENGL_ES_2)
- // FIXME: Implement reliable detection.
- return false;
-#else
+ if (context->isGLES2Compliant()) {
+ static bool supportsSubImage = context->getExtensions()->supports("GL_EXT_unpack_subimage");
+ return supportsSubImage;
+ }
+
return true;
-#endif
}
void BitmapTextureGL::didReset()
@@ -678,7 +817,6 @@ void BitmapTextureGL::didReset()
if (m_textureSize == contentSize())
return;
- Platform3DObject format = driverSupportsBGRASwizzling() ? GraphicsContext3D::BGRA : GraphicsContext3D::RGBA;
m_textureSize = contentSize();
m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id);
@@ -686,28 +824,36 @@ void BitmapTextureGL::didReset()
m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
- m_context3D->texImage2DDirect(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_textureSize.width(), m_textureSize.height(), 0, format, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, 0);
+
+ Platform3DObject internalFormat = GraphicsContext3D::RGBA;
+ Platform3DObject externalFormat = GraphicsContext3D::BGRA;
+ if (m_context3D->isGLES2Compliant()) {
+ if (driverSupportsExternalTextureBGRA(m_context3D.get()))
+ internalFormat = GraphicsContext3D::BGRA;
+ else
+ externalFormat = GraphicsContext3D::RGBA;
+ }
+
+ m_context3D->texImage2DDirect(GraphicsContext3D::TEXTURE_2D, 0, internalFormat, m_textureSize.width(), m_textureSize.height(), 0, externalFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, 0);
}
void BitmapTextureGL::updateContentsNoSwizzle(const void* srcData, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine, unsigned bytesPerPixel, Platform3DObject glFormat)
{
m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id);
-#if !defined(TEXMAP_OPENGL_ES_2)
- if (driverSupportsSubImage()) { // For ES drivers that don't support sub-images.
+ if (driverSupportsSubImage(m_context3D.get())) { // For ES drivers that don't support sub-images.
// Use the OpenGL sub-image extension, now that we know it's available.
m_context3D->pixelStorei(GL_UNPACK_ROW_LENGTH, bytesPerLine / bytesPerPixel);
m_context3D->pixelStorei(GL_UNPACK_SKIP_ROWS, sourceOffset.y());
m_context3D->pixelStorei(GL_UNPACK_SKIP_PIXELS, sourceOffset.x());
}
-#endif
+
m_context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, srcData);
-#if !defined(TEXMAP_OPENGL_ES_2)
- if (driverSupportsSubImage()) { // For ES drivers that don't support sub-images.
+
+ if (driverSupportsSubImage(m_context3D.get())) { // For ES drivers that don't support sub-images.
m_context3D->pixelStorei(GL_UNPACK_ROW_LENGTH, 0);
m_context3D->pixelStorei(GL_UNPACK_SKIP_ROWS, 0);
m_context3D->pixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
}
-#endif
}
void BitmapTextureGL::updateContents(const void* srcData, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine, UpdateContentsFlag updateContentsFlag)
@@ -721,11 +867,11 @@ void BitmapTextureGL::updateContents(const void* srcData, const IntRect& targetR
IntPoint adjustedSourceOffset = sourceOffset;
// Texture upload requires subimage buffer if driver doesn't support subimage and we don't have full image upload.
- bool requireSubImageBuffer = !driverSupportsSubImage()
+ bool requireSubImageBuffer = !driverSupportsSubImage(m_context3D.get())
&& !(bytesPerLine == static_cast<int>(targetRect.width() * bytesPerPixel) && adjustedSourceOffset == IntPoint::zero());
// prepare temporaryData if necessary
- if ((!driverSupportsBGRASwizzling() && updateContentsFlag == UpdateCannotModifyOriginalImageData) || requireSubImageBuffer) {
+ if ((!driverSupportsExternalTextureBGRA(m_context3D.get()) && updateContentsFlag == UpdateCannotModifyOriginalImageData) || requireSubImageBuffer) {
temporaryData.resize(targetRect.width() * targetRect.height() * bytesPerPixel);
data = temporaryData.data();
const char* bits = static_cast<const char*>(srcData);
@@ -742,10 +888,10 @@ void BitmapTextureGL::updateContents(const void* srcData, const IntRect& targetR
adjustedSourceOffset = IntPoint(0, 0);
}
- if (driverSupportsBGRASwizzling())
+ if (driverSupportsExternalTextureBGRA(m_context3D.get()))
glFormat = GraphicsContext3D::BGRA;
else
- swizzleBGRAToRGBA(reinterpret_cast<uint32_t*>(data), IntRect(adjustedSourceOffset, targetRect.size()), bytesPerLine / bytesPerPixel);
+ swizzleBGRAToRGBA(reinterpret_cast_ptr<uint32_t*>(data), IntRect(adjustedSourceOffset, targetRect.size()), bytesPerLine / bytesPerPixel);
updateContentsNoSwizzle(data, targetRect, adjustedSourceOffset, bytesPerLine, bytesPerPixel, glFormat);
}
@@ -766,7 +912,7 @@ void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, co
imageData = reinterpret_cast<const char*>(qImage.constBits());
bytesPerLine = qImage.bytesPerLine();
#elif USE(CAIRO)
- cairo_surface_t* surface = frameImage->surface();
+ cairo_surface_t* surface = frameImage.get();
imageData = reinterpret_cast<const char*>(cairo_image_surface_get_data(surface));
bytesPerLine = cairo_image_surface_get_stride(surface);
#endif
@@ -774,154 +920,6 @@ void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, co
updateContents(imageData, targetRect, offset, bytesPerLine, updateContentsFlag);
}
-#if ENABLE(CSS_FILTERS)
-
-static TextureMapperShaderManager::ShaderKey keyForFilterType(FilterOperation::OperationType type, unsigned pass)
-{
- switch (type) {
- case FilterOperation::GRAYSCALE:
- return TextureMapperShaderManager::GrayscaleFilter;
- case FilterOperation::SEPIA:
- return TextureMapperShaderManager::SepiaFilter;
- case FilterOperation::SATURATE:
- return TextureMapperShaderManager::SaturateFilter;
- case FilterOperation::HUE_ROTATE:
- return TextureMapperShaderManager::HueRotateFilter;
- case FilterOperation::INVERT:
- return TextureMapperShaderManager::InvertFilter;
- case FilterOperation::BRIGHTNESS:
- return TextureMapperShaderManager::BrightnessFilter;
- case FilterOperation::CONTRAST:
- return TextureMapperShaderManager::ContrastFilter;
- case FilterOperation::OPACITY:
- return TextureMapperShaderManager::OpacityFilter;
- case FilterOperation::BLUR:
- return TextureMapperShaderManager::BlurFilter;
- case FilterOperation::DROP_SHADOW:
- return pass ? TextureMapperShaderManager::ShadowFilterPass2 : TextureMapperShaderManager::ShadowFilterPass1;
- default:
- ASSERT_NOT_REACHED();
- return TextureMapperShaderManager::Invalid;
- }
-}
-
-static unsigned getPassesRequiredForFilter(FilterOperation::OperationType type)
-{
- switch (type) {
- case FilterOperation::GRAYSCALE:
- case FilterOperation::SEPIA:
- case FilterOperation::SATURATE:
- case FilterOperation::HUE_ROTATE:
- case FilterOperation::INVERT:
- case FilterOperation::BRIGHTNESS:
- case FilterOperation::CONTRAST:
- case FilterOperation::OPACITY:
-#if ENABLE(CSS_SHADERS)
- case FilterOperation::CUSTOM:
- case FilterOperation::VALIDATED_CUSTOM:
-#endif
- return 1;
- case FilterOperation::BLUR:
- case FilterOperation::DROP_SHADOW:
- // We use two-passes (vertical+horizontal) for blur and drop-shadow.
- return 2;
- default:
- return 0;
- }
-}
-
-// Create a normal distribution of 21 values between -2 and 2.
-static const unsigned GaussianKernelHalfWidth = 11;
-static const float GaussianKernelStep = 0.2;
-
-static inline float gauss(float x)
-{
- return exp(-(x * x) / 2.);
-}
-
-static float* gaussianKernel()
-{
- static bool prepared = false;
- static float kernel[GaussianKernelHalfWidth] = {0, };
-
- if (prepared)
- return kernel;
-
- kernel[0] = gauss(0);
- float sum = kernel[0];
- for (unsigned i = 1; i < GaussianKernelHalfWidth; ++i) {
- kernel[i] = gauss(i * GaussianKernelStep);
- sum += 2 * kernel[i];
- }
-
- // Normalize the kernel.
- float scale = 1 / sum;
- for (unsigned i = 0; i < GaussianKernelHalfWidth; ++i)
- kernel[i] *= scale;
-
- prepared = true;
- return kernel;
-}
-
-static void prepareFilterProgram(TextureMapperShaderProgram* program, const FilterOperation& operation, unsigned pass, const IntSize& size, GC3Duint contentTexture)
-{
- RefPtr<GraphicsContext3D> context = program->context();
- context->useProgram(program->programID());
-
- switch (operation.getOperationType()) {
- case FilterOperation::GRAYSCALE:
- case FilterOperation::SEPIA:
- case FilterOperation::SATURATE:
- case FilterOperation::HUE_ROTATE:
- context->uniform1f(program->amountLocation(), static_cast<const BasicColorMatrixFilterOperation&>(operation).amount());
- break;
- case FilterOperation::INVERT:
- case FilterOperation::BRIGHTNESS:
- case FilterOperation::CONTRAST:
- case FilterOperation::OPACITY:
- context->uniform1f(program->amountLocation(), static_cast<const BasicComponentTransferFilterOperation&>(operation).amount());
- break;
- case FilterOperation::BLUR: {
- const BlurFilterOperation& blur = static_cast<const BlurFilterOperation&>(operation);
- FloatSize radius;
-
- // Blur is done in two passes, first horizontally and then vertically. The same shader is used for both.
- if (pass)
- radius.setHeight(floatValueForLength(blur.stdDeviation(), size.height()) / size.height());
- else
- radius.setWidth(floatValueForLength(blur.stdDeviation(), size.width()) / size.width());
-
- context->uniform2f(program->blurRadiusLocation(), radius.width(), radius.height());
- context->uniform1fv(program->gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel());
- break;
- }
- case FilterOperation::DROP_SHADOW: {
- const DropShadowFilterOperation& shadow = static_cast<const DropShadowFilterOperation&>(operation);
- context->uniform1fv(program->gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel());
- switch (pass) {
- case 0:
- // First pass: vertical alpha blur.
- context->uniform2f(program->shadowOffsetLocation(), float(shadow.location().x()) / float(size.width()), float(shadow.location().y()) / float(size.height()));
- context->uniform1f(program->blurRadiusLocation(), shadow.stdDeviation() / float(size.width()));
- break;
- case 1:
- // Second pass: we need the shadow color and the content texture for compositing.
- context->uniform1f(program->blurRadiusLocation(), shadow.stdDeviation() / float(size.height()));
- context->activeTexture(GraphicsContext3D::TEXTURE1);
- context->bindTexture(GraphicsContext3D::TEXTURE_2D, contentTexture);
- context->uniform1i(program->contentTextureLocation(), 1);
- float r, g, b, a;
- shadow.color().getRGBA(r, g, b, a);
- context->uniform4f(program->shadowColorLocation(), r, g, b, a);
- break;
- }
- break;
- }
- default:
- break;
- }
-}
-
#if ENABLE(CSS_SHADERS)
void TextureMapperGL::removeCachedCustomFilterProgram(CustomFilterProgram* program)
{
@@ -938,15 +936,11 @@ bool TextureMapperGL::drawUsingCustomFilter(BitmapTexture& target, const BitmapT
const CustomFilterOperation* customFilter = static_cast<const CustomFilterOperation*>(&filter);
RefPtr<CustomFilterProgram> program = customFilter->program();
renderer = CustomFilterRenderer::create(m_context3D, program->programType(), customFilter->parameters(),
- customFilter->meshRows(), customFilter->meshColumns(), customFilter->meshBoxType(), customFilter->meshType());
- RefPtr<CustomFilterCompiledProgram> compiledProgram;
- CustomFilterProgramMap::iterator iter = m_customFilterPrograms.find(program->programInfo());
- if (iter == m_customFilterPrograms.end()) {
- compiledProgram = CustomFilterCompiledProgram::create(m_context3D, program->vertexShaderString(), program->fragmentShaderString(), program->programType());
- m_customFilterPrograms.set(program->programInfo(), compiledProgram);
- } else
- compiledProgram = iter->value;
- renderer->setCompiledProgram(compiledProgram.release());
+ customFilter->meshRows(), customFilter->meshColumns(), customFilter->meshType());
+ CustomFilterProgramMap::AddResult result = m_customFilterPrograms.add(program->programInfo(), 0);
+ if (result.isNewEntry)
+ result.iterator->value = CustomFilterCompiledProgram::create(m_context3D, program->vertexShaderString(), program->fragmentShaderString(), program->programType());
+ renderer->setCompiledProgram(result.iterator->value);
break;
}
case FilterOperation::VALIDATED_CUSTOM: {
@@ -954,15 +948,12 @@ bool TextureMapperGL::drawUsingCustomFilter(BitmapTexture& target, const BitmapT
const ValidatedCustomFilterOperation* customFilter = static_cast<const ValidatedCustomFilterOperation*>(&filter);
RefPtr<CustomFilterValidatedProgram> program = customFilter->validatedProgram();
renderer = CustomFilterRenderer::create(m_context3D, program->programInfo().programType(), customFilter->parameters(),
- customFilter->meshRows(), customFilter->meshColumns(), customFilter->meshBoxType(), customFilter->meshType());
+ customFilter->meshRows(), customFilter->meshColumns(), customFilter->meshType());
RefPtr<CustomFilterCompiledProgram> compiledProgram;
- CustomFilterProgramMap::iterator iter = m_customFilterPrograms.find(program->programInfo());
- if (iter == m_customFilterPrograms.end()) {
- compiledProgram = CustomFilterCompiledProgram::create(m_context3D, program->validatedVertexShader(), program->validatedFragmentShader(), program->programInfo().programType());
- m_customFilterPrograms.set(program->programInfo(), compiledProgram);
- } else
- compiledProgram = iter->value;
- renderer->setCompiledProgram(compiledProgram.release());
+ CustomFilterProgramMap::AddResult result = m_customFilterPrograms.add(program->programInfo(), 0);
+ if (result.isNewEntry)
+ result.iterator->value = CustomFilterCompiledProgram::create(m_context3D, program->validatedVertexShader(), program->validatedFragmentShader(), program->programInfo().programType());
+ renderer->setCompiledProgram(result.iterator->value);
break;
}
default:
@@ -988,65 +979,79 @@ bool TextureMapperGL::drawUsingCustomFilter(BitmapTexture& target, const BitmapT
}
#endif
-void TextureMapperGL::drawFiltered(const BitmapTexture& sampler, const BitmapTexture& contentTexture, const FilterOperation& filter, int pass)
+#if ENABLE(CSS_FILTERS)
+void TextureMapperGL::drawFiltered(const BitmapTexture& sampler, const BitmapTexture* contentTexture, const FilterOperation& filter, int pass)
{
// For standard filters, we always draw the whole texture without transformations.
- TextureMapperShaderManager::ShaderKey key = keyForFilterType(filter.getOperationType(), pass);
- RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(key);
+ TextureMapperShaderProgram::Options options = optionsForFilterType(filter.getOperationType(), pass);
+ RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().getShaderProgram(options);
ASSERT(program);
- prepareFilterProgram(program.get(), filter, pass, sampler.contentSize(), static_cast<const BitmapTextureGL&>(contentTexture).id());
+ prepareFilterProgram(program.get(), filter, pass, sampler.contentSize(), contentTexture ? static_cast<const BitmapTextureGL*>(contentTexture)->id() : 0);
+ FloatRect targetRect(IntPoint::zero(), sampler.contentSize());
+ drawTexturedQuadWithProgram(program.get(), static_cast<const BitmapTextureGL&>(sampler).id(), 0, IntSize(1, 1), targetRect, TransformationMatrix(), 1);
+}
- m_context3D->enableVertexAttribArray(program->vertexLocation());
- m_context3D->enableVertexAttribArray(program->texCoordLocation());
- m_context3D->activeTexture(GraphicsContext3D::TEXTURE0);
- m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, static_cast<const BitmapTextureGL&>(sampler).id());
- m_context3D->uniform1i(program->samplerLocation(), 0);
- const GC3Dfloat targetVertices[] = {-1, -1, 1, -1, 1, 1, -1, 1};
- const GC3Dfloat sourceVertices[] = {0, 0, 1, 0, 1, 1, 0, 1};
- m_context3D->vertexAttribPointer(program->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(targetVertices));
- m_context3D->vertexAttribPointer(program->texCoordLocation(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(sourceVertices));
- m_context3D->disable(GraphicsContext3D::BLEND);
- m_context3D->drawArrays(GraphicsContext3D::TRIANGLE_FAN, 0, 4);
- m_context3D->disableVertexAttribArray(program->vertexLocation());
- m_context3D->disableVertexAttribArray(program->texCoordLocation());
+static bool isCustomFilter(FilterOperation::OperationType type)
+{
+#if ENABLE(CSS_SHADERS)
+ return type == FilterOperation::CUSTOM || type == FilterOperation::VALIDATED_CUSTOM;
+#else
+ return false;
+#endif
}
-PassRefPtr<BitmapTexture> BitmapTextureGL::applyFilters(TextureMapper* textureMapper, const BitmapTexture& contentTexture, const FilterOperations& filters)
+PassRefPtr<BitmapTexture> BitmapTextureGL::applyFilters(TextureMapper* textureMapper, const FilterOperations& filters)
{
- TextureMapperGL* textureMapperGL = static_cast<TextureMapperGL*>(textureMapper);
- RefPtr<BitmapTexture> previousSurface = textureMapperGL->data().currentSurface;
+ if (filters.isEmpty())
+ return this;
+
+ TextureMapperGL* texmapGL = static_cast<TextureMapperGL*>(textureMapper);
+ RefPtr<BitmapTexture> previousSurface = texmapGL->data().currentSurface;
+ RefPtr<BitmapTexture> resultSurface = this;
+ RefPtr<BitmapTexture> intermediateSurface;
+ RefPtr<BitmapTexture> spareSurface;
- RefPtr<BitmapTexture> source = this;
- RefPtr<BitmapTexture> target = textureMapper->acquireTextureFromPool(m_textureSize);
+ m_filterInfo = FilterInfo();
- bool useContentTexture = true;
for (size_t i = 0; i < filters.size(); ++i) {
- const FilterOperation* filter = filters.at(i);
+ RefPtr<FilterOperation> filter = filters.operations()[i];
ASSERT(filter);
+ bool custom = isCustomFilter(filter->getOperationType());
+
int numPasses = getPassesRequiredForFilter(filter->getOperationType());
for (int j = 0; j < numPasses; ++j) {
- textureMapperGL->bindSurface(target.get());
- const BitmapTexture& sourceTexture = useContentTexture ? contentTexture : *source;
+ bool last = (i == filters.size() - 1) && (j == numPasses - 1);
+ if (custom || !last) {
+ if (!intermediateSurface)
+ intermediateSurface = texmapGL->acquireTextureFromPool(contentSize());
+ texmapGL->bindSurface(intermediateSurface.get());
+ }
+
#if ENABLE(CSS_SHADERS)
- if (filter->getOperationType() == FilterOperation::CUSTOM || filter->getOperationType() == FilterOperation::VALIDATED_CUSTOM) {
- if (textureMapperGL->drawUsingCustomFilter(*target, sourceTexture, *filter)) {
- // Only swap if the draw was successful.
- std::swap(source, target);
- useContentTexture = false;
- }
+ if (custom) {
+ if (texmapGL->drawUsingCustomFilter(*intermediateSurface.get(), *resultSurface.get(), *filter))
+ std::swap(resultSurface, intermediateSurface);
continue;
}
#endif
- textureMapperGL->drawFiltered(sourceTexture, contentTexture, *filter, j);
- std::swap(source, target);
- useContentTexture = false;
+ if (last) {
+ toBitmapTextureGL(resultSurface.get())->m_filterInfo = BitmapTextureGL::FilterInfo(filter, j, spareSurface);
+ break;
+ }
+
+ texmapGL->drawFiltered(*resultSurface.get(), spareSurface.get(), *filter, j);
+ if (!j && filter->getOperationType() == FilterOperation::DROP_SHADOW) {
+ spareSurface = resultSurface;
+ resultSurface.clear();
+ }
+ std::swap(resultSurface, intermediateSurface);
}
}
- textureMapperGL->bindSurface(previousSurface.get());
- return source;
+ texmapGL->bindSurface(previousSurface.get());
+ return resultSurface;
}
#endif
@@ -1096,8 +1101,8 @@ void BitmapTextureGL::clearIfNeeded()
if (!m_shouldClear)
return;
- m_clipStack.init(IntRect(IntPoint::zero(), m_textureSize));
- m_clipStack.apply(m_context3D.get());
+ m_clipStack.reset(IntRect(IntPoint::zero(), m_textureSize), TextureMapperGL::ClipStack::DefaultYAxis);
+ m_clipStack.applyIfNeeded(m_context3D.get());
m_context3D->clearColor(0, 0, 0, 0);
m_context3D->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
m_shouldClear = false;
@@ -1190,8 +1195,8 @@ bool TextureMapperGL::beginScissorClip(const TransformationMatrix& modelViewMatr
if (!quad.isRectilinear() || rect.isEmpty())
return false;
- clipStack().current().scissorBox.intersect(rect);
- clipStack().apply(m_context3D.get());
+ clipStack().intersect(rect);
+ clipStack().applyIfNeeded(m_context3D.get());
return true;
}
@@ -1203,35 +1208,19 @@ void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, con
data().initializeStencil();
- RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Default);
+ RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().getShaderProgram(TextureMapperShaderProgram::SolidColor);
m_context3D->useProgram(program->programID());
m_context3D->enableVertexAttribArray(program->vertexLocation());
const GC3Dfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1};
m_context3D->vertexAttribPointer(program->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(unitRect));
- TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix)
- .multiply(modelViewMatrix)
- .multiply(TransformationMatrix(targetRect.width(), 0, 0, 0,
- 0, targetRect.height(), 0, 0,
- 0, 0, 1, 0,
- targetRect.x(), targetRect.y(), 0, 1));
-
- const GC3Dfloat m4[] = {
- matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
- matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
- matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
- matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()
- };
+ TransformationMatrix matrix = TransformationMatrix(modelViewMatrix)
+ .multiply(TransformationMatrix::rectToRect(FloatRect(0, 0, 1, 1), targetRect));
- const GC3Dfloat m4all[] = {
- 2, 0, 0, 0,
- 0, 2, 0, 0,
- 0, 0, 1, 0,
- -1, -1, 0, 1
- };
+ static const TransformationMatrix fullProjectionMatrix = TransformationMatrix::rectToRect(FloatRect(0, 0, 1, 1), FloatRect(-1, -1, 2, 2));
- int& stencilIndex = clipStack().current().stencilIndex;
+ int stencilIndex = clipStack().getStencilIndex();
m_context3D->enable(GraphicsContext3D::STENCIL_TEST);
@@ -1242,13 +1231,15 @@ void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, con
m_context3D->stencilMask(0xff & ~(stencilIndex - 1));
// First clear the entire buffer at the current index.
- m_context3D->uniformMatrix4fv(program->matrixLocation(), 1, false, const_cast<GC3Dfloat*>(m4all));
+ program->setMatrix(program->projectionMatrixLocation(), fullProjectionMatrix);
+ program->setMatrix(program->modelViewMatrixLocation(), TransformationMatrix());
m_context3D->stencilOp(GraphicsContext3D::ZERO, GraphicsContext3D::ZERO, GraphicsContext3D::ZERO);
m_context3D->drawArrays(GraphicsContext3D::TRIANGLE_FAN, 0, 4);
// Now apply the current index to the new quad.
m_context3D->stencilOp(GraphicsContext3D::REPLACE, GraphicsContext3D::REPLACE, GraphicsContext3D::REPLACE);
- m_context3D->uniformMatrix4fv(program->matrixLocation(), 1, false, const_cast<GC3Dfloat*>(m4));
+ program->setMatrix(program->projectionMatrixLocation(), data().projectionMatrix);
+ program->setMatrix(program->modelViewMatrixLocation(), matrix);
m_context3D->drawArrays(GraphicsContext3D::TRIANGLE_FAN, 0, 4);
// Clear the state.
@@ -1256,14 +1247,19 @@ void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, con
m_context3D->stencilMask(0);
// Increase stencilIndex and apply stencil testing.
- stencilIndex *= 2;
- clipStack().apply(m_context3D.get());
+ clipStack().setStencilIndex(stencilIndex * 2);
+ clipStack().applyIfNeeded(m_context3D.get());
}
void TextureMapperGL::endClip()
{
clipStack().pop();
- clipStack().apply(m_context3D.get());
+ clipStack().applyIfNeeded(m_context3D.get());
+}
+
+IntRect TextureMapperGL::clipBounds()
+{
+ return clipStack().current().scissorBox;
}
PassRefPtr<BitmapTexture> TextureMapperGL::createTexture()
@@ -1278,3 +1274,4 @@ PassOwnPtr<TextureMapper> TextureMapper::platformCreateAccelerated()
}
};
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h
index cc556e4b1..18a5c4d6f 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h
@@ -20,9 +20,10 @@
#ifndef TextureMapperGL_h
#define TextureMapperGL_h
-#if USE(ACCELERATED_COMPOSITING)
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
#include "CustomFilterProgramInfo.h"
+#include "FilterOperation.h"
#include "FloatQuad.h"
#include "GraphicsContext3D.h"
#include "IntSize.h"
@@ -34,8 +35,8 @@ namespace WebCore {
class CustomFilterProgram;
class CustomFilterCompiledProgram;
class TextureMapperGLData;
-class GraphicsContext;
class TextureMapperShaderProgram;
+class FilterOperation;
// An OpenGL-ES2 implementation of TextureMapper.
class TextureMapperGL : public TextureMapper {
@@ -44,36 +45,33 @@ public:
virtual ~TextureMapperGL();
enum Flag {
- SupportsBlending = 0x01,
- ShouldFlipTexture = 0x02
+ ShouldBlend = 0x01,
+ ShouldFlipTexture = 0x02,
+ ShouldUseARBTextureRect = 0x04,
+ ShouldAntialias = 0x08
};
typedef int Flags;
// TextureMapper implementation
- virtual void drawBorder(const Color&, float borderWidth, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix = TransformationMatrix()) OVERRIDE;
- virtual void drawRepaintCounter(int value, int pointSize, const FloatPoint&, const TransformationMatrix& modelViewMatrix = TransformationMatrix()) OVERRIDE;
- virtual void drawTexture(const BitmapTexture&, const FloatRect&, const TransformationMatrix&, float opacity, const BitmapTexture* maskTexture, unsigned exposedEdges) OVERRIDE;
- virtual void drawTexture(uint32_t texture, Flags, const IntSize& textureSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture, unsigned exposedEdges = AllEdges);
+ virtual void drawBorder(const Color&, float borderWidth, const FloatRect&, const TransformationMatrix&) OVERRIDE;
+ virtual void drawNumber(int number, const Color&, const FloatPoint&, const TransformationMatrix&) OVERRIDE;
+ virtual void drawTexture(const BitmapTexture&, const FloatRect&, const TransformationMatrix&, float opacity, unsigned exposedEdges) OVERRIDE;
+ virtual void drawTexture(Platform3DObject texture, Flags, const IntSize& textureSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, unsigned exposedEdges = AllEdges);
virtual void drawSolidColor(const FloatRect&, const TransformationMatrix&, const Color&) OVERRIDE;
-#if !USE(TEXMAP_OPENGL_ES_2)
- virtual void drawTextureRectangleARB(uint32_t texture, Flags, const IntSize& textureSize, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture);
-#endif
-
virtual void bindSurface(BitmapTexture* surface) OVERRIDE;
virtual void beginClip(const TransformationMatrix&, const FloatRect&) OVERRIDE;
virtual void beginPainting(PaintFlags = 0) OVERRIDE;
virtual void endPainting() OVERRIDE;
virtual void endClip() OVERRIDE;
+ virtual IntRect clipBounds() OVERRIDE;
virtual IntSize maxTextureSize() const OVERRIDE { return IntSize(2000, 2000); }
virtual PassRefPtr<BitmapTexture> createTexture() OVERRIDE;
- virtual GraphicsContext* graphicsContext() OVERRIDE { return m_context; }
inline GraphicsContext3D* graphicsContext3D() const { return m_context3D.get(); }
- virtual void setGraphicsContext(GraphicsContext* context) OVERRIDE { m_context = context; }
#if ENABLE(CSS_FILTERS)
- void drawFiltered(const BitmapTexture& sourceTexture, const BitmapTexture& contentTexture, const FilterOperation&, int pass);
+ void drawFiltered(const BitmapTexture& sourceTexture, const BitmapTexture* contentTexture, const FilterOperation&, int pass);
#endif
#if ENABLE(CSS_SHADERS)
bool drawUsingCustomFilter(BitmapTexture& targetTexture, const BitmapTexture& sourceTexture, const FilterOperation&);
@@ -94,39 +92,53 @@ private:
class ClipStack {
public:
+ ClipStack()
+ : clipStateDirty(false)
+ { }
+
+ // Y-axis should be inverted only when painting into the window.
+ enum YAxisMode {
+ DefaultYAxis,
+ InvertedYAxis
+ };
+
void push();
void pop();
void apply(GraphicsContext3D*);
+ void applyIfNeeded(GraphicsContext3D*);
inline ClipState& current() { return clipState; }
- void init(const IntRect&);
+ void reset(const IntRect&, YAxisMode);
+ void intersect(const IntRect&);
+ void setStencilIndex(int);
+ inline int getStencilIndex() const
+ {
+ return clipState.stencilIndex;
+ }
+ inline bool isCurrentScissorBoxEmpty() const
+ {
+ return clipState.scissorBox.isEmpty();
+ }
private:
ClipState clipState;
Vector<ClipState> clipStack;
- };
-
- struct DrawQuad {
- DrawQuad(const FloatRect& originalTargetRect, const FloatQuad& targetRectMappedToUnitSquare = FloatRect(FloatPoint(), FloatSize(1, 1)))
- : originalTargetRect(originalTargetRect)
- , targetRectMappedToUnitSquare(targetRectMappedToUnitSquare)
- {
- }
-
- FloatRect originalTargetRect;
- FloatQuad targetRectMappedToUnitSquare;
+ bool clipStateDirty;
+ IntSize size;
+ YAxisMode yAxisMode;
};
TextureMapperGL();
- bool drawTextureWithAntialiasing(uint32_t texture, Flags, const FloatRect& originalTargetRect, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture, unsigned exposedEdges);
- void drawTexturedQuadWithProgram(TextureMapperShaderProgram*, uint32_t texture, Flags, const DrawQuad&, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture);
- void drawQuad(const DrawQuad&, const TransformationMatrix& modelViewMatrix, TextureMapperShaderProgram*, GC3Denum drawingMode, bool needsBlending);
+ void drawTexturedQuadWithProgram(TextureMapperShaderProgram*, uint32_t texture, Flags, const IntSize&, const FloatRect&, const TransformationMatrix& modelViewMatrix, float opacity);
+ void draw(const FloatRect&, const TransformationMatrix& modelViewMatrix, TextureMapperShaderProgram*, GC3Denum drawingMode, Flags);
+
+ void drawUnitRect(TextureMapperShaderProgram*, GC3Denum drawingMode);
+ void drawEdgeTriangles(TextureMapperShaderProgram*);
bool beginScissorClip(const TransformationMatrix&, const FloatRect&);
void bindDefaultSurface();
ClipStack& clipStack();
inline TextureMapperGLData& data() { return *m_data; }
- GraphicsContext* m_context;
RefPtr<GraphicsContext3D> m_context3D;
TextureMapperGLData* m_data;
ClipStack m_clipStack;
@@ -158,7 +170,19 @@ public:
virtual bool isBackedByOpenGL() const { return true; }
#if ENABLE(CSS_FILTERS)
- virtual PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const BitmapTexture& contentTexture, const FilterOperations&);
+ virtual PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const FilterOperations&) OVERRIDE;
+ struct FilterInfo {
+ RefPtr<FilterOperation> filter;
+ unsigned pass;
+ RefPtr<BitmapTexture> contentTexture;
+
+ FilterInfo(PassRefPtr<FilterOperation> f = 0, unsigned p = 0, PassRefPtr<BitmapTexture> t = 0)
+ : filter(f)
+ , pass(p)
+ , contentTexture(t)
+ { }
+ };
+ const FilterInfo* filterInfo() const { return &m_filterInfo; }
#endif
private:
@@ -180,6 +204,10 @@ private:
void clearIfNeeded();
void createFboIfNeeded();
+#if ENABLE(CSS_FILTERS)
+ FilterInfo m_filterInfo;
+#endif
+
friend class TextureMapperGL;
};
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp
index e01ed3d9f..03273ba0f 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp
@@ -20,11 +20,11 @@
#include "config.h"
#include "TextureMapperImageBuffer.h"
-#include "FilterEffectRenderer.h"
#include "GraphicsLayer.h"
#if PLATFORM(QT)
#include "NativeImageQt.h"
#endif
+#include "NotImplemented.h"
#if USE(TEXTURE_MAPPER)
@@ -57,7 +57,7 @@ void BitmapTextureImageBuffer::updateContents(const void* data, const IntRect& t
#endif
}
-void BitmapTextureImageBuffer::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const IntRect& targetRect, const IntPoint& sourceOffset, UpdateContentsFlag)
+void BitmapTextureImageBuffer::updateContents(TextureMapper*, GraphicsLayer* sourceLayer, const IntRect& targetRect, const IntPoint& sourceOffset, UpdateContentsFlag)
{
GraphicsContext* context = m_image->context();
@@ -66,6 +66,7 @@ void BitmapTextureImageBuffer::updateContents(TextureMapper* textureMapper, Grap
IntRect sourceRect(targetRect);
sourceRect.setLocation(sourceOffset);
context->save();
+ context->clip(targetRect);
context->translate(targetRect.x() - sourceOffset.x(), targetRect.y() - sourceOffset.y());
sourceLayer->paintGraphicsLayerContents(*context, sourceRect);
context->restore();
@@ -113,7 +114,7 @@ void TextureMapperImageBuffer::beginClip(const TransformationMatrix& matrix, con
#endif
}
-void TextureMapperImageBuffer::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* maskTexture, unsigned /* exposedEdges */)
+void TextureMapperImageBuffer::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, unsigned /* exposedEdges */)
{
GraphicsContext* context = currentContext();
if (!context)
@@ -121,22 +122,8 @@ void TextureMapperImageBuffer::drawTexture(const BitmapTexture& texture, const F
const BitmapTextureImageBuffer& textureImageBuffer = static_cast<const BitmapTextureImageBuffer&>(texture);
ImageBuffer* image = textureImageBuffer.m_image.get();
- OwnPtr<ImageBuffer> maskedImage;
-
- if (maskTexture && maskTexture->isValid()) {
- const BitmapTextureImageBuffer* mask = static_cast<const BitmapTextureImageBuffer*>(maskTexture);
- maskedImage = ImageBuffer::create(maskTexture->contentSize());
- GraphicsContext* maskContext = maskedImage->context();
- maskContext->drawImageBuffer(image, ColorSpaceDeviceRGB, IntPoint::zero(), CompositeCopy);
- if (opacity < 1) {
- maskContext->setAlpha(opacity);
- opacity = 1;
- }
- maskContext->drawImageBuffer(mask->m_image.get(), ColorSpaceDeviceRGB, IntPoint::zero(), CompositeDestinationIn);
- image = maskedImage.get();
- }
-
context->save();
+ context->setCompositeOperation(isInMaskMode() ? CompositeDestinationIn : CompositeSourceOver);
context->setAlpha(opacity);
#if ENABLE(3D_RENDERING)
context->concat3DTransform(matrix);
@@ -154,6 +141,7 @@ void TextureMapperImageBuffer::drawSolidColor(const FloatRect& rect, const Trans
return;
context->save();
+ context->setCompositeOperation(isInMaskMode() ? CompositeDestinationIn : CompositeSourceOver);
#if ENABLE(3D_RENDERING)
context->concat3DTransform(matrix);
#else
@@ -164,20 +152,19 @@ void TextureMapperImageBuffer::drawSolidColor(const FloatRect& rect, const Trans
context->restore();
}
+void TextureMapperImageBuffer::drawBorder(const Color&, float /* borderWidth */, const FloatRect&, const TransformationMatrix&)
+{
+ notImplemented();
+}
+
+void TextureMapperImageBuffer::drawNumber(int /* number */, const Color&, const FloatPoint&, const TransformationMatrix&)
+{
+ notImplemented();
+}
+
#if ENABLE(CSS_FILTERS)
-PassRefPtr<BitmapTexture> BitmapTextureImageBuffer::applyFilters(TextureMapper*, const BitmapTexture& contentTexture, const FilterOperations& filters)
+PassRefPtr<BitmapTexture> BitmapTextureImageBuffer::applyFilters(TextureMapper*, const FilterOperations&)
{
- RefPtr<FilterEffectRenderer> renderer = FilterEffectRenderer::create();
- renderer->setSourceImageRect(FloatRect(FloatPoint::zero(), contentTexture.size()));
-
- // The document parameter is only needed for CSS shaders.
- if (renderer->build(0 /*document */, filters)) {
- renderer->allocateBackingStoreIfNeeded();
- GraphicsContext* context = renderer->inputContext();
- context->drawImageBuffer(static_cast<const BitmapTextureImageBuffer&>(contentTexture).m_image.get(), ColorSpaceDeviceRGB, IntPoint::zero());
- renderer->apply();
- m_image->context()->drawImageBuffer(renderer->output(), ColorSpaceDeviceRGB, renderer->outputRect());
- }
return this;
}
#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h
index 9de6d4cbd..060713ce5 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h
@@ -38,7 +38,7 @@ public:
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&);
+ PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const FilterOperations&);
#endif
private:
@@ -53,19 +53,14 @@ public:
static PassOwnPtr<TextureMapper> create() { return adoptPtr(new TextureMapperImageBuffer); }
// TextureMapper implementation
- virtual void drawBorder(const Color&, float /* borderWidth */, const FloatRect& /* targetRect */, const TransformationMatrix& modelViewMatrix = TransformationMatrix()) OVERRIDE
- {
- UNUSED_PARAM(modelViewMatrix);
- };
- virtual void drawRepaintCounter(int /* value */, int /* pointSize */, const FloatPoint&, const TransformationMatrix& modelViewMatrix = TransformationMatrix()) OVERRIDE
- {
- UNUSED_PARAM(modelViewMatrix);
- };
- virtual void drawTexture(const BitmapTexture&, const FloatRect& targetRect, const TransformationMatrix&, float opacity, const BitmapTexture* maskTexture, unsigned exposedEdges) OVERRIDE;
+ virtual void drawBorder(const Color&, float borderWidth, const FloatRect&, const TransformationMatrix&) OVERRIDE;
+ virtual void drawNumber(int number, const Color&, const FloatPoint&, const TransformationMatrix&) OVERRIDE;
+ virtual void drawTexture(const BitmapTexture&, const FloatRect& targetRect, const TransformationMatrix&, float opacity, unsigned exposedEdges) OVERRIDE;
virtual void drawSolidColor(const FloatRect&, const TransformationMatrix&, const Color&) OVERRIDE;
virtual void beginClip(const TransformationMatrix&, const FloatRect&) OVERRIDE;
virtual void bindSurface(BitmapTexture* surface) OVERRIDE { m_currentSurface = surface;}
virtual void endClip() OVERRIDE { graphicsContext()->restore(); }
+ virtual IntRect clipBounds() OVERRIDE { return currentContext()->clipBounds(); }
virtual IntSize maxTextureSize() const;
virtual PassRefPtr<BitmapTexture> createTexture() OVERRIDE { return BitmapTextureImageBuffer::create(); }
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp
index 40243335b..80c253543 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp
@@ -20,16 +20,26 @@
#include "config.h"
#include "TextureMapperLayer.h"
-#if USE(ACCELERATED_COMPOSITING)
+#include "FloatQuad.h"
+#include "Region.h"
+#include <wtf/MathExtras.h>
-#include "GraphicsLayerTextureMapper.h"
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
namespace WebCore {
-TextureMapperLayer* toTextureMapperLayer(GraphicsLayer* layer)
-{
- return layer ? toGraphicsLayerTextureMapper(layer)->layer() : 0;
-}
+class TextureMapperPaintOptions {
+public:
+ RefPtr<BitmapTexture> surface;
+ float opacity;
+ TransformationMatrix transform;
+ IntSize offset;
+ TextureMapper* textureMapper;
+ TextureMapperPaintOptions()
+ : opacity(1)
+ , textureMapper(0)
+ { }
+};
const TextureMapperLayer* TextureMapperLayer::rootLayer() const
{
@@ -40,38 +50,23 @@ const TextureMapperLayer* TextureMapperLayer::rootLayer() const
return this;
}
-void TextureMapperLayer::setTransform(const TransformationMatrix& matrix)
-{
- m_transform.setLocalTransform(matrix);
-}
-
-void TextureMapperLayer::clearBackingStoresRecursive()
-{
- m_backingStore.clear();
- m_contentsLayer = 0;
- for (size_t i = 0; i < m_children.size(); ++i)
- m_children[i]->clearBackingStoresRecursive();
- if (m_state.maskLayer)
- m_state.maskLayer->clearBackingStoresRecursive();
-}
-
void TextureMapperLayer::computeTransformsRecursive()
{
- if (m_size.isEmpty() && m_state.masksToBounds)
+ if (m_state.size.isEmpty() && m_state.masksToBounds)
return;
// Compute transforms recursively on the way down to leafs.
TransformationMatrix parentTransform;
if (m_parent)
- parentTransform = m_parent->m_transform.combinedForChildren();
+ parentTransform = m_parent->m_currentTransform.combinedForChildren();
else if (m_effectTarget)
- parentTransform = m_effectTarget->m_transform.combined();
- m_transform.combineTransforms(parentTransform);
+ parentTransform = m_effectTarget->m_currentTransform.combined();
+ m_currentTransform.combineTransforms(parentTransform);
- m_state.visible = m_state.backfaceVisibility || !m_transform.combined().isBackFaceVisible();
+ m_state.visible = m_state.backfaceVisibility || !m_currentTransform.combined().isBackFaceVisible();
if (m_parent && m_parent->m_state.preserves3D)
- m_centerZ = m_transform.combined().mapPoint(FloatPoint3D(m_size.width() / 2, m_size.height() / 2, 0)).z();
+ m_centerZ = m_currentTransform.combined().mapPoint(FloatPoint3D(m_state.size.width() / 2, m_state.size.height() / 2, 0)).z();
if (m_state.maskLayer)
m_state.maskLayer->computeTransformsRecursive();
@@ -82,7 +77,7 @@ void TextureMapperLayer::computeTransformsRecursive()
// Reorder children if needed on the way back up.
if (m_state.preserves3D)
- sortByZOrder(m_children, 0, m_children.size());
+ sortByZOrder(m_children);
}
void TextureMapperLayer::paint()
@@ -95,6 +90,26 @@ void TextureMapperLayer::paint()
paintRecursive(options);
}
+static Color blendWithOpacity(const Color& color, float opacity)
+{
+ RGBA32 rgba = color.rgb();
+ // See Color::getRGBA() to know how to extract alpha from color.
+ float alpha = alphaChannel(rgba) / 255.;
+ float effectiveAlpha = alpha * opacity;
+ return Color(colorWithOverrideAlpha(rgba, effectiveAlpha));
+}
+
+void TextureMapperLayer::computePatternTransformIfNeeded()
+{
+ if (!m_patternTransformDirty)
+ return;
+
+ m_patternTransformDirty = false;
+ m_patternTransform =
+ TransformationMatrix::rectToRect(FloatRect(FloatPoint::zero(), m_state.contentsTileSize), m_state.contentsRect)
+ .multiply(TransformationMatrix().translate(m_state.contentsTilePhase.x() / m_state.contentsRect.width(), m_state.contentsTilePhase.y() / m_state.contentsRect.height()));
+}
+
void TextureMapperLayer::paintSelf(const TextureMapperPaintOptions& options)
{
if (!m_state.visible || !m_state.contentsVisible)
@@ -104,21 +119,42 @@ void TextureMapperLayer::paintSelf(const TextureMapperPaintOptions& options)
TransformationMatrix transform;
transform.translate(options.offset.width(), options.offset.height());
transform.multiply(options.transform);
- transform.multiply(m_transform.combined());
+ transform.multiply(m_currentTransform.combined());
- float opacity = options.opacity;
- RefPtr<BitmapTexture> mask = options.mask;
+ if (m_state.solidColor.isValid() && !m_state.contentsRect.isEmpty() && m_state.solidColor.alpha()) {
+ options.textureMapper->drawSolidColor(m_state.contentsRect, transform, blendWithOpacity(m_state.solidColor, options.opacity));
+ if (m_state.showDebugBorders)
+ options.textureMapper->drawBorder(m_state.debugBorderColor, m_state.debugBorderWidth, layerRect(), transform);
+ return;
+ }
+
+ options.textureMapper->setWrapMode(TextureMapper::StretchWrap);
+ options.textureMapper->setPatternTransform(TransformationMatrix());
if (m_backingStore) {
- ASSERT(m_state.drawsContent && m_state.contentsVisible && !m_size.isEmpty());
- ASSERT(!layerRect().isEmpty());
- m_backingStore->paintToTextureMapper(options.textureMapper, layerRect(), transform, opacity, mask.get());
+ FloatRect targetRect = layerRect();
+ ASSERT(!targetRect.isEmpty());
+ m_backingStore->paintToTextureMapper(options.textureMapper, targetRect, transform, options.opacity);
+ if (m_state.showDebugBorders)
+ m_backingStore->drawBorder(options.textureMapper, m_state.debugBorderColor, m_state.debugBorderWidth, targetRect, transform);
+ // Only draw repaint count for the main backing store.
+ if (m_state.showRepaintCounter)
+ m_backingStore->drawRepaintCounter(options.textureMapper, m_state.repaintCount, m_state.debugBorderColor, targetRect, transform);
}
- if (m_contentsLayer) {
- ASSERT(!layerRect().isEmpty());
- m_contentsLayer->paintToTextureMapper(options.textureMapper, m_state.contentsRect, transform, opacity, mask.get());
+ if (!m_contentsLayer)
+ return;
+
+ if (!m_state.contentsTileSize.isEmpty()) {
+ computePatternTransformIfNeeded();
+ options.textureMapper->setWrapMode(TextureMapper::RepeatWrap);
+ options.textureMapper->setPatternTransform(m_patternTransform);
}
+
+ ASSERT(!layerRect().isEmpty());
+ m_contentsLayer->paintToTextureMapper(options.textureMapper, m_state.contentsRect, transform, options.opacity);
+ if (m_state.showDebugBorders)
+ m_contentsLayer->drawBorder(options.textureMapper, m_state.debugBorderColor, m_state.debugBorderWidth, m_state.contentsRect, transform);
}
int TextureMapperLayer::compareGraphicsLayersZValue(const void* a, const void* b)
@@ -128,7 +164,7 @@ int TextureMapperLayer::compareGraphicsLayersZValue(const void* a, const void* b
return int(((*layerA)->m_centerZ - (*layerB)->m_centerZ) * 1000);
}
-void TextureMapperLayer::sortByZOrder(Vector<TextureMapperLayer* >& array, int /* first */, int /* last */)
+void TextureMapperLayer::sortByZOrder(Vector<TextureMapperLayer* >& array)
{
qsort(array.data(), array.size(), sizeof(TextureMapperLayer*), compareGraphicsLayersZValue);
}
@@ -141,8 +177,13 @@ void TextureMapperLayer::paintSelfAndChildren(const TextureMapperPaintOptions& o
return;
bool shouldClip = m_state.masksToBounds && !m_state.preserves3D;
- if (shouldClip)
- options.textureMapper->beginClip(TransformationMatrix(options.transform).multiply(m_transform.combined()), layerRect());
+ if (shouldClip) {
+ TransformationMatrix clipTransform;
+ clipTransform.translate(options.offset.width(), options.offset.height());
+ clipTransform.multiply(options.transform);
+ clipTransform.multiply(m_currentTransform.combined());
+ options.textureMapper->beginClip(clipTransform, layerRect());
+ }
for (size_t i = 0; i < m_children.size(); ++i)
m_children[i]->paintRecursive(options);
@@ -151,97 +192,26 @@ void TextureMapperLayer::paintSelfAndChildren(const TextureMapperPaintOptions& o
options.textureMapper->endClip();
}
-IntRect TextureMapperLayer::intermediateSurfaceRect()
-{
- // FIXME: Add an inverse transform to LayerTransform.
- return intermediateSurfaceRect(m_transform.combined().inverse());
-}
-
-IntRect TextureMapperLayer::intermediateSurfaceRect(const TransformationMatrix& matrix)
-{
- IntRect rect;
- TransformationMatrix localTransform = TransformationMatrix(matrix).multiply(m_transform.combined());
- rect = enclosingIntRect(localTransform.mapRect(layerRect()));
- if (!m_state.masksToBounds && !m_state.maskLayer) {
- for (size_t i = 0; i < m_children.size(); ++i)
- rect.unite(m_children[i]->intermediateSurfaceRect(matrix));
- }
-
-#if ENABLE(CSS_FILTERS)
- if (m_filters.hasOutsets()) {
- int leftOutset;
- int topOutset;
- int bottomOutset;
- int rightOutset;
- m_filters.getOutsets(topOutset, rightOutset, bottomOutset, leftOutset);
- IntRect unfilteredTargetRect(rect);
- rect.move(std::max(0, -leftOutset), std::max(0, -topOutset));
- rect.expand(leftOutset + rightOutset, topOutset + bottomOutset);
- rect.unite(unfilteredTargetRect);
- }
-#endif
-
- if (m_state.replicaLayer)
- rect.unite(m_state.replicaLayer->intermediateSurfaceRect(matrix));
-
- return rect;
-}
-
-TextureMapperLayer::ContentsLayerCount TextureMapperLayer::countPotentialLayersWithContents() const
-{
- int selfLayersWithContents = (m_state.drawsContent ? 1 : 0) + (m_contentsLayer ? 1 : 0);
- int potentialLayersWithContents = selfLayersWithContents + m_children.size();
-
- if (!potentialLayersWithContents)
- return NoLayersWithContent;
-
- if (potentialLayersWithContents > 1)
- return MultipleLayersWithContents;
-
- if (m_children.isEmpty())
- return SingleLayerWithContents;
-
- return m_children.first()->countPotentialLayersWithContents();
-}
-
-bool TextureMapperLayer::shouldPaintToIntermediateSurface() const
+bool TextureMapperLayer::shouldBlend() const
{
-#if ENABLE(CSS_FILTERS)
- if (m_filters.size())
- return true;
-#endif
- bool hasOpacity = m_opacity < 0.99;
- bool canHaveMultipleLayersWithContent = countPotentialLayersWithContents() == MultipleLayersWithContents;
- bool hasReplica = !!m_state.replicaLayer;
- bool hasMask = !!m_state.maskLayer;
-
- // We don't use two-pass blending for preserves-3d, that's in sync with Safari.
if (m_state.preserves3D)
return false;
- // We should use an intermediate surface when blending several items with an ancestor opacity.
- // Tested by compositing/reflections/reflection-opacity.html
- if (hasOpacity && (canHaveMultipleLayersWithContent || hasReplica))
- return true;
-
- // We should use an intermediate surface with a masked ancestor.
- // In the case of replicas the mask is applied before replicating.
- // Tested by compositing/masks/masked-ancestor.html
- if (hasMask && canHaveMultipleLayersWithContent && !hasReplica)
- return true;
-
- return false;
+ return m_currentOpacity < 1
+ || hasFilters()
+ || m_state.maskLayer
+ || (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer);
}
bool TextureMapperLayer::isVisible() const
{
- if (m_size.isEmpty() && (m_state.masksToBounds || m_state.maskLayer || m_children.isEmpty()))
+ if (m_state.size.isEmpty() && (m_state.masksToBounds || m_state.maskLayer || m_children.isEmpty()))
return false;
if (!m_state.visible && m_children.isEmpty())
return false;
if (!m_state.contentsVisible && m_children.isEmpty())
return false;
- if (m_opacity < 0.01)
+ if (m_currentOpacity < 0.01)
return false;
return true;
}
@@ -250,92 +220,241 @@ void TextureMapperLayer::paintSelfAndChildrenWithReplica(const TextureMapperPain
{
if (m_state.replicaLayer) {
TextureMapperPaintOptions replicaOptions(options);
- // We choose either the content's mask or the replica's mask.
- // FIXME: blend the two if both exist.
- if (m_state.replicaLayer->m_state.maskLayer)
- replicaOptions.mask = m_state.replicaLayer->m_state.maskLayer->texture();
-
replicaOptions.transform
- .multiply(m_state.replicaLayer->m_transform.combined())
- .multiply(m_transform.combined().inverse());
+ .multiply(m_state.replicaLayer->m_currentTransform.combined())
+ .multiply(m_currentTransform.combined().inverse());
paintSelfAndChildren(replicaOptions);
}
paintSelfAndChildren(options);
}
-#if ENABLE(CSS_FILTERS)
-static bool shouldKeepContentTexture(const FilterOperations& filters)
+void TextureMapperLayer::setAnimatedTransform(const TransformationMatrix& matrix)
{
- for (size_t i = 0; i < filters.size(); ++i) {
- switch (filters.operations().at(i)->getOperationType()) {
- // The drop-shadow filter requires the content texture, because it needs to composite it
- // on top of the blurred shadow color.
- case FilterOperation::DROP_SHADOW:
- return true;
- default:
- break;
- }
- }
+ m_currentTransform.setLocalTransform(matrix);
+}
- return false;
+void TextureMapperLayer::setAnimatedOpacity(float opacity)
+{
+ m_currentOpacity = opacity;
}
-static PassRefPtr<BitmapTexture> applyFilters(const FilterOperations& filters, TextureMapper* textureMapper, BitmapTexture* source, IntRect& targetRect)
+TransformationMatrix TextureMapperLayer::replicaTransform()
{
- if (!filters.size())
- return source;
+ return TransformationMatrix(m_state.replicaLayer->m_currentTransform.combined()).multiply(m_currentTransform.combined().inverse());
+}
- RefPtr<BitmapTexture> filterSurface = shouldKeepContentTexture(filters) ? textureMapper->acquireTextureFromPool(source->size()) : source;
- return filterSurface->applyFilters(textureMapper, *source, filters);
+#if ENABLE(CSS_FILTERS)
+void TextureMapperLayer::setAnimatedFilters(const FilterOperations& filters)
+{
+ m_currentFilters = filters;
}
#endif
-void TextureMapperLayer::paintRecursive(const TextureMapperPaintOptions& options)
+static void resolveOverlaps(Region newRegion, Region& overlapRegion, Region& nonOverlapRegion)
{
- if (!isVisible())
+ Region newOverlapRegion(newRegion);
+ newOverlapRegion.intersect(nonOverlapRegion);
+ nonOverlapRegion.subtract(newOverlapRegion);
+ overlapRegion.unite(newOverlapRegion);
+ newRegion.subtract(overlapRegion);
+ nonOverlapRegion.unite(newRegion);
+}
+
+void TextureMapperLayer::computeOverlapRegions(Region& overlapRegion, Region& nonOverlapRegion, ResolveSelfOverlapMode mode)
+{
+ if (!m_state.visible || !m_state.contentsVisible)
return;
- float opacity = options.opacity * m_opacity;
- RefPtr<BitmapTexture> maskTexture = m_state.maskLayer ? m_state.maskLayer->texture() : 0;
+ FloatRect boundingRect;
+ if (m_backingStore || m_state.masksToBounds || m_state.maskLayer || hasFilters())
+ boundingRect = layerRect();
+ else if (m_contentsLayer || m_state.solidColor.alpha())
+ boundingRect = m_state.contentsRect;
- TextureMapperPaintOptions paintOptions(options);
- paintOptions.mask = maskTexture.get();
+#if ENABLE(CSS_FILTERS)
+ if (m_currentFilters.hasOutsets()) {
+ FilterOutsets outsets = m_currentFilters.outsets();
+ IntRect unfilteredTargetRect(boundingRect);
+ boundingRect.move(std::max(0, -outsets.left()), std::max(0, -outsets.top()));
+ boundingRect.expand(outsets.left() + outsets.right(), outsets.top() + outsets.bottom());
+ boundingRect.unite(unfilteredTargetRect);
+ }
+#endif
- if (!shouldPaintToIntermediateSurface()) {
- paintOptions.opacity = opacity;
- paintSelfAndChildrenWithReplica(paintOptions);
+ TransformationMatrix replicaMatrix;
+ if (m_state.replicaLayer) {
+ replicaMatrix = replicaTransform();
+ boundingRect.unite(replicaMatrix.mapRect(boundingRect));
+ }
+
+ boundingRect = m_currentTransform.combined().mapRect(boundingRect);
+
+ // Count all masks and filters as overlap layers.
+ if (hasFilters() || m_state.maskLayer || (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer)) {
+ Region newOverlapRegion(enclosingIntRect(boundingRect));
+ nonOverlapRegion.subtract(newOverlapRegion);
+ overlapRegion.unite(newOverlapRegion);
return;
}
- // Prepare a surface to paint into.
- // We paint into the surface ignoring the opacity/transform of the current layer.
- IntRect surfaceRect = intermediateSurfaceRect();
- RefPtr<BitmapTexture> surface = options.textureMapper->acquireTextureFromPool(surfaceRect.size());
- paintOptions.surface = surface;
- options.textureMapper->bindSurface(surface.get());
- paintOptions.opacity = 1;
+ Region newOverlapRegion;
+ Region newNonOverlapRegion(enclosingIntRect(boundingRect));
- paintOptions.transform = m_transform.combined().inverse();
- paintOptions.offset = -IntSize(surfaceRect.x(), surfaceRect.y());
+ if (!m_state.masksToBounds) {
+ for (size_t i = 0; i < m_children.size(); ++i) {
+ TextureMapperLayer* child = m_children[i];
+ child->computeOverlapRegions(newOverlapRegion, newNonOverlapRegion, ResolveSelfOverlapIfNeeded);
+ }
+ }
- paintSelfAndChildrenWithReplica(paintOptions);
+ if (m_state.replicaLayer) {
+ newOverlapRegion.unite(replicaMatrix.mapRect(newOverlapRegion.bounds()));
+ Region replicaRegion(replicaMatrix.mapRect(newNonOverlapRegion.bounds()));
+ resolveOverlaps(replicaRegion, newOverlapRegion, newNonOverlapRegion);
+ }
- // If we painted the replica, the mask is already applied so we don't need to paint it again.
- if (m_state.replicaLayer)
- maskTexture = 0;
+ if ((mode != ResolveSelfOverlapAlways) && shouldBlend()) {
+ newNonOverlapRegion.unite(newOverlapRegion);
+ newOverlapRegion = Region();
+ }
+
+ overlapRegion.unite(newOverlapRegion);
+ resolveOverlaps(newNonOverlapRegion, overlapRegion, nonOverlapRegion);
+}
+
+void TextureMapperLayer::paintUsingOverlapRegions(const TextureMapperPaintOptions& options)
+{
+ Region overlapRegion;
+ Region nonOverlapRegion;
+ computeOverlapRegions(overlapRegion, nonOverlapRegion, ResolveSelfOverlapAlways);
+ if (overlapRegion.isEmpty()) {
+ paintSelfAndChildrenWithReplica(options);
+ return;
+ }
+
+ // Having both overlap and non-overlap regions carries some overhead. Avoid it if the overlap area
+ // is big anyway.
+ if (overlapRegion.bounds().size().area() > nonOverlapRegion.bounds().size().area()) {
+ overlapRegion.unite(nonOverlapRegion);
+ nonOverlapRegion = Region();
+ }
+
+ nonOverlapRegion.translate(options.offset);
+ Vector<IntRect> rects = nonOverlapRegion.rects();
+
+ for (size_t i = 0; i < rects.size(); ++i) {
+ IntRect rect = rects[i];
+ if (!rect.intersects(options.textureMapper->clipBounds()))
+ continue;
+
+ options.textureMapper->beginClip(TransformationMatrix(), rects[i]);
+ paintSelfAndChildrenWithReplica(options);
+ options.textureMapper->endClip();
+ }
+
+ rects = overlapRegion.rects();
+ static const size_t OverlapRegionConsolidationThreshold = 4;
+ if (nonOverlapRegion.isEmpty() && rects.size() > OverlapRegionConsolidationThreshold) {
+ rects.clear();
+ rects.append(overlapRegion.bounds());
+ }
+
+ IntSize maxTextureSize = options.textureMapper->maxTextureSize();
+ IntRect adjustedClipBounds(options.textureMapper->clipBounds());
+ adjustedClipBounds.move(-options.offset);
+ for (size_t i = 0; i < rects.size(); ++i) {
+ IntRect rect = rects[i];
+ for (int x = rect.x(); x < rect.maxX(); x += maxTextureSize.width()) {
+ for (int y = rect.y(); y < rect.maxY(); y += maxTextureSize.height()) {
+ IntRect tileRect(IntPoint(x, y), maxTextureSize);
+ tileRect.intersect(rect);
+ if (!tileRect.intersects(adjustedClipBounds))
+ continue;
+
+ paintWithIntermediateSurface(options, tileRect);
+ }
+ }
+ }
+}
+void TextureMapperLayer::applyMask(const TextureMapperPaintOptions& options)
+{
+ options.textureMapper->setMaskMode(true);
+ paintSelf(options);
+ options.textureMapper->setMaskMode(false);
+}
+
+PassRefPtr<BitmapTexture> TextureMapperLayer::paintIntoSurface(const TextureMapperPaintOptions& options, const IntSize& size)
+{
+ RefPtr<BitmapTexture> surface = options.textureMapper->acquireTextureFromPool(size);
+ TextureMapperPaintOptions paintOptions(options);
+ paintOptions.surface = surface;
+ options.textureMapper->bindSurface(surface.get());
+ paintSelfAndChildren(paintOptions);
+ if (m_state.maskLayer)
+ m_state.maskLayer->applyMask(options);
#if ENABLE(CSS_FILTERS)
- surface = applyFilters(m_filters, options.textureMapper, surface.get(), surfaceRect);
+ surface = surface->applyFilters(options.textureMapper, m_currentFilters);
#endif
+ options.textureMapper->bindSurface(surface.get());
+ return surface;
+}
+static void commitSurface(const TextureMapperPaintOptions& options, PassRefPtr<BitmapTexture> surface, const IntRect& rect, float opacity)
+{
options.textureMapper->bindSurface(options.surface.get());
TransformationMatrix targetTransform;
targetTransform.translate(options.offset.width(), options.offset.height());
targetTransform.multiply(options.transform);
- targetTransform.multiply(m_transform.combined());
+ options.textureMapper->drawTexture(*surface.get(), rect, targetTransform, opacity);
+}
+
+void TextureMapperLayer::paintWithIntermediateSurface(const TextureMapperPaintOptions& options, const IntRect& rect)
+{
+ RefPtr<BitmapTexture> replicaSurface;
+ RefPtr<BitmapTexture> mainSurface;
+ TextureMapperPaintOptions paintOptions(options);
+ paintOptions.offset = -IntSize(rect.x(), rect.y());
+ paintOptions.opacity = 1;
+ paintOptions.transform = TransformationMatrix();
+ if (m_state.replicaLayer) {
+ paintOptions.transform = replicaTransform();
+ replicaSurface = paintIntoSurface(paintOptions, rect.size());
+ paintOptions.transform = TransformationMatrix();
+ if (m_state.replicaLayer->m_state.maskLayer)
+ m_state.replicaLayer->m_state.maskLayer->applyMask(paintOptions);
+ }
+
+ if (replicaSurface && options.opacity == 1) {
+ commitSurface(options, replicaSurface, rect, 1);
+ replicaSurface.clear();
+ }
+
+ mainSurface = paintIntoSurface(paintOptions, rect.size());
+ if (replicaSurface) {
+ options.textureMapper->bindSurface(replicaSurface.get());
+ options.textureMapper->drawTexture(*mainSurface.get(), FloatRect(FloatPoint::zero(), rect.size()));
+ mainSurface = replicaSurface;
+ }
+
+ commitSurface(options, mainSurface, rect, options.opacity);
+}
- options.textureMapper->drawTexture(*surface.get(), surfaceRect, targetTransform, opacity, maskTexture.get());
+void TextureMapperLayer::paintRecursive(const TextureMapperPaintOptions& options)
+{
+ if (!isVisible())
+ return;
+
+ TextureMapperPaintOptions paintOptions(options);
+ paintOptions.opacity *= m_currentOpacity;
+
+ if (!shouldBlend()) {
+ paintSelfAndChildrenWithReplica(paintOptions);
+ return;
+ }
+
+ paintUsingOverlapRegions(paintOptions);
}
TextureMapperLayer::~TextureMapperLayer()
@@ -352,98 +471,195 @@ TextureMapper* TextureMapperLayer::textureMapper() const
return rootLayer()->m_textureMapper;
}
-void TextureMapperLayer::flushCompositingState(GraphicsLayerTextureMapper* graphicsLayer, int options)
+void TextureMapperLayer::setChildren(const Vector<TextureMapperLayer*>& newChildren)
{
- flushCompositingState(graphicsLayer, textureMapper(), options);
+ removeAllChildren();
+ for (size_t i = 0; i < newChildren.size(); ++i)
+ addChild(newChildren[i]);
}
-void TextureMapperLayer::flushCompositingStateSelf(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper*)
+void TextureMapperLayer::addChild(TextureMapperLayer* childLayer)
{
- int changeMask = graphicsLayer->changeMask();
+ ASSERT(childLayer != this);
- if (changeMask == NoChanges && graphicsLayer->m_animations.isEmpty())
- return;
+ if (childLayer->m_parent)
+ childLayer->removeFromParent();
- graphicsLayer->updateDebugIndicators();
+ childLayer->m_parent = this;
+ m_children.append(childLayer);
+}
- if (changeMask & ParentChange) {
- TextureMapperLayer* newParent = toTextureMapperLayer(graphicsLayer->parent());
- if (newParent != m_parent) {
- // Remove layer from current from child list first.
- if (m_parent) {
- size_t index = m_parent->m_children.find(this);
- m_parent->m_children.remove(index);
- m_parent = 0;
- }
- // Set new layer parent and add layer to the parents child list.
- if (newParent) {
- m_parent = newParent;
- m_parent->m_children.append(this);
+void TextureMapperLayer::removeFromParent()
+{
+ if (m_parent) {
+ unsigned i;
+ for (i = 0; i < m_parent->m_children.size(); i++) {
+ if (this == m_parent->m_children[i]) {
+ m_parent->m_children.remove(i);
+ break;
}
}
+
+ m_parent = 0;
}
+}
- if (changeMask & ChildrenChange) {
- // Clear children parent pointer to avoid unsync and crash on layer delete.
- for (size_t i = 0; i < m_children.size(); i++)
- m_children[i]->m_parent = 0;
-
- m_children.clear();
- for (size_t i = 0; i < graphicsLayer->children().size(); ++i) {
- TextureMapperLayer* child = toTextureMapperLayer(graphicsLayer->children()[i]);
- if (!child)
- continue;
- m_children.append(child);
- child->m_parent = this;
- }
+void TextureMapperLayer::removeAllChildren()
+{
+ while (m_children.size()) {
+ TextureMapperLayer* curLayer = m_children[0];
+ ASSERT(curLayer->m_parent);
+ curLayer->removeFromParent();
}
+}
- m_size = graphicsLayer->size();
+void TextureMapperLayer::setMaskLayer(TextureMapperLayer* maskLayer)
+{
+ if (maskLayer)
+ maskLayer->m_effectTarget = this;
+ m_state.maskLayer = maskLayer;
+}
- if ((changeMask & DrawsContentChange) && graphicsLayer->drawsContent())
- graphicsLayer->setNeedsDisplay();
+void TextureMapperLayer::setReplicaLayer(TextureMapperLayer* replicaLayer)
+{
+ if (replicaLayer)
+ replicaLayer->m_effectTarget = this;
+ m_state.replicaLayer = replicaLayer;
+}
- if (changeMask & MaskLayerChange) {
- if (TextureMapperLayer* layer = toTextureMapperLayer(graphicsLayer->maskLayer()))
- layer->m_effectTarget = this;
- }
+void TextureMapperLayer::setPosition(const FloatPoint& position)
+{
+ m_state.pos = position;
+ m_currentTransform.setPosition(adjustedPosition());
+}
- if (changeMask & ReplicaLayerChange) {
- if (TextureMapperLayer* layer = toTextureMapperLayer(graphicsLayer->replicaLayer()))
- layer->m_effectTarget = this;
- }
+void TextureMapperLayer::setSize(const FloatSize& size)
+{
+ m_state.size = size;
+ m_currentTransform.setSize(size);
+}
+
+void TextureMapperLayer::setAnchorPoint(const FloatPoint3D& anchorPoint)
+{
+ m_state.anchorPoint = anchorPoint;
+ m_currentTransform.setAnchorPoint(anchorPoint);
+}
+
+void TextureMapperLayer::setPreserves3D(bool preserves3D)
+{
+ m_state.preserves3D = preserves3D;
+ m_currentTransform.setFlattening(!preserves3D);
+}
+
+void TextureMapperLayer::setTransform(const TransformationMatrix& transform)
+{
+ m_state.transform = transform;
+ m_currentTransform.setLocalTransform(transform);
+}
+
+void TextureMapperLayer::setChildrenTransform(const TransformationMatrix& childrenTransform)
+{
+ m_state.childrenTransform = childrenTransform;
+ m_currentTransform.setChildrenTransform(childrenTransform);
+}
+
+void TextureMapperLayer::setContentsRect(const IntRect& contentsRect)
+{
+ if (contentsRect == m_state.contentsRect)
+ return;
+ m_state.contentsRect = contentsRect;
+ m_patternTransformDirty = true;
+}
+
+void TextureMapperLayer::setContentsTileSize(const IntSize& size)
+{
+ if (size == m_state.contentsTileSize)
+ return;
+ m_state.contentsTileSize = size;
+ m_patternTransformDirty = true;
+}
+
+void TextureMapperLayer::setContentsTilePhase(const IntPoint& phase)
+{
+ if (phase == m_state.contentsTilePhase)
+ return;
+ m_state.contentsTilePhase = phase;
+ m_patternTransformDirty = true;
+}
+
+void TextureMapperLayer::setMasksToBounds(bool masksToBounds)
+{
+ m_state.masksToBounds = masksToBounds;
+}
+
+void TextureMapperLayer::setDrawsContent(bool drawsContent)
+{
+ m_state.drawsContent = drawsContent;
+}
+
+void TextureMapperLayer::setContentsVisible(bool contentsVisible)
+{
+ m_state.contentsVisible = contentsVisible;
+}
+
+void TextureMapperLayer::setContentsOpaque(bool contentsOpaque)
+{
+ m_state.contentsOpaque = contentsOpaque;
+}
+
+void TextureMapperLayer::setBackfaceVisibility(bool backfaceVisibility)
+{
+ m_state.backfaceVisibility = backfaceVisibility;
+}
+
+void TextureMapperLayer::setOpacity(float opacity)
+{
+ m_state.opacity = opacity;
+}
+
+void TextureMapperLayer::setSolidColor(const Color& color)
+{
+ m_state.solidColor = color;
+}
- if (changeMask & AnimationChange)
- m_animations = graphicsLayer->m_animations;
-
- m_state.maskLayer = toTextureMapperLayer(graphicsLayer->maskLayer());
- m_state.replicaLayer = toTextureMapperLayer(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.preserves3D = graphicsLayer->preserves3D();
- m_state.masksToBounds = graphicsLayer->masksToBounds();
- m_state.drawsContent = graphicsLayer->drawsContent();
- m_state.contentsVisible = graphicsLayer->contentsAreVisible();
- m_state.contentsOpaque = graphicsLayer->contentsOpaque();
- m_state.backfaceVisibility = graphicsLayer->backfaceVisibility();
- m_state.childrenTransform = graphicsLayer->childrenTransform();
- m_state.opacity = graphicsLayer->opacity();
#if ENABLE(CSS_FILTERS)
- if (changeMask & FilterChange)
- m_state.filters = graphicsLayer->filters();
+void TextureMapperLayer::setFilters(const FilterOperations& filters)
+{
+ m_state.filters = filters;
+}
#endif
- m_fixedToViewport = graphicsLayer->fixedToViewport();
- m_contentsLayer = graphicsLayer->platformLayer();
+void TextureMapperLayer::setDebugVisuals(bool showDebugBorders, const Color& debugBorderColor, float debugBorderWidth, bool showRepaintCounter)
+{
+ m_state.showDebugBorders = showDebugBorders;
+ m_state.debugBorderColor = debugBorderColor;
+ m_state.debugBorderWidth = debugBorderWidth;
+ m_state.showRepaintCounter = showRepaintCounter;
+}
+
+void TextureMapperLayer::setRepaintCount(int repaintCount)
+{
+ m_state.repaintCount = repaintCount;
+}
- m_transform.setPosition(adjustedPosition());
- m_transform.setAnchorPoint(m_state.anchorPoint);
- m_transform.setSize(m_state.size);
- m_transform.setFlattening(!m_state.preserves3D);
- m_transform.setChildrenTransform(m_state.childrenTransform);
+void TextureMapperLayer::setContentsLayer(TextureMapperPlatformLayer* platformLayer)
+{
+ m_contentsLayer = platformLayer;
+}
+
+void TextureMapperLayer::setAnimations(const GraphicsLayerAnimations& animations)
+{
+ m_animations = animations;
+}
+
+void TextureMapperLayer::setFixedToViewport(bool fixedToViewport)
+{
+ m_fixedToViewport = fixedToViewport;
+}
+
+void TextureMapperLayer::setBackingStore(PassRefPtr<TextureMapperBackingStore> backingStore)
+{
+ m_backingStore = backingStore;
}
bool TextureMapperLayer::descendantsOrSelfHaveRunningAnimations() const
@@ -470,48 +686,16 @@ void TextureMapperLayer::syncAnimations()
{
m_animations.apply(this);
if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitTransform))
- setTransform(m_state.transform);
+ m_currentTransform.setLocalTransform(m_state.transform);
if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyOpacity))
- setOpacity(m_state.opacity);
+ m_currentOpacity = m_state.opacity;
+
#if ENABLE(CSS_FILTERS)
if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitFilter))
- setFilters(m_state.filters);
+ m_currentFilters = m_state.filters;
#endif
}
-void TextureMapperLayer::flushCompositingState(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper, int options)
-{
- if (!textureMapper)
- return;
-
- if (graphicsLayer && !(options & ComputationsOnly))
- flushCompositingStateSelf(graphicsLayer, textureMapper);
-
- if (graphicsLayer && m_state.maskLayer)
- m_state.maskLayer->flushCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->maskLayer()), textureMapper);
-
- if (m_state.replicaLayer)
- m_state.replicaLayer->flushCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->replicaLayer()), textureMapper);
-
- syncAnimations();
-
- if (!(options & TraverseDescendants))
- options = ComputationsOnly;
-
- if (graphicsLayer) {
- Vector<GraphicsLayer*> children = graphicsLayer->children();
- for (int i = children.size() - 1; i >= 0; --i) {
- TextureMapperLayer* layer = toTextureMapperLayer(children[i]);
- if (!layer)
- continue;
- layer->flushCompositingState(toGraphicsLayerTextureMapper(children[i]), textureMapper, options);
- }
- } else {
- for (int i = m_children.size() - 1; i >= 0; --i)
- m_children[i]->flushCompositingState(0, textureMapper, options);
- }
-}
-
bool TextureMapperLayer::isAncestorFixedToViewport() const
{
for (TextureMapperLayer* parent = m_parent; parent; parent = parent->m_parent) {
@@ -532,7 +716,80 @@ void TextureMapperLayer::setScrollPositionDeltaIfNeeded(const FloatSize& delta)
m_scrollPositionDelta = FloatSize();
else
m_scrollPositionDelta = delta;
- m_transform.setPosition(adjustedPosition());
+ m_currentTransform.setPosition(adjustedPosition());
+}
+
+template<class HitTestCondition> TextureMapperLayer* TextureMapperLayer::hitTest(const FloatPoint& point, HitTestCondition condition)
+{
+ if (!m_state.visible || !m_state.contentsVisible)
+ return 0;
+
+ TextureMapperLayer* result = 0;
+ for (int i = m_children.size() - 1; !result && i >= 0; --i)
+ result = m_children[i]->hitTest(point, condition);
+
+ if (result)
+ return result;
+
+ return condition(this, point) ? this : 0;
+}
+
+bool TextureMapperLayer::scrollableLayerHitTestCondition(TextureMapperLayer* layer, const FloatPoint& point)
+{
+ // scrolling layer's m_parent->m_parent, the parent of the scrolling layes, is the one that defines the
+ // rectangle to be used for hit testing.
+ if (!layer->isScrollable() || !layer->m_parent || !layer->m_parent->m_parent)
+ return false;
+
+ TextureMapperLayer* parentLayer = layer->m_parent->m_parent;
+ FloatRect rect = parentLayer->layerRect();
+ return parentLayer->m_currentTransform.combined().mapQuad(rect).containsPoint(point);
+}
+
+TextureMapperLayer* TextureMapperLayer::findScrollableContentsLayerAt(const FloatPoint& point)
+{
+ return hitTest(point, &TextureMapperLayer::scrollableLayerHitTestCondition);
+}
+
+FloatSize TextureMapperLayer::mapScrollOffset(const FloatSize& offset)
+{
+ double zeroX, zeroY, offsetX, offsetY;
+ TransformationMatrix transform = m_currentTransform.combined().inverse();
+ transform.map(0, 0, zeroX, zeroY);
+ transform.map(offset.width(), offset.height(), offsetX, offsetY);
+ return FloatSize(offsetX - zeroX, offsetY - zeroY);
+}
+
+void TextureMapperLayer::commitScrollOffset(const FloatSize& offset)
+{
+ FloatSize fullOffset = m_accumulatedScrollOffsetFractionalPart + offset;
+
+ int intWidth = round(fullOffset.width());
+ int intHeight = round(fullOffset.height());
+
+ // m_accumulatedScrollOffsetFractionalPart holds the fractional part of the user scroll offset that
+ // has not yet been synced with the web process because the web process expects an IntSize.
+ m_accumulatedScrollOffsetFractionalPart = FloatSize(fullOffset.width() - intWidth, fullOffset.height() - intHeight);
+
+ m_scrollClient->commitScrollOffset(m_id, IntSize(intWidth, intHeight));
+}
+
+void TextureMapperLayer::scrollBy(const FloatSize& offset)
+{
+ if (!isScrollable() || !m_scrollClient || offset.isZero())
+ return;
+
+ FloatSize scrollOffset = mapScrollOffset(offset);
+ m_userScrollOffset += scrollOffset;
+
+ m_currentTransform.setPosition(adjustedPosition());
+ commitScrollOffset(scrollOffset);
+}
+
+void TextureMapperLayer::didCommitScrollOffset(const IntSize& offset)
+{
+ m_userScrollOffset = FloatSize(m_userScrollOffset.width() - offset.width(), m_userScrollOffset.height() - offset.height());
+ m_currentTransform.setPosition(adjustedPosition());
}
}
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h
index 27a77f6fe..7b62b0a0b 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h
@@ -20,11 +20,10 @@
#ifndef TextureMapperLayer_h
#define TextureMapperLayer_h
-#if USE(ACCELERATED_COMPOSITING)
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
#include "FilterOperations.h"
#include "FloatRect.h"
-#include "GraphicsLayer.h"
#include "GraphicsLayerAnimation.h"
#include "GraphicsLayerTransform.h"
#include "TextureMapper.h"
@@ -32,132 +31,145 @@
namespace WebCore {
+class Region;
+class TextureMapperPaintOptions;
class TextureMapperPlatformLayer;
-class GraphicsLayerTextureMapper;
-
-class TextureMapperPaintOptions {
-public:
- RefPtr<BitmapTexture> surface;
- RefPtr<BitmapTexture> mask;
- float opacity;
- TransformationMatrix transform;
- IntSize offset;
- TextureMapper* textureMapper;
- TextureMapperPaintOptions()
- : opacity(1)
- , textureMapper(0)
- { }
-};
class TextureMapperLayer : public GraphicsLayerAnimation::Client {
+ WTF_MAKE_NONCOPYABLE(TextureMapperLayer);
WTF_MAKE_FAST_ALLOCATED;
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),
- ContentsVisibleChange = (1L << 15),
- ContentsOpaqueChange = (1L << 16),
-
- BackfaceVisibilityChange = (1L << 17),
- ChildrenTransformChange = (1L << 18),
- DisplayChange = (1L << 19),
- BackgroundColorChange = (1L << 20),
-
- ReplicaLayerChange = (1L << 21),
- AnimationChange = (1L << 22),
- FilterChange = (1L << 23)
- };
- enum SyncOptions {
- TraverseDescendants = 1,
- ComputationsOnly = 2
+ class ScrollingClient {
+ public:
+ virtual void commitScrollOffset(uint32_t layerID, const IntSize& offset) = 0;
};
TextureMapperLayer()
: m_parent(0)
, m_effectTarget(0)
, m_contentsLayer(0)
- , m_opacity(1)
+ , m_currentOpacity(1)
, m_centerZ(0)
, m_textureMapper(0)
+ , m_fixedToViewport(false)
+ , m_id(0)
+ , m_scrollClient(0)
+ , m_isScrollable(false)
+ , m_patternTransformDirty(false)
{ }
virtual ~TextureMapperLayer();
+ void setID(uint32_t id) { m_id = id; }
+ uint32_t id() { return m_id; }
+
+ const Vector<TextureMapperLayer*>& children() const { return m_children; }
+ TextureMapperLayer* findScrollableContentsLayerAt(const FloatPoint& pos);
+
+ void setScrollClient(ScrollingClient* scrollClient) { m_scrollClient = scrollClient; }
+ void scrollBy(const WebCore::FloatSize&);
+
+ void didCommitScrollOffset(const IntSize&);
+ void setIsScrollable(bool isScrollable) { m_isScrollable = isScrollable; }
+ bool isScrollable() const { return m_isScrollable; }
+
TextureMapper* textureMapper() const;
- void flushCompositingState(GraphicsLayerTextureMapper*, int syncOptions = 0);
- void flushCompositingState(GraphicsLayerTextureMapper*, TextureMapper*, int syncOptions = 0);
- IntSize size() const { return IntSize(m_size.width(), m_size.height()); }
+ void setTextureMapper(TextureMapper* texmap) { m_textureMapper = texmap; }
+
+ void setChildren(const Vector<TextureMapperLayer*>&);
+ void setMaskLayer(TextureMapperLayer*);
+ void setReplicaLayer(TextureMapperLayer*);
+ void setPosition(const FloatPoint&);
+ void setSize(const FloatSize&);
+ void setAnchorPoint(const FloatPoint3D&);
+ void setPreserves3D(bool);
void setTransform(const TransformationMatrix&);
- void setOpacity(float value) { m_opacity = value; }
+ void setChildrenTransform(const TransformationMatrix&);
+ void setContentsRect(const IntRect&);
+ void setMasksToBounds(bool);
+ void setDrawsContent(bool);
+ bool drawsContent() const { return m_state.drawsContent; }
+ bool contentsAreVisible() const { return m_state.contentsVisible; }
+ FloatSize size() const { return m_state.size; }
+ float opacity() const { return m_state.opacity; }
+ TransformationMatrix transform() const { return m_state.transform; }
+ void setContentsVisible(bool);
+ void setContentsOpaque(bool);
+ void setBackfaceVisibility(bool);
+ void setOpacity(float);
+ void setSolidColor(const Color&);
+ void setContentsTileSize(const IntSize&);
+ void setContentsTilePhase(const IntPoint&);
#if ENABLE(CSS_FILTERS)
- void setFilters(const FilterOperations& filters) { m_filters = filters; }
+ void setFilters(const FilterOperations&);
#endif
- void setTextureMapper(TextureMapper* texmap) { m_textureMapper = texmap; }
+
+ bool hasFilters() const
+ {
+#if ENABLE(CSS_FILTERS)
+ return !m_currentFilters.isEmpty();
+#else
+ return false;
+#endif
+ }
+
+ void setDebugVisuals(bool showDebugBorders, const Color& debugBorderColor, float debugBorderWidth, bool showRepaintCounter);
+ bool isShowingRepaintCounter() const { return m_state.showRepaintCounter; }
+ void setRepaintCount(int);
+ void setContentsLayer(TextureMapperPlatformLayer*);
+ void setAnimations(const GraphicsLayerAnimations&);
+ void setFixedToViewport(bool);
+ bool fixedToViewport() const { return m_fixedToViewport; }
+ void setBackingStore(PassRefPtr<TextureMapperBackingStore>);
+
+ void syncAnimations();
bool descendantsOrSelfHaveRunningAnimations() const;
void paint();
- void setBackingStore(PassRefPtr<TextureMapperBackingStore> backingStore) { m_backingStore = backingStore; }
- PassRefPtr<TextureMapperBackingStore> backingStore() { return m_backingStore; }
- void clearBackingStoresRecursive();
-
void setScrollPositionDeltaIfNeeded(const FloatSize&);
void applyAnimationsRecursively();
+ void addChild(TextureMapperLayer*);
private:
const TextureMapperLayer* rootLayer() const;
void computeTransformsRecursive();
- void computeOverlapsIfNeeded();
- void computeTiles();
- IntRect intermediateSurfaceRect(const TransformationMatrix&);
- IntRect intermediateSurfaceRect();
- void swapContentsBuffers();
- FloatRect targetRectForTileRect(const FloatRect& totalTargetRect, const FloatRect& tileRect) const;
- void invalidateViewport(const FloatRect&);
- void notifyChange(ChangeMask);
- void flushCompositingStateSelf(GraphicsLayerTextureMapper*, TextureMapper*);
static int compareGraphicsLayersZValue(const void* a, const void* b);
- static void sortByZOrder(Vector<TextureMapperLayer* >& array, int first, int last);
+ static void sortByZOrder(Vector<TextureMapperLayer* >& array);
PassRefPtr<BitmapTexture> texture() { return m_backingStore ? m_backingStore->texture() : 0; }
- FloatPoint adjustedPosition() const { return m_state.pos + m_scrollPositionDelta; }
+ FloatPoint adjustedPosition() const { return m_state.pos + m_scrollPositionDelta - m_userScrollOffset; }
bool isAncestorFixedToViewport() const;
+ TransformationMatrix replicaTransform();
+ void removeFromParent();
+ void removeAllChildren();
+
+ enum ResolveSelfOverlapMode {
+ ResolveSelfOverlapAlways = 0,
+ ResolveSelfOverlapIfNeeded
+ };
+ void computeOverlapRegions(Region& overlapRegion, Region& nonOverlapRegion, ResolveSelfOverlapMode);
void paintRecursive(const TextureMapperPaintOptions&);
+ void paintUsingOverlapRegions(const TextureMapperPaintOptions&);
+ PassRefPtr<BitmapTexture> paintIntoSurface(const TextureMapperPaintOptions&, const IntSize&);
+ void paintWithIntermediateSurface(const TextureMapperPaintOptions&, const IntRect&);
void paintSelf(const TextureMapperPaintOptions&);
void paintSelfAndChildren(const TextureMapperPaintOptions&);
void paintSelfAndChildrenWithReplica(const TextureMapperPaintOptions&);
+ void applyMask(const TextureMapperPaintOptions&);
+ void computePatternTransformIfNeeded();
// GraphicsLayerAnimation::Client
- void setAnimatedTransform(const TransformationMatrix& matrix) { setTransform(matrix); }
- void setAnimatedOpacity(float opacity) { setOpacity(opacity); }
+ virtual void setAnimatedTransform(const TransformationMatrix&) OVERRIDE;
+ virtual void setAnimatedOpacity(float) OVERRIDE;
#if ENABLE(CSS_FILTERS)
- virtual void setAnimatedFilters(const FilterOperations& filters) { setFilters(filters); }
+ virtual void setAnimatedFilters(const FilterOperations&) OVERRIDE;
#endif
- void syncAnimations();
bool isVisible() const;
enum ContentsLayerCount {
NoLayersWithContent,
@@ -165,14 +177,11 @@ private:
MultipleLayersWithContents
};
- ContentsLayerCount countPotentialLayersWithContents() const;
- bool shouldPaintToIntermediateSurface() const;
-
- GraphicsLayerTransform m_transform;
+ bool shouldBlend() const;
inline FloatRect layerRect() const
{
- return FloatRect(FloatPoint::zero(), m_size);
+ return FloatRect(FloatPoint::zero(), m_state.size);
}
Vector<TextureMapperLayer*> m_children;
@@ -180,13 +189,18 @@ private:
TextureMapperLayer* m_effectTarget;
RefPtr<TextureMapperBackingStore> m_backingStore;
TextureMapperPlatformLayer* m_contentsLayer;
- FloatSize m_size;
- float m_opacity;
+ GraphicsLayerTransform m_currentTransform;
+ float m_currentOpacity;
#if ENABLE(CSS_FILTERS)
- FilterOperations m_filters;
+ FilterOperations m_currentFilters;
#endif
float m_centerZ;
- String m_name;
+
+ template<class HitTestCondition> TextureMapperLayer* hitTest(const FloatPoint&, HitTestCondition);
+ static bool scrollableLayerHitTestCondition(TextureMapperLayer*, const FloatPoint&);
+
+ FloatSize mapScrollOffset(const FloatSize&);
+ void commitScrollOffset(const FloatSize&);
struct State {
FloatPoint pos;
@@ -196,12 +210,17 @@ private:
TransformationMatrix childrenTransform;
float opacity;
FloatRect contentsRect;
- int descendantsWithContent;
+ IntSize contentsTileSize;
+ IntPoint contentsTilePhase;
TextureMapperLayer* maskLayer;
TextureMapperLayer* replicaLayer;
+ Color solidColor;
#if ENABLE(CSS_FILTERS)
- FilterOperations filters;
+ FilterOperations filters;
#endif
+ Color debugBorderColor;
+ float debugBorderWidth;
+ int repaintCount;
bool preserves3D : 1;
bool masksToBounds : 1;
@@ -210,21 +229,24 @@ private:
bool contentsOpaque : 1;
bool backfaceVisibility : 1;
bool visible : 1;
- bool mightHaveOverlaps : 1;
- bool needsRepaint;
+ bool showDebugBorders : 1;
+ bool showRepaintCounter : 1;
+
State()
- : opacity(1.f)
+ : opacity(1)
, maskLayer(0)
, replicaLayer(0)
+ , debugBorderWidth(0)
+ , repaintCount(0)
, preserves3D(false)
, masksToBounds(false)
, drawsContent(false)
, contentsVisible(true)
, contentsOpaque(false)
- , backfaceVisibility(false)
+ , backfaceVisibility(true)
, visible(true)
- , mightHaveOverlaps(false)
- , needsRepaint(false)
+ , showDebugBorders(false)
+ , showRepaintCounter(false)
{
}
};
@@ -234,11 +256,15 @@ private:
GraphicsLayerAnimations m_animations;
FloatSize m_scrollPositionDelta;
bool m_fixedToViewport;
+ uint32_t m_id;
+ ScrollingClient* m_scrollClient;
+ bool m_isScrollable;
+ FloatSize m_userScrollOffset;
+ FloatSize m_accumulatedScrollOffsetFractionalPart;
+ TransformationMatrix m_patternTransform;
+ bool m_patternTransformDirty;
};
-
-TextureMapperLayer* toTextureMapperLayer(GraphicsLayer*);
-
}
#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
index 38af03e89..0cab98da4 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h
@@ -24,23 +24,42 @@
#include "GraphicsSurface.h"
#endif
+#include "TextureMapper.h"
#include "TransformationMatrix.h"
namespace WebCore {
-class TextureMapper;
-class BitmapTexture;
-
class TextureMapperPlatformLayer {
public:
+ class Client {
+ public:
+ virtual void setPlatformLayerNeedsDisplay() = 0;
+ };
+
+ TextureMapperPlatformLayer() : m_client(0) { }
virtual ~TextureMapperPlatformLayer() { }
- virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix& modelViewMatrix = TransformationMatrix(), float opacity = 1.0, BitmapTexture* mask = 0) = 0;
+ virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix& modelViewMatrix = TransformationMatrix(), float opacity = 1.0) = 0;
virtual void swapBuffers() { }
+ virtual void drawBorder(TextureMapper* textureMapper, const Color& color, float borderWidth, const FloatRect& targetRect, const TransformationMatrix& transform)
+ {
+ textureMapper->drawBorder(color, borderWidth, targetRect, transform);
+ }
+ void setClient(TextureMapperPlatformLayer::Client* client)
+ {
+ m_client = client;
+ }
#if USE(GRAPHICS_SURFACE)
virtual IntSize platformLayerSize() const { return IntSize(); }
virtual uint32_t copyToGraphicsSurface() { return 0; }
virtual GraphicsSurfaceToken graphicsSurfaceToken() const { return GraphicsSurfaceToken(); }
+ virtual GraphicsSurface::Flags graphicsSurfaceFlags() const { return GraphicsSurface::SupportsTextureTarget | GraphicsSurface::SupportsSharing; }
#endif
+
+protected:
+ TextureMapperPlatformLayer::Client* client() { return m_client; }
+
+private:
+ TextureMapperPlatformLayer::Client* m_client;
};
};
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp
deleted file mode 100644
index c8e1ae461..000000000
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
- Copyright (C) 2012 Igalia S.L.
- Copyright (C) 2011 Google Inc. All rights reserved.
-
- 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 "TextureMapperShaderManager.h"
-
-#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
-
-#include "LengthFunctions.h"
-#include "Logging.h"
-#include "TextureMapperGL.h"
-
-#define STRINGIFY(...) #__VA_ARGS__
-
-namespace WebCore {
-
-
-static inline bool compositingLogEnabled()
-{
-#if !LOG_DISABLED
- return LogCompositing.state == WTFLogChannelOn;
-#else
- return false;
-#endif
-}
-
-TextureMapperShaderProgram::TextureMapperShaderProgram(PassRefPtr<GraphicsContext3D> context, const String& vertex, const String& fragment)
- : m_context(context)
-{
- m_vertexShader = m_context->createShader(GraphicsContext3D::VERTEX_SHADER);
- m_fragmentShader = m_context->createShader(GraphicsContext3D::FRAGMENT_SHADER);
- m_context->shaderSource(m_vertexShader, vertex);
- m_context->shaderSource(m_fragmentShader, fragment);
- m_id = m_context->createProgram();
- m_context->compileShader(m_vertexShader);
- m_context->compileShader(m_fragmentShader);
- m_context->attachShader(m_id, m_vertexShader);
- m_context->attachShader(m_id, m_fragmentShader);
- m_context->linkProgram(m_id);
-
- if (!compositingLogEnabled())
- return;
-
- if (m_context->getError() == GraphicsContext3D::NO_ERROR)
- return;
-
- String log = m_context->getShaderInfoLog(m_vertexShader);
- LOG(Compositing, "Vertex shader log: %s\n", log.utf8().data());
- log = m_context->getShaderInfoLog(m_fragmentShader);
- LOG(Compositing, "Fragment shader log: %s\n", log.utf8().data());
- log = m_context->getProgramInfoLog(m_id);
- LOG(Compositing, "Program log: %s\n", log.utf8().data());
-}
-
-GC3Duint TextureMapperShaderProgram::getLocation(const AtomicString& name, VariableType type)
-{
- HashMap<AtomicString, GC3Duint>::iterator it = m_variables.find(name);
- if (it != m_variables.end())
- return it->value;
-
- GC3Duint location = 0;
- switch (type) {
- case UniformVariable:
- location = m_context->getUniformLocation(m_id, name);
- break;
- case AttribVariable:
- location = m_context->getAttribLocation(m_id, name);
- break;
- default:
- ASSERT_NOT_REACHED();
- break;
- }
-
- m_variables.add(name, location);
- return location;
-}
-
-TextureMapperShaderProgram::~TextureMapperShaderProgram()
-{
- Platform3DObject programID = m_id;
- if (!programID)
- return;
-
- m_context->detachShader(programID, m_vertexShader);
- m_context->deleteShader(m_vertexShader);
- m_context->detachShader(programID, m_fragmentShader);
- m_context->deleteShader(m_fragmentShader);
- m_context->deleteProgram(programID);
-}
-
-struct ShaderSpec {
- String vertexShader;
- String fragmentShader;
- ShaderSpec(const char* vertex = 0, const char* fragment = 0)
- : vertexShader(vertex ? String(ASCIILiteral(vertex)) : String())
- , fragmentShader(fragment ? String(ASCIILiteral(fragment)) : String())
- {
- }
-};
-
-static void getShaderSpec(TextureMapperShaderManager::ShaderKey key, String& vertexSource, String& fragmentSource)
-{
- static Vector<ShaderSpec> specs = Vector<ShaderSpec>();
- static const char* fragmentOpacityAndMask =
- STRINGIFY(
- precision mediump float;
- uniform sampler2D s_sampler;
- uniform sampler2D s_mask;
- uniform lowp float u_opacity;
- varying highp vec2 v_sourceTexCoord;
- varying highp vec2 v_maskTexCoord;
- void main(void)
- {
- lowp vec4 color = texture2D(s_sampler, v_sourceTexCoord);
- lowp vec4 maskColor = texture2D(s_mask, v_maskTexCoord);
- lowp float fragmentAlpha = u_opacity * maskColor.a;
- gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha);
- }
- );
-
- static const char* fragmentRectOpacityAndMask =
- STRINGIFY(
- precision mediump float;
- uniform sampler2DRect s_sampler;
- uniform sampler2DRect s_mask;
- uniform lowp float u_opacity;
- varying highp vec2 v_sourceTexCoord;
- varying highp vec2 v_maskTexCoord;
- void main(void)
- {
- lowp vec4 color = texture2DRect(s_sampler, v_sourceTexCoord);
- lowp vec4 maskColor = texture2DRect(s_mask, v_maskTexCoord);
- lowp float fragmentAlpha = u_opacity * maskColor.a;
- gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha);
- }
- );
-
- static const char* vertexOpacityAndMask =
- STRINGIFY(
- uniform mat4 u_matrix;
- uniform lowp float u_flip;
- attribute vec4 a_vertex;
- varying highp vec2 v_sourceTexCoord;
- varying highp vec2 v_maskTexCoord;
- void main(void)
- {
- v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip));
- v_maskTexCoord = vec2(a_vertex);
- gl_Position = u_matrix * a_vertex;
- }
- );
-
- static const char* fragmentSimple =
- STRINGIFY(
- precision mediump float;
- uniform sampler2D s_sampler;
- uniform lowp float u_opacity;
- varying highp vec2 v_sourceTexCoord;
- void main(void)
- {
- lowp vec4 color = texture2D(s_sampler, v_sourceTexCoord);
- gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity);
- }
- );
-
- static const char* fragmentAntialiasingNoMask =
- STRINGIFY(
- precision mediump float;
- uniform sampler2D s_sampler;
- varying highp vec2 v_sourceTexCoord;
- uniform lowp float u_opacity;
- uniform vec3 u_expandedQuadEdgesInScreenSpace[8];
- void main()
- {
- vec4 sampledColor = texture2D(s_sampler, clamp(v_sourceTexCoord, 0.0, 1.0));
- vec3 pos = vec3(gl_FragCoord.xy, 1);
-
- // The data passed in u_expandedQuadEdgesInScreenSpace is merely the
- // pre-scaled coeffecients of the line equations describing the four edges
- // of the expanded quad in screen space and the rectangular bounding box
- // of the expanded quad.
- //
- // We are doing a simple distance calculation here according to the formula:
- // (A*p.x + B*p.y + C) / sqrt(A^2 + B^2) = distance from line to p
- // Note that A, B and C have already been scaled by 1 / sqrt(A^2 + B^2).
- float a0 = clamp(dot(u_expandedQuadEdgesInScreenSpace[0], pos), 0.0, 1.0);
- float a1 = clamp(dot(u_expandedQuadEdgesInScreenSpace[1], pos), 0.0, 1.0);
- float a2 = clamp(dot(u_expandedQuadEdgesInScreenSpace[2], pos), 0.0, 1.0);
- float a3 = clamp(dot(u_expandedQuadEdgesInScreenSpace[3], pos), 0.0, 1.0);
- float a4 = clamp(dot(u_expandedQuadEdgesInScreenSpace[4], pos), 0.0, 1.0);
- float a5 = clamp(dot(u_expandedQuadEdgesInScreenSpace[5], pos), 0.0, 1.0);
- float a6 = clamp(dot(u_expandedQuadEdgesInScreenSpace[6], pos), 0.0, 1.0);
- float a7 = clamp(dot(u_expandedQuadEdgesInScreenSpace[7], pos), 0.0, 1.0);
-
- // Now we want to reduce the alpha value of the fragment if it is close to the
- // edges of the expanded quad (or rectangular bounding box -- which seems to be
- // important for backfacing quads). Note that we are combining the contribution
- // from the (top || bottom) and (left || right) edge by simply multiplying. This follows
- // the approach described at: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter22.html,
- // in this case without using Gaussian weights.
- gl_FragColor = sampledColor * u_opacity * min(min(a0, a2) * min(a1, a3), min(a4, a6) * min(a5, a7));
- }
- );
-
- static const char* fragmentRectSimple =
- STRINGIFY(
- precision mediump float;
- uniform sampler2DRect s_sampler;
- uniform lowp vec2 u_samplerSize;
- uniform lowp float u_opacity;
- varying highp vec2 v_sourceTexCoord;
- void main(void)
- {
- lowp vec4 color = texture2DRect(s_sampler, u_samplerSize * v_sourceTexCoord);
- gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity);
- }
- );
-
- static const char* vertexSimple =
- STRINGIFY(
- uniform mat4 u_matrix;
- uniform lowp float u_flip;
- attribute vec4 a_vertex;
- varying highp vec2 v_sourceTexCoord;
- void main(void)
- {
- v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip));
- gl_Position = u_matrix * a_vertex;
- }
- );
-
- static const char* vertexSolidColor =
- STRINGIFY(
- uniform mat4 u_matrix;
- attribute vec4 a_vertex;
- void main(void)
- {
- gl_Position = u_matrix * a_vertex;
- }
- );
-
-
- static const char* fragmentSolidColor =
- STRINGIFY(
- precision mediump float;
- uniform vec4 u_color;
- void main(void)
- {
- gl_FragColor = u_color;
- }
- );
-
- static const char* vertexFilter =
- STRINGIFY(
- attribute vec4 a_vertex;
- attribute vec4 a_texCoord;
- varying highp vec2 v_texCoord;
- void main(void)
- {
- v_texCoord = vec2(a_texCoord);
- gl_Position = a_vertex;
- }
- );
-
-#define STANDARD_FILTER(...) \
- "precision mediump float;\n"\
- "varying highp vec2 v_texCoord;\n"\
- "uniform highp float u_amount;\n"\
- "uniform sampler2D s_sampler;\n"#__VA_ARGS__ \
- "void main(void)\n { gl_FragColor = shade(texture2D(s_sampler, v_texCoord)); }"
-
- static const char* fragmentGrayscaleFilter =
- STANDARD_FILTER(
- lowp vec4 shade(lowp vec4 color)
- {
- lowp float amount = 1.0 - u_amount;
- return vec4((0.2126 + 0.7874 * amount) * color.r + (0.7152 - 0.7152 * amount) * color.g + (0.0722 - 0.0722 * amount) * color.b,
- (0.2126 - 0.2126 * amount) * color.r + (0.7152 + 0.2848 * amount) * color.g + (0.0722 - 0.0722 * amount) * color.b,
- (0.2126 - 0.2126 * amount) * color.r + (0.7152 - 0.7152 * amount) * color.g + (0.0722 + 0.9278 * amount) * color.b,
- color.a);
- }
- );
-
- static const char* fragmentSepiaFilter =
- STANDARD_FILTER(
- lowp vec4 shade(lowp vec4 color)
- {
- lowp float amount = 1.0 - u_amount;
- return vec4((0.393 + 0.607 * amount) * color.r + (0.769 - 0.769 * amount) * color.g + (0.189 - 0.189 * amount) * color.b,
- (0.349 - 0.349 * amount) * color.r + (0.686 + 0.314 * amount) * color.g + (0.168 - 0.168 * amount) * color.b,
- (0.272 - 0.272 * amount) * color.r + (0.534 - 0.534 * amount) * color.g + (0.131 + 0.869 * amount) * color.b,
- color.a);
- }
- );
-
- static const char* fragmentSaturateFilter =
- STANDARD_FILTER(
- lowp vec4 shade(lowp vec4 color)
- {
- return vec4((0.213 + 0.787 * u_amount) * color.r + (0.715 - 0.715 * u_amount) * color.g + (0.072 - 0.072 * u_amount) * color.b,
- (0.213 - 0.213 * u_amount) * color.r + (0.715 + 0.285 * u_amount) * color.g + (0.072 - 0.072 * u_amount) * color.b,
- (0.213 - 0.213 * u_amount) * color.r + (0.715 - 0.715 * u_amount) * color.g + (0.072 + 0.928 * u_amount) * color.b,
- color.a);
- }
- );
-
- static const char* fragmentHueRotateFilter =
- STANDARD_FILTER(
- lowp vec4 shade(lowp vec4 color)
- {
- highp float pi = 3.14159265358979323846;
- highp float c = cos(u_amount * pi / 180.0);
- highp float s = sin(u_amount * pi / 180.0);
- return vec4(color.r * (0.213 + c * 0.787 - s * 0.213) + color.g * (0.715 - c * 0.715 - s * 0.715) + color.b * (0.072 - c * 0.072 + s * 0.928),
- color.r * (0.213 - c * 0.213 + s * 0.143) + color.g * (0.715 + c * 0.285 + s * 0.140) + color.b * (0.072 - c * 0.072 - s * 0.283),
- color.r * (0.213 - c * 0.213 - s * 0.787) + color.g * (0.715 - c * 0.715 + s * 0.715) + color.b * (0.072 + c * 0.928 + s * 0.072),
- color.a);
- }
- );
-
- static const char* fragmentInvertFilter =
- STANDARD_FILTER(
- lowp float invert(lowp float n) { return (1.0 - n) * u_amount + n * (1.0 - u_amount); }
- lowp vec4 shade(lowp vec4 color)
- {
- return vec4(invert(color.r), invert(color.g), invert(color.b), color.a);
- }
- );
-
- static const char* fragmentBrightnessFilter =
- STANDARD_FILTER(
- lowp vec4 shade(lowp vec4 color)
- {
- return vec4(color.rgb * (1.0 + u_amount), color.a);
- }
- );
-
- static const char* fragmentContrastFilter =
- STANDARD_FILTER(
- lowp float contrast(lowp float n) { return (n - 0.5) * u_amount + 0.5; }
- lowp vec4 shade(lowp vec4 color)
- {
- return vec4(contrast(color.r), contrast(color.g), contrast(color.b), color.a);
- }
- );
-
- static const char* fragmentOpacityFilter =
- STANDARD_FILTER(
- lowp vec4 shade(lowp vec4 color)
- {
- return vec4(color.r, color.g, color.b, color.a * u_amount);
- }
- );
-
-#define BLUR_CONSTANTS "#define GAUSSIAN_KERNEL_HALF_WIDTH 11\n#define GAUSSIAN_KERNEL_STEP 0.2\n"
-
- static const char* fragmentBlurFilter =
- BLUR_CONSTANTS
- STRINGIFY(
- // Create a normal distribution of 21 values between -2 and 2.
- precision mediump float;
- varying highp vec2 v_texCoord;
- uniform lowp vec2 u_blurRadius;
- uniform sampler2D s_sampler;
- uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];
-
- lowp vec4 sampleColor(float radius)
- {
- vec2 coord = v_texCoord + radius * u_blurRadius;
- return texture2D(s_sampler, coord) * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.);
- }
-
- vec4 blur()
- {
- vec4 total = sampleColor(0.) * u_gaussianKernel[0];
- for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) {
- total += sampleColor(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
- total += sampleColor(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
- }
-
- return total;
- }
-
- void main(void)
- {
- gl_FragColor = blur();
- }
- );
-
- static const char* fragmentShadowFilter1 =
- BLUR_CONSTANTS
- STRINGIFY(
- precision mediump float;
- varying highp vec2 v_texCoord;
- uniform lowp float u_blurRadius;
- uniform lowp vec2 u_shadowOffset;
- uniform sampler2D s_sampler;
- uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];
-
- lowp float sampleAlpha(float radius)
- {
- vec2 coord = v_texCoord - u_shadowOffset + vec2(radius * u_blurRadius, 0.);
- return texture2D(s_sampler, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.);
- }
-
- lowp float shadowBlurHorizontal()
- {
- float total = sampleAlpha(0.) * u_gaussianKernel[0];
- for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) {
- total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
- total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
- }
-
- return total;
- }
-
- void main(void)
- {
- gl_FragColor = vec4(1., 1., 1., 1.) * shadowBlurHorizontal();
- }
- );
-
- // Second pass: vertical alpha blur and composite with origin.
- static const char* fragmentShadowFilter2 =
- BLUR_CONSTANTS
- STRINGIFY(
- precision mediump float;
- varying highp vec2 v_texCoord;
- uniform lowp float u_blurRadius;
- uniform lowp vec4 u_shadowColor;
- uniform sampler2D s_sampler;
- uniform sampler2D s_contentTexture;
- uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];
-
- lowp float sampleAlpha(float r)
- {
- vec2 coord = v_texCoord + vec2(0., r * u_blurRadius);
- return texture2D(s_sampler, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.);
- }
-
- lowp float shadowBlurVertical()
- {
- float total = sampleAlpha(0.) * u_gaussianKernel[0];
- for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) {
- total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
- total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
- }
-
- return total;
- }
-
- lowp vec4 sourceOver(lowp vec4 source, lowp vec4 destination)
- {
- // Composite the shadow with the original texture.
- return source + destination * (1. - source.a);
- }
-
- void main(void)
- {
- gl_FragColor = sourceOver(texture2D(s_contentTexture, v_texCoord), shadowBlurVertical() * u_shadowColor);
- }
- );
-
- if (specs.isEmpty()) {
- specs.resize(TextureMapperShaderManager::LastFilter);
- specs[TextureMapperShaderManager::Default] = ShaderSpec(vertexSimple, fragmentSimple);
- specs[TextureMapperShaderManager::SolidColor] = ShaderSpec(vertexSolidColor, fragmentSolidColor);
- specs[TextureMapperShaderManager::Rect] = ShaderSpec(vertexSimple, fragmentRectSimple);
- specs[TextureMapperShaderManager::Masked] = ShaderSpec(vertexOpacityAndMask, fragmentOpacityAndMask);
- specs[TextureMapperShaderManager::MaskedRect] = ShaderSpec(vertexOpacityAndMask, fragmentRectOpacityAndMask);
- specs[TextureMapperShaderManager::Antialiased] = ShaderSpec(vertexSimple, fragmentAntialiasingNoMask);
- specs[TextureMapperShaderManager::GrayscaleFilter] = ShaderSpec(vertexFilter, fragmentGrayscaleFilter);
- specs[TextureMapperShaderManager::SepiaFilter] = ShaderSpec(vertexFilter, fragmentSepiaFilter);
- specs[TextureMapperShaderManager::SaturateFilter] = ShaderSpec(vertexFilter, fragmentSaturateFilter);
- specs[TextureMapperShaderManager::HueRotateFilter] = ShaderSpec(vertexFilter, fragmentHueRotateFilter);
- specs[TextureMapperShaderManager::BrightnessFilter] = ShaderSpec(vertexFilter, fragmentBrightnessFilter);
- specs[TextureMapperShaderManager::ContrastFilter] = ShaderSpec(vertexFilter, fragmentContrastFilter);
- specs[TextureMapperShaderManager::InvertFilter] = ShaderSpec(vertexFilter, fragmentInvertFilter);
- specs[TextureMapperShaderManager::OpacityFilter] = ShaderSpec(vertexFilter, fragmentOpacityFilter);
- specs[TextureMapperShaderManager::BlurFilter] = ShaderSpec(vertexFilter, fragmentBlurFilter);
- specs[TextureMapperShaderManager::ShadowFilterPass1] = ShaderSpec(vertexFilter, fragmentShadowFilter1);
- specs[TextureMapperShaderManager::ShadowFilterPass2] = ShaderSpec(vertexFilter, fragmentShadowFilter2);
- }
-
- ASSERT(specs.size() > key);
- ShaderSpec& spec = specs[key];
- vertexSource = spec.vertexShader;
- fragmentSource = spec.fragmentShader;
-}
-
-TextureMapperShaderManager::TextureMapperShaderManager(GraphicsContext3D* context)
- : m_context(context)
-{
-}
-
-TextureMapperShaderManager::~TextureMapperShaderManager()
-{
-}
-
-PassRefPtr<TextureMapperShaderProgram> TextureMapperShaderManager::getShaderProgram(ShaderKey key)
-{
- TextureMapperShaderProgramMap::iterator it = m_programs.find(key);
- if (it != m_programs.end())
- return it->value;
-
- String vertexShader;
- String fragmentShader;
- getShaderSpec(key, vertexShader, fragmentShader);
- RefPtr<TextureMapperShaderProgram> program = TextureMapperShaderProgram::create(m_context, vertexShader, fragmentShader);
- m_programs.add(key, program);
- return program;
-}
-};
-
-#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.cpp
new file mode 100644
index 000000000..3f64c4b8a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.cpp
@@ -0,0 +1,382 @@
+/*
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2012 Igalia S.L.
+ Copyright (C) 2011 Google Inc. All rights reserved.
+
+ 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 "TextureMapperShaderProgram.h"
+
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
+#include "LengthFunctions.h"
+#include "Logging.h"
+#include "TextureMapperGL.h"
+
+#include <wtf/text/StringBuilder.h>
+
+#define STRINGIFY(...) #__VA_ARGS__
+
+namespace WebCore {
+
+static inline bool compositingLogEnabled()
+{
+#if !LOG_DISABLED
+ return LogCompositing.state == WTFLogChannelOn;
+#else
+ return false;
+#endif
+}
+
+TextureMapperShaderProgram::TextureMapperShaderProgram(PassRefPtr<GraphicsContext3D> context, const String& vertex, const String& fragment)
+ : m_context(context)
+{
+ m_vertexShader = m_context->createShader(GraphicsContext3D::VERTEX_SHADER);
+ m_fragmentShader = m_context->createShader(GraphicsContext3D::FRAGMENT_SHADER);
+ m_context->shaderSource(m_vertexShader, vertex);
+ m_context->shaderSource(m_fragmentShader, fragment);
+ m_id = m_context->createProgram();
+ m_context->compileShader(m_vertexShader);
+ m_context->compileShader(m_fragmentShader);
+ m_context->attachShader(m_id, m_vertexShader);
+ m_context->attachShader(m_id, m_fragmentShader);
+ m_context->linkProgram(m_id);
+
+ if (!compositingLogEnabled())
+ return;
+
+ if (m_context->getError() == GraphicsContext3D::NO_ERROR)
+ return;
+
+ String log = m_context->getShaderInfoLog(m_vertexShader);
+ LOG(Compositing, "Vertex shader log: %s\n", log.utf8().data());
+ log = m_context->getShaderInfoLog(m_fragmentShader);
+ LOG(Compositing, "Fragment shader log: %s\n", log.utf8().data());
+ log = m_context->getProgramInfoLog(m_id);
+ LOG(Compositing, "Program log: %s\n", log.utf8().data());
+}
+
+void TextureMapperShaderProgram::setMatrix(GC3Duint location, const TransformationMatrix& matrix)
+{
+ GC3Dfloat matrixAsFloats[] = {
+ GC3Dfloat(matrix.m11()), GC3Dfloat(matrix.m12()), GC3Dfloat(matrix.m13()), GC3Dfloat(matrix.m14()),
+ GC3Dfloat(matrix.m21()), GC3Dfloat(matrix.m22()), GC3Dfloat(matrix.m23()), GC3Dfloat(matrix.m24()),
+ GC3Dfloat(matrix.m31()), GC3Dfloat(matrix.m32()), GC3Dfloat(matrix.m33()), GC3Dfloat(matrix.m34()),
+ GC3Dfloat(matrix.m41()), GC3Dfloat(matrix.m42()), GC3Dfloat(matrix.m43()), GC3Dfloat(matrix.m44())
+ };
+
+ m_context->uniformMatrix4fv(location, 1, false, matrixAsFloats);
+}
+
+GC3Duint TextureMapperShaderProgram::getLocation(const AtomicString& name, VariableType type)
+{
+ HashMap<AtomicString, GC3Duint>::iterator it = m_variables.find(name);
+ if (it != m_variables.end())
+ return it->value;
+
+ GC3Duint location = 0;
+ switch (type) {
+ case UniformVariable:
+ location = m_context->getUniformLocation(m_id, name);
+ break;
+ case AttribVariable:
+ location = m_context->getAttribLocation(m_id, name);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ m_variables.add(name, location);
+ return location;
+}
+
+TextureMapperShaderProgram::~TextureMapperShaderProgram()
+{
+ Platform3DObject programID = m_id;
+ if (!programID)
+ return;
+
+ m_context->detachShader(programID, m_vertexShader);
+ m_context->deleteShader(m_vertexShader);
+ m_context->detachShader(programID, m_fragmentShader);
+ m_context->deleteShader(m_fragmentShader);
+ m_context->deleteProgram(programID);
+}
+
+#define GLSL_DIRECTIVE(...) "#"#__VA_ARGS__"\n"
+static const char* vertexTemplate =
+ STRINGIFY(
+ attribute vec4 a_vertex;
+ uniform mat4 u_modelViewMatrix;
+ uniform mat4 u_projectionMatrix;
+ uniform mat4 u_textureSpaceMatrix;
+
+ varying vec2 v_texCoord;
+ varying float v_antialias;
+
+ void noop(inout vec2 dummyParameter) { }
+
+ vec4 toViewportSpace(vec2 pos) { return vec4(pos, 0., 1.) * u_modelViewMatrix; }
+
+ // This function relies on the assumption that we get edge triangles with control points,
+ // a control point being the nearest point to the coordinate that is on the edge.
+ void applyAntialiasing(inout vec2 position)
+ {
+ // We count on the fact that quad passed in is always a unit rect,
+ // and the transformation matrix applies the real rect.
+ const vec2 center = vec2(0.5, 0.5);
+ const float antialiasInflationDistance = 1.;
+
+ // We pass the control point as the zw coordinates of the vertex.
+ // The control point is the point on the edge closest to the current position.
+ // The control point is used to compute the antialias value.
+ vec2 controlPoint = a_vertex.zw;
+
+ // First we calculate the distance in viewport space.
+ vec4 centerInViewportCoordinates = toViewportSpace(center);
+ vec4 controlPointInViewportCoordinates = toViewportSpace(controlPoint);
+ float viewportSpaceDistance = distance(centerInViewportCoordinates, controlPointInViewportCoordinates);
+
+ // We add the inflation distance to the computed distance, and compute the ratio.
+ float inflationRatio = (viewportSpaceDistance + antialiasInflationDistance) / viewportSpaceDistance;
+
+ // v_antialias needs to be 0 for the outer edge and 1. for the inner edge.
+ // Since the controlPoint is equal to the position in the edge vertices, the value is always 0 for those.
+ // For the center point, the distance is always 0.5, so we normalize to 1. by multiplying by 2.
+ // By multplying by inflationRatio and dividing by (inflationRatio - 1),
+ // We make sure that the varying interpolates between 0 (outer edge), 1 (inner edge) and n > 1 (center).
+ v_antialias = distance(controlPoint, position) * 2. * inflationRatio / (inflationRatio - 1.);
+
+ // Now inflate the actual position. By using this formula instead of inflating position directly,
+ // we ensure that the center vertex is never inflated.
+ position = center + (position - center) * inflationRatio;
+ }
+
+ void main(void)
+ {
+ vec2 position = a_vertex.xy;
+ applyAntialiasingIfNeeded(position);
+
+ // The texture position needs to be clamped to 0..1 before the texture matrix is applied.
+ vec4 clampedPosition = clamp(vec4(position, 0., 1.), 0., 1.);
+ v_texCoord = (u_textureSpaceMatrix * clampedPosition).xy;
+ gl_Position = u_projectionMatrix * u_modelViewMatrix * vec4(position, 0., 1.);
+ }
+ );
+
+#define RECT_TEXTURE_DIRECTIVE \
+ GLSL_DIRECTIVE(ifdef ENABLE_Rect) \
+ GLSL_DIRECTIVE(define SamplerType sampler2DRect) \
+ GLSL_DIRECTIVE(define SamplerFunction texture2DRect) \
+ GLSL_DIRECTIVE(else) \
+ GLSL_DIRECTIVE(define SamplerType sampler2D) \
+ GLSL_DIRECTIVE(define SamplerFunction texture2D) \
+ GLSL_DIRECTIVE(endif)
+
+#define ENABLE_APPLIER(Name) "#define ENABLE_"#Name"\n#define apply"#Name"IfNeeded apply"#Name"\n"
+#define DISABLE_APPLIER(Name) "#define apply"#Name"IfNeeded noop\n"
+#define BLUR_CONSTANTS \
+ GLSL_DIRECTIVE(define GAUSSIAN_KERNEL_HALF_WIDTH 11) \
+ GLSL_DIRECTIVE(define GAUSSIAN_KERNEL_STEP 0.2)
+
+
+static const char* fragmentTemplate =
+ RECT_TEXTURE_DIRECTIVE
+ BLUR_CONSTANTS
+ STRINGIFY(
+ precision mediump float;
+ uniform SamplerType s_sampler;
+ uniform sampler2D s_contentTexture;
+ uniform float u_opacity;
+ varying float v_antialias;
+ varying vec2 v_texCoord;
+ uniform float u_filterAmount;
+ uniform vec2 u_blurRadius;
+ uniform vec2 u_shadowOffset;
+ uniform vec4 u_color;
+ uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];
+
+ void noop(inout vec4 dummyParameter) { }
+
+ float antialias() { return smoothstep(v_antialias, 0., 1.); }
+
+ void applyTexture(inout vec4 color) { color = SamplerFunction(s_sampler, v_texCoord); }
+ void applyOpacity(inout vec4 color) { color *= u_opacity; }
+ void applyAntialiasing(inout vec4 color) { color *= antialias(); }
+
+ void applyGrayscaleFilter(inout vec4 color)
+ {
+ float amount = 1.0 - u_filterAmount;
+ color = vec4((0.2126 + 0.7874 * amount) * color.r + (0.7152 - 0.7152 * amount) * color.g + (0.0722 - 0.0722 * amount) * color.b,
+ (0.2126 - 0.2126 * amount) * color.r + (0.7152 + 0.2848 * amount) * color.g + (0.0722 - 0.0722 * amount) * color.b,
+ (0.2126 - 0.2126 * amount) * color.r + (0.7152 - 0.7152 * amount) * color.g + (0.0722 + 0.9278 * amount) * color.b,
+ color.a);
+ }
+
+ void applySepiaFilter(inout vec4 color)
+ {
+ float amount = 1.0 - u_filterAmount;
+ color = vec4((0.393 + 0.607 * amount) * color.r + (0.769 - 0.769 * amount) * color.g + (0.189 - 0.189 * amount) * color.b,
+ (0.349 - 0.349 * amount) * color.r + (0.686 + 0.314 * amount) * color.g + (0.168 - 0.168 * amount) * color.b,
+ (0.272 - 0.272 * amount) * color.r + (0.534 - 0.534 * amount) * color.g + (0.131 + 0.869 * amount) * color.b,
+ color.a);
+ }
+
+ void applySaturateFilter(inout vec4 color)
+ {
+ color = vec4((0.213 + 0.787 * u_filterAmount) * color.r + (0.715 - 0.715 * u_filterAmount) * color.g + (0.072 - 0.072 * u_filterAmount) * color.b,
+ (0.213 - 0.213 * u_filterAmount) * color.r + (0.715 + 0.285 * u_filterAmount) * color.g + (0.072 - 0.072 * u_filterAmount) * color.b,
+ (0.213 - 0.213 * u_filterAmount) * color.r + (0.715 - 0.715 * u_filterAmount) * color.g + (0.072 + 0.928 * u_filterAmount) * color.b,
+ color.a);
+ }
+
+ void applyHueRotateFilter(inout vec4 color)
+ {
+ float pi = 3.14159265358979323846;
+ float c = cos(u_filterAmount * pi / 180.0);
+ float s = sin(u_filterAmount * pi / 180.0);
+ color = vec4(color.r * (0.213 + c * 0.787 - s * 0.213) + color.g * (0.715 - c * 0.715 - s * 0.715) + color.b * (0.072 - c * 0.072 + s * 0.928),
+ color.r * (0.213 - c * 0.213 + s * 0.143) + color.g * (0.715 + c * 0.285 + s * 0.140) + color.b * (0.072 - c * 0.072 - s * 0.283),
+ color.r * (0.213 - c * 0.213 - s * 0.787) + color.g * (0.715 - c * 0.715 + s * 0.715) + color.b * (0.072 + c * 0.928 + s * 0.072),
+ color.a);
+ }
+
+ float invert(float n) { return (1.0 - n) * u_filterAmount + n * (1.0 - u_filterAmount); }
+ void applyInvertFilter(inout vec4 color)
+ {
+ color = vec4(invert(color.r), invert(color.g), invert(color.b), color.a);
+ }
+
+ void applyBrightnessFilter(inout vec4 color)
+ {
+ color = vec4(color.rgb * u_filterAmount, color.a);
+ }
+
+ float contrast(float n) { return (n - 0.5) * u_filterAmount + 0.5; }
+ void applyContrastFilter(inout vec4 color)
+ {
+ color = vec4(contrast(color.r), contrast(color.g), contrast(color.b), color.a);
+ }
+
+ void applyOpacityFilter(inout vec4 color)
+ {
+ color = vec4(color.r, color.g, color.b, color.a * u_filterAmount);
+ }
+
+ vec4 sampleColorAtRadius(float radius)
+ {
+ vec2 coord = v_texCoord + radius * u_blurRadius;
+ return SamplerFunction(s_sampler, coord) * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.);
+ }
+
+ float sampleAlphaAtRadius(float radius)
+ {
+ vec2 coord = v_texCoord - u_shadowOffset + radius * u_blurRadius;
+ return SamplerFunction(s_sampler, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.);
+ }
+
+ void applyBlurFilter(inout vec4 color)
+ {
+ vec4 total = sampleColorAtRadius(0.) * u_gaussianKernel[0];
+ for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) {
+ total += sampleColorAtRadius(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
+ total += sampleColorAtRadius(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
+ }
+
+ color = total;
+ }
+
+ void applyAlphaBlur(inout vec4 color)
+ {
+ float total = sampleAlphaAtRadius(0.) * u_gaussianKernel[0];
+ for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) {
+ total += sampleAlphaAtRadius(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
+ total += sampleAlphaAtRadius(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
+ }
+
+ color *= total;
+ }
+
+ vec4 sourceOver(vec4 src, vec4 dst) { return src + dst * (1. - dst.a); }
+
+ void applyContentTexture(inout vec4 color)
+ {
+ vec4 contentColor = texture2D(s_contentTexture, v_texCoord);
+ color = sourceOver(contentColor, color);
+ }
+
+ void applySolidColor(inout vec4 color) { color *= u_color; }
+
+ void main(void)
+ {
+ vec4 color = vec4(1., 1., 1., 1.);
+ applyTextureIfNeeded(color);
+ applySolidColorIfNeeded(color);
+ applyAntialiasingIfNeeded(color);
+ applyOpacityIfNeeded(color);
+ applyGrayscaleFilterIfNeeded(color);
+ applySepiaFilterIfNeeded(color);
+ applySaturateFilterIfNeeded(color);
+ applyHueRotateFilterIfNeeded(color);
+ applyInvertFilterIfNeeded(color);
+ applyBrightnessFilterIfNeeded(color);
+ applyContrastFilterIfNeeded(color);
+ applyOpacityFilterIfNeeded(color);
+ applyBlurFilterIfNeeded(color);
+ applyAlphaBlurIfNeeded(color);
+ applyContentTextureIfNeeded(color);
+ gl_FragColor = color;
+ }
+ );
+
+PassRefPtr<TextureMapperShaderProgram> TextureMapperShaderProgram::create(PassRefPtr<GraphicsContext3D> context, TextureMapperShaderProgram::Options options)
+{
+ StringBuilder shaderBuilder;
+#define SET_APPLIER_FROM_OPTIONS(Applier) \
+ shaderBuilder.append(\
+ (options & TextureMapperShaderProgram::Applier) ? ENABLE_APPLIER(Applier) : DISABLE_APPLIER(Applier))
+
+ SET_APPLIER_FROM_OPTIONS(Texture);
+ SET_APPLIER_FROM_OPTIONS(Rect);
+ SET_APPLIER_FROM_OPTIONS(SolidColor);
+ SET_APPLIER_FROM_OPTIONS(Opacity);
+ SET_APPLIER_FROM_OPTIONS(Antialiasing);
+ SET_APPLIER_FROM_OPTIONS(GrayscaleFilter);
+ SET_APPLIER_FROM_OPTIONS(SepiaFilter);
+ SET_APPLIER_FROM_OPTIONS(SaturateFilter);
+ SET_APPLIER_FROM_OPTIONS(HueRotateFilter);
+ SET_APPLIER_FROM_OPTIONS(BrightnessFilter);
+ SET_APPLIER_FROM_OPTIONS(ContrastFilter);
+ SET_APPLIER_FROM_OPTIONS(InvertFilter);
+ SET_APPLIER_FROM_OPTIONS(OpacityFilter);
+ SET_APPLIER_FROM_OPTIONS(BlurFilter);
+ SET_APPLIER_FROM_OPTIONS(AlphaBlur);
+ SET_APPLIER_FROM_OPTIONS(ContentTexture);
+ StringBuilder vertexBuilder;
+ vertexBuilder.append(shaderBuilder.toString());
+ vertexBuilder.append(vertexTemplate);
+ shaderBuilder.append(fragmentTemplate);
+
+ String vertexSource = vertexBuilder.toString();
+ String fragmentSource = shaderBuilder.toString();
+
+ return adoptRef(new TextureMapperShaderProgram(context, vertexSource, fragmentSource));
+}
+
+}
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h
index 496b7e81b..3345fc9fe 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h
@@ -18,12 +18,12 @@
Boston, MA 02110-1301, USA.
*/
-#ifndef TextureMapperShaderManager_h
-#define TextureMapperShaderManager_h
+#ifndef TextureMapperShaderProgram_h
+#define TextureMapperShaderProgram_h
#if USE(TEXTURE_MAPPER)
#include "GraphicsContext3D.h"
-#include "TextureMapperGL.h"
+#include "TransformationMatrix.h"
#include <wtf/HashMap.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefPtr.h>
@@ -37,21 +37,37 @@ namespace WebCore {
class TextureMapperShaderProgram : public RefCounted<TextureMapperShaderProgram> {
public:
- Platform3DObject programID() const { return m_id; }
- GraphicsContext3D* context() { return m_context.get(); }
- static PassRefPtr<TextureMapperShaderProgram> create(PassRefPtr<GraphicsContext3D> context, const String& vertex, const String& fragment)
- {
- return adoptRef(new TextureMapperShaderProgram(context, vertex, fragment));
- }
+ enum Option {
+ Texture = 1L << 0,
+ Rect = 1L << 1,
+ SolidColor = 1L << 2,
+ Opacity = 1L << 3,
+ Antialiasing = 1L << 5,
+ GrayscaleFilter = 1L << 6,
+ SepiaFilter = 1L << 7,
+ SaturateFilter = 1L << 8,
+ HueRotateFilter = 1L << 9,
+ BrightnessFilter = 1L << 10,
+ ContrastFilter = 1L << 11,
+ InvertFilter = 1L << 12,
+ OpacityFilter = 1L << 13,
+ BlurFilter = 1L << 14,
+ AlphaBlur = 1L << 15,
+ ContentTexture = 1L << 16
+ };
+
+ typedef unsigned Options;
+ static PassRefPtr<TextureMapperShaderProgram> create(PassRefPtr<GraphicsContext3D>, Options);
virtual ~TextureMapperShaderProgram();
+ Platform3DObject programID() const { return m_id; }
+ GraphicsContext3D* context() { return m_context.get(); }
TEXMAP_DECLARE_ATTRIBUTE(vertex)
- TEXMAP_DECLARE_ATTRIBUTE(texCoord)
- TEXMAP_DECLARE_UNIFORM(matrix)
- TEXMAP_DECLARE_UNIFORM(flip)
- TEXMAP_DECLARE_UNIFORM(samplerSize)
+ TEXMAP_DECLARE_UNIFORM(modelViewMatrix)
+ TEXMAP_DECLARE_UNIFORM(projectionMatrix)
+ TEXMAP_DECLARE_UNIFORM(textureSpaceMatrix)
TEXMAP_DECLARE_UNIFORM(opacity)
TEXMAP_DECLARE_UNIFORM(color)
TEXMAP_DECLARE_UNIFORM(expandedQuadEdgesInScreenSpace)
@@ -59,14 +75,15 @@ public:
TEXMAP_DECLARE_SAMPLER(mask)
#if ENABLE(CSS_FILTERS)
- TEXMAP_DECLARE_UNIFORM(amount)
+ TEXMAP_DECLARE_UNIFORM(filterAmount)
TEXMAP_DECLARE_UNIFORM(gaussianKernel)
TEXMAP_DECLARE_UNIFORM(blurRadius)
- TEXMAP_DECLARE_UNIFORM(shadowColor)
TEXMAP_DECLARE_UNIFORM(shadowOffset)
TEXMAP_DECLARE_SAMPLER(contentTexture)
#endif
+ void setMatrix(GC3Duint, const TransformationMatrix&);
+
private:
TextureMapperShaderProgram(PassRefPtr<GraphicsContext3D>, const String& vertexShaderSource, const String& fragmentShaderSource);
Platform3DObject m_vertexShader;
@@ -80,43 +97,7 @@ private:
HashMap<AtomicString, GC3Duint> m_variables;
};
-class TextureMapperShaderManager {
-public:
- enum ShaderKey {
- Invalid = 0,
- Default,
- Rect,
- Masked,
- MaskedRect,
- SolidColor,
- Antialiased,
- GrayscaleFilter,
- SepiaFilter,
- SaturateFilter,
- HueRotateFilter,
- BrightnessFilter,
- ContrastFilter,
- OpacityFilter,
- InvertFilter,
- BlurFilter,
- ShadowFilterPass1,
- ShadowFilterPass2,
- LastFilter
- };
-
- TextureMapperShaderManager() { }
- explicit TextureMapperShaderManager(GraphicsContext3D*);
- virtual ~TextureMapperShaderManager();
-
- PassRefPtr<TextureMapperShaderProgram> getShaderProgram(ShaderKey);
-
-private:
- typedef HashMap<ShaderKey, RefPtr<TextureMapperShaderProgram>, DefaultHash<int>::Hash, HashTraits<int> > TextureMapperShaderProgramMap;
- TextureMapperShaderProgramMap m_programs;
- RefPtr<GraphicsContext3D> m_context;
-};
-
}
#endif
-#endif // TextureMapperShaderManager_h
+#endif // TextureMapperShaderProgram_h
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.cpp
new file mode 100644
index 000000000..8d38776e9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.cpp
@@ -0,0 +1,54 @@
+/*
+ Copyright (C) 2013 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"
+
+#if USE(ACCELERATED_COMPOSITING) && USE(GRAPHICS_SURFACE)
+#include "TextureMapperSurfaceBackingStore.h"
+
+#include "GraphicsSurface.h"
+
+namespace WebCore {
+
+void TextureMapperSurfaceBackingStore::setGraphicsSurface(PassRefPtr<GraphicsSurface> surface)
+{
+ m_graphicsSurface = surface;
+}
+
+void TextureMapperSurfaceBackingStore::swapBuffersIfNeeded(uint32_t)
+{
+ if (m_graphicsSurface)
+ m_graphicsSurface->swapBuffers();
+}
+
+PassRefPtr<BitmapTexture> TextureMapperSurfaceBackingStore::texture() const
+{
+ // FIXME: Instead of just returning an empty texture, we should wrap the texture contents into a BitmapTexture.
+ RefPtr<BitmapTexture> emptyTexture;
+ return emptyTexture;
+}
+
+void TextureMapperSurfaceBackingStore::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity)
+{
+ if (m_graphicsSurface)
+ m_graphicsSurface->paintToTextureMapper(textureMapper, targetRect, transform, opacity);
+}
+
+} // namespace WebCore
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.h b/Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.h
new file mode 100644
index 000000000..793c61dc3
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperSurfaceBackingStore.h
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2013 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 TextureMapperSurfaceBackingStore_h
+#define TextureMapperSurfaceBackingStore_h
+
+#if USE(ACCELERATED_COMPOSITING) && USE(GRAPHICS_SURFACE)
+
+#include "GraphicsSurface.h"
+#include "TextureMapperBackingStore.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class TextureMapper;
+class FloatRect;
+
+class TextureMapperSurfaceBackingStore : public TextureMapperBackingStore {
+public:
+ static PassRefPtr<TextureMapperSurfaceBackingStore> create() { return adoptRef(new TextureMapperSurfaceBackingStore); }
+ void setGraphicsSurface(PassRefPtr<GraphicsSurface>);
+ void swapBuffersIfNeeded(uint32_t frontBuffer);
+ virtual PassRefPtr<BitmapTexture> texture() const;
+ virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float);
+ virtual ~TextureMapperSurfaceBackingStore() { }
+
+private:
+ TextureMapperSurfaceBackingStore()
+ : TextureMapperBackingStore()
+ { }
+
+ RefPtr<GraphicsSurface> m_graphicsSurface;
+};
+
+}
+
+#endif
+
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperTile.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperTile.cpp
new file mode 100644
index 000000000..2ea7fb6ed
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperTile.cpp
@@ -0,0 +1,79 @@
+/*
+ Copyright (C) 2013 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"
+
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
+#include "TextureMapperTile.h"
+
+#include "Image.h"
+#include "TextureMapper.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class GraphicsLayer;
+
+void TextureMapperTile::updateContents(TextureMapper* textureMapper, Image* image, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
+{
+ IntRect targetRect = enclosingIntRect(m_rect);
+ targetRect.intersect(dirtyRect);
+ if (targetRect.isEmpty())
+ return;
+ IntPoint sourceOffset = targetRect.location();
+
+ // Normalize sourceRect to the buffer's coordinates.
+ sourceOffset.move(-dirtyRect.x(), -dirtyRect.y());
+
+ // 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(), image->currentFrameKnownToBeOpaque() ? 0 : BitmapTexture::SupportsAlpha);
+ }
+
+ 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, const unsigned exposedEdges)
+{
+ if (texture().get())
+ textureMapper->drawTexture(*texture().get(), rect(), transform, opacity, exposedEdges);
+}
+
+} // namespace WebCore
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperTile.h b/Source/WebCore/platform/graphics/texmap/TextureMapperTile.h
new file mode 100644
index 000000000..ee6809f20
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperTile.h
@@ -0,0 +1,60 @@
+/*
+ Copyright (C) 2013 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 TextureMapperTile_h
+#define TextureMapperTile_h
+
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
+
+#include "FloatRect.h"
+#include "Image.h"
+#include "TextureMapper.h"
+#include "TextureMapperPlatformLayer.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class GraphicsLayer;
+
+class TextureMapperTile {
+public:
+ inline PassRefPtr<BitmapTexture> texture() const { return m_texture; }
+ inline FloatRect rect() const { return m_rect; }
+ inline void setTexture(BitmapTexture* texture) { m_texture = texture; }
+ 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, const unsigned exposedEdges);
+ virtual ~TextureMapperTile() { }
+
+ explicit TextureMapperTile(const FloatRect& rect)
+ : m_rect(rect)
+ {
+ }
+
+private:
+ RefPtr<BitmapTexture> m_texture;
+ FloatRect m_rect;
+};
+
+}
+#endif
+
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.cpp
new file mode 100644
index 000000000..ef564023d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.cpp
@@ -0,0 +1,162 @@
+/*
+ Copyright (C) 2012 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"
+
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
+#include "TextureMapperTiledBackingStore.h"
+
+#include "ImageBuffer.h"
+#include "TextureMapper.h"
+
+namespace WebCore {
+
+class GraphicsLayer;
+
+TextureMapperTiledBackingStore::TextureMapperTiledBackingStore()
+{
+}
+
+void TextureMapperTiledBackingStore::updateContentsFromImageIfNeeded(TextureMapper* textureMapper)
+{
+ if (!m_image)
+ return;
+
+ updateContents(textureMapper, m_image.get(), m_image->size(), m_image->rect(), BitmapTexture::UpdateCannotModifyOriginalImageData);
+ m_image.clear();
+}
+
+TransformationMatrix TextureMapperTiledBackingStore::adjustedTransformForRect(const FloatRect& targetRect)
+{
+ return TransformationMatrix::rectToRect(rect(), targetRect);
+}
+
+void TextureMapperTiledBackingStore::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity)
+{
+ updateContentsFromImageIfNeeded(textureMapper);
+ TransformationMatrix adjustedTransform = transform * adjustedTransformForRect(targetRect);
+ for (size_t i = 0; i < m_tiles.size(); ++i)
+ m_tiles[i].paint(textureMapper, adjustedTransform, opacity, calculateExposedTileEdges(rect(), m_tiles[i].rect()));
+}
+
+void TextureMapperTiledBackingStore::drawBorder(TextureMapper* textureMapper, const Color& borderColor, float borderWidth, const FloatRect& targetRect, const TransformationMatrix& transform)
+{
+ TransformationMatrix adjustedTransform = transform * adjustedTransformForRect(targetRect);
+ for (size_t i = 0; i < m_tiles.size(); ++i)
+ textureMapper->drawBorder(borderColor, borderWidth, m_tiles[i].rect(), adjustedTransform);
+}
+
+void TextureMapperTiledBackingStore::drawRepaintCounter(TextureMapper* textureMapper, int repaintCount, const Color& borderColor, const FloatRect& targetRect, const TransformationMatrix& transform)
+{
+ TransformationMatrix adjustedTransform = transform * adjustedTransformForRect(targetRect);
+ for (size_t i = 0; i < m_tiles.size(); ++i)
+ textureMapper->drawNumber(repaintCount, borderColor, m_tiles[i].rect().location(), adjustedTransform);
+}
+
+void TextureMapperTiledBackingStore::createOrDestroyTilesIfNeeded(const FloatSize& size, const IntSize& tileSize, bool hasAlpha)
+{
+ if (size == m_size)
+ return;
+
+ m_size = size;
+
+ Vector<FloatRect> tileRectsToAdd;
+ Vector<int> tileIndicesToRemove;
+ static const size_t TileEraseThreshold = 6;
+
+ // This method recycles tiles. We check which tiles we need to add, which to remove, and use as many
+ // removable tiles as replacement for new tiles when possible.
+ for (float y = 0; y < m_size.height(); y += tileSize.height()) {
+ for (float x = 0; x < m_size.width(); x += tileSize.width()) {
+ FloatRect tileRect(x, y, tileSize.width(), tileSize.height());
+ tileRect.intersect(rect());
+ tileRectsToAdd.append(tileRect);
+ }
+ }
+
+ // Check which tiles need to be removed, and which already exist.
+ for (int i = m_tiles.size() - 1; i >= 0; --i) {
+ FloatRect oldTile = m_tiles[i].rect();
+ bool existsAlready = false;
+
+ for (int j = tileRectsToAdd.size() - 1; j >= 0; --j) {
+ FloatRect newTile = tileRectsToAdd[j];
+ if (oldTile != newTile)
+ continue;
+
+ // A tile that we want to add already exists, no need to add or remove it.
+ existsAlready = true;
+ tileRectsToAdd.remove(j);
+ break;
+ }
+
+ // This tile is not needed.
+ if (!existsAlready)
+ tileIndicesToRemove.append(i);
+ }
+
+ // Recycle removable tiles to be used for newly requested tiles.
+ for (size_t i = 0; i < tileRectsToAdd.size(); ++i) {
+ if (!tileIndicesToRemove.isEmpty()) {
+ // We recycle an existing tile for usage with a new tile rect.
+ TextureMapperTile& tile = m_tiles[tileIndicesToRemove.last()];
+ tileIndicesToRemove.removeLast();
+ tile.setRect(tileRectsToAdd[i]);
+
+ if (tile.texture())
+ tile.texture()->reset(enclosingIntRect(tile.rect()).size(), hasAlpha ? BitmapTexture::SupportsAlpha : 0);
+ continue;
+ }
+
+ m_tiles.append(TextureMapperTile(tileRectsToAdd[i]));
+ }
+
+ // Remove unnecessary tiles, if they weren't recycled.
+ // We use a threshold to make sure we don't create/destroy tiles too eagerly.
+ for (size_t i = 0; i < tileIndicesToRemove.size() && m_tiles.size() > TileEraseThreshold; ++i)
+ m_tiles.remove(tileIndicesToRemove[i]);
+}
+
+void TextureMapperTiledBackingStore::updateContents(TextureMapper* textureMapper, Image* image, const FloatSize& totalSize, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
+{
+ createOrDestroyTilesIfNeeded(totalSize, textureMapper->maxTextureSize(), !image->currentFrameKnownToBeOpaque());
+ for (size_t i = 0; i < m_tiles.size(); ++i)
+ 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) {
+ RefPtr<BitmapTexture> texture = m_tiles[i].texture();
+ if (texture)
+ return texture;
+ }
+
+ return PassRefPtr<BitmapTexture>();
+}
+
+} // namespace WebCore
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.h b/Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.h
new file mode 100644
index 000000000..9b8568463
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.h
@@ -0,0 +1,64 @@
+/*
+ Copyright (C) 2013 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 TextureMapperTiledBackingStore_h
+#define TextureMapperTiledBackingStore_h
+
+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
+
+#include "FloatRect.h"
+#include "Image.h"
+#include "TextureMapperBackingStore.h"
+#include "TextureMapperTile.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class TextureMapper;
+
+class TextureMapperTiledBackingStore : public TextureMapperBackingStore {
+public:
+ static PassRefPtr<TextureMapperTiledBackingStore> create() { return adoptRef(new TextureMapperTiledBackingStore); }
+ virtual ~TextureMapperTiledBackingStore() { }
+
+ virtual PassRefPtr<BitmapTexture> texture() const OVERRIDE;
+ virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float) OVERRIDE;
+ virtual void drawBorder(TextureMapper*, const Color&, float borderWidth, const FloatRect&, const TransformationMatrix&) OVERRIDE;
+ virtual void drawRepaintCounter(TextureMapper*, int repaintCount, const Color&, const FloatRect&, const TransformationMatrix&) 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; }
+
+private:
+ TextureMapperTiledBackingStore();
+ void createOrDestroyTilesIfNeeded(const FloatSize& backingStoreSize, const IntSize& tileSize, bool hasAlpha);
+ void updateContentsFromImageIfNeeded(TextureMapper*);
+ TransformationMatrix adjustedTransformForRect(const FloatRect&);
+ inline FloatRect rect() const { return FloatRect(FloatPoint::zero(), m_size); }
+
+ Vector<TextureMapperTile> m_tiles;
+ FloatSize m_size;
+ RefPtr<Image> m_image;
+};
+
+} // namespace WebCore
+#endif
+
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/AreaAllocator.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/AreaAllocator.cpp
new file mode 100644
index 000000000..9f54185b9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/AreaAllocator.cpp
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2012 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 Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+
+#if USE(COORDINATED_GRAPHICS)
+
+#include "AreaAllocator.h"
+
+namespace WebCore {
+
+AreaAllocator::AreaAllocator(const IntSize& size)
+ : m_size(size)
+ , m_minAlloc(1, 1)
+ , m_margin(0, 0)
+{
+}
+
+AreaAllocator::~AreaAllocator()
+{
+}
+
+void AreaAllocator::expand(const IntSize& size)
+{
+ m_size = m_size.expandedTo(size);
+}
+
+void AreaAllocator::expandBy(const IntSize& size)
+{
+ m_size += size;
+}
+
+void AreaAllocator::release(const IntRect&)
+{
+}
+
+int AreaAllocator::overhead() const
+{
+ return 0;
+}
+
+IntSize AreaAllocator::roundAllocation(const IntSize& size) const
+{
+ int width = size.width() + m_margin.width();
+ int height = size.height() + m_margin.height();
+ int extra = width % m_minAlloc.width();
+ if (extra)
+ width += m_minAlloc.width() - extra;
+ extra = height % m_minAlloc.height();
+ if (extra)
+ height += m_minAlloc.height() - extra;
+
+ return IntSize(width, height);
+}
+
+GeneralAreaAllocator::GeneralAreaAllocator(const IntSize& size)
+ : AreaAllocator(nextPowerOfTwo(size))
+{
+ m_root = new Node();
+ m_root->rect = IntRect(0, 0, m_size.width(), m_size.height());
+ m_root->largestFree = m_size;
+ m_root->parent = 0;
+ m_root->left = 0;
+ m_root->right = 0;
+ m_nodeCount = 1;
+ setMinimumAllocation(IntSize(8, 8));
+}
+
+GeneralAreaAllocator::~GeneralAreaAllocator()
+{
+ freeNode(m_root);
+}
+
+void GeneralAreaAllocator::freeNode(Node* node)
+{
+ if (node) {
+ freeNode(node->left);
+ freeNode(node->right);
+ }
+ delete node;
+}
+
+void GeneralAreaAllocator::expand(const IntSize& size)
+{
+ AreaAllocator::expand(nextPowerOfTwo(size));
+
+ if (m_root->rect.size() == m_size)
+ return; // No change.
+
+ if (!m_root->left && m_root->largestFree.width() > 0) {
+ // No allocations have occurred, so just adjust the root size.
+ m_root->rect = IntRect(0, 0, m_size.width(), m_size.height());
+ m_root->largestFree = m_size;
+ return;
+ }
+
+ // Add extra nodes above the current root to expand the tree.
+ Node* oldRoot = m_root;
+ Split split;
+ if (m_size.width() >= m_size.height())
+ split = SplitOnX;
+ else
+ split = SplitOnY;
+
+ while (m_root->rect.size() != m_size) {
+ if (m_root->rect.width() == m_size.width())
+ split = SplitOnY;
+ else if (m_root->rect.height() == m_size.height())
+ split = SplitOnX;
+ Node* parent = new Node();
+ Node* right = new Node();
+ m_nodeCount += 2;
+ m_root->parent = parent;
+ parent->parent = 0;
+ parent->left = m_root;
+ parent->right = right;
+ parent->largestFree = m_root->rect.size();
+ right->parent = parent;
+ right->left = 0;
+ right->right = 0;
+ right->largestFree = m_root->rect.size();
+ if (split == SplitOnX) {
+ parent->rect = IntRect(m_root->rect.x(), m_root->rect.y(),
+ m_root->rect.width() * 2, m_root->rect.height());
+ right->rect = IntRect(m_root->rect.x() + m_root->rect.width(), m_root->rect.y(),
+ m_root->rect.width(), m_root->rect.height());
+ } else {
+ parent->rect = IntRect(m_root->rect.x(), m_root->rect.y(),
+ m_root->rect.width(), m_root->rect.height() * 2);
+ right->rect = IntRect(m_root->rect.x(), m_root->rect.y() + m_root->rect.width(),
+ m_root->rect.width(), m_root->rect.height());
+ }
+ split = (split == SplitOnX ? SplitOnY : SplitOnX);
+ m_root = parent;
+ }
+ updateLargestFree(oldRoot);
+}
+
+static inline bool fitsWithin(const IntSize& size1, const IntSize& size2)
+{
+ return size1.width() <= size2.width() && size1.height() <= size2.height();
+}
+
+IntRect GeneralAreaAllocator::allocate(const IntSize& size)
+{
+ IntSize rounded = roundAllocation(size);
+ rounded = nextPowerOfTwo(rounded);
+ if (rounded.width() <= 0 || rounded.width() > m_size.width()
+ || rounded.height() <= 0 || rounded.height() > m_size.height())
+ return IntRect();
+
+ IntPoint point = allocateFromNode(rounded, m_root);
+ if (point.x() >= 0)
+ return IntRect(point, size);
+ return IntRect();
+}
+
+IntPoint GeneralAreaAllocator::allocateFromNode(const IntSize& size, Node* node)
+{
+ // Find the best node to insert into, which should be
+ // a node with the least amount of unused space that is
+ // big enough to contain the requested size.
+ while (node) {
+ // Go down a level and determine if the left or right
+ // sub-tree contains the best chance of allocation.
+ Node* left = node->left;
+ Node* right = node->right;
+ if (left && fitsWithin(size, left->largestFree)) {
+ if (right && fitsWithin(size, right->largestFree)) {
+ if (left->largestFree.width() < right->largestFree.width()
+ || left->largestFree.height() < right->largestFree.height()) {
+ // The largestFree values may be a little oversized,
+ // so try the left sub-tree and then the right sub-tree.
+ IntPoint point = allocateFromNode(size, left);
+ if (point.x() >= 0)
+ return point;
+ return allocateFromNode(size, right);
+ }
+ node = right;
+ } else
+ node = left;
+ } else if (right && fitsWithin(size, right->largestFree))
+ node = right;
+ else if (left || right) {
+ // Neither sub-node has enough space to allocate from.
+ return IntPoint(-1, -1);
+ } else if (fitsWithin(size, node->largestFree)) {
+ // Do we need to split this node into smaller pieces?
+ Split split;
+ if (fitsWithin(IntSize(size.width() * 2, size.height() * 2), node->largestFree)) {
+ // Split in either direction: choose the inverse of
+ // the parent node's split direction to try to balance
+ // out the wasted space as further subdivisions happen.
+ if (node->parent
+ && node->parent->left->rect.x() == node->parent->right->rect.x())
+ split = SplitOnX;
+ else if (node->parent)
+ split = SplitOnY;
+ else if (node->rect.width() >= node->rect.height())
+ split = SplitOnX;
+ else
+ split = SplitOnY;
+ } else if (fitsWithin(IntSize(size.width() * 2, size.height()), node->largestFree)) {
+ // Split along the X direction.
+ split = SplitOnX;
+ } else if (fitsWithin(IntSize(size.width(), size.height() * 2), node->largestFree)) {
+ // Split along the Y direction.
+ split = SplitOnY;
+ } else {
+ // Cannot split further - allocate this node.
+ node->largestFree = IntSize(0, 0);
+ updateLargestFree(node);
+ return node->rect.location();
+ }
+
+ // Split the node, then go around again using the left sub-tree.
+ node = splitNode(node, split);
+ } else {
+ // Cannot possibly fit into this node.
+ break;
+ }
+ }
+ return IntPoint(-1, -1);
+}
+
+GeneralAreaAllocator::Node* GeneralAreaAllocator::splitNode
+ (Node* node, Split split)
+{
+ Node* left = new Node();
+ Node* right = new Node();
+ m_nodeCount += 2;
+ left->parent = node;
+ left->left = 0;
+ left->right = 0;
+ right->parent = node;
+ right->left = 0;
+ right->right = 0;
+ node->left = left;
+ node->right = right;
+
+ if (split == SplitOnX) {
+ left->rect = IntRect(node->rect.x(), node->rect.y(),
+ node->rect.width() / 2, node->rect.height());
+ right->rect = IntRect(left->rect.maxX(), node->rect.y(),
+ node->rect.width() / 2, node->rect.height());
+ } else {
+ left->rect = IntRect(node->rect.x(), node->rect.y(),
+ node->rect.width(), node->rect.height() / 2);
+ right->rect = IntRect(node->rect.x(), left->rect.maxY(),
+ node->rect.width(), node->rect.height() / 2);
+ }
+
+ left->largestFree = left->rect.size();
+ right->largestFree = right->rect.size();
+ node->largestFree = right->largestFree;
+ return left;
+}
+
+void GeneralAreaAllocator::updateLargestFree(Node* node)
+{
+ while ((node = node->parent)) {
+ node->largestFree = IntSize(
+ std::max(node->left->largestFree.width(), node->right->largestFree.width()),
+ std::max(node->left->largestFree.height(), node->right->largestFree.height())
+ );
+ }
+}
+
+void GeneralAreaAllocator::release(const IntRect& rect)
+{
+ // Locate the node that contains the allocated region.
+ Node* node = m_root;
+ IntPoint point = rect.location();
+ while (node) {
+ if (node->left && node->left->rect.contains(point))
+ node = node->left;
+ else if (node->right && node->right->rect.contains(point))
+ node = node->right;
+ else if (node->rect.contains(point))
+ break;
+ else
+ return; // Point is completely outside the tree.
+ }
+ if (!node)
+ return;
+
+ // Mark the node as free and then work upwards through the tree
+ // recombining and deleting nodes until we reach a sibling
+ // that is still allocated.
+ node->largestFree = node->rect.size();
+ while (node->parent) {
+ if (node->parent->left == node) {
+ if (node->parent->right->largestFree != node->parent->right->rect.size())
+ break;
+ } else {
+ if (node->parent->left->largestFree != node->parent->left->rect.size())
+ break;
+ }
+ node = node->parent;
+ freeNode(node->left);
+ freeNode(node->right);
+ m_nodeCount -= 2;
+ node->left = 0;
+ node->right = 0;
+ node->largestFree = node->rect.size();
+ }
+
+ // Make the rest of our ancestors have the correct "largest free size".
+ updateLargestFree(node);
+}
+
+int GeneralAreaAllocator::overhead() const
+{
+ return m_nodeCount * sizeof(Node);
+}
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/AreaAllocator.h b/Source/WebCore/platform/graphics/texmap/coordinated/AreaAllocator.h
new file mode 100644
index 000000000..4180cae23
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/AreaAllocator.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2012 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 Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef AreaAllocator_h
+#define AreaAllocator_h
+
+#include "IntPoint.h"
+#include "IntRect.h"
+#include "IntSize.h"
+
+#if USE(COORDINATED_GRAPHICS)
+
+namespace WebCore {
+
+inline int nextPowerOfTwo(int number)
+{
+ // This is a fast trick to get nextPowerOfTwo for an integer.
+ --number;
+ number |= number >> 1;
+ number |= number >> 2;
+ number |= number >> 4;
+ number |= number >> 8;
+ number |= number >> 16;
+ number++;
+ return number;
+}
+
+inline IntSize nextPowerOfTwo(const IntSize& size)
+{
+ return IntSize(nextPowerOfTwo(size.width()), nextPowerOfTwo(size.height()));
+}
+
+class AreaAllocator {
+public:
+ explicit AreaAllocator(const IntSize&);
+ virtual ~AreaAllocator();
+
+ IntSize size() const { return m_size; }
+
+ IntSize minimumAllocation() const { return m_minAlloc; }
+ void setMinimumAllocation(const IntSize& size) { m_minAlloc = size; }
+
+ IntSize margin() const { return m_margin; }
+ void setMargin(const IntSize &margin) { m_margin = margin; }
+
+ virtual void expand(const IntSize&);
+ void expandBy(const IntSize&);
+
+ virtual IntRect allocate(const IntSize&) = 0;
+ virtual void release(const IntRect&);
+
+ virtual int overhead() const;
+
+protected:
+ IntSize m_size;
+ IntSize m_minAlloc;
+ IntSize m_margin;
+
+ IntSize roundAllocation(const IntSize&) const;
+};
+
+class GeneralAreaAllocator : public AreaAllocator {
+public:
+ explicit GeneralAreaAllocator(const IntSize&);
+ virtual ~GeneralAreaAllocator();
+
+ void expand(const IntSize&);
+ IntRect allocate(const IntSize&);
+ void release(const IntRect&);
+ int overhead() const;
+
+private:
+ enum Split { SplitOnX, SplitOnY };
+
+ struct Node {
+ IntRect rect;
+ IntSize largestFree;
+ Node* parent;
+ Node* left;
+ Node* right;
+ };
+
+ Node* m_root;
+ int m_nodeCount;
+
+ static void freeNode(Node*);
+ IntPoint allocateFromNode(const IntSize&, Node*);
+ Node* splitNode(Node*, Split);
+ static void updateLargestFree(Node*);
+};
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // AreaAllocator_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CompositingCoordinator.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/CompositingCoordinator.cpp
new file mode 100644
index 000000000..74cd528ec
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CompositingCoordinator.cpp
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2013 Company 100, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(COORDINATED_GRAPHICS)
+#include "CompositingCoordinator.h"
+
+#include "Frame.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "InspectorController.h"
+#include "Page.h"
+#include "Settings.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/TemporaryChange.h>
+
+namespace WebCore {
+
+PassOwnPtr<CompositingCoordinator> CompositingCoordinator::create(Page* page, CompositingCoordinator::Client* client)
+{
+ return adoptPtr(new CompositingCoordinator(page, client));
+}
+
+CompositingCoordinator::~CompositingCoordinator()
+{
+ purgeBackingStores();
+
+ LayerMap::iterator end = m_registeredLayers.end();
+ for (LayerMap::iterator it = m_registeredLayers.begin(); it != end; ++it)
+ it->value->setCoordinator(0);
+}
+
+CompositingCoordinator::CompositingCoordinator(Page* page, CompositingCoordinator::Client* client)
+ : m_page(page)
+ , m_client(client)
+ , m_rootCompositingLayer(0)
+ , m_isPurging(false)
+ , m_isFlushingLayerChanges(false)
+ , m_shouldSyncFrame(false)
+ , m_didInitializeRootCompositingLayer(false)
+ , m_releaseInactiveAtlasesTimer(this, &CompositingCoordinator::releaseInactiveAtlasesTimerFired)
+#if ENABLE(REQUEST_ANIMATION_FRAME)
+ , m_lastAnimationServiceTime(0)
+#endif
+{
+ m_page->settings()->setApplyDeviceScaleFactorInCompositor(true);
+
+ // This is a temporary way to enable this only in the GL case, until TextureMapperImageBuffer is removed.
+ // See https://bugs.webkit.org/show_bug.cgi?id=114869
+ CoordinatedGraphicsLayer::setShouldSupportContentsTiling(true);
+}
+
+void CompositingCoordinator::setRootCompositingLayer(GraphicsLayer* layer)
+{
+ if (m_rootCompositingLayer)
+ m_rootCompositingLayer->removeFromParent();
+
+ m_rootCompositingLayer = layer;
+ if (m_rootCompositingLayer)
+ m_rootLayer->addChildAtIndex(m_rootCompositingLayer, 0);
+}
+
+void CompositingCoordinator::sizeDidChange(const IntSize& newSize)
+{
+ m_rootLayer->setSize(newSize);
+ m_client->notifyFlushRequired();
+}
+
+bool CompositingCoordinator::flushPendingLayerChanges()
+{
+ TemporaryChange<bool> protector(m_isFlushingLayerChanges, true);
+
+ initializeRootCompositingLayerIfNeeded();
+
+ m_rootLayer->flushCompositingStateForThisLayerOnly();
+ m_client->didFlushRootLayer();
+
+ bool didSync = m_page->mainFrame()->view()->flushCompositingStateIncludingSubframes();
+
+ toCoordinatedGraphicsLayer(m_rootLayer.get())->updateContentBuffersIncludingSubLayers();
+ toCoordinatedGraphicsLayer(m_rootLayer.get())->syncPendingStateChangesIncludingSubLayers();
+
+ flushPendingImageBackingChanges();
+
+ if (m_shouldSyncFrame) {
+ didSync = true;
+
+ if (m_rootCompositingLayer) {
+ m_state.contentsSize = roundedIntSize(m_rootCompositingLayer->size());
+ if (CoordinatedGraphicsLayer* contentsLayer = mainContentsLayer())
+ m_state.coveredRect = contentsLayer->coverRect();
+ }
+ m_state.scrollPosition = m_visibleContentsRect.location();
+
+ m_client->commitSceneState(m_state);
+
+ clearPendingStateChanges();
+ m_shouldSyncFrame = false;
+ }
+
+ return didSync;
+}
+
+void CompositingCoordinator::syncDisplayState()
+{
+#if ENABLE(INSPECTOR)
+ m_page->inspectorController()->didBeginFrame();
+#endif
+
+#if ENABLE(REQUEST_ANIMATION_FRAME) && !USE(REQUEST_ANIMATION_FRAME_TIMER) && !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+ // Make sure that any previously registered animation callbacks are being executed before we flush the layers.
+ m_lastAnimationServiceTime = WTF::monotonicallyIncreasingTime();
+ m_page->mainFrame()->view()->serviceScriptedAnimations(m_lastAnimationServiceTime);
+#endif
+ m_page->mainFrame()->view()->updateLayoutAndStyleIfNeededRecursive();
+}
+
+#if ENABLE(REQUEST_ANIMATION_FRAME)
+double CompositingCoordinator::nextAnimationServiceTime() const
+{
+ // According to the requestAnimationFrame spec, rAF callbacks should not be faster than 60FPS.
+ static const double MinimalTimeoutForAnimations = 1. / 60.;
+ return std::max<double>(0., MinimalTimeoutForAnimations - WTF::monotonicallyIncreasingTime() + m_lastAnimationServiceTime);
+}
+#endif
+
+void CompositingCoordinator::clearPendingStateChanges()
+{
+ m_state.layersToCreate.clear();
+ m_state.layersToUpdate.clear();
+ m_state.layersToRemove.clear();
+
+ m_state.imagesToCreate.clear();
+ m_state.imagesToRemove.clear();
+ m_state.imagesToUpdate.clear();
+ m_state.imagesToClear.clear();
+
+ m_state.updateAtlasesToCreate.clear();
+ m_state.updateAtlasesToRemove.clear();
+
+#if ENABLE(CSS_SHADERS)
+ m_state.customFiltersToCreate.clear();
+ m_state.customFiltersToRemove.clear();
+#endif
+}
+
+void CompositingCoordinator::initializeRootCompositingLayerIfNeeded()
+{
+ if (m_didInitializeRootCompositingLayer)
+ return;
+
+ m_state.rootCompositingLayer = toCoordinatedGraphicsLayer(m_rootLayer.get())->id();
+ m_didInitializeRootCompositingLayer = true;
+ m_shouldSyncFrame = true;
+}
+
+void CompositingCoordinator::createRootLayer(const IntSize& size)
+{
+ ASSERT(!m_rootLayer);
+ // Create a root layer.
+ m_rootLayer = GraphicsLayer::create(this, this);
+#ifndef NDEBUG
+ m_rootLayer->setName("CompositingCoordinator root layer");
+#endif
+ m_rootLayer->setDrawsContent(false);
+ m_rootLayer->setSize(size);
+}
+
+void CompositingCoordinator::syncLayerState(CoordinatedLayerID id, CoordinatedGraphicsLayerState& state)
+{
+ m_shouldSyncFrame = true;
+ m_client->willSyncLayerState(state);
+ m_state.layersToUpdate.append(std::make_pair(id, state));
+}
+
+PassRefPtr<CoordinatedImageBacking> CompositingCoordinator::createImageBackingIfNeeded(Image* image)
+{
+ CoordinatedImageBackingID imageID = CoordinatedImageBacking::getCoordinatedImageBackingID(image);
+ ImageBackingMap::iterator it = m_imageBackings.find(imageID);
+ RefPtr<CoordinatedImageBacking> imageBacking;
+ if (it == m_imageBackings.end()) {
+ imageBacking = CoordinatedImageBacking::create(this, image);
+ m_imageBackings.add(imageID, imageBacking);
+ } else
+ imageBacking = it->value;
+
+ return imageBacking;
+}
+
+void CompositingCoordinator::createImageBacking(CoordinatedImageBackingID imageID)
+{
+ m_state.imagesToCreate.append(imageID);
+}
+
+void CompositingCoordinator::updateImageBacking(CoordinatedImageBackingID imageID, PassRefPtr<CoordinatedSurface> coordinatedSurface)
+{
+ m_shouldSyncFrame = true;
+ m_state.imagesToUpdate.append(std::make_pair(imageID, coordinatedSurface));
+}
+
+void CompositingCoordinator::clearImageBackingContents(CoordinatedImageBackingID imageID)
+{
+ m_shouldSyncFrame = true;
+ m_state.imagesToClear.append(imageID);
+}
+
+void CompositingCoordinator::removeImageBacking(CoordinatedImageBackingID imageID)
+{
+ if (m_isPurging)
+ return;
+
+ ASSERT(m_imageBackings.contains(imageID));
+ m_imageBackings.remove(imageID);
+
+ m_state.imagesToRemove.append(imageID);
+}
+
+void CompositingCoordinator::flushPendingImageBackingChanges()
+{
+ ImageBackingMap::iterator end = m_imageBackings.end();
+ for (ImageBackingMap::iterator iter = m_imageBackings.begin(); iter != end; ++iter)
+ iter->value->update();
+}
+
+void CompositingCoordinator::notifyAnimationStarted(const GraphicsLayer*, double /* time */)
+{
+}
+
+void CompositingCoordinator::notifyFlushRequired(const GraphicsLayer*)
+{
+ m_client->notifyFlushRequired();
+}
+
+
+void CompositingCoordinator::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& graphicsContext, GraphicsLayerPaintingPhase, const IntRect& clipRect)
+{
+ m_client->paintLayerContents(graphicsLayer, graphicsContext, clipRect);
+}
+
+PassOwnPtr<GraphicsLayer> CompositingCoordinator::createGraphicsLayer(GraphicsLayerClient* client)
+{
+ CoordinatedGraphicsLayer* layer = new CoordinatedGraphicsLayer(client);
+ layer->setCoordinator(this);
+ m_registeredLayers.add(layer->id(), layer);
+ m_state.layersToCreate.append(layer->id());
+ layer->setNeedsVisibleRectAdjustment();
+ m_client->notifyFlushRequired();
+ return adoptPtr(layer);
+}
+
+float CompositingCoordinator::deviceScaleFactor() const
+{
+ return m_page->deviceScaleFactor();
+}
+
+float CompositingCoordinator::pageScaleFactor() const
+{
+ return m_page->pageScaleFactor();
+}
+
+void CompositingCoordinator::createUpdateAtlas(uint32_t atlasID, PassRefPtr<CoordinatedSurface> coordinatedSurface)
+{
+ m_state.updateAtlasesToCreate.append(std::make_pair(atlasID, coordinatedSurface));
+}
+
+void CompositingCoordinator::removeUpdateAtlas(uint32_t atlasID)
+{
+ if (m_isPurging)
+ return;
+ m_state.updateAtlasesToRemove.append(atlasID);
+}
+
+FloatRect CompositingCoordinator::visibleContentsRect() const
+{
+ return m_visibleContentsRect;
+}
+
+CoordinatedGraphicsLayer* CompositingCoordinator::mainContentsLayer()
+{
+ if (!m_rootCompositingLayer)
+ return 0;
+
+ return toCoordinatedGraphicsLayer(m_rootCompositingLayer)->findFirstDescendantWithContentsRecursively();
+}
+
+void CompositingCoordinator::setVisibleContentsRect(const FloatRect& rect, const FloatPoint& trajectoryVector)
+{
+ // A zero trajectoryVector indicates that tiles all around the viewport are requested.
+ if (CoordinatedGraphicsLayer* contentsLayer = mainContentsLayer())
+ contentsLayer->setVisibleContentRectTrajectoryVector(trajectoryVector);
+
+ bool contentsRectDidChange = rect != m_visibleContentsRect;
+ if (contentsRectDidChange) {
+ m_visibleContentsRect = rect;
+
+ LayerMap::iterator end = m_registeredLayers.end();
+ for (LayerMap::iterator it = m_registeredLayers.begin(); it != end; ++it)
+ it->value->setNeedsVisibleRectAdjustment();
+ }
+
+ FrameView* view = m_page->mainFrame()->view();
+ if (view->useFixedLayout()) {
+ // Round the rect instead of enclosing it to make sure that its size stays
+ // the same while panning. This can have nasty effects on layout.
+ view->setFixedVisibleContentRect(roundedIntRect(rect));
+ }
+}
+
+void CompositingCoordinator::deviceOrPageScaleFactorChanged()
+{
+ m_rootLayer->deviceOrPageScaleFactorChanged();
+}
+
+void CompositingCoordinator::detachLayer(CoordinatedGraphicsLayer* layer)
+{
+ if (m_isPurging)
+ return;
+
+ m_registeredLayers.remove(layer->id());
+
+ size_t index = m_state.layersToCreate.find(layer->id());
+ if (index != notFound) {
+ m_state.layersToCreate.remove(index);
+ return;
+ }
+
+ m_state.layersToRemove.append(layer->id());
+ m_client->notifyFlushRequired();
+}
+
+void CompositingCoordinator::commitScrollOffset(uint32_t layerID, const WebCore::IntSize& offset)
+{
+ LayerMap::iterator i = m_registeredLayers.find(layerID);
+ if (i == m_registeredLayers.end())
+ return;
+
+ i->value->commitScrollOffset(offset);
+}
+
+void CompositingCoordinator::renderNextFrame()
+{
+ for (unsigned i = 0; i < m_updateAtlases.size(); ++i)
+ m_updateAtlases[i]->didSwapBuffers();
+}
+
+void CompositingCoordinator::purgeBackingStores()
+{
+ TemporaryChange<bool> purgingToggle(m_isPurging, true);
+
+ LayerMap::iterator end = m_registeredLayers.end();
+ for (LayerMap::iterator it = m_registeredLayers.begin(); it != end; ++it)
+ it->value->purgeBackingStores();
+
+ m_imageBackings.clear();
+ m_updateAtlases.clear();
+}
+
+bool CompositingCoordinator::paintToSurface(const IntSize& size, CoordinatedSurface::Flags flags, uint32_t& atlasID, IntPoint& offset, CoordinatedSurface::Client* client)
+{
+ for (unsigned i = 0; i < m_updateAtlases.size(); ++i) {
+ UpdateAtlas* atlas = m_updateAtlases[i].get();
+ if (atlas->supportsAlpha() == (flags & CoordinatedSurface::SupportsAlpha)) {
+ // This will be false if there is no available buffer space.
+ if (atlas->paintOnAvailableBuffer(size, atlasID, offset, client))
+ return true;
+ }
+ }
+
+ static const int ScratchBufferDimension = 1024; // Should be a power of two.
+ m_updateAtlases.append(adoptPtr(new UpdateAtlas(this, ScratchBufferDimension, flags)));
+ scheduleReleaseInactiveAtlases();
+ return m_updateAtlases.last()->paintOnAvailableBuffer(size, atlasID, offset, client);
+}
+
+const double ReleaseInactiveAtlasesTimerInterval = 0.5;
+
+void CompositingCoordinator::scheduleReleaseInactiveAtlases()
+{
+ if (!m_releaseInactiveAtlasesTimer.isActive())
+ m_releaseInactiveAtlasesTimer.startRepeating(ReleaseInactiveAtlasesTimerInterval);
+}
+
+void CompositingCoordinator::releaseInactiveAtlasesTimerFired(Timer<CompositingCoordinator>*)
+{
+ // We always want to keep one atlas for root contents layer.
+ OwnPtr<UpdateAtlas> atlasToKeepAnyway;
+ bool foundActiveAtlasForRootContentsLayer = false;
+ for (int i = m_updateAtlases.size() - 1; i >= 0; --i) {
+ UpdateAtlas* atlas = m_updateAtlases[i].get();
+ if (!atlas->isInUse())
+ atlas->addTimeInactive(ReleaseInactiveAtlasesTimerInterval);
+ bool usableForRootContentsLayer = !atlas->supportsAlpha();
+ if (atlas->isInactive()) {
+ if (!foundActiveAtlasForRootContentsLayer && !atlasToKeepAnyway && usableForRootContentsLayer)
+ atlasToKeepAnyway = m_updateAtlases[i].release();
+ m_updateAtlases.remove(i);
+ } else if (usableForRootContentsLayer)
+ foundActiveAtlasForRootContentsLayer = true;
+ }
+
+ if (!foundActiveAtlasForRootContentsLayer && atlasToKeepAnyway)
+ m_updateAtlases.append(atlasToKeepAnyway.release());
+
+ if (m_updateAtlases.size() <= 1)
+ m_releaseInactiveAtlasesTimer.stop();
+}
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CompositingCoordinator.h b/Source/WebCore/platform/graphics/texmap/coordinated/CompositingCoordinator.h
new file mode 100644
index 000000000..fd41cb873
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CompositingCoordinator.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2013 Company 100, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CompositingCoordinator_h
+#define CompositingCoordinator_h
+
+#if USE(COORDINATED_GRAPHICS)
+
+#include "CoordinatedGraphicsLayer.h"
+#include "CoordinatedGraphicsState.h"
+#include "CoordinatedImageBacking.h"
+#include "FloatPoint.h"
+#include "GraphicsLayerClient.h"
+#include "GraphicsLayerFactory.h"
+#include "IntRect.h"
+#include "Timer.h"
+#include "UpdateAtlas.h"
+#include <wtf/OwnPtr.h>
+
+#if ENABLE(CSS_SHADERS)
+#include "FilterOperations.h"
+#endif
+
+namespace WebCore {
+
+class Page;
+class GraphicsContext;
+class GraphicsLayer;
+class CoordinatedSurface;
+
+class CompositingCoordinator : public GraphicsLayerClient
+ , public CoordinatedGraphicsLayerClient
+ , public CoordinatedImageBacking::Client
+ , public UpdateAtlas::Client
+ , public GraphicsLayerFactory {
+ WTF_MAKE_NONCOPYABLE(CompositingCoordinator); WTF_MAKE_FAST_ALLOCATED;
+public:
+ class Client {
+ public:
+ virtual void didFlushRootLayer() = 0;
+ virtual void willSyncLayerState(CoordinatedGraphicsLayerState&) = 0;
+ virtual void notifyFlushRequired() = 0;
+ virtual void commitSceneState(const CoordinatedGraphicsState&) = 0;
+ virtual void paintLayerContents(const GraphicsLayer*, GraphicsContext&, const IntRect& clipRect) = 0;
+ };
+
+ static PassOwnPtr<CompositingCoordinator> create(Page*, CompositingCoordinator::Client*);
+ virtual ~CompositingCoordinator();
+
+ void setRootCompositingLayer(GraphicsLayer*);
+ void sizeDidChange(const IntSize& newSize);
+ void deviceOrPageScaleFactorChanged();
+
+ void setVisibleContentsRect(const FloatRect&, const FloatPoint&);
+ void renderNextFrame();
+ void purgeBackingStores();
+ void commitScrollOffset(uint32_t layerID, const IntSize& offset);
+
+ void createRootLayer(const IntSize&);
+ void clearRootLayer() { m_rootLayer = nullptr; }
+ GraphicsLayer* rootLayer() const { return m_rootLayer.get(); }
+ CoordinatedGraphicsLayer* mainContentsLayer();
+
+ bool flushPendingLayerChanges();
+ CoordinatedGraphicsState& state() { return m_state; }
+
+ void syncDisplayState();
+
+#if ENABLE(REQUEST_ANIMATION_FRAME)
+ double nextAnimationServiceTime() const;
+#endif
+
+private:
+ CompositingCoordinator(Page*, CompositingCoordinator::Client*);
+
+ // GraphicsLayerClient
+ virtual void notifyAnimationStarted(const GraphicsLayer*, double time) OVERRIDE;
+ virtual void notifyFlushRequired(const GraphicsLayer*) OVERRIDE;
+ virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& clipRect) OVERRIDE;
+ virtual float deviceScaleFactor() const OVERRIDE;
+ virtual float pageScaleFactor() const OVERRIDE;
+
+ // CoordinatedImageBacking::Client
+ virtual void createImageBacking(CoordinatedImageBackingID) OVERRIDE;
+ virtual void updateImageBacking(CoordinatedImageBackingID, PassRefPtr<CoordinatedSurface>) OVERRIDE;
+ virtual void clearImageBackingContents(CoordinatedImageBackingID) OVERRIDE;
+ virtual void removeImageBacking(CoordinatedImageBackingID) OVERRIDE;
+
+ // CoordinatedGraphicsLayerClient
+ virtual bool isFlushingLayerChanges() const OVERRIDE { return m_isFlushingLayerChanges; }
+ virtual FloatRect visibleContentsRect() const OVERRIDE;
+ virtual PassRefPtr<CoordinatedImageBacking> createImageBackingIfNeeded(Image*) OVERRIDE;
+ virtual void detachLayer(CoordinatedGraphicsLayer*) OVERRIDE;
+ virtual bool paintToSurface(const WebCore::IntSize&, WebCore::CoordinatedSurface::Flags, uint32_t& /* atlasID */, WebCore::IntPoint&, WebCore::CoordinatedSurface::Client*) OVERRIDE;
+ virtual void syncLayerState(CoordinatedLayerID, CoordinatedGraphicsLayerState&) OVERRIDE;
+
+ // UpdateAtlas::Client
+ virtual void createUpdateAtlas(uint32_t atlasID, PassRefPtr<CoordinatedSurface>) OVERRIDE;
+ virtual void removeUpdateAtlas(uint32_t atlasID) OVERRIDE;
+
+ // GraphicsLayerFactory
+ virtual PassOwnPtr<GraphicsLayer> createGraphicsLayer(GraphicsLayerClient*) OVERRIDE;
+
+ void initializeRootCompositingLayerIfNeeded();
+ void flushPendingImageBackingChanges();
+ void clearPendingStateChanges();
+
+ void scheduleReleaseInactiveAtlases();
+
+ void releaseInactiveAtlasesTimerFired(Timer<CompositingCoordinator>*);
+
+ Page* m_page;
+ CompositingCoordinator::Client* m_client;
+
+ OwnPtr<GraphicsLayer> m_rootLayer;
+ GraphicsLayer* m_rootCompositingLayer;
+
+ CoordinatedGraphicsState m_state;
+
+ typedef HashMap<CoordinatedLayerID, CoordinatedGraphicsLayer*> LayerMap;
+ LayerMap m_registeredLayers;
+ typedef HashMap<CoordinatedImageBackingID, RefPtr<CoordinatedImageBacking> > ImageBackingMap;
+ ImageBackingMap m_imageBackings;
+ Vector<OwnPtr<UpdateAtlas> > m_updateAtlases;
+
+ // We don't send the messages related to releasing resources to renderer during purging, because renderer already had removed all resources.
+ bool m_isPurging;
+ bool m_isFlushingLayerChanges;
+
+ FloatRect m_visibleContentsRect;
+
+ bool m_shouldSyncFrame;
+ bool m_didInitializeRootCompositingLayer;
+ Timer<CompositingCoordinator> m_releaseInactiveAtlasesTimer;
+
+#if ENABLE(REQUEST_ANIMATION_FRAME)
+ double m_lastAnimationServiceTime;
+#endif
+};
+
+}
+
+#endif
+
+#endif // CompositingCoordinator_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedBackingStore.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedBackingStore.cpp
new file mode 100644
index 000000000..2737ec125
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedBackingStore.cpp
@@ -0,0 +1,194 @@
+/*
+ Copyright (C) 2012 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 "CoordinatedBackingStore.h"
+
+#if USE(COORDINATED_GRAPHICS)
+#include "CoordinatedSurface.h"
+#include "GraphicsLayer.h"
+#include "TextureMapper.h"
+#include "TextureMapperGL.h"
+
+namespace WebCore {
+
+void CoordinatedBackingStoreTile::swapBuffers(TextureMapper* textureMapper)
+{
+ if (!m_surface)
+ return;
+
+ FloatRect tileRect(m_tileRect);
+ tileRect.scale(1. / m_scale);
+ bool shouldReset = false;
+ if (tileRect != rect()) {
+ setRect(tileRect);
+ shouldReset = true;
+ }
+ RefPtr<BitmapTexture> texture = this->texture();
+ if (!texture) {
+ texture = textureMapper->createTexture();
+ setTexture(texture.get());
+ shouldReset = true;
+ }
+
+ ASSERT(textureMapper->maxTextureSize().width() >= m_tileRect.size().width());
+ ASSERT(textureMapper->maxTextureSize().height() >= m_tileRect.size().height());
+ if (shouldReset)
+ texture->reset(m_tileRect.size(), m_surface->supportsAlpha());
+
+ m_surface->copyToTexture(texture, m_sourceRect, m_surfaceOffset);
+ m_surface.clear();
+}
+
+void CoordinatedBackingStoreTile::setBackBuffer(const IntRect& tileRect, const IntRect& sourceRect, PassRefPtr<CoordinatedSurface> buffer, const IntPoint& offset)
+{
+ m_sourceRect = sourceRect;
+ m_tileRect = tileRect;
+ m_surfaceOffset = offset;
+ m_surface = buffer;
+}
+
+void CoordinatedBackingStore::createTile(uint32_t id, float scale)
+{
+ m_tiles.add(id, CoordinatedBackingStoreTile(scale));
+ m_scale = scale;
+}
+
+void CoordinatedBackingStore::removeTile(uint32_t id)
+{
+ ASSERT(m_tiles.contains(id));
+ m_tilesToRemove.add(id);
+}
+
+void CoordinatedBackingStore::removeAllTiles()
+{
+ CoordinatedBackingStoreTileMap::iterator end = m_tiles.end();
+ for (CoordinatedBackingStoreTileMap::iterator it = m_tiles.begin(); it != end; ++it)
+ m_tilesToRemove.add(it->key);
+}
+
+void CoordinatedBackingStore::updateTile(uint32_t id, const IntRect& sourceRect, const IntRect& tileRect, PassRefPtr<CoordinatedSurface> backBuffer, const IntPoint& offset)
+{
+ CoordinatedBackingStoreTileMap::iterator it = m_tiles.find(id);
+ ASSERT(it != m_tiles.end());
+ it->value.setBackBuffer(tileRect, sourceRect, backBuffer, offset);
+}
+
+PassRefPtr<BitmapTexture> CoordinatedBackingStore::texture() const
+{
+ CoordinatedBackingStoreTileMap::const_iterator end = m_tiles.end();
+ for (CoordinatedBackingStoreTileMap::const_iterator it = m_tiles.begin(); it != end; ++it) {
+ RefPtr<BitmapTexture> texture = it->value.texture();
+ if (texture)
+ return texture;
+ }
+
+ return PassRefPtr<BitmapTexture>();
+}
+
+void CoordinatedBackingStore::setSize(const FloatSize& size)
+{
+ m_pendingSize = size;
+}
+
+void CoordinatedBackingStore::paintTilesToTextureMapper(Vector<TextureMapperTile*>& tiles, TextureMapper* textureMapper, const TransformationMatrix& transform, float opacity, const FloatRect& rect)
+{
+ for (size_t i = 0; i < tiles.size(); ++i)
+ tiles[i]->paint(textureMapper, transform, opacity, calculateExposedTileEdges(rect, tiles[i]->rect()));
+}
+
+TransformationMatrix CoordinatedBackingStore::adjustedTransformForRect(const FloatRect& targetRect)
+{
+ return TransformationMatrix::rectToRect(rect(), targetRect);
+}
+
+void CoordinatedBackingStore::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity)
+{
+ if (m_tiles.isEmpty())
+ return;
+ ASSERT(!m_size.isZero());
+
+ Vector<TextureMapperTile*> tilesToPaint;
+ Vector<TextureMapperTile*> previousTilesToPaint;
+
+ // We have to do this every time we paint, in case the opacity has changed.
+ CoordinatedBackingStoreTileMap::iterator end = m_tiles.end();
+ FloatRect coveredRect;
+ for (CoordinatedBackingStoreTileMap::iterator it = m_tiles.begin(); it != end; ++it) {
+ CoordinatedBackingStoreTile& tile = it->value;
+ if (!tile.texture())
+ continue;
+
+ if (tile.scale() == m_scale) {
+ tilesToPaint.append(&tile);
+ coveredRect.unite(tile.rect());
+ continue;
+ }
+
+ // Only show the previous tile if the opacity is high, otherwise effect looks like a bug.
+ // We show the previous-scale tile anyway if it doesn't intersect with any current-scale tile.
+ if (opacity < 0.95 && coveredRect.intersects(tile.rect()))
+ continue;
+
+ previousTilesToPaint.append(&tile);
+ }
+
+ // targetRect is on the contents coordinate system, so we must compare two rects on the contents coordinate system.
+ // See TiledBackingStore.
+ TransformationMatrix adjustedTransform = transform * adjustedTransformForRect(targetRect);
+
+ paintTilesToTextureMapper(previousTilesToPaint, textureMapper, adjustedTransform, opacity, rect());
+ paintTilesToTextureMapper(tilesToPaint, textureMapper, adjustedTransform, opacity, rect());
+}
+
+void CoordinatedBackingStore::drawBorder(TextureMapper* textureMapper, const Color& borderColor, float borderWidth, const FloatRect& targetRect, const TransformationMatrix& transform)
+{
+ TransformationMatrix adjustedTransform = transform * adjustedTransformForRect(targetRect);
+ CoordinatedBackingStoreTileMap::iterator end = m_tiles.end();
+ for (CoordinatedBackingStoreTileMap::iterator it = m_tiles.begin(); it != end; ++it)
+ textureMapper->drawBorder(borderColor, borderWidth, it->value.rect(), adjustedTransform);
+}
+
+void CoordinatedBackingStore::drawRepaintCounter(TextureMapper* textureMapper, int repaintCount, const Color& borderColor, const FloatRect& targetRect, const TransformationMatrix& transform)
+{
+ TransformationMatrix adjustedTransform = transform * adjustedTransformForRect(targetRect);
+ CoordinatedBackingStoreTileMap::iterator end = m_tiles.end();
+ for (CoordinatedBackingStoreTileMap::iterator it = m_tiles.begin(); it != end; ++it)
+ textureMapper->drawNumber(repaintCount, borderColor, it->value.rect().location(), adjustedTransform);
+}
+
+void CoordinatedBackingStore::commitTileOperations(TextureMapper* textureMapper)
+{
+ if (!m_pendingSize.isZero()) {
+ m_size = m_pendingSize;
+ m_pendingSize = FloatSize();
+ }
+
+ HashSet<uint32_t>::iterator tilesToRemoveEnd = m_tilesToRemove.end();
+ for (HashSet<uint32_t>::iterator it = m_tilesToRemove.begin(); it != tilesToRemoveEnd; ++it)
+ m_tiles.remove(*it);
+ m_tilesToRemove.clear();
+
+ CoordinatedBackingStoreTileMap::iterator tilesEnd = m_tiles.end();
+ for (CoordinatedBackingStoreTileMap::iterator it = m_tiles.begin(); it != tilesEnd; ++it)
+ it->value.swapBuffers(textureMapper);
+}
+
+} // namespace WebCore
+#endif // USE(COORDINATED_GRAPHICS)
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedBackingStore.h b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedBackingStore.h
new file mode 100644
index 000000000..4201454bd
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedBackingStore.h
@@ -0,0 +1,90 @@
+/*
+ Copyright (C) 2012 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 CoordinatedBackingStore_h
+#define CoordinatedBackingStore_h
+
+#if USE(COORDINATED_GRAPHICS)
+
+#include "TextureMapper.h"
+#include "TextureMapperBackingStore.h"
+#include "TextureMapperTile.h"
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+
+namespace WebCore {
+
+class CoordinatedSurface;
+
+class CoordinatedBackingStoreTile : public TextureMapperTile {
+public:
+ explicit CoordinatedBackingStoreTile(float scale = 1)
+ : TextureMapperTile(FloatRect())
+ , m_scale(scale)
+ {
+ }
+
+ inline float scale() const { return m_scale; }
+ void swapBuffers(TextureMapper*);
+ void setBackBuffer(const IntRect&, const IntRect&, PassRefPtr<CoordinatedSurface> buffer, const IntPoint&);
+
+private:
+ RefPtr<CoordinatedSurface> m_surface;
+ IntRect m_sourceRect;
+ IntRect m_tileRect;
+ IntPoint m_surfaceOffset;
+ float m_scale;
+};
+
+class CoordinatedBackingStore : public TextureMapperBackingStore {
+public:
+ void createTile(uint32_t tileID, float);
+ void removeTile(uint32_t tileID);
+ void removeAllTiles();
+ void updateTile(uint32_t tileID, const IntRect&, const IntRect&, PassRefPtr<CoordinatedSurface>, const IntPoint&);
+ static PassRefPtr<CoordinatedBackingStore> create() { return adoptRef(new CoordinatedBackingStore); }
+ void commitTileOperations(TextureMapper*);
+ PassRefPtr<BitmapTexture> texture() const;
+ void setSize(const FloatSize&);
+ virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float);
+ virtual void drawBorder(TextureMapper*, const Color&, float borderWidth, const FloatRect&, const TransformationMatrix&) OVERRIDE;
+ virtual void drawRepaintCounter(TextureMapper*, int repaintCount, const Color&, const FloatRect&, const TransformationMatrix&) OVERRIDE;
+
+private:
+ CoordinatedBackingStore()
+ : m_scale(1.)
+ { }
+ void paintTilesToTextureMapper(Vector<TextureMapperTile*>&, TextureMapper*, const TransformationMatrix&, float, const FloatRect&);
+ TransformationMatrix adjustedTransformForRect(const FloatRect&);
+ FloatRect rect() const { return FloatRect(FloatPoint::zero(), m_size); }
+
+ typedef HashMap<uint32_t, CoordinatedBackingStoreTile> CoordinatedBackingStoreTileMap;
+ CoordinatedBackingStoreTileMap m_tiles;
+ HashSet<uint32_t> m_tilesToRemove;
+ // FIXME: m_pendingSize should be removed after the following bug is fixed: https://bugs.webkit.org/show_bug.cgi?id=108294
+ FloatSize m_pendingSize;
+ FloatSize m_size;
+ float m_scale;
+};
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // CoordinatedBackingStore_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedCustomFilterOperation.h b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedCustomFilterOperation.h
new file mode 100644
index 000000000..17a7182b4
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedCustomFilterOperation.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef CoordinatedCustomFilterOperation_h
+#define CoordinatedCustomFilterOperation_h
+
+#if ENABLE(CSS_SHADERS)
+#include "CustomFilterOperation.h"
+
+namespace WebCore {
+
+// This class is only adding the programId on top of CustomFilterOperation. The argument decoder has no
+// context, so we cannot search in our cached CustomFilterPrograms while decoding. In that case
+// it will just store the programId and no CustomFilterProgram instance. The receiver is supposed to
+// iterate on this structure and inject the right CustomFilterPrograms.
+
+class CoordinatedCustomFilterOperation : public CustomFilterOperation {
+public:
+ static PassRefPtr<CoordinatedCustomFilterOperation> create(PassRefPtr<CustomFilterProgram> program, int programID, const CustomFilterParameterList& sortedParameters, unsigned meshRows, unsigned meshColumns)
+ {
+ return adoptRef(new CoordinatedCustomFilterOperation(program, programID, sortedParameters, meshRows, meshColumns));
+ }
+
+ int programID() const { return m_programID; }
+
+private:
+ CoordinatedCustomFilterOperation(PassRefPtr<CustomFilterProgram> program, int programID, const CustomFilterParameterList& sortedParameters, unsigned meshRows, unsigned meshColumns)
+ : CustomFilterOperation(program, sortedParameters, meshRows, meshColumns)
+ , m_programID(programID)
+ {
+ }
+
+ int m_programID;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_SHADERS)
+
+#endif // CoordinatedCustomFilterOperation_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedCustomFilterProgram.h b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedCustomFilterProgram.h
new file mode 100644
index 000000000..7f4f154c9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedCustomFilterProgram.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Company 100, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CoordinatedCustomFilterProgram_h
+#define CoordinatedCustomFilterProgram_h
+
+#if USE(COORDINATED_GRAPHICS) && ENABLE(CSS_SHADERS)
+#include "CustomFilterConstants.h"
+#include "CustomFilterProgram.h"
+
+namespace WebCore {
+
+class CoordinatedCustomFilterProgram : public CustomFilterProgram {
+public:
+ static PassRefPtr<CoordinatedCustomFilterProgram> create(String vertexShaderString, String m_fragmentShaderString, CustomFilterProgramType programType, CustomFilterProgramMixSettings mixSettings, CustomFilterMeshType meshType)
+ {
+ return adoptRef(new CoordinatedCustomFilterProgram(vertexShaderString, m_fragmentShaderString, programType, mixSettings, meshType));
+ }
+
+ virtual bool isLoaded() const OVERRIDE { return true; }
+
+protected:
+ virtual String vertexShaderString() const OVERRIDE { return m_vertexShaderString; }
+ virtual String fragmentShaderString() const OVERRIDE { return m_fragmentShaderString; }
+
+ virtual void willHaveClients() OVERRIDE { notifyClients(); }
+ virtual void didRemoveLastClient() OVERRIDE { }
+
+private:
+ CoordinatedCustomFilterProgram(String vertexShaderString, String fragmentShaderString, CustomFilterProgramType programType, CustomFilterProgramMixSettings mixSettings, CustomFilterMeshType meshType)
+ : CustomFilterProgram(programType, mixSettings, meshType)
+ , m_vertexShaderString(vertexShaderString)
+ , m_fragmentShaderString(fragmentShaderString)
+ {
+ }
+
+ String m_vertexShaderString;
+ String m_fragmentShaderString;
+};
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS) && ENABLE(CSS_SHADERS)
+
+#endif // CoordinatedCustomFilterProgram_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp
new file mode 100644
index 000000000..7e70bbb0d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp
@@ -0,0 +1,1255 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2010 Apple Inc. All rights reserved.
+ Copyright (C) 2012 Company 100, Inc.
+ Copyright (C) 2012 Intel Corporation. All rights reserved.
+
+ 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"
+
+#if USE(COORDINATED_GRAPHICS)
+#include "CoordinatedGraphicsLayer.h"
+
+#include "CoordinatedTile.h"
+#include "FloatQuad.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "GraphicsLayer.h"
+#include "Page.h"
+#include "ScrollableArea.h"
+#include "TextureMapperPlatformLayer.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/HashMap.h>
+#ifndef NDEBUG
+#include <wtf/TemporaryChange.h>
+#endif
+#include <wtf/text/CString.h>
+
+namespace WebCore {
+
+static CoordinatedLayerID toCoordinatedLayerID(GraphicsLayer* layer)
+{
+ return layer ? toCoordinatedGraphicsLayer(layer)->id() : 0;
+}
+
+void CoordinatedGraphicsLayer::didChangeLayerState()
+{
+ m_shouldSyncLayerState = true;
+ if (client())
+ client()->notifyFlushRequired(this);
+}
+
+void CoordinatedGraphicsLayer::didChangeAnimations()
+{
+ m_shouldSyncAnimations = true;
+ if (client())
+ client()->notifyFlushRequired(this);
+}
+
+void CoordinatedGraphicsLayer::didChangeChildren()
+{
+ m_shouldSyncChildren = true;
+ if (client())
+ client()->notifyFlushRequired(this);
+}
+
+#if ENABLE(CSS_FILTERS)
+void CoordinatedGraphicsLayer::didChangeFilters()
+{
+ m_shouldSyncFilters = true;
+ if (client())
+ client()->notifyFlushRequired(this);
+}
+#endif
+
+void CoordinatedGraphicsLayer::didChangeImageBacking()
+{
+ m_shouldSyncImageBacking = true;
+ if (client())
+ client()->notifyFlushRequired(this);
+}
+
+void CoordinatedGraphicsLayer::setShouldUpdateVisibleRect()
+{
+ m_shouldUpdateVisibleRect = true;
+ for (size_t i = 0; i < children().size(); ++i)
+ toCoordinatedGraphicsLayer(children()[i])->setShouldUpdateVisibleRect();
+ if (replicaLayer())
+ toCoordinatedGraphicsLayer(replicaLayer())->setShouldUpdateVisibleRect();
+}
+
+void CoordinatedGraphicsLayer::didChangeGeometry()
+{
+ didChangeLayerState();
+ setShouldUpdateVisibleRect();
+}
+
+CoordinatedGraphicsLayer::CoordinatedGraphicsLayer(GraphicsLayerClient* client)
+ : GraphicsLayer(client)
+#ifndef NDEBUG
+ , m_isPurging(false)
+#endif
+ , m_shouldUpdateVisibleRect(true)
+ , m_shouldSyncLayerState(true)
+ , m_shouldSyncChildren(true)
+ , m_shouldSyncFilters(true)
+ , m_shouldSyncImageBacking(true)
+ , m_shouldSyncAnimations(true)
+ , m_fixedToViewport(false)
+ , m_movingVisibleRect(false)
+ , m_pendingContentsScaleAdjustment(false)
+ , m_pendingVisibleRectAdjustment(false)
+#if USE(GRAPHICS_SURFACE)
+ , m_isValidCanvas(false)
+ , m_pendingCanvasOperation(None)
+#endif
+ , m_coordinator(0)
+ , m_compositedNativeImagePtr(0)
+ , m_canvasPlatformLayer(0)
+ , m_animationStartedTimer(this, &CoordinatedGraphicsLayer::animationStartedTimerFired)
+ , m_scrollableArea(0)
+{
+ static CoordinatedLayerID nextLayerID = 1;
+ m_id = nextLayerID++;
+}
+
+CoordinatedGraphicsLayer::~CoordinatedGraphicsLayer()
+{
+ if (m_coordinator) {
+ purgeBackingStores();
+ m_coordinator->detachLayer(this);
+ }
+ ASSERT(!m_coordinatedImageBacking);
+ ASSERT(!m_mainBackingStore);
+ willBeDestroyed();
+}
+
+bool CoordinatedGraphicsLayer::setChildren(const Vector<GraphicsLayer*>& children)
+{
+ bool ok = GraphicsLayer::setChildren(children);
+ if (!ok)
+ return false;
+ didChangeChildren();
+ return true;
+}
+
+void CoordinatedGraphicsLayer::addChild(GraphicsLayer* layer)
+{
+ GraphicsLayer::addChild(layer);
+ didChangeChildren();
+}
+
+void CoordinatedGraphicsLayer::addChildAtIndex(GraphicsLayer* layer, int index)
+{
+ GraphicsLayer::addChildAtIndex(layer, index);
+ didChangeChildren();
+}
+
+void CoordinatedGraphicsLayer::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling)
+{
+ GraphicsLayer::addChildAbove(layer, sibling);
+ didChangeChildren();
+}
+
+void CoordinatedGraphicsLayer::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling)
+{
+ GraphicsLayer::addChildBelow(layer, sibling);
+ didChangeChildren();
+}
+
+bool CoordinatedGraphicsLayer::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
+{
+ bool ok = GraphicsLayer::replaceChild(oldChild, newChild);
+ if (!ok)
+ return false;
+ didChangeChildren();
+ return true;
+}
+
+void CoordinatedGraphicsLayer::removeFromParent()
+{
+ if (CoordinatedGraphicsLayer* parentLayer = toCoordinatedGraphicsLayer(parent()))
+ parentLayer->didChangeChildren();
+ GraphicsLayer::removeFromParent();
+}
+
+void CoordinatedGraphicsLayer::setPosition(const FloatPoint& p)
+{
+ if (position() == p)
+ return;
+
+ GraphicsLayer::setPosition(p);
+ m_layerState.positionChanged = true;
+ didChangeGeometry();
+}
+
+void CoordinatedGraphicsLayer::setAnchorPoint(const FloatPoint3D& p)
+{
+ if (anchorPoint() == p)
+ return;
+
+ GraphicsLayer::setAnchorPoint(p);
+ m_layerState.anchorPointChanged = true;
+ didChangeGeometry();
+}
+
+void CoordinatedGraphicsLayer::setSize(const FloatSize& size)
+{
+ if (this->size() == size)
+ return;
+
+ GraphicsLayer::setSize(size);
+ m_layerState.sizeChanged = true;
+
+ if (maskLayer())
+ maskLayer()->setSize(size);
+ didChangeGeometry();
+}
+
+void CoordinatedGraphicsLayer::setTransform(const TransformationMatrix& t)
+{
+ if (transform() == t)
+ return;
+
+ GraphicsLayer::setTransform(t);
+ m_layerState.transformChanged = true;
+
+ didChangeGeometry();
+}
+
+void CoordinatedGraphicsLayer::setChildrenTransform(const TransformationMatrix& t)
+{
+ if (childrenTransform() == t)
+ return;
+
+ GraphicsLayer::setChildrenTransform(t);
+ m_layerState.childrenTransformChanged = true;
+
+ didChangeGeometry();
+}
+
+void CoordinatedGraphicsLayer::setPreserves3D(bool b)
+{
+ if (preserves3D() == b)
+ return;
+
+ GraphicsLayer::setPreserves3D(b);
+ m_layerState.preserves3D = b;
+ m_layerState.flagsChanged = true;
+
+ didChangeGeometry();
+}
+
+void CoordinatedGraphicsLayer::setMasksToBounds(bool b)
+{
+ if (masksToBounds() == b)
+ return;
+ GraphicsLayer::setMasksToBounds(b);
+ m_layerState.masksToBounds = b;
+ m_layerState.flagsChanged = true;
+
+ didChangeGeometry();
+}
+
+void CoordinatedGraphicsLayer::setDrawsContent(bool b)
+{
+ if (drawsContent() == b)
+ return;
+ GraphicsLayer::setDrawsContent(b);
+ m_layerState.drawsContent = b;
+ m_layerState.flagsChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setContentsVisible(bool b)
+{
+ if (contentsAreVisible() == b)
+ return;
+ GraphicsLayer::setContentsVisible(b);
+ m_layerState.contentsVisible = b;
+ m_layerState.flagsChanged = true;
+
+ if (maskLayer())
+ maskLayer()->setContentsVisible(b);
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setContentsOpaque(bool b)
+{
+ if (contentsOpaque() == b)
+ return;
+ if (m_mainBackingStore)
+ m_mainBackingStore->setSupportsAlpha(!b);
+ GraphicsLayer::setContentsOpaque(b);
+ m_layerState.contentsOpaque = b;
+ m_layerState.flagsChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setBackfaceVisibility(bool b)
+{
+ if (backfaceVisibility() == b)
+ return;
+
+ GraphicsLayer::setBackfaceVisibility(b);
+ m_layerState.backfaceVisible = b;
+ m_layerState.flagsChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setOpacity(float opacity)
+{
+ if (this->opacity() == opacity)
+ return;
+
+ GraphicsLayer::setOpacity(opacity);
+ m_layerState.opacity = opacity;
+ m_layerState.opacityChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setContentsRect(const IntRect& r)
+{
+ if (contentsRect() == r)
+ return;
+
+ GraphicsLayer::setContentsRect(r);
+ m_layerState.contentsRect = r;
+ m_layerState.contentsRectChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setContentsTileSize(const IntSize& s)
+{
+ if (contentsTileSize() == s)
+ return;
+
+ GraphicsLayer::setContentsTileSize(s);
+ m_layerState.contentsTileSize = s;
+ m_layerState.contentsTilingChanged = true;
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setContentsTilePhase(const IntPoint& p)
+{
+ if (contentsTilePhase() == p)
+ return;
+
+ GraphicsLayer::setContentsTilePhase(p);
+ m_layerState.contentsTilePhase = p;
+ m_layerState.contentsTilingChanged = true;
+ didChangeLayerState();
+}
+
+static bool s_shouldSupportContentsTiling = false;
+
+void CoordinatedGraphicsLayer::setShouldSupportContentsTiling(bool s)
+{
+ s_shouldSupportContentsTiling = s;
+}
+
+bool GraphicsLayer::supportsContentsTiling()
+{
+ return s_shouldSupportContentsTiling;
+}
+
+void CoordinatedGraphicsLayer::setContentsNeedsDisplay()
+{
+#if USE(GRAPHICS_SURFACE)
+ if (m_canvasPlatformLayer)
+ m_pendingCanvasOperation |= SyncCanvas;
+#endif
+
+ if (client())
+ client()->notifyFlushRequired(this);
+
+ addRepaintRect(contentsRect());
+}
+
+void CoordinatedGraphicsLayer::setContentsToCanvas(PlatformLayer* platformLayer)
+{
+#if USE(GRAPHICS_SURFACE)
+ if (m_canvasPlatformLayer) {
+ ASSERT(m_canvasToken.isValid());
+ if (!platformLayer) {
+ m_pendingCanvasOperation |= DestroyCanvas;
+ m_pendingCanvasOperation &= ~CreateCanvas;
+ } else if ((m_canvasSize != platformLayer->platformLayerSize()) || (m_canvasToken != platformLayer->graphicsSurfaceToken())) {
+ // m_canvasToken can be different to platformLayer->graphicsSurfaceToken(), even if m_canvasPlatformLayer equals platformLayer.
+ m_pendingCanvasOperation |= RecreateCanvas;
+ }
+ } else {
+ if (platformLayer)
+ m_pendingCanvasOperation |= CreateAndSyncCanvas;
+ }
+
+ m_canvasPlatformLayer = platformLayer;
+ // m_canvasToken is updated only here. In detail, when GraphicsContext3D is changed or reshaped, m_canvasToken is changed and setContentsToCanvas() is always called.
+ m_canvasSize = m_canvasPlatformLayer ? m_canvasPlatformLayer->platformLayerSize() : IntSize();
+ m_canvasToken = m_canvasPlatformLayer ? m_canvasPlatformLayer->graphicsSurfaceToken() : GraphicsSurfaceToken();
+ ASSERT(!(!m_canvasToken.isValid() && m_canvasPlatformLayer));
+
+ if (client())
+ client()->notifyFlushRequired(this);
+#else
+ UNUSED_PARAM(platformLayer);
+#endif
+}
+
+#if ENABLE(CSS_FILTERS)
+bool CoordinatedGraphicsLayer::setFilters(const FilterOperations& newFilters)
+{
+ if (filters() == newFilters)
+ return true;
+
+ if (!GraphicsLayer::setFilters(newFilters))
+ return false;
+
+ didChangeFilters();
+ return true;
+}
+#endif
+
+void CoordinatedGraphicsLayer::setContentsToSolidColor(const Color& color)
+{
+ if (m_layerState.solidColor == color)
+ return;
+
+ m_layerState.solidColor = color;
+ m_layerState.solidColorChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setShowDebugBorder(bool show)
+{
+ if (isShowingDebugBorder() == show)
+ return;
+
+ GraphicsLayer::setShowDebugBorder(show);
+ m_layerState.showDebugBorders = true;
+ m_layerState.flagsChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setShowRepaintCounter(bool show)
+{
+ if (isShowingRepaintCounter() == show)
+ return;
+
+ GraphicsLayer::setShowRepaintCounter(show);
+ m_layerState.showRepaintCounter = true;
+ m_layerState.flagsChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setContentsToImage(Image* image)
+{
+ NativeImagePtr newNativeImagePtr = image ? image->nativeImageForCurrentFrame() : 0;
+ if (newNativeImagePtr) {
+ // This code makes the assumption that pointer equality on a NativeImagePtr is a valid way to tell if the image is changed.
+ // This assumption is true in Qt, GTK and EFL.
+ if (newNativeImagePtr == m_compositedNativeImagePtr)
+ return;
+
+ m_compositedImage = image;
+ m_compositedNativeImagePtr = newNativeImagePtr;
+ } else {
+ m_compositedImage = 0;
+ m_compositedNativeImagePtr = 0;
+ }
+
+ GraphicsLayer::setContentsToImage(image);
+ didChangeImageBacking();
+}
+
+void CoordinatedGraphicsLayer::setMaskLayer(GraphicsLayer* layer)
+{
+ if (layer == maskLayer())
+ return;
+
+ GraphicsLayer::setMaskLayer(layer);
+
+ if (!layer)
+ return;
+
+ layer->setSize(size());
+ layer->setContentsVisible(contentsAreVisible());
+ CoordinatedGraphicsLayer* coordinatedLayer = toCoordinatedGraphicsLayer(layer);
+ coordinatedLayer->didChangeLayerState();
+
+ m_layerState.mask = coordinatedLayer->id();
+ m_layerState.maskChanged = true;
+
+ didChangeLayerState();
+}
+
+bool CoordinatedGraphicsLayer::shouldDirectlyCompositeImage(Image* image) const
+{
+ if (!image || !image->isBitmapImage())
+ return false;
+
+ enum { MaxDimenstionForDirectCompositing = 2000 };
+ if (image->width() > MaxDimenstionForDirectCompositing || image->height() > MaxDimenstionForDirectCompositing)
+ return false;
+
+ return true;
+}
+
+void CoordinatedGraphicsLayer::setReplicatedByLayer(GraphicsLayer* layer)
+{
+ if (layer == replicaLayer())
+ return;
+
+ GraphicsLayer::setReplicatedByLayer(layer);
+ m_layerState.replica = toCoordinatedLayerID(layer);
+ m_layerState.replicaChanged = true;
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setNeedsDisplay()
+{
+ setNeedsDisplayInRect(FloatRect(FloatPoint(), size()));
+}
+
+void CoordinatedGraphicsLayer::setNeedsDisplayInRect(const FloatRect& rect)
+{
+ if (m_mainBackingStore)
+ m_mainBackingStore->invalidate(IntRect(rect));
+
+ didChangeLayerState();
+
+ addRepaintRect(rect);
+}
+
+CoordinatedLayerID CoordinatedGraphicsLayer::id() const
+{
+ return m_id;
+}
+
+void CoordinatedGraphicsLayer::setScrollableArea(ScrollableArea* scrollableArea)
+{
+ bool oldScrollable = isScrollable();
+ m_scrollableArea = scrollableArea;
+ if (oldScrollable == isScrollable())
+ return;
+
+ m_layerState.isScrollable = isScrollable();
+ m_layerState.flagsChanged = true;
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::commitScrollOffset(const IntSize& offset)
+{
+ if (!isScrollable() || offset.isZero())
+ return;
+
+ m_scrollableArea->notifyScrollPositionChanged(m_scrollableArea->scrollPosition() + offset);
+ m_layerState.committedScrollOffset += offset;
+ m_layerState.committedScrollOffsetChanged = true;
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setFixedToViewport(bool isFixed)
+{
+ if (m_fixedToViewport == isFixed)
+ return;
+
+ m_fixedToViewport = isFixed;
+ m_layerState.fixedToViewport = isFixed;
+ m_layerState.flagsChanged = true;
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::flushCompositingState(const FloatRect& rect)
+{
+ if (!m_coordinator->isFlushingLayerChanges()) {
+ if (client())
+ client()->notifyFlushRequired(this);
+ return;
+ }
+
+ if (CoordinatedGraphicsLayer* mask = toCoordinatedGraphicsLayer(maskLayer()))
+ mask->flushCompositingStateForThisLayerOnly();
+
+ if (CoordinatedGraphicsLayer* replica = toCoordinatedGraphicsLayer(replicaLayer()))
+ replica->flushCompositingStateForThisLayerOnly();
+
+ flushCompositingStateForThisLayerOnly();
+
+ for (size_t i = 0; i < children().size(); ++i)
+ children()[i]->flushCompositingState(rect);
+}
+
+CoordinatedGraphicsLayer* toCoordinatedGraphicsLayer(GraphicsLayer* layer)
+{
+ return static_cast<CoordinatedGraphicsLayer*>(layer);
+}
+
+void CoordinatedGraphicsLayer::syncChildren()
+{
+ if (!m_shouldSyncChildren)
+ return;
+ m_shouldSyncChildren = false;
+ m_layerState.childrenChanged = true;
+ m_layerState.children.clear();
+ for (size_t i = 0; i < children().size(); ++i)
+ m_layerState.children.append(toCoordinatedLayerID(children()[i]));
+}
+
+#if ENABLE(CSS_FILTERS)
+void CoordinatedGraphicsLayer::syncFilters()
+{
+ if (!m_shouldSyncFilters)
+ return;
+ m_shouldSyncFilters = false;
+
+ m_layerState.filters = GraphicsLayer::filters();
+ m_layerState.filtersChanged = true;
+}
+#endif
+
+void CoordinatedGraphicsLayer::syncImageBacking()
+{
+ if (!m_shouldSyncImageBacking)
+ return;
+ m_shouldSyncImageBacking = false;
+
+ if (m_compositedNativeImagePtr) {
+ ASSERT(!shouldHaveBackingStore());
+ ASSERT(m_compositedImage);
+
+ bool imageInstanceReplaced = m_coordinatedImageBacking && (m_coordinatedImageBacking->id() != CoordinatedImageBacking::getCoordinatedImageBackingID(m_compositedImage.get()));
+ if (imageInstanceReplaced)
+ releaseImageBackingIfNeeded();
+
+ if (!m_coordinatedImageBacking) {
+ m_coordinatedImageBacking = m_coordinator->createImageBackingIfNeeded(m_compositedImage.get());
+ m_coordinatedImageBacking->addHost(this);
+ m_layerState.imageID = m_coordinatedImageBacking->id();
+ }
+
+ m_coordinatedImageBacking->markDirty();
+ m_layerState.imageChanged = true;
+ } else
+ releaseImageBackingIfNeeded();
+
+ // syncImageBacking() changed m_layerState.imageID.
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::syncLayerState()
+{
+ if (!m_shouldSyncLayerState)
+ return;
+ m_shouldSyncLayerState = false;
+
+ m_layerState.childrenTransform = childrenTransform();
+ m_layerState.contentsRect = contentsRect();
+ m_layerState.mask = toCoordinatedLayerID(maskLayer());
+ m_layerState.opacity = opacity();
+ m_layerState.replica = toCoordinatedLayerID(replicaLayer());
+ m_layerState.transform = transform();
+
+ m_layerState.anchorPoint = m_adjustedAnchorPoint;
+ m_layerState.pos = m_adjustedPosition;
+ m_layerState.size = m_adjustedSize;
+
+ if (m_layerState.flagsChanged) {
+ m_layerState.drawsContent = drawsContent();
+ m_layerState.contentsVisible = contentsAreVisible();
+ m_layerState.backfaceVisible = backfaceVisibility();
+ m_layerState.masksToBounds = masksToBounds();
+ m_layerState.preserves3D = preserves3D();
+ m_layerState.fixedToViewport = fixedToViewport();
+ m_layerState.showDebugBorders = isShowingDebugBorder();
+ m_layerState.showRepaintCounter = isShowingRepaintCounter();
+ m_layerState.isScrollable = isScrollable();
+ }
+
+ if (m_layerState.showDebugBorders)
+ updateDebugIndicators();
+}
+
+void CoordinatedGraphicsLayer::setDebugBorder(const Color& color, float width)
+{
+ ASSERT(m_layerState.showDebugBorders);
+ if (m_layerState.debugBorderColor != color) {
+ m_layerState.debugBorderColor = color;
+ m_layerState.debugBorderColorChanged = true;
+ }
+
+ if (m_layerState.debugBorderWidth != width) {
+ m_layerState.debugBorderWidth = width;
+ m_layerState.debugBorderWidthChanged = true;
+ }
+}
+
+void CoordinatedGraphicsLayer::syncAnimations()
+{
+ if (!m_shouldSyncAnimations)
+ return;
+
+ m_shouldSyncAnimations = false;
+ m_layerState.animations = m_animations.getActiveAnimations();
+ m_layerState.animationsChanged = true;
+}
+
+#if USE(GRAPHICS_SURFACE)
+void CoordinatedGraphicsLayer::syncCanvas()
+{
+ destroyCanvasIfNeeded();
+ createCanvasIfNeeded();
+
+ if (!(m_pendingCanvasOperation & SyncCanvas))
+ return;
+
+ m_pendingCanvasOperation &= ~SyncCanvas;
+
+ if (!m_isValidCanvas)
+ return;
+
+ ASSERT(m_canvasPlatformLayer);
+ m_layerState.canvasFrontBuffer = m_canvasPlatformLayer->copyToGraphicsSurface();
+ m_layerState.canvasShouldSwapBuffers = true;
+}
+
+void CoordinatedGraphicsLayer::destroyCanvasIfNeeded()
+{
+ if (!(m_pendingCanvasOperation & DestroyCanvas))
+ return;
+
+ if (m_isValidCanvas) {
+ m_isValidCanvas = false;
+ m_layerState.canvasToken = GraphicsSurfaceToken();
+ m_layerState.canvasChanged = true;
+ }
+
+ m_pendingCanvasOperation &= ~DestroyCanvas;
+}
+
+void CoordinatedGraphicsLayer::createCanvasIfNeeded()
+{
+ if (!(m_pendingCanvasOperation & CreateCanvas))
+ return;
+
+ ASSERT(m_canvasPlatformLayer);
+ if (!m_isValidCanvas) {
+ m_layerState.canvasSize = m_canvasPlatformLayer->platformLayerSize();
+ m_layerState.canvasToken = m_canvasPlatformLayer->graphicsSurfaceToken();
+ m_layerState.canvasSurfaceFlags = m_canvasPlatformLayer->graphicsSurfaceFlags();
+ m_layerState.canvasChanged = true;
+ m_isValidCanvas = true;
+ }
+
+ m_pendingCanvasOperation &= ~CreateCanvas;
+}
+#endif
+
+void CoordinatedGraphicsLayer::flushCompositingStateForThisLayerOnly()
+{
+ ASSERT(m_coordinator->isFlushingLayerChanges());
+
+ // When we have a transform animation, we need to update visible rect every frame to adjust the visible rect of a backing store.
+ bool hasActiveTransformAnimation = selfOrAncestorHasActiveTransformAnimation();
+ if (hasActiveTransformAnimation)
+ m_movingVisibleRect = true;
+
+ // Sets the values.
+ computePixelAlignment(m_adjustedPosition, m_adjustedSize, m_adjustedAnchorPoint, m_pixelAlignmentOffset);
+
+ syncImageBacking();
+ syncLayerState();
+ syncAnimations();
+ computeTransformedVisibleRect();
+ syncChildren();
+#if ENABLE(CSS_FILTERS)
+ syncFilters();
+#endif
+#if USE(GRAPHICS_SURFACE)
+ syncCanvas();
+#endif
+
+ // Only unset m_movingVisibleRect after we have updated the visible rect after the animation stopped.
+ if (!hasActiveTransformAnimation)
+ m_movingVisibleRect = false;
+}
+
+void CoordinatedGraphicsLayer::syncPendingStateChangesIncludingSubLayers()
+{
+ if (m_layerState.hasPendingChanges()) {
+ m_coordinator->syncLayerState(m_id, m_layerState);
+ resetLayerState();
+ }
+
+ for (size_t i = 0; i < children().size(); ++i)
+ toCoordinatedGraphicsLayer(children()[i])->syncPendingStateChangesIncludingSubLayers();
+}
+
+void CoordinatedGraphicsLayer::resetLayerState()
+{
+ m_layerState.changeMask = 0;
+ m_layerState.tilesToCreate.clear();
+ m_layerState.tilesToRemove.clear();
+ m_layerState.tilesToUpdate.clear();
+ m_layerState.committedScrollOffset = IntSize();
+}
+
+bool CoordinatedGraphicsLayer::imageBackingVisible()
+{
+ ASSERT(m_coordinatedImageBacking);
+ return tiledBackingStoreVisibleRect().intersects(contentsRect());
+}
+
+void CoordinatedGraphicsLayer::releaseImageBackingIfNeeded()
+{
+ if (!m_coordinatedImageBacking)
+ return;
+
+ ASSERT(m_coordinator);
+ m_coordinatedImageBacking->removeHost(this);
+ m_coordinatedImageBacking.clear();
+ m_layerState.imageID = InvalidCoordinatedImageBackingID;
+ m_layerState.imageChanged = true;
+}
+
+void CoordinatedGraphicsLayer::tiledBackingStorePaintBegin()
+{
+}
+
+CoordinatedGraphicsLayer* CoordinatedGraphicsLayer::findFirstDescendantWithContentsRecursively()
+{
+ if (shouldHaveBackingStore())
+ return this;
+
+ for (size_t i = 0; i < children().size(); ++i) {
+ CoordinatedGraphicsLayer* layer = toCoordinatedGraphicsLayer(children()[i])->findFirstDescendantWithContentsRecursively();
+ if (layer)
+ return layer;
+ }
+
+ return 0;
+}
+
+void CoordinatedGraphicsLayer::setVisibleContentRectTrajectoryVector(const FloatPoint& trajectoryVector)
+{
+ if (!m_mainBackingStore)
+ return;
+
+ m_mainBackingStore->setTrajectoryVector(trajectoryVector);
+ setNeedsVisibleRectAdjustment();
+}
+
+void CoordinatedGraphicsLayer::deviceOrPageScaleFactorChanged()
+{
+ if (shouldHaveBackingStore())
+ m_pendingContentsScaleAdjustment = true;
+}
+
+float CoordinatedGraphicsLayer::effectiveContentsScale()
+{
+ return selfOrAncestorHaveNonAffineTransforms() ? 1 : deviceScaleFactor() * pageScaleFactor();
+}
+
+void CoordinatedGraphicsLayer::adjustContentsScale()
+{
+ ASSERT(shouldHaveBackingStore());
+ if (!m_mainBackingStore || m_mainBackingStore->contentsScale() == effectiveContentsScale())
+ return;
+
+ // Between creating the new backing store and painting the content,
+ // we do not want to drop the previous one as that might result in
+ // briefly seeing flickering as the old tiles may be dropped before
+ // something replaces them.
+ m_previousBackingStore = m_mainBackingStore.release();
+
+ // No reason to save the previous backing store for non-visible areas.
+ m_previousBackingStore->removeAllNonVisibleTiles();
+}
+
+void CoordinatedGraphicsLayer::createBackingStore()
+{
+ m_mainBackingStore = adoptPtr(new TiledBackingStore(this, CoordinatedTileBackend::create(this)));
+ m_mainBackingStore->setSupportsAlpha(!contentsOpaque());
+ m_mainBackingStore->setContentsScale(effectiveContentsScale());
+}
+
+void CoordinatedGraphicsLayer::tiledBackingStorePaint(GraphicsContext* context, const IntRect& rect)
+{
+ if (rect.isEmpty())
+ return;
+ paintGraphicsLayerContents(*context, rect);
+}
+
+void CoordinatedGraphicsLayer::tiledBackingStorePaintEnd(const Vector<IntRect>& updatedRects)
+{
+ if (!isShowingRepaintCounter() || updatedRects.isEmpty())
+ return;
+
+ m_layerState.repaintCount = incrementRepaintCount();
+ m_layerState.repaintCountChanged = true;
+}
+
+void CoordinatedGraphicsLayer::tiledBackingStoreHasPendingTileCreation()
+{
+ setNeedsVisibleRectAdjustment();
+ if (client())
+ client()->notifyFlushRequired(this);
+}
+
+IntRect CoordinatedGraphicsLayer::tiledBackingStoreContentsRect()
+{
+ return IntRect(0, 0, size().width(), size().height());
+}
+
+static void clampToContentsRectIfRectIsInfinite(FloatRect& rect, const IntRect& contentsRect)
+{
+ if (rect.width() >= LayoutUnit::nearlyMax() || rect.width() <= LayoutUnit::nearlyMin()) {
+ rect.setX(contentsRect.x());
+ rect.setWidth(contentsRect.width());
+ }
+
+ if (rect.height() >= LayoutUnit::nearlyMax() || rect.height() <= LayoutUnit::nearlyMin()) {
+ rect.setY(contentsRect.y());
+ rect.setHeight(contentsRect.height());
+ }
+}
+
+IntRect CoordinatedGraphicsLayer::tiledBackingStoreVisibleRect()
+{
+ // Non-invertible layers are not visible.
+ if (!m_layerTransform.combined().isInvertible())
+ return IntRect();
+
+ // Return a projection of the visible rect (surface coordinates) onto the layer's plane (layer coordinates).
+ // The resulting quad might be squewed and the visible rect is the bounding box of this quad,
+ // so it might spread further than the real visible area (and then even more amplified by the cover rect multiplier).
+ ASSERT(m_cachedInverseTransform == m_layerTransform.combined().inverse());
+ FloatRect rect = m_cachedInverseTransform.clampedBoundsOfProjectedQuad(FloatQuad(m_coordinator->visibleContentsRect()));
+ clampToContentsRectIfRectIsInfinite(rect, tiledBackingStoreContentsRect());
+ return enclosingIntRect(rect);
+}
+
+Color CoordinatedGraphicsLayer::tiledBackingStoreBackgroundColor() const
+{
+ return contentsOpaque() ? Color::white : Color::transparent;
+}
+
+bool CoordinatedGraphicsLayer::paintToSurface(const IntSize& size, uint32_t& atlas, IntPoint& offset, CoordinatedSurface::Client* client)
+{
+ ASSERT(m_coordinator);
+ ASSERT(m_coordinator->isFlushingLayerChanges());
+ return m_coordinator->paintToSurface(size, contentsOpaque() ? CoordinatedSurface::NoFlags : CoordinatedSurface::SupportsAlpha, atlas, offset, client);
+}
+
+void CoordinatedGraphicsLayer::createTile(uint32_t tileID, const SurfaceUpdateInfo& updateInfo, const IntRect& tileRect)
+{
+ ASSERT(m_coordinator);
+ ASSERT(m_coordinator->isFlushingLayerChanges());
+
+ TileCreationInfo creationInfo;
+ creationInfo.tileID = tileID;
+ creationInfo.scale = updateInfo.scaleFactor;
+
+ m_layerState.tilesToCreate.append(creationInfo);
+ updateTile(tileID, updateInfo, tileRect);
+}
+
+void CoordinatedGraphicsLayer::updateTile(uint32_t tileID, const SurfaceUpdateInfo& updateInfo, const IntRect& tileRect)
+{
+ ASSERT(m_coordinator);
+ ASSERT(m_coordinator->isFlushingLayerChanges());
+
+ TileUpdateInfo tileUpdateInfo;
+ tileUpdateInfo.tileID = tileID;
+ tileUpdateInfo.tileRect = tileRect;
+ tileUpdateInfo.updateInfo = updateInfo;
+ m_layerState.tilesToUpdate.append(tileUpdateInfo);
+}
+
+void CoordinatedGraphicsLayer::removeTile(uint32_t tileID)
+{
+ ASSERT(m_coordinator);
+ ASSERT(m_coordinator->isFlushingLayerChanges() || m_isPurging);
+ m_layerState.tilesToRemove.append(tileID);
+}
+
+void CoordinatedGraphicsLayer::updateContentBuffersIncludingSubLayers()
+{
+ if (CoordinatedGraphicsLayer* mask = toCoordinatedGraphicsLayer(maskLayer()))
+ mask->updateContentBuffers();
+
+ if (CoordinatedGraphicsLayer* replica = toCoordinatedGraphicsLayer(replicaLayer()))
+ replica->updateContentBuffers();
+
+ updateContentBuffers();
+
+ for (size_t i = 0; i < children().size(); ++i)
+ toCoordinatedGraphicsLayer(children()[i])->updateContentBuffersIncludingSubLayers();
+}
+
+void CoordinatedGraphicsLayer::updateContentBuffers()
+{
+ if (!shouldHaveBackingStore()) {
+ m_mainBackingStore.clear();
+ m_previousBackingStore.clear();
+ return;
+ }
+
+ if (m_pendingContentsScaleAdjustment) {
+ adjustContentsScale();
+ m_pendingContentsScaleAdjustment = false;
+ }
+
+ // This is the only place we (re)create the main tiled backing store, once we
+ // have a remote client and we are ready to send our data to the UI process.
+ if (!m_mainBackingStore)
+ createBackingStore();
+
+ if (m_pendingVisibleRectAdjustment) {
+ m_pendingVisibleRectAdjustment = false;
+ m_mainBackingStore->coverWithTilesIfNeeded();
+ }
+
+ m_mainBackingStore->updateTileBuffers();
+
+ // The previous backing store is kept around to avoid flickering between
+ // removing the existing tiles and painting the new ones. The first time
+ // the visibleRect is full painted we remove the previous backing store.
+ if (m_mainBackingStore->visibleAreaIsCovered())
+ m_previousBackingStore.clear();
+}
+
+void CoordinatedGraphicsLayer::purgeBackingStores()
+{
+#ifndef NDEBUG
+ TemporaryChange<bool> updateModeProtector(m_isPurging, true);
+#endif
+ m_mainBackingStore.clear();
+ m_previousBackingStore.clear();
+
+ releaseImageBackingIfNeeded();
+
+ didChangeLayerState();
+}
+
+void CoordinatedGraphicsLayer::setCoordinator(CoordinatedGraphicsLayerClient* coordinator)
+{
+ m_coordinator = coordinator;
+}
+
+void CoordinatedGraphicsLayer::setNeedsVisibleRectAdjustment()
+{
+ if (shouldHaveBackingStore())
+ m_pendingVisibleRectAdjustment = true;
+}
+
+bool CoordinatedGraphicsLayer::hasPendingVisibleChanges()
+{
+ if (opacity() < 0.01 && !m_animations.hasActiveAnimationsOfType(AnimatedPropertyOpacity))
+ return false;
+
+ for (size_t i = 0; i < children().size(); ++i) {
+ if (toCoordinatedGraphicsLayer(children()[i])->hasPendingVisibleChanges())
+ return true;
+ }
+
+ bool shouldSyncCanvas = false;
+#if USE(GRAPHICS_SURFACE)
+ shouldSyncCanvas = m_pendingCanvasOperation & SyncCanvas;
+#endif
+
+ if (!m_shouldSyncLayerState && !m_shouldSyncChildren && !m_shouldSyncFilters && !m_shouldSyncImageBacking && !m_shouldSyncAnimations && !shouldSyncCanvas)
+ return false;
+
+ return tiledBackingStoreVisibleRect().intersects(tiledBackingStoreContentsRect());
+}
+
+static inline bool isIntegral(float value)
+{
+ return static_cast<int>(value) == value;
+}
+
+FloatPoint CoordinatedGraphicsLayer::computePositionRelativeToBase()
+{
+ FloatPoint offset;
+ for (const GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent())
+ offset += currLayer->position();
+
+ return offset;
+}
+
+void CoordinatedGraphicsLayer::computePixelAlignment(FloatPoint& position, FloatSize& size, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset)
+{
+ if (isIntegral(effectiveContentsScale())) {
+ position = m_position;
+ size = m_size;
+ anchorPoint = m_anchorPoint;
+ alignmentOffset = FloatSize();
+ return;
+ }
+
+ FloatPoint positionRelativeToBase = computePositionRelativeToBase();
+
+ FloatRect baseRelativeBounds(positionRelativeToBase, m_size);
+ FloatRect scaledBounds = baseRelativeBounds;
+
+ // Scale by the effective scale factor to compute the screen-relative bounds.
+ scaledBounds.scale(effectiveContentsScale());
+
+ // Round to integer boundaries.
+ // NOTE: When using enclosingIntRect (as mac) it will have different sizes depending on position.
+ FloatRect alignedBounds = roundedIntRect(scaledBounds);
+
+ // Convert back to layer coordinates.
+ alignedBounds.scale(1 / effectiveContentsScale());
+
+ // Convert back to layer coordinates.
+ alignmentOffset = baseRelativeBounds.location() - alignedBounds.location();
+
+ position = m_position - alignmentOffset;
+ size = alignedBounds.size();
+
+ // Now we have to compute a new anchor point which compensates for rounding.
+ float anchorPointX = m_anchorPoint.x();
+ float anchorPointY = m_anchorPoint.y();
+
+ if (alignedBounds.width())
+ anchorPointX = (baseRelativeBounds.width() * anchorPointX + alignmentOffset.width()) / alignedBounds.width();
+
+ if (alignedBounds.height())
+ anchorPointY = (baseRelativeBounds.height() * anchorPointY + alignmentOffset.height()) / alignedBounds.height();
+
+ anchorPoint = FloatPoint3D(anchorPointX, anchorPointY, m_anchorPoint.z() * effectiveContentsScale());
+}
+
+void CoordinatedGraphicsLayer::computeTransformedVisibleRect()
+{
+ if (!m_shouldUpdateVisibleRect && !m_movingVisibleRect)
+ return;
+
+ m_shouldUpdateVisibleRect = false;
+ TransformationMatrix currentTransform = transform();
+ if (m_movingVisibleRect)
+ client()->getCurrentTransform(this, currentTransform);
+ m_layerTransform.setLocalTransform(currentTransform);
+
+ m_layerTransform.setAnchorPoint(m_adjustedAnchorPoint);
+ m_layerTransform.setPosition(m_adjustedPosition);
+ m_layerTransform.setSize(m_adjustedSize);
+
+ m_layerTransform.setFlattening(!preserves3D());
+ m_layerTransform.setChildrenTransform(childrenTransform());
+ m_layerTransform.combineTransforms(parent() ? toCoordinatedGraphicsLayer(parent())->m_layerTransform.combinedForChildren() : TransformationMatrix());
+
+ m_cachedInverseTransform = m_layerTransform.combined().inverse();
+
+ // The combined transform will be used in tiledBackingStoreVisibleRect.
+ setNeedsVisibleRectAdjustment();
+}
+
+bool CoordinatedGraphicsLayer::shouldHaveBackingStore() const
+{
+ return drawsContent() && contentsAreVisible() && !m_size.isEmpty();
+}
+
+bool CoordinatedGraphicsLayer::selfOrAncestorHasActiveTransformAnimation() const
+{
+ if (m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitTransform))
+ return true;
+
+ if (!parent())
+ return false;
+
+ return toCoordinatedGraphicsLayer(parent())->selfOrAncestorHasActiveTransformAnimation();
+}
+
+bool CoordinatedGraphicsLayer::selfOrAncestorHaveNonAffineTransforms()
+{
+ if (m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitTransform))
+ return true;
+
+ if (!m_layerTransform.combined().isAffine())
+ return true;
+
+ if (!parent())
+ return false;
+
+ return toCoordinatedGraphicsLayer(parent())->selfOrAncestorHaveNonAffineTransforms();
+}
+
+bool CoordinatedGraphicsLayer::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double delayAsNegativeTimeOffset)
+{
+ ASSERT(!keyframesName.isEmpty());
+
+ if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyWebkitTransform && valueList.property() != AnimatedPropertyOpacity && valueList.property() != AnimatedPropertyWebkitFilter))
+ return false;
+
+ bool listsMatch = false;
+ bool ignoredHasBigRotation;
+
+ if (valueList.property() == AnimatedPropertyWebkitTransform)
+ listsMatch = validateTransformOperations(valueList, ignoredHasBigRotation) >= 0;
+
+ m_lastAnimationStartTime = WTF::currentTime() - delayAsNegativeTimeOffset;
+ m_animations.add(GraphicsLayerAnimation(keyframesName, valueList, boxSize, anim, m_lastAnimationStartTime, listsMatch));
+ m_animationStartedTimer.startOneShot(0);
+ didChangeAnimations();
+ return true;
+}
+
+void CoordinatedGraphicsLayer::pauseAnimation(const String& animationName, double time)
+{
+ m_animations.pause(animationName, time);
+ didChangeAnimations();
+}
+
+void CoordinatedGraphicsLayer::removeAnimation(const String& animationName)
+{
+ m_animations.remove(animationName);
+ didChangeAnimations();
+}
+
+void CoordinatedGraphicsLayer::suspendAnimations(double time)
+{
+ m_animations.suspend(time);
+ didChangeAnimations();
+}
+
+void CoordinatedGraphicsLayer::resumeAnimations()
+{
+ m_animations.resume();
+ didChangeAnimations();
+}
+
+void CoordinatedGraphicsLayer::animationStartedTimerFired(Timer<CoordinatedGraphicsLayer>*)
+{
+ client()->notifyAnimationStarted(this, m_lastAnimationStartTime);
+}
+} // namespace WebCore
+#endif // USE(COORDINATED_GRAPHICS)
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.h b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.h
new file mode 100644
index 000000000..cfbc2135d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.h
@@ -0,0 +1,264 @@
+/*
+ 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 CoordinatedGraphicsLayer_h
+#define CoordinatedGraphicsLayer_h
+
+#include "CoordinatedGraphicsState.h"
+#include "CoordinatedImageBacking.h"
+#include "CoordinatedTile.h"
+#include "FloatPoint3D.h"
+#include "GraphicsLayer.h"
+#include "GraphicsLayerAnimation.h"
+#include "GraphicsLayerTransform.h"
+#include "Image.h"
+#include "IntSize.h"
+#include "RunLoop.h"
+#include "TiledBackingStore.h"
+#include "TiledBackingStoreClient.h"
+#include "TransformationMatrix.h"
+#if USE(GRAPHICS_SURFACE)
+#include "GraphicsSurfaceToken.h"
+#endif
+#include <wtf/text/StringHash.h>
+
+#if USE(COORDINATED_GRAPHICS)
+
+namespace WebCore {
+class CoordinatedGraphicsLayer;
+class GraphicsLayerAnimations;
+class ScrollableArea;
+
+class CoordinatedGraphicsLayerClient {
+public:
+ virtual bool isFlushingLayerChanges() const = 0;
+ virtual FloatRect visibleContentsRect() const = 0;
+ virtual PassRefPtr<CoordinatedImageBacking> createImageBackingIfNeeded(Image*) = 0;
+ virtual void detachLayer(CoordinatedGraphicsLayer*) = 0;
+ virtual bool paintToSurface(const IntSize&, CoordinatedSurface::Flags, uint32_t& atlasID, IntPoint&, CoordinatedSurface::Client*) = 0;
+
+ virtual void syncLayerState(CoordinatedLayerID, CoordinatedGraphicsLayerState&) = 0;
+};
+
+class CoordinatedGraphicsLayer : public GraphicsLayer
+ , public TiledBackingStoreClient
+ , public CoordinatedImageBacking::Host
+ , public CoordinatedTileClient {
+public:
+ explicit CoordinatedGraphicsLayer(GraphicsLayerClient*);
+ virtual ~CoordinatedGraphicsLayer();
+
+ // Reimplementations from GraphicsLayer.h.
+ virtual bool setChildren(const Vector<GraphicsLayer*>&) OVERRIDE;
+ virtual void addChild(GraphicsLayer*) OVERRIDE;
+ virtual void addChildAtIndex(GraphicsLayer*, int) OVERRIDE;
+ virtual void addChildAbove(GraphicsLayer*, GraphicsLayer*) OVERRIDE;
+ virtual void addChildBelow(GraphicsLayer*, GraphicsLayer*) OVERRIDE;
+ virtual bool replaceChild(GraphicsLayer*, GraphicsLayer*) OVERRIDE;
+ virtual void removeFromParent() OVERRIDE;
+ virtual void setPosition(const FloatPoint&) OVERRIDE;
+ virtual void setAnchorPoint(const FloatPoint3D&) OVERRIDE;
+ virtual void setSize(const FloatSize&) OVERRIDE;
+ virtual void setTransform(const TransformationMatrix&) OVERRIDE;
+ virtual void setChildrenTransform(const TransformationMatrix&) OVERRIDE;
+ virtual void setPreserves3D(bool) OVERRIDE;
+ virtual void setMasksToBounds(bool) OVERRIDE;
+ virtual void setDrawsContent(bool) OVERRIDE;
+ virtual void setContentsVisible(bool) OVERRIDE;
+ virtual void setContentsOpaque(bool) OVERRIDE;
+ virtual void setBackfaceVisibility(bool) OVERRIDE;
+ virtual void setOpacity(float) OVERRIDE;
+ virtual void setContentsRect(const IntRect&) OVERRIDE;
+ virtual void setContentsTilePhase(const IntPoint&) OVERRIDE;
+ virtual void setContentsTileSize(const IntSize&) OVERRIDE;
+ virtual void setContentsToImage(Image*) OVERRIDE;
+ virtual void setContentsToSolidColor(const Color&) OVERRIDE;
+ virtual void setShowDebugBorder(bool) OVERRIDE;
+ virtual void setShowRepaintCounter(bool) OVERRIDE;
+ virtual bool shouldDirectlyCompositeImage(Image*) const OVERRIDE;
+ virtual void setContentsToCanvas(PlatformLayer*) OVERRIDE;
+ virtual void setMaskLayer(GraphicsLayer*) OVERRIDE;
+ virtual void setReplicatedByLayer(GraphicsLayer*) OVERRIDE;
+ virtual void setNeedsDisplay() OVERRIDE;
+ virtual void setNeedsDisplayInRect(const FloatRect&) OVERRIDE;
+ virtual void setContentsNeedsDisplay() OVERRIDE;
+ virtual void deviceOrPageScaleFactorChanged() OVERRIDE;
+ virtual void flushCompositingState(const FloatRect&) OVERRIDE;
+ virtual void flushCompositingStateForThisLayerOnly() OVERRIDE;
+#if ENABLE(CSS_FILTERS)
+ virtual bool setFilters(const FilterOperations&) OVERRIDE;
+#endif
+ virtual bool addAnimation(const KeyframeValueList&, const IntSize&, const Animation*, const String&, double) OVERRIDE;
+ virtual void pauseAnimation(const String&, double) OVERRIDE;
+ virtual void removeAnimation(const String&) OVERRIDE;
+ virtual void suspendAnimations(double time) OVERRIDE;
+ virtual void resumeAnimations() OVERRIDE;
+ virtual bool hasContentsLayer() const OVERRIDE { return m_canvasPlatformLayer || m_compositedImage; }
+
+ void syncPendingStateChangesIncludingSubLayers();
+ void updateContentBuffersIncludingSubLayers();
+
+ FloatPoint computePositionRelativeToBase();
+ void computePixelAlignment(FloatPoint& position, FloatSize&, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset);
+
+ void setVisibleContentRectTrajectoryVector(const FloatPoint&);
+
+ void setScrollableArea(ScrollableArea*);
+ bool isScrollable() const { return !!m_scrollableArea; }
+ void commitScrollOffset(const IntSize&);
+
+ CoordinatedLayerID id() const;
+
+ void setFixedToViewport(bool isFixed);
+
+ IntRect coverRect() const { return m_mainBackingStore ? m_mainBackingStore->mapToContents(m_mainBackingStore->coverRect()) : IntRect(); }
+
+ // TiledBackingStoreClient
+ virtual void tiledBackingStorePaintBegin() OVERRIDE;
+ virtual void tiledBackingStorePaint(GraphicsContext*, const IntRect&) OVERRIDE;
+ virtual void tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea) OVERRIDE;
+ virtual void tiledBackingStoreHasPendingTileCreation() OVERRIDE;
+ virtual IntRect tiledBackingStoreContentsRect() OVERRIDE;
+ virtual IntRect tiledBackingStoreVisibleRect() OVERRIDE;
+ virtual Color tiledBackingStoreBackgroundColor() const OVERRIDE;
+
+ // CoordinatedTileClient
+ virtual void createTile(uint32_t tileID, const SurfaceUpdateInfo&, const IntRect&) OVERRIDE;
+ virtual void updateTile(uint32_t tileID, const SurfaceUpdateInfo&, const IntRect&) OVERRIDE;
+ virtual void removeTile(uint32_t tileID) OVERRIDE;
+ virtual bool paintToSurface(const IntSize&, uint32_t& /* atlasID */, IntPoint&, CoordinatedSurface::Client*) OVERRIDE;
+
+ void setCoordinator(CoordinatedGraphicsLayerClient*);
+
+ void setNeedsVisibleRectAdjustment();
+ void purgeBackingStores();
+ bool hasPendingVisibleChanges();
+
+ static void setShouldSupportContentsTiling(bool);
+ CoordinatedGraphicsLayer* findFirstDescendantWithContentsRecursively();
+
+private:
+#if USE(GRAPHICS_SURFACE)
+ enum PendingCanvasOperation {
+ None = 0x00,
+ CreateCanvas = 0x01,
+ DestroyCanvas = 0x02,
+ SyncCanvas = 0x04,
+ CreateAndSyncCanvas = CreateCanvas | SyncCanvas,
+ RecreateCanvas = CreateAndSyncCanvas | DestroyCanvas
+ };
+
+ void syncCanvas();
+ void destroyCanvasIfNeeded();
+ void createCanvasIfNeeded();
+#endif
+
+ virtual void setDebugBorder(const Color&, float width) OVERRIDE;
+
+ bool fixedToViewport() const { return m_fixedToViewport; }
+
+ void didChangeLayerState();
+ void didChangeAnimations();
+ void didChangeGeometry();
+ void didChangeChildren();
+#if ENABLE(CSS_FILTERS)
+ void didChangeFilters();
+#endif
+ void didChangeImageBacking();
+
+ void resetLayerState();
+ void syncLayerState();
+ void syncAnimations();
+ void syncChildren();
+#if ENABLE(CSS_FILTERS)
+ void syncFilters();
+#endif
+ void syncImageBacking();
+ void computeTransformedVisibleRect();
+ void updateContentBuffers();
+
+ void createBackingStore();
+ void releaseImageBackingIfNeeded();
+
+ // CoordinatedImageBacking::Host
+ virtual bool imageBackingVisible() OVERRIDE;
+ bool shouldHaveBackingStore() const;
+ bool selfOrAncestorHasActiveTransformAnimation() const;
+ bool selfOrAncestorHaveNonAffineTransforms();
+ void adjustContentsScale();
+
+ void setShouldUpdateVisibleRect();
+ float effectiveContentsScale();
+
+ void animationStartedTimerFired(Timer<CoordinatedGraphicsLayer>*);
+
+ CoordinatedLayerID m_id;
+ CoordinatedGraphicsLayerState m_layerState;
+ GraphicsLayerTransform m_layerTransform;
+ TransformationMatrix m_cachedInverseTransform;
+ FloatSize m_pixelAlignmentOffset;
+ FloatSize m_adjustedSize;
+ FloatPoint m_adjustedPosition;
+ FloatPoint3D m_adjustedAnchorPoint;
+
+#ifndef NDEBUG
+ bool m_isPurging;
+#endif
+ bool m_shouldUpdateVisibleRect: 1;
+ bool m_shouldSyncLayerState: 1;
+ bool m_shouldSyncChildren: 1;
+ bool m_shouldSyncFilters: 1;
+ bool m_shouldSyncImageBacking: 1;
+ bool m_shouldSyncAnimations: 1;
+ bool m_fixedToViewport : 1;
+ bool m_movingVisibleRect : 1;
+ bool m_pendingContentsScaleAdjustment : 1;
+ bool m_pendingVisibleRectAdjustment : 1;
+#if USE(GRAPHICS_SURFACE)
+ bool m_isValidCanvas : 1;
+ unsigned m_pendingCanvasOperation : 3;
+#endif
+
+ CoordinatedGraphicsLayerClient* m_coordinator;
+ OwnPtr<TiledBackingStore> m_mainBackingStore;
+ OwnPtr<TiledBackingStore> m_previousBackingStore;
+
+ RefPtr<Image> m_compositedImage;
+ NativeImagePtr m_compositedNativeImagePtr;
+ RefPtr<CoordinatedImageBacking> m_coordinatedImageBacking;
+
+ PlatformLayer* m_canvasPlatformLayer;
+#if USE(GRAPHICS_SURFACE)
+ IntSize m_canvasSize;
+ GraphicsSurfaceToken m_canvasToken;
+#endif
+ Timer<CoordinatedGraphicsLayer> m_animationStartedTimer;
+ GraphicsLayerAnimations m_animations;
+ double m_lastAnimationStartTime;
+
+ ScrollableArea* m_scrollableArea;
+};
+
+CoordinatedGraphicsLayer* toCoordinatedGraphicsLayer(GraphicsLayer*);
+
+} // namespace WebCore
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // CoordinatedGraphicsLayer_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsScene.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsScene.cpp
new file mode 100644
index 000000000..32c7dace4
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsScene.cpp
@@ -0,0 +1,781 @@
+/*
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2012 Company 100, Inc.
+
+ 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"
+
+#if USE(COORDINATED_GRAPHICS)
+
+#include "CoordinatedGraphicsScene.h"
+
+#include "CoordinatedBackingStore.h"
+#include "TextureMapper.h"
+#include "TextureMapperBackingStore.h"
+#include "TextureMapperGL.h"
+#include "TextureMapperLayer.h"
+#include <OpenGLShims.h>
+#include <wtf/Atomics.h>
+#include <wtf/MainThread.h>
+
+#if ENABLE(CSS_SHADERS)
+#include "CoordinatedCustomFilterOperation.h"
+#include "CoordinatedCustomFilterProgram.h"
+#include "CustomFilterProgram.h"
+#include "CustomFilterProgramInfo.h"
+#endif
+
+namespace WebCore {
+
+void CoordinatedGraphicsScene::dispatchOnMainThread(const Function<void()>& function)
+{
+ if (isMainThread())
+ function();
+ else
+ callOnMainThread(function);
+}
+
+static bool layerShouldHaveBackingStore(TextureMapperLayer* layer)
+{
+ return layer->drawsContent() && layer->contentsAreVisible() && !layer->size().isEmpty();
+}
+
+CoordinatedGraphicsScene::CoordinatedGraphicsScene(CoordinatedGraphicsSceneClient* client)
+ : m_client(client)
+ , m_isActive(false)
+ , m_rootLayerID(InvalidCoordinatedLayerID)
+ , m_backgroundColor(Color::white)
+ , m_setDrawsBackground(false)
+{
+ ASSERT(isMainThread());
+}
+
+CoordinatedGraphicsScene::~CoordinatedGraphicsScene()
+{
+}
+
+void CoordinatedGraphicsScene::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity, const FloatRect& clipRect, TextureMapper::PaintFlags PaintFlags)
+{
+ if (!m_textureMapper) {
+ m_textureMapper = TextureMapper::create(TextureMapper::OpenGLMode);
+ static_cast<TextureMapperGL*>(m_textureMapper.get())->setEnableEdgeDistanceAntialiasing(true);
+ }
+
+ ASSERT(m_textureMapper->accelerationMode() == TextureMapper::OpenGLMode);
+ syncRemoteContent();
+
+ adjustPositionForFixedLayers();
+ TextureMapperLayer* currentRootLayer = rootLayer();
+ if (!currentRootLayer)
+ return;
+
+ TextureMapperLayer* layer = currentRootLayer;
+
+ if (!layer)
+ return;
+
+ layer->setTextureMapper(m_textureMapper.get());
+ layer->applyAnimationsRecursively();
+ m_textureMapper->beginPainting(PaintFlags);
+ m_textureMapper->beginClip(TransformationMatrix(), clipRect);
+
+ if (m_setDrawsBackground) {
+ RGBA32 rgba = makeRGBA32FromFloats(m_backgroundColor.red(),
+ m_backgroundColor.green(), m_backgroundColor.blue(),
+ m_backgroundColor.alpha() * opacity);
+ m_textureMapper->drawSolidColor(clipRect, TransformationMatrix(), Color(rgba));
+ }
+
+ if (currentRootLayer->opacity() != opacity || currentRootLayer->transform() != matrix) {
+ currentRootLayer->setOpacity(opacity);
+ currentRootLayer->setTransform(matrix);
+ }
+
+ layer->paint();
+ m_fpsCounter.updateFPSAndDisplay(m_textureMapper.get(), clipRect.location(), matrix);
+ m_textureMapper->endClip();
+ m_textureMapper->endPainting();
+
+ if (layer->descendantsOrSelfHaveRunningAnimations())
+ dispatchOnMainThread(bind(&CoordinatedGraphicsScene::updateViewport, this));
+}
+
+void CoordinatedGraphicsScene::paintToGraphicsContext(PlatformGraphicsContext* platformContext)
+{
+ if (!m_textureMapper)
+ m_textureMapper = TextureMapper::create();
+ ASSERT(m_textureMapper->accelerationMode() == TextureMapper::SoftwareMode);
+ syncRemoteContent();
+ TextureMapperLayer* layer = rootLayer();
+
+ if (!layer)
+ return;
+
+ GraphicsContext graphicsContext(platformContext);
+ m_textureMapper->setGraphicsContext(&graphicsContext);
+ m_textureMapper->beginPainting();
+
+ IntRect clipRect = graphicsContext.clipBounds();
+ if (m_setDrawsBackground)
+ m_textureMapper->drawSolidColor(clipRect, TransformationMatrix(), m_backgroundColor);
+
+ layer->paint();
+ m_fpsCounter.updateFPSAndDisplay(m_textureMapper.get(), clipRect.location());
+ m_textureMapper->endPainting();
+ m_textureMapper->setGraphicsContext(0);
+}
+
+void CoordinatedGraphicsScene::setScrollPosition(const FloatPoint& scrollPosition)
+{
+ m_scrollPosition = scrollPosition;
+}
+
+void CoordinatedGraphicsScene::updateViewport()
+{
+ ASSERT(isMainThread());
+ if (m_client)
+ m_client->updateViewport();
+}
+
+void CoordinatedGraphicsScene::adjustPositionForFixedLayers()
+{
+ if (m_fixedLayers.isEmpty())
+ return;
+
+ // Fixed layer positions are updated by the web process when we update the visible contents rect / scroll position.
+ // If we want those layers to follow accurately the viewport when we move between the web process updates, we have to offset
+ // them by the delta between the current position and the position of the viewport used for the last layout.
+ FloatSize delta = m_scrollPosition - m_renderedContentsScrollPosition;
+
+ LayerRawPtrMap::iterator end = m_fixedLayers.end();
+ for (LayerRawPtrMap::iterator it = m_fixedLayers.begin(); it != end; ++it)
+ it->value->setScrollPositionDeltaIfNeeded(delta);
+}
+
+#if USE(GRAPHICS_SURFACE)
+void CoordinatedGraphicsScene::createCanvasIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
+{
+ if (!state.canvasToken.isValid())
+ return;
+
+ RefPtr<TextureMapperSurfaceBackingStore> canvasBackingStore(TextureMapperSurfaceBackingStore::create());
+ m_surfaceBackingStores.set(layer, canvasBackingStore);
+ canvasBackingStore->setGraphicsSurface(GraphicsSurface::create(state.canvasSize, state.canvasSurfaceFlags, state.canvasToken));
+ layer->setContentsLayer(canvasBackingStore.get());
+}
+
+void CoordinatedGraphicsScene::syncCanvasIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
+{
+ ASSERT(m_textureMapper);
+
+ if (state.canvasChanged) {
+ destroyCanvasIfNeeded(layer, state);
+ createCanvasIfNeeded(layer, state);
+ }
+
+ if (state.canvasShouldSwapBuffers) {
+ ASSERT(m_surfaceBackingStores.contains(layer));
+ SurfaceBackingStoreMap::iterator it = m_surfaceBackingStores.find(layer);
+ RefPtr<TextureMapperSurfaceBackingStore> canvasBackingStore = it->value;
+ canvasBackingStore->swapBuffersIfNeeded(state.canvasFrontBuffer);
+ }
+}
+
+void CoordinatedGraphicsScene::destroyCanvasIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
+{
+ if (state.canvasToken.isValid())
+ return;
+
+ m_surfaceBackingStores.remove(layer);
+ layer->setContentsLayer(0);
+}
+#endif
+
+void CoordinatedGraphicsScene::setLayerRepaintCountIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
+{
+ if (!layer->isShowingRepaintCounter() || !state.repaintCountChanged)
+ return;
+
+ layer->setRepaintCount(state.repaintCount);
+}
+
+void CoordinatedGraphicsScene::setLayerChildrenIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
+{
+ if (!state.childrenChanged)
+ return;
+
+ Vector<TextureMapperLayer*> children;
+
+ for (size_t i = 0; i < state.children.size(); ++i) {
+ CoordinatedLayerID childID = state.children[i];
+ TextureMapperLayer* child = layerByID(childID);
+ children.append(child);
+ }
+ layer->setChildren(children);
+}
+
+#if ENABLE(CSS_FILTERS)
+void CoordinatedGraphicsScene::setLayerFiltersIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
+{
+ if (!state.filtersChanged)
+ return;
+
+#if ENABLE(CSS_SHADERS)
+ injectCachedCustomFilterPrograms(state.filters);
+#endif
+ layer->setFilters(state.filters);
+}
+#endif
+
+#if ENABLE(CSS_SHADERS)
+void CoordinatedGraphicsScene::syncCustomFilterPrograms(const CoordinatedGraphicsState& state)
+{
+ for (size_t i = 0; i < state.customFiltersToCreate.size(); ++i)
+ createCustomFilterProgram(state.customFiltersToCreate[i].first, state.customFiltersToCreate[i].second);
+
+ for (size_t i = 0; i < state.customFiltersToRemove.size(); ++i)
+ removeCustomFilterProgram(state.customFiltersToRemove[i]);
+}
+
+void CoordinatedGraphicsScene::injectCachedCustomFilterPrograms(const FilterOperations& filters) const
+{
+ for (size_t i = 0; i < filters.size(); ++i) {
+ FilterOperation* operation = filters.operations().at(i).get();
+ if (operation->getOperationType() != FilterOperation::CUSTOM)
+ continue;
+
+ CoordinatedCustomFilterOperation* customOperation = static_cast<CoordinatedCustomFilterOperation*>(operation);
+ ASSERT(!customOperation->program());
+ CustomFilterProgramMap::const_iterator iter = m_customFilterPrograms.find(customOperation->programID());
+ ASSERT(iter != m_customFilterPrograms.end());
+ customOperation->setProgram(iter->value.get());
+ }
+}
+
+void CoordinatedGraphicsScene::createCustomFilterProgram(int id, const CustomFilterProgramInfo& programInfo)
+{
+ ASSERT(!m_customFilterPrograms.contains(id));
+ m_customFilterPrograms.set(id, CoordinatedCustomFilterProgram::create(programInfo.vertexShaderString(), programInfo.fragmentShaderString(), programInfo.programType(), programInfo.mixSettings(), programInfo.meshType()));
+}
+
+void CoordinatedGraphicsScene::removeCustomFilterProgram(int id)
+{
+ CustomFilterProgramMap::iterator iter = m_customFilterPrograms.find(id);
+ ASSERT(iter != m_customFilterPrograms.end());
+ if (m_textureMapper)
+ m_textureMapper->removeCachedCustomFilterProgram(iter->value.get());
+ m_customFilterPrograms.remove(iter);
+}
+#endif // ENABLE(CSS_SHADERS)
+
+void CoordinatedGraphicsScene::setLayerState(CoordinatedLayerID id, const CoordinatedGraphicsLayerState& layerState)
+{
+ ASSERT(m_rootLayerID != InvalidCoordinatedLayerID);
+ TextureMapperLayer* layer = layerByID(id);
+
+ if (layerState.positionChanged)
+ layer->setPosition(layerState.pos);
+
+ if (layerState.anchorPointChanged)
+ layer->setAnchorPoint(layerState.anchorPoint);
+
+ if (layerState.sizeChanged)
+ layer->setSize(layerState.size);
+
+ if (layerState.transformChanged)
+ layer->setTransform(layerState.transform);
+
+ if (layerState.childrenTransformChanged)
+ layer->setChildrenTransform(layerState.childrenTransform);
+
+ if (layerState.contentsRectChanged)
+ layer->setContentsRect(layerState.contentsRect);
+
+ if (layerState.contentsTilingChanged) {
+ layer->setContentsTilePhase(layerState.contentsTilePhase);
+ layer->setContentsTileSize(layerState.contentsTileSize);
+ }
+
+ if (layerState.opacityChanged)
+ layer->setOpacity(layerState.opacity);
+
+ if (layerState.solidColorChanged)
+ layer->setSolidColor(layerState.solidColor);
+
+ if (layerState.debugBorderColorChanged || layerState.debugBorderWidthChanged)
+ layer->setDebugVisuals(layerState.showDebugBorders, layerState.debugBorderColor, layerState.debugBorderWidth, layerState.showRepaintCounter);
+
+ if (layerState.replicaChanged)
+ layer->setReplicaLayer(getLayerByIDIfExists(layerState.replica));
+
+ if (layerState.maskChanged)
+ layer->setMaskLayer(getLayerByIDIfExists(layerState.mask));
+
+ if (layerState.imageChanged)
+ assignImageBackingToLayer(layer, layerState.imageID);
+
+ if (layerState.flagsChanged) {
+ layer->setContentsOpaque(layerState.contentsOpaque);
+ layer->setDrawsContent(layerState.drawsContent);
+ layer->setContentsVisible(layerState.contentsVisible);
+ layer->setBackfaceVisibility(layerState.backfaceVisible);
+
+ // Never clip the root layer.
+ layer->setMasksToBounds(id == m_rootLayerID ? false : layerState.masksToBounds);
+ layer->setPreserves3D(layerState.preserves3D);
+
+ bool fixedToViewportChanged = layer->fixedToViewport() != layerState.fixedToViewport;
+ layer->setFixedToViewport(layerState.fixedToViewport);
+ if (fixedToViewportChanged) {
+ if (layerState.fixedToViewport)
+ m_fixedLayers.add(id, layer);
+ else
+ m_fixedLayers.remove(id);
+ }
+
+ layer->setIsScrollable(layerState.isScrollable);
+ }
+
+ if (layerState.committedScrollOffsetChanged)
+ layer->didCommitScrollOffset(layerState.committedScrollOffset);
+
+ prepareContentBackingStore(layer);
+
+ // Apply Operations.
+ setLayerChildrenIfNeeded(layer, layerState);
+ createTilesIfNeeded(layer, layerState);
+ removeTilesIfNeeded(layer, layerState);
+ updateTilesIfNeeded(layer, layerState);
+#if ENABLE(CSS_FILTERS)
+ setLayerFiltersIfNeeded(layer, layerState);
+#endif
+ setLayerAnimationsIfNeeded(layer, layerState);
+#if USE(GRAPHICS_SURFACE)
+ syncCanvasIfNeeded(layer, layerState);
+#endif
+ setLayerRepaintCountIfNeeded(layer, layerState);
+}
+
+TextureMapperLayer* CoordinatedGraphicsScene::getLayerByIDIfExists(CoordinatedLayerID id)
+{
+ return (id != InvalidCoordinatedLayerID) ? layerByID(id) : 0;
+}
+
+void CoordinatedGraphicsScene::createLayers(const Vector<CoordinatedLayerID>& ids)
+{
+ for (size_t index = 0; index < ids.size(); ++index)
+ createLayer(ids[index]);
+}
+
+void CoordinatedGraphicsScene::createLayer(CoordinatedLayerID id)
+{
+ OwnPtr<TextureMapperLayer> newLayer = adoptPtr(new TextureMapperLayer);
+ newLayer->setID(id);
+ newLayer->setScrollClient(this);
+ m_layers.add(id, newLayer.release());
+}
+
+void CoordinatedGraphicsScene::deleteLayers(const Vector<CoordinatedLayerID>& layerIDs)
+{
+ for (size_t index = 0; index < layerIDs.size(); ++index)
+ deleteLayer(layerIDs[index]);
+}
+
+void CoordinatedGraphicsScene::deleteLayer(CoordinatedLayerID layerID)
+{
+ OwnPtr<TextureMapperLayer> layer = m_layers.take(layerID);
+ ASSERT(layer);
+
+ m_backingStores.remove(layer.get());
+ m_fixedLayers.remove(layerID);
+#if USE(GRAPHICS_SURFACE)
+ m_surfaceBackingStores.remove(layer.get());
+#endif
+}
+
+void CoordinatedGraphicsScene::setRootLayerID(CoordinatedLayerID layerID)
+{
+ ASSERT(layerID != InvalidCoordinatedLayerID);
+ ASSERT(m_rootLayerID == InvalidCoordinatedLayerID);
+
+ m_rootLayerID = layerID;
+
+ TextureMapperLayer* layer = layerByID(layerID);
+ ASSERT(m_rootLayer->children().isEmpty());
+ m_rootLayer->addChild(layer);
+}
+
+void CoordinatedGraphicsScene::prepareContentBackingStore(TextureMapperLayer* layer)
+{
+ if (!layerShouldHaveBackingStore(layer)) {
+ removeBackingStoreIfNeeded(layer);
+ return;
+ }
+
+ createBackingStoreIfNeeded(layer);
+ resetBackingStoreSizeToLayerSize(layer);
+}
+
+void CoordinatedGraphicsScene::createBackingStoreIfNeeded(TextureMapperLayer* layer)
+{
+ if (m_backingStores.contains(layer))
+ return;
+
+ RefPtr<CoordinatedBackingStore> backingStore(CoordinatedBackingStore::create());
+ m_backingStores.add(layer, backingStore);
+ layer->setBackingStore(backingStore);
+}
+
+void CoordinatedGraphicsScene::removeBackingStoreIfNeeded(TextureMapperLayer* layer)
+{
+ RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.take(layer);
+ if (!backingStore)
+ return;
+
+ layer->setBackingStore(0);
+}
+
+void CoordinatedGraphicsScene::resetBackingStoreSizeToLayerSize(TextureMapperLayer* layer)
+{
+ RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
+ ASSERT(backingStore);
+ backingStore->setSize(layer->size());
+ m_backingStoresWithPendingBuffers.add(backingStore);
+}
+
+void CoordinatedGraphicsScene::createTilesIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
+{
+ if (state.tilesToCreate.isEmpty())
+ return;
+
+ RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
+ ASSERT(backingStore);
+
+ for (size_t i = 0; i < state.tilesToCreate.size(); ++i)
+ backingStore->createTile(state.tilesToCreate[i].tileID, state.tilesToCreate[i].scale);
+}
+
+void CoordinatedGraphicsScene::removeTilesIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
+{
+ if (state.tilesToRemove.isEmpty())
+ return;
+
+ RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
+ if (!backingStore)
+ return;
+
+ for (size_t i = 0; i < state.tilesToRemove.size(); ++i)
+ backingStore->removeTile(state.tilesToRemove[i]);
+
+ m_backingStoresWithPendingBuffers.add(backingStore);
+}
+
+void CoordinatedGraphicsScene::updateTilesIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
+{
+ if (state.tilesToUpdate.isEmpty())
+ return;
+
+ RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
+ ASSERT(backingStore);
+
+ for (size_t i = 0; i < state.tilesToUpdate.size(); ++i) {
+ const TileUpdateInfo& tileInfo = state.tilesToUpdate[i];
+ const SurfaceUpdateInfo& surfaceUpdateInfo = tileInfo.updateInfo;
+
+ SurfaceMap::iterator surfaceIt = m_surfaces.find(surfaceUpdateInfo.atlasID);
+ ASSERT(surfaceIt != m_surfaces.end());
+
+ backingStore->updateTile(tileInfo.tileID, surfaceUpdateInfo.updateRect, tileInfo.tileRect, surfaceIt->value, surfaceUpdateInfo.surfaceOffset);
+ m_backingStoresWithPendingBuffers.add(backingStore);
+ }
+}
+
+void CoordinatedGraphicsScene::syncUpdateAtlases(const CoordinatedGraphicsState& state)
+{
+ for (size_t i = 0; i < state.updateAtlasesToCreate.size(); ++i)
+ createUpdateAtlas(state.updateAtlasesToCreate[i].first, state.updateAtlasesToCreate[i].second);
+
+ for (size_t i = 0; i < state.updateAtlasesToRemove.size(); ++i)
+ removeUpdateAtlas(state.updateAtlasesToRemove[i]);
+}
+
+void CoordinatedGraphicsScene::createUpdateAtlas(uint32_t atlasID, PassRefPtr<CoordinatedSurface> surface)
+{
+ ASSERT(!m_surfaces.contains(atlasID));
+ m_surfaces.add(atlasID, surface);
+}
+
+void CoordinatedGraphicsScene::removeUpdateAtlas(uint32_t atlasID)
+{
+ ASSERT(m_surfaces.contains(atlasID));
+ m_surfaces.remove(atlasID);
+}
+
+void CoordinatedGraphicsScene::syncImageBackings(const CoordinatedGraphicsState& state)
+{
+ for (size_t i = 0; i < state.imagesToRemove.size(); ++i)
+ removeImageBacking(state.imagesToRemove[i]);
+
+ for (size_t i = 0; i < state.imagesToCreate.size(); ++i)
+ createImageBacking(state.imagesToCreate[i]);
+
+ for (size_t i = 0; i < state.imagesToUpdate.size(); ++i)
+ updateImageBacking(state.imagesToUpdate[i].first, state.imagesToUpdate[i].second);
+
+ for (size_t i = 0; i < state.imagesToClear.size(); ++i)
+ clearImageBackingContents(state.imagesToClear[i]);
+}
+
+void CoordinatedGraphicsScene::createImageBacking(CoordinatedImageBackingID imageID)
+{
+ ASSERT(!m_imageBackings.contains(imageID));
+ RefPtr<CoordinatedBackingStore> backingStore(CoordinatedBackingStore::create());
+ m_imageBackings.add(imageID, backingStore.release());
+}
+
+void CoordinatedGraphicsScene::updateImageBacking(CoordinatedImageBackingID imageID, PassRefPtr<CoordinatedSurface> surface)
+{
+ ASSERT(m_imageBackings.contains(imageID));
+ ImageBackingMap::iterator it = m_imageBackings.find(imageID);
+ RefPtr<CoordinatedBackingStore> backingStore = it->value;
+
+ // CoordinatedImageBacking is realized to CoordinatedBackingStore with only one tile in UI Process.
+ backingStore->createTile(1 /* id */, 1 /* scale */);
+ IntRect rect(IntPoint::zero(), surface->size());
+ // See CoordinatedGraphicsLayer::shouldDirectlyCompositeImage()
+ ASSERT(2000 >= std::max(rect.width(), rect.height()));
+ backingStore->setSize(rect.size());
+ backingStore->updateTile(1 /* id */, rect, rect, surface, rect.location());
+
+ m_backingStoresWithPendingBuffers.add(backingStore);
+}
+
+void CoordinatedGraphicsScene::clearImageBackingContents(CoordinatedImageBackingID imageID)
+{
+ ASSERT(m_imageBackings.contains(imageID));
+ ImageBackingMap::iterator it = m_imageBackings.find(imageID);
+ RefPtr<CoordinatedBackingStore> backingStore = it->value;
+ backingStore->removeAllTiles();
+ m_backingStoresWithPendingBuffers.add(backingStore);
+}
+
+void CoordinatedGraphicsScene::removeImageBacking(CoordinatedImageBackingID imageID)
+{
+ ASSERT(m_imageBackings.contains(imageID));
+
+ // We don't want TextureMapperLayer refers a dangling pointer.
+ m_releasedImageBackings.append(m_imageBackings.take(imageID));
+}
+
+void CoordinatedGraphicsScene::assignImageBackingToLayer(TextureMapperLayer* layer, CoordinatedImageBackingID imageID)
+{
+#if USE(GRAPHICS_SURFACE)
+ if (m_surfaceBackingStores.contains(layer))
+ return;
+#endif
+
+ if (imageID == InvalidCoordinatedImageBackingID) {
+ layer->setContentsLayer(0);
+ return;
+ }
+
+ ImageBackingMap::iterator it = m_imageBackings.find(imageID);
+ ASSERT(it != m_imageBackings.end());
+ layer->setContentsLayer(it->value.get());
+}
+
+void CoordinatedGraphicsScene::removeReleasedImageBackingsIfNeeded()
+{
+ m_releasedImageBackings.clear();
+}
+
+void CoordinatedGraphicsScene::commitPendingBackingStoreOperations()
+{
+ HashSet<RefPtr<CoordinatedBackingStore> >::iterator end = m_backingStoresWithPendingBuffers.end();
+ for (HashSet<RefPtr<CoordinatedBackingStore> >::iterator it = m_backingStoresWithPendingBuffers.begin(); it != end; ++it)
+ (*it)->commitTileOperations(m_textureMapper.get());
+
+ m_backingStoresWithPendingBuffers.clear();
+}
+
+void CoordinatedGraphicsScene::commitSceneState(const CoordinatedGraphicsState& state)
+{
+ m_renderedContentsScrollPosition = state.scrollPosition;
+
+ createLayers(state.layersToCreate);
+ deleteLayers(state.layersToRemove);
+
+ if (state.rootCompositingLayer != m_rootLayerID)
+ setRootLayerID(state.rootCompositingLayer);
+
+ syncImageBackings(state);
+ syncUpdateAtlases(state);
+#if ENABLE(CSS_SHADERS)
+ syncCustomFilterPrograms(state);
+#endif
+
+ for (size_t i = 0; i < state.layersToUpdate.size(); ++i)
+ setLayerState(state.layersToUpdate[i].first, state.layersToUpdate[i].second);
+
+ commitPendingBackingStoreOperations();
+ removeReleasedImageBackingsIfNeeded();
+
+ // The pending tiles state is on its way for the screen, tell the web process to render the next one.
+ dispatchOnMainThread(bind(&CoordinatedGraphicsScene::renderNextFrame, this));
+}
+
+void CoordinatedGraphicsScene::renderNextFrame()
+{
+ if (m_client)
+ m_client->renderNextFrame();
+}
+
+void CoordinatedGraphicsScene::ensureRootLayer()
+{
+ if (m_rootLayer)
+ return;
+
+ m_rootLayer = adoptPtr(new TextureMapperLayer);
+ m_rootLayer->setMasksToBounds(false);
+ m_rootLayer->setDrawsContent(false);
+ m_rootLayer->setAnchorPoint(FloatPoint3D(0, 0, 0));
+
+ // The root layer should not have zero size, or it would be optimized out.
+ m_rootLayer->setSize(FloatSize(1.0, 1.0));
+
+ ASSERT(m_textureMapper);
+ m_rootLayer->setTextureMapper(m_textureMapper.get());
+}
+
+void CoordinatedGraphicsScene::syncRemoteContent()
+{
+ // We enqueue messages and execute them during paint, as they require an active GL context.
+ ensureRootLayer();
+
+ Vector<Function<void()> > renderQueue;
+ bool calledOnMainThread = WTF::isMainThread();
+ if (!calledOnMainThread)
+ m_renderQueueMutex.lock();
+ renderQueue.swap(m_renderQueue);
+ if (!calledOnMainThread)
+ m_renderQueueMutex.unlock();
+
+ for (size_t i = 0; i < renderQueue.size(); ++i)
+ renderQueue[i]();
+}
+
+void CoordinatedGraphicsScene::purgeGLResources()
+{
+ m_imageBackings.clear();
+ m_releasedImageBackings.clear();
+#if USE(GRAPHICS_SURFACE)
+ m_surfaceBackingStores.clear();
+#endif
+ m_surfaces.clear();
+
+ m_rootLayer.clear();
+ m_rootLayerID = InvalidCoordinatedLayerID;
+ m_layers.clear();
+ m_fixedLayers.clear();
+ m_textureMapper.clear();
+ m_backingStores.clear();
+ m_backingStoresWithPendingBuffers.clear();
+
+ setActive(false);
+ dispatchOnMainThread(bind(&CoordinatedGraphicsScene::purgeBackingStores, this));
+}
+
+void CoordinatedGraphicsScene::dispatchCommitScrollOffset(uint32_t layerID, const IntSize& offset)
+{
+ m_client->commitScrollOffset(layerID, offset);
+}
+
+void CoordinatedGraphicsScene::commitScrollOffset(uint32_t layerID, const IntSize& offset)
+{
+ dispatchOnMainThread(bind(&CoordinatedGraphicsScene::dispatchCommitScrollOffset, this, layerID, offset));
+}
+
+void CoordinatedGraphicsScene::purgeBackingStores()
+{
+ if (m_client)
+ m_client->purgeBackingStores();
+}
+
+void CoordinatedGraphicsScene::setLayerAnimationsIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
+{
+ if (!state.animationsChanged)
+ return;
+
+#if ENABLE(CSS_SHADERS)
+ for (size_t i = 0; i < state.animations.animations().size(); ++i) {
+ const KeyframeValueList& keyframes = state.animations.animations().at(i).keyframes();
+ if (keyframes.property() != AnimatedPropertyWebkitFilter)
+ continue;
+ for (size_t j = 0; j < keyframes.size(); ++j) {
+ const FilterAnimationValue& filterValue = static_cast<const FilterAnimationValue&>(keyframes.at(j));
+ injectCachedCustomFilterPrograms(filterValue.value());
+ }
+ }
+#endif
+ layer->setAnimations(state.animations);
+}
+
+void CoordinatedGraphicsScene::detach()
+{
+ ASSERT(isMainThread());
+ m_renderQueue.clear();
+ m_client = 0;
+}
+
+void CoordinatedGraphicsScene::appendUpdate(const Function<void()>& function)
+{
+ if (!m_isActive)
+ return;
+
+ ASSERT(isMainThread());
+ MutexLocker locker(m_renderQueueMutex);
+ m_renderQueue.append(function);
+}
+
+void CoordinatedGraphicsScene::setActive(bool active)
+{
+ if (m_isActive == active)
+ return;
+
+ // Have to clear render queue in both cases.
+ // If there are some updates in queue during activation then those updates are from previous instance of paint node
+ // and cannot be applied to the newly created instance.
+ m_renderQueue.clear();
+ m_isActive = active;
+ if (m_isActive)
+ dispatchOnMainThread(bind(&CoordinatedGraphicsScene::renderNextFrame, this));
+}
+
+void CoordinatedGraphicsScene::setBackgroundColor(const Color& color)
+{
+ m_backgroundColor = color;
+}
+
+TextureMapperLayer* CoordinatedGraphicsScene::findScrollableContentsLayerAt(const FloatPoint& point)
+{
+ return rootLayer() ? rootLayer()->findScrollableContentsLayerAt(point) : 0;
+}
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsScene.h b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsScene.h
new file mode 100644
index 000000000..7fa92ad87
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsScene.h
@@ -0,0 +1,209 @@
+/*
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2013 Company 100, Inc.
+
+ 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 CoordinatedGraphicsScene_h
+#define CoordinatedGraphicsScene_h
+
+#if USE(COORDINATED_GRAPHICS)
+#include "CoordinatedGraphicsState.h"
+#include "CoordinatedSurface.h"
+#include "GraphicsContext.h"
+#include "GraphicsLayer.h"
+#include "GraphicsLayerAnimation.h"
+#include "GraphicsSurface.h"
+#include "IntRect.h"
+#include "IntSize.h"
+#include "RunLoop.h"
+#include "TextureMapper.h"
+#include "TextureMapperBackingStore.h"
+#include "TextureMapperFPSCounter.h"
+#include "TextureMapperLayer.h"
+#include "Timer.h"
+#include <wtf/Functional.h>
+#include <wtf/HashSet.h>
+#include <wtf/ThreadingPrimitives.h>
+#include <wtf/Vector.h>
+
+#if USE(GRAPHICS_SURFACE)
+#include "TextureMapperSurfaceBackingStore.h"
+#endif
+
+namespace WebCore {
+
+class CoordinatedBackingStore;
+class CustomFilterProgram;
+class CustomFilterProgramInfo;
+
+class CoordinatedGraphicsSceneClient {
+public:
+ virtual ~CoordinatedGraphicsSceneClient() { }
+ virtual void purgeBackingStores() = 0;
+ virtual void renderNextFrame() = 0;
+ virtual void updateViewport() = 0;
+ virtual void commitScrollOffset(uint32_t layerID, const IntSize& offset) = 0;
+};
+
+class CoordinatedGraphicsScene : public ThreadSafeRefCounted<CoordinatedGraphicsScene>, public TextureMapperLayer::ScrollingClient {
+public:
+ explicit CoordinatedGraphicsScene(CoordinatedGraphicsSceneClient*);
+ virtual ~CoordinatedGraphicsScene();
+ void paintToCurrentGLContext(const TransformationMatrix&, float, const FloatRect&, TextureMapper::PaintFlags = 0);
+ void paintToGraphicsContext(PlatformGraphicsContext*);
+ void setScrollPosition(const FloatPoint&);
+ void detach();
+ void appendUpdate(const Function<void()>&);
+
+ WebCore::TextureMapperLayer* findScrollableContentsLayerAt(const WebCore::FloatPoint&);
+
+ virtual void commitScrollOffset(uint32_t layerID, const IntSize& offset);
+
+ // The painting thread must lock the main thread to use below two methods, because two methods access members that the main thread manages. See m_client.
+ // Currently, QQuickWebPage::updatePaintNode() locks the main thread before calling both methods.
+ void purgeGLResources();
+ void setActive(bool);
+
+ void commitSceneState(const CoordinatedGraphicsState&);
+
+ void setBackgroundColor(const Color&);
+ void setDrawsBackground(bool enable) { m_setDrawsBackground = enable; }
+
+private:
+ void setRootLayerID(CoordinatedLayerID);
+ void createLayers(const Vector<CoordinatedLayerID>&);
+ void deleteLayers(const Vector<CoordinatedLayerID>&);
+ void setLayerState(CoordinatedLayerID, const CoordinatedGraphicsLayerState&);
+ void setLayerChildrenIfNeeded(TextureMapperLayer*, const CoordinatedGraphicsLayerState&);
+ void updateTilesIfNeeded(TextureMapperLayer*, const CoordinatedGraphicsLayerState&);
+ void createTilesIfNeeded(TextureMapperLayer*, const CoordinatedGraphicsLayerState&);
+ void removeTilesIfNeeded(TextureMapperLayer*, const CoordinatedGraphicsLayerState&);
+#if ENABLE(CSS_FILTERS)
+ void setLayerFiltersIfNeeded(TextureMapperLayer*, const CoordinatedGraphicsLayerState&);
+#endif
+ void setLayerAnimationsIfNeeded(TextureMapperLayer*, const CoordinatedGraphicsLayerState&);
+#if USE(GRAPHICS_SURFACE)
+ void createCanvasIfNeeded(TextureMapperLayer*, const CoordinatedGraphicsLayerState&);
+ void syncCanvasIfNeeded(TextureMapperLayer*, const CoordinatedGraphicsLayerState&);
+ void destroyCanvasIfNeeded(TextureMapperLayer*, const CoordinatedGraphicsLayerState&);
+#endif
+ void setLayerRepaintCountIfNeeded(TextureMapperLayer*, const CoordinatedGraphicsLayerState&);
+
+ void syncUpdateAtlases(const CoordinatedGraphicsState&);
+ void createUpdateAtlas(uint32_t atlasID, PassRefPtr<CoordinatedSurface>);
+ void removeUpdateAtlas(uint32_t atlasID);
+
+ void syncImageBackings(const CoordinatedGraphicsState&);
+ void createImageBacking(CoordinatedImageBackingID);
+ void updateImageBacking(CoordinatedImageBackingID, PassRefPtr<CoordinatedSurface>);
+ void clearImageBackingContents(CoordinatedImageBackingID);
+ void removeImageBacking(CoordinatedImageBackingID);
+
+#if ENABLE(CSS_SHADERS)
+ void syncCustomFilterPrograms(const CoordinatedGraphicsState&);
+ void injectCachedCustomFilterPrograms(const FilterOperations& filters) const;
+ void createCustomFilterProgram(int id, const CustomFilterProgramInfo&);
+ void removeCustomFilterProgram(int id);
+#endif
+
+ TextureMapperLayer* layerByID(CoordinatedLayerID id)
+ {
+ ASSERT(m_layers.contains(id));
+ ASSERT(id != InvalidCoordinatedLayerID);
+ return m_layers.get(id);
+ }
+ TextureMapperLayer* getLayerByIDIfExists(CoordinatedLayerID);
+ TextureMapperLayer* rootLayer() { return m_rootLayer.get(); }
+
+ void syncRemoteContent();
+ void adjustPositionForFixedLayers();
+
+ void dispatchOnMainThread(const Function<void()>&);
+ void updateViewport();
+ void renderNextFrame();
+ void purgeBackingStores();
+
+ void createLayer(CoordinatedLayerID);
+ void deleteLayer(CoordinatedLayerID);
+
+ void assignImageBackingToLayer(TextureMapperLayer*, CoordinatedImageBackingID);
+ void removeReleasedImageBackingsIfNeeded();
+ void ensureRootLayer();
+ void commitPendingBackingStoreOperations();
+
+ void prepareContentBackingStore(TextureMapperLayer*);
+ void createBackingStoreIfNeeded(TextureMapperLayer*);
+ void removeBackingStoreIfNeeded(TextureMapperLayer*);
+ void resetBackingStoreSizeToLayerSize(TextureMapperLayer*);
+
+ void dispatchCommitScrollOffset(uint32_t layerID, const IntSize& offset);
+
+ // Render queue can be accessed ony from main thread or updatePaintNode call stack!
+ Vector<Function<void()> > m_renderQueue;
+ Mutex m_renderQueueMutex;
+
+ OwnPtr<TextureMapper> m_textureMapper;
+
+ typedef HashMap<CoordinatedImageBackingID, RefPtr<CoordinatedBackingStore> > ImageBackingMap;
+ ImageBackingMap m_imageBackings;
+ Vector<RefPtr<CoordinatedBackingStore> > m_releasedImageBackings;
+
+ typedef HashMap<TextureMapperLayer*, RefPtr<CoordinatedBackingStore> > BackingStoreMap;
+ BackingStoreMap m_backingStores;
+
+ HashSet<RefPtr<CoordinatedBackingStore> > m_backingStoresWithPendingBuffers;
+
+#if USE(GRAPHICS_SURFACE)
+ typedef HashMap<TextureMapperLayer*, RefPtr<TextureMapperSurfaceBackingStore> > SurfaceBackingStoreMap;
+ SurfaceBackingStoreMap m_surfaceBackingStores;
+#endif
+
+ typedef HashMap<uint32_t /* atlasID */, RefPtr<CoordinatedSurface> > SurfaceMap;
+ SurfaceMap m_surfaces;
+
+ // Below two members are accessed by only the main thread. The painting thread must lock the main thread to access both members.
+ CoordinatedGraphicsSceneClient* m_client;
+ bool m_isActive;
+
+ OwnPtr<TextureMapperLayer> m_rootLayer;
+
+ typedef HashMap<CoordinatedLayerID, OwnPtr<TextureMapperLayer> > LayerMap;
+ LayerMap m_layers;
+ typedef HashMap<CoordinatedLayerID, TextureMapperLayer*> LayerRawPtrMap;
+ LayerRawPtrMap m_fixedLayers;
+ CoordinatedLayerID m_rootLayerID;
+ FloatPoint m_scrollPosition;
+ FloatPoint m_renderedContentsScrollPosition;
+ Color m_backgroundColor;
+ bool m_setDrawsBackground;
+
+#if ENABLE(CSS_SHADERS)
+ typedef HashMap<int, RefPtr<CustomFilterProgram> > CustomFilterProgramMap;
+ CustomFilterProgramMap m_customFilterPrograms;
+#endif
+
+ TextureMapperFPSCounter m_fpsCounter;
+};
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // CoordinatedGraphicsScene_h
+
+
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsState.h b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsState.h
new file mode 100644
index 000000000..5445e62ff
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsState.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2013 Company 100, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CoordinatedGraphicsState_h
+#define CoordinatedGraphicsState_h
+
+#if USE(COORDINATED_GRAPHICS)
+
+#include "Color.h"
+#include "FloatRect.h"
+#include "FloatSize.h"
+#include "GraphicsLayerAnimation.h"
+#include "IntRect.h"
+#include "IntSize.h"
+#include "SurfaceUpdateInfo.h"
+#include "TransformationMatrix.h"
+
+#if ENABLE(CSS_FILTERS)
+#include "FilterOperations.h"
+#endif
+
+#if ENABLE(CSS_FILTERS)
+#include "CustomFilterProgramInfo.h"
+#endif
+
+#if USE(GRAPHICS_SURFACE)
+#include "GraphicsSurface.h"
+#include "GraphicsSurfaceToken.h"
+#endif
+
+namespace WebCore {
+
+class CoordinatedSurface;
+
+typedef uint32_t CoordinatedLayerID;
+enum { InvalidCoordinatedLayerID = 0 };
+
+typedef uint64_t CoordinatedImageBackingID;
+enum { InvalidCoordinatedImageBackingID = 0 };
+
+struct TileUpdateInfo {
+ uint32_t tileID;
+ IntRect tileRect;
+ WebCore::SurfaceUpdateInfo updateInfo;
+};
+
+struct TileCreationInfo {
+ uint32_t tileID;
+ float scale;
+};
+
+struct CoordinatedGraphicsLayerState {
+ union {
+ struct {
+ bool positionChanged: 1;
+ bool anchorPointChanged: 1;
+ bool sizeChanged: 1;
+ bool transformChanged: 1;
+ bool childrenTransformChanged: 1;
+ bool contentsRectChanged: 1;
+ bool opacityChanged: 1;
+ bool solidColorChanged: 1;
+ bool debugBorderColorChanged: 1;
+ bool debugBorderWidthChanged: 1;
+ bool replicaChanged: 1;
+ bool maskChanged: 1;
+ bool imageChanged: 1;
+ bool flagsChanged: 1;
+ bool animationsChanged: 1;
+ bool filtersChanged: 1;
+ bool childrenChanged: 1;
+ bool repaintCountChanged : 1;
+ bool canvasChanged: 1;
+ bool canvasShouldSwapBuffers: 1;
+ bool isScrollableChanged: 1;
+ bool committedScrollOffsetChanged: 1;
+ bool contentsTilingChanged: 1;
+ };
+ unsigned changeMask;
+ };
+ union {
+ struct {
+ bool contentsOpaque : 1;
+ bool drawsContent : 1;
+ bool contentsVisible : 1;
+ bool backfaceVisible : 1;
+ bool masksToBounds : 1;
+ bool preserves3D : 1;
+ bool fixedToViewport : 1;
+ bool showDebugBorders : 1;
+ bool showRepaintCounter : 1;
+ bool isScrollable: 1;
+ };
+ unsigned flags;
+ };
+
+ CoordinatedGraphicsLayerState()
+ : changeMask(0)
+ , contentsOpaque(false)
+ , drawsContent(false)
+ , contentsVisible(true)
+ , backfaceVisible(true)
+ , masksToBounds(false)
+ , preserves3D(false)
+ , fixedToViewport(false)
+ , showDebugBorders(false)
+ , showRepaintCounter(false)
+ , isScrollable(false)
+ , opacity(0)
+ , debugBorderWidth(0)
+ , replica(InvalidCoordinatedLayerID)
+ , mask(InvalidCoordinatedLayerID)
+ , imageID(InvalidCoordinatedImageBackingID)
+#if USE(GRAPHICS_SURFACE)
+ , canvasFrontBuffer(0)
+#endif
+ {
+ }
+
+ FloatPoint pos;
+ FloatPoint3D anchorPoint;
+ FloatSize size;
+ TransformationMatrix transform;
+ TransformationMatrix childrenTransform;
+ IntRect contentsRect;
+ IntPoint contentsTilePhase;
+ IntSize contentsTileSize;
+ float opacity;
+ Color solidColor;
+ Color debugBorderColor;
+ float debugBorderWidth;
+#if ENABLE(CSS_FILTERS)
+ FilterOperations filters;
+#endif
+ GraphicsLayerAnimations animations;
+ Vector<uint32_t> children;
+ Vector<TileCreationInfo> tilesToCreate;
+ Vector<uint32_t> tilesToRemove;
+ CoordinatedLayerID replica;
+ CoordinatedLayerID mask;
+ CoordinatedImageBackingID imageID;
+
+ unsigned repaintCount;
+ Vector<TileUpdateInfo> tilesToUpdate;
+
+#if USE(GRAPHICS_SURFACE)
+ IntSize canvasSize;
+ GraphicsSurfaceToken canvasToken;
+ uint32_t canvasFrontBuffer;
+ GraphicsSurface::Flags canvasSurfaceFlags;
+#endif
+
+ IntSize committedScrollOffset;
+
+ bool hasPendingChanges() const
+ {
+ return changeMask || tilesToUpdate.size() || tilesToRemove.size() || tilesToCreate.size();
+ }
+};
+
+struct CoordinatedGraphicsState {
+ uint32_t rootCompositingLayer;
+ FloatPoint scrollPosition;
+ IntSize contentsSize;
+ IntRect coveredRect;
+
+ Vector<CoordinatedLayerID> layersToCreate;
+ Vector<std::pair<CoordinatedLayerID, CoordinatedGraphicsLayerState> > layersToUpdate;
+ Vector<CoordinatedLayerID> layersToRemove;
+
+ Vector<CoordinatedImageBackingID> imagesToCreate;
+ Vector<CoordinatedImageBackingID> imagesToRemove;
+ Vector<std::pair<CoordinatedImageBackingID, RefPtr<CoordinatedSurface> > > imagesToUpdate;
+ Vector<CoordinatedImageBackingID> imagesToClear;
+
+ Vector<std::pair<uint32_t /* atlasID */, RefPtr<CoordinatedSurface> > > updateAtlasesToCreate;
+ Vector<uint32_t /* atlasID */> updateAtlasesToRemove;
+
+#if ENABLE(CSS_SHADERS)
+ Vector<std::pair<uint32_t /* FilterID */, CustomFilterProgramInfo> > customFiltersToCreate;
+ Vector<uint32_t> customFiltersToRemove;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // CoordinatedGraphicsState_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.cpp
new file mode 100644
index 000000000..5ca430b47
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2012 Company 100, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(COORDINATED_GRAPHICS)
+#include "CoordinatedImageBacking.h"
+
+#include "CoordinatedGraphicsState.h"
+#include "GraphicsContext.h"
+
+namespace WebCore {
+
+class ImageBackingSurfaceClient : public CoordinatedSurface::Client {
+public:
+ ImageBackingSurfaceClient(Image* image, const IntRect& rect)
+ : m_image(image)
+ , m_rect(rect)
+ {
+ }
+
+ virtual void paintToSurfaceContext(GraphicsContext* context) OVERRIDE
+ {
+ context->drawImage(m_image, ColorSpaceDeviceRGB, m_rect, m_rect);
+ }
+
+private:
+ Image* m_image;
+ IntRect m_rect;
+};
+
+CoordinatedImageBackingID CoordinatedImageBacking::getCoordinatedImageBackingID(Image* image)
+{
+ // CoordinatedImageBacking keeps a RefPtr<Image> member, so the same Image pointer can not refer two different instances until CoordinatedImageBacking releases the member.
+ return reinterpret_cast<CoordinatedImageBackingID>(image);
+}
+
+PassRefPtr<CoordinatedImageBacking> CoordinatedImageBacking::create(Client* client, PassRefPtr<Image> image)
+{
+ return adoptRef(new CoordinatedImageBacking(client, image));
+}
+
+CoordinatedImageBacking::CoordinatedImageBacking(Client* client, PassRefPtr<Image> image)
+ : m_client(client)
+ , m_image(image)
+ , m_id(getCoordinatedImageBackingID(m_image.get()))
+ , m_clearContentsTimer(this, &CoordinatedImageBacking::clearContentsTimerFired)
+ , m_isDirty(false)
+ , m_isVisible(false)
+{
+ // FIXME: We would need to decode a small image directly into a GraphicsSurface.
+ // http://webkit.org/b/101426
+
+ m_client->createImageBacking(id());
+}
+
+CoordinatedImageBacking::~CoordinatedImageBacking()
+{
+}
+
+void CoordinatedImageBacking::addHost(Host* host)
+{
+ ASSERT(!m_hosts.contains(host));
+ m_hosts.append(host);
+}
+
+void CoordinatedImageBacking::removeHost(Host* host)
+{
+ size_t position = m_hosts.find(host);
+ ASSERT(position != notFound);
+ m_hosts.remove(position);
+
+ if (m_hosts.isEmpty())
+ m_client->removeImageBacking(id());
+}
+
+void CoordinatedImageBacking::markDirty()
+{
+ m_isDirty = true;
+}
+
+void CoordinatedImageBacking::update()
+{
+ releaseSurfaceIfNeeded();
+
+ bool changedToVisible;
+ updateVisibilityIfNeeded(changedToVisible);
+ if (!m_isVisible)
+ return;
+
+ if (!changedToVisible) {
+ if (!m_isDirty)
+ return;
+
+ if (m_nativeImagePtr == m_image->nativeImageForCurrentFrame()) {
+ m_isDirty = false;
+ return;
+ }
+ }
+
+ m_surface = CoordinatedSurface::create(m_image->size(), !m_image->currentFrameKnownToBeOpaque() ? CoordinatedSurface::SupportsAlpha : CoordinatedSurface::NoFlags);
+ if (!m_surface) {
+ m_isDirty = false;
+ return;
+ }
+
+ IntRect rect(IntPoint::zero(), m_image->size());
+
+ ImageBackingSurfaceClient surfaceClient(m_image.get(), rect);
+ m_surface->paintToSurface(rect, &surfaceClient);
+
+ m_nativeImagePtr = m_image->nativeImageForCurrentFrame();
+
+ m_client->updateImageBacking(id(), m_surface);
+ m_isDirty = false;
+}
+
+void CoordinatedImageBacking::releaseSurfaceIfNeeded()
+{
+ // We must keep m_surface until UI Process reads m_surface.
+ // If m_surface exists, it was created in the previous update.
+ m_surface.clear();
+}
+
+static const double clearContentsTimerInterval = 3;
+
+void CoordinatedImageBacking::updateVisibilityIfNeeded(bool& changedToVisible)
+{
+ bool previousIsVisible = m_isVisible;
+
+ m_isVisible = false;
+ for (size_t i = 0; i < m_hosts.size(); ++i) {
+ if (m_hosts[i]->imageBackingVisible()) {
+ m_isVisible = true;
+ break;
+ }
+ }
+
+ bool changedToInvisible = previousIsVisible && !m_isVisible;
+ if (changedToInvisible) {
+ ASSERT(!m_clearContentsTimer.isActive());
+ m_clearContentsTimer.startOneShot(clearContentsTimerInterval);
+ }
+
+ changedToVisible = !previousIsVisible && m_isVisible;
+
+ if (m_isVisible && m_clearContentsTimer.isActive()) {
+ m_clearContentsTimer.stop();
+ // We don't want to update the texture if we didn't remove the texture.
+ changedToVisible = false;
+ }
+}
+
+void CoordinatedImageBacking::clearContentsTimerFired(Timer<CoordinatedImageBacking>*)
+{
+ m_client->clearImageBackingContents(id());
+}
+
+} // namespace WebCore
+#endif
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.h b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.h
new file mode 100644
index 000000000..711e491fe
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedImageBacking.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 Company 100, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef CoordinatedImageBacking_h
+#define CoordinatedImageBacking_h
+
+#if USE(COORDINATED_GRAPHICS)
+#include "CoordinatedGraphicsState.h"
+#include "CoordinatedSurface.h"
+#include "Image.h"
+#include "Timer.h"
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CoordinatedImageBacking : public RefCounted<CoordinatedImageBacking> {
+public:
+ class Client {
+ public:
+ virtual void createImageBacking(CoordinatedImageBackingID) = 0;
+ virtual void updateImageBacking(CoordinatedImageBackingID, PassRefPtr<CoordinatedSurface>) = 0;
+ virtual void clearImageBackingContents(CoordinatedImageBackingID) = 0;
+ virtual void removeImageBacking(CoordinatedImageBackingID) = 0;
+ };
+
+ class Host {
+ public:
+ virtual bool imageBackingVisible() = 0;
+ };
+
+ static PassRefPtr<CoordinatedImageBacking> create(Client*, PassRefPtr<Image>);
+ virtual ~CoordinatedImageBacking();
+
+ static CoordinatedImageBackingID getCoordinatedImageBackingID(Image*);
+ CoordinatedImageBackingID id() const { return m_id; }
+
+ void addHost(Host*);
+ void removeHost(Host*);
+
+ // When a new image is updated or an animated gif is progressed, CoordinatedGraphicsLayer calls markDirty().
+ void markDirty();
+
+ // Create, remove or update its backing.
+ void update();
+
+private:
+ CoordinatedImageBacking(Client*, PassRefPtr<Image>);
+
+ void releaseSurfaceIfNeeded();
+ void updateVisibilityIfNeeded(bool& changedToVisible);
+ void clearContentsTimerFired(Timer<CoordinatedImageBacking>*);
+
+ Client* m_client;
+ RefPtr<Image> m_image;
+ NativeImagePtr m_nativeImagePtr;
+ CoordinatedImageBackingID m_id;
+ Vector<Host*> m_hosts;
+
+ RefPtr<CoordinatedSurface> m_surface;
+
+ Timer<CoordinatedImageBacking> m_clearContentsTimer;
+
+ bool m_isDirty;
+ bool m_isVisible;
+
+};
+
+} // namespace WebCore
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // CoordinatedImageBacking_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.cpp
new file mode 100644
index 000000000..9aa67a5e0
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 Company 100, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CoordinatedSurface.h"
+
+#if USE(COORDINATED_GRAPHICS)
+
+namespace WebCore {
+
+CoordinatedSurface::Factory* CoordinatedSurface::s_factory = 0;
+
+void CoordinatedSurface::setFactory(CoordinatedSurface::Factory factory)
+{
+ s_factory = factory;
+}
+
+PassRefPtr<CoordinatedSurface> CoordinatedSurface::create(const IntSize& size, Flags flags)
+{
+ ASSERT(s_factory);
+ return s_factory(size, flags);
+}
+
+CoordinatedSurface::CoordinatedSurface(const IntSize& size, Flags flags)
+ : m_size(size)
+ , m_flags(flags)
+{
+}
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.h b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.h
new file mode 100644
index 000000000..9142528c6
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedSurface.h
@@ -0,0 +1,76 @@
+/*
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2012 Company 100, Inc.
+
+ 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 CoordinatedSurface_h
+#define CoordinatedSurface_h
+
+#if USE(COORDINATED_GRAPHICS)
+#include "IntRect.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/ThreadSafeRefCounted.h>
+
+namespace WebCore {
+class BitmapTexture;
+class GraphicsContext;
+
+class CoordinatedSurface : public ThreadSafeRefCounted<CoordinatedSurface> {
+public:
+ enum Flag {
+ NoFlags = 0,
+ SupportsAlpha = 1 << 0,
+ };
+ typedef unsigned Flags;
+
+ class Client {
+ public:
+ virtual ~Client() { }
+ virtual void paintToSurfaceContext(GraphicsContext*) = 0;
+ };
+
+ typedef PassRefPtr<CoordinatedSurface> Factory(const IntSize&, Flags);
+ static void setFactory(Factory);
+ static PassRefPtr<CoordinatedSurface> create(const IntSize&, Flags);
+
+ virtual ~CoordinatedSurface() { }
+
+ bool supportsAlpha() const { return flags() & SupportsAlpha; }
+ IntSize size() const { return m_size; }
+
+ virtual void paintToSurface(const IntRect&, Client*) = 0;
+
+#if USE(TEXTURE_MAPPER)
+ virtual void copyToTexture(PassRefPtr<BitmapTexture>, const IntRect& target, const IntPoint& sourceOffset) = 0;
+#endif
+
+protected:
+ CoordinatedSurface(const IntSize&, Flags);
+ Flags flags() const { return m_flags; }
+
+ IntSize m_size;
+ Flags m_flags;
+
+private:
+ static CoordinatedSurface::Factory* s_factory;
+};
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
+#endif // CoordinatedSurface_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedTile.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedTile.cpp
new file mode 100644
index 000000000..b24f48d23
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedTile.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CoordinatedTile.h"
+
+#if USE(TILED_BACKING_STORE)
+
+#include "GraphicsContext.h"
+#include "ImageBuffer.h"
+#include "SurfaceUpdateInfo.h"
+#include "TiledBackingStoreClient.h"
+
+namespace WebCore {
+
+static const uint32_t InvalidCoordinatedTileID = 0;
+
+CoordinatedTile::CoordinatedTile(CoordinatedTileClient* client, TiledBackingStore* tiledBackingStore, const Coordinate& tileCoordinate)
+ : m_client(client)
+ , m_tiledBackingStore(tiledBackingStore)
+ , m_coordinate(tileCoordinate)
+ , m_rect(tiledBackingStore->tileRectForCoordinate(tileCoordinate))
+ , m_ID(InvalidCoordinatedTileID)
+ , m_dirtyRect(m_rect)
+{
+}
+
+CoordinatedTile::~CoordinatedTile()
+{
+ if (m_ID != InvalidCoordinatedTileID)
+ m_client->removeTile(m_ID);
+}
+
+bool CoordinatedTile::isDirty() const
+{
+ return !m_dirtyRect.isEmpty();
+}
+
+void CoordinatedTile::invalidate(const IntRect& dirtyRect)
+{
+ IntRect tileDirtyRect = intersection(dirtyRect, m_rect);
+ if (tileDirtyRect.isEmpty())
+ return;
+
+ m_dirtyRect.unite(tileDirtyRect);
+}
+
+Vector<IntRect> CoordinatedTile::updateBackBuffer()
+{
+ if (!isDirty())
+ return Vector<IntRect>();
+
+ SurfaceUpdateInfo updateInfo;
+
+ if (!m_client->paintToSurface(m_dirtyRect.size(), updateInfo.atlasID, updateInfo.surfaceOffset, this))
+ return Vector<IntRect>();
+
+ updateInfo.updateRect = m_dirtyRect;
+ updateInfo.updateRect.move(-m_rect.x(), -m_rect.y());
+ updateInfo.scaleFactor = m_tiledBackingStore->contentsScale();
+
+ static uint32_t id = 1;
+ if (m_ID == InvalidCoordinatedTileID) {
+ m_ID = id++;
+ // We may get an invalid ID due to wrap-around on overflow.
+ if (m_ID == InvalidCoordinatedTileID)
+ m_ID = id++;
+ m_client->createTile(m_ID, updateInfo, m_rect);
+ } else
+ m_client->updateTile(m_ID, updateInfo, m_rect);
+
+ Vector<IntRect> updatedRects;
+ updatedRects.append(m_dirtyRect);
+ m_dirtyRect = IntRect();
+ return updatedRects;
+}
+
+void CoordinatedTile::paintToSurfaceContext(GraphicsContext* context)
+{
+ context->translate(-m_dirtyRect.x(), -m_dirtyRect.y());
+ context->scale(FloatSize(m_tiledBackingStore->contentsScale(), m_tiledBackingStore->contentsScale()));
+ m_tiledBackingStore->client()->tiledBackingStorePaint(context, m_tiledBackingStore->mapToContents(m_dirtyRect));
+}
+
+void CoordinatedTile::swapBackBufferToFront()
+{
+ // Handled by tiledBackingStorePaintEnd.
+}
+
+bool CoordinatedTile::isReadyToPaint() const
+{
+ return m_ID != InvalidCoordinatedTileID;
+}
+
+void CoordinatedTile::paint(GraphicsContext*, const IntRect&)
+{
+ ASSERT_NOT_REACHED();
+}
+
+void CoordinatedTile::resize(const IntSize& newSize)
+{
+ m_rect = IntRect(m_rect.location(), newSize);
+ m_dirtyRect = m_rect;
+}
+
+CoordinatedTileBackend::CoordinatedTileBackend(CoordinatedTileClient* client)
+ : m_client(client)
+{
+}
+
+PassRefPtr<Tile> CoordinatedTileBackend::createTile(TiledBackingStore* tiledBackingStore, const Tile::Coordinate& tileCoordinate)
+{
+ return CoordinatedTile::create(m_client, tiledBackingStore, tileCoordinate);
+}
+
+void CoordinatedTileBackend::paintCheckerPattern(GraphicsContext*, const FloatRect&)
+{
+}
+
+} // namespace WebCore
+
+#endif // USE(TILED_BACKING_STORE)
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedTile.h b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedTile.h
new file mode 100644
index 000000000..cab526e2b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedTile.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CoordinatedTile_h
+#define CoordinatedTile_h
+
+#if USE(TILED_BACKING_STORE)
+
+#include "CoordinatedSurface.h"
+#include "IntRect.h"
+#include "Tile.h"
+#include "TiledBackingStore.h"
+
+namespace WebCore {
+
+class CoordinatedTileClient;
+class ImageBuffer;
+class SurfaceUpdateInfo;
+class TiledBackingStore;
+
+class CoordinatedTile : public Tile, public CoordinatedSurface::Client {
+public:
+ static PassRefPtr<Tile> create(CoordinatedTileClient* client, TiledBackingStore* tiledBackingStore, const Coordinate& tileCoordinate) { return adoptRef(new CoordinatedTile(client, tiledBackingStore, tileCoordinate)); }
+ ~CoordinatedTile();
+
+ bool isDirty() const;
+ void invalidate(const IntRect&);
+ Vector<IntRect> updateBackBuffer();
+ void swapBackBufferToFront();
+ bool isReadyToPaint() const;
+ void paint(GraphicsContext*, const IntRect&);
+
+ const Coordinate& coordinate() const { return m_coordinate; }
+ const IntRect& rect() const { return m_rect; }
+ void resize(const IntSize&);
+
+ virtual void paintToSurfaceContext(GraphicsContext*) OVERRIDE;
+
+private:
+ CoordinatedTile(CoordinatedTileClient*, TiledBackingStore*, const Coordinate&);
+
+ CoordinatedTileClient* m_client;
+ TiledBackingStore* m_tiledBackingStore;
+ Coordinate m_coordinate;
+ IntRect m_rect;
+
+ uint32_t m_ID;
+ IntRect m_dirtyRect;
+
+ OwnPtr<ImageBuffer> m_localBuffer;
+};
+
+class CoordinatedTileClient {
+public:
+ virtual ~CoordinatedTileClient() { }
+ virtual void createTile(uint32_t tileID, const SurfaceUpdateInfo&, const IntRect&) = 0;
+ virtual void updateTile(uint32_t tileID, const SurfaceUpdateInfo&, const IntRect&) = 0;
+ virtual void removeTile(uint32_t tileID) = 0;
+ virtual bool paintToSurface(const IntSize&, uint32_t& atlasID, IntPoint&, CoordinatedSurface::Client*) = 0;
+};
+
+class CoordinatedTileBackend : public TiledBackingStoreBackend {
+public:
+ static PassOwnPtr<TiledBackingStoreBackend> create(CoordinatedTileClient* client) { return adoptPtr(new CoordinatedTileBackend(client)); }
+ PassRefPtr<Tile> createTile(TiledBackingStore*, const Tile::Coordinate&);
+ void paintCheckerPattern(GraphicsContext*, const FloatRect&);
+
+private:
+ explicit CoordinatedTileBackend(CoordinatedTileClient*);
+ CoordinatedTileClient* m_client;
+};
+
+} // namespace WebCore
+
+#endif // USE(TILED_BACKING_STORE)
+
+#endif // CoordinatedTile_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/SurfaceUpdateInfo.h b/Source/WebCore/platform/graphics/texmap/coordinated/SurfaceUpdateInfo.h
new file mode 100644
index 000000000..5af069a2b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/SurfaceUpdateInfo.h
@@ -0,0 +1,51 @@
+/*
+ Copyright (C) 2012 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 SurfaceUpdateInfo_h
+#define SurfaceUpdateInfo_h
+
+#if USE(COORDINATED_GRAPHICS)
+
+#include "IntRect.h"
+
+namespace WebCore {
+
+class SurfaceUpdateInfo {
+
+public:
+ SurfaceUpdateInfo() { }
+
+ // The rect to be updated.
+ IntRect updateRect;
+
+ // The page scale factor used to render this update.
+ float scaleFactor;
+
+ // The id of the update atlas including the shareable bitmap containing the updates.
+ uint32_t atlasID;
+
+ // The offset in the bitmap where the rendered contents are.
+ IntPoint surfaceOffset;
+};
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // SurfaceUpdateInfo_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/ThreadSafeCoordinatedSurface.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/ThreadSafeCoordinatedSurface.cpp
new file mode 100644
index 000000000..94497dd84
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/ThreadSafeCoordinatedSurface.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 Company 100, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ThreadSafeCoordinatedSurface.h"
+
+#if USE(COORDINATED_GRAPHICS)
+
+#include "TextureMapper.h"
+
+namespace WebCore {
+
+PassRefPtr<ThreadSafeCoordinatedSurface> ThreadSafeCoordinatedSurface::create(const IntSize& size, CoordinatedSurface::Flags flags)
+{
+ return adoptRef(new ThreadSafeCoordinatedSurface(size, flags, ImageBuffer::create(size)));
+}
+
+ThreadSafeCoordinatedSurface::ThreadSafeCoordinatedSurface(const IntSize& size, CoordinatedSurface::Flags flags, PassOwnPtr<ImageBuffer> buffer)
+ : CoordinatedSurface(size, flags)
+ , m_imageBuffer(buffer)
+{
+}
+
+ThreadSafeCoordinatedSurface::~ThreadSafeCoordinatedSurface()
+{
+}
+
+void ThreadSafeCoordinatedSurface::paintToSurface(const IntRect& rect, CoordinatedSurface::Client* client)
+{
+ ASSERT(client);
+ ASSERT(m_imageBuffer);
+
+ GraphicsContext* context = m_imageBuffer->context();
+ context->save();
+ context->clip(rect);
+ context->translate(rect.x(), rect.y());
+
+ client->paintToSurfaceContext(context);
+
+ context->restore();
+}
+
+void ThreadSafeCoordinatedSurface::copyToTexture(PassRefPtr<BitmapTexture> passTexture, const IntRect& target, const IntPoint& sourceOffset)
+{
+ RefPtr<BitmapTexture> texture(passTexture);
+
+ ASSERT(m_imageBuffer);
+ RefPtr<Image> image = m_imageBuffer->copyImage(DontCopyBackingStore);
+ texture->updateContents(image.get(), target, sourceOffset, BitmapTexture::UpdateCanModifyOriginalImageData);
+}
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/ThreadSafeCoordinatedSurface.h b/Source/WebCore/platform/graphics/texmap/coordinated/ThreadSafeCoordinatedSurface.h
new file mode 100644
index 000000000..e003818af
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/ThreadSafeCoordinatedSurface.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 Company 100, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ThreadSafeCoordinatedSurface_h
+#define ThreadSafeCoordinatedSurface_h
+
+#if USE(COORDINATED_GRAPHICS)
+#include "CoordinatedSurface.h"
+#include "ImageBuffer.h"
+
+namespace WebCore {
+
+class ThreadSafeCoordinatedSurface : public CoordinatedSurface {
+public:
+ virtual ~ThreadSafeCoordinatedSurface();
+
+ static PassRefPtr<ThreadSafeCoordinatedSurface> create(const IntSize&, Flags);
+
+ virtual void paintToSurface(const IntRect&, CoordinatedSurface::Client*) OVERRIDE;
+ virtual void copyToTexture(PassRefPtr<BitmapTexture>, const IntRect& target, const IntPoint& sourceOffset) OVERRIDE;
+
+private:
+ ThreadSafeCoordinatedSurface(const IntSize&, Flags, PassOwnPtr<ImageBuffer>);
+
+ OwnPtr<ImageBuffer> m_imageBuffer;
+};
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // ThreadSafeCoordinatedSurface_h
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/UpdateAtlas.cpp b/Source/WebCore/platform/graphics/texmap/coordinated/UpdateAtlas.cpp
new file mode 100644
index 000000000..319e9b8e4
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/UpdateAtlas.cpp
@@ -0,0 +1,116 @@
+/*
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2012 Company 100, Inc.
+
+ 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 "UpdateAtlas.h"
+
+#if USE(COORDINATED_GRAPHICS)
+
+#include "CoordinatedGraphicsState.h"
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+class UpdateAtlasSurfaceClient : public CoordinatedSurface::Client {
+public:
+ UpdateAtlasSurfaceClient(CoordinatedSurface::Client* client, const IntSize& size, bool supportsAlpha)
+ : m_client(client)
+ , m_size(size)
+ , m_supportsAlpha(supportsAlpha)
+ {
+ }
+
+ virtual void paintToSurfaceContext(GraphicsContext* context) OVERRIDE
+ {
+ if (m_supportsAlpha) {
+ context->setCompositeOperation(CompositeCopy);
+ context->fillRect(IntRect(IntPoint::zero(), m_size), Color::transparent, ColorSpaceDeviceRGB);
+ context->setCompositeOperation(CompositeSourceOver);
+ }
+
+ m_client->paintToSurfaceContext(context);
+ }
+
+private:
+ CoordinatedSurface::Client* m_client;
+ IntSize m_size;
+ bool m_supportsAlpha;
+};
+
+UpdateAtlas::UpdateAtlas(Client* client, int dimension, CoordinatedSurface::Flags flags)
+ : m_client(client)
+ , m_inactivityInSeconds(0)
+{
+ static uint32_t nextID = 0;
+ m_ID = ++nextID;
+ IntSize size = nextPowerOfTwo(IntSize(dimension, dimension));
+ m_surface = CoordinatedSurface::create(size, flags);
+
+ m_client->createUpdateAtlas(m_ID, m_surface);
+}
+
+UpdateAtlas::~UpdateAtlas()
+{
+ if (m_surface)
+ m_client->removeUpdateAtlas(m_ID);
+}
+
+void UpdateAtlas::buildLayoutIfNeeded()
+{
+ if (!m_areaAllocator) {
+ m_areaAllocator = adoptPtr(new GeneralAreaAllocator(size()));
+ m_areaAllocator->setMinimumAllocation(IntSize(32, 32));
+ }
+}
+
+void UpdateAtlas::didSwapBuffers()
+{
+ m_areaAllocator.clear();
+}
+
+
+bool UpdateAtlas::paintOnAvailableBuffer(const IntSize& size, uint32_t& atlasID, IntPoint& offset, CoordinatedSurface::Client* client)
+{
+ m_inactivityInSeconds = 0;
+ buildLayoutIfNeeded();
+ IntRect rect = m_areaAllocator->allocate(size);
+
+ // No available buffer was found.
+ if (rect.isEmpty())
+ return false;
+
+ if (!m_surface)
+ return false;
+
+ atlasID = m_ID;
+
+ // FIXME: Use tri-state buffers, to allow faster updates.
+ offset = rect.location();
+
+ UpdateAtlasSurfaceClient surfaceClient(client, size, supportsAlpha());
+ m_surface->paintToSurface(rect, &surfaceClient);
+
+ return true;
+}
+
+} // namespace WebCore
+#endif // USE(COORDINATED_GRAPHICS)
diff --git a/Source/WebCore/platform/graphics/texmap/coordinated/UpdateAtlas.h b/Source/WebCore/platform/graphics/texmap/coordinated/UpdateAtlas.h
new file mode 100644
index 000000000..2eb45f7c7
--- /dev/null
+++ b/Source/WebCore/platform/graphics/texmap/coordinated/UpdateAtlas.h
@@ -0,0 +1,78 @@
+/*
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2012 Company 100, Inc.
+
+ 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 UpdateAtlas_h
+#define UpdateAtlas_h
+
+#include "AreaAllocator.h"
+#include "CoordinatedSurface.h"
+#include "IntSize.h"
+
+#if USE(COORDINATED_GRAPHICS)
+
+namespace WebCore {
+class GraphicsContext;
+class IntPoint;
+
+class UpdateAtlas {
+ WTF_MAKE_NONCOPYABLE(UpdateAtlas);
+public:
+ class Client {
+ public:
+ virtual void createUpdateAtlas(uint32_t /* id */, PassRefPtr<CoordinatedSurface>) = 0;
+ virtual void removeUpdateAtlas(uint32_t /* id */) = 0;
+ };
+
+ UpdateAtlas(Client*, int dimension, CoordinatedSurface::Flags);
+ ~UpdateAtlas();
+
+ inline IntSize size() const { return m_surface->size(); }
+
+ // Returns false if there is no available buffer.
+ bool paintOnAvailableBuffer(const IntSize&, uint32_t& atlasID, IntPoint& offset, CoordinatedSurface::Client*);
+ void didSwapBuffers();
+ bool supportsAlpha() const { return m_surface->supportsAlpha(); }
+
+ void addTimeInactive(double seconds)
+ {
+ ASSERT(!isInUse());
+ m_inactivityInSeconds += seconds;
+ }
+ bool isInactive() const
+ {
+ const double inactiveSecondsTolerance = 3;
+ return m_inactivityInSeconds > inactiveSecondsTolerance;
+ }
+ bool isInUse() const { return m_areaAllocator; }
+
+private:
+ void buildLayoutIfNeeded();
+
+private:
+ Client* m_client;
+ OwnPtr<GeneralAreaAllocator> m_areaAllocator;
+ RefPtr<CoordinatedSurface> m_surface;
+ double m_inactivityInSeconds;
+ uint32_t m_ID;
+};
+
+} // namespace WebCore
+#endif // USE(COORDINATED_GRAPHICS)
+#endif // UpdateAtlas_h