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