1/* 2 Copyright (C) 2012 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 22#if USE(TEXTURE_MAPPER) 23#include "TextureMapperTiledBackingStore.h" 24 25#include "ImageBuffer.h" 26#include "TextureMapper.h" 27 28namespace WebCore { 29 30class GraphicsLayer; 31 32TextureMapperTiledBackingStore::TextureMapperTiledBackingStore() 33{ 34} 35 36void TextureMapperTiledBackingStore::updateContentsFromImageIfNeeded(TextureMapper* textureMapper) 37{ 38 if (!m_image) 39 return; 40 41 updateContents(textureMapper, m_image.get(), m_image->size(), enclosingIntRect(m_image->rect()), BitmapTexture::UpdateCannotModifyOriginalImageData); 42 m_image.clear(); 43} 44 45TransformationMatrix TextureMapperTiledBackingStore::adjustedTransformForRect(const FloatRect& targetRect) 46{ 47 return TransformationMatrix::rectToRect(rect(), targetRect); 48} 49 50void TextureMapperTiledBackingStore::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity) 51{ 52 updateContentsFromImageIfNeeded(textureMapper); 53 TransformationMatrix adjustedTransform = transform * adjustedTransformForRect(targetRect); 54 for (size_t i = 0; i < m_tiles.size(); ++i) 55 m_tiles[i].paint(textureMapper, adjustedTransform, opacity, calculateExposedTileEdges(rect(), m_tiles[i].rect())); 56} 57 58void TextureMapperTiledBackingStore::drawBorder(TextureMapper* textureMapper, const Color& borderColor, float borderWidth, const FloatRect& targetRect, const TransformationMatrix& transform) 59{ 60 TransformationMatrix adjustedTransform = transform * adjustedTransformForRect(targetRect); 61 for (size_t i = 0; i < m_tiles.size(); ++i) 62 textureMapper->drawBorder(borderColor, borderWidth, m_tiles[i].rect(), adjustedTransform); 63} 64 65void TextureMapperTiledBackingStore::drawRepaintCounter(TextureMapper* textureMapper, int repaintCount, const Color& borderColor, const FloatRect& targetRect, const TransformationMatrix& transform) 66{ 67 TransformationMatrix adjustedTransform = transform * adjustedTransformForRect(targetRect); 68 for (size_t i = 0; i < m_tiles.size(); ++i) 69 textureMapper->drawNumber(repaintCount, borderColor, m_tiles[i].rect().location(), adjustedTransform); 70} 71 72void TextureMapperTiledBackingStore::createOrDestroyTilesIfNeeded(const FloatSize& size, const IntSize& tileSize, bool hasAlpha) 73{ 74 if (size == m_size) 75 return; 76 77 m_size = size; 78 79 Vector<FloatRect> tileRectsToAdd; 80 Vector<int> tileIndicesToRemove; 81 static const size_t TileEraseThreshold = 6; 82 83 // This method recycles tiles. We check which tiles we need to add, which to remove, and use as many 84 // removable tiles as replacement for new tiles when possible. 85 for (float y = 0; y < m_size.height(); y += tileSize.height()) { 86 for (float x = 0; x < m_size.width(); x += tileSize.width()) { 87 FloatRect tileRect(x, y, tileSize.width(), tileSize.height()); 88 tileRect.intersect(rect()); 89 tileRectsToAdd.append(tileRect); 90 } 91 } 92 93 // Check which tiles need to be removed, and which already exist. 94 for (int i = m_tiles.size() - 1; i >= 0; --i) { 95 FloatRect oldTile = m_tiles[i].rect(); 96 bool existsAlready = false; 97 98 for (int j = tileRectsToAdd.size() - 1; j >= 0; --j) { 99 FloatRect newTile = tileRectsToAdd[j]; 100 if (oldTile != newTile) 101 continue; 102 103 // A tile that we want to add already exists, no need to add or remove it. 104 existsAlready = true; 105 tileRectsToAdd.remove(j); 106 break; 107 } 108 109 // This tile is not needed. 110 if (!existsAlready) 111 tileIndicesToRemove.append(i); 112 } 113 114 // Recycle removable tiles to be used for newly requested tiles. 115 for (size_t i = 0; i < tileRectsToAdd.size(); ++i) { 116 if (!tileIndicesToRemove.isEmpty()) { 117 // We recycle an existing tile for usage with a new tile rect. 118 TextureMapperTile& tile = m_tiles[tileIndicesToRemove.last()]; 119 tileIndicesToRemove.removeLast(); 120 tile.setRect(tileRectsToAdd[i]); 121 122 if (tile.texture()) 123 tile.texture()->reset(enclosingIntRect(tile.rect()).size(), hasAlpha ? BitmapTexture::SupportsAlpha : 0); 124 continue; 125 } 126 127 m_tiles.append(TextureMapperTile(tileRectsToAdd[i])); 128 } 129 130 // Remove unnecessary tiles, if they weren't recycled. 131 // We use a threshold to make sure we don't create/destroy tiles too eagerly. 132 for (size_t i = 0; i < tileIndicesToRemove.size() && m_tiles.size() > TileEraseThreshold; ++i) 133 m_tiles.remove(tileIndicesToRemove[i]); 134} 135 136void TextureMapperTiledBackingStore::updateContents(TextureMapper* textureMapper, Image* image, const FloatSize& totalSize, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag) 137{ 138 createOrDestroyTilesIfNeeded(totalSize, textureMapper->maxTextureSize(), !image->currentFrameKnownToBeOpaque()); 139 for (size_t i = 0; i < m_tiles.size(); ++i) 140 m_tiles[i].updateContents(textureMapper, image, dirtyRect, updateContentsFlag); 141} 142 143void TextureMapperTiledBackingStore::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const FloatSize& totalSize, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag) 144{ 145 createOrDestroyTilesIfNeeded(totalSize, textureMapper->maxTextureSize(), true); 146 for (size_t i = 0; i < m_tiles.size(); ++i) 147 m_tiles[i].updateContents(textureMapper, sourceLayer, dirtyRect, updateContentsFlag); 148} 149 150PassRefPtr<BitmapTexture> TextureMapperTiledBackingStore::texture() const 151{ 152 for (size_t i = 0; i < m_tiles.size(); ++i) { 153 RefPtr<BitmapTexture> texture = m_tiles[i].texture(); 154 if (texture) 155 return texture; 156 } 157 158 return PassRefPtr<BitmapTexture>(); 159} 160 161} // namespace WebCore 162#endif 163