[Texmap] LayoutTests/compositing/animation/state-at-end-event-transform-layer.html...
[WebKit-https.git] / Source / WebCore / platform / graphics / texmap / TextureMapperLayer.cpp
1 /*
2  Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
3
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  Library General Public License for more details.
13
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB.  If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "TextureMapperLayer.h"
22
23 #if USE(ACCELERATED_COMPOSITING)
24
25 namespace WebCore {
26
27 class TextureMapperPaintOptions {
28 public:
29     RefPtr<BitmapTexture> surface;
30     RefPtr<BitmapTexture> mask;
31     float opacity;
32     TransformationMatrix transform;
33     IntSize offset;
34     TextureMapper* textureMapper;
35     TextureMapperPaintOptions()
36         : opacity(1)
37         , textureMapper(0)
38     { }
39 };
40
41 const TextureMapperLayer* TextureMapperLayer::rootLayer() const
42 {
43     if (m_effectTarget)
44         return m_effectTarget->rootLayer();
45     if (m_parent)
46         return m_parent->rootLayer();
47     return this;
48 }
49
50 void TextureMapperLayer::computeTransformsRecursive()
51 {
52     if (m_state.size.isEmpty() && m_state.masksToBounds)
53         return;
54
55     // Compute transforms recursively on the way down to leafs.
56     TransformationMatrix parentTransform;
57     if (m_parent)
58         parentTransform = m_parent->m_currentTransform.combinedForChildren();
59     else if (m_effectTarget)
60         parentTransform = m_effectTarget->m_currentTransform.combined();
61     m_currentTransform.combineTransforms(parentTransform);
62
63     m_state.visible = m_state.backfaceVisibility || !m_currentTransform.combined().isBackFaceVisible();
64
65     if (m_parent && m_parent->m_state.preserves3D)
66         m_centerZ = m_currentTransform.combined().mapPoint(FloatPoint3D(m_state.size.width() / 2, m_state.size.height() / 2, 0)).z();
67
68     if (m_state.maskLayer)
69         m_state.maskLayer->computeTransformsRecursive();
70     if (m_state.replicaLayer)
71         m_state.replicaLayer->computeTransformsRecursive();
72     for (size_t i = 0; i < m_children.size(); ++i)
73         m_children[i]->computeTransformsRecursive();
74
75     // Reorder children if needed on the way back up.
76     if (m_state.preserves3D)
77         sortByZOrder(m_children, 0, m_children.size());
78 }
79
80 void TextureMapperLayer::paint()
81 {
82     computeTransformsRecursive();
83
84     TextureMapperPaintOptions options;
85     options.textureMapper = m_textureMapper;
86     options.textureMapper->bindSurface(0);
87     paintRecursive(options);
88 }
89
90 static Color blendWithOpacity(const Color& color, float opacity)
91 {
92     RGBA32 rgba = color.rgb();
93     // See Color::getRGBA() to know how to extract alpha from color.
94     float alpha = alphaChannel(rgba) / 255.;
95     float effectiveAlpha = alpha * opacity;
96     return Color(colorWithOverrideAlpha(rgba, effectiveAlpha));
97 }
98
99 void TextureMapperLayer::paintSelf(const TextureMapperPaintOptions& options)
100 {
101     if (!m_state.visible || !m_state.contentsVisible)
102         return;
103
104     // We apply the following transform to compensate for painting into a surface, and then apply the offset so that the painting fits in the target rect.
105     TransformationMatrix transform;
106     transform.translate(options.offset.width(), options.offset.height());
107     transform.multiply(options.transform);
108     transform.multiply(m_currentTransform.combined());
109
110     float opacity = options.opacity;
111     RefPtr<BitmapTexture> mask = options.mask;
112
113     if (m_state.solidColor.isValid() && !m_state.contentsRect.isEmpty()) {
114         options.textureMapper->drawSolidColor(m_state.contentsRect, transform, blendWithOpacity(m_state.solidColor, opacity));
115         if (m_state.showDebugBorders)
116             options.textureMapper->drawBorder(m_state.debugBorderColor, m_state.debugBorderWidth, layerRect(), transform);
117         return;
118     }
119
120     if (m_backingStore) {
121         ASSERT(m_state.drawsContent && m_state.contentsVisible && !m_state.size.isEmpty());
122         ASSERT(!layerRect().isEmpty());
123         m_backingStore->paintToTextureMapper(options.textureMapper, layerRect(), transform, opacity, mask.get());
124         if (m_state.showDebugBorders)
125             m_backingStore->drawBorder(options.textureMapper, m_state.debugBorderColor, m_state.debugBorderWidth, layerRect(), transform);
126         // Only draw repaint count for the main backing store.
127         if (m_state.showRepaintCounter)
128             m_backingStore->drawRepaintCounter(options.textureMapper, m_state.repaintCount, m_state.debugBorderColor, layerRect(), transform);
129     }
130
131     if (m_contentsLayer) {
132         ASSERT(!layerRect().isEmpty());
133         m_contentsLayer->paintToTextureMapper(options.textureMapper, m_state.contentsRect, transform, opacity, mask.get());
134         if (m_state.showDebugBorders)
135             m_contentsLayer->drawBorder(options.textureMapper, m_state.debugBorderColor, m_state.debugBorderWidth, m_state.contentsRect, transform);
136     }
137 }
138
139 int TextureMapperLayer::compareGraphicsLayersZValue(const void* a, const void* b)
140 {
141     TextureMapperLayer* const* layerA = static_cast<TextureMapperLayer* const*>(a);
142     TextureMapperLayer* const* layerB = static_cast<TextureMapperLayer* const*>(b);
143     return int(((*layerA)->m_centerZ - (*layerB)->m_centerZ) * 1000);
144 }
145
146 void TextureMapperLayer::sortByZOrder(Vector<TextureMapperLayer* >& array, int /* first */, int /* last */)
147 {
148     qsort(array.data(), array.size(), sizeof(TextureMapperLayer*), compareGraphicsLayersZValue);
149 }
150
151 void TextureMapperLayer::paintSelfAndChildren(const TextureMapperPaintOptions& options)
152 {
153     paintSelf(options);
154
155     if (m_children.isEmpty())
156         return;
157
158     bool shouldClip = m_state.masksToBounds && !m_state.preserves3D;
159     if (shouldClip)
160         options.textureMapper->beginClip(TransformationMatrix(options.transform).multiply(m_currentTransform.combined()), layerRect());
161
162     for (size_t i = 0; i < m_children.size(); ++i)
163         m_children[i]->paintRecursive(options);
164
165     if (shouldClip)
166         options.textureMapper->endClip();
167 }
168
169 IntRect TextureMapperLayer::intermediateSurfaceRect()
170 {
171     // FIXME: Add an inverse transform to LayerTransform.
172     return intermediateSurfaceRect(m_currentTransform.combined().inverse());
173 }
174
175 IntRect TextureMapperLayer::intermediateSurfaceRect(const TransformationMatrix& matrix)
176 {
177     IntRect rect;
178     TransformationMatrix localTransform = TransformationMatrix(matrix).multiply(m_currentTransform.combined());
179     rect = enclosingIntRect(localTransform.mapRect(layerRect()));
180     if (!m_state.masksToBounds && !m_state.maskLayer) {
181         for (size_t i = 0; i < m_children.size(); ++i)
182             rect.unite(m_children[i]->intermediateSurfaceRect(matrix));
183     }
184
185 #if ENABLE(CSS_FILTERS)
186     if (m_currentFilters.hasOutsets()) {
187         FilterOutsets outsets = m_currentFilters.outsets();
188         IntRect unfilteredTargetRect(rect);
189         rect.move(std::max(0, -outsets.left()), std::max(0, -outsets.top()));
190         rect.expand(outsets.left() + outsets.right(), outsets.top() + outsets.bottom());
191         rect.unite(unfilteredTargetRect);
192     }
193 #endif
194
195     if (m_state.replicaLayer)
196         rect.unite(m_state.replicaLayer->intermediateSurfaceRect(matrix));
197
198     return rect;
199 }
200
201 TextureMapperLayer::ContentsLayerCount TextureMapperLayer::countPotentialLayersWithContents() const
202 {
203     int selfLayersWithContents = (m_state.drawsContent ? 1 : 0) + (m_contentsLayer ? 1 : 0);
204     int potentialLayersWithContents = selfLayersWithContents + m_children.size();
205
206     if (!potentialLayersWithContents)
207         return NoLayersWithContent;
208
209     if (potentialLayersWithContents > 1)
210         return MultipleLayersWithContents;
211
212     if (m_children.isEmpty())
213         return SingleLayerWithContents;
214
215     return m_children.first()->countPotentialLayersWithContents();
216 }
217
218 bool TextureMapperLayer::shouldPaintToIntermediateSurface() const
219 {
220 #if ENABLE(CSS_FILTERS)
221     if (m_currentFilters.size())
222         return true;
223 #endif
224     bool hasOpacity = m_currentOpacity < 0.99;
225     bool canHaveMultipleLayersWithContent = countPotentialLayersWithContents() == MultipleLayersWithContents;
226     bool hasReplica = !!m_state.replicaLayer;
227     bool hasMask = !!m_state.maskLayer;
228
229     // We don't use two-pass blending for preserves-3d, that's in sync with Safari.
230     if (m_state.preserves3D)
231         return false;
232
233     // We should use an intermediate surface when blending several items with an ancestor opacity.
234     // Tested by compositing/reflections/reflection-opacity.html
235     if (hasOpacity && (canHaveMultipleLayersWithContent || hasReplica))
236         return true;
237
238     // We should use an intermediate surface with a masked ancestor.
239     // In the case of replicas the mask is applied before replicating.
240     // Tested by compositing/masks/masked-ancestor.html
241     if (hasMask && canHaveMultipleLayersWithContent && !hasReplica)
242         return true;
243
244     return false;
245 }
246
247 bool TextureMapperLayer::isVisible() const
248 {
249     if (m_state.size.isEmpty() && (m_state.masksToBounds || m_state.maskLayer || m_children.isEmpty()))
250         return false;
251     if (!m_state.visible && m_children.isEmpty())
252         return false;
253     if (!m_state.contentsVisible && m_children.isEmpty())
254         return false;
255     if (m_currentOpacity < 0.01)
256         return false;
257     return true;
258 }
259
260 void TextureMapperLayer::paintSelfAndChildrenWithReplica(const TextureMapperPaintOptions& options)
261 {
262     if (m_state.replicaLayer) {
263         TextureMapperPaintOptions replicaOptions(options);
264         // We choose either the content's mask or the replica's mask.
265         // FIXME: blend the two if both exist.
266         if (m_state.replicaLayer->m_state.maskLayer)
267             replicaOptions.mask = m_state.replicaLayer->m_state.maskLayer->texture();
268
269         replicaOptions.transform
270             .multiply(m_state.replicaLayer->m_currentTransform.combined())
271             .multiply(m_currentTransform.combined().inverse());
272         paintSelfAndChildren(replicaOptions);
273     }
274
275     paintSelfAndChildren(options);
276 }
277
278 void TextureMapperLayer::setAnimatedTransform(const TransformationMatrix& matrix)
279 {
280     m_currentTransform.setLocalTransform(matrix);
281 }
282
283 void TextureMapperLayer::setAnimatedOpacity(float opacity)
284 {
285     m_currentOpacity = opacity;
286 }
287
288 #if ENABLE(CSS_FILTERS)
289 void TextureMapperLayer::setAnimatedFilters(const FilterOperations& filters)
290 {
291     m_currentFilters = filters;
292 }
293
294 static bool shouldKeepContentTexture(const FilterOperations& filters)
295 {
296     for (size_t i = 0; i < filters.size(); ++i) {
297         switch (filters.operations().at(i)->getOperationType()) {
298         // The drop-shadow filter requires the content texture, because it needs to composite it
299         // on top of the blurred shadow color.
300         case FilterOperation::DROP_SHADOW:
301             return true;
302         default:
303             break;
304         }
305     }
306
307     return false;
308 }
309
310 static PassRefPtr<BitmapTexture> applyFilters(const FilterOperations& filters, TextureMapper* textureMapper, BitmapTexture* source, IntRect& targetRect)
311 {
312     if (!filters.size())
313         return source;
314
315     RefPtr<BitmapTexture> filterSurface = shouldKeepContentTexture(filters) ? textureMapper->acquireTextureFromPool(source->size()) : source;
316     return filterSurface->applyFilters(textureMapper, *source, filters);
317 }
318 #endif
319
320 void TextureMapperLayer::paintRecursive(const TextureMapperPaintOptions& options)
321 {
322     if (!isVisible())
323         return;
324
325     float opacity = options.opacity * m_currentOpacity;
326     RefPtr<BitmapTexture> maskTexture = m_state.maskLayer ? m_state.maskLayer->texture() : 0;
327
328     TextureMapperPaintOptions paintOptions(options);
329     paintOptions.mask = maskTexture.get();
330
331     if (!shouldPaintToIntermediateSurface()) {
332         paintOptions.opacity = opacity;
333         paintSelfAndChildrenWithReplica(paintOptions);
334         return;
335     }
336
337     // Prepare a surface to paint into.
338     // We paint into the surface ignoring the opacity/transform of the current layer.
339     IntRect surfaceRect = intermediateSurfaceRect();
340     RefPtr<BitmapTexture> surface = options.textureMapper->acquireTextureFromPool(surfaceRect.size());
341     paintOptions.surface = surface;
342     options.textureMapper->bindSurface(surface.get());
343     paintOptions.opacity = 1;
344
345     paintOptions.transform = m_currentTransform.combined().inverse();
346     paintOptions.offset = -IntSize(surfaceRect.x(), surfaceRect.y());
347
348     paintSelfAndChildrenWithReplica(paintOptions);
349
350     // If we painted the replica, the mask is already applied so we don't need to paint it again.
351     if (m_state.replicaLayer)
352         maskTexture = 0;
353
354 #if ENABLE(CSS_FILTERS)
355     surface = applyFilters(m_currentFilters, options.textureMapper, surface.get(), surfaceRect);
356 #endif
357
358     options.textureMapper->bindSurface(options.surface.get());
359     TransformationMatrix targetTransform;
360     targetTransform.translate(options.offset.width(), options.offset.height());
361     targetTransform.multiply(options.transform);
362     targetTransform.multiply(m_currentTransform.combined());
363
364     options.textureMapper->drawTexture(*surface.get(), surfaceRect, targetTransform, opacity, maskTexture.get());
365 }
366
367 TextureMapperLayer::~TextureMapperLayer()
368 {
369     for (int i = m_children.size() - 1; i >= 0; --i)
370         m_children[i]->m_parent = 0;
371
372     if (m_parent)
373         m_parent->m_children.remove(m_parent->m_children.find(this));
374 }
375
376 TextureMapper* TextureMapperLayer::textureMapper() const
377 {
378     return rootLayer()->m_textureMapper;
379 }
380
381 void TextureMapperLayer::setChildren(const Vector<TextureMapperLayer*>& newChildren)
382 {
383     removeAllChildren();
384     for (size_t i = 0; i < newChildren.size(); ++i)
385         addChild(newChildren[i]);
386 }
387
388 void TextureMapperLayer::addChild(TextureMapperLayer* childLayer)
389 {
390     ASSERT(childLayer != this);
391
392     if (childLayer->m_parent)
393         childLayer->removeFromParent();
394
395     childLayer->m_parent = this;
396     m_children.append(childLayer);
397 }
398
399 void TextureMapperLayer::removeFromParent()
400 {
401     if (m_parent) {
402         unsigned i;
403         for (i = 0; i < m_parent->m_children.size(); i++) {
404             if (this == m_parent->m_children[i]) {
405                 m_parent->m_children.remove(i);
406                 break;
407             }
408         }
409
410         m_parent = 0;
411     }
412 }
413
414 void TextureMapperLayer::removeAllChildren()
415 {
416     while (m_children.size()) {
417         TextureMapperLayer* curLayer = m_children[0];
418         ASSERT(curLayer->m_parent);
419         curLayer->removeFromParent();
420     }
421 }
422
423 void TextureMapperLayer::setMaskLayer(TextureMapperLayer* maskLayer)
424 {
425     if (maskLayer)
426         maskLayer->m_effectTarget = this;
427     m_state.maskLayer = maskLayer;
428 }
429
430 void TextureMapperLayer::setReplicaLayer(TextureMapperLayer* replicaLayer)
431 {
432     if (replicaLayer)
433         replicaLayer->m_effectTarget = this;
434     m_state.replicaLayer = replicaLayer;
435 }
436
437 void TextureMapperLayer::setPosition(const FloatPoint& position)
438 {
439     m_state.pos = position;
440     m_currentTransform.setPosition(adjustedPosition());
441 }
442
443 void TextureMapperLayer::setSize(const FloatSize& size)
444 {
445     m_state.size = size;
446     m_currentTransform.setSize(size);
447 }
448
449 void TextureMapperLayer::setAnchorPoint(const FloatPoint3D& anchorPoint)
450 {
451     m_state.anchorPoint = anchorPoint;
452     m_currentTransform.setAnchorPoint(anchorPoint);
453 }
454
455 void TextureMapperLayer::setPreserves3D(bool preserves3D)
456 {
457     m_state.preserves3D = preserves3D;
458     m_currentTransform.setFlattening(!preserves3D);
459 }
460
461 void TextureMapperLayer::setTransform(const TransformationMatrix& transform)
462 {
463     m_state.transform = transform;
464     m_currentTransform.setLocalTransform(transform);
465 }
466
467 void TextureMapperLayer::setChildrenTransform(const TransformationMatrix& childrenTransform)
468 {
469     m_state.childrenTransform = childrenTransform;
470     m_currentTransform.setChildrenTransform(childrenTransform);
471 }
472
473 void TextureMapperLayer::setContentsRect(const IntRect& contentsRect)
474 {
475     m_state.contentsRect = contentsRect;
476 }
477
478 void TextureMapperLayer::setMasksToBounds(bool masksToBounds)
479 {
480     m_state.masksToBounds = masksToBounds;
481 }
482
483 void TextureMapperLayer::setDrawsContent(bool drawsContent)
484 {
485     m_state.drawsContent = drawsContent;
486 }
487
488 void TextureMapperLayer::setContentsVisible(bool contentsVisible)
489 {
490     m_state.contentsVisible = contentsVisible;
491 }
492
493 void TextureMapperLayer::setContentsOpaque(bool contentsOpaque)
494 {
495     m_state.contentsOpaque = contentsOpaque;
496 }
497
498 void TextureMapperLayer::setBackfaceVisibility(bool backfaceVisibility)
499 {
500     m_state.backfaceVisibility = backfaceVisibility;
501 }
502
503 void TextureMapperLayer::setOpacity(float opacity)
504 {
505     m_state.opacity = opacity;
506 }
507
508 void TextureMapperLayer::setSolidColor(const Color& color)
509 {
510     m_state.solidColor = color;
511 }
512
513 #if ENABLE(CSS_FILTERS)
514 void TextureMapperLayer::setFilters(const FilterOperations& filters)
515 {
516     m_state.filters = filters;
517 }
518 #endif
519
520 void TextureMapperLayer::setDebugVisuals(bool showDebugBorders, const Color& debugBorderColor, float debugBorderWidth, bool showRepaintCounter)
521 {
522     m_state.showDebugBorders = showDebugBorders;
523     m_state.debugBorderColor = debugBorderColor;
524     m_state.debugBorderWidth = debugBorderWidth;
525     m_state.showRepaintCounter = showRepaintCounter;
526 }
527
528 void TextureMapperLayer::setRepaintCount(int repaintCount)
529 {
530     m_state.repaintCount = repaintCount;
531 }
532
533 void TextureMapperLayer::setContentsLayer(TextureMapperPlatformLayer* platformLayer)
534 {
535     m_contentsLayer = platformLayer;
536 }
537
538 void TextureMapperLayer::setAnimations(const GraphicsLayerAnimations& animations)
539 {
540     m_animations = animations;
541 }
542
543 void TextureMapperLayer::setFixedToViewport(bool fixedToViewport)
544 {
545     m_fixedToViewport = fixedToViewport;
546 }
547
548 void TextureMapperLayer::setBackingStore(PassRefPtr<TextureMapperBackingStore> backingStore)
549 {
550     m_backingStore = backingStore;
551 }
552
553 bool TextureMapperLayer::descendantsOrSelfHaveRunningAnimations() const
554 {
555     if (m_animations.hasRunningAnimations())
556         return true;
557
558     for (size_t i = 0; i < m_children.size(); ++i) {
559         if (m_children[i]->descendantsOrSelfHaveRunningAnimations())
560             return true;
561     }
562
563     return false;
564 }
565
566 void TextureMapperLayer::applyAnimationsRecursively()
567 {
568     syncAnimations();
569     for (size_t i = 0; i < m_children.size(); ++i)
570         m_children[i]->applyAnimationsRecursively();
571 }
572
573 void TextureMapperLayer::syncAnimations()
574 {
575     m_animations.apply(this);
576     if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitTransform))
577         m_currentTransform.setLocalTransform(m_state.transform);
578     if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyOpacity))
579         m_currentOpacity = m_state.opacity;
580
581 #if ENABLE(CSS_FILTERS)
582     if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitFilter))
583         m_currentFilters = m_state.filters;
584 #endif
585 }
586
587 bool TextureMapperLayer::isAncestorFixedToViewport() const
588 {
589     for (TextureMapperLayer* parent = m_parent; parent; parent = parent->m_parent) {
590         if (parent->m_fixedToViewport)
591             return true;
592     }
593
594     return false;
595 }
596
597 void TextureMapperLayer::setScrollPositionDeltaIfNeeded(const FloatSize& delta)
598 {
599     // delta is the difference between the scroll offset in the ui process and the scroll offset
600     // in the web process. We add this delta to the position of fixed layers, to make
601     // sure that they do not move while scrolling. We need to reset this delta to fixed layers
602     // that have an ancestor which is also a fixed layer, because the delta will be added to the ancestor.
603     if (isAncestorFixedToViewport())
604         m_scrollPositionDelta = FloatSize();
605     else
606         m_scrollPositionDelta = delta;
607     m_currentTransform.setPosition(adjustedPosition());
608 }
609
610 }
611 #endif