4928608003610fbcbc63368554c6394a4877071d
[WebKit-https.git] / Source / WebCore / platform / graphics / texmap / TextureMapper.cpp
1 /*
2  Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
3
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.
8
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.
13
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.
18  */
19
20 #include "config.h"
21 #include "TextureMapper.h"
22
23 #include "FilterOperations.h"
24 #include "GraphicsLayer.h"
25 #include "TextureMapperImageBuffer.h"
26 #include "Timer.h"
27 #include <wtf/CurrentTime.h>
28
29 #if USE(TEXTURE_MAPPER)
30
31 namespace WebCore {
32
33 struct BitmapTexturePoolEntry {
34     explicit BitmapTexturePoolEntry(PassRefPtr<BitmapTexture> texture)
35         : m_texture(texture)
36     { }
37     inline void markUsed() { m_timeLastUsed = monotonicallyIncreasingTime(); }
38     static bool compareTimeLastUsed(const BitmapTexturePoolEntry& a, const BitmapTexturePoolEntry& b)
39     {
40         return a.m_timeLastUsed - b.m_timeLastUsed > 0;
41     }
42
43     RefPtr<BitmapTexture> m_texture;
44     double m_timeLastUsed;
45 };
46
47 class BitmapTexturePool {
48     WTF_MAKE_NONCOPYABLE(BitmapTexturePool);
49     WTF_MAKE_FAST_ALLOCATED;
50 public:
51     BitmapTexturePool();
52
53     PassRefPtr<BitmapTexture> acquireTexture(const IntSize&, TextureMapper*);
54
55 private:
56     void scheduleReleaseUnusedTextures();
57     void releaseUnusedTexturesTimerFired();
58
59     Vector<BitmapTexturePoolEntry> m_textures;
60     Timer m_releaseUnusedTexturesTimer;
61
62     static const double s_releaseUnusedSecondsTolerance;
63     static const double s_releaseUnusedTexturesTimerInterval;
64 };
65
66 const double BitmapTexturePool::s_releaseUnusedSecondsTolerance = 3;
67 const double BitmapTexturePool::s_releaseUnusedTexturesTimerInterval = 0.5;
68
69 BitmapTexturePool::BitmapTexturePool()
70     : m_releaseUnusedTexturesTimer(*this, &BitmapTexturePool::releaseUnusedTexturesTimerFired)
71 { }
72
73 void BitmapTexturePool::scheduleReleaseUnusedTextures()
74 {
75     if (m_releaseUnusedTexturesTimer.isActive())
76         m_releaseUnusedTexturesTimer.stop();
77
78     m_releaseUnusedTexturesTimer.startOneShot(s_releaseUnusedTexturesTimerInterval);
79 }
80
81 void BitmapTexturePool::releaseUnusedTexturesTimerFired()
82 {
83     if (m_textures.isEmpty())
84         return;
85
86     // Delete entries, which have been unused in s_releaseUnusedSecondsTolerance.
87     std::sort(m_textures.begin(), m_textures.end(), BitmapTexturePoolEntry::compareTimeLastUsed);
88
89     double minUsedTime = monotonicallyIncreasingTime() - s_releaseUnusedSecondsTolerance;
90     for (size_t i = 0; i < m_textures.size(); ++i) {
91         if (m_textures[i].m_timeLastUsed < minUsedTime) {
92             m_textures.remove(i, m_textures.size() - i);
93             break;
94         }
95     }
96 }
97
98 PassRefPtr<BitmapTexture> BitmapTexturePool::acquireTexture(const IntSize& size, TextureMapper* textureMapper)
99 {
100     BitmapTexturePoolEntry* selectedEntry = 0;
101     for (auto& entry : m_textures) {
102         // If the surface has only one reference (the one in m_textures), we can safely reuse it.
103         if (entry.m_texture->refCount() > 1)
104             continue;
105
106         if (entry.m_texture->canReuseWith(size)) {
107             selectedEntry = &entry;
108             break;
109         }
110     }
111
112     if (!selectedEntry) {
113         m_textures.append(BitmapTexturePoolEntry(textureMapper->createTexture()));
114         selectedEntry = &m_textures.last();
115     }
116
117     scheduleReleaseUnusedTextures();
118     selectedEntry->markUsed();
119     return selectedEntry->m_texture;
120 }
121
122 PassRefPtr<BitmapTexture> TextureMapper::acquireTextureFromPool(const IntSize& size, const BitmapTexture::Flags flags)
123 {
124     RefPtr<BitmapTexture> selectedTexture = m_texturePool->acquireTexture(size, this);
125     selectedTexture->reset(size, flags);
126     return selectedTexture.release();
127 }
128
129 std::unique_ptr<TextureMapper> TextureMapper::create(AccelerationMode mode)
130 {
131     if (mode == SoftwareMode)
132         return std::make_unique<TextureMapperImageBuffer>();
133     return platformCreateAccelerated();
134 }
135
136 TextureMapper::TextureMapper(AccelerationMode accelerationMode)
137     : m_context(0)
138     , m_interpolationQuality(InterpolationDefault)
139     , m_textDrawingMode(TextModeFill)
140     , m_texturePool(std::make_unique<BitmapTexturePool>())
141     , m_accelerationMode(accelerationMode)
142     , m_isMaskMode(false)
143     , m_wrapMode(StretchWrap)
144 { }
145
146 TextureMapper::~TextureMapper()
147 { }
148
149 void BitmapTexture::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const IntRect& targetRect, const IntPoint& offset, UpdateContentsFlag updateContentsFlag)
150 {
151     std::unique_ptr<ImageBuffer> imageBuffer = ImageBuffer::create(targetRect.size());
152     GraphicsContext* context = imageBuffer->context();
153     context->setImageInterpolationQuality(textureMapper->imageInterpolationQuality());
154     context->setTextDrawingMode(textureMapper->textDrawingMode());
155
156     IntRect sourceRect(targetRect);
157     sourceRect.setLocation(offset);
158     context->translate(-offset.x(), -offset.y());
159     sourceLayer->paintGraphicsLayerContents(*context, sourceRect);
160
161     RefPtr<Image> image = imageBuffer->copyImage(DontCopyBackingStore);
162
163     updateContents(image.get(), targetRect, IntPoint(), updateContentsFlag);
164 }
165
166 } // namespace
167
168 #endif