2 Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
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.
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.
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.
21 #include "TextureMapperNode.h"
23 #if USE(ACCELERATED_COMPOSITING)
25 #include "GraphicsLayerTextureMapper.h"
26 #include "MathExtras.h"
29 static const float gTileDimension = 1024.0;
34 class TextureMapperSurfaceManager {
36 TextureMapper* textureMapper;
37 Vector<RefPtr<BitmapTexture> > surfaces;
40 PassRefPtr<BitmapTexture> getIntermediateSurface()
42 IntSize newViewportSize = textureMapper->viewportSize();
43 if (newViewportSize != viewportSize) {
44 viewportSize = newViewportSize;
47 if (surfaces.isEmpty()) {
48 RefPtr<BitmapTexture> newSurface = textureMapper->createTexture();
49 newSurface->reset(viewportSize, false);
50 return newSurface.get();
52 RefPtr<BitmapTexture> surface = surfaces.last();
53 surface->reset(viewportSize, false);
54 surfaces.removeLast();
59 void releaseIntermediateSurface(BitmapTexture* surface)
63 surfaces.append(surface);
68 TextureMapperNode* toTextureMapperNode(GraphicsLayer* layer)
70 return layer ? toGraphicsLayerTextureMapper(layer)->node() : 0;
73 TextureMapperNode* TextureMapperNode::rootLayer()
76 return m_effectTarget->rootLayer();
78 return m_parent->rootLayer();
82 void TextureMapperNode::setTransform(const TransformationMatrix& matrix)
84 if (m_transforms.base == matrix)
87 m_transforms.base = matrix;
90 void TextureMapperNode::computePerspectiveTransformIfNeeded()
92 if (m_children.isEmpty() || m_state.childrenTransform.isIdentity())
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());
102 int TextureMapperNode::countDescendantsWithContent() const
104 if (!m_state.visible || (!m_size.width() && !m_size.height() && m_state.masksToBounds))
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();
113 void TextureMapperNode::computeOverlapsIfNeeded()
115 m_state.mightHaveOverlaps = countDescendantsWithContent() > 1;
118 void TextureMapperNode::computeReplicaTransformIfNeeded()
120 if (!m_state.replicaLayer)
123 m_transforms.replica =
124 TransformationMatrix(m_transforms.target)
125 .multiply(m_state.replicaLayer->m_transforms.local)
126 .multiply(TransformationMatrix(m_transforms.target).inverse());
129 void TextureMapperNode::computeLocalTransformIfNeeded()
131 float originX = m_state.anchorPoint.x() * m_size.width();
132 float originY = m_state.anchorPoint.y() * m_size.height();
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());
140 void TextureMapperNode::computeAllTransforms()
142 #if !ENABLE(TIZEN_WEBKIT2_TILED_AC)
143 if (m_size.isEmpty() && m_state.masksToBounds)
147 computeLocalTransformIfNeeded();
148 computeReplicaTransformIfNeeded();
149 computePerspectiveTransformIfNeeded();
151 m_transforms.target = TransformationMatrix(m_parent ? m_parent->m_transforms.forDescendants : TransformationMatrix()).multiply(m_transforms.local);
153 m_state.visible = m_state.backfaceVisibility || m_transforms.target.inverse().m33() >= 0;
154 if (!m_state.visible)
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();
161 if (!m_children.size())
164 m_transforms.forDescendants = m_transforms.target;
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(),
171 m_transforms.forDescendants.m41(), m_transforms.forDescendants.m42(), 0, m_transforms.forDescendants.m44());
174 m_transforms.forDescendants.multiply(m_transforms.perspective);
177 void TextureMapperNode::computeTiles()
179 #if USE(TILED_BACKING_STORE)
180 if (m_state.tileOwnership == ExternallyManagedTiles)
183 if (m_currentContent.contentType == HTMLContentType && !m_state.drawsContent) {
184 m_ownedTiles.clear();
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());
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);
204 for (int i = m_ownedTiles.size() - 1; i >= 0; --i) {
205 const FloatRect oldTile = m_ownedTiles[i].rect;
208 for (int j = tilesToAdd.size() - 1; j >= 0; --j) {
209 const FloatRect newTile = tilesToAdd[j];
210 if (oldTile != newTile)
214 tilesToAdd.remove(j);
219 tilesToRemove.append(i);
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;
232 tile.rect = tilesToAdd[i];
233 tile.needsReset = true;
234 m_ownedTiles.append(tile);
237 for (size_t i = 0; i < tilesToRemove.size() && m_ownedTiles.size() > TileEraseThreshold; ++i)
238 m_ownedTiles.remove(tilesToRemove[i]);
241 #if USE(TILED_BACKING_STORE)
242 static void clampRect(IntRect& rect, int dimension)
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);
250 bool TextureMapperNode::collectVisibleContentsRects(NodeRectMap& rectMap, const FloatRect& rootVisibleRect)
252 if (!m_state.visible)
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;
263 // Non-invertible layers are not visible.
264 if (!m_transforms.target.isInvertible())
267 static const int tilingThreshold = 256;
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);
277 if (visibleContentsRect.isEmpty() || visibleContentsRect == m_state.visibleRect)
280 m_state.visibleRect = visibleContentsRect;
281 rectMap.add(this, m_state.visibleRect);
287 void TextureMapperNode::renderContent(TextureMapper* textureMapper, GraphicsLayer* layer)
289 #if USE(TILED_BACKING_STORE)
290 if (m_state.tileOwnership == ExternallyManagedTiles)
294 if (m_size.isEmpty() || !layer || (!m_state.drawsContent && m_currentContent.contentType == HTMLContentType)) {
295 m_ownedTiles.clear();
302 // FIXME: Add directly composited images.
303 FloatRect dirtyRect = m_currentContent.needsDisplay ? entireRect() : m_currentContent.needsDisplayRect;
305 for (size_t tileIndex = 0; tileIndex < m_ownedTiles.size(); ++tileIndex) {
306 OwnedTile& tile = m_ownedTiles[tileIndex];
307 FloatRect rect = dirtyRect;
309 tile.texture = textureMapper->createTexture();
310 RefPtr<BitmapTexture>& texture = tile.texture;
311 IntSize tileSize = enclosingIntRect(tile.rect).size();
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);
319 IntRect contentRect = enclosingIntRect(tile.rect);
320 contentRect.intersect(enclosingIntRect(rect));
321 if (contentRect.isEmpty())
324 FloatRect contentRectInTileCoordinates = contentRect;
325 FloatPoint offset(-tile.rect.x(), -tile.rect.y());
326 contentRectInTileCoordinates.move(offset.x(), offset.y());
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));
337 layer->paintGraphicsLayerContents(context, enclosingIntRect(scaledContentRect));
342 m_currentContent.needsDisplay = false;
343 m_currentContent.needsDisplayRect = IntRect();
346 void TextureMapperNode::paint()
348 if (m_size.isEmpty())
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);
361 FloatRect TextureMapperNode::targetRectForTileRect(const FloatRect& targetRect, const FloatRect& tileRect) const
364 targetRect.x() + (tileRect.x() - targetRect.x()),
365 targetRect.y() + (tileRect.y() - targetRect.y()),
370 void TextureMapperNode::paintSelf(const TextureMapperPaintOptions& options)
372 if (m_size.isEmpty() || (!m_state.drawsContent && m_currentContent.contentType == HTMLContentType))
375 RefPtr<BitmapTexture> maskTexture;
376 RefPtr<BitmapTexture> replicaMaskTexture;
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();
383 float opacity = options.isSurface ? 1 : options.opacity;
384 FloatRect targetRect = this->targetRect();
386 #if USE(TILED_BACKING_STORE)
387 Vector<ExternallyManagedTile> tilesToPaint;
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)
397 if (it->second.scale == m_state.contentScale) {
398 tiles.append(&it->second);
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.
404 tiles.prepend(&it->second);
407 TransformationMatrix replicaMatrix;
408 for (int i = 0; i < tiles.size(); ++i) {
409 ExternallyManagedTile& tile = *tiles[i];
410 FloatRect rect = tile.frontBuffer.targetRect;
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;
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());
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());
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());
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());
451 int TextureMapperNode::compareGraphicsLayersZValue(const void* a, const void* b)
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);
458 void TextureMapperNode::sortByZOrder(Vector<TextureMapperNode* >& array, int first, int last)
460 qsort(array.data(), array.size(), sizeof(TextureMapperNode*), compareGraphicsLayersZValue);
463 void TextureMapperNode::paintSelfAndChildren(const TextureMapperPaintOptions& options, TextureMapperPaintOptions& optionsForDescendants)
465 bool hasClip = m_state.masksToBounds && !m_children.isEmpty();
467 options.textureMapper->beginClip(m_transforms.forDescendants, FloatRect(0, 0, m_size.width(), m_size.height()));
471 for (int i = 0; i < m_children.size(); ++i)
472 m_children[i]->paintRecursive(optionsForDescendants);
475 options.textureMapper->endClip();
478 bool TextureMapperNode::paintReflection(const TextureMapperPaintOptions& options, BitmapTexture* contentSurface)
480 if (!m_state.replicaLayer)
483 RefPtr<BitmapTexture> surface(contentSurface);
484 RefPtr<BitmapTexture> maskSurface;
485 RefPtr<BitmapTexture> replicaMaskSurface;
486 RefPtr<BitmapTexture> replicaMaskTexture;
488 if (TextureMapperNode* replicaMask = m_state.replicaLayer->m_state.maskLayer)
489 replicaMaskTexture = replicaMask->texture();
491 RefPtr<BitmapTexture> maskTexture;
492 if (TextureMapperNode* mask = m_state.maskLayer)
493 maskTexture = mask->texture();
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());
500 // The mask has to be adjusted to target coordinates.
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;
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;
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;
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;
536 options.textureMapper->bindSurface(options.surface);
538 // Draw the reflection.
539 if (!useIntermediateBufferForReplica)
540 options.textureMapper->drawTexture(*surface.get(), viewportRect, m_transforms.replica, m_state.replicaLayer->m_opacity, replicaMaskTexture.get());
542 // Draw the original.
543 options.textureMapper->drawTexture(*surface.get(), viewportRect, TransformationMatrix(), options.opacity, maskTexture.get());
545 options.surfaceManager->releaseIntermediateSurface(maskSurface.get());
546 options.surfaceManager->releaseIntermediateSurface(replicaMaskSurface.get());
551 void TextureMapperNode::paintRecursive(TextureMapperPaintOptions options)
553 if ((m_size.isEmpty() && (m_state.masksToBounds
554 || m_children.isEmpty())) || !m_state.visible || options.opacity < 0.01 || m_opacity < 0.01)
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;
563 TextureMapperPaintOptions optionsForDescendants(options);
566 paintSelfAndChildren(options, optionsForDescendants);
570 FloatRect viewportRect(0, 0, viewportSize.width(), viewportSize.height());
572 RefPtr<BitmapTexture> maskSurface;
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);
581 surface = options.surfaceManager->getIntermediateSurface();
582 optionsForDescendants.surface = surface.get();
583 options.isSurface = true;
584 optionsForDescendants.opacity = 1;
585 options.textureMapper->bindSurface(surface.get());
587 paintSelfAndChildren(options, optionsForDescendants);
589 if (!paintReflection(options, surface.get())) {
590 options.textureMapper->bindSurface(options.surface);
591 options.textureMapper->drawTexture(*surface.get(), viewportRect, TransformationMatrix(), options.opacity, 0);
594 options.surfaceManager->releaseIntermediateSurface(surface.get());
595 options.surfaceManager->releaseIntermediateSurface(maskSurface.get());
598 TextureMapperNode::~TextureMapperNode()
600 for (int i = m_children.size() - 1; i >= 0; --i)
601 m_children[i]->m_parent = 0;
604 m_parent->m_children.remove(m_parent->m_children.find(this));
607 #if USE(TILED_BACKING_STORE)
608 int TextureMapperNode::createContentsTile(float scale)
610 static int nextID = 0;
612 m_externallyManagedTiles.add(id, ExternallyManagedTile(scale));
613 m_state.contentScale = scale;
617 void TextureMapperNode::removeContentsTile(int id)
619 m_externallyManagedTiles.remove(id);
622 void TextureMapperNode::purgeNodeTexturesRecursive()
624 m_externallyManagedTiles.clear();
626 for (int i = m_children.size() - 1; i >= 0; --i)
627 m_children[i]->purgeNodeTexturesRecursive();
630 void TextureMapperNode::setTileBackBufferTextureForDirectlyCompositedImage(int id, const IntRect& sourceRect, const FloatRect& targetRect, BitmapTexture* texture)
632 HashMap<int, ExternallyManagedTile>::iterator it = m_externallyManagedTiles.find(id);
634 if (it == m_externallyManagedTiles.end())
637 ExternallyManagedTile& tile = it->second;
639 tile.backBuffer.sourceRect = sourceRect;
640 tile.backBuffer.targetRect = targetRect;
641 tile.backBuffer.texture = texture;
642 tile.isBackBufferUpdated = true;
643 tile.isDirectlyCompositedImage = true;
646 void TextureMapperNode::clearAllDirectlyCompositedImageTiles()
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);
654 void TextureMapperNode::setContentsTileBackBuffer(int id, const IntRect& sourceRect, const IntRect& targetRect, void* bits, BitmapTexture::PixelFormat format)
656 ASSERT(m_textureMapper);
658 HashMap<int, ExternallyManagedTile>::iterator it = m_externallyManagedTiles.find(id);
659 if (it == m_externallyManagedTiles.end())
662 ExternallyManagedTile& tile = it->second;
664 tile.backBuffer.sourceRect = sourceRect;
665 tile.backBuffer.targetRect = FloatRect(targetRect);
666 tile.backBuffer.targetRect.scale(1.0 / tile.scale);
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;
675 void TextureMapperNode::swapContentsBuffers()
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)
682 tile.isBackBufferUpdated = false;
683 ExternallyManagedTileBuffer swapBuffer = tile.frontBuffer;
684 tile.frontBuffer = tile.backBuffer;
685 tile.backBuffer = swapBuffer;
690 void TextureMapperNode::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, int options)
692 syncCompositingState(graphicsLayer, rootLayer()->m_textureMapper, options);
695 void TextureMapperNode::syncCompositingStateSelf(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper)
697 int changeMask = graphicsLayer->changeMask();
698 const TextureMapperNode::ContentData& pendingContent = graphicsLayer->pendingContent();
699 #if USE(TILED_BACKING_STORE)
700 swapContentsBuffers();
702 if (changeMask == NoChanges && graphicsLayer->m_animations.isEmpty() && pendingContent.needsDisplayRect.isEmpty() && !pendingContent.needsDisplay)
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.
710 size_t index = m_parent->m_children.find(this);
711 m_parent->m_children.remove(index);
714 // Set new node parent and add node to the parents child list.
716 m_parent = newParent;
717 m_parent->m_children.append(this);
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;
728 for (size_t i = 0; i < graphicsLayer->children().size(); ++i) {
729 TextureMapperNode* child = toTextureMapperNode(graphicsLayer->children()[i]);
732 m_children.append(child);
733 child->m_parent = this;
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());
742 if (wantedSize != m_size)
743 m_ownedTiles.clear();
748 if (changeMask & MaskLayerChange) {
749 if (TextureMapperNode* layer = toTextureMapperNode(graphicsLayer->maskLayer()))
750 layer->m_effectTarget = this;
753 if (changeMask & ReplicaLayerChange) {
754 if (TextureMapperNode* layer = toTextureMapperNode(graphicsLayer->replicaLayer()))
755 layer->m_effectTarget = this;
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]);
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);
786 if (!hasOpacityAnimation())
787 m_opacity = m_state.opacity;
788 if (!hasTransformAnimation())
789 m_transforms.base = m_state.transform;
792 bool TextureMapperNode::descendantsOrSelfHaveRunningAnimations() const
794 for (size_t i = 0; i < m_animations.size(); ++i) {
795 if (!m_animations[i]->paused)
799 for (size_t i = 0; i < m_children.size(); ++i) {
800 if (m_children[i]->descendantsOrSelfHaveRunningAnimations())
807 static double normalizedAnimationValue(double runningTime, double duration, bool alternate)
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;
818 void TextureMapperNode::applyOpacityAnimation(float fromOpacity, float toOpacity, double progress)
820 // Optimization: special case the edge values (0 and 1).
822 setOpacity(toOpacity);
824 setOpacity(fromOpacity);
826 setOpacity(fromOpacity + progress * (toOpacity - fromOpacity));
829 static inline double solveEpsilon(double duration)
831 return 1.0 / (200.0 * duration);
834 static inline double solveCubicBezierFunction(double p1x, double p1y, double p2x, double p2y, double t, double duration)
836 UnitBezier bezier(p1x, p1y, p2x, p2y);
837 return bezier.solve(t, solveEpsilon(duration));
840 static inline double solveStepsFunction(int numSteps, bool stepAtStart, double t)
843 #if USE(TIZEN_TEXTURE_MAPPER)
844 return fmin(1.0, (floor(numSteps * t) + 1) / numSteps);
846 return std::min(1.0, (floor(numSteps * t) + 1) / numSteps);
848 return floor(numSteps * t) / numSteps;
851 static inline float applyTimingFunction(const TimingFunction* timingFunction, float progress, double duration)
856 if (timingFunction->isCubicBezierTimingFunction()) {
857 const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction);
858 return solveCubicBezierFunction(ctf->x1(),
865 if (timingFunction->isStepsTimingFunction()) {
866 const StepsTimingFunction* stf = static_cast<const StepsTimingFunction*>(timingFunction);
867 return solveStepsFunction(stf->numberOfSteps(), stf->stepAtStart(), double(progress));
873 void TextureMapperNode::applyTransformAnimation(const TextureMapperAnimation& animation, const TransformOperations* from, const TransformOperations* to, double progress)
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);
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);
892 TransformationMatrix matrix;
895 const TransformOperations* swap = to;
898 } else if (!from->size())
899 progress = 1.0 - progress;
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);
905 setTransform(matrix);
908 void TextureMapperNode::applyAnimationFrame(const TextureMapperAnimation& animation, const AnimationValue* from, const AnimationValue* to, float progress)
910 switch (animation.keyframes.property()) {
911 case AnimatedPropertyOpacity:
912 applyOpacityAnimation((static_cast<const FloatAnimationValue*>(from)->value()), (static_cast<const FloatAnimationValue*>(to)->value()), progress);
914 case AnimatedPropertyWebkitTransform:
915 applyTransformAnimation(animation, static_cast<const TransformAnimationValue*>(from)->value(), static_cast<const TransformAnimationValue*>(to)->value(), progress);
918 ASSERT_NOT_REACHED();
922 void TextureMapperNode::applyAnimation(const TextureMapperAnimation& animation, double normalizedValue)
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);
929 if (normalizedValue == 1.0) {
930 applyAnimationFrame(animation, animation.keyframes.at(animation.keyframes.size() - 2), animation.keyframes.at(animation.keyframes.size() - 1), 1);
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);
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)
945 normalizedValue = (normalizedValue - from->keyTime()) / (to->keyTime() - from->keyTime());
946 normalizedValue = applyTimingFunction(from->timingFunction(), normalizedValue, animation.animation->duration());
947 applyAnimationFrame(animation, from, to, normalizedValue);
952 bool TextureMapperNode::hasOpacityAnimation() const
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)
962 bool TextureMapperNode::hasTransformAnimation() const
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)
972 void TextureMapperNode::syncAnimations(GraphicsLayerTextureMapper* layer)
974 for (int i = m_animations.size() - 1; i >= 0; --i) {
975 RefPtr<TextureMapperAnimation> animation = m_animations[i];
977 double totalRunningTime = WTF::currentTime() - animation->startTime;
978 RefPtr<Animation> anim = animation->animation;
979 double normalizedValue = normalizedAnimationValue(totalRunningTime, anim->duration(), anim->direction());
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;
990 m_animations.remove(i);
994 if (!animation->paused)
995 applyAnimation(*animation.get(), normalizedValue);
999 void TextureMapperNode::syncAnimationsRecursively()
1003 computeAllTransforms();
1005 for (int i = m_children.size() - 1; i >= 0; --i)
1006 m_children[i]->syncAnimationsRecursively();
1009 void TextureMapperNode::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper, int options)
1011 if (graphicsLayer && !(options & ComputationsOnly)) {
1012 syncCompositingStateSelf(graphicsLayer, textureMapper);
1013 graphicsLayer->didSynchronize();
1016 if (graphicsLayer && m_state.maskLayer) {
1017 m_state.maskLayer->syncCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->maskLayer()), textureMapper);
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;
1024 if (m_state.replicaLayer)
1025 m_state.replicaLayer->syncCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->replicaLayer()), textureMapper);
1027 syncAnimations(graphicsLayer);
1029 computeAllTransforms();
1031 computeOverlapsIfNeeded();
1034 renderContent(textureMapper, graphicsLayer);
1036 if (!(options & TraverseDescendants))
1037 options = ComputationsOnly;
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]);
1045 node->syncCompositingState(toGraphicsLayerTextureMapper(children[i]), textureMapper, options);
1048 for (int i = m_children.size() - 1; i >= 0; --i)
1049 m_children[i]->syncCompositingState(0, textureMapper, options);
1052 if (m_state.preserves3D)
1053 sortByZOrder(m_children, 0, m_children.size());
1056 TextureMapperAnimation::TextureMapperAnimation(const KeyframeValueList& values)
1061 #if ENABLE(TIZEN_WEBKIT2_TILED_AC)
1062 bool TextureMapperNode::collectVisibleContentRects(NodeRectMap& rectMap, const FloatRect& rootVisibleRect)
1064 if (!m_state.visible || m_state.opacity < 0.01)
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;
1075 if (!m_transforms.target.isInvertible())
1078 IntRect visibleContentsRect(0, 0, m_size.width(), m_size.height());
1079 if (visibleContentsRect == m_state.visibleRect)
1082 m_state.visibleRect = visibleContentsRect;
1083 rectMap.add(this, m_state.visibleRect);