| Differences between
and this patch
- a/WebCore/ChangeLog +22 lines
Lines 1-3 a/WebCore/ChangeLog_sec1
1
2009-01-15  Simon Fraser  <simon.fraser@apple.com>
2
3
        Reviewed by NOBODY (OOPS!).
4
5
        https://bugs.webkit.org/show_bug.cgi?id=23357
6
        
7
        New files to support accelerated compositing at the RenderLayer
8
        level.
9
        
10
        * WebCore.xcodeproj/project.pbxproj:
11
        New files added to project.
12
        
13
        * rendering/RenderLayerBacking.cpp: Added.
14
        * rendering/RenderLayerBacking.h: Added.
15
        New object to store compositing-related data for a single
16
        RenderLayer.
17
        
18
        * rendering/RenderLayerCompositor.cpp: Added.
19
        * rendering/RenderLayerCompositor.h: Added.
20
        Per-RenderView controller object for compositing hierarchy
21
        maintenance.
22
1
2009-01-15  Dimitri Glazkov  <dglazkov@chromium.org>
23
2009-01-15  Dimitri Glazkov  <dglazkov@chromium.org>
2
24
3
        Reviewed by Darin Adler.
25
        Reviewed by Darin Adler.
- a/WebCore/WebCore.xcodeproj/project.pbxproj +16 lines
Lines 117-122 a/WebCore/WebCore.xcodeproj/project.pbxproj_sec1
117
		0A4844990CA44CB200B7BD48 /* SoftLinking.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A4844980CA44CB200B7BD48 /* SoftLinking.h */; settings = {ATTRIBUTES = (Private, ); }; };
117
		0A4844990CA44CB200B7BD48 /* SoftLinking.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A4844980CA44CB200B7BD48 /* SoftLinking.h */; settings = {ATTRIBUTES = (Private, ); }; };
118
		0F56028F0E4B76580065B038 /* RenderMarquee.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F56028D0E4B76580065B038 /* RenderMarquee.h */; };
118
		0F56028F0E4B76580065B038 /* RenderMarquee.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F56028D0E4B76580065B038 /* RenderMarquee.h */; };
119
		0F5602900E4B76580065B038 /* RenderMarquee.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F56028E0E4B76580065B038 /* RenderMarquee.cpp */; };
119
		0F5602900E4B76580065B038 /* RenderMarquee.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F56028E0E4B76580065B038 /* RenderMarquee.cpp */; };
120
		0F580CFD0F12DE9B0051D689 /* RenderLayerCompositor.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F580CF90F12DE9B0051D689 /* RenderLayerCompositor.h */; };
121
		0F580CFE0F12DE9B0051D689 /* RenderLayerCompositor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F580CFA0F12DE9B0051D689 /* RenderLayerCompositor.cpp */; };
122
		0F580CFF0F12DE9B0051D689 /* RenderLayerBacking.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F580CFB0F12DE9B0051D689 /* RenderLayerBacking.h */; };
123
		0F580D000F12DE9B0051D689 /* RenderLayerBacking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F580CFC0F12DE9B0051D689 /* RenderLayerBacking.cpp */; };
120
		0FC705210EB1815600B90AD8 /* AtomicStringHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC705200EB1815600B90AD8 /* AtomicStringHash.h */; settings = {ATTRIBUTES = (Private, ); }; };
124
		0FC705210EB1815600B90AD8 /* AtomicStringHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC705200EB1815600B90AD8 /* AtomicStringHash.h */; settings = {ATTRIBUTES = (Private, ); }; };
121
		0FD723820EC8BD9300CA5DD7 /* FloatQuad.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD723800EC8BD9300CA5DD7 /* FloatQuad.h */; settings = {ATTRIBUTES = (Private, ); }; };
125
		0FD723820EC8BD9300CA5DD7 /* FloatQuad.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD723800EC8BD9300CA5DD7 /* FloatQuad.h */; settings = {ATTRIBUTES = (Private, ); }; };
122
		0FD723830EC8BD9300CA5DD7 /* FloatQuad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD723810EC8BD9300CA5DD7 /* FloatQuad.cpp */; };
126
		0FD723830EC8BD9300CA5DD7 /* FloatQuad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD723810EC8BD9300CA5DD7 /* FloatQuad.cpp */; };
Lines 4931-4936 a/WebCore/WebCore.xcodeproj/project.pbxproj_sec2
4931
		0A4844980CA44CB200B7BD48 /* SoftLinking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SoftLinking.h; sourceTree = "<group>"; };
4935
		0A4844980CA44CB200B7BD48 /* SoftLinking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SoftLinking.h; sourceTree = "<group>"; };
4932
		0F56028D0E4B76580065B038 /* RenderMarquee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderMarquee.h; sourceTree = "<group>"; };
4936
		0F56028D0E4B76580065B038 /* RenderMarquee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderMarquee.h; sourceTree = "<group>"; };
4933
		0F56028E0E4B76580065B038 /* RenderMarquee.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderMarquee.cpp; sourceTree = "<group>"; };
4937
		0F56028E0E4B76580065B038 /* RenderMarquee.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderMarquee.cpp; sourceTree = "<group>"; };
4938
		0F580CF90F12DE9B0051D689 /* RenderLayerCompositor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderLayerCompositor.h; sourceTree = "<group>"; };
4939
		0F580CFA0F12DE9B0051D689 /* RenderLayerCompositor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderLayerCompositor.cpp; sourceTree = "<group>"; };
4940
		0F580CFB0F12DE9B0051D689 /* RenderLayerBacking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderLayerBacking.h; sourceTree = "<group>"; };
4941
		0F580CFC0F12DE9B0051D689 /* RenderLayerBacking.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderLayerBacking.cpp; sourceTree = "<group>"; };
4934
		0FC705200EB1815600B90AD8 /* AtomicStringHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtomicStringHash.h; sourceTree = "<group>"; };
4942
		0FC705200EB1815600B90AD8 /* AtomicStringHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtomicStringHash.h; sourceTree = "<group>"; };
4935
		0FD723800EC8BD9300CA5DD7 /* FloatQuad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FloatQuad.h; sourceTree = "<group>"; };
4943
		0FD723800EC8BD9300CA5DD7 /* FloatQuad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FloatQuad.h; sourceTree = "<group>"; };
4936
		0FD723810EC8BD9300CA5DD7 /* FloatQuad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FloatQuad.cpp; sourceTree = "<group>"; };
4944
		0FD723810EC8BD9300CA5DD7 /* FloatQuad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FloatQuad.cpp; sourceTree = "<group>"; };
Lines 13994-13999 a/WebCore/WebCore.xcodeproj/project.pbxproj_sec3
13994
				BCEA4839097D93020094C9E4 /* RenderInline.h */,
14002
				BCEA4839097D93020094C9E4 /* RenderInline.h */,
13995
				BCEA483A097D93020094C9E4 /* RenderLayer.cpp */,
14003
				BCEA483A097D93020094C9E4 /* RenderLayer.cpp */,
13996
				BCEA483B097D93020094C9E4 /* RenderLayer.h */,
14004
				BCEA483B097D93020094C9E4 /* RenderLayer.h */,
14005
				0F580CFB0F12DE9B0051D689 /* RenderLayerBacking.h */,
14006
				0F580CFC0F12DE9B0051D689 /* RenderLayerBacking.cpp */,
14007
				0F580CF90F12DE9B0051D689 /* RenderLayerCompositor.h */,
14008
				0F580CFA0F12DE9B0051D689 /* RenderLayerCompositor.cpp */,
13997
				A8EA73B60A1900E300A8EF5F /* RenderLegend.cpp */,
14009
				A8EA73B60A1900E300A8EF5F /* RenderLegend.cpp */,
13998
				A8EA73BD0A1900E300A8EF5F /* RenderLegend.h */,
14010
				A8EA73BD0A1900E300A8EF5F /* RenderLegend.h */,
13999
				ABB5419C0ACDDFE4002820EB /* RenderListBox.cpp */,
14011
				ABB5419C0ACDDFE4002820EB /* RenderListBox.cpp */,
Lines 16542-16547 a/WebCore/WebCore.xcodeproj/project.pbxproj_sec4
16542
				498391520F1E76B400C23782 /* DOMWebKitCSSMatrixInternal.h in Headers */,
16554
				498391520F1E76B400C23782 /* DOMWebKitCSSMatrixInternal.h in Headers */,
16543
				498391590F1E776900C23782 /* WebKitCSSMatrix.h in Headers */,
16555
				498391590F1E776900C23782 /* WebKitCSSMatrix.h in Headers */,
16544
				498391640F1E8EE100C23782 /* JSWebKitCSSMatrixConstructor.h in Headers */,
16556
				498391640F1E8EE100C23782 /* JSWebKitCSSMatrixConstructor.h in Headers */,
16557
				0F580CFD0F12DE9B0051D689 /* RenderLayerCompositor.h in Headers */,
16558
				0F580CFF0F12DE9B0051D689 /* RenderLayerBacking.h in Headers */,
16545
			);
16559
			);
16546
			runOnlyForDeploymentPostprocessing = 0;
16560
			runOnlyForDeploymentPostprocessing = 0;
16547
		};
16561
		};
Lines 18501-18506 a/WebCore/WebCore.xcodeproj/project.pbxproj_sec5
18501
				498391510F1E76B400C23782 /* DOMWebKitCSSMatrix.mm in Sources */,
18515
				498391510F1E76B400C23782 /* DOMWebKitCSSMatrix.mm in Sources */,
18502
				498391580F1E776900C23782 /* WebKitCSSMatrix.cpp in Sources */,
18516
				498391580F1E776900C23782 /* WebKitCSSMatrix.cpp in Sources */,
18503
				498391630F1E8EE100C23782 /* JSWebKitCSSMatrixConstructor.cpp in Sources */,
18517
				498391630F1E8EE100C23782 /* JSWebKitCSSMatrixConstructor.cpp in Sources */,
18518
				0F580CFE0F12DE9B0051D689 /* RenderLayerCompositor.cpp in Sources */,
18519
				0F580D000F12DE9B0051D689 /* RenderLayerBacking.cpp in Sources */,
18504
			);
18520
			);
18505
			runOnlyForDeploymentPostprocessing = 0;
18521
			runOnlyForDeploymentPostprocessing = 0;
18506
		};
18522
		};
