1/*
2 Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
3 Copyright (C) 2012 Company 100, Inc.
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB.  If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20
21#include "config.h"
22#include "UpdateAtlas.h"
23
24#if USE(COORDINATED_GRAPHICS)
25
26#include "CoordinatedGraphicsState.h"
27#include "GraphicsContext.h"
28#include "IntRect.h"
29#include <wtf/MathExtras.h>
30
31namespace WebCore {
32
33class UpdateAtlasSurfaceClient : public CoordinatedSurface::Client {
34public:
35    UpdateAtlasSurfaceClient(CoordinatedSurface::Client* client, const IntSize& size, bool supportsAlpha)
36        : m_client(client)
37        , m_size(size)
38        , m_supportsAlpha(supportsAlpha)
39    {
40    }
41
42    virtual void paintToSurfaceContext(GraphicsContext* context) override
43    {
44        if (m_supportsAlpha) {
45            context->setCompositeOperation(CompositeCopy);
46            context->fillRect(IntRect(IntPoint::zero(), m_size), Color::transparent, ColorSpaceDeviceRGB);
47            context->setCompositeOperation(CompositeSourceOver);
48        }
49
50        m_client->paintToSurfaceContext(context);
51    }
52
53private:
54    CoordinatedSurface::Client* m_client;
55    IntSize m_size;
56    bool m_supportsAlpha;
57};
58
59UpdateAtlas::UpdateAtlas(Client* client, int dimension, CoordinatedSurface::Flags flags)
60    : m_client(client)
61    , m_inactivityInSeconds(0)
62{
63    static uint32_t nextID = 0;
64    m_ID = ++nextID;
65    IntSize size = nextPowerOfTwo(IntSize(dimension, dimension));
66    m_surface = CoordinatedSurface::create(size, flags);
67
68    m_client->createUpdateAtlas(m_ID, m_surface);
69}
70
71UpdateAtlas::~UpdateAtlas()
72{
73    if (m_surface)
74        m_client->removeUpdateAtlas(m_ID);
75}
76
77void UpdateAtlas::buildLayoutIfNeeded()
78{
79    if (!m_areaAllocator) {
80        m_areaAllocator = std::make_unique<GeneralAreaAllocator>(size());
81        m_areaAllocator->setMinimumAllocation(IntSize(32, 32));
82    }
83}
84
85void UpdateAtlas::didSwapBuffers()
86{
87    m_areaAllocator = nullptr;
88}
89
90
91bool UpdateAtlas::paintOnAvailableBuffer(const IntSize& size, uint32_t& atlasID, IntPoint& offset, CoordinatedSurface::Client* client)
92{
93    m_inactivityInSeconds = 0;
94    buildLayoutIfNeeded();
95    IntRect rect = m_areaAllocator->allocate(size);
96
97    // No available buffer was found.
98    if (rect.isEmpty())
99        return false;
100
101    if (!m_surface)
102        return false;
103
104    atlasID = m_ID;
105
106    // FIXME: Use tri-state buffers, to allow faster updates.
107    offset = rect.location();
108
109    UpdateAtlasSurfaceClient surfaceClient(client, size, supportsAlpha());
110    m_surface->paintToSurface(rect, &surfaceClient);
111
112    return true;
113}
114
115} // namespace WebCore
116#endif // USE(COORDINATED_GRAPHICS)
117