Title: [105467] trunk/Source/WebCore
Revision
105467
Author
[email protected]
Date
2012-01-19 17:34:24 -0800 (Thu, 19 Jan 2012)

Log Message

[Texmap] TextureMapper creates two many big intermediate surfaces
https://bugs.webkit.org/show_bug.cgi?id=76336

Reviewed by Simon Hausmann.

The following has been done to optimize surface allocation:
1. Instead of using a viewport-size surface, use a surface in the size of the layer's
   bounding rect and apply the transform after the content has been rendered into it.
2. Avoid generating intermediate surface for occasions where they're not necessary,
   such as nested reflections without opacity.
3. Releasing of textures from the pool is now implicit, based on refCount.
4. Do not use intermediate surfaces for preserve-3d layers. This is in alignment with
   other ports.

Tests in LayoutTests/compositing/masks and LayoutTests/compositing/reflection cover this.

* platform/graphics/texmap/TextureMapper.cpp:
(WebCore::TextureMapper::acquireTextureFromPool):
* platform/graphics/texmap/TextureMapper.h:
* platform/graphics/texmap/TextureMapperNode.cpp:
(WebCore::TextureMapperNode::paintSelf):
(WebCore::TextureMapperNode::paintSelfAndChildren):
(WebCore::TextureMapperNode::intermediateSurfaceRect):
(WebCore::TextureMapperNode::shouldPaintToIntermediateSurface):
(WebCore::TextureMapperNode::isVisible):
(WebCore::TextureMapperNode::paintSelfAndChildrenWithReplica):
(WebCore::TextureMapperNode::paintRecursive):
(WebCore::TextureMapperNode::syncCompositingStateSelf):
(WebCore::TextureMapperNode::syncCompositingState):
* platform/graphics/texmap/TextureMapperNode.h:
(WebCore::TextureMapperPaintOptions::TextureMapperPaintOptions):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (105466 => 105467)