- a/WebCore/rendering/RenderLayerBacking.cpp +1271 lines
Line 0 a/WebCore/rendering/RenderLayerBacking.cpp_sec1
1
/*
2
 * Copyright (C) 2009 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 *
8
 * 1.  Redistributions of source code must retain the above copyright
9
 *     notice, this list of conditions and the following disclaimer. 
10
 * 2.  Redistributions in binary form must reproduce the above copyright
11
 *     notice, this list of conditions and the following disclaimer in the
12
 *     documentation and/or other materials provided with the distribution. 
13
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14
 *     its contributors may be used to endorse or promote products derived
15
 *     from this software without specific prior written permission. 
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
28
29
#include "config.h"
30
31
#if USE(ACCELERATED_COMPOSITING)
32
33
#include "AnimationController.h"
34
#include "CSSStyleSelector.h"
35
#include "FrameView.h"
36
#include "GraphicsContext.h"
37
#include "GraphicsLayer.h"
38
#include "HitTestRequest.h"
39
#include "HitTestResult.h"
40
#include "HTMLNames.h"
41
#include "RenderImage.h"
42
#include "RenderLayerCompositor.h"
43
#include "RenderVideo.h"
44
#include "RenderView.h"
45
46
#include "RenderLayerBacking.h"
47
48
using namespace std;
49
50
namespace WebCore {
51
52
struct LayerHitTestData {
53
    LayerHitTestData(RenderLayer* inRootLayer, const HitTestRequest& inRequest, HitTestResult& inResult, const IntRect& hitTestRect)
54
    : m_rootLayer(inRootLayer)
55
    , m_request(inRequest)
56
    , m_hitTestRect(hitTestRect)
57
    , m_result(inResult)
58
    {
59
    }
60
    
61
    RenderLayer* m_rootLayer;
62
    const HitTestRequest& m_request;
63
    const IntRect& m_hitTestRect;
64
    HitTestResult& m_result;
65
};
66
67
68
RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
69
    : m_owningLayer(layer)
70
    , m_ancestorClippingLayer(0)
71
    , m_graphicsLayer(0)
72
    , m_contentsLayer(0)
73
    , m_clippingLayer(0)
74
    , m_forceCompositingLayer(false)
75
    , m_isSimpleContainerCompositingLayer(false)
76
    , m_simpleCompositingLayerStatusDirty(true)
77
    , m_compositingContentOffsetDirty(true)
78
{
79
    createGraphicsLayer();
80
}
81
82
RenderLayerBacking::~RenderLayerBacking()
83
{
84
    updateClippingLayers(false, false);
85
    updateContentsLayer(false);
86
    destroyGraphicsLayer();
87
}
88
89
void RenderLayerBacking::createGraphicsLayer()
90
{
91
    m_graphicsLayer = GraphicsLayer::createGraphicsLayer(this);
92
    
93
#ifndef NDEBUG
94
    if (renderer()->node()->isDocumentNode())
95
        m_graphicsLayer->setName("Document Node");
96
    else {
97
        if (renderer()->node()->isHTMLElement() && renderer()->node()->hasID())
98
            m_graphicsLayer->setName(renderer()->renderName() + String(" ") + ((HTMLElement*)renderer()->node())->id());
99
        else
100
            m_graphicsLayer->setName(renderer()->renderName());
101
    }
102
#endif  // NDEBUG
103
104
    updateLayerOpacity();
105
    updateLayerTransform();
106
}
107
108
void RenderLayerBacking::destroyGraphicsLayer()
109
{
110
    if (m_graphicsLayer)
111
        m_graphicsLayer->removeFromParent();
112
113
    delete m_graphicsLayer;
114
    m_graphicsLayer = 0;
115
116
    delete m_contentsLayer;
117
    m_contentsLayer = 0;
118
119
    delete m_clippingLayer;
120
    m_clippingLayer = 0;
121
}
122
123
void RenderLayerBacking::updateLayerOpacity()
124
{
125
    m_graphicsLayer->setOpacity(compositingOpacity(renderer()->opacity()), 0, 0);
126
}
127
128
void RenderLayerBacking::updateLayerTransform()
129
{
130
    RenderStyle* style = renderer()->style();
131
    const IntRect borderBox = renderer()->borderBox();
132
133
    // FIXME: This should use m_owningLayer->transform(), but that currently has transform-origin
134
    // baked into it, and we don't want that.
135
    TransformationMatrix t;
136
    style->applyTransform(t, borderBox.size(), false);
137
138
    m_graphicsLayer->setTransform(t);
139
}
140
141
void RenderLayerBacking::updateAfterLayout()
142
{
143
    invalidateDrawingOptimizations();
144
    detectDrawingOptimizations();
145
146
    updateGraphicsLayerGeometry();
147
}
148
149
bool RenderLayerBacking::updateGraphicsLayers(bool needsContentsLayer, bool needsUpperClippingLayer, bool needsLowerClippingLayer, bool needsRepaint)
150
{
151
    bool layerConfigChanged = false;
152
    if (updateContentsLayer(needsContentsLayer))
153
        layerConfigChanged = true;
154
    
155
    if (updateClippingLayers(needsUpperClippingLayer, needsLowerClippingLayer))
156
        layerConfigChanged = true;
157
158
    // See if we can now use any drawing optimizations.
159
    bool didDrawContent = graphicsLayer()->drawsContent();
160
    invalidateDrawingOptimizations();
161
    detectDrawingOptimizations();
162
    if (!didDrawContent && graphicsLayer()->drawsContent())
163
        needsRepaint = true;
164
165
    // Set opacity, if it is not animating.
166
    if (!renderer()->animation()->isAnimatingPropertyOnRenderer(renderer(), CSSPropertyOpacity))
167
        updateLayerOpacity();
168
    
169
    // Set transform property, if it is not animating.
170
    if (!renderer()->animation()->isAnimatingPropertyOnRenderer(renderer(), CSSPropertyWebkitTransform))
171
        updateLayerTransform();
172
    
173
    updateGraphicsLayerGeometry();
174
    
175
    m_graphicsLayer->updateContentsRect();
176
    
177
    if (needsRepaint) {
178
        m_graphicsLayer->setNeedsDisplay();
179
        if (m_contentsLayer)
180
            m_contentsLayer->setNeedsDisplay();
181
    }
182
    
183
    return layerConfigChanged;
184
}
185
186
void RenderLayerBacking::updateGraphicsLayerGeometry()
187
{
188
    // If we haven't built z-order lists yet, wait until later.
189
    if (m_owningLayer->isStackingContext() && m_owningLayer->m_zOrderListsDirty)
190
        return;
191
192
    m_compositingContentOffsetDirty = true;
193
    
194
    RenderLayer* compAncestor = compositor()->enclosingCompositingLayer(m_owningLayer, false);
195
    IntRect ancestorCompositingBounds;
196
197
    const RenderLayer* rootLayer = m_owningLayer->root();
198
    
199
    // FIXME: optimize calculateCompositedBounds calls. Too many coord conversions in this code.
200
    if (compAncestor)
201
        ancestorCompositingBounds = compositor()->calculateCompositedBounds(compAncestor, rootLayer);
202
    
203
    IntRect compositingBounds = compositor()->calculateCompositedBounds(m_owningLayer, rootLayer);
204
205
    if (compAncestor && m_ancestorClippingLayer) {
206
        IntRect clippingLayerContentBox;
207
        // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
208
        // layer. Note that we call it with temporaryClipRects=true because normally when computing clip rects
209
        // for a compositing layer, rootLayer is the layer itself.
210
        IntRect infiniteRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX);
211
        IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
212
        m_owningLayer->calculateRects(compAncestor, infiniteRect, layerBounds, backgroundRect, foregroundRect, outlineRect, true);
213
        // FIXME: if the layer that is clipping has a transform, this does not work correctly.
214
        clippingLayerContentBox = backgroundRect;
215
        
216
        int absX = 0, absY = 0;
217
        compAncestor->convertToLayerCoords(rootLayer, absX, absY);
218
        clippingLayerContentBox.move(absX, absY);
219
220
        // Position relative to the compAncestor
221
        if (compAncestor->backing()->hasClippingLayer()) {
222
            IntRect parentClippingBox = compAncestor->renderer()->getOverflowClipRect(absX, absY);
223
            m_ancestorClippingLayer->setPosition(FloatPoint() + (clippingLayerContentBox.location() - parentClippingBox.location()));
224
        } else
225
            m_ancestorClippingLayer->setPosition(FloatPoint() + (clippingLayerContentBox.location() - ancestorCompositingBounds.location()));
226
227
        m_ancestorClippingLayer->setSize(clippingLayerContentBox.size());
228
229
        m_graphicsLayer->setPosition(FloatPoint() + (compositingBounds.location() - clippingLayerContentBox.location()));
230
    } else if (compAncestor && compAncestor->backing()->hasClippingLayer()) {
231
        // The clipping layer is the size of the ancestor's overflowClipRect, so account for
232
        // its offset in its containing layer.
233
        int absX = 0, absY = 0;
234
        compAncestor->convertToLayerCoords(rootLayer, absX, absY);
235
        IntRect clippingLayerContentBox = compAncestor->renderer()->getOverflowClipRect(absX, absY);
236
237
        m_graphicsLayer->setPosition(FloatPoint() + (compositingBounds.location() - clippingLayerContentBox.location()));
238
    } else
239
        m_graphicsLayer->setPosition(FloatPoint() + (compositingBounds.location() - ancestorCompositingBounds.location()));
240
    
241
    FloatSize oldSize = m_graphicsLayer->size();
242
    FloatSize newSize(compositingBounds.size());
243
    if (oldSize != newSize) {
244
        m_graphicsLayer->setSize(newSize);
245
        // A bounds change will almost always require redisplay. Usually that redisplay
246
        // will happen because of a repaint elsewhere, but not always:
247
        // e.g. see RenderView::setMaximalOutlineSize()
248
        m_graphicsLayer->setNeedsDisplay();
249
    }
250
251
    // If we have a layer that clips children, position it.
252
    if (m_clippingLayer) {
253
        int absX = 0, absY = 0;
254
        m_owningLayer->convertToLayerCoords(rootLayer, absX, absY);
255
        IntRect clippingLayerContentBox = renderer()->getOverflowClipRect(absX, absY);
256
        
257
        m_clippingLayer->setPosition(FloatPoint() + (clippingLayerContentBox.location() - compositingBounds.location()));
258
        m_clippingLayer->setSize(clippingLayerContentBox.size());
259
    }
260
    
261
    IntRect layerBounds = IntRect(m_owningLayer->xPos(), m_owningLayer->yPos(), renderer()->width(), renderer()->height());
262
263
    // Convert to absolute coords to match bbox.
264
    int absX = 0, absY = 0;
265
    m_owningLayer->convertToLayerCoords(rootLayer, absX, absY);
266
    layerBounds.move(absX - m_owningLayer->xPos(), absY - m_owningLayer->yPos());
267
268
    // Update properties that depend on layer dimensions
269
    const IntRect borderBox = renderer()->borderBox();
270
271
    FloatPoint3D transformOrigin = computeTransformOrigin(borderBox);
272
    // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set.
273
    FloatPoint  anchor(compositingBounds.width()  != 0.0f ? ((layerBounds.x() - compositingBounds.x()) + transformOrigin.x()) / compositingBounds.width()  : 0.5f,
274
                       compositingBounds.height() != 0.0f ? ((layerBounds.y() - compositingBounds.y()) + transformOrigin.y()) / compositingBounds.height() : 0.5f);
275
    m_graphicsLayer->setAnchorPoint(anchor, transformOrigin.z());
276
277
    if (m_contentsLayer) {
278
        m_contentsLayer->setPosition(IntPoint(0, 0));
279
        m_contentsLayer->setSize(newSize);
280
    }
281
282
    m_graphicsLayer->updateContentsRect();
283
}
284
285
void RenderLayerBacking::updateInternalHierarchy()
286
{
287
    // m_contentsLayer has to be inserted in the correct order with child layers,
288
    // so it's not inserted here.
289
    if (m_ancestorClippingLayer) {
290
        m_ancestorClippingLayer->removeAllChildren();
291
        m_graphicsLayer->removeFromParent();
292
        m_ancestorClippingLayer->addChild(m_graphicsLayer);
293
    }
294
295
    if (m_clippingLayer) {
296
        m_clippingLayer->removeFromParent();
297
        m_graphicsLayer->addChild(m_clippingLayer);
298
    }
299
}
300
301
// Return true if the layers changed.
302
bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip)
303
{
304
    bool layersChanged = false;
305
306
    if (needsAncestorClip) {
307
        if (!m_ancestorClippingLayer) {
308
            m_ancestorClippingLayer = GraphicsLayer::createGraphicsLayer(0);
309
#ifndef NDEBUG
310
            m_ancestorClippingLayer->setName("Ancestor clipping Layer");
311
#endif
312
            m_ancestorClippingLayer->setMasksToBounds(true);
313
            layersChanged = true;
314
        }
315
    } else if (m_ancestorClippingLayer) {
316
        m_ancestorClippingLayer->removeFromParent();
317
        delete m_ancestorClippingLayer;
318
        m_ancestorClippingLayer = 0;
319
        layersChanged = true;
320
    }
321
    
322
    if (needsDescendantClip) {
323
        if (!m_clippingLayer) {
324
            m_clippingLayer = GraphicsLayer::createGraphicsLayer(0);
325
#ifndef NDEBUG
326
            m_clippingLayer->setName("Child clipping Layer");
327
#endif
328
            m_clippingLayer->setMasksToBounds(true);
329
            layersChanged = true;
330
        }
331
    } else if (m_clippingLayer) {
332
        m_clippingLayer->removeFromParent();
333
        delete m_clippingLayer;
334
        m_clippingLayer = 0;
335
        layersChanged = true;
336
    }
337
    
338
    if (layersChanged)
339
        updateInternalHierarchy();
340
341
    return layersChanged;
342
}
343
344
bool RenderLayerBacking::updateContentsLayer(bool needsContentsLayer)
345
{
346
    bool layerChanged = false;
347
    if (needsContentsLayer) {
348
        if (!m_contentsLayer) {
349
            m_contentsLayer = GraphicsLayer::createGraphicsLayer(this);
350
#ifndef NDEBUG
351
            m_contentsLayer->setName("Contents");
352
#endif
353
            m_contentsLayer->setDrawsContent(true);
354
            m_contentsLayer->setDrawingPhase(GraphicsLayerPaintForegroundMask);
355
            m_graphicsLayer->setDrawingPhase(GraphicsLayerPaintBackgroundMask);
356
            layerChanged = true;
357
        }
358
    } else if (m_contentsLayer) {
359
        m_contentsLayer->removeFromParent();
360
        delete m_contentsLayer;
361
        m_contentsLayer = 0;
362
        m_graphicsLayer->setDrawingPhase(GraphicsLayerPaintAllMask);
363
        layerChanged = true;
364
    }
365
    return layerChanged;
366
}
367
368
float RenderLayerBacking::compositingOpacity(float rendererOpacity) const
369
{
370
    float finalOpacity = rendererOpacity;
371
    
372
    for (RenderLayer* curr = m_owningLayer->parent(); curr != 0; curr = curr->parent()) {
373
        // We only care about parents that are stacking contexts.
374
        // Recall that opacity creates stacking context.
375
        if (!curr->isStackingContext())
376
            continue;
377
        
378
        // If we found a compositing layer, we want to compute opacity
379
        // relative to it. So we can break here.
380
        if (curr->isComposited())
381
            break;
382
        
383
        finalOpacity *= curr->renderer()->opacity();
384
    }
385
386
    return finalOpacity;
387
}
388
389
// A simple background is either none or a solid color.
390
static bool hasSimpleBackground(RenderStyle* inStyle)
391
{
392
    return !inStyle->hasBackgroundImage();
393
}
394
395
static bool hasBorderOutlineOrShadow(RenderStyle* inStyle)
396
{
397
    return (inStyle->hasBorder() || inStyle->hasBorderRadius() || inStyle->hasOutline() || (inStyle->boxShadow() != 0));
398
}
399
400
bool RenderLayerBacking::rendererHasBackground() const
401
{
402
    // FIXME: share more code here
403
    if (renderer()->node()->isDocumentNode()) {
404
        RenderObject* htmlObject = renderer()->firstChild();
405
        if (!htmlObject)
406
            return false;
407
        
408
        RenderStyle* style = htmlObject->style();
409
        if (style->hasBackground())
410
            return true;
411
        
412
        RenderObject* bodyObject = htmlObject->firstChild();
413
        if (!bodyObject)
414
            return false;
415
        
416
        style = bodyObject->style();
417
        return style->hasBackground();
418
    }
419
    
420
    return renderer()->style()->hasBackground();
421
}
422
423
const Color& RenderLayerBacking::rendererBackgroundColor() const
424
{
425
    // FIXME: share more code here
426
    if (renderer()->node()->isDocumentNode()) {
427
        RenderObject* htmlObject = renderer()->firstChild();
428
        RenderStyle* style = htmlObject->style();
429
        if (style->hasBackground())
430
            return style->backgroundColor();
431
432
        RenderObject* bodyObject = htmlObject->firstChild();
433
        style = bodyObject->style();
434
        return style->backgroundColor();
435
    }
436
437
    return renderer()->style()->backgroundColor();
438
}
439
440
bool RenderLayerBacking::canBeSimpleContainerCompositingLayer() const
441
{
442
    RenderObject* renderObject = renderer();
443
    if (renderObject->isReplaced() ||       // replaced objects are not containers
444
        renderObject->hasMask())            // masks require special treatment
445
        return false;
446
447
    RenderStyle* style = renderObject->style();
448
449
    // Reject anything that has a border, a border-radius or outline,
450
    // or any background (color or image).
451
    // FIXME: we could optimize layers for simple backgrounds.
452
    if (hasBorderOutlineOrShadow(style) ||
453
        style->hasBackground())
454
        return false;
455
456
    // If we have got this far and the renderer has no children, then we're ok.
457
    if (!renderObject->firstChild())
458
        return true;
459
    
460
    if (renderObject->node()->isDocumentNode()) {
461
        // Look to see if the root object has a non-simple backgound
462
        RenderObject* rootObject = renderObject->document()->documentElement()->renderer();
463
        if (!rootObject)
464
            return false;
465
        
466
        style = rootObject->style();
467
        
468
        // Reject anything that has a border, a border-radius or outline,
469
        // or is not a simple background (no background, or solid color).
470
        if (hasBorderOutlineOrShadow(style) ||
471
            !hasSimpleBackground(style))
472
            return false;
473
        
474
        // Now look at the body's renderer.
475
        HTMLElement* body = renderObject->document()->body();
476
        RenderObject* bodyObject = (body && body->hasLocalName(HTMLNames::bodyTag)) ? body->renderer() : 0;
477
        if (!bodyObject)
478
            return false;
479
        
480
        style = bodyObject->style();
481
        
482
        if (hasBorderOutlineOrShadow(style) ||
483
            !hasSimpleBackground(style))
484
            return false;
485
486
        // Ceck to see if all the body's children are compositing layers.
487
        if (hasNonCompositingContent())
488
            return false;
489
        
490
        return true;
491
    }
492
493
    // Check to see if all the renderer's children are compositing layers.
494
    if (hasNonCompositingContent())
495
        return false;
496
    
497
    return true;
498
}
499
500
bool RenderLayerBacking::hasNonCompositingContent() const
501
{
502
    // Conservative test for having no rendered children.
503
    
504
    // Some HTML can cause whitespace text nodes to have renderers, like:
505
    // <div>
506
    // <img src=...>
507
    // </div>
508
    // so test for 0x0 RenderTexts here
509
    for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
510
        if (!child->hasLayer() && (child->width() > 0 || child->height() > 0))
511
            return true;
512
    }
513
514
    // FIXME: test for overflow controls.
515
    if (m_owningLayer->isStackingContext()) {
516
        // Use the m_hasCompositingDescendant bit to optimize?
517
        Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList();
518
        if (negZOrderList && negZOrderList->size() > 0) {
519
            for (Vector<RenderLayer*>::const_iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) {
520
                RenderLayer* curLayer = (*it);
521
                if (!curLayer->isComposited())
522
                    return true;
523
            }
524
        }
525
526
        Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList();
527
        if (posZOrderList && posZOrderList->size() > 0)
528
            for (Vector<RenderLayer*>::const_iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) {
529
                RenderLayer* curLayer = (*it);
530
                if (!curLayer->isComposited())
531
                    return true;
532
            }
533
    }
534
535
    Vector<RenderLayer*>* overflowList = m_owningLayer->overflowList();
536
    if (overflowList && overflowList->size() > 0)
537
        for (Vector<RenderLayer*>::const_iterator it = overflowList->begin(); it != overflowList->end(); ++it) {
538
            RenderLayer* curLayer = (*it);
539
            if (!curLayer->isComposited())
540
                return true;
541
        }
542
543
    return false;
544
}
545
546
// A "simple container layer" is a RenderLayer which has no visible content to render.
547
// It may have no children, or all its children may be themselves composited.
548
// This is a useful optimization, because it allows us to avoid allocating backing store.
549
bool RenderLayerBacking::isSimpleContainerCompositingLayer()
550
{
551
    if (m_simpleCompositingLayerStatusDirty) {
552
        m_isSimpleContainerCompositingLayer = canBeSimpleContainerCompositingLayer();
553
        m_simpleCompositingLayerStatusDirty = false;
554
    }
555
556
    return m_isSimpleContainerCompositingLayer;
557
}
558
559
void RenderLayerBacking::detectDrawingOptimizations()
560
{
561
    bool drawsContent = true;
562
563
    if (isSimpleContainerCompositingLayer() || paintingGoesToWindow())
564
        drawsContent = false;
565
566
    m_graphicsLayer->setDrawsContent(drawsContent);
567
}
568
569
void RenderLayerBacking::invalidateDrawingOptimizations()
570
{
571
    m_simpleCompositingLayerStatusDirty = true;
572
}
573
574
void RenderLayerBacking::forceCompositingLayer(bool force)
575
{
576
    m_forceCompositingLayer = force;
577
}
578
579
FloatPoint RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox) const
580
{
581
    RenderStyle* style = renderer()->style();
582
583
    FloatPoint origin;
584
    origin.setX(style->transformOriginX().calcFloatValue(borderBox.width()));
585
    origin.setY(style->transformOriginY().calcFloatValue(borderBox.height()));
586
587
    return origin;
588
}
589
590
// Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
591
IntSize RenderLayerBacking::contentOffsetInCompostingLayer()
592
{
593
    if (!m_compositingContentOffsetDirty)
594
        return m_compositingContentOffset;
595
596
    IntRect relativeCompositingBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer);
597
    m_compositingContentOffset = IntSize(-relativeCompositingBounds.x(), -relativeCompositingBounds.y());
598
    m_compositingContentOffsetDirty = false;
599
600
    return m_compositingContentOffset;
601
}
602
603
IntRect RenderLayerBacking::contentsBox(const GraphicsLayer*)
604
{
605
    IntRect contentsRect;
606
    contentsRect = renderer()->contentBox();
607
608
    IntSize  contentOffset = contentOffsetInCompostingLayer();
609
    contentsRect.move(contentOffset);
610
    return contentsRect;
611
}
612
613
// Map the given point from coordinates in the GraphicsLayer to RenderLayer coordinates.
614
FloatPoint RenderLayerBacking::graphicsLayerToContentsCoordinates(const FloatPoint& point)
615
{
616
    IntSize contentOffset = contentOffsetInCompostingLayer();
617
    return FloatPoint(point.x() - contentOffset.width(), point.y() - contentOffset.height());
618
}
619
620
// Map the given point from coordinates in the RenderLayer to GraphicsLayer coordinates.
621
FloatPoint RenderLayerBacking::contentsToGraphicsLayerCoordinates(const FloatPoint& point)
622
{
623
    IntSize contentOffset = contentOffsetInCompostingLayer();
624
    return FloatPoint(point.x() + contentOffset.width(), point.y() + contentOffset.height());
625
}
626
627
bool RenderLayerBacking::paintingGoesToWindow() const
628
{
629
    return m_owningLayer->isDocumentLayer()
630
#ifndef NDEBUG
631
        && !GraphicsLayer::showLayerHierarchy()
632
#endif
633
        ;
634
}
635
636
void RenderLayerBacking::setContentsNeedDisplay()
637
{
638
    if (m_graphicsLayer)
639
        m_graphicsLayer->setNeedsDisplay();
640
    if (m_contentsLayer)
641
        m_contentsLayer->setNeedsDisplay();
642
}
643
644
// r is in the coordinate space of the layer's render object
645
void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
646
{
647
    if (m_graphicsLayer) {
648
        FloatPoint dirtyOrigin = contentsToGraphicsLayerCoordinates(FloatPoint(r.x(), r.y()));
649
        FloatRect dirtyRect(dirtyOrigin, r.size());
650
        FloatRect bounds(FloatPoint(), m_graphicsLayer->size());
651
        if (bounds.intersects(dirtyRect))
652
            m_graphicsLayer->setNeedsDisplayInRect(dirtyRect);
653
    }
654
655
    if (m_contentsLayer) {
656
        // FIXME: do incremental repaint
657
        m_contentsLayer->setNeedsDisplay();
658
    }
659
}
660
661
static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
662
{
663
    if (paintDirtyRect == clipRect)
664
        return;
665
    p->save();
666
    p->clip(clipRect);
667
}
668
669
static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
670
{
671
    if (paintDirtyRect == clipRect)
672
        return;
673
    p->restore();
674
}
675
676
// Share this with RenderLayer::paintLayer, which would have to be educated about GraphicsLayerPaintingPhase?
677
void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context,
678
                    const IntRect& paintDirtyRect,      // in the coords of rootLayer
679
                    bool haveTransparency, PaintRestriction paintRestriction, GraphicsLayerPaintingPhase paintingPhase,
680
                    RenderObject* paintingRoot)
681
{
682
    if (paintingGoesToWindow()) {
683
        ASSERT_NOT_REACHED();
684
        return;
685
    }
686
    
687
    if (m_owningLayer->isStackingContext() && (m_owningLayer->m_zOrderListsDirty || m_owningLayer->m_overflowListDirty))
688
        compositor()->updateCompositingLayers(m_owningLayer);
689
    
690
    // Calculate the clip rects we should use.
691
    IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
692
    m_owningLayer->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
693
    
694
    int x = layerBounds.x();        // layerBounds is computed relative to rootLayer
695
    int y = layerBounds.y();
696
    int tx = x - renderer()->xPos();
697
    int ty = y - renderer()->yPos() + renderer()->borderTopExtra();
698
699
    // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
700
    // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
701
    // Else, our renderer tree may or may not contain the painting root, so we pass that root along
702
    // so it will be tested against as we decend through the renderers.
703
    RenderObject *paintingRootForRenderer = 0;
704
    if (paintingRoot && !renderer()->isDescendantOf(paintingRoot))
705
        paintingRootForRenderer = paintingRoot;
706
707
    if (paintingPhase & GraphicsLayerPaintBackgroundMask) {
708
        // If this is the root then we need to send in a bigger bounding box
709
        // because we'll be painting the background as well (see RenderBox::paintRootBoxDecorations()).
710
        IntRect paintBox = clipRectToApply;
711
        
712
        if (renderer()->node()->isDocumentNode() && renderer()->document()->isHTMLDocument()) {
713
            int w = renderer()->width();
714
            int h = renderer()->height();
715
            
716
            int rw;
717
            int rh;
718
            if (renderer()->view()->frameView()) {
719
                rw = renderer()->view()->frameView()->contentsWidth();
720
                rh = renderer()->view()->frameView()->contentsHeight();
721
            } else {
722
                rw = renderer()->view()->width();
723
                rh = renderer()->view()->height();
724
            }
725
            
726
            int bx = tx - renderer()->marginLeft();
727
            int by = ty - renderer()->marginTop();
728
            int bw = max(w + renderer()->marginLeft() + renderer()->marginRight() + renderer()->borderLeft() + renderer()->borderRight(), rw);
729
            int bh = max(h + renderer()->marginTop() + renderer()->marginBottom() + renderer()->borderTop() + renderer()->borderBottom(), rh);
730
            paintBox = IntRect(bx, by, bw, bh);
731
        }
732
733
        // Paint our background first, before painting any child layers.
734
        // Establish the clip used to paint our background.
735
        setClip(context, paintDirtyRect, damageRect);
736
        
737
        RenderObject::PaintInfo info(context, paintBox, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
738
        renderer()->paint(info, tx, ty);
739
740
        // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
741
        // z-index.  We paint after we painted the background/border, so that the scrollbars will
742
        // sit above the background/border.
743
        m_owningLayer->paintOverflowControls(context, x, y, damageRect);
744
        
745
        // Restore the clip.
746
        restoreClip(context, paintDirtyRect, damageRect);
747
    }
748
                
749
    if (paintingPhase & GraphicsLayerPaintForegroundMask) {
750
        // Now walk the sorted list of children with negative z-indices. Only RenderLayers without compositing layers will paint.
751
        // FIXME: should these be painted as background?
752
        Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList();
753
        if (negZOrderList)
754
            for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it)
755
                it[0]->paintLayer(rootLayer, context, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot);
756
757
        bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText;
758
        bool selectionOnly  = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText;
759
760
        // Set up the clip used when painting our children.
761
        setClip(context, paintDirtyRect, clipRectToApply);
762
        RenderObject::PaintInfo paintInfo(context, clipRectToApply, 
763
                                          selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds,
764
                                          forceBlackText, paintingRootForRenderer, 0);
765
        renderer()->paint(paintInfo, tx, ty);
766
767
        if (!selectionOnly) {
768
            paintInfo.phase = PaintPhaseFloat;
769
            renderer()->paint(paintInfo, tx, ty);
770
771
            paintInfo.phase = PaintPhaseForeground;
772
            renderer()->paint(paintInfo, tx, ty);
773
774
            paintInfo.phase = PaintPhaseChildOutlines;
775
            renderer()->paint(paintInfo, tx, ty);
776
        }
777
778
        // Now restore our clip.
779
        restoreClip(context, paintDirtyRect, clipRectToApply);
780
781
        if (!outlineRect.isEmpty()) {
782
            // Paint our own outline
783
            RenderObject::PaintInfo paintInfo(context, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0);
784
            setClip(context, paintDirtyRect, outlineRect);
785
            renderer()->paint(paintInfo, tx, ty);
786
            restoreClip(context, paintDirtyRect, outlineRect);
787
        }
788
789
        // Paint any child layers that have overflow.
790
        Vector<RenderLayer*>* overflowList = m_owningLayer->overflowList();
791
        if (overflowList)
792
            for (Vector<RenderLayer*>::iterator it = overflowList->begin(); it != overflowList->end(); ++it)
793
                it[0]->paintLayer(rootLayer, context, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot);
794
        
795
        // Now walk the sorted list of children with positive z-indices.
796
        Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList();
797
        if (posZOrderList)
798
            for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it)
799
                it[0]->paintLayer(rootLayer, context, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot);
800
801
        if (renderer()->hasMask() && !selectionOnly && !damageRect.isEmpty()) {
802
            setClip(context, paintDirtyRect, damageRect);
803
804
            // Paint the mask.
805
            RenderObject::PaintInfo paintInfo(context, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0);
806
            renderer()->paint(paintInfo, tx, ty);
807
            
808
            // Restore the clip.
809
            restoreClip(context, paintDirtyRect, damageRect);
810
        }
811
    }
812
813
    ASSERT(!m_owningLayer->m_usedTransparency);
814
}
815
816
// Up-call from compositing layer drawing callback.
817
void RenderLayerBacking::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase drawingPhase, const IntRect& clip)
818
{
819
    // We have to use the same root as for hit testing, because both methods
820
    // can compute and cache clipRects.
821
    IntRect enclosingBBox = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer);
822
823
    IntRect clipRect(clip);
824
    
825
    // Set up the coordinate space to be in the layer's rendering coordinates.
826
    context.translate(-enclosingBBox.x(), -enclosingBBox.y());
827
828
    // Offset the clip.
829
    clipRect.move(enclosingBBox.x(), enclosingBBox.y());
830
    
831
    // The dirtyRect is in the coords of the painting root.
832
    IntRect dirtyRect = enclosingBBox;
833
    dirtyRect.intersect(clipRect);
834
835
    paintIntoLayer(m_owningLayer, &context, dirtyRect, false, PaintRestrictionNone, drawingPhase, renderer());
836
}
837
838
FloatPoint RenderLayerBacking::convertToContentsCoordinates(const GraphicsLayer*, const FloatPoint& point)
839
{
840
    return graphicsLayerToContentsCoordinates(point);
841
}
842
843
// Compositing layer hit testing works like this:
844
//  * hitTestLayer() is called on the root.
845
//  * in compositing mode, that calls hitTestRootLayer()
846
//  * it calls findHitCompositingLayer().
847
//  * findHitCompositingLayer does hitTesting via GraphicsLayers, which involves
848
//      calling back via contentsContainPoint() to find out
849
//      if the given point should be considered to be "inside" the layer based on
850
//      HTML hit testing rules.
851
//  * Once we've found a hit compositing layer, hitTestRootLayer() then goes on to
852
//      do a final hitTestLayer() in order to fill in result.
853
//
854
// FIXME: move to RenderLayerCompositor?
855
RenderLayer* RenderLayerBacking::hitTestRootLayer(RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
856
                                           const IntRect& hitTestRect, const IntPoint& hitTestPoint)
857
{
858
    RenderLayer* hitCompositingLayer = findHitCompositingLayer(rootLayer, request, result, hitTestRect, hitTestPoint);
859
    if (!hitCompositingLayer) {
860
        // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down, 
861
        // return ourselves. We do this so mouse events continue getting delivered after a drag has 
862
        // exited the WebView, and so hit testing over a scrollbar hits the content document.
863
        if ((request.active || request.mouseUp) && renderer()->isRenderView()) {
864
            m_owningLayer->renderer()->updateHitTestResult(result, hitTestPoint);
865
            return m_owningLayer;
866
        }
867
        return 0;
868
    }
869
870
    // if we hit the root layer, we're done
871
    if (hitCompositingLayer == m_owningLayer) {
872
        m_owningLayer->renderer()->updateHitTestResult(result, hitTestPoint);
873
        return m_owningLayer;
874
    }
875
876
    // convert hitTestPoint to coords of the hit layer
877
    FloatPoint hitPoint = convertPointToLayer(hitTestPoint, hitCompositingLayer);
878
    IntPoint destHitTestPoint(roundf(hitPoint.x()), roundf(hitPoint.y()));
879
    
880
    // convert hitTestRect to the hit layer by mapping a quad, then getting its
881
    // bounding box
882
    IntRect destHitTestRect;
883
    {
884
        // FIXME: move into a helper function
885
        FloatQuad   hitTestQuad(hitTestRect);
886
        GraphicsLayer* destCompositingLayer = hitCompositingLayer->backing()->graphicsLayer();
887
        IntSize contentOffset = contentOffsetInCompostingLayer();
888
        hitTestQuad.move(contentOffset.width(), contentOffset.height());
889
890
        graphicsLayer()->convertQuadToLayer(hitTestQuad, destCompositingLayer);
891
892
        IntSize destContentOffset = hitCompositingLayer->backing()->contentOffsetInCompostingLayer();
893
        hitTestQuad.move(-destContentOffset.width(), -destContentOffset.height());
894
        destHitTestRect = enclosingIntRect(hitTestQuad.boundingBox());
895
    }
896
897
    // clear out the state in result that we may have set in contentsContainPoint(),
898
    // and run hit testing on the hit compositing layer
899
    result.setInnerNode(0);
900
    result.setInnerNonSharedNode(0);
901
    return hitCompositingLayer->hitTestLayer(hitCompositingLayer, request, result, destHitTestRect, destHitTestPoint);
902
}
903
904
// hitTestPoint and hitTestRect are in the coordinate system of rootLayer
905
RenderLayer* RenderLayerBacking::findHitCompositingLayer(RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result, const IntRect& hitTestRect, const IntPoint& hitTestPoint)
906
{
907
    LayerHitTestData hitTestData(rootLayer, request, result, hitTestRect);
908
909
    // Calculate the clip rects we should use.
910
    IntRect layerBounds;
911
    IntRect bgRect;
912
    IntRect fgRect;
913
    IntRect outlineRect;
914
    m_owningLayer->calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect);
915
916
    // Check our lists are up-to-date.
917
    ASSERT(!m_owningLayer->isStackingContext() || !m_owningLayer->m_zOrderListsDirty);
918
    ASSERT(!m_owningLayer->isStackingContext() || !m_owningLayer->m_overflowListDirty);
919
920
    GraphicsLayer* rootGraphicsLayer = compositor()->rootPlatformLayer();
921
922
    // convert hitTestPoint to the coordinate system of the compositing layer
923
    FloatPoint hitPoint = contentsToGraphicsLayerCoordinates(hitTestPoint);
924
925
    // We assume here that the result.point() is in the coordinate system of m_graphicsLayer, so we
926
    // convert to the root layer, since we need to pass superlayer-relative coordinates into
927
    // the hitTest.
928
    hitPoint = m_graphicsLayer->convertPointToLayer(hitPoint, rootGraphicsLayer);
929
930
    // as hitTest is called on LCLayers, contentsContainPoint() is called for each compositing layer
931
    GraphicsLayer* hitLayer = m_graphicsLayer->hitTest(hitPoint, &hitTestData);
932
    if (!hitLayer)
933
        return 0;
934
935
    // note that hitLayer may be a m_contentsLayer, but we should not need to do anything special
936
937
    // Convert the point to the coords of the hit GraphicsLayer, which takes
938
    // layer transforms into account
939
    hitPoint = rootGraphicsLayer->convertPointToLayer(hitPoint, hitLayer);
940
941
    // Then convert it back to the coords of the root layer. We do all
942
    // the hit testing in root-relative coords, because all the clip rects
943
    // are root-relative (just like painting).
944
    RenderLayerBacking* hitLayerBacking = static_cast<RenderLayerBacking*>(hitLayer->client());
945
    RenderLayer* hitRenderLayer = hitLayerBacking ? hitLayerBacking->owningLayer() : 0;
946
    ASSERT(hitRenderLayer);
947
    return hitRenderLayer;
948
}
949
950
// up-call from compositing layer hit testing machinery. inPoint is in this layer coordinates.
951
bool RenderLayerBacking::contentsContainPoint(const GraphicsLayer*, const IntPoint& point, GraphicsLayerPaintingPhase compositePhase, struct LayerHitTestData* hitTestData)
952
{
953
    RenderLayer* rootLayer = hitTestData->m_rootLayer;
954
    const HitTestRequest& request = hitTestData->m_request;
955
    HitTestResult& result = hitTestData->m_result;
956
    IntRect hitTestRect = hitTestData->m_hitTestRect;
957
958
    // map hitTestRect to this layer
959
    FloatQuad hitTestQuad(hitTestRect);
960
961
    GraphicsLayer* rootCompositingLayer = rootLayer->backing()->graphicsLayer();
962
    IntSize rootContentOffset = rootLayer->backing()->contentOffsetInCompostingLayer();
963
    hitTestQuad.move(rootContentOffset.width(), rootContentOffset.height());
964
965
    rootCompositingLayer->convertQuadToLayer(hitTestQuad, graphicsLayer());
966
967
    IntSize contentOffset = contentOffsetInCompostingLayer();
968
    hitTestQuad.move(-contentOffset.width(), -contentOffset.height());
969
970
    IntRect destHitTestRect = enclosingIntRect(hitTestQuad.boundingBox());
971
    hitTestRect = destHitTestRect;
972
973
    // use this layer as the hit testing root
974
    rootLayer = m_owningLayer;
975
976
    // inPoint is already in the coords of this layer
977
    IntPoint hitTestPoint = point;
978
979
    // Calculate the clip rects we should use.
980
    IntRect layerBounds;
981
    IntRect bgRect;
982
    IntRect fgRect;
983
    IntRect outlineRect;
984
    m_owningLayer->calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect);
985
986
    RenderLayer* insideLayer = 0;
987
988
    ASSERT(m_owningLayer->isStackingContext() || (!m_owningLayer->m_posZOrderList || m_owningLayer->m_posZOrderList->size() == 0));
989
    
990
    // FIXME: share this code with hitTestLayer above
991
    if (compositePhase & GraphicsLayerPaintForegroundMask) {
992
        // Begin by walking our list of positive layers from highest z-index down to the lowest
993
        // z-index. Only test non-compositing layers, since the first hitTestLayer will have found
994
        // any hit compositing layers.
995
        Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList();
996
        if (posZOrderList) {
997
            for (int i = posZOrderList->size() - 1; i >= 0; --i) {
998
                RenderLayer* curLayer = posZOrderList->at(i);
999
                if (!curLayer->isComposited()) {
1000
                    insideLayer = curLayer->hitTestLayer(rootLayer, request, result, hitTestRect, hitTestPoint);
1001
                    if (insideLayer)
1002
                        return true;
1003
                }
1004
            }
1005
        }
1006
1007
        // Now check our overflow objects.
1008
        Vector<RenderLayer*>* overflowList = m_owningLayer->overflowList();
1009
        if (overflowList) {
1010
            for (int i = overflowList->size() - 1; i >= 0; --i) {
1011
                RenderLayer* curLayer = overflowList->at(i);
1012
                if (!curLayer->isComposited()) {
1013
                    insideLayer = curLayer->hitTestLayer(rootLayer, request, result, hitTestRect, hitTestPoint);
1014
                    if (insideLayer)
1015
                        return true;
1016
                }
1017
            }
1018
        }
1019
1020
        // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
1021
        if (fgRect.contains(hitTestPoint) && 
1022
            renderer()->hitTest(request, result, hitTestPoint,
1023
                                layerBounds.x() - renderer()->xPos(),
1024
                                layerBounds.y() - renderer()->yPos() + renderer()->borderTopExtra(), 
1025
                                HitTestDescendants)) {
1026
            // For positioned generated content, we might still not have a
1027
            // node by the time we get to the layer level, since none of
1028
            // the content in the layer has an element. So just walk up
1029
            // the tree.
1030
            if (!result.innerNode() || !result.innerNonSharedNode()) {
1031
                Node* e = m_owningLayer->enclosingElement();
1032
                if (!result.innerNode())
1033
                    result.setInnerNode(e);
1034
                if (!result.innerNonSharedNode())
1035
                    result.setInnerNonSharedNode(e);
1036
            }
1037
            return true;
1038
        }
1039
1040
        // Now check our negative z-index children.
1041
        Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList();
1042
        if (negZOrderList) {
1043
            for (int i = negZOrderList->size() - 1; i >= 0; --i) {
1044
                RenderLayer* curLayer = negZOrderList->at(i);
1045
                if (!curLayer->isComposited()) {
1046
                    insideLayer = negZOrderList->at(i)->hitTestLayer(rootLayer, request, result, hitTestRect, hitTestPoint);
1047
                    if (insideLayer)
1048
                        return true;
1049
                }
1050
            }
1051
        }
1052
    }
1053
1054
    if (compositePhase & GraphicsLayerPaintBackgroundMask) {
1055
        if (bgRect.contains(hitTestPoint) &&
1056
            renderer()->hitTest(request, result, hitTestPoint,
1057
                                layerBounds.x() - renderer()->xPos(),
1058
                                layerBounds.y() - renderer()->yPos() + renderer()->borderTopExtra(),
1059
                                HitTestSelf)) {
1060
            if (!result.innerNode() || !result.innerNonSharedNode()) {
1061
                Node* e = m_owningLayer->enclosingElement();
1062
                if (!result.innerNode())
1063
                    result.setInnerNode(e);
1064
                if (!result.innerNonSharedNode())
1065
                    result.setInnerNonSharedNode(e);
1066
            }
1067
            return true;
1068
        }
1069
    }
1070
1071
    return false;
1072
}
1073
1074
bool RenderLayerBacking::startAnimation(double beginTime, const Animation* anim, const KeyframeList& keyframes)
1075
{
1076
    bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
1077
    bool hasTransform = keyframes.containsProperty(CSSPropertyWebkitTransform);
1078
    
1079
    if (!hasOpacity && !hasTransform)
1080
        return false;
1081
    
1082
    GraphicsLayer::TransformValueList transformVector;
1083
    GraphicsLayer::FloatValueList opacityVector;
1084
1085
    for (Vector<KeyframeValue>::const_iterator it = keyframes.beginKeyframes(); it != keyframes.endKeyframes(); ++it) {
1086
        const RenderStyle* keyframeStyle = it->style();
1087
        float key = it->key();
1088
1089
        if (!keyframeStyle)
1090
            continue;
1091
            
1092
        // get timing function
1093
        const TimingFunction* tf = keyframeStyle->hasAnimations() ? &((*keyframeStyle->animations()).animation(0)->timingFunction()) : 0;
1094
        
1095
        if (hasTransform)
1096
            transformVector.insert(key, &(keyframeStyle->transform()), tf);
1097
1098
        if (hasOpacity)
1099
            opacityVector.insert(key, keyframeStyle->opacity(), tf);
1100
    }
1101
1102
    bool didAnimateTransform = !hasTransform;
1103
    bool didAnimateOpacity = !hasOpacity;
1104
    
1105
    if (hasTransform && m_graphicsLayer->animateTransform(transformVector, renderer()->borderBox().size(), anim, beginTime, false))
1106
        didAnimateTransform = true;
1107
1108
    if (hasOpacity && m_graphicsLayer->animateFloat(AnimatedPropertyOpacity, opacityVector, anim, beginTime))
1109
        didAnimateOpacity = true;
1110
    
1111
    return didAnimateTransform && didAnimateOpacity;
1112
}
1113
1114
bool RenderLayerBacking::startTransition(double beginTime, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
1115
{
1116
    bool didAnimate = false;
1117
    
1118
    if (property == cAnimateAll || property == (int)CSSPropertyOpacity) {
1119
        const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
1120
        if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
1121
            // If beginTime is not 0, we are restarting this transition, so first set the from value
1122
            // in case it was smashed by a previous animation.
1123
            if (beginTime > 0)
1124
                m_graphicsLayer->setOpacity(compositingOpacity(fromStyle->opacity()), 0, 0);
1125
1126
            if (m_graphicsLayer->setOpacity(compositingOpacity(toStyle->opacity()), opacityAnim, beginTime))
1127
                didAnimate = true;
1128
        }
1129
    }
1130
    if (property == cAnimateAll || property == (int)CSSPropertyWebkitTransform) {
1131
        // We get a TransformOperation, which is a linked list of primitive operations and their arguments.
1132
        // Arguments can be floats or Length values, which need to be converted to numbers using
1133
        // val.calcFloatValue(renderer()->width()) (or height()).
1134
        const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform);
1135
        if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
1136
            GraphicsLayer::TransformValueList transformVector;
1137
            transformVector.insert(0, &fromStyle->transform(), 0);        
1138
            transformVector.insert(1, &toStyle->transform(), 0);        
1139
            if (m_graphicsLayer->animateTransform(transformVector, renderer()->borderBox().size(), transformAnim, beginTime, true))
1140
                didAnimate = true;
1141
        }
1142
    }
1143
    
1144
    return didAnimate;
1145
}
1146
1147
void RenderLayerBacking::notifyTransitionStarted(const GraphicsLayer*, AnimatedPropertyID property, double time)
1148
{
1149
    int cssProperty = CSSPropertyInvalid;
1150
    switch (property) {
1151
        case AnimatedPropertyInvalid:
1152
            break;
1153
        case AnimatedPropertyWebkitTransform:
1154
            cssProperty = CSSPropertyWebkitTransform;
1155
            break;
1156
        case AnimatedPropertyOpacity:
1157
            cssProperty = CSSPropertyOpacity;
1158
            break;
1159
        case AnimatedPropertyBackgroundColor:
1160
            cssProperty = CSSPropertyBackgroundColor;
1161
            break;
1162
    }
1163
    
1164
    renderer()->notifyTransitionStarted(cssProperty, time);
1165
}
1166
1167
void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time)
1168
{
1169
    renderer()->notifyAnimationStarted(time);
1170
}
1171
1172
void RenderLayerBacking::animationFinished(const String& name, int index, bool reset)
1173
{
1174
    m_graphicsLayer->removeFinishedAnimations(name, index, reset);
1175
}
1176
1177
void RenderLayerBacking::transitionFinished(int property)
1178
{
1179
    m_graphicsLayer->removeFinishedTransitions(property);
1180
}
1181
1182
void RenderLayerBacking::suspendAnimations()
1183
{
1184
    m_graphicsLayer->suspendAnimations();
1185
}
1186
1187
void RenderLayerBacking::resumeAnimations()
1188
{
1189
    m_graphicsLayer->resumeAnimations();
1190
}
1191
1192
FloatPoint RenderLayerBacking::convertPointToLayer(const FloatPoint& point, RenderLayer* targetLayer)
1193
{
1194
    RenderLayer* srcCompLayer = compositor()->enclosingCompositingLayer(m_owningLayer);
1195
    RenderLayer* destCompLayer = compositor()->enclosingCompositingLayer(targetLayer);
1196
1197
    FloatPoint srcPoint(point);
1198
1199
    // EnclosingCompositingLayer doesn't guarantee that a compositing layer has been created yet
1200
    // FIXME: this should never happen
1201
    if (!srcCompLayer->isComposited() || !destCompLayer->isComposited()) {
1202
#ifndef NDEBUG
1203
        fprintf(stderr, "convertPointToLayer bailing because source or target doesn't have compositing layer");
1204
#endif
1205
        // FIXME: sucky absolute logic
1206
        FloatPoint srcPos = renderer()->localToAbsolute();
1207
        FloatPoint dstPos = targetLayer->renderer()->localToAbsolute();
1208
1209
        srcPoint += (dstPos - srcPos);
1210
        return srcPoint;
1211
    }
1212
1213
    if (srcCompLayer != m_owningLayer) {
1214
        int x = 0, y = 0;
1215
        m_owningLayer->convertToLayerCoords(srcCompLayer, x, y);
1216
        srcPoint.move(x, y);
1217
    }
1218
    
1219
    // convert from RenderLayer to GraphicsLayer coords
1220
    srcPoint = contentsToGraphicsLayerCoordinates(srcPoint);
1221
    // map to the dest layer
1222
    GraphicsLayer* srcPlatformLayer = srcCompLayer->backing()->graphicsLayer();
1223
    GraphicsLayer* dstPlatformLayer = destCompLayer->backing()->graphicsLayer();
1224
    FloatPoint destPoint = srcPlatformLayer->convertPointToLayer(srcPoint, dstPlatformLayer);
1225
    // convert back from GraphicsLayer to RenderLayer coords
1226
    destPoint = destCompLayer->backing()->graphicsLayerToContentsCoordinates(destPoint);
1227
1228
    if (destCompLayer != targetLayer) {
1229
        int x = 0, y = 0;
1230
        targetLayer->convertToLayerCoords(destCompLayer, x, y);
1231
        destPoint.move(-x, -y);
1232
    }
1233
1234
    return destPoint;
1235
}
1236
1237
// inPoint is relative to our renderer()
1238
FloatPoint RenderLayerBacking::convertToPageUsingCompositingLayer(const FloatPoint& inPoint)
1239
{
1240
    RenderLayer* docLayer = m_owningLayer->enclosingDocumentLayer();
1241
    return convertPointToLayer(inPoint, docLayer);
1242
}
1243
1244
// inPoint is relative to the document
1245
FloatPoint RenderLayerBacking::convertFromPageUsingCompositingLayer(const FloatPoint& inPoint)
1246
{
1247
    RenderLayer* docLayer = m_owningLayer->enclosingDocumentLayer();
1248
    return docLayer->backing()->convertPointToLayer(inPoint, m_owningLayer);
1249
}
1250
1251
void RenderLayerBacking::convertQuadToPageUsingCompositingLayer(FloatQuad& quad)
1252
{
1253
    RenderLayer* docLayer = m_owningLayer->enclosingDocumentLayer();
1254
    GraphicsLayer* docCompLayer = docLayer ? docLayer->backing()->graphicsLayer() : 0;
1255
    ASSERT(docCompLayer);
1256
    if (!docCompLayer)
1257
        return;
1258
1259
    // do the math that contentsToGraphicsLayerCoordinates does
1260
    IntSize contentOffset = contentOffsetInCompostingLayer();
1261
    quad.move(contentOffset.width(), contentOffset.height());
1262
1263
    m_graphicsLayer->convertQuadToLayer(quad, docCompLayer);
1264
1265
    IntSize docContentOffset = docLayer->backing()->contentOffsetInCompostingLayer();
1266
    quad.move(-docContentOffset.width(), -docContentOffset.height());
1267
}
1268
1269
} // namespace WebCore
1270
1271
#endif // USE(ACCELERATED_COMPOSITING)
- a/WebCore/rendering/RenderLayerBacking.h +188 lines
Line 0 a/WebCore/rendering/RenderLayerBacking.h_sec1
1
/*
2
 * Copyright (C) 2009 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 *
8
 * 1.  Redistributions of source code must retain the above copyright
9
 *     notice, this list of conditions and the following disclaimer. 
10
 * 2.  Redistributions in binary form must reproduce the above copyright
11
 *     notice, this list of conditions and the following disclaimer in the
12
 *     documentation and/or other materials provided with the distribution. 
13
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14
 *     its contributors may be used to endorse or promote products derived
15
 *     from this software without specific prior written permission. 
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
28
29
#ifndef RenderLayerBacking_h
30
#define RenderLayerBacking_h
31
32
#if USE(ACCELERATED_COMPOSITING)
33
34
#include "FloatPoint.h"
35
#include "FloatPoint3D.h"
36
#include "GraphicsLayer.h";
37
#include "GraphicsLayerClient.h";
38
#include "RenderLayer.h"
39
#include "TransformationMatrix.h"
40
41
namespace WebCore {
42
43
class RenderLayerCompositor;
44
45
// RenderLayerBacking controls the compositing behavior for a single RenderLayer.
46
// It holds the various GraphicsLayers, and makes decisions about intra-layer rendering
47
// optimizations.
48
// 
49
// There is one RenderLayerBacking for each RenderLayer that is composited.
50
51
class RenderLayerBacking : public GraphicsLayerClient {
52
public:
53
    RenderLayerBacking(RenderLayer*);
54
    ~RenderLayerBacking();
55
56
    RenderLayer* owningLayer() const { return m_owningLayer; }
57
58
    void updateAfterLayout();
59
    
60
    // Returns true if layer configuration changed.
61
    bool updateGraphicsLayers(bool needsContentsLayer, bool needsUpperClippingLayer, bool needsLowerClippingLayer, bool needsRepaint);
62
    void updateGraphicsLayerGeometry();
63
    void updateInternalHierarchy();
64
    
65
    GraphicsLayer* graphicsLayer() const { return m_graphicsLayer; }
66
67
    // Layer to clip children
68
    bool hasClippingLayer() const   { return m_clippingLayer != 0; }
69
    GraphicsLayer* clippingLayer() const  { return m_clippingLayer; }
70
71
    // Layer to get clipped by ancestor
72
    bool hasAncestorClippingLayer() const   { return m_ancestorClippingLayer != 0; }
73
    GraphicsLayer* ancestorClippingLayer() const  { return m_ancestorClippingLayer; }
74
75
    bool hasContentsLayer() const   { return m_contentsLayer != 0; }
76
    GraphicsLayer* contentsLayer() const   { return m_contentsLayer; }
77
    
78
    GraphicsLayer* parentForSublayers() const { return m_clippingLayer ? m_clippingLayer : m_graphicsLayer; }
79
    GraphicsLayer* childForSuperlayers() const { return m_ancestorClippingLayer ? m_ancestorClippingLayer : m_graphicsLayer; }
80
81
    // RenderLayers with backing normally short-circuit paintLayer() because
82
    // their content is rendered via callbacks from GraphicsLayer. However, the document
83
    // layer is special, because it has a GraphicsLayer to act as a container for the GraphicsLayers
84
    // for descendants, but its contents usually render into the window (in which case this returns true).
85
    // This returns false for other layers, and when the document layer actually needs to paint into its backing store
86
    // for some reason.
87
    bool paintingGoesToWindow() const;
88
89
    void setContentsNeedDisplay();
90
    // r is in the coordinate space of the layer's render object
91
    void setContentsNeedDisplayInRect(const IntRect& r);
92
93
    // Interface to start, finish, suspend and resume animations and transitions
94
    bool startAnimation(double beginTime, const Animation* anim, const KeyframeList& keyframes);
95
    bool startTransition(double beginTime, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle);
96
    void animationFinished(const String& name, int index, bool reset);
97
    void transitionFinished(int property);
98
99
    void suspendAnimations();
100
    void resumeAnimations();
101
102
    FloatPoint graphicsLayerToContentsCoordinates(const FloatPoint&);
103
    FloatPoint contentsToGraphicsLayerCoordinates(const FloatPoint&);
104
105
    // convert points, taking transforms into account
106
    FloatPoint convertPointToLayer(const FloatPoint&, RenderLayer* targetLayer);
107
108
    FloatPoint convertToPageUsingCompositingLayer(const FloatPoint&);
109
    FloatPoint convertFromPageUsingCompositingLayer(const FloatPoint&);
110
111
    void convertQuadToPageUsingCompositingLayer(FloatQuad&);
112
113
    void forceCompositingLayer(bool force = true);
114
    bool forcedCompositingLayer() const { return m_forceCompositingLayer; }
115
116
    void detectDrawingOptimizations();
117
    void invalidateDrawingOptimizations();
118
119
    // Up-calls from GraphicsLayer
120
    RenderLayer* hitTestRootLayer(RenderLayer* rootLayer, const HitTestRequest&, HitTestResult&, const IntRect& hitTestRect, const IntPoint& hitTestPoint);
121
122
    // GraphicsLayerClient interface
123
    virtual void notifyTransitionStarted(const GraphicsLayer*, AnimatedPropertyID, double startTime);
124
    virtual void notifyAnimationStarted(const GraphicsLayer*, double startTime);
125
126
    virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& clip);
127
    virtual bool contentsContainPoint(const GraphicsLayer*, const IntPoint& point, GraphicsLayerPaintingPhase , struct LayerHitTestData*);
128
129
    virtual FloatPoint convertToContentsCoordinates(const GraphicsLayer*, const FloatPoint&);
130
    virtual IntRect contentsBox(const GraphicsLayer*);
131
    
132
private:
133
    void createGraphicsLayer();
134
    void destroyGraphicsLayer();
135
136
    RenderObject* renderer() const { return m_owningLayer->renderer(); }
137
    RenderLayerCompositor* compositor() const { return m_owningLayer->compositor(); }
138
139
    bool updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip);
140
    bool updateContentsLayer(bool needsContentsLayer);
141
142
    IntSize contentOffsetInCompostingLayer();
143
    // Result is transform origin in pixels.
144
    FloatPoint computeTransformOrigin(const IntRect& borderBox) const;
145
146
    void updateLayerOpacity();
147
    void updateLayerTransform();
148
149
    // Return the opacity value that this layer should use for compositing.
150
    float compositingOpacity(float rendererOpacity) const;
151
    
152
    // Returns true if this RenderLayer only has content that can be rendered directly
153
    // by the compositing layer, without drawing (e.g. solid background color).
154
    bool isSimpleContainerCompositingLayer();
155
156
    bool rendererHasBackground() const;
157
    const Color& rendererBackgroundColor() const;
158
159
    bool canBeSimpleContainerCompositingLayer() const;
160
    bool hasNonCompositingContent() const;
161
    
162
    void paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect,
163
                    bool haveTransparency, PaintRestriction paintRestriction, GraphicsLayerPaintingPhase, RenderObject* paintingRoot);
164
165
    RenderLayer* findHitCompositingLayer(RenderLayer* rootLayer, const HitTestRequest&, HitTestResult&, const IntRect& hitTestRect, const IntPoint& hitTestPoint);
166
167
private:
168
    RenderLayer* m_owningLayer;
169
170
    GraphicsLayer* m_ancestorClippingLayer; // only used if we are clipped by an ancestor which is not a stacking context
171
    GraphicsLayer* m_graphicsLayer;
172
    GraphicsLayer* m_contentsLayer;         // only used in cases where we need to draw the foreground separately
173
    GraphicsLayer* m_clippingLayer;         // only used if we have clipping on a stacking context, with compositing children
174
175
    IntSize m_compositingContentOffset;
176
177
    bool m_forceCompositingLayer : 1;   // set if we need a compositing layer because of some external requirement
178
    bool m_isSimpleContainerCompositingLayer : 1;  // is this compositing layer able to be simplified
179
    bool m_simpleCompositingLayerStatusDirty : 1; // set if the test for simple layers needs to be redone
180
181
    bool m_compositingContentOffsetDirty: 1;
182
};
183
184
} // namespace WebCore
185
186
#endif // USE(ACCELERATED_COMPOSITING)
187
188
#endif // RenderLayerBacking_h
- a/WebCore/rendering/RenderLayerCompositor.cpp +757 lines
Line 0 a/WebCore/rendering/RenderLayerCompositor.cpp_sec1
1
/*
2
 * Copyright (C) 2009 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 *
8
 * 1.  Redistributions of source code must retain the above copyright
9
 *     notice, this list of conditions and the following disclaimer. 
10
 * 2.  Redistributions in binary form must reproduce the above copyright
11
 *     notice, this list of conditions and the following disclaimer in the
12
 *     documentation and/or other materials provided with the distribution. 
13
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14
 *     its contributors may be used to endorse or promote products derived
15
 *     from this software without specific prior written permission. 
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
28
29
#include "config.h"
30
31
#if ENABLE(3D_TRANSFORMS)
32
// This symbol is used to determine from a script whether 3D transforms are enabled (via 'nm').
33
bool WebCoreHas3DTransforms = true;
34
#endif
35
36
#if USE(ACCELERATED_COMPOSITING)
37
38
#include "RenderLayerCompositor.h"
39
40
#include "AnimationController.h"
41
#include "ChromeClient.h"
42
#include "FrameView.h"
43
#include "GraphicsLayer.h"
44
#include "HitTestRequest.h"
45
#include "HitTestResult.h"
46
#include "Page.h"
47
#include "RenderLayerBacking.h"
48
#include "RenderView.h"
49
#include "SystemTime.h"
50
51
#ifndef NDEBUG
52
#include "CString.h"
53
#include "RenderTreeAsText.h"
54
#endif
55
56
namespace WebCore {
57
58
struct CompositingState {
59
    CompositingState(RenderLayer* inCompAncestor)
60
    : m_subtreeIsCompositing(false)
61
    , m_compositingAncestor(inCompAncestor)
62
    , m_depth(0)
63
    {
64
    }
65
    
66
    bool m_subtreeIsCompositing;
67
    RenderLayer* m_compositingAncestor;
68
    int m_depth;        // just used for debugging
69
};
70
71
static TransformationMatrix flipTransform()
72
{
73
    TransformationMatrix flipper;
74
    flipper.flipY();
75
    return flipper;
76
}
77
78
RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView)
79
    : m_renderView(renderView)
80
    , m_rootPlatformLayer(0)
81
    , m_compositing(false)
82
    , m_rootLayerAttached(false)
83
    , m_compositingLayersNeedUpdate(false)
84
#if PROFILE_LAYER_REBUILD
85
    , m_rootLayerUpdateCount(0)
86
#endif // PROFILE_LAYER_REBUILD
87
{
88
}
89
90
RenderLayerCompositor::~RenderLayerCompositor()
91
{
92
    ASSERT(!m_rootLayerAttached);
93
    delete m_rootPlatformLayer;
94
}
95
96
void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */)
97
{
98
    if (enable != m_compositing) {
99
        m_compositing = enable;
100
        
101
        // We never go out of compositing mode for a given page,
102
        // but if all the layers disappear, we'll just be left with
103
        // the empty root layer, which has minimal overhead.
104
        if (m_compositing)
105
            ensureRootPlatformLayer();
106
    }
107
}
108
109
void RenderLayerCompositor::setCompositingLayersNeedUpdate(bool needUpdate)
110
{
111
    if (inCompositingMode())
112
        m_compositingLayersNeedUpdate = needUpdate;
113
}
114
115
void RenderLayerCompositor::updateCompositingLayers(RenderLayer* updateRoot)
116
{
117
    if (!m_compositingLayersNeedUpdate)
118
        return;
119
120
    m_compositingLayersNeedUpdate = false;
121
122
    ASSERT(inCompositingMode());
123
124
    if (!updateRoot)
125
        updateRoot = rootRenderLayer();
126
127
#if PROFILE_LAYER_REBUILD
128
    ++m_rootLayerUpdateCount;
129
    
130
    double startTime = currentTime();
131
#endif        
132
133
    // Go through the layers in presentation order, so that we can compute which
134
    // RLs need compositing layers.
135
    // FIXME: we could maybe do this in one pass, but the parenting logic would be more
136
    // complex.
137
    {
138
        CompositingState compState(updateRoot);
139
        computeCompositingRequirements(updateRoot, compState);
140
    }
141
142
    // Now create and parent the compositing layers.
143
    {
144
        CompositingState compState(updateRoot);
145
        rebuildCompositingLayerTree(updateRoot, compState);
146
    }
147
    
148
    {
149
        // If you uncomment this, be sure to comment the layout() and updateCompositingLayers() lines in
150
        // RenderTreeAsText.cpp, externalRepresentation(), to avoid recursion.
151
        //String dump = externalRepresentation(m_renderView);
152
        //fprintf(stderr, "%s", dump.utf8().data());
153
    }
154
155
#if PROFILE_LAYER_REBUILD
156
    double endTime = currentTime();
157
    if (!updateRoot)
158
        fprintf(stderr, "Update %d: computeCompositingRequirements for the world took %fms\n"
159
                    m_rootLayerUpdateCount, 1000.0 * (endTime - startTime));
160
#endif
161
    ASSERT(!m_compositingLayersNeedUpdate);
162
}
163
164
bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, RenderStyle::Diff diff)
165
{
166
    bool needsLayer = needsToBeComposited(layer);
167
    bool layerChanged = false;
168
    if (needsLayer) {
169
        enableCompositingMode();
170
        if (!layer->backing()) {
171
            layer->ensureBacking();
172
            layerChanged = true;
173
        }
174
    } else {
175
        if (layer->backing()) {
176
            layer->clearBacking();
177
            layerChanged = true;
178
        }
179
    }
180
    
181
    if (layerChanged) {
182
        // invalidate the parent in this region
183
        RenderLayer* compLayer = enclosingCompositingLayer(layer, false);
184
        if (compLayer) {
185
            // We can't reliably compute a dirty rect, because style may have changed already, 
186
            // so just dirty the whole parent layer
187
            compLayer->setNeedsRepaint();
188
        }
189
190
        layer->renderer()->compositingStateChanged();
191
    }
192
193
    if (!needsLayer)
194
        return layerChanged;
195
196
    if (layer->backing()->updateGraphicsLayers(needsContentsCompositingLayer(layer),
197
                                               clippedByAncestor(layer),
198
                                               clipsCompositingDescendants(layer),
199
                                               diff >= RenderStyle::Repaint))
200
        layerChanged = true;
201
202
    return layerChanged;
203
}
204
205
// The bounds of the GraphicsLayer created for a compositing layer is the union of the bounds of all the descendant
206
// RenderLayers that are rendered by the composited RenderLayer.
207
IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer, IntRect* layerBoundingBox)
208
{
209
    IntRect boundingBoxRect, unionBounds;
210
    boundingBoxRect = unionBounds = layer->boundingBox(layer);
211
    
212
    ASSERT(layer->isStackingContext() || (!layer->m_posZOrderList || layer->m_posZOrderList->size() == 0));
213
214
    Vector<RenderLayer*>* negZOrderList = layer->negZOrderList();
215
    if (negZOrderList)
216
        for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) {
217
            RenderLayer* curLayer = (*it);
218
            if (!curLayer->isComposited()) {
219
                IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer);
220
                unionBounds.unite(childUnionBounds);
221
            }
