Home | History | Annotate | Download | only in texmap
      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 #include "GraphicsLayerTextureMapper.h"
     24 
     25 namespace WebCore {
     26 
     27 class TextureMapperCache {
     28 public:
     29     void mark(BitmapTexture* texture);
     30 
     31     class Entry {
     32     public:
     33         RefPtr<BitmapTexture> texture;
     34         Entry() : previousCost(0) { }
     35         inline int computeCost() const
     36         {
     37             if (!texture || !texture->isValid() || texture->isPacked())
     38                 return 0;
     39             const IntSize textureSize = texture->size();
     40             // An image's cost in bytes is width * height * bytes per pixel (4).
     41             return textureSize.width() * textureSize.height() * 4;
     42         }
     43         Entry(BitmapTexture* newTexture)
     44             : texture(newTexture)
     45         {
     46         }
     47         bool operator==(const Entry& other) const { return texture == other.texture; }
     48         int previousCost;
     49     };
     50 
     51     TextureMapperCache()
     52         : m_totalCost(0)
     53     {
     54     }
     55 
     56     void purge();
     57     Vector<Entry> m_data;
     58     int m_totalCost;
     59 #ifndef TEXMAP_TEXTURE_CACHE_KBS
     60 #define TEXMAP_TEXTURE_CACHE_KBS 24 * 1024
     61 #endif
     62     static const int MaxCost = TEXMAP_TEXTURE_CACHE_KBS * 1024;
     63     static const int PurgeAmount = MaxCost / 4;
     64 };
     65 
     66 
     67 void TextureMapperCache::purge()
     68 {
     69     const int size = m_data.size();
     70 
     71     if (m_totalCost <= TextureMapperCache::MaxCost)
     72         return;
     73 
     74     // Ensure that we have the right count. It might be inaccurate if content changed size.
     75     // We only do this when we're actually ready to purge.
     76     m_totalCost = 0;
     77     for (int i = 0; i < size; ++i)
     78         m_totalCost += m_data[i].computeCost();
     79 
     80     for (int i = size-1; i >= 0 && m_totalCost > TextureMapperCache::MaxCost - TextureMapperCache::PurgeAmount; --i) {
     81         Entry& entry = m_data[i];
     82         if (entry.texture->isLocked() || !entry.texture->isValid() || entry.texture->isPacked())
     83             continue;
     84         m_totalCost -= entry.previousCost;
     85         entry.texture->pack();
     86         m_data.remove(i);
     87     }
     88 }
     89 
     90 void TextureMapperCache::mark(BitmapTexture* texture)
     91 {
     92     if (!texture || !texture->isValid())
     93         return;
     94 
     95     Entry entry(texture);
     96     size_t index = m_data.find(entry);
     97     if (!index)
     98         return;
     99 
    100     int previousCost = 0;
    101 
    102     if (index < m_data.size()) {
    103         previousCost = m_data[index].previousCost;
    104         m_data.remove(index);
    105     }
    106     const int cost = entry.computeCost();
    107     m_totalCost -= previousCost;
    108     m_totalCost += (entry.previousCost = cost);
    109     m_data.prepend(entry);
    110 }
    111 
    112 class TextureMapperCacheLock {
    113 public:
    114     TextureMapperCacheLock(BitmapTexture* texture) : m_texture(texture)
    115     {
    116         if (m_texture)
    117             m_texture->lock();
    118     }
    119     ~TextureMapperCacheLock()
    120     {
    121         if (m_texture)
    122             m_texture->unlock();
    123     }
    124 
    125 private:
    126     RefPtr<BitmapTexture> m_texture;
    127 };
    128 
    129 
    130 TextureMapperCache* TextureMapperNode::cache()
    131 {
    132     TextureMapperNode* root = rootLayer();
    133     if (!root)
    134         return 0;
    135     if (!root->m_cache)
    136         root->m_cache = new TextureMapperCache;
    137     return root->m_cache;
    138 }
    139 
    140 void TextureMapperNode::setNeedsDisplayInRect(IntRect rect)
    141 {
    142     if (m_platformClient) {
    143         if (m_state.hasSurfaceDescendants) {
    144             m_platformClient->setNeedsDisplay();
    145             return;
    146         }
    147         rect.intersect(IntRect(0, 0, m_size.width(), m_size.height()));
    148         if (rect.isEmpty())
    149             return;
    150         m_platformClient->setNeedsDisplayInRect(rect);
    151         return;
    152     }
    153 
    154     if (!m_parent)
    155         return;
    156 
    157     m_parent->setNeedsDisplayInRect(rect);
    158 }
    159 
    160 void TextureMapperNode::setNeedsDisplay()
    161 {
    162     if (m_effectTarget)
    163         m_effectTarget->setNeedsDisplay();
    164     if (m_transforms.targetBoundingRect.isEmpty())
    165         return;
    166     if (m_state.drawsContent || m_currentContent.contentType != HTMLContentType)
    167         setNeedsDisplayInRect(m_transforms.targetBoundingRect);
    168 }
    169 
    170 void TextureMapperNode::setPlatformLayerClient(TextureMapperLayerClient* client)
    171 {
    172     m_platformClient = client;
    173 }
    174 
    175 int TextureMapperNode::compareGraphicsLayersZValue(const void* a, const void* b)
    176 {
    177     typedef const TextureMapperNode* NodePtr;
    178     const NodePtr* nodeA = static_cast<const NodePtr*>(a);
    179     const NodePtr* nodeB = static_cast<const NodePtr*>(b);
    180     return int(((*nodeA)->m_transforms.centerZ - (*nodeB)->m_transforms.centerZ) * 1000);
    181 }
    182 
    183 void TextureMapperNode::sortByZOrder(Vector<TextureMapperNode* >& array, int first, int last)
    184 {
    185     qsort(array.data(), array.size(), sizeof(TextureMapperNode*), TextureMapperNode::compareGraphicsLayersZValue);
    186 }
    187 
    188 bool TextureMapperNode::hasSurfaceDescendants() const
    189 {
    190     if (m_layerType == ClipLayer || m_layerType == TransparencyLayer || m_state.replicaLayer)
    191         return true;
    192 
    193     const int size = m_children.size();
    194     for (int i = 0; i < size; ++i) {
    195         if (TextureMapperNode* child = m_children[i]) {
    196             if (child->hasSurfaceDescendants())
    197                 return true;
    198         }
    199     }
    200     return false;
    201 }
    202 
    203 int TextureMapperNode::countDescendantsWithContent() const
    204 {
    205     if (!m_state.visible || m_state.opacity < 0.001)
    206         return 0;
    207 
    208     int descendantsWithContent = (m_state.drawsContent || m_currentContent.contentType != HTMLContentType) ? 1 : 0;
    209 
    210     const int size = m_children.size();
    211     for (int i = 0; i < size; ++i) {
    212         if (TextureMapperNode* child = m_children[i])
    213             descendantsWithContent += child->countDescendantsWithContent();
    214     }
    215 
    216     return descendantsWithContent;
    217 }
    218 
    219 TextureMapperNode* TextureMapperNode::toTextureMapperNode(GraphicsLayer* layer)
    220 {
    221     return layer ? static_cast<TextureMapperNode*>(layer->platformLayer()) : 0;
    222 }
    223 
    224 void TextureMapperNode::computeLayerType()
    225 {
    226     const bool selfHasContent = m_state.drawsContent || (m_currentContent.contentType != HTMLContentType);
    227     const bool hasDescendantsWithContent = m_state.descendantsWithContent - (selfHasContent ? 1 : 0);
    228     const bool hasTransparency = m_state.opacity < 0.99 || m_state.maskLayer;
    229     const bool hasReplica = m_state.replicaLayer;
    230 
    231     //  DefaultLayer: draws itself and its children directly to the current framebuffer.
    232     //                any layer that doesn't conform to the other rules is a DefaultLayer.
    233     m_layerType = DefaultLayer;
    234 
    235     //  RootLayer: the top level. Draws to a framebuffer, and the target texture draws into the viewport.
    236     //            only one layer is the root layer.
    237     if (!m_parent && !m_effectTarget) {
    238         m_layerType = RootLayer;
    239         return;
    240     }
    241 
    242     // A layer with no contents is always a default layer.
    243     if (!m_state.descendantsWithContent)
    244         return;
    245 
    246     //  ClipLayer: creates a new framebuffer, the size of the layer, and then paints it to the enclosing BitmapTexture with the layer's transform/opacity.
    247     //              A clip layer is a layer that masks to bounds, doesn't preserve 3D, has children, and has a transparency/mask or a non-rectangular transform.
    248     if (hasDescendantsWithContent && m_state.maskLayer) {
    249         m_layerType = ClipLayer;
    250         return;
    251     }
    252 
    253     //  ScissorLayer: draws to the current framebuffer, and applies an extra scissor before drawing its children.
    254     //                A scissor layer is a layer with children that masks to bounds, is not a transparency layer, and has a rectangular clip.
    255     if (m_state.masksToBounds && hasDescendantsWithContent) {
    256         if (hasTransparency || !m_state.transform.isIdentityOrTranslation() || m_parent->m_state.preserves3D)
    257             m_layerType = ClipLayer;
    258         else
    259             m_layerType = ScissorLayer;
    260         return;
    261     }
    262 
    263     //  TransparencyLayer: creates a new framebuffer idetical in size to the current framebuffer. Then draws the fb's texture to the current framebuffer with identity transform.
    264     //                     Used for layers with children and transparency/mask that preserve 3D or don't mask to bounds.
    265     if ((hasReplica && hasDescendantsWithContent) || (hasReplica && hasTransparency) || (hasTransparency && m_state.descendantsWithContent > 1))
    266         m_layerType = TransparencyLayer;
    267 }
    268 
    269 void TextureMapperNode::initializeTextureMapper(TextureMapper* textureMapper)
    270 {
    271     if (m_texture)
    272         return;
    273     m_surface = textureMapper->createTexture();
    274     m_replicaSurface = textureMapper->createTexture();
    275     m_texture = textureMapper->createTexture();
    276     cache()->mark(m_texture.get());
    277 }
    278 
    279 TextureMapperNode::TextureMapperNode()
    280     : m_layerType(DefaultLayer)
    281     , m_surface(0)
    282     , m_parent(0)
    283     , m_effectTarget(0)
    284     , m_platformClient(0)
    285     , m_cache(0)
    286 {
    287 }
    288 
    289 TextureMapperNode* TextureMapperNode::rootLayer()
    290 {
    291     if (m_effectTarget)
    292         return m_effectTarget->rootLayer();
    293     if (m_parent)
    294         return m_parent->rootLayer();
    295     return this;
    296 }
    297 
    298 void TextureMapperNode::invalidateTransform()
    299 {
    300     m_transforms.dirty = true;
    301     if (m_layerType != ClipLayer)
    302         m_state.dirty = true;
    303     if (m_state.replicaLayer)
    304         m_state.replicaLayer->invalidateTransform();
    305     const int size = m_children.size();
    306     for (int i = 0; i < size; ++i) {
    307         if (TextureMapperNode* layer = m_children[i])
    308             layer->invalidateTransform();
    309     }
    310 }
    311 
    312 void TextureMapperNode::computeLocalTransform()
    313 {
    314     if (!m_transforms.localDirty)
    315         return;
    316     const float originX = m_state.anchorPoint.x() * m_size.width();
    317     const float originY = m_state.anchorPoint.y() * m_size.height();
    318     m_transforms.local =
    319         TransformationMatrix()
    320         .translate3d(originX + m_state.pos.x(), originY + m_state.pos.y(), m_state.anchorPoint.z())
    321         .multiply(m_state.transform)
    322         .translate3d(-originX, -originY, -m_state.anchorPoint.z());
    323     m_transforms.localDirty = false;
    324 }
    325 
    326 void TextureMapperNode::flattenTo2DSpaceIfNecessary()
    327 {
    328     if (m_state.preserves3D)
    329         return;
    330 
    331     m_transforms.forDescendants.setM13(0);
    332     m_transforms.forDescendants.setM23(0);
    333     m_transforms.forDescendants.setM31(0);
    334     m_transforms.forDescendants.setM32(0);
    335     m_transforms.forDescendants.setM33(1);
    336     m_transforms.forDescendants.setM34(0);
    337     m_transforms.forDescendants.setM43(0);
    338 }
    339 
    340 IntSize TextureMapperNode::nearestSurfaceSize() const
    341 {
    342     if (m_layerType == ClipLayer || m_layerType == RootLayer)
    343         return m_surface && !m_surface->size().isEmpty() ? m_surface->size() : m_size;
    344     return m_parent->nearestSurfaceSize();
    345 }
    346 
    347 void TextureMapperNode::computeReplicaTransform()
    348 {
    349     if (!m_state.replicaLayer)
    350         return;
    351 
    352     m_nearestSurfaceSize = nearestSurfaceSize();
    353 
    354     if (m_layerType != TransparencyLayer) {
    355         m_transforms.replica = TransformationMatrix(m_transforms.target).multiply(m_state.replicaLayer->m_transforms.local);
    356         return;
    357     }
    358 
    359     const float originX = m_transforms.target.m41();
    360     const float originY = m_transforms.target.m42();
    361     m_transforms.replica =
    362             TransformationMatrix()
    363                 .translate(originX, originY)
    364                 .multiply(m_state.replicaLayer->m_transforms.local)
    365                 .translate(-originX, -originY);
    366 }
    367 
    368 void TextureMapperNode::computeTransformations()
    369 {
    370     if (!m_transforms.dirty)
    371         return;
    372 
    373     m_transforms.dirty = false;
    374     if ((m_size.isEmpty() && m_state.masksToBounds))
    375         return;
    376 
    377     TextureMapperNode* parent = m_parent;
    378     computeLocalTransform();
    379 
    380     m_transforms.target = TransformationMatrix(parent ? parent->m_transforms.forDescendants : TransformationMatrix()).multiply(m_transforms.local);
    381     m_transforms.forDescendants = (m_layerType == ClipLayer ? TransformationMatrix() : m_transforms.target);
    382 
    383     if (m_effectTarget)
    384         return;
    385 
    386     m_transforms.targetBoundingRect = IntRect(m_transforms.target.mapRect(entireRect()));
    387     if (m_state.replicaLayer)
    388         m_state.replicaLayer->computeTransformations();
    389 
    390     flattenTo2DSpaceIfNecessary();
    391 
    392     if (!m_state.backfaceVisibility && m_transforms.target.inverse().m33() < 0) {
    393         m_state.visible = false;
    394         return;
    395     }
    396     m_state.visible = true;
    397 
    398     if (parent && parent->m_state.preserves3D)
    399         m_transforms.centerZ = m_transforms.target.mapPoint(FloatPoint3D(m_size.width() / 2, m_size.height() / 2, 0)).z();
    400 
    401     if (!m_children.size())
    402         return;
    403 
    404     if (m_state.childrenTransform.isIdentity())
    405         return;
    406 
    407     const FloatPoint centerPoint = FloatPoint(m_size.width() / 2, m_size.height() / 2);
    408     if (m_transforms.perspectiveDirty)
    409         m_transforms.perspective = TransformationMatrix()
    410             .translate(centerPoint.x(), centerPoint.y())
    411             .multiply(m_state.childrenTransform)
    412             .translate(-centerPoint.x(), -centerPoint.y());
    413     m_transforms.perspectiveDirty = false;
    414     m_transforms.forDescendants.multiply(m_transforms.perspective);
    415 }
    416 
    417 void TextureMapperNode::uploadTextureFromContent(TextureMapper* textureMapper, const IntRect& visibleRect, GraphicsLayer* layer)
    418 {
    419     if (m_size.isEmpty() || !layer) {
    420         m_texture->destroy();
    421         return;
    422     }
    423 
    424     if (m_currentContent.contentType == DirectImageContentType) {
    425         if (m_currentContent.image)
    426             m_texture->setContentsToImage(m_currentContent.image.get());
    427         return;
    428     }
    429 
    430     if (m_currentContent.contentType == MediaContentType) {
    431         if (!m_currentContent.media)
    432             return;
    433         m_texture->reset(m_size, true);
    434         PlatformGraphicsContext* platformContext = m_texture->beginPaintMedia();
    435         GraphicsContext context(platformContext);
    436         m_currentContent.media->paint(&context);
    437         m_texture->endPaint();
    438         return;
    439     }
    440 
    441     const bool needsReset = (m_texture->contentSize() != m_size) || !m_texture->isValid();
    442     if ((m_currentContent.contentType != HTMLContentType)
    443         || (!m_currentContent.needsDisplay && m_currentContent.needsDisplayRect.isEmpty() && !needsReset))
    444         return;
    445 
    446     IntRect dirtyRect = IntRect(0, 0, m_size.width(), m_size.height());
    447     if (!needsReset && !m_currentContent.needsDisplay)
    448         dirtyRect.intersect(m_currentContent.needsDisplayRect);
    449 
    450     if (needsReset)
    451         m_texture->reset(m_size, m_state.contentsOpaque);
    452 
    453     {
    454         GraphicsContext context(m_texture->beginPaint(dirtyRect));
    455         if (textureMapper) {
    456             context.setImageInterpolationQuality(textureMapper->imageInterpolationQuality());
    457             context.setTextDrawingMode(textureMapper->textDrawingMode());
    458         }
    459         layer->paintGraphicsLayerContents(context, dirtyRect);
    460     }
    461     m_texture->endPaint();
    462     m_currentContent.needsDisplay = false;
    463 }
    464 
    465 
    466 void TextureMapperNode::paint(TextureMapper* textureMapper, const TextureMapperContentLayer::PaintOptions& options)
    467 {
    468     ASSERT(m_layerType == RootLayer);
    469     if (m_size.isEmpty())
    470         return;
    471 
    472     TexmapPaintOptions opt;
    473     opt.opacity = 1;
    474     opt.rootLayer = this;
    475     opt.scissorRect = options.targetRect;
    476     opt.visibleRect = options.visibleRect;
    477     opt.textureMapper = textureMapper;
    478     opt.surface = 0;
    479     opt.cache = m_cache;
    480     paintRecursive(opt);
    481 
    482     if (textureMapper->allowSurfaceForRoot() || m_state.hasSurfaceDescendants) {
    483         textureMapper->bindSurface(0);
    484         textureMapper->paintToTarget(*m_surface.get(), options.viewportSize, options.transform, options.opacity * m_state.opacity, options.targetRect);
    485     }
    486     m_cache->purge();
    487 }
    488 
    489 void TextureMapperNode::paintSelf(const TexmapPaintOptions& options)
    490 {
    491     if (m_size.isEmpty() || (!m_state.drawsContent && m_currentContent.contentType == HTMLContentType))
    492         return;
    493 
    494     RefPtr<BitmapTexture> replicaMaskTexture;
    495     m_texture->unpack();
    496 
    497     RefPtr<BitmapTexture> maskTexture = m_state.maskLayer ? m_state.maskLayer->m_texture : 0;
    498     if (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer)
    499         replicaMaskTexture = m_state.replicaLayer->m_state.maskLayer->m_texture;
    500 
    501     if (maskTexture)
    502         maskTexture->unpack();
    503 
    504     if (replicaMaskTexture)
    505         replicaMaskTexture->unpack();
    506 
    507     const float opacity = options.isSurface ? 1 : options.opacity;
    508 
    509     if (m_state.replicaLayer && !options.isSurface)
    510         options.textureMapper->drawTexture(*m_texture.get(), replicaRect(), m_transforms.replica,
    511                          opacity * m_state.replicaLayer->m_state.opacity,
    512                          replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get());
    513 
    514     const IntRect rect = m_layerType == ClipLayer ? entireRect() : targetRect();
    515     const TransformationMatrix transform = m_layerType == ClipLayer ? TransformationMatrix() : m_transforms.target;
    516     options.textureMapper->drawTexture(*m_texture.get(), rect, transform, opacity, options.isSurface ? 0 : maskTexture.get());
    517     options.cache->mark(m_texture.get());
    518 }
    519 
    520 bool TextureMapperNode::paintReplica(const TexmapPaintOptions& options)
    521 {
    522     BitmapTexture& texture = *m_surface.get();
    523     TextureMapperNode* replica = m_state.replicaLayer;
    524     RefPtr<BitmapTexture> maskTexture;
    525     if (TextureMapperNode* mask = m_state.maskLayer)
    526         maskTexture = mask->m_texture;
    527     RefPtr<BitmapTexture> replicaMaskTexture;
    528     if (!replica)
    529         return false;
    530 
    531     if (replica && replica->m_state.maskLayer)
    532         replicaMaskTexture = replica->m_state.maskLayer->m_texture;
    533 
    534     if (replicaMaskTexture)
    535         replicaMaskTexture->unpack();
    536     ASSERT(m_replicaSurface);
    537     m_replicaSurface->reset(options.surface->size());
    538     m_replicaSurface->setOffset(options.surface->offset());
    539     options.cache->mark(m_replicaSurface.get());
    540     options.textureMapper->bindSurface(m_replicaSurface.get());
    541     options.textureMapper->drawTexture(texture, replicaRect(), m_transforms.replica, replica->m_state.opacity, replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get());
    542     options.textureMapper->drawTexture(texture, IntRect(IntPoint(0, 0), options.surface->size()), TransformationMatrix(), 1.0f, maskTexture.get());
    543     options.textureMapper->bindSurface(options.surface);
    544     options.cache->mark(options.surface);
    545     options.textureMapper->drawTexture(*m_replicaSurface.get(), IntRect(IntPoint(0, 0), options.surface->size()), TransformationMatrix(), options.opacity, 0);
    546     return true;
    547 }
    548 
    549 void TextureMapperNode::paintSurface(const TexmapPaintOptions& options)
    550 {
    551     if (m_layerType == RootLayer || m_layerType == DefaultLayer || m_layerType == ScissorLayer)
    552         return;
    553 
    554     RefPtr<BitmapTexture> maskTexture;
    555     if (TextureMapperNode* mask = m_state.maskLayer)
    556         maskTexture = mask->m_texture;
    557 
    558     ASSERT(m_surface);
    559     BitmapTexture& texture = *m_surface.get();
    560     if (maskTexture)
    561         maskTexture->unpack();
    562     texture.unpack();
    563 
    564     if (paintReplica(options))
    565         return;
    566 
    567     options.textureMapper->bindSurface(options.surface);
    568     options.textureMapper->drawTexture(texture,
    569                              m_layerType == TransparencyLayer ? IntRect(IntPoint(0, 0), options.surface->size()) :
    570                              targetRect(),
    571                              m_layerType == TransparencyLayer ? TransformationMatrix() : m_transforms.target,
    572                              options.opacity, maskTexture.get());
    573     options.cache->mark(&texture);
    574 }
    575 
    576 void TextureMapperNode::paintSelfAndChildren(const TexmapPaintOptions& options, TexmapPaintOptions& optionsForDescendants)
    577 {
    578     bool didPaintSelf = false;
    579     if (!m_state.preserves3D || m_children.isEmpty()) {
    580         paintSelf(options);
    581         didPaintSelf = true;
    582     }
    583 
    584     if (m_children.isEmpty() && !options.isSurface)
    585         return;
    586 
    587     if (m_layerType == ScissorLayer)
    588         optionsForDescendants.scissorRect.intersect(m_transforms.target.mapRect(IntRect(0, 0, m_size.width(), m_size.height())));
    589 
    590     for (int i = 0; i < m_children.size(); ++i) {
    591         TextureMapperNode* layer = m_children[i];
    592         if (!layer)
    593             continue;
    594 
    595         if (!didPaintSelf && layer->m_transforms.centerZ >= 0) {
    596             paintSelf(options);
    597             didPaintSelf = true;
    598         }
    599         layer->paintRecursive(optionsForDescendants);
    600         if (options.isSurface) {
    601             ASSERT(m_surface);
    602             options.cache->mark(m_surface.get());
    603             options.textureMapper->bindSurface(m_surface.get());
    604         }
    605     }
    606     if (!didPaintSelf) {
    607         paintSelf(options);
    608         didPaintSelf = true;
    609     }
    610 }
    611 
    612 void TextureMapperNode::paintRecursive(TexmapPaintOptions options)
    613 {
    614     bool isDirty = m_state.dirty;
    615     m_state.dirty = false;
    616 
    617     if ((m_size.isEmpty() && (m_state.masksToBounds
    618         || m_children.isEmpty())) || !m_state.visible || options.opacity < 0.01 || m_state.opacity < 0.01)
    619         return;
    620 
    621     computeReplicaTransform();
    622 
    623     if (m_state.maskLayer)
    624         m_state.maskLayer->m_state.dirty = false;
    625 
    626     if (m_state.replicaLayer) {
    627         m_state.replicaLayer->m_state.dirty = false;
    628         if (m_state.replicaLayer->m_state.maskLayer)
    629             m_state.replicaLayer->m_state.maskLayer->m_state.dirty = false;
    630     }
    631 
    632     const bool isSurface = (m_layerType == ClipLayer
    633                             || m_layerType == TransparencyLayer
    634                             || (m_layerType == RootLayer
    635                                 && (options.textureMapper->allowSurfaceForRoot() || m_state.hasSurfaceDescendants)
    636                                 ));
    637 
    638     const IntRect boundingRectfromNearestSurface = m_transforms.targetBoundingRect;
    639 
    640     options.opacity *= m_state.opacity;
    641 
    642     TexmapPaintOptions optionsForDescendants(options);
    643     optionsForDescendants.opacity = isSurface ? 1 : options.opacity;
    644     options.isSurface = isSurface;
    645 
    646     if (m_layerType == ClipLayer) {
    647         optionsForDescendants.visibleRect = TransformationMatrix().translate(-boundingRectfromNearestSurface.x(), -boundingRectfromNearestSurface.y()).mapRect(options.visibleRect);
    648         optionsForDescendants.scissorRect = IntRect(0, 0, m_size.width(), m_size.height());
    649     }
    650 
    651     if (m_layerType == ScissorLayer)
    652         optionsForDescendants.scissorRect.intersect(m_transforms.targetBoundingRect);
    653     options.textureMapper->setClip(optionsForDescendants.scissorRect);
    654 
    655     TextureMapperCacheLock(m_texture.get());
    656     TextureMapperCacheLock(m_surface.get());
    657     TextureMapperCacheLock(m_replicaSurface.get());
    658 
    659     options.cache->purge();
    660 
    661     if (isSurface) {
    662         ASSERT(m_surface);
    663         if (!m_surface->isValid())
    664             isDirty = true;
    665         if (m_state.tiled) {
    666             m_surface->reset(options.visibleRect.size());
    667             m_surface->setOffset(options.visibleRect.location());
    668         } else if (isDirty)
    669             m_surface->reset(m_layerType == TransparencyLayer ? options.surface->size() : m_size);
    670         options.cache->mark(m_surface.get());
    671         options.textureMapper->bindSurface(m_surface.get());
    672         optionsForDescendants.surface = m_surface.get();
    673     } else if (m_surface)
    674         m_surface->destroy();
    675 
    676     if (isDirty || !isSurface || m_state.tiled || !m_surface->isValid())
    677         paintSelfAndChildren(options, optionsForDescendants);
    678 
    679     paintSurface(options);
    680 }
    681 
    682 TextureMapperNode::~TextureMapperNode()
    683 {
    684     setNeedsDisplay();
    685     {
    686         const int childrenSize = m_children.size();
    687         for (int i = childrenSize-1; i >= 0; --i) {
    688             ASSERT(m_children[i]->m_parent == this);
    689             m_children[i]->m_parent = 0;
    690         }
    691     }
    692     if (m_parent)
    693         m_parent->m_children.remove(m_parent->m_children.find(this));
    694     if (m_cache)
    695         delete m_cache;
    696 }
    697 
    698 void TextureMapperNode::performPostSyncOperations()
    699 {
    700     const LayerType prevLayerType = m_layerType;
    701     computeLayerType();
    702     if (prevLayerType != m_layerType)
    703         m_state.dirty = true;
    704     if (m_transforms.dirty)
    705         setNeedsDisplay();
    706 
    707     computeTransformations();
    708     if (m_state.maskLayer && !m_state.dirty)
    709         m_state.dirty = m_state.maskLayer->m_state.dirty;
    710     if (m_state.replicaLayer && !m_state.dirty)
    711         m_state.dirty = m_state.replicaLayer->m_state.dirty;
    712 
    713     const int size = m_children.size();
    714 
    715     for (int i = size - 1; i >= 0; --i) {
    716         TextureMapperNode* layer = m_children[i];
    717 
    718         layer->performPostSyncOperations();
    719         if (!m_state.dirty)
    720             m_state.dirty = layer->m_state.dirty;
    721     }
    722     m_state.hasSurfaceDescendants = hasSurfaceDescendants();
    723     if (m_state.dirty)
    724         m_state.descendantsWithContent = countDescendantsWithContent();
    725 
    726     if (m_state.preserves3D)
    727         sortByZOrder(m_children, 0, size);
    728     if (m_state.dirty)
    729         setNeedsDisplay();
    730 }
    731 
    732 void TextureMapperNode::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, bool recurse)
    733 {
    734     TextureMapper* textureMapper = rootLayer()->m_platformClient->textureMapper();
    735     syncCompositingStateInternal(graphicsLayer, recurse, textureMapper);
    736     performPostSyncOperations();
    737 }
    738 
    739 void TextureMapperNode::syncCompositingStateSelf(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper)
    740 {
    741     const int changeMask = graphicsLayer->changeMask();
    742     initializeTextureMapper(textureMapper);
    743     const TextureMapperNode::ContentData& pendingContent = graphicsLayer->pendingContent();
    744     if (changeMask == NoChanges && pendingContent.needsDisplayRect.isEmpty() && !pendingContent.needsDisplay)
    745         return;
    746 
    747     setNeedsDisplay();
    748     if (m_parent)
    749         m_parent->m_state.dirty = true;
    750 
    751     if (m_currentContent.contentType == HTMLContentType && (changeMask & ParentChange)) {
    752         // The WebCore compositor manages item ownership. We have to make sure graphicsview doesn't
    753         // try to snatch that ownership.
    754 
    755         if (!graphicsLayer->parent())
    756             m_parent = 0;
    757         else
    758             m_parent = toTextureMapperNode(graphicsLayer->parent());
    759 
    760         if (!graphicsLayer->parent() && m_parent) {
    761             size_t index = m_parent->m_children.find(this);
    762             m_parent->m_children.remove(index);
    763         }
    764     }
    765 
    766     if (changeMask & ChildrenChange) {
    767         m_children.clear();
    768         for (size_t i = 0; i < graphicsLayer->children().size(); ++i) {
    769             if (TextureMapperNode* child = toTextureMapperNode(graphicsLayer->children()[i])) {
    770                 if (!child)
    771                     continue;
    772                 m_children.append(child);
    773                 child->m_parent = this;
    774             }
    775         }
    776         m_state.dirty = true;
    777     }
    778 
    779     if (changeMask & (SizeChange | ContentsRectChange)) {
    780         IntSize wantedSize = IntSize(graphicsLayer->size().width(), graphicsLayer->size().height());
    781         if (wantedSize.isEmpty() && pendingContent.contentType == HTMLContentType)
    782             wantedSize = IntSize(graphicsLayer->contentsRect().width(), graphicsLayer->contentsRect().height());
    783 
    784         if (wantedSize != m_size) {
    785             m_size = IntSize(wantedSize.width(), wantedSize.height());
    786             if (m_platformClient)
    787                 m_platformClient->setSizeChanged(m_size);
    788             const bool needsTiling = m_size.width() > 2000 || m_size.height() > 2000;
    789             if (m_state.tiled != needsTiling)
    790                 m_state.tiled = needsTiling;
    791             m_state.dirty = true;
    792         }
    793     }
    794 
    795     if (changeMask & MaskLayerChange) {
    796        if (TextureMapperNode* layer = toTextureMapperNode(graphicsLayer->maskLayer()))
    797            layer->m_effectTarget = this;
    798     }
    799 
    800     if (changeMask & ReplicaLayerChange) {
    801        if (TextureMapperNode* layer = toTextureMapperNode(graphicsLayer->replicaLayer()))
    802            layer->m_effectTarget = this;
    803     }
    804 
    805     if (changeMask & (TransformChange | SizeChange | AnchorPointChange | PositionChange))
    806         m_transforms.localDirty = true;
    807 
    808     if (changeMask & (ChildrenTransformChange | SizeChange))
    809         m_transforms.perspectiveDirty = true;
    810 
    811     if (changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange | ContentsRectChange | BackfaceVisibilityChange | PositionChange | MaskLayerChange | DrawsContentChange | ContentChange | ReplicaLayerChange))    {
    812         // Due to the differences between the way WebCore handles transforms and the way Qt handles transforms,
    813         // all these elements affect the transforms of all the descendants.
    814         invalidateTransform();
    815     }
    816 
    817     if (changeMask & DisplayChange)
    818         m_state.dirty = true;
    819 
    820     m_state.maskLayer = toTextureMapperNode(graphicsLayer->maskLayer());
    821     m_state.replicaLayer = toTextureMapperNode(graphicsLayer->replicaLayer());
    822     m_state.pos = graphicsLayer->position();
    823     m_state.anchorPoint = graphicsLayer->anchorPoint();
    824     m_state.size = graphicsLayer->size();
    825     m_state.transform = graphicsLayer->transform();
    826     m_state.contentsRect = graphicsLayer->contentsRect();
    827     m_state.opacity = graphicsLayer->opacity();
    828     m_state.contentsRect = graphicsLayer->contentsRect();
    829     m_state.preserves3D = graphicsLayer->preserves3D();
    830     m_state.masksToBounds = graphicsLayer->masksToBounds();
    831     m_state.drawsContent = graphicsLayer->drawsContent();
    832     m_state.contentsOpaque = graphicsLayer->contentsOpaque();
    833     m_state.backfaceVisibility = graphicsLayer->backfaceVisibility();
    834     m_state.childrenTransform = graphicsLayer->childrenTransform();
    835     m_currentContent.contentType = pendingContent.contentType;
    836     m_currentContent.image = pendingContent.image;
    837     m_currentContent.media = pendingContent.media;
    838     m_currentContent.backgroundColor = pendingContent.backgroundColor;
    839     m_currentContent.needsDisplay = m_currentContent.needsDisplay || pendingContent.needsDisplay;
    840     m_currentContent.needsDisplayRect.unite(pendingContent.needsDisplayRect);
    841 
    842 }
    843 
    844 void TextureMapperNode::syncCompositingStateInternal(GraphicsLayerTextureMapper* graphicsLayer, bool recurse, TextureMapper* textureMapper)
    845 {
    846     syncCompositingStateSelf(graphicsLayer, textureMapper);
    847 
    848     graphicsLayer->didSynchronize();
    849 
    850     if (m_state.maskLayer) {
    851         m_state.maskLayer->syncCompositingStateInternal(toGraphicsLayerTextureMapper(graphicsLayer->maskLayer()), false, textureMapper);
    852         if (m_state.maskLayer->m_size.isEmpty())
    853             m_state.maskLayer->m_size = m_size;
    854     }
    855 
    856     if (m_state.replicaLayer)
    857         m_state.replicaLayer->syncCompositingStateInternal(toGraphicsLayerTextureMapper(graphicsLayer->replicaLayer()), false, textureMapper);
    858 
    859     if (m_state.dirty)
    860         uploadTextureFromContent(textureMapper, m_state.visibleRect, graphicsLayer);
    861 
    862     m_currentContent.needsDisplayRect = IntRect();
    863     m_currentContent.needsDisplay = false;
    864 
    865     if (!recurse)
    866         return;
    867 
    868     Vector<GraphicsLayer*> children = graphicsLayer->children();
    869     for (int i = children.size() - 1; i >= 0; --i) {
    870         TextureMapperNode* node = toTextureMapperNode(children[i]);
    871         if (!node)
    872             continue;
    873         node->syncCompositingStateInternal(toGraphicsLayerTextureMapper(children[i]), true, textureMapper);
    874     }
    875 }
    876 
    877 }
    878