[Chromium] Remove unused variable added by r99813.
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / TiledLayerChromium.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #if USE(ACCELERATED_COMPOSITING)
29
30 #include "TiledLayerChromium.h"
31
32 #include "GraphicsContext3D.h"
33 #include "LayerRendererChromium.h"
34 #include "ManagedTexture.h"
35 #include "TextStream.h"
36 #include "cc/CCLayerImpl.h"
37 #include "cc/CCTextureUpdater.h"
38 #include "cc/CCTiledLayerImpl.h"
39 #include <wtf/CurrentTime.h>
40
41 // Start tiling when the width and height of a layer are larger than this size.
42 static int maxUntiledSize = 512;
43
44 // When tiling is enabled, use tiles of this dimension squared.
45 static int defaultTileSize = 256;
46
47 using namespace std;
48
49 namespace WebCore {
50
51 class UpdatableTile : public CCLayerTilingData::Tile {
52     WTF_MAKE_NONCOPYABLE(UpdatableTile);
53 public:
54     explicit UpdatableTile(PassRefPtr<LayerTextureUpdater::Texture> texture) : m_texture(texture) { }
55
56     LayerTextureUpdater::Texture* texture() { return m_texture.get(); }
57     ManagedTexture* managedTexture() { return m_texture->texture(); }
58
59     bool dirty() const { return !m_dirtyLayerRect.isEmpty(); }
60     void clearDirty() { m_dirtyLayerRect = IntRect(); }
61
62     // Layer-space dirty rectangle that needs to be repainted.
63     IntRect m_dirtyLayerRect;
64     // Content-space rectangle that needs to be updated.
65     IntRect m_updateRect;
66 private:
67     RefPtr<LayerTextureUpdater::Texture> m_texture;
68 };
69
70 TiledLayerChromium::TiledLayerChromium(CCLayerDelegate* delegate)
71     : LayerChromium(delegate)
72     , m_tilingOption(AutoTile)
73     , m_textureFormat(GraphicsContext3D::INVALID_ENUM)
74     , m_skipsDraw(false)
75     , m_textureOrientation(LayerTextureUpdater::InvalidOrientation)
76     , m_sampledTexelFormat(LayerTextureUpdater::SampledTexelFormatInvalid)
77 {
78 }
79
80 TiledLayerChromium::~TiledLayerChromium()
81 {
82 }
83
84 PassRefPtr<CCLayerImpl> TiledLayerChromium::createCCLayerImpl()
85 {
86     return CCTiledLayerImpl::create(id());
87 }
88
89 void TiledLayerChromium::cleanupResources()
90 {
91     LayerChromium::cleanupResources();
92
93     m_tiler.clear();
94     m_paintRect = IntRect();
95     m_requestedUpdateRect = IntRect();
96 }
97
98 void TiledLayerChromium::updateTileSizeAndTilingOption()
99 {
100     if (!m_tiler)
101         return;
102
103     const IntSize tileSize(min(defaultTileSize, contentBounds().width()), min(defaultTileSize, contentBounds().height()));
104
105     // Tile if both dimensions large, or any one dimension large and the other
106     // extends into a second tile. This heuristic allows for long skinny layers
107     // (e.g. scrollbars) that are Nx1 tiles to minimize wasted texture space.
108     const bool anyDimensionLarge = contentBounds().width() > maxUntiledSize || contentBounds().height() > maxUntiledSize;
109     const bool anyDimensionOneTile = contentBounds().width() <= defaultTileSize || contentBounds().height() <= defaultTileSize;
110     const bool autoTiled = anyDimensionLarge && !anyDimensionOneTile;
111
112     bool isTiled;
113     if (m_tilingOption == AlwaysTile)
114         isTiled = true;
115     else if (m_tilingOption == NeverTile)
116         isTiled = false;
117     else
118         isTiled = autoTiled;
119
120     IntSize requestedSize = isTiled ? tileSize : contentBounds();
121     const int maxSize = layerTreeHost()->layerRendererCapabilities().maxTextureSize;
122     IntSize clampedSize = requestedSize.shrunkTo(IntSize(maxSize, maxSize));
123     m_tiler->setTileSize(clampedSize);
124 }
125
126 bool TiledLayerChromium::drawsContent() const
127 {
128     if (!m_delegate)
129         return false;
130
131     if (!m_tiler)
132         return true;
133
134     if (m_tilingOption == NeverTile && m_tiler->numTiles() > 1)
135         return false;
136
137     return !m_skipsDraw;
138 }
139
140 void TiledLayerChromium::setLayerTreeHost(CCLayerTreeHost* host)
141 {
142     LayerChromium::setLayerTreeHost(host);
143
144     if (m_tiler || !host)
145         return;
146
147     createTextureUpdater(host);
148
149     m_textureFormat = host->layerRendererCapabilities().bestTextureFormat;
150     m_textureOrientation = textureUpdater()->orientation();
151     m_sampledTexelFormat = textureUpdater()->sampledTexelFormat(m_textureFormat);
152     m_tiler = CCLayerTilingData::create(
153         IntSize(defaultTileSize, defaultTileSize),
154         isNonCompositedContent() ? CCLayerTilingData::NoBorderTexels : CCLayerTilingData::HasBorderTexels);
155 }
156
157 void TiledLayerChromium::updateCompositorResources(GraphicsContext3D* context, CCTextureUpdater& updater)
158 {
159     // Painting could cause compositing to get turned off, which may cause the tiler to become invalidated mid-update.
160     if (m_skipsDraw || m_requestedUpdateRect.isEmpty() || !m_tiler->numTiles())
161         return;
162
163     int left, top, right, bottom;
164     m_tiler->contentRectToTileIndices(m_requestedUpdateRect, left, top, right, bottom);
165     for (int j = top; j <= bottom; ++j) {
166         for (int i = left; i <= right; ++i) {
167             UpdatableTile* tile = tileAt(i, j);
168             if (!tile)
169                 tile = createTile(i, j);
170             else if (!tile->dirty())
171                 continue;
172
173             IntRect sourceRect = tile->m_updateRect;
174             if (tile->m_updateRect.isEmpty())
175                 continue;
176
177             ASSERT(tile->managedTexture()->isReserved());
178             const IntPoint anchor = m_tiler->tileContentRect(tile).location();
179
180             // Calculate tile-space rectangle to upload into.
181             IntRect destRect(IntPoint(sourceRect.x() - anchor.x(), sourceRect.y() - anchor.y()), sourceRect.size());
182             if (destRect.x() < 0)
183                 CRASH();
184             if (destRect.y() < 0)
185                 CRASH();
186
187             // Offset from paint rectangle to this tile's dirty rectangle.
188             IntPoint paintOffset(sourceRect.x() - m_paintRect.x(), sourceRect.y() - m_paintRect.y());
189             if (paintOffset.x() < 0)
190                 CRASH();
191             if (paintOffset.y() < 0)
192                 CRASH();
193             if (paintOffset.x() + destRect.width() > m_paintRect.width())
194                 CRASH();
195             if (paintOffset.y() + destRect.height() > m_paintRect.height())
196                 CRASH();
197
198             tile->managedTexture()->bindTexture(context, updater.allocator());
199             const GC3Dint filter = m_tiler->hasBorderTexels() ? GraphicsContext3D::LINEAR : GraphicsContext3D::NEAREST;
200             GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, filter));
201             GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, filter));
202
203             updater.append(tile->texture(), sourceRect, destRect);
204             tile->clearDirty();
205         }
206     }
207
208     m_updateRect = FloatRect(m_tiler->contentRectToLayerRect(m_paintRect));
209 }
210
211 void TiledLayerChromium::setTilingOption(TilingOption tilingOption)
212 {
213     m_tilingOption = tilingOption;
214     updateTileSizeAndTilingOption();
215 }
216
217 void TiledLayerChromium::setIsMask(bool isMask)
218 {
219     setTilingOption(isMask ? NeverTile : AutoTile);
220 }
221
222 void TiledLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
223 {
224     LayerChromium::pushPropertiesTo(layer);
225
226     CCTiledLayerImpl* tiledLayer = static_cast<CCTiledLayerImpl*>(layer);
227     if (!m_tiler) {
228         tiledLayer->setSkipsDraw(true);
229         return;
230     }
231
232     tiledLayer->setSkipsDraw(m_skipsDraw);
233     tiledLayer->setTextureOrientation(m_textureOrientation);
234     tiledLayer->setSampledTexelFormat(m_sampledTexelFormat);
235     tiledLayer->setTilingData(*m_tiler);
236
237     for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) {
238         int i = iter->first.first;
239         int j = iter->first.second;
240         UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get());
241         if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat))
242             continue;
243
244         tiledLayer->syncTextureId(i, j, tile->managedTexture()->textureId());
245     }
246 }
247
248 TextureManager* TiledLayerChromium::textureManager() const
249 {
250     if (!layerTreeHost())
251         return 0;
252     return layerTreeHost()->contentsTextureManager();
253 }
254
255 UpdatableTile* TiledLayerChromium::tileAt(int i, int j) const
256 {
257     return static_cast<UpdatableTile*>(m_tiler->tileAt(i, j));
258 }
259
260 UpdatableTile* TiledLayerChromium::createTile(int i, int j)
261 {
262     RefPtr<UpdatableTile> tile = adoptRef(new UpdatableTile(textureUpdater()->createTexture(textureManager())));
263     m_tiler->addTile(tile, i, j);
264     tile->m_dirtyLayerRect = m_tiler->tileLayerRect(tile.get());
265
266     return tile.get();
267 }
268
269 void TiledLayerChromium::invalidateRect(const IntRect& contentRect)
270 {
271     if (!m_tiler || contentRect.isEmpty() || m_skipsDraw)
272         return;
273
274     m_tiler->growLayerToContain(contentRect);
275
276     // Dirty rects are always in layer space, as the layer could be repositioned
277     // after invalidation.
278     const IntRect layerRect = m_tiler->contentRectToLayerRect(contentRect);
279
280     int left, top, right, bottom;
281     m_tiler->contentRectToTileIndices(contentRect, left, top, right, bottom);
282     for (int j = top; j <= bottom; ++j) {
283         for (int i = left; i <= right; ++i) {
284             UpdatableTile* tile = tileAt(i, j);
285             if (!tile)
286                 continue;
287             IntRect bound = m_tiler->tileLayerRect(tile);
288             bound.intersect(layerRect);
289             tile->m_dirtyLayerRect.unite(bound);
290         }
291     }
292 }
293
294 void TiledLayerChromium::protectVisibleTileTextures()
295 {
296     protectTileTextures(IntRect(IntPoint::zero(), contentBounds()));
297 }
298
299 void TiledLayerChromium::protectTileTextures(const IntRect& contentRect)
300 {
301     if (!m_tiler || contentRect.isEmpty())
302         return;
303
304     int left, top, right, bottom;
305     m_tiler->contentRectToTileIndices(contentRect, left, top, right, bottom);
306
307     for (int j = top; j <= bottom; ++j) {
308         for (int i = left; i <= right; ++i) {
309             UpdatableTile* tile = tileAt(i, j);
310             if (!tile || !tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat))
311                 continue;
312
313             tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureFormat);
314         }
315     }
316 }
317
318 void TiledLayerChromium::prepareToUpdate(const IntRect& contentRect)
319 {
320     ASSERT(m_tiler);
321
322     m_skipsDraw = false;
323
324     if (contentRect.isEmpty()) {
325         m_requestedUpdateRect = IntRect();
326         return;
327     }
328
329     m_tiler->growLayerToContain(contentRect);
330
331     if (!m_tiler->numTiles()) {
332         m_requestedUpdateRect = IntRect();
333         return;
334     }
335
336     // Create tiles as needed, expanding a dirty rect to contain all
337     // the dirty regions currently being drawn.
338     IntRect dirtyLayerRect;
339     int left, top, right, bottom;
340     m_tiler->contentRectToTileIndices(contentRect, left, top, right, bottom);
341     for (int j = top; j <= bottom; ++j) {
342         for (int i = left; i <= right; ++i) {
343             UpdatableTile* tile = tileAt(i, j);
344             if (!tile)
345                 tile = createTile(i, j);
346
347             if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat))
348                 tile->m_dirtyLayerRect = m_tiler->tileLayerRect(tile);
349
350             if (!tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureFormat)) {
351                 m_skipsDraw = true;
352                 cleanupResources();
353                 return;
354             }
355
356             dirtyLayerRect.unite(tile->m_dirtyLayerRect);
357         }
358     }
359
360     // Due to borders, when the paint rect is extended to tile boundaries, it
361     // may end up overlapping more tiles than the original content rect. Record
362     // that original rect so we don't upload more tiles than necessary.
363     m_requestedUpdateRect = contentRect;
364
365     m_paintRect = m_tiler->layerRectToContentRect(dirtyLayerRect);
366     if (dirtyLayerRect.isEmpty())
367         return;
368
369     // Calling prepareToUpdate() calls into WebKit to paint, which may have the side
370     // effect of disabling compositing, which causes our reference to the texture updater to be deleted.
371     // However, we can't free the memory backing the GraphicsContext until the paint finishes,
372     // so we grab a local reference here to hold the updater alive until the paint completes.
373     RefPtr<LayerTextureUpdater> protector(textureUpdater());
374     textureUpdater()->prepareToUpdate(m_paintRect, m_tiler->tileSize(), m_tiler->hasBorderTexels());
375
376     m_tiler->contentRectToTileIndices(m_requestedUpdateRect, left, top, right, bottom);
377     for (int j = top; j <= bottom; ++j) {
378         for (int i = left; i <= right; ++i) {
379             UpdatableTile* tile = tileAt(i, j);
380             if (!tile)
381                 tile = createTile(i, j);
382             else if (!tile->dirty())
383                 continue;
384
385             // Calculate content-space rectangle to copy from.
386             IntRect sourceRect = m_tiler->tileContentRect(tile);
387             sourceRect.intersect(m_tiler->layerRectToContentRect(tile->m_dirtyLayerRect));
388             // Paint rect not guaranteed to line up on tile boundaries, so
389             // make sure that sourceRect doesn't extend outside of it.
390             sourceRect.intersect(m_paintRect);
391
392             tile->m_updateRect = sourceRect;
393             if (sourceRect.isEmpty())
394                 continue;
395
396             tile->texture()->prepareRect(sourceRect);
397         }
398     }
399 }
400
401 }
402 #endif // USE(ACCELERATED_COMPOSITING)