--- trunk/Source/WebCore/ChangeLog	2012-01-20 01:22:52 UTC (rev 105466)
+++ trunk/Source/WebCore/ChangeLog	2012-01-20 01:34:24 UTC (rev 105467)
@@ -1,3 +1,37 @@
+2012-01-19  No'am Rosenthal  <[email protected]>
+
+        [Texmap] TextureMapper creates two many big intermediate surfaces
+        https://bugs.webkit.org/show_bug.cgi?id=76336
+
+        Reviewed by Simon Hausmann.
+
+        The following has been done to optimize surface allocation:
+        1. Instead of using a viewport-size surface, use a surface in the size of the layer's
+           bounding rect and apply the transform after the content has been rendered into it.
+        2. Avoid generating intermediate surface for occasions where they're not necessary,
+           such as nested reflections without opacity.
+        3. Releasing of textures from the pool is now implicit, based on refCount.
+        4. Do not use intermediate surfaces for preserve-3d layers. This is in alignment with
+           other ports.
+
+        Tests in LayoutTests/compositing/masks and LayoutTests/compositing/reflection cover this.
+
+        * platform/graphics/texmap/TextureMapper.cpp:
+        (WebCore::TextureMapper::acquireTextureFromPool):
+        * platform/graphics/texmap/TextureMapper.h:
+        * platform/graphics/texmap/TextureMapperNode.cpp:
+        (WebCore::TextureMapperNode::paintSelf):
+        (WebCore::TextureMapperNode::paintSelfAndChildren):
+        (WebCore::TextureMapperNode::intermediateSurfaceRect):
+        (WebCore::TextureMapperNode::shouldPaintToIntermediateSurface):
+        (WebCore::TextureMapperNode::isVisible):
+        (WebCore::TextureMapperNode::paintSelfAndChildrenWithReplica):
+        (WebCore::TextureMapperNode::paintRecursive):
+        (WebCore::TextureMapperNode::syncCompositingStateSelf):
+        (WebCore::TextureMapperNode::syncCompositingState):
+        * platform/graphics/texmap/TextureMapperNode.h:
+        (WebCore::TextureMapperPaintOptions::TextureMapperPaintOptions):
+
 2012-01-19  Eric Seidel  <[email protected]>
 
         Assertion failure in WebCore::HTMLFrameElementBase::insertedIntoDocument()

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp (105466 => 105467)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp	2012-01-20 01:22:52 UTC (rev 105466)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp	2012-01-20 01:34:24 UTC (rev 105467)
@@ -26,19 +26,21 @@
 
 PassRefPtr<BitmapTexture> TextureMapper::acquireTextureFromPool(const IntSize& size)
 {
-    if (m_texturePool.isEmpty()) {
-        RefPtr<BitmapTexture> selectedTexture = createTexture();
-        selectedTexture->reset(size, false);
-        selectedTexture->lock();
-        return selectedTexture;
-    }
+    RefPtr<BitmapTexture> selectedTexture;
 
-    size_t index = 0;
-    RefPtr<BitmapTexture> selectedTexture = m_texturePool[0];
+    for (size_t i = 0; i < m_texturePool.size(); ++i) {
+        RefPtr<BitmapTexture>& texture = m_texturePool[i];
 
-    for (size_t i = 1; i < m_texturePool.size(); ++i) {
-        RefPtr<BitmapTexture> texture = m_texturePool[i];
+        // If the surface has only one reference (the one in m_texturePool), we can safely reuse it.
+        if (texture->refCount() > 1)
+            continue;
 
+        // We default to the first available texture.
+        if (!selectedTexture) {
+            selectedTexture = texture;
+            continue;
+        }
+
         IntSize textureSize = texture->size();
         IntSize selectedTextureSize = selectedTexture->size();
 
@@ -58,22 +60,16 @@
             continue;
 
         selectedTexture = texture;
-        index = i;
     }
 
-    m_texturePool.remove(index);
+    if (!selectedTexture) {
+        selectedTexture = createTexture();
+        m_texturePool.append(selectedTexture);
+    }
+
     selectedTexture->reset(size, false);
-    selectedTexture->lock();
     return selectedTexture;
 }
 
-void TextureMapper::releaseTextureToPool(BitmapTexture* texture)
-{
-    if (!texture)
-        return;
-    m_texturePool.append(texture);
-    texture->unlock();
 }
-
-}
 #endif

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.h (105466 => 105467)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.h	2012-01-20 01:22:52 UTC (rev 105466)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.h	2012-01-20 01:34:24 UTC (rev 105467)
@@ -126,7 +126,7 @@
     virtual void beginPainting() { }
     virtual void endPainting() { }
 
-    virtual void releaseTextureToPool(BitmapTexture* surface);
+    // A surface is released implicitly when dereferenced.
     virtual PassRefPtr<BitmapTexture> acquireTextureFromPool(const IntSize&);
 
 

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp (105466 => 105467)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp	2012-01-20 01:22:52 UTC (rev 105466)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp	2012-01-20 01:34:24 UTC (rev 105467)
@@ -50,22 +50,6 @@
     m_transform.setLocalTransform(matrix);
 }
 
-int TextureMapperNode::countDescendantsWithContent() const
-{
-    if (!m_state.visible || (!m_size.width() && !m_size.height() && m_state.masksToBounds))
-        return 0;
-    int count = (m_size.width() && m_size.height() && (m_state.drawsContent || m_currentContent.contentType != HTMLContentType)) ? 1 : 0;
-    for (size_t i = 0; i < m_children.size(); ++i)
-        count += m_children[i]->countDescendantsWithContent();
-
-    return count;
-}
-
-void TextureMapperNode::computeOverlapsIfNeeded()
-{
-    m_state.mightHaveOverlaps = countDescendantsWithContent() > 1;
-}
-
 void TextureMapperNode::computeTransformsRecursive()
 {
     if (m_size.isEmpty() && m_state.masksToBounds)
@@ -157,34 +141,6 @@
         m_ownedTiles.remove(tilesToRemove[i]);
 }
 
