diff options
Diffstat (limited to 'Source/WebKit2/WebProcess/WebPage/UpdateAtlas.cpp')
| -rw-r--r-- | Source/WebKit2/WebProcess/WebPage/UpdateAtlas.cpp | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/Source/WebKit2/WebProcess/WebPage/UpdateAtlas.cpp b/Source/WebKit2/WebProcess/WebPage/UpdateAtlas.cpp new file mode 100644 index 000000000..9383bc52d --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/UpdateAtlas.cpp @@ -0,0 +1,140 @@ +/* + 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 "UpdateAtlas.h" + +#if USE(UI_SIDE_COMPOSITING) + +#include "GraphicsContext.h" +#include "IntRect.h" +#include "MathExtras.h" +using namespace WebCore; + +namespace WebKit { + +UpdateAtlas::UpdateAtlas(int dimension, ShareableBitmap::Flags flags) + : m_flags(flags) +{ + m_surface = ShareableSurface::create(IntSize(dimension, dimension), 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); + } + + 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() +{ + buildLayoutIfNeeded(); + for (int i = 0; i < m_bufferStates.size(); ++i) + m_bufferStates[i] = Available; +} + +PassOwnPtr<GraphicsContext> UpdateAtlas::beginPaintingOnAvailableBuffer(const WebCore::IntSize& size, IntPoint& offset) +{ + buildLayoutIfNeeded(); + int index = findAvailableIndex(size); + + // No available buffer was found, returning null. + if (index < 0) + return PassOwnPtr<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)); + + if (flags() & ShareableBitmap::SupportsAlpha) { + graphicsContext->setCompositeOperation(CompositeCopy); + graphicsContext->fillRect(rect, 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 |
