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 31namespace WebCore { 32 33struct 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 47class BitmapTexturePool { 48 WTF_MAKE_NONCOPYABLE(BitmapTexturePool); 49 WTF_MAKE_FAST_ALLOCATED; 50public: 51 BitmapTexturePool(); 52 53 PassRefPtr<BitmapTexture> acquireTexture(const IntSize&, TextureMapper*); 54 55private: 56 void scheduleReleaseUnusedTextures(); 57 void releaseUnusedTexturesTimerFired(Timer<BitmapTexturePool>*); 58 59 Vector<BitmapTexturePoolEntry> m_textures; 60 Timer<BitmapTexturePool> m_releaseUnusedTexturesTimer; 61 62 static const double s_releaseUnusedSecondsTolerance; 63 static const double s_releaseUnusedTexturesTimerInterval; 64}; 65 66const double BitmapTexturePool::s_releaseUnusedSecondsTolerance = 3; 67const double BitmapTexturePool::s_releaseUnusedTexturesTimerInterval = 0.5; 68 69BitmapTexturePool::BitmapTexturePool() 70 : m_releaseUnusedTexturesTimer(this, &BitmapTexturePool::releaseUnusedTexturesTimerFired) 71{ } 72 73void BitmapTexturePool::scheduleReleaseUnusedTextures() 74{ 75 if (m_releaseUnusedTexturesTimer.isActive()) 76 m_releaseUnusedTexturesTimer.stop(); 77 78 m_releaseUnusedTexturesTimer.startOneShot(s_releaseUnusedTexturesTimerInterval); 79} 80 81void BitmapTexturePool::releaseUnusedTexturesTimerFired(Timer<BitmapTexturePool>*) 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 98PassRefPtr<BitmapTexture> BitmapTexturePool::acquireTexture(const IntSize& size, TextureMapper* textureMapper) 99{ 100 BitmapTexturePoolEntry* selectedEntry = 0; 101 for (size_t i = 0; i < m_textures.size(); ++i) { 102 BitmapTexturePoolEntry* entry = &m_textures[i]; 103 104 // If the surface has only one reference (the one in m_textures), we can safely reuse it. 105 if (entry->m_texture->refCount() > 1) 106 continue; 107 108 if (entry->m_texture->canReuseWith(size)) { 109 selectedEntry = entry; 110 break; 111 } 112 } 113 114 if (!selectedEntry) { 115 m_textures.append(BitmapTexturePoolEntry(textureMapper->createTexture())); 116 selectedEntry = &m_textures.last(); 117 } 118 119 scheduleReleaseUnusedTextures(); 120 selectedEntry->markUsed(); 121 return selectedEntry->m_texture; 122} 123 124PassRefPtr<BitmapTexture> TextureMapper::acquireTextureFromPool(const IntSize& size, const BitmapTexture::Flags flags) 125{ 126 RefPtr<BitmapTexture> selectedTexture = m_texturePool->acquireTexture(size, this); 127 selectedTexture->reset(size, flags); 128 return selectedTexture; 129} 130 131std::unique_ptr<TextureMapper> TextureMapper::create(AccelerationMode mode) 132{ 133 if (mode == SoftwareMode) 134 return std::make_unique<TextureMapperImageBuffer>(); 135 return platformCreateAccelerated(); 136} 137 138TextureMapper::TextureMapper(AccelerationMode accelerationMode) 139 : m_context(0) 140 , m_interpolationQuality(InterpolationDefault) 141 , m_textDrawingMode(TextModeFill) 142 , m_texturePool(std::make_unique<BitmapTexturePool>()) 143 , m_accelerationMode(accelerationMode) 144 , m_isMaskMode(false) 145 , m_wrapMode(StretchWrap) 146{ } 147 148TextureMapper::~TextureMapper() 149{ } 150 151void BitmapTexture::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const IntRect& targetRect, const IntPoint& offset, UpdateContentsFlag updateContentsFlag) 152{ 153 std::unique_ptr<ImageBuffer> imageBuffer = ImageBuffer::create(targetRect.size()); 154 GraphicsContext* context = imageBuffer->context(); 155 context->setImageInterpolationQuality(textureMapper->imageInterpolationQuality()); 156 context->setTextDrawingMode(textureMapper->textDrawingMode()); 157 158 IntRect sourceRect(targetRect); 159 sourceRect.setLocation(offset); 160 context->translate(-offset.x(), -offset.y()); 161 sourceLayer->paintGraphicsLayerContents(*context, sourceRect); 162 163 RefPtr<Image> image = imageBuffer->copyImage(DontCopyBackingStore); 164 165 updateContents(image.get(), targetRect, IntPoint(), updateContentsFlag); 166} 167 168} // namespace 169 170#endif 171