summaryrefslogtreecommitdiff
path: root/Source/WebKit2/Shared/CoordinatedGraphics
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebKit2/Shared/CoordinatedGraphics
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebKit2/Shared/CoordinatedGraphics')
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedBackingStore.cpp191
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedBackingStore.h93
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsArgumentCoders.cpp924
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsArgumentCoders.h101
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsScene.cpp682
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsScene.h194
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp172
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.h81
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/WebCoordinatedSurface.cpp131
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/WebCoordinatedSurface.h83
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/CompositingRunLoop.cpp173
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/CompositingRunLoop.h73
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.cpp87
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.h58
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp222
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.h109
16 files changed, 3374 insertions, 0 deletions
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedBackingStore.cpp b/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedBackingStore.cpp
new file mode 100644
index 000000000..bb46942a1
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedBackingStore.cpp
@@ -0,0 +1,191 @@
+/*
+ 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 <WebCore/CoordinatedSurface.h>
+#include <WebCore/GraphicsLayer.h>
+#include <WebCore/TextureMapper.h>
+#include <WebCore/TextureMapperGL.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+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;
+ }
+
+ if (m_surface->supportsAlpha() == texture->isOpaque())
+ 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 = nullptr;
+}
+
+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()
+{
+ for (auto& key : m_tiles.keys())
+ m_tilesToRemove.add(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);
+}
+
+RefPtr<BitmapTexture> CoordinatedBackingStore::texture() const
+{
+ for (auto& tile : m_tiles.values()) {
+ RefPtr<BitmapTexture> texture = tile.texture();
+ if (texture)
+ return texture;
+ }
+
+ return RefPtr<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 (auto& tile : tiles)
+ tile->paint(textureMapper, transform, opacity, calculateExposedTileEdges(rect, tile->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.
+ FloatRect coveredRect;
+ for (auto& tile : m_tiles.values()) {
+ 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);
+ for (auto& tile : m_tiles.values())
+ textureMapper.drawBorder(borderColor, borderWidth, tile.rect(), adjustedTransform);
+}
+
+void CoordinatedBackingStore::drawRepaintCounter(TextureMapper& textureMapper, int repaintCount, const Color& borderColor, const FloatRect& targetRect, const TransformationMatrix& transform)
+{
+ TransformationMatrix adjustedTransform = transform * adjustedTransformForRect(targetRect);
+ for (auto& tile : m_tiles.values())
+ textureMapper.drawNumber(repaintCount, borderColor, tile.rect().location(), adjustedTransform);
+}
+
+void CoordinatedBackingStore::commitTileOperations(TextureMapper& textureMapper)
+{
+ if (!m_pendingSize.isZero()) {
+ m_size = m_pendingSize;
+ m_pendingSize = FloatSize();
+ }
+
+ for (auto& tileToRemove : m_tilesToRemove)
+ m_tiles.remove(tileToRemove);
+ m_tilesToRemove.clear();
+
+ for (auto& tile : m_tiles.values())
+ tile.swapBuffers(textureMapper);
+}
+
+} // namespace WebCore
+#endif // USE(COORDINATED_GRAPHICS)
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedBackingStore.h b/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedBackingStore.h
new file mode 100644
index 000000000..166c0a1c7
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedBackingStore.h
@@ -0,0 +1,93 @@
+/*
+ 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 <WebCore/TextureMapper.h>
+#include <WebCore/TextureMapperBackingStore.h>
+#include <WebCore/TextureMapperTile.h>
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+
+
+namespace WebCore {
+class CoordinatedSurface;
+}
+
+namespace WebKit {
+
+class CoordinatedBackingStoreTile : public WebCore::TextureMapperTile {
+public:
+ explicit CoordinatedBackingStoreTile(float scale = 1)
+ : WebCore::TextureMapperTile(WebCore::FloatRect())
+ , m_scale(scale)
+ {
+ }
+
+ inline float scale() const { return m_scale; }
+ void swapBuffers(WebCore::TextureMapper&);
+ void setBackBuffer(const WebCore::IntRect&, const WebCore::IntRect&, PassRefPtr<WebCore::CoordinatedSurface> buffer, const WebCore::IntPoint&);
+
+private:
+ RefPtr<WebCore::CoordinatedSurface> m_surface;
+ WebCore::IntRect m_sourceRect;
+ WebCore::IntRect m_tileRect;
+ WebCore::IntPoint m_surfaceOffset;
+ float m_scale;
+};
+
+class CoordinatedBackingStore : public WebCore::TextureMapperBackingStore {
+public:
+ void createTile(uint32_t tileID, float);
+ void removeTile(uint32_t tileID);
+ void removeAllTiles();
+ void updateTile(uint32_t tileID, const WebCore::IntRect&, const WebCore::IntRect&, PassRefPtr<WebCore::CoordinatedSurface>, const WebCore::IntPoint&);
+ static Ref<CoordinatedBackingStore> create() { return adoptRef(*new CoordinatedBackingStore); }
+ void commitTileOperations(WebCore::TextureMapper&);
+ RefPtr<WebCore::BitmapTexture> texture() const override;
+ void setSize(const WebCore::FloatSize&);
+ void paintToTextureMapper(WebCore::TextureMapper&, const WebCore::FloatRect&, const WebCore::TransformationMatrix&, float) override;
+ void drawBorder(WebCore::TextureMapper&, const WebCore::Color&, float borderWidth, const WebCore::FloatRect&, const WebCore::TransformationMatrix&) override;
+ void drawRepaintCounter(WebCore::TextureMapper&, int repaintCount, const WebCore::Color&, const WebCore::FloatRect&, const WebCore::TransformationMatrix&) override;
+
+private:
+ CoordinatedBackingStore()
+ : m_scale(1.)
+ { }
+ void paintTilesToTextureMapper(Vector<WebCore::TextureMapperTile*>&, WebCore::TextureMapper&, const WebCore::TransformationMatrix&, float, const WebCore::FloatRect&);
+ WebCore::TransformationMatrix adjustedTransformForRect(const WebCore::FloatRect&);
+ WebCore::FloatRect rect() const { return WebCore::FloatRect(WebCore::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
+ WebCore::FloatSize m_pendingSize;
+ WebCore::FloatSize m_size;
+ float m_scale;
+};
+
+} // namespace WebKit
+
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // CoordinatedBackingStore_h
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsArgumentCoders.cpp b/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsArgumentCoders.cpp
new file mode 100644
index 000000000..9492d826f
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsArgumentCoders.cpp
@@ -0,0 +1,924 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2012 Company 100, Inc.
+ *
+ * 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 "CoordinatedGraphicsArgumentCoders.h"
+
+#if USE(COORDINATED_GRAPHICS)
+#include "WebCoordinatedSurface.h"
+#include "WebCoreArgumentCoders.h"
+#include <WebCore/Animation.h>
+#include <WebCore/Color.h>
+#include <WebCore/CoordinatedGraphicsState.h>
+#include <WebCore/FilterOperations.h>
+#include <WebCore/FloatPoint3D.h>
+#include <WebCore/IdentityTransformOperation.h>
+#include <WebCore/IntPoint.h>
+#include <WebCore/Length.h>
+#include <WebCore/Matrix3DTransformOperation.h>
+#include <WebCore/MatrixTransformOperation.h>
+#include <WebCore/PerspectiveTransformOperation.h>
+#include <WebCore/RotateTransformOperation.h>
+#include <WebCore/ScaleTransformOperation.h>
+#include <WebCore/SkewTransformOperation.h>
+#include <WebCore/SurfaceUpdateInfo.h>
+#include <WebCore/TextureMapperAnimation.h>
+#include <WebCore/TimingFunction.h>
+#include <WebCore/TransformationMatrix.h>
+#include <WebCore/TranslateTransformOperation.h>
+
+using namespace WebCore;
+using namespace WebKit;
+
+namespace IPC {
+
+void ArgumentCoder<WebCore::FilterOperations>::encode(Encoder& encoder, const WebCore::FilterOperations& filters)
+{
+ encoder << static_cast<uint32_t>(filters.size());
+ for (size_t i = 0; i < filters.size(); ++i) {
+ const FilterOperation& filter = *filters.at(i);
+ FilterOperation::OperationType type = filter.type();
+ encoder.encodeEnum(type);
+ switch (type) {
+ case FilterOperation::GRAYSCALE:
+ case FilterOperation::SEPIA:
+ case FilterOperation::SATURATE:
+ case FilterOperation::HUE_ROTATE:
+ encoder << static_cast<double>(downcast<BasicColorMatrixFilterOperation>(filter).amount());
+ break;
+ case FilterOperation::INVERT:
+ case FilterOperation::BRIGHTNESS:
+ case FilterOperation::CONTRAST:
+ case FilterOperation::OPACITY:
+ encoder << static_cast<double>(downcast<BasicComponentTransferFilterOperation>(filter).amount());
+ break;
+ case FilterOperation::BLUR:
+ ArgumentCoder<Length>::encode(encoder, downcast<BlurFilterOperation>(filter).stdDeviation());
+ break;
+ case FilterOperation::DROP_SHADOW: {
+ const DropShadowFilterOperation& shadow = downcast<DropShadowFilterOperation>(filter);
+ ArgumentCoder<IntPoint>::encode(encoder, shadow.location());
+ encoder << static_cast<int32_t>(shadow.stdDeviation());
+ ArgumentCoder<Color>::encode(encoder, shadow.color());
+ break;
+ }
+ case FilterOperation::REFERENCE:
+ case FilterOperation::PASSTHROUGH:
+ case FilterOperation::DEFAULT:
+ case FilterOperation::NONE:
+ break;
+ }
+ }
+}
+
+bool ArgumentCoder<WebCore::FilterOperations>::decode(Decoder& decoder, WebCore::FilterOperations& filters)
+{
+ uint32_t size;
+ if (!decoder.decode(size))
+ return false;
+
+ Vector<RefPtr<FilterOperation> >& operations = filters.operations();
+
+ for (size_t i = 0; i < size; ++i) {
+ FilterOperation::OperationType type;
+ RefPtr<FilterOperation> filter;
+ if (!decoder.decodeEnum(type))
+ return false;
+
+ switch (type) {
+ case FilterOperation::GRAYSCALE:
+ case FilterOperation::SEPIA:
+ case FilterOperation::SATURATE:
+ case FilterOperation::HUE_ROTATE: {
+ double value;
+ if (!decoder.decode(value))
+ return false;
+ filter = BasicColorMatrixFilterOperation::create(value, type);
+ break;
+ }
+ case FilterOperation::INVERT:
+ case FilterOperation::BRIGHTNESS:
+ case FilterOperation::CONTRAST:
+ case FilterOperation::OPACITY: {
+ double value;
+ if (!decoder.decode(value))
+ return false;
+ filter = BasicComponentTransferFilterOperation::create(value, type);
+ break;
+ }
+ case FilterOperation::BLUR: {
+ Length length;
+ if (!ArgumentCoder<Length>::decode(decoder, length))
+ return false;
+ filter = BlurFilterOperation::create(length);
+ break;
+ }
+ case FilterOperation::DROP_SHADOW: {
+ IntPoint location;
+ int32_t stdDeviation;
+ Color color;
+ if (!ArgumentCoder<IntPoint>::decode(decoder, location))
+ return false;
+ if (!decoder.decode(stdDeviation))
+ return false;
+ if (!ArgumentCoder<Color>::decode(decoder, color))
+ return false;
+ filter = DropShadowFilterOperation::create(location, stdDeviation, color);
+ break;
+ }
+ case FilterOperation::REFERENCE:
+ case FilterOperation::PASSTHROUGH:
+ case FilterOperation::DEFAULT:
+ case FilterOperation::NONE:
+ break;
+ }
+
+ if (filter)
+ operations.append(filter);
+ }
+
+ return true;
+}
+
+void ArgumentCoder<TransformOperations>::encode(Encoder& encoder, const TransformOperations& transformOperations)
+{
+ encoder << static_cast<uint32_t>(transformOperations.size());
+ for (const auto& operation : transformOperations.operations()) {
+ encoder.encodeEnum(operation->type());
+
+ switch (operation->type()) {
+ case TransformOperation::SCALE_X:
+ case TransformOperation::SCALE_Y:
+ case TransformOperation::SCALE:
+ case TransformOperation::SCALE_Z:
+ case TransformOperation::SCALE_3D: {
+ const auto& scaleOperation = downcast<ScaleTransformOperation>(*operation);
+ encoder << scaleOperation.x();
+ encoder << scaleOperation.y();
+ encoder << scaleOperation.z();
+ break;
+ }
+ case TransformOperation::TRANSLATE_X:
+ case TransformOperation::TRANSLATE_Y:
+ case TransformOperation::TRANSLATE:
+ case TransformOperation::TRANSLATE_Z:
+ case TransformOperation::TRANSLATE_3D: {
+ const auto& translateOperation = downcast<TranslateTransformOperation>(*operation);
+ ArgumentCoder<Length>::encode(encoder, translateOperation.x());
+ ArgumentCoder<Length>::encode(encoder, translateOperation.y());
+ ArgumentCoder<Length>::encode(encoder, translateOperation.z());
+ break;
+ }
+ case TransformOperation::ROTATE:
+ case TransformOperation::ROTATE_X:
+ case TransformOperation::ROTATE_Y:
+ case TransformOperation::ROTATE_3D: {
+ const auto& rotateOperation = downcast<RotateTransformOperation>(*operation);
+ encoder << rotateOperation.x();
+ encoder << rotateOperation.y();
+ encoder << rotateOperation.z();
+ encoder << rotateOperation.angle();
+ break;
+ }
+ case TransformOperation::SKEW_X:
+ case TransformOperation::SKEW_Y:
+ case TransformOperation::SKEW: {
+ const auto& skewOperation = downcast<SkewTransformOperation>(*operation);
+ encoder << skewOperation.angleX();
+ encoder << skewOperation.angleY();
+ break;
+ }
+ case TransformOperation::MATRIX:
+ ArgumentCoder<TransformationMatrix>::encode(encoder, downcast<MatrixTransformOperation>(*operation).matrix());
+ break;
+ case TransformOperation::MATRIX_3D:
+ ArgumentCoder<TransformationMatrix>::encode(encoder, downcast<Matrix3DTransformOperation>(*operation).matrix());
+ break;
+ case TransformOperation::PERSPECTIVE:
+ ArgumentCoder<Length>::encode(encoder, downcast<PerspectiveTransformOperation>(*operation).perspective());
+ break;
+ case TransformOperation::IDENTITY:
+ break;
+ case TransformOperation::NONE:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+}
+
+bool ArgumentCoder<TransformOperations>::decode(Decoder& decoder, TransformOperations& transformOperations)
+{
+ uint32_t operationsSize;
+ if (!decoder.decode(operationsSize))
+ return false;
+
+ for (size_t i = 0; i < operationsSize; ++i) {
+ TransformOperation::OperationType operationType;
+ if (!decoder.decodeEnum(operationType))
+ return false;
+
+ switch (operationType) {
+ case TransformOperation::SCALE_X:
+ case TransformOperation::SCALE_Y:
+ case TransformOperation::SCALE:
+ case TransformOperation::SCALE_Z:
+ case TransformOperation::SCALE_3D: {
+ double x, y, z;
+ if (!decoder.decode(x))
+ return false;
+ if (!decoder.decode(y))
+ return false;
+ if (!decoder.decode(z))
+ return false;
+ transformOperations.operations().append(ScaleTransformOperation::create(x, y, z, operationType));
+ break;
+ }
+ case TransformOperation::TRANSLATE_X:
+ case TransformOperation::TRANSLATE_Y:
+ case TransformOperation::TRANSLATE:
+ case TransformOperation::TRANSLATE_Z:
+ case TransformOperation::TRANSLATE_3D: {
+ Length x, y, z;
+ if (!ArgumentCoder<Length>::decode(decoder, x))
+ return false;
+ if (!ArgumentCoder<Length>::decode(decoder, y))
+ return false;
+ if (!ArgumentCoder<Length>::decode(decoder, z))
+ return false;
+ transformOperations.operations().append(TranslateTransformOperation::create(x, y, z, operationType));
+ break;
+ }
+ case TransformOperation::ROTATE:
+ case TransformOperation::ROTATE_X:
+ case TransformOperation::ROTATE_Y:
+ case TransformOperation::ROTATE_3D: {
+ double x, y, z, angle;
+ if (!decoder.decode(x))
+ return false;
+ if (!decoder.decode(y))
+ return false;
+ if (!decoder.decode(z))
+ return false;
+ if (!decoder.decode(angle))
+ return false;
+ transformOperations.operations().append(RotateTransformOperation::create(x, y, z, angle, operationType));
+ break;
+ }
+ case TransformOperation::SKEW_X:
+ case TransformOperation::SKEW_Y:
+ case TransformOperation::SKEW: {
+ double angleX, angleY;
+ if (!decoder.decode(angleX))
+ return false;
+ if (!decoder.decode(angleY))
+ return false;
+ transformOperations.operations().append(SkewTransformOperation::create(angleX, angleY, operationType));
+ break;
+ }
+ case TransformOperation::MATRIX: {
+ TransformationMatrix matrix;
+ if (!ArgumentCoder<TransformationMatrix>::decode(decoder, matrix))
+ return false;
+ transformOperations.operations().append(MatrixTransformOperation::create(matrix));
+ break;
+ }
+ case TransformOperation::MATRIX_3D: {
+ TransformationMatrix matrix;
+ if (!ArgumentCoder<TransformationMatrix>::decode(decoder, matrix))
+ return false;
+ transformOperations.operations().append(Matrix3DTransformOperation::create(matrix));
+ break;
+ }
+ case TransformOperation::PERSPECTIVE: {
+ Length perspective;
+ if (!ArgumentCoder<Length>::decode(decoder, perspective))
+ return false;
+ transformOperations.operations().append(PerspectiveTransformOperation::create(perspective));
+ break;
+ }
+ case TransformOperation::IDENTITY:
+ transformOperations.operations().append(IdentityTransformOperation::create());
+ break;
+ case TransformOperation::NONE:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+ return true;
+}
+
+static void encodeTimingFunction(Encoder& encoder, const TimingFunction* timingFunction)
+{
+ if (!timingFunction) {
+ encoder.encodeEnum(TimingFunction::TimingFunctionType(-1));
+ return;
+ }
+
+ TimingFunction::TimingFunctionType type = timingFunction ? timingFunction->type() : TimingFunction::LinearFunction;
+ encoder.encodeEnum(type);
+ switch (type) {
+ case TimingFunction::LinearFunction:
+ break;
+ case TimingFunction::CubicBezierFunction: {
+ const CubicBezierTimingFunction* cubic = static_cast<const CubicBezierTimingFunction*>(timingFunction);
+ CubicBezierTimingFunction::TimingFunctionPreset bezierPreset = cubic->timingFunctionPreset();
+ encoder.encodeEnum(bezierPreset);
+ if (bezierPreset == CubicBezierTimingFunction::Custom) {
+ encoder << cubic->x1();
+ encoder << cubic->y1();
+ encoder << cubic->x2();
+ encoder << cubic->y2();
+ }
+ break;
+ }
+ case TimingFunction::StepsFunction: {
+ const StepsTimingFunction* steps = static_cast<const StepsTimingFunction*>(timingFunction);
+ encoder << static_cast<uint32_t>(steps->numberOfSteps());
+ encoder << steps->stepAtStart();
+ break;
+ }
+ case TimingFunction::SpringFunction: {
+ const SpringTimingFunction* spring = static_cast<const SpringTimingFunction*>(timingFunction);
+ encoder << spring->mass();
+ encoder << spring->stiffness();
+ encoder << spring->damping();
+ encoder << spring->initialVelocity();
+ break;
+ }
+ }
+}
+
+bool decodeTimingFunction(Decoder& decoder, RefPtr<TimingFunction>& timingFunction)
+{
+ TimingFunction::TimingFunctionType type;
+ if (!decoder.decodeEnum(type))
+ return false;
+
+ if (type == TimingFunction::TimingFunctionType(-1))
+ return true;
+
+ switch (type) {
+ case TimingFunction::LinearFunction:
+ timingFunction = LinearTimingFunction::create();
+ return true;
+ case TimingFunction::CubicBezierFunction: {
+ double x1, y1, x2, y2;
+ CubicBezierTimingFunction::TimingFunctionPreset bezierPreset;
+ if (!decoder.decodeEnum(bezierPreset))
+ return false;
+ if (bezierPreset != CubicBezierTimingFunction::Custom) {
+ timingFunction = CubicBezierTimingFunction::create(bezierPreset);
+ return true;
+ }
+ if (!decoder.decode(x1))
+ return false;
+ if (!decoder.decode(y1))
+ return false;
+ if (!decoder.decode(x2))
+ return false;
+ if (!decoder.decode(y2))
+ return false;
+
+ timingFunction = CubicBezierTimingFunction::create(x1, y1, x2, y2);
+ return true;
+ }
+ case TimingFunction::StepsFunction: {
+ uint32_t numberOfSteps;
+ bool stepAtStart;
+ if (!decoder.decode(numberOfSteps))
+ return false;
+ if (!decoder.decode(stepAtStart))
+ return false;
+
+ timingFunction = StepsTimingFunction::create(numberOfSteps, stepAtStart);
+ return true;
+ }
+ case TimingFunction::SpringFunction: {
+ double mass;
+ if (!decoder.decode(mass))
+ return false;
+ double stiffness;
+ if (!decoder.decode(stiffness))
+ return false;
+ double damping;
+ if (!decoder.decode(damping))
+ return false;
+ double initialVelocity;
+ if (!decoder.decode(initialVelocity))
+ return false;
+
+ timingFunction = SpringTimingFunction::create(mass, stiffness, damping, initialVelocity);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void ArgumentCoder<TextureMapperAnimation>::encode(Encoder& encoder, const TextureMapperAnimation& animation)
+{
+ encoder << animation.name();
+ encoder << animation.boxSize();
+ encoder.encodeEnum(animation.state());
+ encoder << animation.startTime();
+ encoder << animation.pauseTime();
+ encoder << animation.listsMatch();
+
+ RefPtr<Animation> animationObject = animation.animation();
+ encoder.encodeEnum(animationObject->direction());
+ encoder << static_cast<uint32_t>(animationObject->fillMode());
+ encoder << animationObject->duration();
+ encoder << animationObject->iterationCount();
+ encodeTimingFunction(encoder, animationObject->timingFunction());
+
+ const KeyframeValueList& keyframes = animation.keyframes();
+ encoder.encodeEnum(keyframes.property());
+ encoder << static_cast<uint32_t>(keyframes.size());
+ for (size_t i = 0; i < keyframes.size(); ++i) {
+ const AnimationValue& value = keyframes.at(i);
+ encoder << value.keyTime();
+ encodeTimingFunction(encoder, value.timingFunction());
+ switch (keyframes.property()) {
+ case AnimatedPropertyOpacity:
+ encoder << static_cast<const FloatAnimationValue&>(value).value();
+ break;
+ case AnimatedPropertyTransform:
+ encoder << static_cast<const TransformAnimationValue&>(value).value();
+ break;
+ case AnimatedPropertyFilter:
+ encoder << static_cast<const FilterAnimationValue&>(value).value();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+bool ArgumentCoder<TextureMapperAnimation>::decode(Decoder& decoder, TextureMapperAnimation& animation)
+{
+ String name;
+ FloatSize boxSize;
+ TextureMapperAnimation::AnimationState state;
+ double startTime;
+ double pauseTime;
+ bool listsMatch;
+
+ Animation::AnimationDirection direction;
+ unsigned fillMode;
+ double duration;
+ double iterationCount;
+ RefPtr<TimingFunction> timingFunction;
+ RefPtr<Animation> animationObject;
+
+ if (!decoder.decode(name))
+ return false;
+ if (!decoder.decode(boxSize))
+ return false;
+ if (!decoder.decodeEnum(state))
+ return false;
+ if (!decoder.decode(startTime))
+ return false;
+ if (!decoder.decode(pauseTime))
+ return false;
+ if (!decoder.decode(listsMatch))
+ return false;
+ if (!decoder.decodeEnum(direction))
+ return false;
+ if (!decoder.decode(fillMode))
+ return false;
+ if (!decoder.decode(duration))
+ return false;
+ if (!decoder.decode(iterationCount))
+ return false;
+ if (!decodeTimingFunction(decoder, timingFunction))
+ return false;
+
+ animationObject = Animation::create();
+ animationObject->setDirection(direction);
+ animationObject->setFillMode(fillMode);
+ animationObject->setDuration(duration);
+ animationObject->setIterationCount(iterationCount);
+ if (timingFunction)
+ animationObject->setTimingFunction(WTFMove(timingFunction));
+
+ AnimatedPropertyID property;
+ if (!decoder.decodeEnum(property))
+ return false;
+ KeyframeValueList keyframes(property);
+ unsigned keyframesSize;
+ if (!decoder.decode(keyframesSize))
+ return false;
+ for (unsigned i = 0; i < keyframesSize; ++i) {
+ double keyTime;
+ RefPtr<TimingFunction> timingFunction;
+ if (!decoder.decode(keyTime))
+ return false;
+ if (!decodeTimingFunction(decoder, timingFunction))
+ return false;
+
+ switch (property) {
+ case AnimatedPropertyOpacity: {
+ float value;
+ if (!decoder.decode(value))
+ return false;
+ keyframes.insert(std::make_unique<FloatAnimationValue>(keyTime, value, timingFunction.get()));
+ break;
+ }
+ case AnimatedPropertyTransform: {
+ TransformOperations transform;
+ if (!decoder.decode(transform))
+ return false;
+ keyframes.insert(std::make_unique<TransformAnimationValue>(keyTime, transform, timingFunction.get()));
+ break;
+ }
+ case AnimatedPropertyFilter: {
+ FilterOperations filter;
+ if (!decoder.decode(filter))
+ return false;
+ keyframes.insert(std::make_unique<FilterAnimationValue>(keyTime, filter, timingFunction.get()));
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ animation = TextureMapperAnimation(name, keyframes, boxSize, *animationObject, listsMatch, startTime, pauseTime, state);
+ return true;
+}
+
+void ArgumentCoder<TextureMapperAnimations>::encode(Encoder& encoder, const TextureMapperAnimations& animations)
+{
+ encoder << animations.animations();
+}
+
+bool ArgumentCoder<TextureMapperAnimations>::decode(Decoder& decoder, TextureMapperAnimations& animations)
+{
+ return decoder.decode(animations.animations());
+}
+
+bool ArgumentCoder<WebCore::GraphicsSurfaceToken>::decode(Decoder& decoder, WebCore::GraphicsSurfaceToken& token)
+{
+#if OS(DARWIN)
+ Attachment frontAttachment, backAttachment;
+ if (!decoder.decode(frontAttachment))
+ return false;
+ if (!decoder.decode(backAttachment))
+ return false;
+
+ token = GraphicsSurfaceToken(frontAttachment.port(), backAttachment.port());
+#elif OS(LINUX)
+ if (!decoder.decode(token.frontBufferHandle))
+ return false;
+#endif
+ return true;
+}
+#endif
+
+void ArgumentCoder<SurfaceUpdateInfo>::encode(Encoder& encoder, const SurfaceUpdateInfo& surfaceUpdateInfo)
+{
+ SimpleArgumentCoder<SurfaceUpdateInfo>::encode(encoder, surfaceUpdateInfo);
+}
+
+bool ArgumentCoder<SurfaceUpdateInfo>::decode(Decoder& decoder, SurfaceUpdateInfo& surfaceUpdateInfo)
+{
+ return SimpleArgumentCoder<SurfaceUpdateInfo>::decode(decoder, surfaceUpdateInfo);
+}
+
+void ArgumentCoder<CoordinatedGraphicsLayerState>::encode(Encoder& encoder, const CoordinatedGraphicsLayerState& state)
+{
+ encoder << state.changeMask;
+
+ if (state.flagsChanged)
+ encoder << state.flags;
+
+ if (state.positionChanged)
+ encoder << state.pos;
+
+ if (state.anchorPointChanged)
+ encoder << state.anchorPoint;
+
+ if (state.sizeChanged)
+ encoder << state.size;
+
+ if (state.transformChanged)
+ encoder << state.transform;
+
+ if (state.childrenTransformChanged)
+ encoder << state.childrenTransform;
+
+ if (state.contentsRectChanged)
+ encoder << state.contentsRect;
+
+ if (state.contentsTilingChanged) {
+ encoder << state.contentsTileSize;
+ encoder << state.contentsTilePhase;
+ }
+
+ if (state.opacityChanged)
+ encoder << state.opacity;
+
+ if (state.solidColorChanged)
+ encoder << state.solidColor;
+
+ if (state.debugBorderColorChanged)
+ encoder << state.debugBorderColor;
+
+ if (state.debugBorderWidthChanged)
+ encoder << state.debugBorderWidth;
+
+ if (state.filtersChanged)
+ encoder << state.filters;
+
+ if (state.animationsChanged)
+ encoder << state.animations;
+
+ if (state.childrenChanged)
+ encoder << state.children;
+
+ encoder << state.tilesToCreate;
+ encoder << state.tilesToRemove;
+
+ if (state.replicaChanged)
+ encoder << state.replica;
+
+ if (state.maskChanged)
+ encoder << state.mask;
+
+ if (state.imageChanged)
+ encoder << state.imageID;
+
+ if (state.repaintCountChanged)
+ encoder << state.repaintCount;
+
+ encoder << state.tilesToUpdate;
+
+ if (state.committedScrollOffsetChanged)
+ encoder << state.committedScrollOffset;
+}
+
+bool ArgumentCoder<CoordinatedGraphicsLayerState>::decode(Decoder& decoder, CoordinatedGraphicsLayerState& state)
+{
+ if (!decoder.decode(state.changeMask))
+ return false;
+
+ if (state.flagsChanged && !decoder.decode(state.flags))
+ return false;
+
+ if (state.positionChanged && !decoder.decode(state.pos))
+ return false;
+
+ if (state.anchorPointChanged && !decoder.decode(state.anchorPoint))
+ return false;
+
+ if (state.sizeChanged && !decoder.decode(state.size))
+ return false;
+
+ if (state.transformChanged && !decoder.decode(state.transform))
+ return false;
+
+ if (state.childrenTransformChanged && !decoder.decode(state.childrenTransform))
+ return false;
+
+ if (state.contentsRectChanged && !decoder.decode(state.contentsRect))
+ return false;
+
+ if (state.contentsTilingChanged) {
+ if (!decoder.decode(state.contentsTileSize))
+ return false;
+ if (!decoder.decode(state.contentsTilePhase))
+ return false;
+ }
+
+ if (state.opacityChanged && !decoder.decode(state.opacity))
+ return false;
+
+ if (state.solidColorChanged && !decoder.decode(state.solidColor))
+ return false;
+
+ if (state.debugBorderColorChanged && !decoder.decode(state.debugBorderColor))
+ return false;
+
+ if (state.debugBorderWidthChanged && !decoder.decode(state.debugBorderWidth))
+ return false;
+
+ if (state.filtersChanged && !decoder.decode(state.filters))
+ return false;
+
+ if (state.animationsChanged && !decoder.decode(state.animations))
+ return false;
+
+ if (state.childrenChanged && !decoder.decode(state.children))
+ return false;
+
+ if (!decoder.decode(state.tilesToCreate))
+ return false;
+
+ if (!decoder.decode(state.tilesToRemove))
+ return false;
+
+ if (state.replicaChanged && !decoder.decode(state.replica))
+ return false;
+
+ if (state.maskChanged && !decoder.decode(state.mask))
+ return false;
+
+ if (state.imageChanged && !decoder.decode(state.imageID))
+ return false;
+
+ if (state.repaintCountChanged && !decoder.decode(state.repaintCount))
+ return false;
+
+ if (!decoder.decode(state.tilesToUpdate))
+ return false;
+
+ if (state.committedScrollOffsetChanged && !decoder.decode(state.committedScrollOffset))
+ return false;
+
+ return true;
+}
+
+void ArgumentCoder<TileUpdateInfo>::encode(Encoder& encoder, const TileUpdateInfo& updateInfo)
+{
+ SimpleArgumentCoder<TileUpdateInfo>::encode(encoder, updateInfo);
+}
+
+bool ArgumentCoder<TileUpdateInfo>::decode(Decoder& decoder, TileUpdateInfo& updateInfo)
+{
+ return SimpleArgumentCoder<TileUpdateInfo>::decode(decoder, updateInfo);
+}
+
+void ArgumentCoder<TileCreationInfo>::encode(Encoder& encoder, const TileCreationInfo& updateInfo)
+{
+ SimpleArgumentCoder<TileCreationInfo>::encode(encoder, updateInfo);
+}
+
+bool ArgumentCoder<TileCreationInfo>::decode(Decoder& decoder, TileCreationInfo& updateInfo)
+{
+ return SimpleArgumentCoder<TileCreationInfo>::decode(decoder, updateInfo);
+}
+
+static void encodeCoordinatedSurface(Encoder& encoder, const RefPtr<CoordinatedSurface>& surface)
+{
+ bool isValidSurface = false;
+ if (!surface) {
+ encoder << isValidSurface;
+ return;
+ }
+
+ WebCoordinatedSurface* webCoordinatedSurface = static_cast<WebCoordinatedSurface*>(surface.get());
+ WebCoordinatedSurface::Handle handle;
+ if (webCoordinatedSurface->createHandle(handle))
+ isValidSurface = true;
+
+ encoder << isValidSurface;
+
+ if (isValidSurface)
+ encoder << handle;
+}
+
+static bool decodeCoordinatedSurface(Decoder& decoder, RefPtr<CoordinatedSurface>& surface)
+{
+ bool isValidSurface;
+ if (!decoder.decode(isValidSurface))
+ return false;
+
+ if (!isValidSurface)
+ return true;
+
+ WebCoordinatedSurface::Handle handle;
+ if (!decoder.decode(handle))
+ return false;
+
+ surface = WebCoordinatedSurface::create(handle);
+ return true;
+}
+
+void ArgumentCoder<CoordinatedGraphicsState>::encode(Encoder& encoder, const CoordinatedGraphicsState& state)
+{
+ encoder << state.rootCompositingLayer;
+ encoder << state.scrollPosition;
+ encoder << state.contentsSize;
+ encoder << state.coveredRect;
+
+ encoder << state.layersToCreate;
+ encoder << state.layersToUpdate;
+ encoder << state.layersToRemove;
+
+ encoder << state.imagesToCreate;
+ encoder << state.imagesToRemove;
+
+ // We need to encode WebCoordinatedSurface::Handle right after it's creation.
+ // That's why we cannot use simple std::pair encoder.
+ encoder << static_cast<uint64_t>(state.imagesToUpdate.size());
+ for (size_t i = 0; i < state.imagesToUpdate.size(); ++i) {
+ encoder << state.imagesToUpdate[i].first;
+ encodeCoordinatedSurface(encoder, state.imagesToUpdate[i].second);
+ }
+ encoder << state.imagesToClear;
+
+ encoder << static_cast<uint64_t>(state.updateAtlasesToCreate.size());
+ for (size_t i = 0; i < state.updateAtlasesToCreate.size(); ++i) {
+ encoder << state.updateAtlasesToCreate[i].first;
+ encodeCoordinatedSurface(encoder, state.updateAtlasesToCreate[i].second);
+ }
+ encoder << state.updateAtlasesToRemove;
+}
+
+bool ArgumentCoder<CoordinatedGraphicsState>::decode(Decoder& decoder, CoordinatedGraphicsState& state)
+{
+ if (!decoder.decode(state.rootCompositingLayer))
+ return false;
+
+ if (!decoder.decode(state.scrollPosition))
+ return false;
+
+ if (!decoder.decode(state.contentsSize))
+ return false;
+
+ if (!decoder.decode(state.coveredRect))
+ return false;
+
+ if (!decoder.decode(state.layersToCreate))
+ return false;
+
+ if (!decoder.decode(state.layersToUpdate))
+ return false;
+
+ if (!decoder.decode(state.layersToRemove))
+ return false;
+
+ if (!decoder.decode(state.imagesToCreate))
+ return false;
+
+ if (!decoder.decode(state.imagesToRemove))
+ return false;
+
+ uint64_t sizeOfImagesToUpdate;
+ if (!decoder.decode(sizeOfImagesToUpdate))
+ return false;
+
+ for (uint64_t i = 0; i < sizeOfImagesToUpdate; ++i) {
+ CoordinatedImageBackingID imageID;
+ if (!decoder.decode(imageID))
+ return false;
+
+ RefPtr<CoordinatedSurface> surface;
+ if (!decodeCoordinatedSurface(decoder, surface))
+ return false;
+
+ state.imagesToUpdate.append(std::make_pair(imageID, surface.release()));
+ }
+
+ if (!decoder.decode(state.imagesToClear))
+ return false;
+
+ uint64_t sizeOfUpdateAtlasesToCreate;
+ if (!decoder.decode(sizeOfUpdateAtlasesToCreate))
+ return false;
+
+ for (uint64_t i = 0; i < sizeOfUpdateAtlasesToCreate; ++i) {
+ uint32_t atlasID;
+ if (!decoder.decode(atlasID))
+ return false;
+
+ RefPtr<CoordinatedSurface> surface;
+ if (!decodeCoordinatedSurface(decoder, surface))
+ return false;
+
+ state.updateAtlasesToCreate.append(std::make_pair(atlasID, surface.release()));
+ }
+
+ if (!decoder.decode(state.updateAtlasesToRemove))
+ return false;
+
+ return true;
+}
+
+} // namespace IPC
+
+#endif // USE(COORDINATED_GRAPHICS)
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsArgumentCoders.h b/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsArgumentCoders.h
new file mode 100644
index 000000000..dd0c10b59
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsArgumentCoders.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2012 Company 100, Inc.
+ *
+ * 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 CoordinatedGraphicsArgumentCoders_h
+#define CoordinatedGraphicsArgumentCoders_h
+
+#if USE(COORDINATED_GRAPHICS)
+#include "ArgumentCoders.h"
+
+namespace WebCore {
+struct CoordinatedGraphicsLayerState;
+struct CoordinatedGraphicsState;
+class FloatPoint3D;
+class TextureMapperAnimation;
+class TextureMapperAnimations;
+class SurfaceUpdateInfo;
+struct TileCreationInfo;
+struct TileUpdateInfo;
+class TransformationMatrix;
+class TransformOperations;
+struct Length;
+
+class FilterOperations;
+}
+
+namespace IPC {
+
+template<> struct ArgumentCoder<WebCore::FilterOperations> {
+ static void encode(Encoder&, const WebCore::FilterOperations&);
+ static bool decode(Decoder&, WebCore::FilterOperations&);
+};
+
+template<> struct ArgumentCoder<WebCore::TransformOperations> {
+ static void encode(Encoder&, const WebCore::TransformOperations&);
+ static bool decode(Decoder&, WebCore::TransformOperations&);
+};
+
+template<> struct ArgumentCoder<WebCore::TextureMapperAnimations> {
+ static void encode(Encoder&, const WebCore::TextureMapperAnimations&);
+ static bool decode(Decoder&, WebCore::TextureMapperAnimations&);
+};
+
+template<> struct ArgumentCoder<WebCore::TextureMapperAnimation> {
+ static void encode(Encoder&, const WebCore::TextureMapperAnimation&);
+ static bool decode(Decoder&, WebCore::TextureMapperAnimation&);
+};
+
+template<> struct ArgumentCoder<WebCore::SurfaceUpdateInfo> {
+ static void encode(Encoder&, const WebCore::SurfaceUpdateInfo&);
+ static bool decode(Decoder&, WebCore::SurfaceUpdateInfo&);
+};
+
+template<> struct ArgumentCoder<WebCore::CoordinatedGraphicsLayerState> {
+ static void encode(Encoder&, const WebCore::CoordinatedGraphicsLayerState&);
+ static bool decode(Decoder&, WebCore::CoordinatedGraphicsLayerState&);
+};
+
+template<> struct ArgumentCoder<WebCore::TileUpdateInfo> {
+ static void encode(Encoder&, const WebCore::TileUpdateInfo&);
+ static bool decode(Decoder&, WebCore::TileUpdateInfo&);
+};
+
+template<> struct ArgumentCoder<WebCore::TileCreationInfo> {
+ static void encode(Encoder&, const WebCore::TileCreationInfo&);
+ static bool decode(Decoder&, WebCore::TileCreationInfo&);
+};
+
+template<> struct ArgumentCoder<WebCore::CoordinatedGraphicsState> {
+ static void encode(Encoder&, const WebCore::CoordinatedGraphicsState&);
+ static bool decode(Decoder&, WebCore::CoordinatedGraphicsState&);
+};
+
+} // namespace IPC
+
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // CoordinatedGraphicsArgumentCoders_h
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsScene.cpp b/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsScene.cpp
new file mode 100644
index 000000000..b94faea2c
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsScene.cpp
@@ -0,0 +1,682 @@
+/*
+ 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 <WebCore/TextureMapper.h>
+#include <WebCore/TextureMapperBackingStore.h>
+#include <WebCore/TextureMapperGL.h>
+#include <WebCore/TextureMapperLayer.h>
+#include <wtf/Atomics.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+void CoordinatedGraphicsScene::dispatchOnMainThread(Function<void()>&& function)
+{
+ if (isMainThread()) {
+ function();
+ return;
+ }
+
+ RunLoop::main().dispatch([protectedThis = makeRef(*this), function = WTFMove(function)] {
+ function();
+ });
+}
+
+void CoordinatedGraphicsScene::dispatchOnClientRunLoop(Function<void()>&& function)
+{
+ if (&m_clientRunLoop == &RunLoop::current()) {
+ function();
+ return;
+ }
+
+ m_clientRunLoop.dispatch([protectedThis = makeRef(*this), function = WTFMove(function)] {
+ 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_viewBackgroundColor(Color::white)
+ , m_clientRunLoop(RunLoop::current())
+{
+}
+
+CoordinatedGraphicsScene::~CoordinatedGraphicsScene()
+{
+}
+
+void CoordinatedGraphicsScene::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity, const FloatRect& clipRect, const Color& backgroundColor, bool drawsBackground, const FloatPoint& contentPosition, TextureMapper::PaintFlags PaintFlags)
+{
+ if (!m_textureMapper) {
+ m_textureMapper = TextureMapper::create();
+ static_cast<TextureMapperGL*>(m_textureMapper.get())->setEnableEdgeDistanceAntialiasing(true);
+ }
+
+ syncRemoteContent();
+
+ adjustPositionForFixedLayers(contentPosition);
+ TextureMapperLayer* currentRootLayer = rootLayer();
+ if (!currentRootLayer)
+ return;
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ for (auto& proxy : m_platformLayerProxies.values())
+ proxy->swapBuffer();
+#endif
+
+ currentRootLayer->setTextureMapper(m_textureMapper.get());
+ currentRootLayer->applyAnimationsRecursively();
+ m_textureMapper->beginPainting(PaintFlags);
+ m_textureMapper->beginClip(TransformationMatrix(), clipRect);
+
+ if (drawsBackground) {
+ RGBA32 rgba = makeRGBA32FromFloats(backgroundColor.red(),
+ backgroundColor.green(), backgroundColor.blue(),
+ backgroundColor.alpha() * opacity);
+ m_textureMapper->drawSolidColor(clipRect, TransformationMatrix(), Color(rgba));
+ } else {
+ GraphicsContext3D* context = static_cast<TextureMapperGL*>(m_textureMapper.get())->graphicsContext3D();
+ context->clearColor(m_viewBackgroundColor.red() / 255.0f, m_viewBackgroundColor.green() / 255.0f, m_viewBackgroundColor.blue() / 255.0f, m_viewBackgroundColor.alpha() / 255.0f);
+ context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
+ }
+
+ if (currentRootLayer->opacity() != opacity || currentRootLayer->transform() != matrix) {
+ currentRootLayer->setOpacity(opacity);
+ currentRootLayer->setTransform(matrix);
+ }
+
+ currentRootLayer->paint();
+ m_fpsCounter.updateFPSAndDisplay(*m_textureMapper, clipRect.location(), matrix);
+ m_textureMapper->endClip();
+ m_textureMapper->endPainting();
+
+ if (currentRootLayer->descendantsOrSelfHaveRunningAnimations())
+ updateViewport();
+}
+
+void CoordinatedGraphicsScene::updateViewport()
+{
+ if (!m_client)
+ return;
+ dispatchOnClientRunLoop([this] {
+ if (m_client)
+ m_client->updateViewport();
+ });
+}
+
+void CoordinatedGraphicsScene::adjustPositionForFixedLayers(const FloatPoint& contentPosition)
+{
+ 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 = contentPosition - m_renderedContentsScrollPosition;
+
+ for (auto& fixedLayer : m_fixedLayers.values())
+ fixedLayer->setScrollPositionDeltaIfNeeded(delta);
+}
+
+void CoordinatedGraphicsScene::syncPlatformLayerIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
+{
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ if (!state.platformLayerChanged)
+ return;
+
+ if (state.platformLayerProxy) {
+ m_platformLayerProxies.set(layer, state.platformLayerProxy);
+ state.platformLayerProxy->activateOnCompositingThread(this, layer);
+ } else
+ m_platformLayerProxies.remove(layer);
+#else
+ UNUSED_PARAM(layer);
+ UNUSED_PARAM(state);
+#endif
+}
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+void CoordinatedGraphicsScene::onNewBufferAvailable()
+{
+ updateViewport();
+}
+#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;
+ children.reserveCapacity(state.children.size());
+ for (auto& child : state.children)
+ children.append(layerByID(child));
+
+ layer->setChildren(children);
+}
+
+void CoordinatedGraphicsScene::setLayerFiltersIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
+{
+ if (!state.filtersChanged)
+ return;
+
+ layer->setFilters(state.filters);
+}
+
+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);
+ setLayerFiltersIfNeeded(layer, layerState);
+ setLayerAnimationsIfNeeded(layer, layerState);
+ syncPlatformLayerIfNeeded(layer, layerState);
+ setLayerRepaintCountIfNeeded(layer, layerState);
+}
+
+TextureMapperLayer* CoordinatedGraphicsScene::getLayerByIDIfExists(CoordinatedLayerID id)
+{
+ return (id != InvalidCoordinatedLayerID) ? layerByID(id) : 0;
+}
+
+void CoordinatedGraphicsScene::createLayers(const Vector<CoordinatedLayerID>& layerIDs)
+{
+ for (auto& layerID : layerIDs)
+ createLayer(layerID);
+}
+
+void CoordinatedGraphicsScene::createLayer(CoordinatedLayerID id)
+{
+ std::unique_ptr<TextureMapperLayer> newLayer = std::make_unique<TextureMapperLayer>();
+ newLayer->setID(id);
+ newLayer->setScrollClient(this);
+ m_layers.add(id, WTFMove(newLayer));
+}
+
+void CoordinatedGraphicsScene::deleteLayers(const Vector<CoordinatedLayerID>& layerIDs)
+{
+ for (auto& layerID : layerIDs)
+ deleteLayer(layerID);
+}
+
+void CoordinatedGraphicsScene::deleteLayer(CoordinatedLayerID layerID)
+{
+ std::unique_ptr<TextureMapperLayer> layer = m_layers.take(layerID);
+ ASSERT(layer);
+
+ m_backingStores.remove(layer.get());
+ m_fixedLayers.remove(layerID);
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ if (auto platformLayerProxy = m_platformLayerProxies.take(layer.get()))
+ platformLayerProxy->invalidate();
+#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 || !layerShouldHaveBackingStore(layer));
+ if (!backingStore)
+ return;
+
+ for (auto& tile : state.tilesToCreate)
+ backingStore->createTile(tile.tileID, tile.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 (auto& tile : state.tilesToRemove)
+ backingStore->removeTile(tile);
+
+ 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 || !layerShouldHaveBackingStore(layer));
+ if (!backingStore)
+ return;
+
+ for (auto& tile : state.tilesToUpdate) {
+ const SurfaceUpdateInfo& surfaceUpdateInfo = tile.updateInfo;
+
+ SurfaceMap::iterator surfaceIt = m_surfaces.find(surfaceUpdateInfo.atlasID);
+ ASSERT(surfaceIt != m_surfaces.end());
+
+ backingStore->updateTile(tile.tileID, surfaceUpdateInfo.updateRect, tile.tileRect, surfaceIt->value, surfaceUpdateInfo.surfaceOffset);
+ m_backingStoresWithPendingBuffers.add(backingStore);
+ }
+}
+
+void CoordinatedGraphicsScene::syncUpdateAtlases(const CoordinatedGraphicsState& state)
+{
+ for (auto& atlas : state.updateAtlasesToCreate)
+ createUpdateAtlas(atlas.first, atlas.second);
+
+ for (auto& atlas : state.updateAtlasesToRemove)
+ removeUpdateAtlas(atlas);
+}
+
+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 (auto& image : state.imagesToRemove)
+ removeImageBacking(image);
+
+ for (auto& image : state.imagesToCreate)
+ createImageBacking(image);
+
+ for (auto& image : state.imagesToUpdate)
+ updateImageBacking(image.first, image.second);
+
+ for (auto& image : state.imagesToClear)
+ clearImageBackingContents(image);
+}
+
+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 (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()
+{
+ for (auto& backingStore : m_backingStoresWithPendingBuffers)
+ backingStore->commitTileOperations(*m_textureMapper);
+
+ m_backingStoresWithPendingBuffers.clear();
+}
+
+void CoordinatedGraphicsScene::commitSceneState(const CoordinatedGraphicsState& state)
+{
+ if (!m_client)
+ return;
+
+ m_renderedContentsScrollPosition = state.scrollPosition;
+
+ createLayers(state.layersToCreate);
+ deleteLayers(state.layersToRemove);
+
+ if (state.rootCompositingLayer != m_rootLayerID)
+ setRootLayerID(state.rootCompositingLayer);
+
+ syncImageBackings(state);
+ syncUpdateAtlases(state);
+
+ for (auto& layer : state.layersToUpdate)
+ setLayerState(layer.first, layer.second);
+
+ commitPendingBackingStoreOperations();
+ removeReleasedImageBackingsIfNeeded();
+
+ // The pending tiles state is on its way for the screen, tell the web process to render the next one.
+ renderNextFrame();
+}
+
+void CoordinatedGraphicsScene::renderNextFrame()
+{
+ if (!m_client)
+ return;
+ dispatchOnMainThread([this] {
+ if (m_client)
+ m_client->renderNextFrame();
+ });
+}
+
+void CoordinatedGraphicsScene::ensureRootLayer()
+{
+ if (m_rootLayer)
+ return;
+
+ m_rootLayer = std::make_unique<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<std::function<void()>> renderQueue;
+ bool calledOnMainThread = WTF::isMainThread();
+ if (!calledOnMainThread)
+ m_renderQueueMutex.lock();
+ renderQueue = WTFMove(m_renderQueue);
+ if (!calledOnMainThread)
+ m_renderQueueMutex.unlock();
+
+ for (auto& function : renderQueue)
+ function();
+}
+
+void CoordinatedGraphicsScene::purgeGLResources()
+{
+ ASSERT(!m_client);
+
+ m_imageBackings.clear();
+ m_releasedImageBackings.clear();
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ for (auto& proxy : m_platformLayerProxies.values())
+ proxy->invalidate();
+ m_platformLayerProxies.clear();
+#endif
+ m_surfaces.clear();
+
+ m_rootLayer = nullptr;
+ m_rootLayerID = InvalidCoordinatedLayerID;
+ m_layers.clear();
+ m_fixedLayers.clear();
+ m_textureMapper = nullptr;
+ m_backingStores.clear();
+ m_backingStoresWithPendingBuffers.clear();
+}
+
+void CoordinatedGraphicsScene::commitScrollOffset(uint32_t layerID, const IntSize& offset)
+{
+ if (!m_client)
+ return;
+ dispatchOnMainThread([this, layerID, offset] {
+ if (m_client)
+ m_client->commitScrollOffset(layerID, offset);
+ });
+}
+
+void CoordinatedGraphicsScene::setLayerAnimationsIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
+{
+ if (!state.animationsChanged)
+ return;
+
+ layer->setAnimations(state.animations);
+}
+
+void CoordinatedGraphicsScene::detach()
+{
+ ASSERT(isMainThread());
+ m_isActive = false;
+ m_client = nullptr;
+ LockHolder locker(m_renderQueueMutex);
+ m_renderQueue.clear();
+}
+
+void CoordinatedGraphicsScene::appendUpdate(std::function<void()>&& function)
+{
+ if (!m_isActive)
+ return;
+
+ ASSERT(isMainThread());
+ LockHolder locker(m_renderQueueMutex);
+ m_renderQueue.append(WTFMove(function));
+}
+
+void CoordinatedGraphicsScene::setActive(bool active)
+{
+ if (!m_client)
+ return;
+
+ 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)
+ renderNextFrame();
+}
+
+TextureMapperLayer* CoordinatedGraphicsScene::findScrollableContentsLayerAt(const FloatPoint& point)
+{
+ return rootLayer() ? rootLayer()->findScrollableContentsLayerAt(point) : 0;
+}
+
+} // namespace WebKit
+
+#endif // USE(COORDINATED_GRAPHICS)
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsScene.h b/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsScene.h
new file mode 100644
index 000000000..128b7be76
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsScene.h
@@ -0,0 +1,194 @@
+/*
+ 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 <WebCore/CoordinatedGraphicsState.h>
+#include <WebCore/CoordinatedSurface.h>
+#include <WebCore/GraphicsContext.h>
+#include <WebCore/GraphicsLayer.h>
+#include <WebCore/IntRect.h>
+#include <WebCore/IntSize.h>
+#include <WebCore/TextureMapper.h>
+#include <WebCore/TextureMapperBackingStore.h>
+#include <WebCore/TextureMapperFPSCounter.h>
+#include <WebCore/TextureMapperLayer.h>
+#include <WebCore/Timer.h>
+#include <wtf/Function.h>
+#include <wtf/HashSet.h>
+#include <wtf/Lock.h>
+#include <wtf/RunLoop.h>
+#include <wtf/ThreadingPrimitives.h>
+#include <wtf/Vector.h>
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+#include <WebCore/TextureMapperPlatformLayerProxy.h>
+#endif
+
+namespace WebKit {
+
+class CoordinatedBackingStore;
+
+class CoordinatedGraphicsSceneClient {
+public:
+ virtual ~CoordinatedGraphicsSceneClient() { }
+ virtual void renderNextFrame() = 0;
+ virtual void updateViewport() = 0;
+ virtual void commitScrollOffset(uint32_t layerID, const WebCore::IntSize& offset) = 0;
+};
+
+class CoordinatedGraphicsScene : public ThreadSafeRefCounted<CoordinatedGraphicsScene>, public WebCore::TextureMapperLayer::ScrollingClient
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ , public WebCore::TextureMapperPlatformLayerProxy::Compositor
+#endif
+{
+public:
+ explicit CoordinatedGraphicsScene(CoordinatedGraphicsSceneClient*);
+ virtual ~CoordinatedGraphicsScene();
+ void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float, const WebCore::FloatRect&, const WebCore::Color& backgroundColor, bool drawsBackground, const WebCore::FloatPoint&, WebCore::TextureMapper::PaintFlags = 0);
+ void detach();
+ void appendUpdate(std::function<void()>&&);
+
+ WebCore::TextureMapperLayer* findScrollableContentsLayerAt(const WebCore::FloatPoint&);
+
+ void commitScrollOffset(uint32_t layerID, const WebCore::IntSize& offset) override;
+
+ // 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();
+
+ bool isActive() const { return m_isActive; }
+ void setActive(bool);
+
+ void commitSceneState(const WebCore::CoordinatedGraphicsState&);
+
+ void setViewBackgroundColor(const WebCore::Color& color) { m_viewBackgroundColor = color; }
+ WebCore::Color viewBackgroundColor() const { return m_viewBackgroundColor; }
+
+private:
+ void setRootLayerID(WebCore::CoordinatedLayerID);
+ void createLayers(const Vector<WebCore::CoordinatedLayerID>&);
+ void deleteLayers(const Vector<WebCore::CoordinatedLayerID>&);
+ void setLayerState(WebCore::CoordinatedLayerID, const WebCore::CoordinatedGraphicsLayerState&);
+ void setLayerChildrenIfNeeded(WebCore::TextureMapperLayer*, const WebCore::CoordinatedGraphicsLayerState&);
+ void updateTilesIfNeeded(WebCore::TextureMapperLayer*, const WebCore::CoordinatedGraphicsLayerState&);
+ void createTilesIfNeeded(WebCore::TextureMapperLayer*, const WebCore::CoordinatedGraphicsLayerState&);
+ void removeTilesIfNeeded(WebCore::TextureMapperLayer*, const WebCore::CoordinatedGraphicsLayerState&);
+ void setLayerFiltersIfNeeded(WebCore::TextureMapperLayer*, const WebCore::CoordinatedGraphicsLayerState&);
+ void setLayerAnimationsIfNeeded(WebCore::TextureMapperLayer*, const WebCore::CoordinatedGraphicsLayerState&);
+ void syncPlatformLayerIfNeeded(WebCore::TextureMapperLayer*, const WebCore::CoordinatedGraphicsLayerState&);
+ void setLayerRepaintCountIfNeeded(WebCore::TextureMapperLayer*, const WebCore::CoordinatedGraphicsLayerState&);
+
+ void syncUpdateAtlases(const WebCore::CoordinatedGraphicsState&);
+ void createUpdateAtlas(uint32_t atlasID, PassRefPtr<WebCore::CoordinatedSurface>);
+ void removeUpdateAtlas(uint32_t atlasID);
+
+ void syncImageBackings(const WebCore::CoordinatedGraphicsState&);
+ void createImageBacking(WebCore::CoordinatedImageBackingID);
+ void updateImageBacking(WebCore::CoordinatedImageBackingID, PassRefPtr<WebCore::CoordinatedSurface>);
+ void clearImageBackingContents(WebCore::CoordinatedImageBackingID);
+ void removeImageBacking(WebCore::CoordinatedImageBackingID);
+
+ WebCore::TextureMapperLayer* layerByID(WebCore::CoordinatedLayerID id)
+ {
+ ASSERT(m_layers.contains(id));
+ ASSERT(id != WebCore::InvalidCoordinatedLayerID);
+ return m_layers.get(id);
+ }
+ WebCore::TextureMapperLayer* getLayerByIDIfExists(WebCore::CoordinatedLayerID);
+ WebCore::TextureMapperLayer* rootLayer() { return m_rootLayer.get(); }
+
+ void syncRemoteContent();
+ void adjustPositionForFixedLayers(const WebCore::FloatPoint& contentPosition);
+
+ void dispatchOnMainThread(Function<void()>&&);
+ void dispatchOnClientRunLoop(Function<void()>&&);
+ void updateViewport();
+ void renderNextFrame();
+
+ void createLayer(WebCore::CoordinatedLayerID);
+ void deleteLayer(WebCore::CoordinatedLayerID);
+
+ void assignImageBackingToLayer(WebCore::TextureMapperLayer*, WebCore::CoordinatedImageBackingID);
+ void removeReleasedImageBackingsIfNeeded();
+ void ensureRootLayer();
+ void commitPendingBackingStoreOperations();
+
+ void prepareContentBackingStore(WebCore::TextureMapperLayer*);
+ void createBackingStoreIfNeeded(WebCore::TextureMapperLayer*);
+ void removeBackingStoreIfNeeded(WebCore::TextureMapperLayer*);
+ void resetBackingStoreSizeToLayerSize(WebCore::TextureMapperLayer*);
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ void onNewBufferAvailable() override;
+#endif
+
+ // Render queue can be accessed ony from main thread or updatePaintNode call stack!
+ Vector<std::function<void()>> m_renderQueue;
+ Lock m_renderQueueMutex;
+
+ std::unique_ptr<WebCore::TextureMapper> m_textureMapper;
+
+ typedef HashMap<WebCore::CoordinatedImageBackingID, RefPtr<CoordinatedBackingStore>> ImageBackingMap;
+ ImageBackingMap m_imageBackings;
+ Vector<RefPtr<CoordinatedBackingStore>> m_releasedImageBackings;
+
+ typedef HashMap<WebCore::TextureMapperLayer*, RefPtr<CoordinatedBackingStore>> BackingStoreMap;
+ BackingStoreMap m_backingStores;
+
+ HashSet<RefPtr<CoordinatedBackingStore>> m_backingStoresWithPendingBuffers;
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+ typedef HashMap<WebCore::TextureMapperLayer*, RefPtr<WebCore::TextureMapperPlatformLayerProxy>> PlatformLayerProxyMap;
+ PlatformLayerProxyMap m_platformLayerProxies;
+#endif
+
+ typedef HashMap<uint32_t /* atlasID */, RefPtr<WebCore::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;
+
+ std::unique_ptr<WebCore::TextureMapperLayer> m_rootLayer;
+
+ typedef HashMap<WebCore::CoordinatedLayerID, std::unique_ptr<WebCore::TextureMapperLayer>> LayerMap;
+ LayerMap m_layers;
+ typedef HashMap<WebCore::CoordinatedLayerID, WebCore::TextureMapperLayer*> LayerRawPtrMap;
+ LayerRawPtrMap m_fixedLayers;
+ WebCore::CoordinatedLayerID m_rootLayerID;
+ WebCore::FloatPoint m_scrollPosition;
+ WebCore::FloatPoint m_renderedContentsScrollPosition;
+ WebCore::Color m_viewBackgroundColor;
+
+ WebCore::TextureMapperFPSCounter m_fpsCounter;
+
+ RunLoop& m_clientRunLoop;
+};
+
+} // namespace WebKit
+
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // CoordinatedGraphicsScene_h
+
+
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp b/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp
new file mode 100644
index 000000000..a5eaafea4
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2011, 2012 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2011 Benjamin Poulain <benjamin@webkit.org>
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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 program 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 program; 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 "SimpleViewportController.h"
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+
+using namespace WebCore;
+
+namespace WebKit {
+
+SimpleViewportController::SimpleViewportController(const IntSize& size)
+ : m_viewportSize(size)
+{
+ resetViewportToDefaultState();
+}
+
+void SimpleViewportController::didChangeViewportSize(const IntSize& newSize)
+{
+ if (newSize.isEmpty())
+ return;
+
+ m_viewportSize = newSize;
+ updateMinimumScaleToFit();
+}
+
+void SimpleViewportController::didChangeContentsSize(const IntSize& newSize)
+{
+ m_contentsSize = newSize;
+
+ updateMinimumScaleToFit();
+
+ if (m_initiallyFitToViewport) {
+ // Restrict scale factors to m_minimumScaleToFit.
+ ASSERT(m_minimumScaleToFit > 0);
+ m_rawAttributes.initialScale = m_minimumScaleToFit;
+ restrictScaleFactorToInitialScaleIfNotUserScalable(m_rawAttributes);
+ }
+}
+
+void SimpleViewportController::didChangeViewportAttributes(ViewportAttributes&& newAttributes)
+{
+ if (newAttributes.layoutSize.isEmpty()) {
+ resetViewportToDefaultState();
+ return;
+ }
+
+ m_hasViewportAttribute = true;
+
+ m_rawAttributes = WTFMove(newAttributes);
+ m_allowsUserScaling = m_rawAttributes.userScalable;
+ m_initiallyFitToViewport = m_rawAttributes.initialScale < 0;
+
+ if (!m_initiallyFitToViewport)
+ restrictScaleFactorToInitialScaleIfNotUserScalable(m_rawAttributes);
+
+ updateMinimumScaleToFit();
+}
+
+void SimpleViewportController::didScroll(const IntPoint& position)
+{
+ m_contentsPosition = position;
+}
+
+FloatRect SimpleViewportController::visibleContentsRect() const
+{
+ if (m_viewportSize.isEmpty() || m_contentsSize.isEmpty())
+ return { };
+
+ FloatRect visibleContentsRect(boundContentsPosition(m_contentsPosition), visibleContentsSize());
+ visibleContentsRect.intersect(FloatRect(FloatPoint::zero(), m_contentsSize));
+ return visibleContentsRect;
+}
+
+FloatSize SimpleViewportController::visibleContentsSize() const
+{
+ return FloatSize(m_viewportSize.width() / m_pageScaleFactor, m_viewportSize.height() / m_pageScaleFactor);
+}
+
+FloatPoint SimpleViewportController::boundContentsPositionAtScale(const FloatPoint& framePosition, float scale) const
+{
+ // We need to floor the viewport here as to allow aligning the content in device units. If not,
+ // it might not be possible to scroll the last pixel and that affects fixed position elements.
+ return FloatPoint(
+ clampTo(framePosition.x(), .0f, std::max(.0f, m_contentsSize.width() - floorf(m_viewportSize.width() / scale))),
+ clampTo(framePosition.y(), .0f, std::max(.0f, m_contentsSize.height() - floorf(m_viewportSize.height() / scale))));
+}
+
+FloatPoint SimpleViewportController::boundContentsPosition(const FloatPoint& framePosition) const
+{
+ return boundContentsPositionAtScale(framePosition, m_pageScaleFactor);
+}
+
+bool fuzzyCompare(float a, float b, float epsilon)
+{
+ return std::abs(a - b) < epsilon;
+}
+
+bool SimpleViewportController::updateMinimumScaleToFit()
+{
+ if (m_viewportSize.isEmpty() || m_contentsSize.isEmpty() || !m_hasViewportAttribute)
+ return false;
+
+ bool currentlyScaledToFit = fuzzyCompare(m_pageScaleFactor, m_minimumScaleToFit, 0.0001);
+
+ float minimumScale = computeMinimumScaleFactorForContentContained(m_rawAttributes, roundedIntSize(m_viewportSize), roundedIntSize(m_contentsSize));
+
+ if (minimumScale <= 0)
+ return false;
+
+ if (!fuzzyCompare(minimumScale, m_minimumScaleToFit, 0.0001)) {
+ m_minimumScaleToFit = minimumScale;
+
+ if (currentlyScaledToFit)
+ m_pageScaleFactor = m_minimumScaleToFit;
+ else {
+ // Ensure the effective scale stays within bounds.
+ float boundedScale = innerBoundedViewportScale(m_pageScaleFactor);
+ if (!fuzzyCompare(boundedScale, m_pageScaleFactor, 0.0001))
+ m_pageScaleFactor = boundedScale;
+ }
+
+ return true;
+ }
+ return false;
+}
+
+float SimpleViewportController::innerBoundedViewportScale(float viewportScale) const
+{
+ return clampTo(viewportScale, m_minimumScaleToFit, m_rawAttributes.maximumScale);
+}
+
+void SimpleViewportController::resetViewportToDefaultState()
+{
+ m_hasViewportAttribute = false;
+ m_pageScaleFactor = 1;
+ m_minimumScaleToFit = 1;
+
+ // Initializing Viewport Raw Attributes to avoid random negative or infinity scale factors
+ // if there is a race condition between the first layout and setting the viewport attributes for the first time.
+ m_rawAttributes.minimumScale = 1;
+ m_rawAttributes.maximumScale = 1;
+ m_rawAttributes.userScalable = m_allowsUserScaling;
+
+ // The initial scale might be implicit and set to -1, in this case we have to infer it
+ // using the viewport size and the final layout size.
+ // To be able to assert for valid scale we initialize it to -1.
+ m_rawAttributes.initialScale = -1;
+}
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS_THREADED)
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.h b/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.h
new file mode 100644
index 000000000..0bd1a3587
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2011, 2012 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2011 Benjamin Poulain <benjamin@webkit.org>
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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 program 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 program; 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 SimpleViewportController_h
+#define SimpleViewportController_h
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+
+#include <WebCore/FloatPoint.h>
+#include <WebCore/FloatRect.h>
+#include <WebCore/FloatSize.h>
+#include <WebCore/IntRect.h>
+#include <WebCore/IntSize.h>
+#include <WebCore/ViewportArguments.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebKit {
+
+class SimpleViewportController {
+ WTF_MAKE_NONCOPYABLE(SimpleViewportController);
+public:
+ SimpleViewportController(const WebCore::IntSize&);
+
+ void didChangeViewportSize(const WebCore::IntSize&);
+ void didChangeContentsSize(const WebCore::IntSize&);
+ void didChangeViewportAttributes(WebCore::ViewportAttributes&&);
+ void didScroll(const WebCore::IntPoint&);
+
+ WebCore::FloatRect visibleContentsRect() const;
+ float pageScaleFactor() const { return m_pageScaleFactor; }
+
+private:
+ WebCore::FloatSize visibleContentsSize() const;
+
+ void applyScaleAfterRenderingContents(float scale);
+ void applyPositionAfterRenderingContents(const WebCore::FloatPoint& pos);
+
+ WebCore::FloatPoint boundContentsPosition(const WebCore::FloatPoint&) const;
+ WebCore::FloatPoint boundContentsPositionAtScale(const WebCore::FloatPoint&, float scale) const;
+
+ bool updateMinimumScaleToFit();
+ float innerBoundedViewportScale(float) const;
+
+ void resetViewportToDefaultState();
+
+ WebCore::IntPoint m_contentsPosition;
+ WebCore::FloatSize m_contentsSize;
+ WebCore::FloatSize m_viewportSize;
+ float m_pageScaleFactor { 1 };
+
+ bool m_allowsUserScaling { false };
+ float m_minimumScaleToFit { 1 };
+ bool m_initiallyFitToViewport { false };
+
+ bool m_hasViewportAttribute { false };
+ WebCore::ViewportAttributes m_rawAttributes;
+};
+
+} // namespace WebKit
+
+#endif // USE(COORDINATED_GRAPHICS_THREADED)
+
+#endif // SimpleViewportController_h
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/WebCoordinatedSurface.cpp b/Source/WebKit2/Shared/CoordinatedGraphics/WebCoordinatedSurface.cpp
new file mode 100644
index 000000000..0ad1e7f86
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/WebCoordinatedSurface.cpp
@@ -0,0 +1,131 @@
+/*
+ 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 "WebCoordinatedSurface.h"
+
+#if USE(COORDINATED_GRAPHICS)
+#include "CoordinatedGraphicsArgumentCoders.h"
+#include "GraphicsContext.h"
+#include "WebCoreArgumentCoders.h"
+#include <WebCore/GraphicsSurfaceToken.h>
+
+#if USE(TEXTURE_MAPPER)
+#include "BitmapTextureGL.h"
+#include "TextureMapperGL.h"
+#endif
+
+using namespace WebCore;
+
+namespace WebKit {
+
+WebCoordinatedSurface::Handle::Handle()
+{
+}
+
+void WebCoordinatedSurface::Handle::encode(IPC::Encoder& encoder) const
+{
+ encoder << m_size << m_flags;
+ encoder << m_bitmapHandle;
+}
+
+bool WebCoordinatedSurface::Handle::decode(IPC::Decoder& decoder, Handle& handle)
+{
+ if (!decoder.decode(handle.m_size))
+ return false;
+ if (!decoder.decode(handle.m_flags))
+ return false;
+ if (!decoder.decode(handle.m_bitmapHandle))
+ return false;
+
+ return true;
+}
+
+RefPtr<WebCoordinatedSurface> WebCoordinatedSurface::create(const IntSize& size, CoordinatedSurface::Flags flags)
+{
+ if (auto bitmap = ShareableBitmap::createShareable(size, (flags & SupportsAlpha) ? ShareableBitmap::SupportsAlpha : ShareableBitmap::NoFlags))
+ return create(size, flags, WTFMove(bitmap));
+
+ return nullptr;
+}
+
+std::unique_ptr<GraphicsContext> WebCoordinatedSurface::createGraphicsContext(const IntRect& rect)
+{
+ ASSERT(m_bitmap);
+ auto graphicsContext = m_bitmap->createGraphicsContext();
+ graphicsContext->clip(rect);
+ graphicsContext->translate(rect.x(), rect.y());
+ return graphicsContext;
+}
+
+Ref<WebCoordinatedSurface> WebCoordinatedSurface::create(const IntSize& size, CoordinatedSurface::Flags flags, RefPtr<ShareableBitmap> bitmap)
+{
+ return adoptRef(*new WebCoordinatedSurface(size, flags, bitmap));
+}
+
+WebCoordinatedSurface::WebCoordinatedSurface(const IntSize& size, CoordinatedSurface::Flags flags, RefPtr<ShareableBitmap> bitmap)
+ : CoordinatedSurface(size, flags)
+ , m_bitmap(bitmap)
+{
+}
+
+WebCoordinatedSurface::~WebCoordinatedSurface()
+{
+}
+
+RefPtr<WebCoordinatedSurface> WebCoordinatedSurface::create(const Handle& handle)
+{
+ RefPtr<ShareableBitmap> bitmap = ShareableBitmap::create(handle.m_bitmapHandle);
+ if (!bitmap)
+ return nullptr;
+
+ return create(handle.m_size, handle.m_flags, WTFMove(bitmap));
+}
+
+bool WebCoordinatedSurface::createHandle(Handle& handle)
+{
+ handle.m_size = m_size;
+ handle.m_flags = m_flags;
+
+ if (!m_bitmap->createHandle(handle.m_bitmapHandle))
+ return false;
+
+ return true;
+}
+
+void WebCoordinatedSurface::paintToSurface(const IntRect& rect, CoordinatedSurface::Client& client)
+{
+ auto context = createGraphicsContext(rect);
+ client.paintToSurfaceContext(*context);
+}
+
+#if USE(TEXTURE_MAPPER)
+void WebCoordinatedSurface::copyToTexture(RefPtr<WebCore::BitmapTexture> passTexture, const IntRect& target, const IntPoint& sourceOffset)
+{
+ RefPtr<BitmapTexture> texture(passTexture);
+
+ ASSERT(m_bitmap);
+ RefPtr<Image> image = m_bitmap->createImage();
+ texture->updateContents(image.get(), target, sourceOffset, BitmapTexture::UpdateCanModifyOriginalImageData);
+}
+#endif // USE(TEXTURE_MAPPER)
+
+} // namespace WebKit
+#endif // USE(COORDINATED_GRAPHICS)
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/WebCoordinatedSurface.h b/Source/WebKit2/Shared/CoordinatedGraphics/WebCoordinatedSurface.h
new file mode 100644
index 000000000..88a0c1059
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/WebCoordinatedSurface.h
@@ -0,0 +1,83 @@
+/*
+ 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 WebCoordinatedSurface_h
+#define WebCoordinatedSurface_h
+
+#if USE(COORDINATED_GRAPHICS)
+#include "ShareableBitmap.h"
+#include <WebCore/CoordinatedSurface.h>
+
+namespace WebCore {
+class BitmapTexture;
+class GraphicsContext;
+}
+
+namespace WebKit {
+
+class WebCoordinatedSurface : public WebCore::CoordinatedSurface {
+public:
+ class Handle {
+ WTF_MAKE_NONCOPYABLE(Handle);
+ public:
+ Handle();
+
+ void encode(IPC::Encoder&) const;
+ static bool decode(IPC::Decoder&, Handle&);
+
+ private:
+ friend class WebCoordinatedSurface;
+ mutable ShareableBitmap::Handle m_bitmapHandle;
+ WebCore::IntSize m_size;
+ WebCore::CoordinatedSurface::Flags m_flags;
+ };
+
+ // Create a new WebCoordinatedSurface, and allocate either a GraphicsSurface or a ShareableBitmap as backing.
+ static RefPtr<WebCoordinatedSurface> create(const WebCore::IntSize&, Flags);
+
+ // Create a shareable surface from a handle.
+ static RefPtr<WebCoordinatedSurface> create(const Handle&);
+
+ // Create a handle.
+ bool createHandle(Handle&);
+
+ virtual ~WebCoordinatedSurface();
+
+ void paintToSurface(const WebCore::IntRect&, WebCore::CoordinatedSurface::Client&) override;
+
+#if USE(TEXTURE_MAPPER)
+ void copyToTexture(RefPtr<WebCore::BitmapTexture>, const WebCore::IntRect& target, const WebCore::IntPoint& sourceOffset) override;
+#endif
+
+private:
+ WebCoordinatedSurface(const WebCore::IntSize&, Flags, RefPtr<ShareableBitmap>);
+
+ // Create a WebCoordinatedSurface referencing an existing ShareableBitmap.
+ static Ref<WebCoordinatedSurface> create(const WebCore::IntSize&, Flags, RefPtr<ShareableBitmap>);
+
+ std::unique_ptr<WebCore::GraphicsContext> createGraphicsContext(const WebCore::IntRect&);
+
+ RefPtr<ShareableBitmap> m_bitmap;
+};
+
+} // namespace WebKit
+
+#endif // USE(COORDINATED_GRAPHICS)
+#endif // WebCoordinatedSurface_h
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/CompositingRunLoop.cpp b/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/CompositingRunLoop.cpp
new file mode 100644
index 000000000..a6eee3fd9
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/CompositingRunLoop.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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 "CompositingRunLoop.h"
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+
+#include <wtf/HashMap.h>
+#include <wtf/MainThread.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/WorkQueue.h>
+
+#if USE(GLIB_EVENT_LOOP)
+#include <glib.h>
+#endif
+
+namespace WebKit {
+
+class WorkQueuePool {
+ WTF_MAKE_NONCOPYABLE(WorkQueuePool);
+ friend class NeverDestroyed<WorkQueuePool>;
+public:
+ static WorkQueuePool& singleton()
+ {
+ ASSERT(isMainThread());
+ static NeverDestroyed<WorkQueuePool> workQueuePool;
+ return workQueuePool;
+ }
+
+ void dispatch(void* context, Function<void ()>&& function)
+ {
+ ASSERT(isMainThread());
+ getOrCreateWorkQueueForContext(context).dispatch(WTFMove(function));
+ }
+
+ RunLoop& runLoop(void* context)
+ {
+ return getOrCreateWorkQueueForContext(context).runLoop();
+ }
+
+ void invalidate(void* context)
+ {
+ auto workQueue = m_workQueueMap.take(context);
+ ASSERT(workQueue);
+ if (m_workQueueMap.isEmpty()) {
+ m_sharedWorkQueue = nullptr;
+ m_threadCount = 0;
+ } else if (workQueue->hasOneRef())
+ m_threadCount--;
+ }
+
+private:
+ WorkQueuePool()
+ {
+#if PLATFORM(GTK)
+ m_threadCountLimit = 1;
+#else
+ m_threadCountLimit = std::numeric_limits<unsigned>::max();
+#endif
+ }
+
+ WorkQueue& getOrCreateWorkQueueForContext(void* context)
+ {
+ auto addResult = m_workQueueMap.add(context, nullptr);
+ if (addResult.isNewEntry) {
+ // FIXME: This is OK for now, and it works for a single-thread limit. But for configurations where more (but not unlimited)
+ // threads could be used, one option would be to use a HashSet here and disperse the contexts across the available threads.
+ if (m_threadCount >= m_threadCountLimit) {
+ ASSERT(m_sharedWorkQueue);
+ addResult.iterator->value = m_sharedWorkQueue;
+ } else {
+ addResult.iterator->value = WorkQueue::create("org.webkit.ThreadedCompositorWorkQueue");
+ if (!m_threadCount)
+ m_sharedWorkQueue = addResult.iterator->value;
+ m_threadCount++;
+ }
+ }
+
+ return *addResult.iterator->value;
+ }
+
+ HashMap<void*, RefPtr<WorkQueue>> m_workQueueMap;
+ RefPtr<WorkQueue> m_sharedWorkQueue;
+ unsigned m_threadCount { 0 };
+ unsigned m_threadCountLimit;
+};
+
+CompositingRunLoop::CompositingRunLoop(std::function<void ()>&& updateFunction)
+ : m_updateTimer(WorkQueuePool::singleton().runLoop(this), this, &CompositingRunLoop::updateTimerFired)
+ , m_updateFunction(WTFMove(updateFunction))
+{
+#if USE(GLIB_EVENT_LOOP)
+ m_updateTimer.setPriority(G_PRIORITY_HIGH_IDLE);
+#endif
+}
+
+CompositingRunLoop::~CompositingRunLoop()
+{
+ ASSERT(isMainThread());
+ // Make sure the WorkQueue is deleted after the CompositingRunLoop, because m_updateTimer has a reference
+ // of the WorkQueue run loop. Passing this is not a problem because the pointer will only be used as a
+ // HashMap key by WorkQueuePool.
+ RunLoop::main().dispatch([context = this] { WorkQueuePool::singleton().invalidate(context); });
+}
+
+void CompositingRunLoop::performTask(Function<void ()>&& function)
+{
+ ASSERT(isMainThread());
+ WorkQueuePool::singleton().dispatch(this, WTFMove(function));
+}
+
+void CompositingRunLoop::performTaskSync(Function<void ()>&& function)
+{
+ ASSERT(isMainThread());
+ LockHolder locker(m_dispatchSyncConditionMutex);
+ WorkQueuePool::singleton().dispatch(this, [this, function = WTFMove(function)] {
+ function();
+ LockHolder locker(m_dispatchSyncConditionMutex);
+ m_dispatchSyncCondition.notifyOne();
+ });
+ m_dispatchSyncCondition.wait(m_dispatchSyncConditionMutex);
+}
+
+void CompositingRunLoop::startUpdateTimer(UpdateTiming timing)
+{
+ if (m_updateTimer.isActive())
+ return;
+
+ const static double targetFPS = 60;
+ double nextUpdateTime = 0;
+ if (timing == WaitUntilNextFrame)
+ nextUpdateTime = std::max((1 / targetFPS) - (monotonicallyIncreasingTime() - m_lastUpdateTime), 0.0);
+
+ m_updateTimer.startOneShot(nextUpdateTime);
+}
+
+void CompositingRunLoop::stopUpdateTimer()
+{
+ m_updateTimer.stop();
+}
+
+void CompositingRunLoop::updateTimerFired()
+{
+ m_updateFunction();
+ m_lastUpdateTime = monotonicallyIncreasingTime();
+}
+
+} // namespace WebKit
+
+#endif // USE(COORDINATED_GRAPHICS_THREADED)
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/CompositingRunLoop.h b/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/CompositingRunLoop.h
new file mode 100644
index 000000000..52b5d7d10
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/CompositingRunLoop.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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 CompositingRunLoop_h
+#define CompositingRunLoop_h
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+
+#include <wtf/Condition.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/Function.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/RunLoop.h>
+
+namespace WebKit {
+
+class CompositingRunLoop {
+ WTF_MAKE_NONCOPYABLE(CompositingRunLoop);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ enum UpdateTiming {
+ Immediate,
+ WaitUntilNextFrame,
+ };
+
+ CompositingRunLoop(std::function<void ()>&&);
+ ~CompositingRunLoop();
+
+ void performTask(Function<void ()>&&);
+ void performTaskSync(Function<void ()>&&);
+
+ void startUpdateTimer(UpdateTiming = Immediate);
+ void stopUpdateTimer();
+
+private:
+ void updateTimerFired();
+
+ RunLoop::Timer<CompositingRunLoop> m_updateTimer;
+ std::function<void ()> m_updateFunction;
+ Lock m_dispatchSyncConditionMutex;
+ Condition m_dispatchSyncCondition;
+
+ double m_lastUpdateTime { 0 };
+};
+
+} // namespace WebKit
+
+#endif // USE(COORDINATED_GRAPHICS_THREADED)
+
+#endif // CompositingRunLoop_h
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.cpp b/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.cpp
new file mode 100644
index 000000000..54b7ef96f
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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 "ThreadSafeCoordinatedSurface.h"
+
+#include <WebCore/TextureMapperGL.h>
+#include <wtf/StdLibExtras.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+Ref<ThreadSafeCoordinatedSurface> ThreadSafeCoordinatedSurface::create(const IntSize& size, CoordinatedSurface::Flags flags)
+{
+ // Making an unconditionally unaccelerated buffer here is OK because this code
+ // isn't used by any platforms that respect the accelerated bit.
+ return adoptRef(*new ThreadSafeCoordinatedSurface(size, flags, ImageBuffer::create(size, Unaccelerated)));
+}
+
+ThreadSafeCoordinatedSurface::ThreadSafeCoordinatedSurface(const IntSize& size, CoordinatedSurface::Flags flags, std::unique_ptr<ImageBuffer> buffer)
+ : CoordinatedSurface(size, flags)
+ , m_imageBuffer(WTFMove(buffer))
+{
+}
+
+ThreadSafeCoordinatedSurface::~ThreadSafeCoordinatedSurface()
+{
+}
+
+void ThreadSafeCoordinatedSurface::paintToSurface(const IntRect& rect, CoordinatedSurface::Client& client)
+{
+ GraphicsContext& context = beginPaint(rect);
+ client.paintToSurfaceContext(context);
+ endPaint();
+}
+
+GraphicsContext& ThreadSafeCoordinatedSurface::beginPaint(const IntRect& rect)
+{
+ ASSERT(m_imageBuffer);
+ GraphicsContext& graphicsContext = m_imageBuffer->context();
+ graphicsContext.save();
+ graphicsContext.clip(rect);
+ graphicsContext.translate(rect.x(), rect.y());
+ return graphicsContext;
+}
+
+void ThreadSafeCoordinatedSurface::endPaint()
+{
+ ASSERT(m_imageBuffer);
+ m_imageBuffer->context().restore();
+}
+
+void ThreadSafeCoordinatedSurface::copyToTexture(RefPtr<BitmapTexture> texture, const IntRect& target, const IntPoint& sourceOffset)
+{
+ 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/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.h b/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.h
new file mode 100644
index 000000000..f460eaa01
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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 <WebCore/CoordinatedSurface.h>
+#include <WebCore/ImageBuffer.h>
+
+namespace WebKit {
+
+class ThreadSafeCoordinatedSurface : public WebCore::CoordinatedSurface {
+public:
+ virtual ~ThreadSafeCoordinatedSurface();
+
+ // Create a new ThreadSafeCoordinatedSurface and allocate either a GraphicsSurface or a ImageBuffer as backing.
+ static Ref<ThreadSafeCoordinatedSurface> create(const WebCore::IntSize&, WebCore::CoordinatedSurface::Flags);
+
+ void paintToSurface(const WebCore::IntRect&, WebCore::CoordinatedSurface::Client&) override;
+ void copyToTexture(RefPtr<WebCore::BitmapTexture>, const WebCore::IntRect& target, const WebCore::IntPoint& sourceOffset) override;
+
+private:
+ ThreadSafeCoordinatedSurface(const WebCore::IntSize&, WebCore::CoordinatedSurface::Flags, std::unique_ptr<WebCore::ImageBuffer>);
+
+ WebCore::GraphicsContext& beginPaint(const WebCore::IntRect&);
+ void endPaint();
+
+ std::unique_ptr<WebCore::ImageBuffer> m_imageBuffer;
+};
+
+} // namespace WebKit
+
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // ThreadSafeCoordinatedSurface_h
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp b/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp
new file mode 100644
index 000000000..c7ad837c8
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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 "ThreadedCompositor.h"
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+
+#include "CompositingRunLoop.h"
+#include <WebCore/PlatformDisplay.h>
+#include <WebCore/TransformationMatrix.h>
+
+#if USE(OPENGL_ES_2)
+#include <GLES2/gl2.h>
+#else
+#include <GL/gl.h>
+#endif
+
+using namespace WebCore;
+
+namespace WebKit {
+
+Ref<ThreadedCompositor> ThreadedCompositor::create(Client& client, const IntSize& viewportSize, float scaleFactor, uint64_t nativeSurfaceHandle, ShouldDoFrameSync doFrameSync, TextureMapper::PaintFlags paintFlags)
+{
+ return adoptRef(*new ThreadedCompositor(client, viewportSize, scaleFactor, nativeSurfaceHandle, doFrameSync, paintFlags));
+}
+
+ThreadedCompositor::ThreadedCompositor(Client& client, const IntSize& viewportSize, float scaleFactor, uint64_t nativeSurfaceHandle, ShouldDoFrameSync doFrameSync, TextureMapper::PaintFlags paintFlags)
+ : m_client(client)
+ , m_viewportSize(viewportSize)
+ , m_scaleFactor(scaleFactor)
+ , m_nativeSurfaceHandle(nativeSurfaceHandle)
+ , m_doFrameSync(doFrameSync)
+ , m_paintFlags(paintFlags)
+ , m_needsResize(!viewportSize.isEmpty())
+ , m_compositingRunLoop(std::make_unique<CompositingRunLoop>([this] { renderLayerTree(); }))
+{
+ m_compositingRunLoop->performTaskSync([this, protectedThis = makeRef(*this)] {
+ m_scene = adoptRef(new CoordinatedGraphicsScene(this));
+ if (m_nativeSurfaceHandle) {
+ createGLContext();
+ m_scene->setActive(true);
+ } else
+ m_scene->setActive(false);
+ });
+}
+
+ThreadedCompositor::~ThreadedCompositor()
+{
+}
+
+void ThreadedCompositor::createGLContext()
+{
+ ASSERT(!isMainThread());
+ ASSERT(m_nativeSurfaceHandle);
+
+ m_context = GLContext::createContextForWindow(reinterpret_cast<GLNativeWindowType>(m_nativeSurfaceHandle), &PlatformDisplay::sharedDisplayForCompositing());
+ if (!m_context)
+ return;
+
+ if (m_doFrameSync == ShouldDoFrameSync::No) {
+ if (m_context->makeContextCurrent())
+ m_context->swapInterval(0);
+ }
+}
+
+void ThreadedCompositor::invalidate()
+{
+ m_scene->detach();
+ m_compositingRunLoop->stopUpdateTimer();
+ m_compositingRunLoop->performTaskSync([this, protectedThis = makeRef(*this)] {
+ m_scene->purgeGLResources();
+ m_context = nullptr;
+ m_scene = nullptr;
+ });
+ m_compositingRunLoop = nullptr;
+}
+
+void ThreadedCompositor::setNativeSurfaceHandleForCompositing(uint64_t handle)
+{
+ m_compositingRunLoop->stopUpdateTimer();
+ m_compositingRunLoop->performTaskSync([this, protectedThis = makeRef(*this), handle] {
+ // A new native handle can't be set without destroying the previous one first if any.
+ ASSERT(!!handle ^ !!m_nativeSurfaceHandle);
+ m_nativeSurfaceHandle = handle;
+ if (m_nativeSurfaceHandle) {
+ createGLContext();
+ m_scene->setActive(true);
+ } else {
+ m_scene->setActive(false);
+ m_context = nullptr;
+ }
+ });
+}
+
+void ThreadedCompositor::setScaleFactor(float scale)
+{
+ m_compositingRunLoop->performTask([this, protectedThis = makeRef(*this), scale] {
+ m_scaleFactor = scale;
+ scheduleDisplayImmediately();
+ });
+}
+
+void ThreadedCompositor::setScrollPosition(const IntPoint& scrollPosition, float scale)
+{
+ m_compositingRunLoop->performTask([this, protectedThis = makeRef(*this), scrollPosition, scale] {
+ m_scrollPosition = scrollPosition;
+ m_scaleFactor = scale;
+ scheduleDisplayImmediately();
+ });
+}
+
+void ThreadedCompositor::setViewportSize(const IntSize& viewportSize, float scale)
+{
+ m_compositingRunLoop->performTaskSync([this, protectedThis = makeRef(*this), viewportSize, scale] {
+ m_viewportSize = viewportSize;
+ m_scaleFactor = scale;
+ m_needsResize = true;
+ scheduleDisplayImmediately();
+ });
+}
+
+void ThreadedCompositor::setDrawsBackground(bool drawsBackground)
+{
+ m_compositingRunLoop->performTask([this, protectedThis = Ref<ThreadedCompositor>(*this), drawsBackground] {
+ m_drawsBackground = drawsBackground;
+ scheduleDisplayImmediately();
+ });
+}
+
+void ThreadedCompositor::renderNextFrame()
+{
+ ASSERT(isMainThread());
+ m_client.renderNextFrame();
+}
+
+void ThreadedCompositor::commitScrollOffset(uint32_t layerID, const IntSize& offset)
+{
+ ASSERT(isMainThread());
+ m_client.commitScrollOffset(layerID, offset);
+}
+
+void ThreadedCompositor::updateViewport()
+{
+ m_compositingRunLoop->startUpdateTimer(CompositingRunLoop::WaitUntilNextFrame);
+}
+
+void ThreadedCompositor::scheduleDisplayImmediately()
+{
+ m_compositingRunLoop->startUpdateTimer(CompositingRunLoop::Immediate);
+}
+
+void ThreadedCompositor::forceRepaint()
+{
+ m_compositingRunLoop->performTaskSync([this, protectedThis = makeRef(*this)] {
+ renderLayerTree();
+ });
+}
+
+void ThreadedCompositor::renderLayerTree()
+{
+ if (!m_scene || !m_scene->isActive())
+ return;
+
+ if (!m_context || !m_context->makeContextCurrent())
+ return;
+
+ if (m_needsResize) {
+ glViewport(0, 0, m_viewportSize.width(), m_viewportSize.height());
+ m_needsResize = false;
+ }
+ FloatRect clipRect(0, 0, m_viewportSize.width(), m_viewportSize.height());
+
+ TransformationMatrix viewportTransform;
+ viewportTransform.scale(m_scaleFactor);
+ viewportTransform.translate(-m_scrollPosition.x(), -m_scrollPosition.y());
+
+ if (!m_drawsBackground) {
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ m_scene->paintToCurrentGLContext(viewportTransform, 1, clipRect, Color::transparent, !m_drawsBackground, m_scrollPosition, m_paintFlags);
+
+ m_context->swapBuffers();
+}
+
+void ThreadedCompositor::updateSceneState(const CoordinatedGraphicsState& state)
+{
+ ASSERT(isMainThread());
+ RefPtr<CoordinatedGraphicsScene> scene = m_scene;
+ m_scene->appendUpdate([scene, state] {
+ scene->commitSceneState(state);
+ });
+
+ scheduleDisplayImmediately();
+}
+
+}
+#endif // USE(COORDINATED_GRAPHICS_THREADED)
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.h b/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.h
new file mode 100644
index 000000000..bac81a396
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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 ThreadedCompositor_h
+#define ThreadedCompositor_h
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+
+#include "CompositingRunLoop.h"
+#include "CoordinatedGraphicsScene.h"
+#include <WebCore/GLContext.h>
+#include <WebCore/IntSize.h>
+#include <WebCore/TextureMapper.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/ThreadSafeRefCounted.h>
+
+namespace WebCore {
+struct CoordinatedGraphicsState;
+}
+
+namespace WebKit {
+
+class CoordinatedGraphicsScene;
+class CoordinatedGraphicsSceneClient;
+
+class ThreadedCompositor : public CoordinatedGraphicsSceneClient, public ThreadSafeRefCounted<ThreadedCompositor> {
+ WTF_MAKE_NONCOPYABLE(ThreadedCompositor);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ class Client {
+ public:
+ virtual void renderNextFrame() = 0;
+ virtual void commitScrollOffset(uint32_t layerID, const WebCore::IntSize& offset) = 0;
+ };
+
+ enum class ShouldDoFrameSync { No, Yes };
+
+ static Ref<ThreadedCompositor> create(Client&, const WebCore::IntSize&, float scaleFactor, uint64_t nativeSurfaceHandle = 0, ShouldDoFrameSync = ShouldDoFrameSync::Yes, WebCore::TextureMapper::PaintFlags = 0);
+ virtual ~ThreadedCompositor();
+
+ void setNativeSurfaceHandleForCompositing(uint64_t);
+ void setScaleFactor(float);
+ void setScrollPosition(const WebCore::IntPoint&, float scale);
+ void setViewportSize(const WebCore::IntSize&, float scale);
+ void setDrawsBackground(bool);
+
+ void updateSceneState(const WebCore::CoordinatedGraphicsState&);
+
+ void invalidate();
+
+ void forceRepaint();
+
+private:
+ ThreadedCompositor(Client&, const WebCore::IntSize&, float scaleFactor, uint64_t nativeSurfaceHandle, ShouldDoFrameSync, WebCore::TextureMapper::PaintFlags);
+
+ // CoordinatedGraphicsSceneClient
+ void renderNextFrame() override;
+ void updateViewport() override;
+ void commitScrollOffset(uint32_t layerID, const WebCore::IntSize& offset) override;
+
+ void renderLayerTree();
+ void scheduleDisplayImmediately();
+
+ void createGLContext();
+
+ Client& m_client;
+ RefPtr<CoordinatedGraphicsScene> m_scene;
+ std::unique_ptr<WebCore::GLContext> m_context;
+
+ WebCore::IntSize m_viewportSize;
+ WebCore::IntPoint m_scrollPosition;
+ float m_scaleFactor { 1 };
+ bool m_drawsBackground { true };
+ uint64_t m_nativeSurfaceHandle;
+ ShouldDoFrameSync m_doFrameSync;
+ WebCore::TextureMapper::PaintFlags m_paintFlags { 0 };
+ bool m_needsResize { false };
+
+ std::unique_ptr<CompositingRunLoop> m_compositingRunLoop;
+};
+
+} // namespace WebKit
+
+#endif
+
+#endif // ThreadedCompositor_h