[GTK] Build fix for Accelerated Compositing with OpenGL
[WebKit-https.git] / Source / WebCore / platform / graphics / texmap / TextureMapperBackingStore.cpp
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 #include "TextureMapperBackingStore.h"
22
23 #include "GraphicsLayer.h"
24 #include "ImageBuffer.h"
25 #include "TextureMapper.h"
26
27 #if USE(GRAPHICS_SURFACE)
28 #include "GraphicsSurface.h"
29 #include "TextureMapperGL.h"
30 #endif
31
32 namespace WebCore {
33
34 #if USE(GRAPHICS_SURFACE)
35 void TextureMapperSurfaceBackingStore::setGraphicsSurface(uint32_t graphicsSurfaceToken, const IntSize& surfaceSize)
36 {
37     if (graphicsSurfaceToken != m_backBufferGraphicsSurfaceData.m_graphicsSurfaceToken) {
38         GraphicsSurface::Flags surfaceFlags = GraphicsSurface::SupportsTextureTarget
39                                             | GraphicsSurface::SupportsSharing;
40         m_backBufferGraphicsSurfaceData.setSurface(GraphicsSurface::create(surfaceSize, surfaceFlags, graphicsSurfaceToken));
41         m_graphicsSurfaceSize = surfaceSize;
42     }
43
44     std::swap(m_backBufferGraphicsSurfaceData, m_frontBufferGraphicsSurfaceData);
45 }
46
47 PassRefPtr<BitmapTexture> TextureMapperSurfaceBackingStore::texture() const
48 {
49     // FIXME: Instead of just returning an empty texture, we should wrap the texture contents into a BitmapTexture.
50     RefPtr<BitmapTexture> emptyTexture;
51     return emptyTexture;
52 }
53
54 void TextureMapperSurfaceBackingStore::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity, BitmapTexture* mask)
55 {
56     TransformationMatrix adjustedTransform = transform;
57     adjustedTransform.multiply(TransformationMatrix::rectToRect(FloatRect(FloatPoint::zero(), m_graphicsSurfaceSize), targetRect));
58 #if OS(DARWIN)
59     // This is specific to the Mac implementation of GraphicsSurface. IOSurface requires GL_TEXTURE_RECTANGLE_ARB to be used.
60     static_cast<TextureMapperGL*>(textureMapper)->drawTextureRectangleARB(m_frontBufferGraphicsSurfaceData.m_textureID, 0, m_graphicsSurfaceSize, targetRect, adjustedTransform, opacity, mask);
61 #else
62     UNUSED_PARAM(textureMapper);
63     UNUSED_PARAM(opacity);
64     UNUSED_PARAM(mask);
65 #endif
66 }
67 #endif
68
69 void TextureMapperTile::updateContents(TextureMapper* textureMapper, Image* image, const IntRect& dirtyRect)
70 {
71     IntRect targetRect = enclosingIntRect(m_rect);
72     targetRect.intersect(dirtyRect);
73     if (targetRect.isEmpty())
74         return;
75     IntPoint sourceOffset = targetRect.location();
76
77     // Normalize sourceRect to the buffer's coordinates.
78     sourceOffset.move(-dirtyRect.x(), -dirtyRect.y());
79
80     // Normalize targetRect to the texture's coordinates.
81     targetRect.move(-m_rect.x(), -m_rect.y());
82     if (!m_texture) {
83         m_texture = textureMapper->createTexture();
84         m_texture->reset(targetRect.size(), image->currentFrameHasAlpha() ? BitmapTexture::SupportsAlpha : 0);
85     }
86
87     m_texture->updateContents(image, targetRect, sourceOffset);
88 }
89
90 void TextureMapperTile::paint(TextureMapper* textureMapper, const TransformationMatrix& transform, float opacity, BitmapTexture* mask)
91 {
92     textureMapper->drawTexture(*texture().get(), rect(), transform, opacity, mask);
93 }
94
95 TextureMapperTiledBackingStore::TextureMapperTiledBackingStore()
96     : m_drawsDebugBorders(false)
97 {
98 }
99
100 void TextureMapperTiledBackingStore::updateContentsFromImageIfNeeded(TextureMapper* textureMapper)
101 {
102     if (!m_image)
103         return;
104
105     updateContents(textureMapper, m_image.get());
106     m_image.clear();
107 }
108
109 void TextureMapperTiledBackingStore::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& transform, float opacity, BitmapTexture* mask)
110 {
111     updateContentsFromImageIfNeeded(textureMapper);
112     TransformationMatrix adjustedTransform = transform;
113     adjustedTransform.multiply(TransformationMatrix::rectToRect(rect(), targetRect));
114     for (size_t i = 0; i < m_tiles.size(); ++i) {
115         m_tiles[i].paint(textureMapper, adjustedTransform, opacity, mask);
116         if (m_drawsDebugBorders)
117             textureMapper->drawBorder(m_debugBorderColor, m_debugBorderWidth, m_tiles[i].rect(), adjustedTransform);
118     }
119 }
120
121 void TextureMapperTiledBackingStore::createOrDestroyTilesIfNeeded(const FloatSize& size, const IntSize& tileSize, bool hasAlpha)
122 {
123     if (size == m_size)
124         return;
125
126     m_size = size;
127
128     Vector<FloatRect> tileRectsToAdd;
129     Vector<int> tileIndicesToRemove;
130     static const size_t TileEraseThreshold = 6;
131
132     // This method recycles tiles. We check which tiles we need to add, which to remove, and use as many
133     // removable tiles as replacement for new tiles when possible.
134     for (float y = 0; y < m_size.height(); y += tileSize.height()) {
135         for (float x = 0; x < m_size.width(); x += tileSize.width()) {
136             FloatRect tileRect(x, y, tileSize.width(), tileSize.height());
137             tileRect.intersect(rect());
138             tileRectsToAdd.append(tileRect);
139         }
140     }
141
142     // Check which tiles need to be removed, and which already exist.
143     for (int i = m_tiles.size() - 1; i >= 0; --i) {
144         FloatRect oldTile = m_tiles[i].rect();
145         bool existsAlready = false;
146
147         for (int j = tileRectsToAdd.size() - 1; j >= 0; --j) {
148             FloatRect newTile = tileRectsToAdd[j];
149             if (oldTile != newTile)
150                 continue;
151
152             // A tile that we want to add already exists, no need to add or remove it.
153             existsAlready = true;
154             tileRectsToAdd.remove(j);
155             break;
156         }
157
158         // This tile is not needed.
159         if (!existsAlready)
160             tileIndicesToRemove.append(i);
161     }
162
163     // Recycle removable tiles to be used for newly requested tiles.
164     for (size_t i = 0; i < tileRectsToAdd.size(); ++i) {
165         if (!tileIndicesToRemove.isEmpty()) {
166             // We recycle an existing tile for usage with a new tile rect.
167             TextureMapperTile& tile = m_tiles[tileIndicesToRemove.last()];
168             tileIndicesToRemove.removeLast();
169             tile.setRect(tileRectsToAdd[i]);
170
171             if (tile.texture())
172                 tile.texture()->reset(enclosingIntRect(tile.rect()).size(), hasAlpha ? BitmapTexture::SupportsAlpha : 0);
173             continue;
174         }
175
176         m_tiles.append(TextureMapperTile(tileRectsToAdd[i]));
177     }
178
179     // Remove unnecessary tiles, if they weren't recycled.
180     // We use a threshold to make sure we don't create/destroy tiles too eagerly.
181     for (size_t i = 0; i < tileIndicesToRemove.size() && m_tiles.size() > TileEraseThreshold; ++i)
182         m_tiles.remove(tileIndicesToRemove[i]);
183 }
184
185 void TextureMapperTiledBackingStore::updateContents(TextureMapper* textureMapper, Image* image, const FloatSize& totalSize, const IntRect& dirtyRect)
186 {
187     createOrDestroyTilesIfNeeded(totalSize, textureMapper->maxTextureSize(), image->currentFrameHasAlpha());
188     for (size_t i = 0; i < m_tiles.size(); ++i)
189         m_tiles[i].updateContents(textureMapper, image, dirtyRect);
190 }
191
192 PassRefPtr<BitmapTexture> TextureMapperTiledBackingStore::texture() const
193 {
194     for (size_t i = 0; i < m_tiles.size(); ++i) {
195         RefPtr<BitmapTexture> texture = m_tiles[i].texture();
196         if (texture)
197             return texture;
198     }
199
200     return PassRefPtr<BitmapTexture>();
201 }
202
203 void TextureMapperTiledBackingStore::setDebugBorder(const Color& color, float width)
204 {
205     m_debugBorderColor = color;
206     m_debugBorderWidth = width;
207 }
208
209 }