-bool TextureMapperNode::hasMoreThanOneTile() const
-{
-    int tiles = 0;
-
-#if USE(TILED_BACKING_STORE)
-    if (m_state.tileOwnership == ExternallyManagedTiles) {
-        HashMap<int, ExternallyManagedTile>::const_iterator end = m_externallyManagedTiles.end();
-        for (HashMap<int, ExternallyManagedTile>::const_iterator it = m_externallyManagedTiles.begin(); it != end; ++it) {
-            if (it->second.frontBuffer.texture) {
-                if (++tiles > 1)
-                    return true;
-            }
-        }
-
-        return false;
-    }
-#endif
-
-    for (size_t i = 0; i < m_ownedTiles.size(); ++i) {
-        if (m_ownedTiles[i].texture) {
-            if (++tiles > 1)
-                return true;
-        }
-    }
-
-    return false;
-}
-
 void TextureMapperNode::renderContent(TextureMapper* textureMapper, GraphicsLayer* layer)
 {
 #if USE(TILED_BACKING_STORE)
@@ -271,17 +227,16 @@
     if (m_size.isEmpty() || (!m_state.drawsContent && m_currentContent.contentType == HTMLContentType))
         return;
 
-    RefPtr<BitmapTexture> maskTexture;
-    RefPtr<BitmapTexture> replicaMaskTexture;
-
-    if (m_state.maskLayer)
-        maskTexture = m_state.maskLayer->texture();
-    if (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer)
-        replicaMaskTexture = m_state.replicaLayer->m_state.maskLayer->texture();
-
-    float opacity = options.isSurface ? 1 : options.opacity;
+    float opacity = options.opacity;
+    BitmapTexture* mask = options.mask;
     FloatRect targetRect = this->targetRect();
 
+    // 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.
+    TransformationMatrix transform =
+            TransformationMatrix(options.transform)
+            .multiply(m_transform.combined())
+            .translate(options.offset.width(), options.offset.height());
+
 #if USE(TILED_BACKING_STORE)
     Vector<ExternallyManagedTile> tilesToPaint;
 
@@ -303,20 +258,11 @@
                 tiles.prepend(&it->second);
         }
 
-        TransformationMatrix replicaMatrix;
         for (int i = 0; i < tiles.size(); ++i) {
             ExternallyManagedTile& tile = *tiles[i];
             FloatRect rect = tile.frontBuffer.targetRect;
-
-            float replicaOpacity = 1.0;
-            if (m_state.replicaLayer) {
-                replicaMatrix = m_state.replicaLayer->m_transform.combined().scale(1.0 / tile.scale);
-                replicaOpacity = opacity * m_state.replicaLayer->m_opacity;
-            }
             BitmapTexture& texture = *tile.frontBuffer.texture;
-            if (m_state.replicaLayer)
-                options.textureMapper->drawTexture(texture, rect, replicaMatrix, replicaOpacity, replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get());
-            options.textureMapper->drawTexture(texture, rect, m_transform.combined(), opacity, options.isSurface ? 0 : maskTexture.get());
+            options.textureMapper->drawTexture(texture, rect, transform, opacity, mask);
         }
         return;
     }
@@ -325,25 +271,12 @@
     // Now we paint owned tiles, if we're in OwnedTileMode.
     for (size_t i = 0; i < m_ownedTiles.size(); ++i) {
         BitmapTexture* texture = m_ownedTiles[i].texture.get();
-        if (m_state.replicaLayer && !options.isSurface) {
-            options.textureMapper->drawTexture(*texture, targetRectForTileRect(targetRect, m_ownedTiles[i].rect),
-                             m_state.replicaLayer->m_transform.combined(),
-                             opacity * m_state.replicaLayer->m_opacity,
-                             replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get());
-        }
-
         const FloatRect rect = targetRectForTileRect(targetRect, m_ownedTiles[i].rect);
-        options.textureMapper->drawTexture(*texture, rect, m_transform.combined(), opacity, options.isSurface ? 0 : maskTexture.get());
+        options.textureMapper->drawTexture(*texture, rect, transform, opacity, mask);
     }
 