222
        }
223
224
    Vector<RenderLayer*>* posZOrderList = layer->posZOrderList();
225
    if (posZOrderList)
226
        for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) {
227
            RenderLayer* curLayer = (*it);
228
            if (!curLayer->isComposited()) {
229
                IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer);
230
                unionBounds.unite(childUnionBounds);
231
            }
232
        }
233
234
    Vector<RenderLayer*>* overflowList = layer->overflowList();
235
    if (overflowList)
236
        for (Vector<RenderLayer*>::iterator it = overflowList->begin(); it != overflowList->end(); ++it) {
237
            RenderLayer* curLayer = (*it);
238
            if (!curLayer->isComposited()) {
239
                IntRect curAbsBounds = calculateCompositedBounds(curLayer, layer);
240
                unionBounds.unite(curAbsBounds);
241
            }
242
        }
243
244
    if (!layer->isComposited() && layer->transform()) {
245
        TransformationMatrix* affineTrans = layer->transform();
246
        boundingBoxRect = affineTrans->mapRect(boundingBoxRect);
247
        unionBounds = affineTrans->mapRect(unionBounds);
248
    }
249
250
    int ancestorRelX = 0, ancestorRelY = 0;
251
    layer->convertToLayerCoords(ancestorLayer, ancestorRelX, ancestorRelY);
