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