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