252
    unionBounds.move(ancestorRelX, ancestorRelY);
253
254
    if (layerBoundingBox) {
255
        boundingBoxRect.move(ancestorRelX, ancestorRelY);
256
        *layerBoundingBox = boundingBoxRect;
257
    }
258
    
259
    return unionBounds;
260
}
261
262
void RenderLayerCompositor::layerWasAdded(RenderLayer* /*parent*/, RenderLayer* /*child*/)
263
{
264
    setCompositingLayersNeedUpdate();
265
}
266
267
void RenderLayerCompositor::layerWillBeRemoved(RenderLayer* parent, RenderLayer* child)
268
{
269
    if (child->isComposited())
270
        setCompositingParent(child, 0);
271
    
272
    RenderLayer* compLayer = enclosingCompositingLayer(parent, false);
273
    if (compLayer) {
274
        IntRect ancestorRect = calculateCompositedBounds(child, compLayer);
275
        compLayer->setNeedsRepaintInRect(ancestorRect);
276
    }
277
278
    setCompositingLayersNeedUpdate();
279
}
280
281
RenderLayer* RenderLayerCompositor::enclosingCompositingLayer(RenderLayer* layer, bool includeSelf) const
282
{
283
    if (includeSelf && layer->isComposited())
284
        return layer;
285
286
    bool childOverflowOnly = layer->isOverflowOnly();
287
    RenderLayer* curr = layer->parent();
288
    
289
    for ( ; curr != 0; curr = curr->parent()) {
290
        // Compositing layers are parented according to stacking order and overflow list,
291
        // so we have to check whether the parent is a stacking context, or whether 
292
        // the child is overflow-only.
293
        if (curr->isComposited() && (childOverflowOnly || curr->isStackingContext()))
294
            return curr;
295
        
296
        childOverflowOnly = curr->isOverflowOnly();
297
    }
298
         
299
    return 0;
300
}
301
302
RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const RenderLayer* layer) const
303
{
304
    RenderLayer* curr = layer->parent();
305
    for ( ; curr != 0; curr = curr->parent()) {
306
        if (curr->isStackingContext())
307
            return 0;
308
309
        if (curr->renderer()->hasOverflowClip())
310
            return curr;
311
    }
312
    return 0;
313
}
314
315
//  Recurse through the layers in z-index and overflow order (which is equivalent to painting order)
316
//  For the z-order children of a compositing layer:
317
//      If a child layers has a compositing layer, then all subsequent layers must
318
//      be compositing in order to render above that layer.
319
//
320
//      If a child in the negative z-order list is compositing, then the layer itself
321
//      must be compositing so that its contents render over that child.
322
//      This implies that its positive z-index children must also be compositing.
323
//
324
void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, struct CompositingState& ioCompState)
325
{
326
    // Make sure this layer's z-order and overflow lists are up to date
327
    layer->updateThisLayer();
328
    
329
    // Clear the flag
330
    layer->setHasCompositingDescendant(false);
331
332
    setForcedCompositingLayer(layer, ioCompState.m_subtreeIsCompositing);
333
    
334
    const bool isCompositingLayer = needsToBeComposited(layer);
335
    ioCompState.m_subtreeIsCompositing = isCompositingLayer;
336
337
    CompositingState childState = ioCompState;
338
    if (isCompositingLayer)
339
        childState.m_compositingAncestor = layer;
340
341
    // The children of this stacking context don't need to composite, unless there is
342
    // a compositing layer among them, so start by assuming false.
343
    childState.m_subtreeIsCompositing = false;
344
345
    ++childState.m_depth;
346
347
    if (layer->isStackingContext()) {
348
        ASSERT(!layer->m_zOrderListsDirty);
349
        Vector<RenderLayer*>* negZOrderList = layer->negZOrderList();
350
        if (negZOrderList && negZOrderList->size() > 0) {
351
            for (Vector<RenderLayer*>::const_iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) {
352
                RenderLayer* curLayer = (*it);
353
                computeCompositingRequirements(curLayer, childState);
354
355
                // if we have to make a layer for this child, make one now so we can have a contents layer
356
                // (since we need to ensure that the -ve z-order child renders underneath our contents)
357
                if (childState.m_subtreeIsCompositing) {
358
                    // make |this| compositing
359
                    setForcedCompositingLayer(layer, true);
360
                    childState.m_compositingAncestor = layer;
361
                }
362
            }
363
        }
364
    }
365
    
366
    ASSERT(!layer->m_overflowListDirty);
367
    Vector<RenderLayer*>* overflowList = layer->overflowList();
368
    if (overflowList && overflowList->size() > 0)
369
        for (Vector<RenderLayer*>::const_iterator it = overflowList->begin(); it != overflowList->end(); ++it) {
370
            RenderLayer* curLayer = (*it);
371
            computeCompositingRequirements(curLayer, childState);
372
        }
373
374
    if (layer->isStackingContext()) {
375
        Vector<RenderLayer*>* posZOrderList = layer->posZOrderList();
376
        if (posZOrderList && posZOrderList->size() > 0)
377
            for (Vector<RenderLayer*>::const_iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) {
378
                RenderLayer* curLayer = (*it);
379
                computeCompositingRequirements(curLayer, childState);
380
            }
381
    }
382
383
    // If we have a software transform, and we have layers under us, we need to also
384
    // be composited. Also, if we have opacity < 1, then we need to be a layer so that
385
    // the child layers are opaque, then rendered with opacity on this layer.
386
    if (childState.m_subtreeIsCompositing &&
387
        (layer->renderer()->style()->hasTransform() || layer->renderer()->style()->opacity() < 1))
388
        setForcedCompositingLayer(layer, true);
389
390
    // Subsequent layers in the parent stacking context also need to composite.
391
    if (childState.m_subtreeIsCompositing)
392
        ioCompState.m_subtreeIsCompositing = true;
393
394
    // Set the flag to say that this SC has compositing children.
395
    // this can affect the answer to needsToBeComposited() when clipping,
396
    // but that's ok here.
397
    layer->setHasCompositingDescendant(childState.m_subtreeIsCompositing);
398
}
399
400
void RenderLayerCompositor::setForcedCompositingLayer(RenderLayer* layer, bool force)
401
{
402
    if (force) {
403
        layer->ensureBacking();
404
        layer->backing()->forceCompositingLayer();
405
    } else {
406
        if (layer->backing())
407
            layer->backing()->forceCompositingLayer(false);
408
    }
409
}
410
411
void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer)
412
{
413
    ASSERT(childLayer->isComposited());
414
    ASSERT(!parentLayer || parentLayer->isComposited());
415
    
416
    if (parentLayer) {
417
        GraphicsLayer* hostingLayer = parentLayer->backing()->parentForSublayers();
418
        GraphicsLayer* hostedLayer = childLayer->backing()->childForSuperlayers();
419
        
420
        hostingLayer->addChild(hostedLayer);
421
    } else
422
        childLayer->backing()->childForSuperlayers()->removeFromParent();
423
    
424
    // FIXME: setCompositingParent() is only called at present by rebuildCompositingLayerTree(),
425
    // which calls updateGraphicsLayerGeometry via updateLayerCompositingState(), so this should
426
    // be optimized.
427
    if (parentLayer)
428
        childLayer->backing()->updateGraphicsLayerGeometry();
429
}
430
431
void RenderLayerCompositor::removeCompositedChildren(RenderLayer* layer)
432
{
433
    ASSERT(layer->isComposited());
434
435
    GraphicsLayer* hostingLayer = layer->backing()->parentForSublayers();
436
    hostingLayer->removeAllChildren();
437
}
438
439
void RenderLayerCompositor::parentInRootLayer(RenderLayer* layer)
440
{
441
    ASSERT(layer->isComposited());
442
443
    GraphicsLayer* layerAnchor = layer->backing()->childForSuperlayers();
444
445
    if (layerAnchor->parent() != m_rootPlatformLayer) {
446
        layerAnchor->removeFromParent();
447
        if (m_rootPlatformLayer)
448
            m_rootPlatformLayer->addChild(layerAnchor);
449
    }
450
}
451
452
void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, struct CompositingState& ioCompState)
453
{
454
#if 0
455
    bool internalNeedToComposite = requiresCompositingLayer(layer);
456
457
    for (int i = 0; i < ioCompState.m_depth; ++i)
458
        fprintf(stderr, "  ");
459
460
    fprintf(stderr, "rebuildCompositingLayerTree %p: has layer %d, requires layer %d, force layer %d, stacking %d\n",
461
                    this, layer->isComposited(), internalNeedToComposite, ioCompState.m_subtreeIsCompositing, layer->isStackingContext());
462
463
    for (int i = 0; i < ioCompState.m_depth; ++i)
464
        fprintf(stderr, "  ");
465
    fprintf(stderr, "forceCompositingLayer(%d) %p\n", ioCompState.m_subtreeIsCompositing, this);
466
#endif
467
468
    updateLayerCompositingState(layer, RenderStyle::Equal);
469
470
    // host the document layer in the RenderView's root layer
471
    if (layer->isDocumentLayer())
472
        parentInRootLayer(layer);
473
474
    CompositingState childState = ioCompState;
475
    if (layer->isComposited())
476
        childState.m_compositingAncestor = layer;
477
478
    ++childState.m_depth;
479
480
    RenderLayerBacking* layerBacking = layer->backing();
481
    
482
    // FIXME: make this more incremental
483
    if (layer->isComposited()) {
484
        layerBacking->parentForSublayers()->removeAllChildren();
485
        layerBacking->updateInternalHierarchy();
486
    }
487
    
488
    // The children of this stacking context don't need to composite, unless there is
489
    // a compositing layer among them, so start by assuming false.
490
    childState.m_subtreeIsCompositing = false;
491
492
    if (layer->isStackingContext()) {
493
        ASSERT(!layer->m_zOrderListsDirty);
494
495
        Vector<RenderLayer*>* negZOrderList = layer->negZOrderList();
496
        if (negZOrderList && negZOrderList->size() > 0) {
497
            for (Vector<RenderLayer*>::const_iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) {
498
                RenderLayer* curLayer = (*it);
499
                rebuildCompositingLayerTree(curLayer, childState);
500
                if (curLayer->isComposited())
501
                    setCompositingParent(curLayer, childState.m_compositingAncestor);
502
            }
503
        }
504
505
        if (layerBacking && layerBacking->contentsLayer()) {
506
            // we only have a contents layer if we have an m_layer
507
            layerBacking->contentsLayer()->removeFromParent();
508
509
            GraphicsLayer* hostingLayer = layerBacking->clippingLayer() ? layerBacking->clippingLayer() : layerBacking->graphicsLayer();
510
            hostingLayer->addChild(layerBacking->contentsLayer());
511
        }
512
    }
513
514
    ASSERT(!layer->m_overflowListDirty);
515
    Vector<RenderLayer*>* overflowList = layer->overflowList();
516
    if (overflowList && overflowList->size() > 0)
517
        for (Vector<RenderLayer*>::iterator it = overflowList->begin(); it != overflowList->end(); ++it) {
518
            RenderLayer* curLayer = (*it);
519
            rebuildCompositingLayerTree(curLayer, childState);
520
            if (curLayer->isComposited())
521
                setCompositingParent(curLayer, childState.m_compositingAncestor);
522
        }
523
    
524
    if (layer->isStackingContext()) {
525
        Vector<RenderLayer*>* posZOrderList = layer->posZOrderList();
526
        if (posZOrderList && posZOrderList->size() > 0)
527
            for (Vector<RenderLayer*>::const_iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) {
528
                RenderLayer* curLayer = (*it);
529
                rebuildCompositingLayerTree(curLayer, childState);
530
                if (curLayer->isComposited())
531
                    setCompositingParent(curLayer, childState.m_compositingAncestor);
532
            }
533
    }
534
}
535
536
// repaint the given rect in this layer, and optionally the rect in all child layers
537
void RenderLayerCompositor::repaintCompositingLayerRect(RenderLayer* layer, const IntRect& inRect, bool includeDescendants)
538
{
539
    if (layer->isComposited())
540
        layer->backing()->setContentsNeedDisplayInRect(inRect);
541
542
    if (layer->hasCompositingDescendant() && includeDescendants) {
543
        ASSERT(layer->isStackingContext() || (!layer->m_posZOrderList || layer->m_posZOrderList->size() == 0));
544
545
        Vector<RenderLayer*>* negZOrderList = layer->negZOrderList();
546
        if (negZOrderList)
547
            for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) {
548
                RenderLayer* curLayer = (*it);
549
                int x = 0, y = 0;
550
                curLayer->convertToLayerCoords(layer, x, y);
551
                IntRect childRect(inRect);
552
                childRect.move(-x, -y);
553
                repaintCompositingLayerRect(curLayer, childRect, true);
554
            }
555
556
        Vector<RenderLayer*>* posZOrderList = layer->posZOrderList();
557
        if (posZOrderList)
558
            for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) {
559
                RenderLayer* curLayer = (*it);
560
                int x = 0, y = 0;
561
                curLayer->convertToLayerCoords(layer, x, y);
562
                IntRect childRect(inRect);
563
                childRect.move(-x, -y);
564
                repaintCompositingLayerRect(curLayer, childRect, true);
565
            }