-    if (m_currentContent.contentType == MediaContentType && m_currentContent.media) {
-        if (m_state.replicaLayer && !options.isSurface)
-            m_currentContent.media->paintToTextureMapper(options.textureMapper, targetRect,
-                                                         m_state.replicaLayer->m_transform.combined(),
-                                                         opacity * m_state.replicaLayer->m_opacity,
-                                                         replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get());
-        m_currentContent.media->paintToTextureMapper(options.textureMapper, targetRect, m_transform.combined(), opacity, options.isSurface ? 0 : maskTexture.get());
-    }
+    if (m_currentContent.contentType == MediaContentType && m_currentContent.media)
+        m_currentContent.media->paintToTextureMapper(options.textureMapper, targetRect, transform, opacity, mask);
 }
 
 int TextureMapperNode::compareGraphicsLayersZValue(const void* a, const void* b)
@@ -358,150 +291,138 @@
     qsort(array.data(), array.size(), sizeof(TextureMapperNode*), compareGraphicsLayersZValue);
 }
 
-void TextureMapperNode::paintSelfAndChildren(const TextureMapperPaintOptions& options, TextureMapperPaintOptions& optionsForDescendants)
+void TextureMapperNode::paintSelfAndChildren(const TextureMapperPaintOptions& options)
 {
     bool hasClip = m_state.masksToBounds && !m_children.isEmpty();
     if (hasClip)
-        options.textureMapper->beginClip(m_transform.combined(), FloatRect(0, 0, m_size.width(), m_size.height()));
+        options.textureMapper->beginClip(TransformationMatrix(options.transform).multiply(m_transform.combined()), FloatRect(0, 0, m_size.width(), m_size.height()));
 
     paintSelf(options);
 
     for (int i = 0; i < m_children.size(); ++i)
-        m_children[i]->paintRecursive(optionsForDescendants);
+        m_children[i]->paintRecursive(options);
 
     if (hasClip)
         options.textureMapper->endClip();
 }
 
-bool TextureMapperNode::paintReflection(const TextureMapperPaintOptions& options, BitmapTexture* contentSurface)
+IntRect TextureMapperNode::intermediateSurfaceRect()
 {
-    if (!m_state.replicaLayer)
-        return false;
+    // FIXME: Add an inverse transform to LayerTransform.
+    return intermediateSurfaceRect(m_transform.combined().inverse());
+}
 
-    RefPtr<BitmapTexture> surface(contentSurface);
-    RefPtr<BitmapTexture> maskSurface;
-    RefPtr<BitmapTexture> replicaMaskSurface;
-    RefPtr<BitmapTexture> replicaMaskTexture;
+IntRect TextureMapperNode::intermediateSurfaceRect(const TransformationMatrix& matrix)
+{
+    IntRect rect;
+    TransformationMatrix localTransform = TransformationMatrix(matrix).multiply(m_transform.combined());
+    rect = enclosingIntRect(localTransform.mapRect(entireRect()));
+    if (!m_state.masksToBounds && !m_state.maskLayer) {
+        for (int i = 0; i < m_children.size(); ++i)
+            rect.unite(m_children[i]->intermediateSurfaceRect(matrix));
+    }
 
-    if (TextureMapperNode* replicaMask = m_state.replicaLayer->m_state.maskLayer)
-        replicaMaskTexture = replicaMask->texture();
+    if (m_state.replicaLayer)
+        rect.unite(m_state.replicaLayer->intermediateSurfaceRect(matrix));
 
-    RefPtr<BitmapTexture> maskTexture;
-    if (TextureMapperNode* mask = m_state.maskLayer)
-        maskTexture = mask->texture();
+    return rect;
+}
 
