• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
Entry()34         Entry() : previousCost(0) { }
computeCost() const35         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         }
Entry(BitmapTexture * newTexture)43         Entry(BitmapTexture* newTexture)
44             : texture(newTexture)
45         {
46         }
operator ==(const Entry & other) const47         bool operator==(const Entry& other) const { return texture == other.texture; }
48         int previousCost;
49     };
50 
TextureMapperCache()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 
purge()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 
mark(BitmapTexture * texture)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:
TextureMapperCacheLock(BitmapTexture * texture)114     TextureMapperCacheLock(BitmapTexture* texture) : m_texture(texture)
115     {
116         if (m_texture)
117             m_texture->lock();
118     }
~TextureMapperCacheLock()119     ~TextureMapperCacheLock()
120     {
121         if (m_texture)
122             m_texture->unlock();
123     }
124 
125 private:
126     RefPtr<BitmapTexture> m_texture;
127 };
128 
129 
cache()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 
setNeedsDisplayInRect(IntRect rect)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 
setNeedsDisplay()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 
setPlatformLayerClient(TextureMapperLayerClient * client)170 void TextureMapperNode::setPlatformLayerClient(TextureMapperLayerClient* client)
171 {
172     m_platformClient = client;
173 }
174 
compareGraphicsLayersZValue(const void * a,const void * b)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 
sortByZOrder(Vector<TextureMapperNode * > & array,int first,int last)183 void TextureMapperNode::sortByZOrder(Vector<TextureMapperNode* >& array, int first, int last)
184 {
185     qsort(array.data(), array.size(), sizeof(TextureMapperNode*), TextureMapperNode::compareGraphicsLayersZValue);
186 }
187 
hasSurfaceDescendants() const188 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 
countDescendantsWithContent() const203 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 
toTextureMapperNode(GraphicsLayer * layer)219 TextureMapperNode* TextureMapperNode::toTextureMapperNode(GraphicsLayer* layer)
220 {
221     return layer ? static_cast<TextureMapperNode*>(layer->platformLayer()) : 0;
222 }
223 
computeLayerType()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 
initializeTextureMapper(TextureMapper * textureMapper)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 
TextureMapperNode()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 
rootLayer()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 
invalidateTransform()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 
computeLocalTransform()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 
flattenTo2DSpaceIfNecessary()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 
nearestSurfaceSize() const340 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 
computeReplicaTransform()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 
computeTransformations()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 
uploadTextureFromContent(TextureMapper * textureMapper,const IntRect & visibleRect,GraphicsLayer * layer)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 
paint(TextureMapper * textureMapper,const TextureMapperContentLayer::PaintOptions & options)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 
paintSelf(const TexmapPaintOptions & options)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 
paintReplica(const TexmapPaintOptions & options)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 
paintSurface(const TexmapPaintOptions & options)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 
paintSelfAndChildren(const TexmapPaintOptions & options,TexmapPaintOptions & optionsForDescendants)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 
paintRecursive(TexmapPaintOptions options)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 
~TextureMapperNode()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 
performPostSyncOperations()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 
syncCompositingState(GraphicsLayerTextureMapper * graphicsLayer,bool recurse)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 
syncCompositingStateSelf(GraphicsLayerTextureMapper * graphicsLayer,TextureMapper * textureMapper)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 
syncCompositingStateInternal(GraphicsLayerTextureMapper * graphicsLayer,bool recurse,TextureMapper * textureMapper)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