• 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 "LayerChromium.h"
36 
37 #include "cc/CCLayerImpl.h"
38 #include "GraphicsContext3D.h"
39 #include "LayerRendererChromium.h"
40 #if USE(SKIA)
41 #include "NativeImageSkia.h"
42 #include "PlatformContextSkia.h"
43 #endif
44 #include "RenderLayerBacking.h"
45 #include "TextStream.h"
46 #include "skia/ext/platform_canvas.h"
47 
48 namespace WebCore {
49 
50 using namespace std;
51 
52 #ifndef NDEBUG
53 static int s_nextLayerDebugID = 1;
54 #endif
55 
create(GraphicsLayerChromium * owner)56 PassRefPtr<LayerChromium> LayerChromium::create(GraphicsLayerChromium* owner)
57 {
58     return adoptRef(new LayerChromium(owner));
59 }
60 
LayerChromium(GraphicsLayerChromium * owner)61 LayerChromium::LayerChromium(GraphicsLayerChromium* owner)
62     : m_owner(owner)
63     , m_contentsDirty(false)
64     , m_maskLayer(0)
65     , m_ccLayerImpl(0)
66     , m_superlayer(0)
67 #ifndef NDEBUG
68     , m_debugID(s_nextLayerDebugID++)
69 #endif
70     , m_anchorPoint(0.5, 0.5)
71     , m_backgroundColor(0, 0, 0, 0)
72     , m_opacity(1.0)
73     , m_zPosition(0.0)
74     , m_anchorPointZ(0)
75     , m_clearsContext(false)
76     , m_hidden(false)
77     , m_masksToBounds(false)
78     , m_opaque(true)
79     , m_geometryFlipped(false)
80     , m_needsDisplayOnBoundsChange(false)
81     , m_doubleSided(true)
82     , m_replicaLayer(0)
83 {
84 }
85 
~LayerChromium()86 LayerChromium::~LayerChromium()
87 {
88     // Our superlayer should be holding a reference to us so there should be no
89     // way for us to be destroyed while we still have a superlayer.
90     ASSERT(!superlayer());
91 
92     if (m_ccLayerImpl)
93         m_ccLayerImpl->resetOwner();
94 
95     // Remove the superlayer reference from all sublayers.
96     removeAllSublayers();
97 }
98 
cleanupResources()99 void LayerChromium::cleanupResources()
100 {
101     if (m_ccLayerImpl)
102         m_ccLayerImpl->cleanupResources();
103 }
104 
setLayerRenderer(LayerRendererChromium * renderer)105 void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer)
106 {
107     // If we're changing layer renderers then we need to free up any resources
108     // allocated by the old renderer.
109     if (layerRenderer() && layerRenderer() != renderer) {
110         cleanupResources();
111         setNeedsDisplay();
112     }
113     m_layerRenderer = renderer;
114 }
115 
setNeedsCommit()116 void LayerChromium::setNeedsCommit()
117 {
118     // Call notifySyncRequired(), which for non-root layers plumbs through to
119     // call setRootLayerNeedsDisplay() on the WebView, which will cause LayerRendererChromium
120     // to render a frame.
121     // This function has no effect on root layers.
122     if (m_owner)
123         m_owner->notifySyncRequired();
124 }
125 
addSublayer(PassRefPtr<LayerChromium> sublayer)126 void LayerChromium::addSublayer(PassRefPtr<LayerChromium> sublayer)
127 {
128     insertSublayer(sublayer, numSublayers());
129 }
130 
insertSublayer(PassRefPtr<LayerChromium> sublayer,size_t index)131 void LayerChromium::insertSublayer(PassRefPtr<LayerChromium> sublayer, size_t index)
132 {
133     index = min(index, m_sublayers.size());
134     sublayer->removeFromSuperlayer();
135     sublayer->setSuperlayer(this);
136     m_sublayers.insert(index, sublayer);
137     setNeedsCommit();
138 }
139 
removeFromSuperlayer()140 void LayerChromium::removeFromSuperlayer()
141 {
142     if (m_superlayer)
143         m_superlayer->removeSublayer(this);
144 }
145 
removeSublayer(LayerChromium * sublayer)146 void LayerChromium::removeSublayer(LayerChromium* sublayer)
147 {
148     int foundIndex = indexOfSublayer(sublayer);
149     if (foundIndex == -1)
150         return;
151 
152     sublayer->setSuperlayer(0);
153     m_sublayers.remove(foundIndex);
154     setNeedsCommit();
155 }
156 
replaceSublayer(LayerChromium * reference,PassRefPtr<LayerChromium> newLayer)157 void LayerChromium::replaceSublayer(LayerChromium* reference, PassRefPtr<LayerChromium> newLayer)
158 {
159     ASSERT_ARG(reference, reference);
160     ASSERT_ARG(reference, reference->superlayer() == this);
161 
162     if (reference == newLayer)
163         return;
164 
165     int referenceIndex = indexOfSublayer(reference);
166     if (referenceIndex == -1) {
167         ASSERT_NOT_REACHED();
168         return;
169     }
170 
171     reference->removeFromSuperlayer();
172 
173     if (newLayer) {
174         newLayer->removeFromSuperlayer();
175         insertSublayer(newLayer, referenceIndex);
176     }
177 }
178 
indexOfSublayer(const LayerChromium * reference)179 int LayerChromium::indexOfSublayer(const LayerChromium* reference)
180 {
181     for (size_t i = 0; i < m_sublayers.size(); i++) {
182         if (m_sublayers[i] == reference)
183             return i;
184     }
185     return -1;
186 }
187 
setBounds(const IntSize & size)188 void LayerChromium::setBounds(const IntSize& size)
189 {
190     if (bounds() == size)
191         return;
192 
193     bool firstResize = !bounds().width() && !bounds().height() && size.width() && size.height();
194 
195     m_bounds = size;
196 
197     if (firstResize)
198         setNeedsDisplay(FloatRect(0, 0, bounds().width(), bounds().height()));
199     else
200         setNeedsCommit();
201 }
202 
setFrame(const FloatRect & rect)203 void LayerChromium::setFrame(const FloatRect& rect)
204 {
205     if (rect == m_frame)
206       return;
207 
208     m_frame = rect;
209     setNeedsDisplay(FloatRect(0, 0, bounds().width(), bounds().height()));
210 }
211 
rootLayer() const212 const LayerChromium* LayerChromium::rootLayer() const
213 {
214     const LayerChromium* layer = this;
215     for (LayerChromium* superlayer = layer->superlayer(); superlayer; layer = superlayer, superlayer = superlayer->superlayer()) { }
216     return layer;
217 }
218 
removeAllSublayers()219 void LayerChromium::removeAllSublayers()
220 {
221     while (m_sublayers.size()) {
222         LayerChromium* layer = m_sublayers[0].get();
223         ASSERT(layer->superlayer());
224         layer->removeFromSuperlayer();
225     }
226 }
227 
setSublayers(const Vector<RefPtr<LayerChromium>> & sublayers)228 void LayerChromium::setSublayers(const Vector<RefPtr<LayerChromium> >& sublayers)
229 {
230     if (sublayers == m_sublayers)
231         return;
232 
233     removeAllSublayers();
234     size_t listSize = sublayers.size();
235     for (size_t i = 0; i < listSize; i++)
236         addSublayer(sublayers[i]);
237 }
238 
superlayer() const239 LayerChromium* LayerChromium::superlayer() const
240 {
241     return m_superlayer;
242 }
243 
setName(const String & name)244 void LayerChromium::setName(const String& name)
245 {
246     m_name = name;
247 }
248 
setNeedsDisplay(const FloatRect & dirtyRect)249 void LayerChromium::setNeedsDisplay(const FloatRect& dirtyRect)
250 {
251     // Simply mark the contents as dirty. For non-root layers, the call to
252     // setNeedsCommit will schedule a fresh compositing pass.
253     // For the root layer, setNeedsCommit has no effect.
254     m_contentsDirty = true;
255 
256     m_dirtyRect.unite(dirtyRect);
257     setNeedsCommit();
258 }
259 
setNeedsDisplay()260 void LayerChromium::setNeedsDisplay()
261 {
262     m_dirtyRect.setLocation(FloatPoint());
263     m_dirtyRect.setSize(bounds());
264     m_contentsDirty = true;
265     setNeedsCommit();
266 }
267 
resetNeedsDisplay()268 void LayerChromium::resetNeedsDisplay()
269 {
270     m_dirtyRect = FloatRect();
271     m_contentsDirty = false;
272 }
273 
toGLMatrix(float * flattened,const TransformationMatrix & m)274 void LayerChromium::toGLMatrix(float* flattened, const TransformationMatrix& m)
275 {
276     flattened[0] = m.m11();
277     flattened[1] = m.m12();
278     flattened[2] = m.m13();
279     flattened[3] = m.m14();
280     flattened[4] = m.m21();
281     flattened[5] = m.m22();
282     flattened[6] = m.m23();
283     flattened[7] = m.m24();
284     flattened[8] = m.m31();
285     flattened[9] = m.m32();
286     flattened[10] = m.m33();
287     flattened[11] = m.m34();
288     flattened[12] = m.m41();
289     flattened[13] = m.m42();
290     flattened[14] = m.m43();
291     flattened[15] = m.m44();
292 }
293 
pushPropertiesTo(CCLayerImpl * layer)294 void LayerChromium::pushPropertiesTo(CCLayerImpl* layer)
295 {
296     layer->setAnchorPoint(m_anchorPoint);
297     layer->setAnchorPointZ(m_anchorPointZ);
298     layer->setBounds(m_bounds);
299     layer->setDebugBorderColor(m_debugBorderColor);
300     layer->setDebugBorderWidth(m_debugBorderWidth);
301     layer->setDoubleSided(m_doubleSided);
302     layer->setLayerRenderer(m_layerRenderer.get());
303     layer->setMasksToBounds(m_masksToBounds);
304     layer->setName(m_name);
305     layer->setOpacity(m_opacity);
306     layer->setPosition(m_position);
307     layer->setPreserves3D(preserves3D());
308     layer->setSublayerTransform(m_sublayerTransform);
309     layer->setTransform(m_transform);
310 
311     if (maskLayer())
312         maskLayer()->pushPropertiesTo(layer->maskLayer());
313     if (replicaLayer())
314         replicaLayer()->pushPropertiesTo(layer->replicaLayer());
315 }
316 
layerRendererContext() const317 GraphicsContext3D* LayerChromium::layerRendererContext() const
318 {
319     ASSERT(layerRenderer());
320     return layerRenderer()->context();
321 }
322 
drawTexturedQuad(GraphicsContext3D * context,const TransformationMatrix & projectionMatrix,const TransformationMatrix & drawMatrix,float width,float height,float opacity,int matrixLocation,int alphaLocation)323 void LayerChromium::drawTexturedQuad(GraphicsContext3D* context, const TransformationMatrix& projectionMatrix, const TransformationMatrix& drawMatrix,
324                                      float width, float height, float opacity,
325                                      int matrixLocation, int alphaLocation)
326 {
327     static float glMatrix[16];
328 
329     TransformationMatrix renderMatrix = drawMatrix;
330 
331     // Apply a scaling factor to size the quad from 1x1 to its intended size.
332     renderMatrix.scale3d(width, height, 1);
333 
334     // Apply the projection matrix before sending the transform over to the shader.
335     toGLMatrix(&glMatrix[0], projectionMatrix * renderMatrix);
336 
337     GLC(context, context->uniformMatrix4fv(matrixLocation, false, &glMatrix[0], 1));
338 
339     if (alphaLocation != -1)
340         GLC(context, context->uniform1f(alphaLocation, opacity));
341 
342     GLC(context, context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0));
343 }
344 
layerTreeAsText() const345 String LayerChromium::layerTreeAsText() const
346 {
347     TextStream ts;
348     dumpLayer(ts, 0);
349     return ts.release();
350 }
351 
writeIndent(TextStream & ts,int indent)352 static void writeIndent(TextStream& ts, int indent)
353 {
354     for (int i = 0; i != indent; ++i)
355         ts << "  ";
356 }
357 
dumpLayer(TextStream & ts,int indent) const358 void LayerChromium::dumpLayer(TextStream& ts, int indent) const
359 {
360     writeIndent(ts, indent);
361     ts << layerTypeAsString() << "(" << m_name << ")\n";
362     dumpLayerProperties(ts, indent+2);
363     if (m_ccLayerImpl)
364         m_ccLayerImpl->dumpLayerProperties(ts, indent+2);
365     if (m_replicaLayer) {
366         writeIndent(ts, indent+2);
367         ts << "Replica:\n";
368         m_replicaLayer->dumpLayer(ts, indent+3);
369     }
370     if (m_maskLayer) {
371         writeIndent(ts, indent+2);
372         ts << "Mask:\n";
373         m_maskLayer->dumpLayer(ts, indent+3);
374     }
375     for (size_t i = 0; i < m_sublayers.size(); ++i)
376         m_sublayers[i]->dumpLayer(ts, indent+1);
377 }
378 
dumpLayerProperties(TextStream & ts,int indent) const379 void LayerChromium::dumpLayerProperties(TextStream& ts, int indent) const
380 {
381     writeIndent(ts, indent);
382 #ifndef NDEBUG
383     ts << "debugID: " << debugID() << ", ";
384 #else
385 #endif
386     ts << "drawsContent: " << drawsContent() << "\n";
387 
388 }
389 
createCCLayerImpl()390 PassRefPtr<CCLayerImpl> LayerChromium::createCCLayerImpl()
391 {
392     return CCLayerImpl::create(this);
393 }
394 
createCCLayerImplIfNeeded()395 void LayerChromium::createCCLayerImplIfNeeded()
396 {
397     if (!m_ccLayerImpl)
398         m_ccLayerImpl = createCCLayerImpl();
399 }
400 
ccLayerImpl()401 CCLayerImpl* LayerChromium::ccLayerImpl()
402 {
403     return m_ccLayerImpl.get();
404 }
405 
setBorderColor(const Color & color)406 void LayerChromium::setBorderColor(const Color& color)
407 {
408     m_debugBorderColor = color;
409     setNeedsCommit();
410 }
411 
setBorderWidth(float width)412 void LayerChromium::setBorderWidth(float width)
413 {
414     m_debugBorderWidth = width;
415     setNeedsCommit();
416 }
417 
layerRenderer() const418 LayerRendererChromium* LayerChromium::layerRenderer() const
419 {
420     return m_layerRenderer.get();
421 }
422 
423 }
424 #endif // USE(ACCELERATED_COMPOSITING)
425