tizen beta release
[profile/ivi/webkit-efl.git] / Source / WebCore / platform / graphics / texmap / TextureMapperNode.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 "TextureMapperNode.h"
22
23 #if USE(ACCELERATED_COMPOSITING)
24
25 #include "GraphicsLayerTextureMapper.h"
26 #include "MathExtras.h"
27
28 namespace {
29     static const float gTileDimension = 1024.0;
30 }
31
32 namespace WebCore {
33
34 class TextureMapperSurfaceManager {
35 public:
36     TextureMapper* textureMapper;
37     Vector<RefPtr<BitmapTexture> > surfaces;
38     IntSize viewportSize;
39
40     PassRefPtr<BitmapTexture> getIntermediateSurface()
41     {
42         IntSize newViewportSize = textureMapper->viewportSize();
43         if (newViewportSize != viewportSize) {
44             viewportSize = newViewportSize;
45             surfaces.clear();
46         }
47         if (surfaces.isEmpty()) {
48             RefPtr<BitmapTexture> newSurface = textureMapper->createTexture();
49             newSurface->reset(viewportSize, false);
50             return newSurface.get();
51         }
52         RefPtr<BitmapTexture> surface = surfaces.last();
53         surface->reset(viewportSize, false);
54         surfaces.removeLast();
55         surface->lock();
56         return surface.get();
57     }
58
59     void releaseIntermediateSurface(BitmapTexture* surface)
60     {
61         if (!surface)
62             return;
63         surfaces.append(surface);
64         surface->unlock();
65     }
66 };
67
68 TextureMapperNode* toTextureMapperNode(GraphicsLayer* layer)
69 {
70     return layer ? toGraphicsLayerTextureMapper(layer)->node() : 0;
71 }
72
73 TextureMapperNode* TextureMapperNode::rootLayer()
74 {
75     if (m_effectTarget)
76         return m_effectTarget->rootLayer();
77     if (m_parent)
78         return m_parent->rootLayer();
79     return this;
80 }
81
82 void TextureMapperNode::setTransform(const TransformationMatrix& matrix)
83 {
84     if (m_transforms.base == matrix)
85         return;
86
87     m_transforms.base = matrix;
88 }
89
90 void TextureMapperNode::computePerspectiveTransformIfNeeded()
91 {
92     if (m_children.isEmpty() || m_state.childrenTransform.isIdentity())
93         return;
94
95     const FloatPoint centerPoint = FloatPoint(m_size.width() / 2, m_size.height() / 2);
96     m_transforms.perspective = TransformationMatrix()
97             .translate(centerPoint.x(), centerPoint.y())
98             .multiply(m_state.childrenTransform)
99             .translate(-centerPoint.x(), -centerPoint.y());
100 }
101
102 int TextureMapperNode::countDescendantsWithContent() const
103 {
104     if (!m_state.visible || (!m_size.width() && !m_size.height() && m_state.masksToBounds))
105         return 0;
106     int count = (m_size.width() && m_size.height() && (m_state.drawsContent || m_currentContent.contentType != HTMLContentType)) ? 1 : 0;
107     for (size_t i = 0; i < m_children.size(); ++i)
108         count += m_children[i]->countDescendantsWithContent();
109
110     return count;
111 }
112
113 void TextureMapperNode::computeOverlapsIfNeeded()
114 {
115     m_state.mightHaveOverlaps = countDescendantsWithContent() > 1;
116 }
117
118 void TextureMapperNode::computeReplicaTransformIfNeeded()
119 {
120     if (!m_state.replicaLayer)
121         return;
122
123     m_transforms.replica =
124         TransformationMatrix(m_transforms.target)
125             .multiply(m_state.replicaLayer->m_transforms.local)
126             .multiply(TransformationMatrix(m_transforms.target).inverse());
127 }
128
129 void TextureMapperNode::computeLocalTransformIfNeeded()
130 {
131     float originX = m_state.anchorPoint.x() * m_size.width();
132     float originY = m_state.anchorPoint.y() * m_size.height();
133     m_transforms.local =
134         TransformationMatrix()
135         .translate3d(originX + m_state.pos.x(), originY + m_state.pos.y(), m_state.anchorPoint.z() )
136         .multiply(m_transforms.base)
137         .translate3d(-originX, -originY, -m_state.anchorPoint.z());
138 }
139
140 void TextureMapperNode::computeAllTransforms()
141 {
142 #if !ENABLE(TIZEN_WEBKIT2_TILED_AC)
143     if (m_size.isEmpty() && m_state.masksToBounds)
144         return;
145 #endif
146
147     computeLocalTransformIfNeeded();
148     computeReplicaTransformIfNeeded();
149     computePerspectiveTransformIfNeeded();
150
151     m_transforms.target = TransformationMatrix(m_parent ? m_parent->m_transforms.forDescendants : TransformationMatrix()).multiply(m_transforms.local);
152
153     m_state.visible = m_state.backfaceVisibility || m_transforms.target.inverse().m33() >= 0;
154     if (!m_state.visible)
155         return;
156
157     // This transform is only applied if using a two-pass for the replica, because the transform needs to be adjusted to the size of the intermediate surface, insteaf of the size of the content layer.
158     if (m_parent && m_parent->m_state.preserves3D)
159         m_transforms.centerZ = m_transforms.target.mapPoint(FloatPoint3D(m_size.width() / 2, m_size.height() / 2, 0)).z();
160
161     if (!m_children.size())
162         return;
163
164     m_transforms.forDescendants = m_transforms.target;
165
166     if (!m_state.preserves3D) {
167         m_transforms.forDescendants = TransformationMatrix(
168                     m_transforms.forDescendants.m11(), m_transforms.forDescendants.m12(), 0, m_transforms.forDescendants.m14(),
169                     m_transforms.forDescendants.m21(), m_transforms.forDescendants.m22(), 0, m_transforms.forDescendants.m24(),
170                     0, 0, 1, 0,
171                     m_transforms.forDescendants.m41(), m_transforms.forDescendants.m42(), 0, m_transforms.forDescendants.m44());
172     }
173
174     m_transforms.forDescendants.multiply(m_transforms.perspective);
175 }
176
177 void TextureMapperNode::computeTiles()
178 {
179 #if USE(TILED_BACKING_STORE)
180     if (m_state.tileOwnership == ExternallyManagedTiles)
181         return;
182 #endif
183     if (m_currentContent.contentType == HTMLContentType && !m_state.drawsContent) {
184         m_ownedTiles.clear();
185         return;
186     }
187     Vector<FloatRect> tilesToAdd;
188     Vector<int> tilesToRemove;
189     const int TileEraseThreshold = 6;
190     FloatSize size = contentSize();
191     FloatRect contentRect(0, 0, size.width(), size.height());
192
193     for (float y = 0; y < contentRect.height(); y += gTileDimension) {
194         for (float x = 0; x < contentRect.width(); x += gTileDimension) {
195             FloatRect tileRect(x, y, gTileDimension, gTileDimension);
196             tileRect.intersect(contentRect);
197             FloatRect tileRectInRootCoordinates = tileRect;
198             tileRectInRootCoordinates.scale(1.0);
199             tileRectInRootCoordinates = m_transforms.target.mapRect(tileRectInRootCoordinates);
200             tilesToAdd.append(tileRect);
201         }
202     }
203
204     for (int i = m_ownedTiles.size() - 1; i >= 0; --i) {
205         const FloatRect oldTile = m_ownedTiles[i].rect;
206         bool found = false;
207
208         for (int j = tilesToAdd.size() - 1; j >= 0; --j) {
209             const FloatRect newTile = tilesToAdd[j];
210             if (oldTile != newTile)
211                 continue;
212
213             found = true;
214             tilesToAdd.remove(j);
215             break;
216         }
217
218         if (!found)
219             tilesToRemove.append(i);
220     }
221
222     for (size_t i = 0; i < tilesToAdd.size(); ++i) {
223         if (!tilesToRemove.isEmpty()) {
224             OwnedTile& tile = m_ownedTiles[tilesToRemove[0]];
225             tilesToRemove.remove(0);
226             tile.rect = tilesToAdd[i];
227             tile.needsReset = true;
228             continue;
229         }
230
231         OwnedTile tile;
232         tile.rect = tilesToAdd[i];
233         tile.needsReset = true;
234         m_ownedTiles.append(tile);
235     }
236
237     for (size_t i = 0; i < tilesToRemove.size() && m_ownedTiles.size() > TileEraseThreshold; ++i)
238         m_ownedTiles.remove(tilesToRemove[i]);
239 }
240
241 #if USE(TILED_BACKING_STORE)
242 static void clampRect(IntRect& rect, int dimension)
243 {
244     rect.shiftXEdgeTo(rect.x() - rect.x() % dimension);
245     rect.shiftYEdgeTo(rect.y() - rect.y() % dimension);
246     rect.shiftMaxXEdgeTo(rect.maxX() - rect.x() % dimension + dimension);
247     rect.shiftMaxYEdgeTo(rect.maxY() - rect.y() % dimension + dimension);
248 }
249
250 bool TextureMapperNode::collectVisibleContentsRects(NodeRectMap& rectMap, const FloatRect& rootVisibleRect)
251 {
252     if (!m_state.visible)
253         return false;
254     bool exists = false;
255
256     for (int i = 0; i < m_children.size(); ++i)
257         exists = m_children[i]->collectVisibleContentsRects(rectMap, rootVisibleRect) || exists;
258     if (m_state.maskLayer)
259         exists = m_state.maskLayer->collectVisibleContentsRects(rectMap, rootVisibleRect) || exists;
260     if (m_state.replicaLayer)
261         exists = m_state.replicaLayer->collectVisibleContentsRects(rectMap, rootVisibleRect) || exists;
262
263     // Non-invertible layers are not visible.
264     if (!m_transforms.target.isInvertible())
265         return exists;
266
267     static const int tilingThreshold = 256;
268
269     IntRect visibleContentsRect(0, 0, m_size.width(), m_size.height());
270     if (m_size.width() > tilingThreshold || m_size.height() > tilingThreshold) {
271         IntRect visibleRectInLocalCoordinates = enclosingIntRect(TransformationMatrix(m_transforms.target).inverse().mapRect(rootVisibleRect));
272         if (!visibleRectInLocalCoordinates.isEmpty())
273             clampRect(visibleRectInLocalCoordinates, gTileDimension);
274         visibleContentsRect.intersect(visibleRectInLocalCoordinates);
275     }
276
277     if (visibleContentsRect.isEmpty() || visibleContentsRect == m_state.visibleRect)
278         return exists;
279
280     m_state.visibleRect = visibleContentsRect;
281     rectMap.add(this, m_state.visibleRect);
282
283     return true;
284 }
285 #endif
286
287 void TextureMapperNode::renderContent(TextureMapper* textureMapper, GraphicsLayer* layer)
288 {
289 #if USE(TILED_BACKING_STORE)
290     if (m_state.tileOwnership == ExternallyManagedTiles)
291         return;
292 #endif
293
294     if (m_size.isEmpty() || !layer || (!m_state.drawsContent && m_currentContent.contentType == HTMLContentType)) {
295         m_ownedTiles.clear();
296         return;
297     }
298
299     if (!textureMapper)
300         return;
301
302     // FIXME: Add directly composited images.
303     FloatRect dirtyRect = m_currentContent.needsDisplay ? entireRect() : m_currentContent.needsDisplayRect;
304
305     for (size_t tileIndex = 0; tileIndex < m_ownedTiles.size(); ++tileIndex) {
306         OwnedTile& tile = m_ownedTiles[tileIndex];
307         FloatRect rect = dirtyRect;
308         if (!tile.texture)
309             tile.texture = textureMapper->createTexture();
310         RefPtr<BitmapTexture>& texture = tile.texture;
311         IntSize tileSize = enclosingIntRect(tile.rect).size();
312
313         if (tile.needsReset || texture->contentSize() != tileSize || !texture->isValid()) {
314             tile.needsReset = false;
315             texture->reset(tileSize, m_currentContent.contentType == DirectImageContentType ? false : m_state.contentsOpaque);
316             rect = tile.rect;
317         }
318
319         IntRect contentRect = enclosingIntRect(tile.rect);
320         contentRect.intersect(enclosingIntRect(rect));
321         if (contentRect.isEmpty())
322             continue;
323
324         FloatRect contentRectInTileCoordinates = contentRect;
325         FloatPoint offset(-tile.rect.x(), -tile.rect.y());
326         contentRectInTileCoordinates.move(offset.x(), offset.y());
327
328         {
329             GraphicsContext context(texture->beginPaint(enclosingIntRect(contentRectInTileCoordinates)));
330             context.setImageInterpolationQuality(textureMapper->imageInterpolationQuality());
331             context.setTextDrawingMode(textureMapper->textDrawingMode());
332             context.translate(offset.x(), offset.y());
333             FloatRect scaledContentRect(contentRect);
334             if (m_currentContent.contentType == DirectImageContentType)
335                 context.drawImage(m_currentContent.image.get(), ColorSpaceDeviceRGB, IntPoint(0, 0));
336             else
337                 layer->paintGraphicsLayerContents(context, enclosingIntRect(scaledContentRect));
338             texture->endPaint();
339         }
340     }
341
342     m_currentContent.needsDisplay = false;
343     m_currentContent.needsDisplayRect = IntRect();
344 }
345
346 void TextureMapperNode::paint()
347 {
348     if (m_size.isEmpty())
349         return;
350
351     if (!m_surfaceManager)
352         m_surfaceManager = new TextureMapperSurfaceManager;
353     m_surfaceManager->textureMapper = m_textureMapper;
354     TextureMapperPaintOptions opt;
355     opt.surfaceManager = m_surfaceManager;
356     opt.textureMapper = m_textureMapper;
357     opt.textureMapper->bindSurface(0);
358     paintRecursive(opt);
359 }
360
361 FloatRect TextureMapperNode::targetRectForTileRect(const FloatRect& targetRect, const FloatRect& tileRect) const
362 {
363     return FloatRect(
364                 targetRect.x() + (tileRect.x() - targetRect.x()),
365                 targetRect.y() + (tileRect.y() - targetRect.y()),
366                 tileRect.width(),
367                 tileRect.height());
368 }
369
370 void TextureMapperNode::paintSelf(const TextureMapperPaintOptions& options)
371 {
372     if (m_size.isEmpty() || (!m_state.drawsContent && m_currentContent.contentType == HTMLContentType))
373         return;
374
375     RefPtr<BitmapTexture> maskTexture;
376     RefPtr<BitmapTexture> replicaMaskTexture;
377
378     if (m_state.maskLayer)
379         maskTexture = m_state.maskLayer->texture();
380     if (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer)
381         replicaMaskTexture = m_state.replicaLayer->m_state.maskLayer->texture();
382
383     float opacity = options.isSurface ? 1 : options.opacity;
384     FloatRect targetRect = this->targetRect();
385
386 #if USE(TILED_BACKING_STORE)
387     Vector<ExternallyManagedTile> tilesToPaint;
388
389     if (m_state.tileOwnership == ExternallyManagedTiles) {
390          // Sort tiles, with current scale factor last.
391         Vector<ExternallyManagedTile*> tiles;
392         HashMap<int, ExternallyManagedTile>::iterator end = m_externallyManagedTiles.end();
393         for (HashMap<int, ExternallyManagedTile>::iterator it = m_externallyManagedTiles.begin(); it != end; ++it) {
394             if (!it->second.frontBuffer.texture)
395                  continue;
396
397             if (it->second.scale == m_state.contentScale) {
398                   tiles.append(&it->second);
399                 continue;
400             }
401
402             // This creates a transitional effect looks good only when there's no transparency, so we only use it when the opacity for the layer is above a certain threshold.
403             if (opacity > 0.95)
404                  tiles.prepend(&it->second);
405         }
406
407         TransformationMatrix replicaMatrix;
408         for (int i = 0; i < tiles.size(); ++i) {
409             ExternallyManagedTile& tile = *tiles[i];
410             FloatRect rect = tile.frontBuffer.targetRect;
411
412             float replicaOpacity = 1.0;
413             if (m_state.replicaLayer) {
414                 replicaMatrix = TransformationMatrix(m_transforms.target).scale(1.0 / tile.scale).multiply(m_state.replicaLayer->m_transforms.local);
415                 replicaOpacity = opacity * m_state.replicaLayer->m_opacity;
416             }
417             BitmapTexture& texture = *tile.frontBuffer.texture;
418             if (m_state.replicaLayer)
419                 options.textureMapper->drawTexture(texture, rect, replicaMatrix, replicaOpacity, replicaMaskTexture ? replicaMaskTexture.get() :                 maskTexture.get());
420             options.textureMapper->drawTexture(texture, rect, m_transforms.target, opacity, options.isSurface ? 0 : maskTexture.get());
421         }
422         return;
423     }
424 #endif
425
426     // Now we paint owned tiles, if we're in OwnedTileMode.
427     for (size_t i = 0; i < m_ownedTiles.size(); ++i) {
428         BitmapTexture* texture = m_ownedTiles[i].texture.get();
429         if (m_state.replicaLayer && !options.isSurface) {
430             options.textureMapper->drawTexture(*texture, targetRectForTileRect(targetRect, m_ownedTiles[i].rect),
431                              TransformationMatrix(m_transforms.target).multiply(m_state.replicaLayer->m_transforms.local),
432                              opacity * m_state.replicaLayer->m_opacity,
433                              replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get());
434         }
435
436         const FloatRect rect = targetRectForTileRect(targetRect, m_ownedTiles[i].rect);
437         options.textureMapper->drawTexture(*texture, rect, m_transforms.target, opacity, options.isSurface ? 0 : maskTexture.get());
438     }
439 #if !ENABLE(TIZEN_WEBKIT2_TILED_AC)
440     if (m_currentContent.contentType == MediaContentType && m_currentContent.media) {
441         if (m_state.replicaLayer && !options.isSurface)
442             m_currentContent.media->paintToTextureMapper(options.textureMapper, targetRect,
443                                                          TransformationMatrix(m_transforms.target).multiply(m_state.replicaLayer->m_transforms.local),
444                                                          opacity * m_state.replicaLayer->m_opacity,
445                                                          replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get());
446         m_currentContent.media->paintToTextureMapper(options.textureMapper, targetRect, m_transforms.target, opacity, options.isSurface ? 0 : maskTexture.get());
447     }
448 #endif
449 }
450
451 int TextureMapperNode::compareGraphicsLayersZValue(const void* a, const void* b)
452 {
453     TextureMapperNode* const* nodeA = static_cast<TextureMapperNode* const*>(a);
454     TextureMapperNode* const* nodeB = static_cast<TextureMapperNode* const*>(b);
455     return int(((*nodeA)->m_transforms.centerZ - (*nodeB)->m_transforms.centerZ) * 1000);
456 }
457
458 void TextureMapperNode::sortByZOrder(Vector<TextureMapperNode* >& array, int first, int last)
459 {
460     qsort(array.data(), array.size(), sizeof(TextureMapperNode*), compareGraphicsLayersZValue);
461 }
462
463 void TextureMapperNode::paintSelfAndChildren(const TextureMapperPaintOptions& options, TextureMapperPaintOptions& optionsForDescendants)
464 {
465     bool hasClip = m_state.masksToBounds && !m_children.isEmpty();
466     if (hasClip)
467         options.textureMapper->beginClip(m_transforms.forDescendants, FloatRect(0, 0, m_size.width(), m_size.height()));
468
469     paintSelf(options);
470
471     for (int i = 0; i < m_children.size(); ++i)
472         m_children[i]->paintRecursive(optionsForDescendants);
473
474     if (hasClip)
475         options.textureMapper->endClip();
476 }
477
478 bool TextureMapperNode::paintReflection(const TextureMapperPaintOptions& options, BitmapTexture* contentSurface)
479 {
480     if (!m_state.replicaLayer)
481         return false;
482
483     RefPtr<BitmapTexture> surface(contentSurface);
484     RefPtr<BitmapTexture> maskSurface;
485     RefPtr<BitmapTexture> replicaMaskSurface;
486     RefPtr<BitmapTexture> replicaMaskTexture;
487
488     if (TextureMapperNode* replicaMask = m_state.replicaLayer->m_state.maskLayer)
489         replicaMaskTexture = replicaMask->texture();
490
491     RefPtr<BitmapTexture> maskTexture;
492     if (TextureMapperNode* mask = m_state.maskLayer)
493         maskTexture = mask->texture();
494
495     const IntSize viewportSize = options.textureMapper->viewportSize();
496     const bool useIntermediateBufferForReplica = m_state.replicaLayer && options.opacity < 0.99;
497     const bool useIntermediateBufferForMask = maskTexture && replicaMaskTexture;
498     const FloatRect viewportRect(0, 0, viewportSize.width(), viewportSize.height());
499
500     // The mask has to be adjusted to target coordinates.
501     if (maskTexture) {
502         maskSurface = options.surfaceManager->getIntermediateSurface();
503         options.textureMapper->bindSurface(maskSurface.get());
504         options.textureMapper->drawTexture(*maskTexture.get(), entireRect(), m_transforms.target, 1, 0);
505         maskTexture = maskSurface;
506     }
507
508     // The replica's mask has to be adjusted to target coordinates.
509     if (replicaMaskTexture) {
510         replicaMaskSurface = options.surfaceManager->getIntermediateSurface();
511         options.textureMapper->bindSurface(replicaMaskSurface.get());
512         options.textureMapper->drawTexture(*replicaMaskTexture.get(), entireRect(), m_transforms.target, 1, 0);
513         replicaMaskTexture = replicaMaskSurface;
514     }
515
516     // We might need to apply the mask of the content layer before we draw the reflection, as there might be yet another mask for the reflection itself.
517     if (useIntermediateBufferForMask) {
518         RefPtr<BitmapTexture> maskSurface = options.surfaceManager->getIntermediateSurface();
519         options.textureMapper->bindSurface(maskSurface.get());
520         options.textureMapper->drawTexture(*surface.get(), viewportRect, TransformationMatrix(), 1, maskTexture.get());
521         options.surfaceManager->releaseIntermediateSurface(surface.get());
522         surface = maskSurface;
523         maskTexture.clear();
524     }
525
526     // We blend the layer and its replica in an intermediate buffer before blending into the target surface.
527     if (useIntermediateBufferForReplica) {
528         RefPtr<BitmapTexture> replicaSurface = options.surfaceManager->getIntermediateSurface();
529         options.textureMapper->bindSurface(replicaSurface.get());
530         options.textureMapper->drawTexture(*surface.get(), viewportRect, m_transforms.replica, m_state.replicaLayer->m_opacity, replicaMaskTexture.get());
531         options.textureMapper->drawTexture(*surface.get(), viewportRect, TransformationMatrix(), 1, maskTexture.get());
532         options.surfaceManager->releaseIntermediateSurface(surface.get());
533         surface = replicaSurface;
534     }
535
536     options.textureMapper->bindSurface(options.surface);
537
538     // Draw the reflection.
539     if (!useIntermediateBufferForReplica)
540         options.textureMapper->drawTexture(*surface.get(), viewportRect, m_transforms.replica, m_state.replicaLayer->m_opacity, replicaMaskTexture.get());
541
542     // Draw the original.
543     options.textureMapper->drawTexture(*surface.get(), viewportRect, TransformationMatrix(), options.opacity, maskTexture.get());
544
545     options.surfaceManager->releaseIntermediateSurface(maskSurface.get());
546     options.surfaceManager->releaseIntermediateSurface(replicaMaskSurface.get());
547
548     return true;
549 }
550
551 void TextureMapperNode::paintRecursive(TextureMapperPaintOptions options)
552 {
553     if ((m_size.isEmpty() && (m_state.masksToBounds
554         || m_children.isEmpty())) || !m_state.visible || options.opacity < 0.01 || m_opacity < 0.01)
555         return;
556
557     options.opacity *= m_opacity;
558     RefPtr<BitmapTexture> surface;
559     const bool needsTwoPass = ((m_state.replicaLayer || m_state.maskLayer) && !m_children.isEmpty()) || (m_opacity < 0.99 && m_state.mightHaveOverlaps) || (m_opacity < 0.99 && m_state.replicaLayer);
560     const IntSize viewportSize = options.textureMapper->viewportSize();
561     options.isSurface = false;
562
563     TextureMapperPaintOptions optionsForDescendants(options);
564
565     if (!needsTwoPass) {
566         paintSelfAndChildren(options, optionsForDescendants);
567         return;
568     }
569
570     FloatRect viewportRect(0, 0, viewportSize.width(), viewportSize.height());
571
572     RefPtr<BitmapTexture> maskSurface;
573
574     // The mask has to be adjusted to target coordinates.
575     if (m_state.maskLayer) {
576         maskSurface = options.surfaceManager->getIntermediateSurface();
577         options.textureMapper->bindSurface(maskSurface.get());
578         options.textureMapper->drawTexture(*m_state.maskLayer->texture(), entireRect(), m_transforms.target, 1.0, 0);
579     }
580
581     surface = options.surfaceManager->getIntermediateSurface();
582     optionsForDescendants.surface = surface.get();
583     options.isSurface = true;
584     optionsForDescendants.opacity = 1;
585     options.textureMapper->bindSurface(surface.get());
586
587     paintSelfAndChildren(options, optionsForDescendants);
588
589     if (!paintReflection(options, surface.get())) {
590         options.textureMapper->bindSurface(options.surface);
591         options.textureMapper->drawTexture(*surface.get(), viewportRect, TransformationMatrix(), options.opacity, 0);
592     }
593
594     options.surfaceManager->releaseIntermediateSurface(surface.get());
595     options.surfaceManager->releaseIntermediateSurface(maskSurface.get());
596 }
597
598 TextureMapperNode::~TextureMapperNode()
599 {
600     for (int i = m_children.size() - 1; i >= 0; --i)
601         m_children[i]->m_parent = 0;
602
603     if (m_parent)
604         m_parent->m_children.remove(m_parent->m_children.find(this));
605 }
606
607 #if USE(TILED_BACKING_STORE)
608 int TextureMapperNode::createContentsTile(float scale)
609 {
610     static int nextID = 0;
611     int id = ++nextID;
612     m_externallyManagedTiles.add(id, ExternallyManagedTile(scale));
613     m_state.contentScale = scale;
614     return id;
615 }
616
617 void TextureMapperNode::removeContentsTile(int id)
618 {
619     m_externallyManagedTiles.remove(id);
620 }
621
622 void TextureMapperNode::purgeNodeTexturesRecursive()
623 {
624     m_externallyManagedTiles.clear();
625
626     for (int i = m_children.size() - 1; i >= 0; --i)
627         m_children[i]->purgeNodeTexturesRecursive();
628 }
629
630 void TextureMapperNode::setTileBackBufferTextureForDirectlyCompositedImage(int id, const IntRect& sourceRect, const FloatRect& targetRect, BitmapTexture* texture)
631 {
632     HashMap<int, ExternallyManagedTile>::iterator it = m_externallyManagedTiles.find(id);
633
634     if (it == m_externallyManagedTiles.end())
635         return;
636
637     ExternallyManagedTile& tile = it->second;
638
639     tile.backBuffer.sourceRect = sourceRect;
640     tile.backBuffer.targetRect = targetRect;
641     tile.backBuffer.texture = texture;
642     tile.isBackBufferUpdated = true;
643     tile.isDirectlyCompositedImage = true;
644 }
645
646 void TextureMapperNode::clearAllDirectlyCompositedImageTiles()
647 {
648     for (HashMap<int, ExternallyManagedTile>::iterator it = m_externallyManagedTiles.begin(); it != m_externallyManagedTiles.end(); ++it) {
649         if (it->second.isDirectlyCompositedImage)
650             m_externallyManagedTiles.remove(it);
651     }
652 }
653
654 void TextureMapperNode::setContentsTileBackBuffer(int id, const IntRect& sourceRect, const IntRect& targetRect, void* bits, BitmapTexture::PixelFormat format)
655 {
656     ASSERT(m_textureMapper);
657
658     HashMap<int, ExternallyManagedTile>::iterator it = m_externallyManagedTiles.find(id);
659     if (it == m_externallyManagedTiles.end())
660         return;
661
662     ExternallyManagedTile& tile = it->second;
663
664     tile.backBuffer.sourceRect = sourceRect;
665     tile.backBuffer.targetRect = FloatRect(targetRect);
666     tile.backBuffer.targetRect.scale(1.0 / tile.scale);
667
668     if (!tile.backBuffer.texture)
669         tile.backBuffer.texture = m_textureMapper->createTexture();
670     tile.backBuffer.texture->reset(sourceRect.size(), false);
671     tile.backBuffer.texture->updateContents(format, sourceRect, bits);
672     tile.isBackBufferUpdated = true;
673 }
674
675 void TextureMapperNode::swapContentsBuffers()
676 {
677     HashMap<int, ExternallyManagedTile>::iterator end = m_externallyManagedTiles.end();
678     for (HashMap<int, ExternallyManagedTile>::iterator it = m_externallyManagedTiles.begin(); it != end; ++it) {
679         ExternallyManagedTile& tile = it->second;
680         if (!tile.isBackBufferUpdated)
681             continue;
682         tile.isBackBufferUpdated = false;
683         ExternallyManagedTileBuffer swapBuffer = tile.frontBuffer;
684         tile.frontBuffer = tile.backBuffer;
685         tile.backBuffer = swapBuffer;
686     }
687 }
688 #endif
689
690 void TextureMapperNode::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, int options)
691 {
692     syncCompositingState(graphicsLayer, rootLayer()->m_textureMapper, options);
693 }
694
695 void TextureMapperNode::syncCompositingStateSelf(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper)
696 {
697     int changeMask = graphicsLayer->changeMask();
698     const TextureMapperNode::ContentData& pendingContent = graphicsLayer->pendingContent();
699 #if USE(TILED_BACKING_STORE)
700     swapContentsBuffers();
701 #endif
702     if (changeMask == NoChanges && graphicsLayer->m_animations.isEmpty() && pendingContent.needsDisplayRect.isEmpty() && !pendingContent.needsDisplay)
703         return;
704
705     if (m_currentContent.contentType == HTMLContentType && (changeMask & ParentChange)) {
706         TextureMapperNode* newParent = toTextureMapperNode(graphicsLayer->parent());
707         if (newParent != m_parent) {
708             // Remove node from current from child list first.
709             if (m_parent) {
710                 size_t index = m_parent->m_children.find(this);
711                 m_parent->m_children.remove(index);
712                 m_parent = 0;
713             }
714             // Set new node parent and add node to the parents child list.
715             if (newParent) {
716                 m_parent = newParent;
717                 m_parent->m_children.append(this);
718             }
719         }
720     }
721
722     if (changeMask & ChildrenChange) {
723         // Clear children parent pointer to avoid unsync and crash on node delete.
724         for (size_t i = 0; i < m_children.size(); i++)
725             m_children[i]->m_parent = 0;
726
727         m_children.clear();
728         for (size_t i = 0; i < graphicsLayer->children().size(); ++i) {
729             TextureMapperNode* child = toTextureMapperNode(graphicsLayer->children()[i]);
730             if (!child)
731                 continue;
732             m_children.append(child);
733             child->m_parent = this;
734         }
735     }
736
737     if (changeMask & (SizeChange | ContentsRectChange)) {
738         FloatSize wantedSize(graphicsLayer->size().width(), graphicsLayer->size().height());
739         if (wantedSize.isEmpty() && pendingContent.contentType == HTMLContentType)
740             wantedSize = FloatSize(graphicsLayer->contentsRect().width(), graphicsLayer->contentsRect().height());
741
742         if (wantedSize != m_size)
743             m_ownedTiles.clear();
744
745         m_size = wantedSize;
746     }
747
748     if (changeMask & MaskLayerChange) {
749        if (TextureMapperNode* layer = toTextureMapperNode(graphicsLayer->maskLayer()))
750            layer->m_effectTarget = this;
751     }
752
753     if (changeMask & ReplicaLayerChange) {
754        if (TextureMapperNode* layer = toTextureMapperNode(graphicsLayer->replicaLayer()))
755            layer->m_effectTarget = this;
756     }
757
758     if (changeMask & AnimationChange) {
759         m_animations.clear();
760         for (size_t i = 0; i < graphicsLayer->m_animations.size(); ++i)
761             m_animations.append(graphicsLayer->m_animations[i]);
762     }
763
764     m_state.maskLayer = toTextureMapperNode(graphicsLayer->maskLayer());
765     m_state.replicaLayer = toTextureMapperNode(graphicsLayer->replicaLayer());
766     m_state.pos = graphicsLayer->position();
767     m_state.anchorPoint = graphicsLayer->anchorPoint();
768     m_state.size = graphicsLayer->size();
769     m_state.contentsRect = graphicsLayer->contentsRect();
770     m_state.transform = graphicsLayer->transform();
771     m_state.contentsRect = graphicsLayer->contentsRect();
772     m_state.preserves3D = graphicsLayer->preserves3D();
773     m_state.masksToBounds = graphicsLayer->masksToBounds();
774     m_state.drawsContent = graphicsLayer->drawsContent();
775     m_state.contentsOpaque = graphicsLayer->contentsOpaque();
776     m_state.backfaceVisibility = graphicsLayer->backfaceVisibility();
777     m_state.childrenTransform = graphicsLayer->childrenTransform();
778     m_state.opacity = graphicsLayer->opacity();
779     m_currentContent.contentType = pendingContent.contentType;
780     m_currentContent.image = pendingContent.image;
781     m_currentContent.media = pendingContent.media;
782     m_currentContent.needsDisplay = m_currentContent.needsDisplay || pendingContent.needsDisplay;
783     if (!m_currentContent.needsDisplay)
784         m_currentContent.needsDisplayRect.unite(pendingContent.needsDisplayRect);
785
786     if (!hasOpacityAnimation())
787         m_opacity = m_state.opacity;
788     if (!hasTransformAnimation())
789         m_transforms.base = m_state.transform;
790 }
791
792 bool TextureMapperNode::descendantsOrSelfHaveRunningAnimations() const
793 {
794     for (size_t i = 0; i < m_animations.size(); ++i) {
795         if (!m_animations[i]->paused)
796             return true;
797     }
798
799     for (size_t i = 0; i < m_children.size(); ++i) {
800         if (m_children[i]->descendantsOrSelfHaveRunningAnimations())
801             return true;
802     }
803
804     return false;
805 }
806
807 static double normalizedAnimationValue(double runningTime, double duration, bool alternate)
808 {
809     if (!duration)
810         return 0;
811     const int loopCount = runningTime / duration;
812     const double lastFullLoop = duration * double(loopCount);
813     const double remainder = runningTime - lastFullLoop;
814     const double normalized = remainder / duration;
815     return (loopCount % 2 && alternate) ? (1 - normalized) : normalized;
816 }
817
818 void TextureMapperNode::applyOpacityAnimation(float fromOpacity, float toOpacity, double progress)
819 {
820     // Optimization: special case the edge values (0 and 1).
821     if (progress == 1.0)
822         setOpacity(toOpacity);
823     else if (!progress)
824         setOpacity(fromOpacity);
825     else
826         setOpacity(fromOpacity + progress * (toOpacity - fromOpacity));
827 }
828
829 static inline double solveEpsilon(double duration)
830 {
831     return 1.0 / (200.0 * duration);
832 }
833
834 static inline double solveCubicBezierFunction(double p1x, double p1y, double p2x, double p2y, double t, double duration)
835 {
836     UnitBezier bezier(p1x, p1y, p2x, p2y);
837     return bezier.solve(t, solveEpsilon(duration));
838 }
839
840 static inline double solveStepsFunction(int numSteps, bool stepAtStart, double t)
841 {
842     if (stepAtStart)
843 #if USE(TIZEN_TEXTURE_MAPPER)
844         return fmin(1.0, (floor(numSteps * t) + 1) / numSteps);
845 #else
846         return std::min(1.0, (floor(numSteps * t) + 1) / numSteps);
847 #endif
848     return floor(numSteps * t) / numSteps;
849 }
850
851 static inline float applyTimingFunction(const TimingFunction* timingFunction, float progress, double duration)
852 {
853     if (!timingFunction)
854         return progress;
855
856     if (timingFunction->isCubicBezierTimingFunction()) {
857         const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction);
858         return solveCubicBezierFunction(ctf->x1(),
859                                         ctf->y1(),
860                                         ctf->x2(),
861                                         ctf->y2(),
862                                         progress, duration);
863     }
864
865     if (timingFunction->isStepsTimingFunction()) {
866         const StepsTimingFunction* stf = static_cast<const StepsTimingFunction*>(timingFunction);
867         return solveStepsFunction(stf->numberOfSteps(), stf->stepAtStart(), double(progress));
868     }
869
870     return progress;
871 }
872
873 void TextureMapperNode::applyTransformAnimation(const TextureMapperAnimation& animation, const TransformOperations* from, const TransformOperations* to, double progress)
874 {
875     // Optimization: special case the edge values (0 and 1).
876     if (progress == 1.0 || !progress) {
877         TransformationMatrix matrix;
878         const TransformOperations* ops = progress ? to : from;
879         ops->apply(animation.boxSize, matrix);
880         setTransform(matrix);
881     }
882
883     if (!animation.listsMatch) {
884         TransformationMatrix toMatrix, fromMatrix;
885         to->apply(animation.boxSize, toMatrix);
886         from->apply(animation.boxSize, fromMatrix);
887         toMatrix.blend(fromMatrix, progress);
888         setTransform(toMatrix);
889         return;
890     }
891
892     TransformationMatrix matrix;
893
894     if (!to->size()) {
895         const TransformOperations* swap = to;
896         to = from;
897         from = swap;
898     } else if (!from->size())
899         progress = 1.0 - progress;
900
901     TransformOperations blended(*to);
902     for (size_t i = 0; i < animation.functionList.size(); ++i)
903         blended.operations()[i]->blend(from->at(i), progress, !from->at(i))->apply(matrix, animation.boxSize);
904
905     setTransform(matrix);
906 }
907
908 void TextureMapperNode::applyAnimationFrame(const TextureMapperAnimation& animation, const AnimationValue* from, const AnimationValue* to, float progress)
909 {
910     switch (animation.keyframes.property()) {
911     case AnimatedPropertyOpacity:
912         applyOpacityAnimation((static_cast<const FloatAnimationValue*>(from)->value()), (static_cast<const FloatAnimationValue*>(to)->value()), progress);
913         return;
914     case AnimatedPropertyWebkitTransform:
915         applyTransformAnimation(animation, static_cast<const TransformAnimationValue*>(from)->value(), static_cast<const TransformAnimationValue*>(to)->value(), progress);
916         return;
917     default:
918         ASSERT_NOT_REACHED();
919     }
920 }
921
922 void TextureMapperNode::applyAnimation(const TextureMapperAnimation& animation, double normalizedValue)
923 {
924     // Optimization: special case the edge values (0 and 1).
925     if (!normalizedValue) {
926         applyAnimationFrame(animation, animation.keyframes.at(0), animation.keyframes.at(1), 0);
927         return;
928     }
929     if (normalizedValue == 1.0) {
930         applyAnimationFrame(animation, animation.keyframes.at(animation.keyframes.size() - 2), animation.keyframes.at(animation.keyframes.size() - 1), 1);
931         return;
932     }
933     if (animation.keyframes.size() == 2) {
934         normalizedValue = applyTimingFunction(animation.animation->timingFunction().get(), normalizedValue, animation.animation->duration());
935         applyAnimationFrame(animation, animation.keyframes.at(0), animation.keyframes.at(1), normalizedValue);
936         return;
937     }
938
939     for (size_t i = 0; i < animation.keyframes.size() - 1; ++i) {
940         const AnimationValue* from = animation.keyframes.at(i);
941         const AnimationValue* to = animation.keyframes.at(i + 1);
942         if (from->keyTime() > normalizedValue || to->keyTime() < normalizedValue)
943             continue;
944
945         normalizedValue = (normalizedValue - from->keyTime()) / (to->keyTime() - from->keyTime());
946         normalizedValue = applyTimingFunction(from->timingFunction(), normalizedValue, animation.animation->duration());
947         applyAnimationFrame(animation, from, to, normalizedValue);
948         break;
949     }
950 }
951
952 bool TextureMapperNode::hasOpacityAnimation() const
953 {
954     for (size_t i = 0; i < m_animations.size(); ++i) {
955         const TextureMapperAnimation& animation = *m_animations[i].get();
956         if (animation.keyframes.property() == AnimatedPropertyOpacity)
957             return true;
958     }
959     return false;
960 }
961
962 bool TextureMapperNode::hasTransformAnimation() const
963 {
964     for (size_t i = 0; i < m_animations.size(); ++i) {
965         const TextureMapperAnimation& animation = *m_animations[i].get();
966         if (animation.keyframes.property() == AnimatedPropertyWebkitTransform)
967             return true;
968     }
969     return false;
970 }
971
972 void TextureMapperNode::syncAnimations(GraphicsLayerTextureMapper* layer)
973 {
974     for (int i = m_animations.size() - 1; i >= 0; --i) {
975         RefPtr<TextureMapperAnimation> animation = m_animations[i];
976
977         double totalRunningTime = WTF::currentTime() - animation->startTime;
978         RefPtr<Animation> anim = animation->animation;
979         double normalizedValue = normalizedAnimationValue(totalRunningTime, anim->duration(), anim->direction());
980
981         if (anim->iterationCount() != Animation::IterationCountInfinite && totalRunningTime >= anim->duration() * anim->iterationCount()) {
982             // We apply an animation that very close to the edge, so that the final frame is applied, oterwise we might get, for example, an opacity of 0.01 which is still visible.
983             if (anim->fillsForwards()) {
984                 if (animation->keyframes.property() == AnimatedPropertyWebkitTransform)
985                     m_state.transform = m_transforms.base;
986                 else if (animation->keyframes.property() == AnimatedPropertyOpacity)
987                     m_opacity = m_state.opacity;
988             }
989
990             m_animations.remove(i);
991             continue;
992         }
993
994         if (!animation->paused)
995             applyAnimation(*animation.get(), normalizedValue);
996     }
997 }
998
999 void TextureMapperNode::syncAnimationsRecursively()
1000 {
1001     syncAnimations(0);
1002
1003     computeAllTransforms();
1004
1005     for (int i = m_children.size() - 1; i >= 0; --i)
1006         m_children[i]->syncAnimationsRecursively();
1007 }
1008
1009 void TextureMapperNode::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper, int options)
1010 {
1011     if (graphicsLayer && !(options & ComputationsOnly)) {
1012         syncCompositingStateSelf(graphicsLayer, textureMapper);
1013         graphicsLayer->didSynchronize();
1014     }
1015
1016     if (graphicsLayer && m_state.maskLayer) {
1017         m_state.maskLayer->syncCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->maskLayer()), textureMapper);
1018
1019         // A mask layer has its parent's size by default, in case it's not set specifically.
1020         if (m_state.maskLayer->m_size.isEmpty())
1021             m_state.maskLayer->m_size = m_size;
1022     }
1023
1024     if (m_state.replicaLayer)
1025         m_state.replicaLayer->syncCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->replicaLayer()), textureMapper);
1026
1027     syncAnimations(graphicsLayer);
1028
1029     computeAllTransforms();
1030     computeTiles();
1031     computeOverlapsIfNeeded();
1032
1033     if (graphicsLayer)
1034         renderContent(textureMapper, graphicsLayer);
1035
1036     if (!(options & TraverseDescendants))
1037         options = ComputationsOnly;
1038
1039     if (graphicsLayer) {
1040         Vector<GraphicsLayer*> children = graphicsLayer->children();
1041         for (int i = children.size() - 1; i >= 0; --i) {
1042             TextureMapperNode* node = toTextureMapperNode(children[i]);
1043             if (!node)
1044                 continue;
1045             node->syncCompositingState(toGraphicsLayerTextureMapper(children[i]), textureMapper, options);
1046         }
1047     } else {
1048         for (int i = m_children.size() - 1; i >= 0; --i)
1049             m_children[i]->syncCompositingState(0, textureMapper, options);
1050     }
1051
1052     if (m_state.preserves3D)
1053         sortByZOrder(m_children, 0, m_children.size());
1054 }
1055
1056 TextureMapperAnimation::TextureMapperAnimation(const KeyframeValueList& values)
1057     : keyframes(values)
1058 {
1059 }
1060
1061 #if ENABLE(TIZEN_WEBKIT2_TILED_AC)
1062 bool TextureMapperNode::collectVisibleContentRects(NodeRectMap& rectMap, const FloatRect& rootVisibleRect)
1063 {
1064     if (!m_state.visible || m_state.opacity < 0.01)
1065         return false;
1066     bool found = false;
1067
1068     for (int i = 0; i < m_children.size(); ++i)
1069         found = m_children[i]->collectVisibleContentRects(rectMap, rootVisibleRect) || found;
1070     if (m_state.maskLayer)
1071         found = m_state.maskLayer->collectVisibleContentRects(rectMap, rootVisibleRect) || found;
1072     if (m_state.replicaLayer)
1073         found = m_state.replicaLayer->collectVisibleContentRects(rectMap, rootVisibleRect) || found;
1074
1075     if (!m_transforms.target.isInvertible())
1076         return found;
1077
1078     IntRect visibleContentsRect(0, 0, m_size.width(), m_size.height());
1079     if (visibleContentsRect == m_state.visibleRect)
1080         return found;
1081
1082     m_state.visibleRect = visibleContentsRect;
1083     rectMap.add(this, m_state.visibleRect);
1084
1085     return true;
1086 }
1087 #endif
1088 #endif
1089
1090 };