• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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