-    const IntSize viewportSize = options.textureMapper->viewportSize();
-    const bool useIntermediateBufferForReplica = m_state.replicaLayer && options.opacity < 0.99;
-    const bool useIntermediateBufferForMask = maskTexture && replicaMaskTexture;
-    const FloatRect viewportRect(0, 0, viewportSize.width(), viewportSize.height());
-    // Reverse this layer's transform on the replica's transform and use it with the contents
-    // intermediate surface, applied in the viewport coordinate system.
-    TransformationMatrix replicaMatrix = m_state.replicaLayer->m_transform.combined();
-    replicaMatrix.multiply(m_transform.combined().inverse());
+bool TextureMapperNode::shouldPaintToIntermediateSurface() const
+{
+    bool hasOpacity = m_opacity < 0.99;
+    bool hasChildren = !m_children.isEmpty();
+    bool hasReplica = !!m_state.replicaLayer;
+    bool hasMask = !!m_state.maskLayer;
 
-    // The mask has to be adjusted to target coordinates.
-    if (maskTexture) {
-        maskSurface = options.textureMapper->acquireTextureFromPool(options.textureMapper->viewportSize());
-        options.textureMapper->bindSurface(maskSurface.get());
-        options.textureMapper->drawTexture(*maskTexture.get(), entireRect(), m_transform.combined(), 1, 0);
-        maskTexture = maskSurface;
-    }
+    // We don't use two-pass blending for preserves-3d, that's in sync with Safari.
+    if (m_state.preserves3D)
+        return false;
 
-    // The replica's mask has to be adjusted to target coordinates.
-    if (replicaMaskTexture) {
-        replicaMaskSurface = options.textureMapper->acquireTextureFromPool(options.textureMapper->viewportSize());
-        options.textureMapper->bindSurface(replicaMaskSurface.get());
-        options.textureMapper->drawTexture(*replicaMaskTexture.get(), entireRect(), m_transform.combined(), 1, 0);
-        replicaMaskTexture = replicaMaskSurface;
-    }
+    // We should use an intermediate surface when blending several items with an ancestor opacity.
+    // Tested by compositing/reflections/reflection-opacity.html
+    if (hasOpacity && (hasChildren || hasReplica))
+        return true;
 
-    // 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.
-    if (useIntermediateBufferForMask) {
-        RefPtr<BitmapTexture> maskSurface = options.textureMapper->acquireTextureFromPool(options.textureMapper->viewportSize());
-        options.textureMapper->bindSurface(maskSurface.get());
-        options.textureMapper->drawTexture(*surface.get(), viewportRect, TransformationMatrix(), 1, maskTexture.get());
-        options.textureMapper->releaseTextureToPool(surface.get());
-        surface = maskSurface;
-        maskTexture.clear();
-    }
+    // We should use an intermediate surface with a masked ancestor.
+    // In the case of replicas the mask is applied before replicating.
+    // Tested by compositing/masks/masked-ancestor.html
+    if (hasMask && hasChildren && !hasReplica)
+        return true;
 
-    // We blend the layer and its replica in an intermediate buffer before blending into the target surface.
-    if (useIntermediateBufferForReplica) {
-        RefPtr<BitmapTexture> replicaSurface = options.textureMapper->acquireTextureFromPool(options.textureMapper->viewportSize());
-        options.textureMapper->bindSurface(replicaSurface.get());
-        options.textureMapper->drawTexture(*surface.get(), viewportRect, replicaMatrix, m_state.replicaLayer->m_opacity, replicaMaskTexture.get());
-        options.textureMapper->drawTexture(*surface.get(), viewportRect, TransformationMatrix(), 1, maskTexture.get());
-        options.textureMapper->releaseTextureToPool(surface.get());
-        surface = replicaSurface;
-    }
+    return false;
+}
 
-    options.textureMapper->bindSurface(options.surface);
+bool TextureMapperNode::isVisible() const
+{
+    if (m_size.isEmpty() && (m_state.masksToBounds || m_state.maskLayer || m_children.isEmpty()))
+        return false;
+    if (!m_state.visible || m_opacity < 0.01)
+        return false;
+    return true;
+}
 
-    // Draw the reflection.
-    if (!useIntermediateBufferForReplica)
-        options.textureMapper->drawTexture(*surface.get(), viewportRect, replicaMatrix, m_state.replicaLayer->m_opacity, replicaMaskTexture.get());
+void TextureMapperNode::paintSelfAndChildrenWithReplica(const TextureMapperPaintOptions& options)
+{
+    if (m_state.replicaLayer) {
+        TextureMapperPaintOptions replicaOptions(options);
+        // We choose either the content's mask or the replica's mask.
+        // FIXME: blend the two if both exist.
+        if (m_state.replicaLayer->m_state.maskLayer)
+            replicaOptions.mask = m_state.replicaLayer->m_state.maskLayer->texture();
 
-    // Draw the original.
-    options.textureMapper->drawTexture(*surface.get(), viewportRect, TransformationMatrix(), options.opacity, maskTexture.get());
+        replicaOptions.transform
+                  .multiply(m_state.replicaLayer->m_transform.combined())
+                  .multiply(m_transform.combined().inverse());
+        paintSelfAndChildren(replicaOptions);
+    }
 
-    options.textureMapper->releaseTextureToPool(maskSurface.get());
-    options.textureMapper->releaseTextureToPool(replicaMaskSurface.get());
-
-    return true;
+    paintSelfAndChildren(options);
 }
 
