1 /*
2 * Copyright (C) 2010 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 are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32
33 #if USE(ACCELERATED_COMPOSITING)
34
35 #include "ContentLayerChromium.h"
36
37 #include "cc/CCLayerImpl.h"
38 #include "GraphicsContext3D.h"
39 #include "LayerRendererChromium.h"
40 #include "LayerTexture.h"
41 #include "RenderLayerBacking.h"
42 #include "TextStream.h"
43
44 // Maximum size the width or height of this layer can be before enabling tiling
45 // when m_tilingOption == AutoTile.
46 static int maxUntiledSize = 512;
47 // When tiling is enabled, use tiles of this dimension squared.
48 static int defaultTileSize = 256;
49
50 using namespace std;
51
52 namespace WebCore {
53
create(GraphicsLayerChromium * owner)54 PassRefPtr<ContentLayerChromium> ContentLayerChromium::create(GraphicsLayerChromium* owner)
55 {
56 return adoptRef(new ContentLayerChromium(owner));
57 }
58
ContentLayerChromium(GraphicsLayerChromium * owner)59 ContentLayerChromium::ContentLayerChromium(GraphicsLayerChromium* owner)
60 : LayerChromium(owner)
61 , m_tilingOption(ContentLayerChromium::AutoTile)
62 {
63 }
64
~ContentLayerChromium()65 ContentLayerChromium::~ContentLayerChromium()
66 {
67 m_tiler.clear();
68 LayerChromium::cleanupResources();
69 }
70
71 class ContentLayerPainter : public TilePaintInterface {
72 public:
ContentLayerPainter(GraphicsLayerChromium * owner)73 explicit ContentLayerPainter(GraphicsLayerChromium* owner)
74 : m_owner(owner)
75 {
76 }
77
paint(GraphicsContext & context,const IntRect & contentRect)78 virtual void paint(GraphicsContext& context, const IntRect& contentRect)
79 {
80 context.save();
81 context.clearRect(contentRect);
82 context.clip(contentRect);
83 m_owner->paintGraphicsLayerContents(context, contentRect);
84 context.restore();
85 }
86 private:
87 GraphicsLayerChromium* m_owner;
88 };
89
paintContentsIfDirty(const IntRect & targetSurfaceRect)90 void ContentLayerChromium::paintContentsIfDirty(const IntRect& targetSurfaceRect)
91 {
92 ASSERT(drawsContent());
93 ASSERT(layerRenderer());
94
95 createTilerIfNeeded();
96
97 ContentLayerPainter painter(m_owner);
98 updateLayerSize(layerBounds().size());
99
100 IntRect layerRect = visibleLayerRect(targetSurfaceRect);
101 if (layerRect.isEmpty())
102 return;
103
104 IntRect dirty = enclosingIntRect(m_dirtyRect);
105 dirty.intersect(layerBounds());
106 m_tiler->invalidateRect(dirty);
107
108 m_tiler->update(painter, layerRect);
109 m_dirtyRect = FloatRect();
110 }
111
setLayerRenderer(LayerRendererChromium * layerRenderer)112 void ContentLayerChromium::setLayerRenderer(LayerRendererChromium* layerRenderer)
113 {
114 LayerChromium::setLayerRenderer(layerRenderer);
115 createTilerIfNeeded();
116 m_tiler->setLayerRenderer(layerRenderer);
117 }
118
tilingTransform()119 TransformationMatrix ContentLayerChromium::tilingTransform()
120 {
121 TransformationMatrix transform = ccLayerImpl()->drawTransform();
122 // Tiler draws from the upper left corner. The draw transform
123 // specifies the middle of the layer.
124 IntSize size = bounds();
125 transform.translate(-size.width() / 2.0, -size.height() / 2.0);
126
127 return transform;
128 }
129
visibleLayerRect(const IntRect & targetSurfaceRect)130 IntRect ContentLayerChromium::visibleLayerRect(const IntRect& targetSurfaceRect)
131 {
132 if (targetSurfaceRect.isEmpty())
133 return targetSurfaceRect;
134
135 const IntRect layerBoundRect = layerBounds();
136 const TransformationMatrix transform = tilingTransform();
137
138 // Is this layer fully contained within the target surface?
139 IntRect layerInSurfaceSpace = transform.mapRect(layerBoundRect);
140 if (targetSurfaceRect.contains(layerInSurfaceSpace))
141 return layerBoundRect;
142
143 // If the layer doesn't fill up the entire surface, then find the part of
144 // the surface rect where the layer could be visible. This avoids trying to
145 // project surface rect points that are behind the projection point.
146 IntRect minimalSurfaceRect = targetSurfaceRect;
147 minimalSurfaceRect.intersect(layerInSurfaceSpace);
148
149 // Project the corners of the target surface rect into the layer space.
150 // This bounding rectangle may be larger than it needs to be (being
151 // axis-aligned), but is a reasonable filter on the space to consider.
152 // Non-invertible transforms will create an empty rect here.
153 const TransformationMatrix surfaceToLayer = transform.inverse();
154 IntRect layerRect = surfaceToLayer.projectQuad(FloatQuad(FloatRect(minimalSurfaceRect))).enclosingBoundingBox();
155 layerRect.intersect(layerBoundRect);
156 return layerRect;
157 }
158
layerBounds() const159 IntRect ContentLayerChromium::layerBounds() const
160 {
161 return IntRect(IntPoint(0, 0), bounds());
162 }
163
updateLayerSize(const IntSize & layerSize)164 void ContentLayerChromium::updateLayerSize(const IntSize& layerSize)
165 {
166 if (!m_tiler)
167 return;
168
169 const IntSize tileSize(min(defaultTileSize, layerSize.width()), min(defaultTileSize, layerSize.height()));
170 const bool autoTiled = layerSize.width() > maxUntiledSize || layerSize.height() > maxUntiledSize;
171
172 bool isTiled;
173 if (m_tilingOption == AlwaysTile)
174 isTiled = true;
175 else if (m_tilingOption == NeverTile)
176 isTiled = false;
177 else
178 isTiled = autoTiled;
179
180 m_tiler->setTileSize(isTiled ? tileSize : layerSize);
181 }
182
draw(const IntRect & targetSurfaceRect)183 void ContentLayerChromium::draw(const IntRect& targetSurfaceRect)
184 {
185 const TransformationMatrix transform = tilingTransform();
186 IntRect layerRect = visibleLayerRect(targetSurfaceRect);
187 if (!layerRect.isEmpty())
188 m_tiler->draw(layerRect, transform, ccLayerImpl()->drawOpacity());
189 }
190
createTilerIfNeeded()191 void ContentLayerChromium::createTilerIfNeeded()
192 {
193 if (m_tiler)
194 return;
195 m_tiler = LayerTilerChromium::create(layerRenderer(), IntSize(defaultTileSize, defaultTileSize), LayerTilerChromium::HasBorderTexels);
196 }
197
updateCompositorResources()198 void ContentLayerChromium::updateCompositorResources()
199 {
200 m_tiler->uploadCanvas();
201 }
202
setTilingOption(TilingOption option)203 void ContentLayerChromium::setTilingOption(TilingOption option)
204 {
205 m_tilingOption = option;
206 updateLayerSize(bounds());
207 }
208
bindContentsTexture()209 void ContentLayerChromium::bindContentsTexture()
210 {
211 // This function is only valid for single texture layers, e.g. masks.
212 ASSERT(m_tilingOption == NeverTile);
213 ASSERT(m_tiler);
214
215 LayerTexture* texture = m_tiler->getSingleTexture();
216 ASSERT(texture);
217
218 texture->bindTexture();
219 }
220
setIsMask(bool isMask)221 void ContentLayerChromium::setIsMask(bool isMask)
222 {
223 setTilingOption(isMask ? NeverTile : AutoTile);
224 }
225
writeIndent(TextStream & ts,int indent)226 static void writeIndent(TextStream& ts, int indent)
227 {
228 for (int i = 0; i != indent; ++i)
229 ts << " ";
230 }
231
dumpLayerProperties(TextStream & ts,int indent) const232 void ContentLayerChromium::dumpLayerProperties(TextStream& ts, int indent) const
233 {
234 LayerChromium::dumpLayerProperties(ts, indent);
235 writeIndent(ts, indent);
236 ts << "skipsDraw: " << m_tiler->skipsDraw() << "\n";
237 }
238
239 }
240 #endif // USE(ACCELERATED_COMPOSITING)
241