2 Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
21 #include "UpdateAtlas.h"
23 #if USE(UI_SIDE_COMPOSITING)
25 #include "GraphicsContext.h"
27 #include <wtf/MathExtras.h>
28 using namespace WebCore;
32 UpdateAtlas::UpdateAtlas(int dimension, ShareableBitmap::Flags flags)
34 , m_inactivityInSeconds(0)
37 m_surface = ShareableSurface::create(IntSize(dimension, dimension), flags, ShareableSurface::SupportsGraphicsSurface);
40 static int nextPowerOfTwo(int number)
42 // This is a fast trick to get nextPowerOfTwo for an integer.
44 number |= number >> 1;
45 number |= number >> 2;
46 number |= number >> 4;
47 number |= number >> 8;
48 number |= number >> 16;
53 void UpdateAtlas::buildLayoutIfNeeded()
55 if (!m_layout.isEmpty())
58 static const int MinTileSize = 32;
59 static const int MaxTileSize = 512;
61 // Divide our square to square power-of-two boxes.
62 for (int cursor = 0; cursor < size().width(); ) {
63 int remainder = size().width() - cursor;
64 int dimension = std::min(remainder, std::min(MaxTileSize, std::max(MinTileSize, nextPowerOfTwo(remainder / 2))));
66 m_layout.append(dimension);
69 m_bufferStates.resize(m_layout.size() * m_layout.size());
70 size_t size = m_bufferStates.size();
71 for (size_t i = 0; i < size; ++i)
72 m_bufferStates[i] = Available;
75 int UpdateAtlas::findAvailableIndex(const WebCore::IntSize& size)
77 int dimension = m_layout.size();
78 int stride = dimension;
79 int requiredDimension = std::max(size.width(), size.height());
81 // Begin from the smallest buffer, until we reach the smallest available buffer that's big enough to contain our rect.
82 for (int i = m_bufferStates.size() - 1; i >= 0; i -= (dimension + 1), --stride) {
83 // Need a bigger buffer.
84 if (m_layout[i / dimension] < requiredDimension)
87 // Check all buffers of current size, to find an available one.
88 for (int offset = 0; offset < stride; ++offset) {
89 int index = i - offset;
90 if (m_bufferStates[index] == Available)
98 void UpdateAtlas::didSwapBuffers()
100 buildLayoutIfNeeded();
101 size_t size = m_bufferStates.size();
102 for (size_t i = 0; i < size; ++i)
103 m_bufferStates[i] = Available;
107 PassOwnPtr<GraphicsContext> UpdateAtlas::beginPaintingOnAvailableBuffer(ShareableSurface::Handle& handle, const WebCore::IntSize& size, IntPoint& offset)
109 m_inactivityInSeconds = 0;
111 buildLayoutIfNeeded();
112 int index = findAvailableIndex(size);
114 // No available buffer was found, returning null.
116 return PassOwnPtr<GraphicsContext>();
118 if (!m_surface->createHandle(handle))
119 return PassOwnPtr<WebCore::GraphicsContext>();
121 // FIXME: Use tri-state buffers, to allow faster updates.
122 m_bufferStates[index] = Taken;
123 offset = offsetForIndex(index);
124 IntRect rect(IntPoint::zero(), size);
125 OwnPtr<GraphicsContext> graphicsContext = m_surface->createGraphicsContext(IntRect(offset, size));
127 if (flags() & ShareableBitmap::SupportsAlpha) {
128 graphicsContext->setCompositeOperation(CompositeCopy);
129 #if !ENABLE(TIZEN_WEBKIT2_TILED_AC)
130 graphicsContext->fillRect(rect, Color::transparent, ColorSpaceDeviceRGB);
132 graphicsContext->clearRect(rect);
134 graphicsContext->setCompositeOperation(CompositeSourceOver);
137 return graphicsContext.release();
140 IntPoint UpdateAtlas::offsetForIndex(int index) const
142 IntPoint coord(index % m_layout.size(), index / m_layout.size());
145 for (int i = 0; i < coord.x(); ++i)
147 for (int i = 0; i < coord.y(); ++i)
150 return IntPoint(x, y);