Diff
Modified: trunk/Source/WebKit2/CMakeLists.txt (125539 => 125540)
--- trunk/Source/WebKit2/CMakeLists.txt 2012-08-14 11:14:55 UTC (rev 125539)
+++ trunk/Source/WebKit2/CMakeLists.txt 2012-08-14 11:22:06 UTC (rev 125540)
@@ -464,6 +464,7 @@
WebProcess/WebPage/EventDispatcher.cpp
WebProcess/WebPage/FindController.cpp
+ WebProcess/WebPage/AreaAllocator.cpp
WebProcess/WebPage/LayerTreeHost.cpp
WebProcess/WebPage/PageOverlay.cpp
WebProcess/WebPage/TapHighlightController.cpp
Modified: trunk/Source/WebKit2/ChangeLog (125539 => 125540)
--- trunk/Source/WebKit2/ChangeLog 2012-08-14 11:14:55 UTC (rev 125539)
+++ trunk/Source/WebKit2/ChangeLog 2012-08-14 11:22:06 UTC (rev 125540)
@@ -1,3 +1,57 @@
+2012-08-14 Allan Sandfeld Jensen <[email protected]>
+
+ [Qt] UpdateAtlas is wasting memory
+ https://bugs.webkit.org/show_bug.cgi?id=93606
+
+ Reviewed by Jocelyn Turcotte.
+
+ Imported and QAreaAllocator from Qt3D and ported it to WebCore style,
+ and use this new area allocator to replace old one from UpdateAtlas.
+
+ * CMakeLists.txt:
+ * Target.pri:
+ * WebProcess/WebPage/AreaAllocator.cpp: Added.
+ (WebKit::AreaAllocator::AreaAllocator):
+ (WebKit::AreaAllocator::~AreaAllocator):
+ (WebKit::AreaAllocator::expand):
+ (WebKit::AreaAllocator::expandBy):
+ (WebKit::AreaAllocator::release):
+ (WebKit::AreaAllocator::overhead):
+ (WebKit::AreaAllocator::roundAllocation):
+ (WebKit::GeneralAreaAllocator::GeneralAreaAllocator):
+ (WebKit::GeneralAreaAllocator::~GeneralAreaAllocator):
+ (WebKit::GeneralAreaAllocator::freeNode):
+ (WebKit::GeneralAreaAllocator::expand):
+ (WebKit::fitsWithin):
+ (WebKit::GeneralAreaAllocator::allocate):
+ (WebKit::GeneralAreaAllocator::allocateFromNode):
+ (WebKit::GeneralAreaAllocator::splitNode):
+ (WebKit::GeneralAreaAllocator::updateLargestFree):
+ (WebKit::GeneralAreaAllocator::release):
+ (WebKit::GeneralAreaAllocator::overhead):
+ * WebProcess/WebPage/AreaAllocator.h: Added.
+ (WebCore::nextPowerOfTwo):
+ (AreaAllocator):
+ (WebKit::AreaAllocator::size):
+ (WebKit::AreaAllocator::minimumAllocation):
+ (WebKit::AreaAllocator::setMinimumAllocation):
+ (WebKit::AreaAllocator::margin):
+ (WebKit::AreaAllocator::setMargin):
+ (GeneralAreaAllocator):
+ (Node):
+ * WebProcess/WebPage/CoordinatedGraphics/LayerTreeCoordinator.cpp:
+ (WebKit::LayerTreeCoordinator::renderNextFrame):
+ (WebKit::LayerTreeCoordinator::beginContentUpdate):
+ * WebProcess/WebPage/CoordinatedGraphics/LayerTreeCoordinator.h:
+ (LayerTreeCoordinator):
+ * WebProcess/WebPage/UpdateAtlas.cpp:
+ (WebKit::UpdateAtlas::UpdateAtlas):
+ (WebKit::UpdateAtlas::buildLayoutIfNeeded):
+ (WebKit::UpdateAtlas::didSwapBuffers):
+ (WebKit::UpdateAtlas::beginPaintingOnAvailableBuffer):
+ * WebProcess/WebPage/UpdateAtlas.h:
+ (UpdateAtlas):
+
2012-08-14 Sergio Villar Senin <[email protected]>
[GTK] REGRESSION (r122428) WebKit2APITests/TestWebKitFindController fails "next" test
Modified: trunk/Source/WebKit2/Target.pri (125539 => 125540)
--- trunk/Source/WebKit2/Target.pri 2012-08-14 11:14:55 UTC (rev 125539)
+++ trunk/Source/WebKit2/Target.pri 2012-08-14 11:22:06 UTC (rev 125540)
@@ -341,6 +341,7 @@
WebProcess/WebCoreSupport/WebSearchPopupMenu.h \
WebProcess/WebCoreSupport/WebVibrationClient.h \
WebProcess/WebCoreSupport/qt/WebFrameNetworkingContext.h \
+ WebProcess/WebPage/AreaAllocator.h \
WebProcess/WebPage/DrawingArea.h \
WebProcess/WebPage/DrawingAreaImpl.h \
WebProcess/WebPage/EventDispatcher.h \
@@ -702,6 +703,7 @@
WebProcess/WebCoreSupport/qt/WebDragClientQt.cpp \
WebProcess/WebCoreSupport/qt/WebFrameNetworkingContext.cpp \
WebProcess/WebCoreSupport/qt/WebPopupMenuQt.cpp \
+ WebProcess/WebPage/AreaAllocator.cpp \
WebProcess/WebPage/DecoderAdapter.cpp \
WebProcess/WebPage/DrawingArea.cpp \
WebProcess/WebPage/DrawingAreaImpl.cpp \
Added: trunk/Source/WebKit2/WebProcess/WebPage/AreaAllocator.cpp (0 => 125540)
--- trunk/Source/WebKit2/WebProcess/WebPage/AreaAllocator.cpp (rev 0)
+++ trunk/Source/WebKit2/WebProcess/WebPage/AreaAllocator.cpp 2012-08-14 11:22:06 UTC (rev 125540)
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+
+#include "AreaAllocator.h"
+
+namespace WebKit {
+
+AreaAllocator::AreaAllocator(const WebCore::IntSize& size)
+ : m_size(size)
+ , m_minAlloc(1, 1)
+ , m_margin(0, 0)
+{
+}
+
+AreaAllocator::~AreaAllocator()
+{
+}
+
+void AreaAllocator::expand(const WebCore::IntSize& size)
+{
+ m_size = m_size.expandedTo(size);
+}
+
+void AreaAllocator::expandBy(const WebCore::IntSize& size)
+{
+ m_size += size;
+}
+
+void AreaAllocator::release(const WebCore::IntRect&)
+{
+}
+
+int AreaAllocator::overhead() const
+{
+ return 0;
+}
+
+WebCore::IntSize AreaAllocator::roundAllocation(const WebCore::IntSize& size) const
+{
+ int width = size.width() + m_margin.width();
+ int height = size.height() + m_margin.height();
+ int extra = width % m_minAlloc.width();
+ if (extra)
+ width += m_minAlloc.width() - extra;
+ extra = height % m_minAlloc.height();
+ if (extra)
+ height += m_minAlloc.height() - extra;
+
+ return WebCore::IntSize(width, height);
+}
+
+GeneralAreaAllocator::GeneralAreaAllocator(const WebCore::IntSize& size)
+ : AreaAllocator(WebCore::nextPowerOfTwo(size))
+{
+ m_root = new Node();
+ m_root->rect = WebCore::IntRect(0, 0, m_size.width(), m_size.height());
+ m_root->largestFree = m_size;
+ m_root->parent = 0;
+ m_root->left = 0;
+ m_root->right = 0;
+ m_nodeCount = 1;
+ setMinimumAllocation(WebCore::IntSize(8, 8));
+}
+
+GeneralAreaAllocator::~GeneralAreaAllocator()
+{
+ freeNode(m_root);
+}
+
+void GeneralAreaAllocator::freeNode(Node* node)
+{
+ if (node) {
+ freeNode(node->left);
+ freeNode(node->right);
+ }
+ delete node;
+}
+
+void GeneralAreaAllocator::expand(const WebCore::IntSize& size)
+{
+ AreaAllocator::expand(WebCore::nextPowerOfTwo(size));
+
+ if (m_root->rect.size() == m_size)
+ return; // No change.
+
+ if (!m_root->left && m_root->largestFree.width() > 0) {
+ // No allocations have occurred, so just adjust the root size.
+ m_root->rect = WebCore::IntRect(0, 0, m_size.width(), m_size.height());
+ m_root->largestFree = m_size;
+ return;
+ }
+
+ // Add extra nodes above the current root to expand the tree.
+ Node* oldRoot = m_root;
+ Split split;
+ if (m_size.width() >= m_size.height())
+ split = SplitOnX;
+ else
+ split = SplitOnY;
+
+ while (m_root->rect.size() != m_size) {
+ if (m_root->rect.width() == m_size.width())
+ split = SplitOnY;
+ else if (m_root->rect.height() == m_size.height())
+ split = SplitOnX;
+ Node* parent = new Node();
+ Node* right = new Node();
+ m_nodeCount += 2;
+ m_root->parent = parent;
+ parent->parent = 0;
+ parent->left = m_root;
+ parent->right = right;
+ parent->largestFree = m_root->rect.size();
+ right->parent = parent;
+ right->left = 0;
+ right->right = 0;
+ right->largestFree = m_root->rect.size();
+ if (split == SplitOnX) {
+ parent->rect = WebCore::IntRect(m_root->rect.x(), m_root->rect.y(),
+ m_root->rect.width() * 2, m_root->rect.height());
+ right->rect = WebCore::IntRect(m_root->rect.x() + m_root->rect.width(), m_root->rect.y(),
+ m_root->rect.width(), m_root->rect.height());
+ } else {
+ parent->rect = WebCore::IntRect(m_root->rect.x(), m_root->rect.y(),
+ m_root->rect.width(), m_root->rect.height() * 2);
+ right->rect = WebCore::IntRect(m_root->rect.x(), m_root->rect.y() + m_root->rect.width(),
+ m_root->rect.width(), m_root->rect.height());
+ }
+ split = (split == SplitOnX ? SplitOnY : SplitOnX);
+ m_root = parent;
+ }
+ updateLargestFree(oldRoot);
+}
+
+static inline bool fitsWithin(const WebCore::IntSize& size1, const WebCore::IntSize& size2)
+{
+ return size1.width() <= size2.width() && size1.height() <= size2.height();
+}
+
+WebCore::IntRect GeneralAreaAllocator::allocate(const WebCore::IntSize& size)
+{
+ WebCore::IntSize rounded = roundAllocation(size);
+ rounded = WebCore::nextPowerOfTwo(rounded);
+ if (rounded.width() <= 0 || rounded.width() > m_size.width()
+ || rounded.height() <= 0 || rounded.height() > m_size.height())
+ return WebCore::IntRect();
+
+ WebCore::IntPoint point = allocateFromNode(rounded, m_root);
+ if (point.x() >= 0)
+ return WebCore::IntRect(point, size);
+ return WebCore::IntRect();
+}
+
+WebCore::IntPoint GeneralAreaAllocator::allocateFromNode(const WebCore::IntSize& size, Node* node)
+{
+ // Find the best node to insert into, which should be
+ // a node with the least amount of unused space that is
+ // big enough to contain the requested size.
+ while (node) {
+ // Go down a level and determine if the left or right
+ // sub-tree contains the best chance of allocation.
+ Node* left = node->left;
+ Node* right = node->right;
+ if (left && fitsWithin(size, left->largestFree)) {
+ if (right && fitsWithin(size, right->largestFree)) {
+ if (left->largestFree.width() < right->largestFree.width()
+ || left->largestFree.height() < right->largestFree.height()) {
+ // The largestFree values may be a little oversized,
+ // so try the left sub-tree and then the right sub-tree.
+ WebCore::IntPoint point = allocateFromNode(size, left);
+ if (point.x() >= 0)
+ return point;
+ return allocateFromNode(size, right);
+ }
+ node = right;
+ } else
+ node = left;
+ } else if (right && fitsWithin(size, right->largestFree))
+ node = right;
+ else if (left || right) {
+ // Neither sub-node has enough space to allocate from.
+ return WebCore::IntPoint(-1, -1);
+ } else if (fitsWithin(size, node->largestFree)) {
+ // Do we need to split this node into smaller pieces?
+ Split split;
+ if (fitsWithin(WebCore::IntSize(size.width() * 2, size.height() * 2), node->largestFree)) {
+ // Split in either direction: choose the inverse of
+ // the parent node's split direction to try to balance
+ // out the wasted space as further subdivisions happen.
+ if (node->parent
+ && node->parent->left->rect.x() == node->parent->right->rect.x())
+ split = SplitOnX;
+ else if (node->parent)
+ split = SplitOnY;
+ else if (node->rect.width() >= node->rect.height())
+ split = SplitOnX;
+ else
+ split = SplitOnY;
+ } else if (fitsWithin(WebCore::IntSize(size.width() * 2, size.height()), node->largestFree)) {
+ // Split along the X direction.
+ split = SplitOnX;
+ } else if (fitsWithin(WebCore::IntSize(size.width(), size.height() * 2), node->largestFree)) {
+ // Split along the Y direction.
+ split = SplitOnY;
+ } else {
+ // Cannot split further - allocate this node.
+ node->largestFree = WebCore::IntSize(0, 0);
+ updateLargestFree(node);
+ return node->rect.location();
+ }
+
+ // Split the node, then go around again using the left sub-tree.
+ node = splitNode(node, split);
+ } else {
+ // Cannot possibly fit into this node.
+ break;
+ }
+ }
+ return WebCore::IntPoint(-1, -1);
+}
+
+GeneralAreaAllocator::Node* GeneralAreaAllocator::splitNode
+ (Node* node, Split split)
+{
+ Node* left = new Node();
+ Node* right = new Node();
+ m_nodeCount += 2;
+ left->parent = node;
+ left->left = 0;
+ left->right = 0;
+ right->parent = node;
+ right->left = 0;
+ right->right = 0;
+ node->left = left;
+ node->right = right;
+
+ if (split == SplitOnX) {
+ left->rect = WebCore::IntRect(node->rect.x(), node->rect.y(),
+ node->rect.width() / 2, node->rect.height());
+ right->rect = WebCore::IntRect(left->rect.maxX(), node->rect.y(),
+ node->rect.width() / 2, node->rect.height());
+ } else {
+ left->rect = WebCore::IntRect(node->rect.x(), node->rect.y(),
+ node->rect.width(), node->rect.height() / 2);
+ right->rect = WebCore::IntRect(node->rect.x(), left->rect.maxY(),
+ node->rect.width(), node->rect.height() / 2);
+ }
+
+ left->largestFree = left->rect.size();
+ right->largestFree = right->rect.size();
+ node->largestFree = right->largestFree;
+ return left;
+}
+
+void GeneralAreaAllocator::updateLargestFree(Node* node)
+{
+ while ((node = node->parent)) {
+ node->largestFree = WebCore::IntSize(
+ std::max(node->left->largestFree.width(), node->right->largestFree.width()),
+ std::max(node->left->largestFree.height(), node->right->largestFree.height())
+ );
+ }
+}
+
+void GeneralAreaAllocator::release(const WebCore::IntRect& rect)
+{
+ // Locate the node that contains the allocated region.
+ Node* node = m_root;
+ WebCore::IntPoint point = rect.location();
+ while (node) {
+ if (node->left && node->left->rect.contains(point))
+ node = node->left;
+ else if (node->right && node->right->rect.contains(point))
+ node = node->right;
+ else if (node->rect.contains(point))
+ break;
+ else
+ return; // Point is completely outside the tree.
+ }
+ if (!node)
+ return;
+
+ // Mark the node as free and then work upwards through the tree
+ // recombining and deleting nodes until we reach a sibling
+ // that is still allocated.
+ node->largestFree = node->rect.size();
+ while (node->parent) {
+ if (node->parent->left == node) {
+ if (node->parent->right->largestFree != node->parent->right->rect.size())
+ break;
+ } else {
+ if (node->parent->left->largestFree != node->parent->left->rect.size())
+ break;
+ }
+ node = node->parent;
+ freeNode(node->left);
+ freeNode(node->right);
+ m_nodeCount -= 2;
+ node->left = 0;
+ node->right = 0;
+ node->largestFree = node->rect.size();
+ }
+
+ // Make the rest of our ancestors have the correct "largest free size".
+ updateLargestFree(node);
+}
+
+int GeneralAreaAllocator::overhead() const
+{
+ return m_nodeCount * sizeof(Node);
+}
+
+} // namespace
Added: trunk/Source/WebKit2/WebProcess/WebPage/AreaAllocator.h (0 => 125540)
--- trunk/Source/WebKit2/WebProcess/WebPage/AreaAllocator.h (rev 0)
+++ trunk/Source/WebKit2/WebProcess/WebPage/AreaAllocator.h 2012-08-14 11:22:06 UTC (rev 125540)
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef AreaAllocator_h
+#define AreaAllocator_h
+
+#include <IntPoint.h>
+#include <IntRect.h>
+#include <IntSize.h>
+
+namespace WebCore {
+inline int nextPowerOfTwo(int number)
+{
+ // This is a fast trick to get nextPowerOfTwo for an integer.
+ --number;
+ number |= number >> 1;
+ number |= number >> 2;
+ number |= number >> 4;
+ number |= number >> 8;
+ number |= number >> 16;
+ number++;
+ return number;
+}
+
+inline IntSize nextPowerOfTwo(const IntSize& size)
+{
+ return IntSize(nextPowerOfTwo(size.width()), nextPowerOfTwo(size.height()));
+}
+} // namespace WebCore
+
+namespace WebKit {
+
+class AreaAllocator {
+public:
+ AreaAllocator(const WebCore::IntSize&);
+ virtual ~AreaAllocator();
+
+ WebCore::IntSize size() const { return m_size; }
+
+ WebCore::IntSize minimumAllocation() const { return m_minAlloc; }
+ void setMinimumAllocation(const WebCore::IntSize& size) { m_minAlloc = size; }
+
+ WebCore::IntSize margin() const { return m_margin; }
+ void setMargin(const WebCore::IntSize &margin) { m_margin = margin; }
+
+ virtual void expand(const WebCore::IntSize&);
+ void expandBy(const WebCore::IntSize&);
+
+ virtual WebCore::IntRect allocate(const WebCore::IntSize&) = 0;
+ virtual void release(const WebCore::IntRect&);
+
+ virtual int overhead() const;
+
+protected:
+ WebCore::IntSize m_size;
+ WebCore::IntSize m_minAlloc;
+ WebCore::IntSize m_margin;
+
+ WebCore::IntSize roundAllocation(const WebCore::IntSize&) const;
+};
+
+class GeneralAreaAllocator : public AreaAllocator {
+public:
+ GeneralAreaAllocator(const WebCore::IntSize&);
+ virtual ~GeneralAreaAllocator();
+
+ void expand(const WebCore::IntSize&);
+ WebCore::IntRect allocate(const WebCore::IntSize&);
+ void release(const WebCore::IntRect&);
+ int overhead() const;
+
+private:
+ enum Split { SplitOnX, SplitOnY };
+
+ struct Node {
+ WebCore::IntRect rect;
+ WebCore::IntSize largestFree;
+ Node* parent;
+ Node* left;
+ Node* right;
+ };
+
+ Node* m_root;
+ int m_nodeCount;
+
+ static void freeNode(Node*);
+ WebCore::IntPoint allocateFromNode(const WebCore::IntSize&, Node*);
+ Node* splitNode(Node*, Split);
+ static void updateLargestFree(Node*);
+};
+
+} // namespace WebKit
+
+#endif
Modified: trunk/Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/LayerTreeCoordinator.cpp (125539 => 125540)
--- trunk/Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/LayerTreeCoordinator.cpp 2012-08-14 11:14:55 UTC (rev 125539)
+++ trunk/Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/LayerTreeCoordinator.cpp 2012-08-14 11:22:06 UTC (rev 125540)
@@ -601,7 +601,7 @@
m_waitingForUIProcess = false;
scheduleLayerFlush();
for (int i = 0; i < m_updateAtlases.size(); ++i)
- m_updateAtlases[i].didSwapBuffers();
+ m_updateAtlases[i]->didSwapBuffers();
}
bool LayerTreeCoordinator::layerTreeTileUpdatesAllowed() const
@@ -623,18 +623,18 @@
{
OwnPtr<WebCore::GraphicsContext> graphicsContext;
for (int i = 0; i < m_updateAtlases.size(); ++i) {
- UpdateAtlas& atlas = m_updateAtlases[i];
- if (atlas.flags() == flags) {
+ UpdateAtlas* atlas = m_updateAtlases[i].get();
+ if (atlas->flags() == flags) {
// This will return null if there is no available buffer space.
- graphicsContext = atlas.beginPaintingOnAvailableBuffer(handle, size, offset);
+ graphicsContext = atlas->beginPaintingOnAvailableBuffer(handle, size, offset);
if (graphicsContext)
return graphicsContext.release();
}
}
- static const int ScratchBufferDimension = 2000;
- m_updateAtlases.append(UpdateAtlas(ScratchBufferDimension, flags));
- return m_updateAtlases.last().beginPaintingOnAvailableBuffer(handle, size, offset);
+ static const int ScratchBufferDimension = 1024; // Should be a power of two.
+ m_updateAtlases.append(adoptPtr(new UpdateAtlas(ScratchBufferDimension, flags)));
+ return m_updateAtlases.last()->beginPaintingOnAvailableBuffer(handle, size, offset);
}
} // namespace WebKit
Modified: trunk/Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/LayerTreeCoordinator.h (125539 => 125540)
--- trunk/Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/LayerTreeCoordinator.h 2012-08-14 11:14:55 UTC (rev 125539)
+++ trunk/Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/LayerTreeCoordinator.h 2012-08-14 11:22:06 UTC (rev 125540)
@@ -123,7 +123,7 @@
HashSet<WebCore::CoordinatedGraphicsLayer*> m_registeredLayers;
HashMap<int64_t, int> m_directlyCompositedImageRefCounts;
- Vector<UpdateAtlas> m_updateAtlases;
+ Vector<OwnPtr<UpdateAtlas> > m_updateAtlases;
bool m_notifyAfterScheduledLayerFlush;
bool m_isValid;
Modified: trunk/Source/WebKit2/WebProcess/WebPage/UpdateAtlas.cpp (125539 => 125540)
--- trunk/Source/WebKit2/WebProcess/WebPage/UpdateAtlas.cpp 2012-08-14 11:14:55 UTC (rev 125539)
+++ trunk/Source/WebKit2/WebProcess/WebPage/UpdateAtlas.cpp 2012-08-14 11:22:06 UTC (rev 125540)
@@ -25,6 +25,7 @@
#include "GraphicsContext.h"
#include "IntRect.h"
#include <wtf/MathExtras.h>
+
using namespace WebCore;
namespace WebKit {
@@ -32,112 +33,48 @@
UpdateAtlas::UpdateAtlas(int dimension, ShareableBitmap::Flags flags)
: m_flags(flags)
{
- m_surface = ShareableSurface::create(IntSize(dimension, dimension), flags, ShareableSurface::SupportsGraphicsSurface);
+ IntSize size = nextPowerOfTwo(IntSize(dimension, dimension));
+ m_surface = ShareableSurface::create(size, flags, ShareableSurface::SupportsGraphicsSurface);
}
-static int nextPowerOfTwo(int number)
-{
- // This is a fast trick to get nextPowerOfTwo for an integer.
- --number;
- number |= number >> 1;
- number |= number >> 2;
- number |= number >> 4;
- number |= number >> 8;
- number |= number >> 16;
- number++;
- return number;
-}
-
void UpdateAtlas::buildLayoutIfNeeded()
{
- if (!m_layout.isEmpty())
- return;
-
- static const int MinTileSize = 32;
- static const int MaxTileSize = 512;
-
- // Divide our square to square power-of-two boxes.
- for (int cursor = 0; cursor < size().width(); ) {
- int remainder = size().width() - cursor;
- int dimension = std::min(remainder, std::min(MaxTileSize, std::max(MinTileSize, nextPowerOfTwo(remainder / 2))));
- cursor += dimension;
- m_layout.append(dimension);
+ if (!m_areaAllocator) {
+ m_areaAllocator = adoptPtr(new GeneralAreaAllocator(size()));
+ m_areaAllocator->setMinimumAllocation(IntSize(32, 32));
}
-
- m_bufferStates.resize(m_layout.size() * m_layout.size());
- for (int i = 0; i < m_bufferStates.size(); ++i)
- m_bufferStates[i] = Available;
}
-int UpdateAtlas::findAvailableIndex(const WebCore::IntSize& size)
-{
- int dimension = m_layout.size();
- int stride = dimension;
- int requiredDimension = std::max(size.width(), size.height());
-
- // Begin from the smallest buffer, until we reach the smallest available buffer that's big enough to contain our rect.
- for (int i = m_bufferStates.size() - 1; i >= 0; i -= (dimension + 1), --stride) {
- // Need a bigger buffer.
- if (m_layout[i / dimension] < requiredDimension)
- continue;
-
- // Check all buffers of current size, to find an available one.
- for (int offset = 0; offset < stride; ++offset) {
- int index = i - offset;
- if (m_bufferStates[index] == Available)
- return index;
- }
- }
-
- return -1;
-}
-
void UpdateAtlas::didSwapBuffers()
{
+ m_areaAllocator.clear();
buildLayoutIfNeeded();
- for (int i = 0; i < m_bufferStates.size(); ++i)
- m_bufferStates[i] = Available;
}
PassOwnPtr<GraphicsContext> UpdateAtlas::beginPaintingOnAvailableBuffer(ShareableSurface::Handle& handle, const WebCore::IntSize& size, IntPoint& offset)
{
buildLayoutIfNeeded();
- int index = findAvailableIndex(size);
+ IntRect rect = m_areaAllocator->allocate(size);
// No available buffer was found, returning null.
- if (index < 0)
+ if (rect.isEmpty())
return PassOwnPtr<GraphicsContext>();
if (!m_surface->createHandle(handle))
return PassOwnPtr<WebCore::GraphicsContext>();
// FIXME: Use tri-state buffers, to allow faster updates.
- m_bufferStates[index] = Taken;
- offset = offsetForIndex(index);
- IntRect rect(IntPoint::zero(), size);
- OwnPtr<GraphicsContext> graphicsContext = m_surface->createGraphicsContext(IntRect(offset, size));
+ offset = rect.location();
+ OwnPtr<GraphicsContext> graphicsContext = m_surface->createGraphicsContext(rect);
if (flags() & ShareableBitmap::SupportsAlpha) {
graphicsContext->setCompositeOperation(CompositeCopy);
- graphicsContext->fillRect(rect, Color::transparent, ColorSpaceDeviceRGB);
+ graphicsContext->fillRect(IntRect(IntPoint::zero(), size), Color::transparent, ColorSpaceDeviceRGB);
graphicsContext->setCompositeOperation(CompositeSourceOver);
}
return graphicsContext.release();
}
-IntPoint UpdateAtlas::offsetForIndex(int index) const
-{
- IntPoint coord(index % m_layout.size(), index / m_layout.size());
- int x = 0;
- int y = 0;
- for (int i = 0; i < coord.x(); ++i)
- x += m_layout[i];
- for (int i = 0; i < coord.y(); ++i)
- y += m_layout[i];
-
- return IntPoint(x, y);
}
-
-}
#endif
Modified: trunk/Source/WebKit2/WebProcess/WebPage/UpdateAtlas.h (125539 => 125540)
--- trunk/Source/WebKit2/WebProcess/WebPage/UpdateAtlas.h 2012-08-14 11:14:55 UTC (rev 125539)
+++ trunk/Source/WebKit2/WebProcess/WebPage/UpdateAtlas.h 2012-08-14 11:22:06 UTC (rev 125540)
@@ -20,17 +20,20 @@
#ifndef UpdateAtlas_h
#define UpdateAtlas_h
+#include "AreaAllocator.h"
+#include "IntSize.h"
#include "ShareableSurface.h"
#if USE(COORDINATED_GRAPHICS)
namespace WebCore {
class GraphicsContext;
-class IntRect;
+class IntPoint;
}
namespace WebKit {
class UpdateAtlas {
+ WTF_MAKE_NONCOPYABLE(UpdateAtlas);
public:
UpdateAtlas(int dimension, ShareableBitmap::Flags);
@@ -43,17 +46,9 @@
private:
void buildLayoutIfNeeded();
- WebCore::IntPoint offsetForIndex(int) const;
- int findAvailableIndex(const WebCore::IntSize&);
private:
- enum State {
- Available,
- Taken
- };
-
- Vector<State> m_bufferStates;
- Vector<int> m_layout;
+ OwnPtr<GeneralAreaAllocator> m_areaAllocator;
ShareableBitmap::Flags m_flags;
RefPtr<ShareableSurface> m_surface;
};