b21cbc1e4d7fdd137111afd52265b0bc19ee7f06
[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 #include "stdio.h"
24
25 #if USE(ACCELERATED_COMPOSITING)
26
27 #include "GraphicsLayerTextureMapper.h"
28 #include "ImageBuffer.h"
29 #include "MathExtras.h"
30
31 namespace WebCore {
32
33 TextureMapperLayer* toTextureMapperLayer(GraphicsLayer* layer)
34 {
35     return layer ? toGraphicsLayerTextureMapper(layer)->layer() : 0;
36 }
37
38 TextureMapperLayer* TextureMapperLayer::rootLayer()
39 {
40     if (m_effectTarget)
41         return m_effectTarget->rootLayer();
42     if (m_parent)
43         return m_parent->rootLayer();
44     return this;
45 }
46
47 void TextureMapperLayer::setTransform(const TransformationMatrix& matrix)
48 {
49     m_transform.setLocalTransform(matrix);
50 }
51
52 void TextureMapperLayer::clearBackingStoresRecursive()
53 {
54     m_backingStore.clear();
55     m_contentsLayer = 0;
56     for (size_t i = 0; i < m_children.size(); ++i)
57         m_children[i]->clearBackingStoresRecursive();
58     if (m_state.maskLayer)
59         m_state.maskLayer->clearBackingStoresRecursive();
60 }
61
62 void TextureMapperLayer::computeTransformsRecursive()
63 {
64     if (m_size.isEmpty() && m_state.masksToBounds)
65         return;
66
67     // Compute transforms recursively on the way down to leafs.
68     TransformationMatrix parentTransform;
69     if (m_parent)
70         parentTransform = m_parent->m_transform.combinedForChildren();
71     else if (m_effectTarget)
72         parentTransform = m_effectTarget->m_transform.combined();
73     m_transform.combineTransforms(parentTransform);
74
75     m_state.visible = m_state.backfaceVisibility || m_transform.combined().inverse().m33() >= 0;
76
77     if (m_parent && m_parent->m_state.preserves3D)
78         m_centerZ = m_transform.combined().mapPoint(FloatPoint3D(m_size.width() / 2, m_size.height() / 2, 0)).z();
79
80     if (m_state.maskLayer)
81         m_state.maskLayer->computeTransformsRecursive();
82     if (m_state.replicaLayer)
83         m_state.replicaLayer->computeTransformsRecursive();
84     for (size_t i = 0; i < m_children.size(); ++i)
85         m_children[i]->computeTransformsRecursive();
86
87     // Reorder children if needed on the way back up.
88     if (m_state.preserves3D)
89         sortByZOrder(m_children, 0, m_children.size());
90 }
91
92 void TextureMapperLayer::updateBackingStore(TextureMapper* textureMapper, GraphicsLayer* layer)
93 {
94     if (!layer || !textureMapper)
95         return;
96
97     if (!m_shouldUpdateBackingStoreFromLayer)
98         return;
99
100     if (!m_state.drawsContent || m_size.isEmpty()) {
101         m_backingStore.clear();
102         return;
103     }
104
105     IntRect dirtyRect = enclosingIntRect(m_state.needsDisplay ? layerRect() : m_state.needsDisplayRect);
106     if (dirtyRect.isEmpty())
107         return;
108
109     if (!m_backingStore)
110         m_backingStore = TextureMapperTiledBackingStore::create();
111
112     ASSERT(dynamic_cast<TextureMapperTiledBackingStore*>(m_backingStore.get()));
113
114     // Paint the entire dirty rect into an image buffer. This ensures we only paint once.
115     OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(dirtyRect.size());
116     GraphicsContext* context = imageBuffer->context();
117     context->setImageInterpolationQuality(textureMapper->imageInterpolationQuality());
118     context->setTextDrawingMode(textureMapper->textDrawingMode());
119     context->translate(-dirtyRect.x(), -dirtyRect.y());
120     layer->paintGraphicsLayerContents(*context, dirtyRect);
121
122     RefPtr<Image> image;
123
124 #if PLATFORM(QT)
125     image = imageBuffer->copyImage(DontCopyBackingStore);
126 #else
127     // FIXME: support DontCopyBackingStore in non-Qt ports that use TextureMapper.
128     image = imageBuffer->copyImage(CopyBackingStore);
129 #endif
130
131     static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get())->updateContents(textureMapper, image.get(), m_size, dirtyRect, BitmapTexture::BGRAFormat);
132 }
133
134 void TextureMapperLayer::paint()
135 {
136     computeTransformsRecursive();
137
138     TextureMapperPaintOptions options;
139     options.textureMapper = m_textureMapper;
140     options.textureMapper->bindSurface(0);
141     paintRecursive(options);
142 }
143
144 void TextureMapperLayer::paintSelf(const TextureMapperPaintOptions& options)
145 {
146     // 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.
147     TransformationMatrix transform =
148             TransformationMatrix(options.transform)
149             .multiply(m_transform.combined())
150             .translate(options.offset.width(), options.offset.height());
151
152     float opacity = options.opacity;
153     RefPtr<BitmapTexture> mask = options.mask;
154
155     if (m_backingStore)
156         m_backingStore->paintToTextureMapper(options.textureMapper, layerRect(), transform, opacity, mask.get());
157
158     if (m_contentsLayer)
159         m_contentsLayer->paintToTextureMapper(options.textureMapper, m_state.contentsRect, transform, opacity, mask.get());
160 }
161
162 int TextureMapperLayer::compareGraphicsLayersZValue(const void* a, const void* b)
163 {
164     TextureMapperLayer* const* layerA = static_cast<TextureMapperLayer* const*>(a);
165     TextureMapperLayer* const* layerB = static_cast<TextureMapperLayer* const*>(b);
166     return int(((*layerA)->m_centerZ - (*layerB)->m_centerZ) * 1000);
167 }
168
169 void TextureMapperLayer::sortByZOrder(Vector<TextureMapperLayer* >& array, int first, int last)
170 {
171     qsort(array.data(), array.size(), sizeof(TextureMapperLayer*), compareGraphicsLayersZValue);
172 }
173
174 void TextureMapperLayer::paintSelfAndChildren(const TextureMapperPaintOptions& options)
175 {
176     bool hasClip = m_state.masksToBounds && !m_children.isEmpty();
177     if (hasClip)
178         options.textureMapper->beginClip(TransformationMatrix(options.transform).multiply(m_transform.combined()), FloatRect(0, 0, m_size.width(), m_size.height()));
179
180     paintSelf(options);
181
182     for (size_t i = 0; i < m_children.size(); ++i)
183         m_children[i]->paintRecursive(options);
184
185     if (hasClip)
186         options.textureMapper->endClip();
187 }
188
189 IntRect TextureMapperLayer::intermediateSurfaceRect()
190 {
191     // FIXME: Add an inverse transform to LayerTransform.
192     return intermediateSurfaceRect(m_transform.combined().inverse());
193 }
194
195 IntRect TextureMapperLayer::intermediateSurfaceRect(const TransformationMatrix& matrix)
196 {
197     IntRect rect;
198     TransformationMatrix localTransform = TransformationMatrix(matrix).multiply(m_transform.combined());
199     rect = enclosingIntRect(localTransform.mapRect(layerRect()));
200     if (!m_state.masksToBounds && !m_state.maskLayer) {
201         for (size_t i = 0; i < m_children.size(); ++i)
202             rect.unite(m_children[i]->intermediateSurfaceRect(matrix));
203     }
204
205     if (m_state.replicaLayer)
206         rect.unite(m_state.replicaLayer->intermediateSurfaceRect(matrix));
207
208     return rect;
209 }
210
211 bool TextureMapperLayer::shouldPaintToIntermediateSurface() const
212 {
213 #if ENABLE(CSS_FILTERS)
214     if (m_state.filters.size())
215         return true;
216 #endif
217     bool hasOpacity = m_opacity < 0.99;
218     bool hasChildren = !m_children.isEmpty();
219     bool hasReplica = !!m_state.replicaLayer;
220     bool hasMask = !!m_state.maskLayer;
221
222     // We don't use two-pass blending for preserves-3d, that's in sync with Safari.
223     if (m_state.preserves3D)
224         return false;
225
226     // We should use an intermediate surface when blending several items with an ancestor opacity.
227     // Tested by compositing/reflections/reflection-opacity.html
228     if (hasOpacity && (hasChildren || hasReplica))
229         return true;
230
231     // We should use an intermediate surface with a masked ancestor.
232     // In the case of replicas the mask is applied before replicating.
233     // Tested by compositing/masks/masked-ancestor.html
234     if (hasMask && hasChildren && !hasReplica)
235         return true;
236
237     return false;
238 }
239
240 bool TextureMapperLayer::isVisible() const
241 {
242     if (m_size.isEmpty() && (m_state.masksToBounds || m_state.maskLayer || m_children.isEmpty()))
243         return false;
244     if (!m_state.visible || m_opacity < 0.01)
245         return false;
246     return true;
247 }
248
249 void TextureMapperLayer::paintSelfAndChildrenWithReplica(const TextureMapperPaintOptions& options)
250 {
251     if (m_state.replicaLayer) {
252         TextureMapperPaintOptions replicaOptions(options);
253         // We choose either the content's mask or the replica's mask.
254         // FIXME: blend the two if both exist.
255         if (m_state.replicaLayer->m_state.maskLayer)
256             replicaOptions.mask = m_state.replicaLayer->m_state.maskLayer->texture();
257
258         replicaOptions.transform
259                   .multiply(m_state.replicaLayer->m_transform.combined())
260                   .multiply(m_transform.combined().inverse());
261         paintSelfAndChildren(replicaOptions);
262     }
263
264     paintSelfAndChildren(options);
265 }
266
267 #if ENABLE(CSS_FILTERS)
268 static PassRefPtr<BitmapTexture> applyFilters(const FilterOperations& filters, TextureMapper* textureMapper, BitmapTexture* source, IntRect& targetRect)
269 {
270     if (!filters.size())
271         return source;
272
273     RefPtr<BitmapTexture> filterSurface(source);
274     int leftOutset, topOutset, bottomOutset, rightOutset;
275     if (filters.hasOutsets()) {
276         filters.getOutsets(topOutset, rightOutset, bottomOutset, leftOutset);
277         IntRect unfilteredTargetRect(targetRect);
278         targetRect.move(std::max(0, -leftOutset), std::max(0, -topOutset));
279         targetRect.expand(leftOutset + rightOutset, topOutset + bottomOutset);
280         targetRect.unite(unfilteredTargetRect);
281         filterSurface = textureMapper->acquireTextureFromPool(targetRect.size());
282     }
283
284     filterSurface->applyFilters(*source, filters);
285     return filterSurface;
286 }
287 #endif
288
289 void TextureMapperLayer::paintRecursive(const TextureMapperPaintOptions& options)
290 {
291     if (!isVisible())
292         return;
293
294     float opacity = options.opacity * m_opacity;
295     RefPtr<BitmapTexture> maskTexture = m_state.maskLayer ? m_state.maskLayer->texture() : 0;
296
297     TextureMapperPaintOptions paintOptions(options);
298     paintOptions.mask = maskTexture.get();
299     IntRect surfaceRect;
300
301     RefPtr<BitmapTexture> surface;
302
303     if (!shouldPaintToIntermediateSurface()) {
304         paintOptions.opacity = opacity;
305         paintSelfAndChildrenWithReplica(paintOptions);
306         return;
307     }
308
309     // Prepare a surface to paint into.
310     // We paint into the surface ignoring the opacity/transform of the current layer.
311     surfaceRect = intermediateSurfaceRect();
312     surface = options.textureMapper->acquireTextureFromPool(surfaceRect.size());
313     options.textureMapper->bindSurface(surface.get());
314     paintOptions.opacity = 1;
315
316     // We have to use combinedForChildren() and not combined(), otherwise preserve-3D doesn't work.
317     paintOptions.transform = m_transform.combinedForChildren().inverse();
318     paintOptions.offset = -IntSize(surfaceRect.x(), surfaceRect.y());
319
320     paintSelfAndChildrenWithReplica(paintOptions);
321
322     // If we painted the replica, the mask is already applied so we don't need to paint it again.
323     if (m_state.replicaLayer)
324         maskTexture = 0;
325
326 #if ENABLE(CSS_FILTERS)
327     surface = applyFilters(m_state.filters, options.textureMapper, surface.get(), surfaceRect);
328 #endif
329
330     options.textureMapper->bindSurface(options.surface.get());
331     TransformationMatrix targetTransform =
332             TransformationMatrix(options.transform)
333                 .multiply(m_transform.combined())
334                 .translate(options.offset.width(), options.offset.height());
335     options.textureMapper->drawTexture(*surface.get(), surfaceRect, targetTransform, opacity, maskTexture.get());
336 }
337
338 TextureMapperLayer::~TextureMapperLayer()
339 {
340     for (int i = m_children.size() - 1; i >= 0; --i)
341         m_children[i]->m_parent = 0;
342
343     if (m_parent)
344         m_parent->m_children.remove(m_parent->m_children.find(this));
345 }
346
347 void TextureMapperLayer::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, int options)
348 {
349     syncCompositingState(graphicsLayer, rootLayer()->m_textureMapper, options);
350 }
351
352 void TextureMapperLayer::syncCompositingStateSelf(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper)
353 {
354     int changeMask = graphicsLayer->changeMask();
355
356     if (changeMask == NoChanges && graphicsLayer->m_animations.isEmpty())
357         return;
358
359     if (changeMask & ParentChange) {
360         TextureMapperLayer* newParent = toTextureMapperLayer(graphicsLayer->parent());
361         if (newParent != m_parent) {
362             // Remove layer from current from child list first.
363             if (m_parent) {
364                 size_t index = m_parent->m_children.find(this);
365                 m_parent->m_children.remove(index);
366                 m_parent = 0;
367             }
368             // Set new layer parent and add layer to the parents child list.
369             if (newParent) {
370                 m_parent = newParent;
371                 m_parent->m_children.append(this);
372             }
373         }
374     }
375
376     if (changeMask & ChildrenChange) {
377         // Clear children parent pointer to avoid unsync and crash on layer delete.
378         for (size_t i = 0; i < m_children.size(); i++)
379             m_children[i]->m_parent = 0;
380
381         m_children.clear();
382         for (size_t i = 0; i < graphicsLayer->children().size(); ++i) {
383             TextureMapperLayer* child = toTextureMapperLayer(graphicsLayer->children()[i]);
384             if (!child)
385                 continue;
386             m_children.append(child);
387             child->m_parent = this;
388         }
389     }
390
391     m_size = graphicsLayer->size();
392
393     if (changeMask & MaskLayerChange) {
394        if (TextureMapperLayer* layer = toTextureMapperLayer(graphicsLayer->maskLayer()))
395            layer->m_effectTarget = this;
396     }
397
398     if (changeMask & ReplicaLayerChange) {
399        if (TextureMapperLayer* layer = toTextureMapperLayer(graphicsLayer->replicaLayer()))
400            layer->m_effectTarget = this;
401     }
402
403     if (changeMask & AnimationChange)
404         m_animations = graphicsLayer->m_animations;
405
406     m_state.maskLayer = toTextureMapperLayer(graphicsLayer->maskLayer());
407     m_state.replicaLayer = toTextureMapperLayer(graphicsLayer->replicaLayer());
408     m_state.pos = graphicsLayer->position();
409     m_state.anchorPoint = graphicsLayer->anchorPoint();
410     m_state.size = graphicsLayer->size();
411     m_state.contentsRect = graphicsLayer->contentsRect();
412     m_state.transform = graphicsLayer->transform();
413     m_state.contentsRect = graphicsLayer->contentsRect();
414     m_state.preserves3D = graphicsLayer->preserves3D();
415     m_state.masksToBounds = graphicsLayer->masksToBounds();
416     m_state.drawsContent = graphicsLayer->drawsContent();
417     m_state.contentsOpaque = graphicsLayer->contentsOpaque();
418     m_state.backfaceVisibility = graphicsLayer->backfaceVisibility();
419     m_state.childrenTransform = graphicsLayer->childrenTransform();
420     m_state.opacity = graphicsLayer->opacity();
421 #if ENABLE(CSS_FILTERS)
422     m_state.filters = graphicsLayer->filters();
423 #endif
424
425     m_state.needsDisplay = m_state.needsDisplay || graphicsLayer->needsDisplay();
426     if (!m_state.needsDisplay)
427         m_state.needsDisplayRect.unite(graphicsLayer->needsDisplayRect());
428     m_contentsLayer = graphicsLayer->contentsLayer();
429
430     m_transform.setPosition(m_state.pos);
431     m_transform.setAnchorPoint(m_state.anchorPoint);
432     m_transform.setSize(m_state.size);
433     m_transform.setFlattening(!m_state.preserves3D);
434     m_transform.setChildrenTransform(m_state.childrenTransform);
435 }
436
437 bool TextureMapperLayer::descendantsOrSelfHaveRunningAnimations() const
438 {
439     if (m_animations.hasRunningAnimations())
440         return true;
441
442     for (size_t i = 0; i < m_children.size(); ++i) {
443         if (m_children[i]->descendantsOrSelfHaveRunningAnimations())
444             return true;
445     }
446
447     return false;
448 }
449
450 void TextureMapperLayer::syncAnimations()
451 {
452     m_animations.apply(this);
453     if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitTransform))
454         setTransform(m_state.transform);
455     if (!m_animations.hasActiveAnimationsOfType(AnimatedPropertyOpacity))
456         setOpacity(m_state.opacity);
457 }
458
459 void TextureMapperLayer::syncAnimationsRecursively()
460 {
461     syncAnimations();
462
463     for (int i = m_children.size() - 1; i >= 0; --i)
464         m_children[i]->syncAnimationsRecursively();
465 }
466
467 void TextureMapperLayer::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper, int options)
468 {
469     if (!textureMapper)
470         return;
471
472     if (graphicsLayer && !(options & ComputationsOnly)) {
473         syncCompositingStateSelf(graphicsLayer, textureMapper);
474         graphicsLayer->didSynchronize();
475     }
476
477     if (graphicsLayer && m_state.maskLayer) {
478         m_state.maskLayer->syncCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->maskLayer()), textureMapper);
479
480         // A mask layer has its parent's size by default, in case it's not set specifically.
481         if (m_state.maskLayer->m_size.isEmpty())
482             m_state.maskLayer->m_size = m_size;
483     }
484
485     if (m_state.replicaLayer)
486         m_state.replicaLayer->syncCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->replicaLayer()), textureMapper);
487
488     syncAnimations();
489     updateBackingStore(textureMapper, graphicsLayer);
490
491     if (!(options & TraverseDescendants))
492         options = ComputationsOnly;
493
494     if (graphicsLayer) {
495         Vector<GraphicsLayer*> children = graphicsLayer->children();
496         for (int i = children.size() - 1; i >= 0; --i) {
497             TextureMapperLayer* layer = toTextureMapperLayer(children[i]);
498             if (!layer)
499                 continue;
500             layer->syncCompositingState(toGraphicsLayerTextureMapper(children[i]), textureMapper, options);
501         }
502     } else {
503         for (int i = m_children.size() - 1; i >= 0; --i)
504             m_children[i]->syncCompositingState(0, textureMapper, options);
505     }
506 }
507
508 }
509 #endif