-void TextureMapperNode::paintRecursive(TextureMapperPaintOptions options)
+void TextureMapperNode::paintRecursive(const TextureMapperPaintOptions& options)
 {
-    if ((m_size.isEmpty() && (m_state.masksToBounds
-        || m_children.isEmpty())) || !m_state.visible || options.opacity < 0.01 || m_opacity < 0.01)
+    if (!isVisible())
         return;
 
-    options.opacity *= m_opacity;
-    RefPtr<BitmapTexture> surface;
+    float opacity = options.opacity * m_opacity;
+    RefPtr<BitmapTexture> maskTexture = m_state.maskLayer ? m_state.maskLayer->texture() : 0;
 
-    bool hasReplica = m_state.replicaLayer;
-    bool hasMask = m_state.maskLayer;
-    bool needsBlending = m_opacity < 0.99 || hasMask;
-    bool paintsMoreThanOneTexture = !m_children.isEmpty() || hasMoreThanOneTile() || (hasMask && m_state.maskLayer->hasMoreThanOneTile());
-    bool hasOverlaps = m_state.mightHaveOverlaps || hasReplica;
-    const IntSize viewportSize = options.textureMapper->viewportSize();
-    bool needsTwoPass = ((hasReplica || hasMask) && paintsMoreThanOneTexture) || (needsBlending && hasOverlaps);
-    options.isSurface = false;
+    TextureMapperPaintOptions paintOptions(options);
+    paintOptions.mask = maskTexture.get();
+    IntRect surfaceRect;
 
-    TextureMapperPaintOptions optionsForDescendants(options);
+    RefPtr<BitmapTexture> surface;
 
-    if (!needsTwoPass) {
-        paintSelfAndChildren(options, optionsForDescendants);
+    if (!shouldPaintToIntermediateSurface()) {
+        paintOptions.opacity = opacity;
+        paintSelfAndChildrenWithReplica(paintOptions);
         return;
     }
 
-    FloatRect viewportRect(0, 0, viewportSize.width(), viewportSize.height());
-
-    RefPtr<BitmapTexture> maskSurface;
-
-    if (m_state.maskLayer) {
-        maskSurface = options.textureMapper->acquireTextureFromPool(options.textureMapper->viewportSize());
-        options.textureMapper->bindSurface(maskSurface.get());
-        TextureMapperPaintOptions optionsForMask(options);
-        optionsForMask.isSurface = true;
-        m_state.maskLayer->paintSelf(optionsForMask);
-    }
-
-    surface = options.textureMapper->acquireTextureFromPool(options.textureMapper->viewportSize());
-    optionsForDescendants.surface = surface.get();
-    options.isSurface = true;
-    optionsForDescendants.opacity = 1;
+    // Prepare a surface to paint into.
+    // We paint into the surface ignoring the opacity/transform of the current layer.
+    surfaceRect = intermediateSurfaceRect();
+    surface = options.textureMapper->acquireTextureFromPool(surfaceRect.size());
     options.textureMapper->bindSurface(surface.get());
+    paintOptions.opacity = 1;
 
-    paintSelfAndChildren(options, optionsForDescendants);
+    // We have to use combinedForChildren() and not combined(), otherwise preserve-3D doesn't work.
+    paintOptions.transform = m_transform.combinedForChildren().inverse();
+    paintOptions.offset = -IntSize(surfaceRect.x(), surfaceRect.y());
 
-    if (!paintReflection(options, surface.get())) {
-        options.textureMapper->bindSurface(options.surface);
-        options.textureMapper->drawTexture(*surface.get(), viewportRect, TransformationMatrix(), options.opacity, maskSurface.get());
-    }
+    paintSelfAndChildrenWithReplica(paintOptions);
 
-    options.textureMapper->releaseTextureToPool(surface.get());
-    options.textureMapper->releaseTextureToPool(maskSurface.get());
+    // If we painted the replica, the mask is already applied so we don't need to paint it again.
+    if (m_state.replicaLayer)
+        maskTexture = 0;
+
+    options.textureMapper->bindSurface(options.surface);
+    TransformationMatrix targetTransform =
+            TransformationMatrix(options.transform)
+                .multiply(m_transform.combined())
+                .translate(options.offset.width(), options.offset.height());
+    options.textureMapper->drawTexture(*surface.get(), surfaceRect, targetTransform, opacity, maskTexture.get());
 }
 
 TextureMapperNode::~TextureMapperNode()
@@ -685,6 +606,7 @@
     m_state.backfaceVisibility = graphicsLayer->backfaceVisibility();
     m_state.childrenTransform = graphicsLayer->childrenTransform();
     m_state.opacity = graphicsLayer->opacity();
+
     m_currentContent.contentType = pendingContent.contentType;
     m_currentContent.image = pendingContent.image;
     m_currentContent.media = pendingContent.media;
@@ -936,7 +858,6 @@
     syncAnimations(graphicsLayer);
 
     computeTiles();
-    computeOverlapsIfNeeded();
 
     if (graphicsLayer)
         renderContent(textureMapper, graphicsLayer);

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h (105466 => 105467)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h	2012-01-20 01:22:52 UTC (rev 105466)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h	2012-01-20 01:34:24 UTC (rev 105467)
@@ -44,15 +44,16 @@
 class TextureMapperPaintOptions {
 public:
     BitmapTexture* surface;
+    BitmapTexture* mask;
+    float opacity;
+    TransformationMatrix transform;
+    IntSize offset;
     TextureMapper* textureMapper;
-
-    float opacity;
-    bool isSurface;
     TextureMapperPaintOptions()
         : surface(0)
+        , mask(0)
+        , opacity(1)
         , textureMapper(0)
-        , opacity(1)
-        , isSurface(false)
     { }
 };
 
@@ -178,8 +179,9 @@
     void computeTransformsRecursive();
     void computeOverlapsIfNeeded();
     void computeTiles();
+    IntRect intermediateSurfaceRect(const TransformationMatrix&);
+    IntRect intermediateSurfaceRect();
     void swapContentsBuffers();
-    int countDescendantsWithContent() const;
     FloatRect targetRectForTileRect(const FloatRect& totalTargetRect, const FloatRect& tileRect) const;
     void invalidateViewport(const FloatRect&);
     void notifyChange(ChangeMask);
@@ -190,10 +192,10 @@
 
     BitmapTexture* texture() { return m_ownedTiles.isEmpty() ? 0 : m_ownedTiles[0].texture.get(); }
 
-    void paintRecursive(TextureMapperPaintOptions);
-    bool paintReflection(const TextureMapperPaintOptions&, BitmapTexture* surface);
+    void paintRecursive(const TextureMapperPaintOptions&);
     void paintSelf(const TextureMapperPaintOptions&);
-    void paintSelfAndChildren(const TextureMapperPaintOptions&, TextureMapperPaintOptions& optionsForDescendants);
+    void paintSelfAndChildren(const TextureMapperPaintOptions&);
+    void paintSelfAndChildrenWithReplica(const TextureMapperPaintOptions&);
     void renderContent(TextureMapper*, GraphicsLayer*);
 
     void syncAnimations(GraphicsLayerTextureMapper*);
@@ -203,7 +205,8 @@
     void applyTransformAnimation(const TextureMapperAnimation&, const TransformOperations* start, const TransformOperations* end, double);
     bool hasOpacityAnimation() const;
     bool hasTransformAnimation() const;
-    bool hasMoreThanOneTile() const;
+    bool isVisible() const;
+    bool shouldPaintToIntermediateSurface() const;
 
     LayerTransform m_transform;
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to