566
567
        Vector<RenderLayer*>* overflowList = layer->overflowList();
568
        if (overflowList)
569
            for (Vector<RenderLayer*>::iterator it = overflowList->begin(); it != overflowList->end(); ++it) {
570
                RenderLayer* curLayer = (*it);
571
                int x = 0, y = 0;
572
                curLayer->convertToLayerCoords(layer, x, y);
573
                IntRect childRect(inRect);
574
                childRect.move(-x, -y);
575
                repaintCompositingLayerRect(curLayer, childRect, true);
576
            }
577
    }
578
}
579
580
RenderLayer* RenderLayerCompositor::rootRenderLayer() const
581
{
582
    return m_renderView->layer();
583
}
584
585
GraphicsLayer* RenderLayerCompositor::rootPlatformLayer() const
586
{
587
    return m_rootPlatformLayer;
588
}
589
590
void RenderLayerCompositor::willBeDetached()
591
{
592
    if (m_rootPlatformLayer && m_rootLayerAttached) {
593
        Frame* frame = m_renderView->frameView()->frame();
594
        if (!frame)
595
            return;
596
        Page* page = frame->page();
597
        if (!page)
598
            return;
599
        page->chrome()->client()->attachRootGraphicsLayer(frame, 0);
600
        m_rootLayerAttached = false;
601
    }
602
}
603
604
void RenderLayerCompositor::wasAttached()
605
{
606
    if (m_rootPlatformLayer) {
607
        Frame* frame = m_renderView->frameView()->frame();
608
        if (!frame)
609
            return;
610
        Page* page = frame->page();
611
        if (!page)
612
            return;
613
        page->chrome()->client()->attachRootGraphicsLayer(frame, m_rootPlatformLayer);
614
        m_rootLayerAttached = true;
615
    }
616
}
617
618
void RenderLayerCompositor::updateRootLayerPosition()
619
{
620
    if (m_rootPlatformLayer)
621
        m_rootPlatformLayer->setSize(FloatSize(m_renderView->docWidth(), m_renderView->docHeight()));
622
}
623
624
bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const
625
{
626
    return requiresCompositingLayer(layer) || (layer->backing() && layer->backing()->forcedCompositingLayer());
627
}
628
629
static bool requiresCompositingLayerForTransform(const RenderStyle*)
630
{
631
    return false;
632
}
633
634
#define VERBOSE_COMPOSITINGLAYER    0
635
636
// Note: this specifies whether the RL needs a compositing layer for intrinsic reasons.
637
// Use needsToBeComposited() to determine if a RL actually needs a compositing layer.
638
// static
639
bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) const
640
{
641
    // TODO: cache the result of these tests?
642
    const RenderStyle* renderStyle = layer->renderer()->style();
643
644
#if VERBOSE_COMPOSITINGLAYER
645
    bool gotReason = false;
646
647
    if (!gotReason && inCompositingMode() && layer->isDocumentLayer()) {
648
        fprintf(stderr, "RenderLayer %p requires compositing layer because: it's the document root\n", layer);
649
        gotReason = true;
650
    }
651
    
652
    if (!gotReason && requiresCompositingLayerForTransform(renderStyle)) {
653
        fprintf(stderr, "RenderLayer %p requires compositing layer because: it has 3d transform, perspective, backface, or animating transform\n", layer);
654
        gotReason = true;
655
    }
656
657
    if (!gotReason && clipsCompositingDescendants(layer)) {
658
        fprintf(stderr, "RenderLayer %p requires compositing layer because: it has overflow clip\n", layer);
659
        gotReason = true;
660
    }
661
662
    if (!gotReason && requiresCompositingForAnimation(layer)) {
663
        fprintf(stderr, "RenderLayer %p requires compositing layer because: it has a running transition for opacity or transform\n", layer);
664
        gotReason = true;
665
    }
666
    
667
    if (!gotReason)
668
        fprintf(stderr, "RenderLayer %p does not require compositing layer\n", layer);
669
#endif
670
671
    // the root layer always has a compositing layer (for now).
672
    return (inCompositingMode() && layer->isDocumentLayer()) ||
673
#ifndef NDEBUG
674
             (GraphicsLayer::showLayerHierarchy() && layer->isDocumentLayer()) ||
675
#endif
676
             requiresCompositingLayerForTransform(renderStyle) ||
677
             clipsCompositingDescendants(layer) ||
678
             requiresCompositingForAnimation(layer);
679
}
680
681
// Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips,
682
// up to the enclosing compositing ancestor. This is required because compositing layers are parented
683
// according to the z-order hierarchy, yet clipping goes down the renderer hierarchy.
684
// Thus, a RenderLayer can be clipped by a RenderLayer that is an ancestor in the renderer hierarchy,
685
// but a sibling in the z-order hierarchy.
686
bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const
687
{
688
    if (!layer->isComposited() || !layer->parent())
689
        return false;
690
691
    RenderLayer* compositingAncestor = enclosingCompositingLayer(layer, false);
692
693
    // We need ancestor clipping if something clips between this layer and its compositing, stacking context ancestor
694
    for (RenderLayer* curLayer = layer->parent(); curLayer && curLayer != compositingAncestor; curLayer = curLayer->parent()) {
695
        // FIXME: need to look at hasClip() too eventually
696
        if (curLayer->renderer()->hasOverflowClip())
697
            return true;
698
        
699
        // Clip is reset for an absolutely positioned element.
700
        // FIXME: many cases are broken. We need more of the logic in calculateClipRects() here
701
        if (curLayer->renderer()->style()->position() == AbsolutePosition)
702
            break;
703
    }
704
705
    return false;
706
}
707
708
// Return true if the given layer is a stacking context and has compositing child
709
// layers that it needs to clip. In this case we insert a clipping GraphicsLayer
710
// into the hierarchy between this layer and its children in the z-order hierarchy.
711
bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer) const
712
{
713
    // FIXME: need to look at hasClip() too eventually
714
    return layer->hasCompositingDescendant() &&
715
           layer->isStackingContext() &&
716
           layer->renderer()->hasOverflowClip();
717
}
718
719
bool RenderLayerCompositor::requiresCompositingForAnimation(const RenderLayer* layer) const
720
{
721
    AnimationController* animController = layer->renderer()->animation();
722
    if (animController)
723
        return animController->isAnimatingPropertyOnRenderer(layer->renderer(), CSSPropertyOpacity) ||
724
               animController->isAnimatingPropertyOnRenderer(layer->renderer(), CSSPropertyWebkitTransform);
725
    return false;
726
}
727
728
// If an element has negative z-index children, those children render in front of the 
729
// layer background, so we need an extra 'contents' layer for the foreground of the layer
730
// object.
731
bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer* layer) const
732
{
733
    return (layer->m_negZOrderList && layer->m_negZOrderList->size() > 0);
734
}
735
736
void RenderLayerCompositor::ensureRootPlatformLayer()
737
{
738
    if (m_rootPlatformLayer)
739
        return;
740
741
    m_rootPlatformLayer = GraphicsLayer::createGraphicsLayer(0);
742
    m_rootPlatformLayer->setSize(FloatSize(m_renderView->docWidth(), m_renderView->docHeight()));
743
    m_rootPlatformLayer->setPosition(FloatPoint(0, 0));
744
745
    if (GraphicsLayer::graphicsContextsFlipped())
746
        m_rootPlatformLayer->setChildrenTransform(flipTransform());
747
748
    // Need to clip to prevent transformed content showing outside this frame
749
    m_rootPlatformLayer->setMasksToBounds(true);
750
    
751
    wasAttached();
752
}
753
754
} // namespace WebCore
755
756
#endif // USE(ACCELERATED_COMPOSITING)
757
- a/WebCore/rendering/RenderLayerCompositor.h +137 lines
Line 0 a/WebCore/rendering/RenderLayerCompositor.h_sec1
1
/*
2
 * Copyright (C) 2009 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 *
8
 * 1.  Redistributions of source code must retain the above copyright
9
 *     notice, this list of conditions and the following disclaimer. 
10
 * 2.  Redistributions in binary form must reproduce the above copyright
11
 *     notice, this list of conditions and the following disclaimer in the
12
 *     documentation and/or other materials provided with the distribution. 
13
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14
 *     its contributors may be used to endorse or promote products derived
15
 *     from this software without specific prior written permission. 
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
28
29
#ifndef RenderLayerCompositor_h
30
#define RenderLayerCompositor_h
31
32
#include "RenderLayer.h"
33
34
namespace WebCore {
35
36
#define PROFILE_LAYER_REBUILD 0
37
38
class GraphicsLayer;
39
40
// RenderLayerCompositor manages the hierarchy of
41
// composited RenderLayers. It determines which RenderLayers
42
// become compositing, and creates and maintains a hierarchy of
43
// GraphicsLayers based on the RenderLayer painting order.
44
// 
45
// There is one RenderLayerCompositor per RenderView.
46
47
class RenderLayerCompositor {
48
public:
49
50
    RenderLayerCompositor(RenderView*);
51
    ~RenderLayerCompositor();
52
    
53
    // Return true if this RenderView is in "compositing mode" (i.e. has one or more
54
    // composited RenderLayers)
55
    bool inCompositingMode() const { return m_compositing; }
56
    // This will make a compositing layer at the root automatically, and hook up to
57
    // the native view/window system.
58
    void enableCompositingMode(bool enable = true);
59
60
    void setCompositingLayersNeedUpdate(bool needUpdate = true);
61
    bool compositingLayersNeedUpdate() const { return m_compositingLayersNeedUpdate; }
62
63
    // Rebuild the tree of compositing layers
64
    void updateCompositingLayers(RenderLayer* updateRoot = 0);
65
66
    // Update the compositing state of the given layer. Returns true if that state changed
67
    bool updateLayerCompositingState(RenderLayer*, RenderStyle::Diff);
68
69
    // Return the bounding box required for compositing layer and its childern, relative to ancestorLayer.
70
    // If layerBoundingBox is not 0, on return it contains the bounding box of this layer only.
71
    IntRect calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer, IntRect* layerBoundingBox = 0);
72
    
73
    // Notify us that a layer has been added or removed
74
    void layerWasAdded(RenderLayer* parent, RenderLayer* child);
75
    void layerWillBeRemoved(RenderLayer* parent, RenderLayer* child);
76
77
    // Gets the nearest enclosing render layer that is composited (optionally including self)
78
    RenderLayer* enclosingCompositingLayer(RenderLayer* layer, bool includeSelf = true) const;
79
80
    // Get the nearest ancestor layer that has overflow or clip, but is not a stacking context
81
    RenderLayer* enclosingNonStackingClippingLayer(const RenderLayer* layer) const;
82
83
    void repaintCompositingLayerRect(RenderLayer*, const IntRect&, bool includeDescendants);
84
85
    RenderLayer* rootRenderLayer() const;
86
    GraphicsLayer* rootPlatformLayer() const;
87
88
    void willBeDetached();
89
    void wasAttached();
90
    void updateRootLayerPosition();
91
92
private:
93
    // Whether the given RL needs a compositing layer.
94
    bool needsToBeComposited(const RenderLayer*) const;
95
    // Whether the layer has an intrinsic need for compositing layer.
96
    bool requiresCompositingLayer(const RenderLayer*) const;
97
98
    // Whether we need a graphics layer to do clipping by an ancestor (non-stacking-context parent with overflow).
99
    bool clippedByAncestor(RenderLayer*) const;
100
    // Whether we need a graphics layer to clip z-order children of the given layer.
101
    bool clipsCompositingDescendants(const RenderLayer*) const;
102
103
    // Whether a running transition or animation enforces the need for a compositing layer.
104
    bool requiresCompositingForAnimation(const RenderLayer*) const;
105
    // Whether the given layer needs an extra 'contents' layer.
106
    bool needsContentsCompositingLayer(const RenderLayer*) const;
107
108
    // Set a bit on this layer to force it to be composisted, because it has to render on top of
109
    // other compositing layers.
110
    void setForcedCompositingLayer(RenderLayer*, bool force);
111
112
    void computeCompositingRequirements(RenderLayer*, struct CompositingState& compState);
113
    void rebuildCompositingLayerTree(RenderLayer* layer, struct CompositingState& compState);
114
115
    // Hook compositing layers together
116
    void setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer);
117
    void removeCompositedChildren(RenderLayer* layer);
118
119
    void parentInRootLayer(RenderLayer* layer);
120
121
    void ensureRootPlatformLayer();
122
123
private:
124
    RenderView* m_renderView;
125
    GraphicsLayer* m_rootPlatformLayer;
126
    bool m_compositing;
127
    bool m_rootLayerAttached;
128
    bool m_compositingLayersNeedUpdate;
129
#if PROFILE_LAYER_REBUILD
130
    int m_rootLayerUpdateCount;
131
#endif
132
};
133
134
135
} // namespace WebCore
136
137
#endif // RenderLayerCompositor_h

Return to Bug 23357