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
25namespace WebCore {
26
27class TextureMapperCache {
28public:
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
67void 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
90void 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
112class TextureMapperCacheLock {
113public:
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
125private:
126    RefPtr<BitmapTexture> m_texture;
127};
128
129
130TextureMapperCache* 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
140void 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
160void 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
170void TextureMapperNode::setPlatformLayerClient(TextureMapperLayerClient* client)
171{
172    m_platformClient = client;
173}
174
175int 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
183void TextureMapperNode::sortByZOrder(Vector<TextureMapperNode* >& array, int first, int last)
184{
185    qsort(array.data(), array.size(), sizeof(TextureMapperNode*), TextureMapperNode::compareGraphicsLayersZValue);
186}
187
188bool 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
203int 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
219TextureMapperNode* TextureMapperNode::toTextureMapperNode(GraphicsLayer* layer)
220{
221    return layer ? static_cast<TextureMapperNode*>(layer->platformLayer()) : 0;
222}
223
224void 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
269void 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
279TextureMapperNode::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
289TextureMapperNode* 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
298void 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
312void 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
326void 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
340IntSize 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
347void 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
368void 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
417void 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
466void 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
489void 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
520bool 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
549void 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
576void 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
612void 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
682TextureMapperNode::~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
698void 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
732void TextureMapperNode::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, bool recurse)
733{
734    TextureMapper* textureMapper = rootLayer()->m_platformClient->textureMapper();
735    syncCompositingStateInternal(graphicsLayer, recurse, textureMapper);
736    performPostSyncOperations();
737}
738
739void 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
844void 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