Reviewed by Kenneth Russell.
[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 "LayerTilerChromium.h"
35 #include "TextStream.h"
36 #include "cc/CCLayerImpl.h"
37 #include "cc/CCTiledLayerImpl.h"
38 #include <wtf/CurrentTime.h>
39
40 // Start tiling when the width and height of a layer are larger than this size.
41 static int maxUntiledSize = 510;
42
43 // When tiling is enabled, use tiles of this dimension squared.
44 static int defaultTileSize = 256;
45
46 using namespace std;
47
48 namespace WebCore {
49
50 TiledLayerChromium::TiledLayerChromium(GraphicsLayerChromium* owner)
51     : LayerChromium(owner)
52     , m_tilingOption(AutoTile)
53     , m_borderTexels(true)
54 {
55 }
56
57 TiledLayerChromium::~TiledLayerChromium()
58 {
59 }
60
61 PassRefPtr<CCLayerImpl> TiledLayerChromium::createCCLayerImpl()
62 {
63     return CCTiledLayerImpl::create(this, id());
64 }
65
66 void TiledLayerChromium::cleanupResources()
67 {
68     m_tiler.clear();
69     LayerChromium::cleanupResources();
70 }
71
72 void TiledLayerChromium::setLayerRenderer(LayerRendererChromium* layerRenderer)
73 {
74     LayerChromium::setLayerRenderer(layerRenderer);
75     createTilerIfNeeded();
76 }
77
78 void TiledLayerChromium::updateTileSizeAndTilingOption()
79 {
80     if (!m_tiler)
81         return;
82
83     const IntSize tileSize(defaultTileSize, defaultTileSize);
84
85     // Tile if both dimensions large, or any one dimension large and the other
86     // extends into a second tile. This heuristic allows for long skinny layers
87     // (e.g. scrollbars) that are Nx1 tiles to minimize wasted texture space.
88     const bool anyDimensionLarge = contentBounds().width() > maxUntiledSize || contentBounds().height() > maxUntiledSize;
89     const bool anyDimensionOneTile = contentBounds().width() <= defaultTileSize || contentBounds().height() <= defaultTileSize;
90     const bool autoTiled = anyDimensionLarge && !anyDimensionOneTile;
91
92     bool isTiled;
93     if (m_tilingOption == AlwaysTile)
94         isTiled = true;
95     else if (m_tilingOption == NeverTile)
96         isTiled = false;
97     else
98         isTiled = autoTiled;
99
100     // Empty tile size tells the tiler to avoid tiling.
101     IntSize requestedSize = isTiled ? tileSize : IntSize();
102     const int maxSize = layerRenderer()->maxTextureSize();
103     IntSize clampedSize = requestedSize.shrunkTo(IntSize(maxSize, maxSize));
104     m_tiler->setTileSize(clampedSize);
105 }
106
107 bool TiledLayerChromium::drawsContent() const
108 {
109     if (!m_owner)
110         return false;
111
112     if (!m_tiler)
113         return true;
114
115     if (m_tilingOption == NeverTile && m_tiler->numTiles() > 1)
116         return false;
117
118     return !m_tiler->skipsDraw();
119 }
120
121 void TiledLayerChromium::createTilerIfNeeded()
122 {
123     if (m_tiler)
124         return;
125
126     createTextureUpdaterIfNeeded();
127
128     m_tiler = LayerTilerChromium::create(
129         layerRenderer(),
130         IntSize(defaultTileSize, defaultTileSize),
131         m_borderTexels ? LayerTilerChromium::HasBorderTexels : LayerTilerChromium::NoBorderTexels);
132 }
133
134 void TiledLayerChromium::updateCompositorResources()
135 {
136     m_tiler->updateRect(textureUpdater());
137 }
138
139 void TiledLayerChromium::setTilingOption(TilingOption tilingOption)
140 {
141     m_tilingOption = tilingOption;
142     updateTileSizeAndTilingOption();
143 }
144
145 void TiledLayerChromium::setIsMask(bool isMask)
146 {
147     m_borderTexels = !isMask;
148     setTilingOption(isMask ? NeverTile : AutoTile);
149 }
150
151 TransformationMatrix TiledLayerChromium::tilingTransform() const
152 {
153     TransformationMatrix transform = ccLayerImpl()->drawTransform();
154
155     if (contentBounds().isEmpty())
156         return transform;
157
158     transform.scaleNonUniform(bounds().width() / static_cast<double>(contentBounds().width()),
159                               bounds().height() / static_cast<double>(contentBounds().height()));
160
161     // Tiler draws with a different origin from other layers.
162     transform.translate(-contentBounds().width() / 2.0, -contentBounds().height() / 2.0);
163
164     return transform;
165 }
166
167 void TiledLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
168 {
169     LayerChromium::pushPropertiesTo(layer);
170
171     CCTiledLayerImpl* tiledLayer = static_cast<CCTiledLayerImpl*>(layer);
172     tiledLayer->setTilingTransform(tilingTransform());
173     tiledLayer->setTiler(m_tiler.get());
174 }
175
176 static void writeIndent(TextStream& ts, int indent)
177 {
178     for (int i = 0; i != indent; ++i)
179         ts << "  ";
180 }
181
182 void TiledLayerChromium::dumpLayerProperties(TextStream& ts, int indent) const
183 {
184     LayerChromium::dumpLayerProperties(ts, indent);
185     writeIndent(ts, indent);
186     ts << "skipsDraw: " << (!m_tiler || m_tiler->skipsDraw()) << "\n";
187 }
188
189 }
190 #endif // USE(ACCELERATED_COMPOSITING)