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