Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Side by Side Diff: third_party/WebKit/Source/platform/graphics/paint/GeometryMapper.cpp

Issue 2672993004: Fix clip caching bug in GeometryMapper. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "platform/graphics/paint/GeometryMapper.h" 5 #include "platform/graphics/paint/GeometryMapper.h"
6 6
7 #include "platform/RuntimeEnabledFeatures.h" 7 #include "platform/RuntimeEnabledFeatures.h"
8 #include "platform/geometry/LayoutRect.h" 8 #include "platform/geometry/LayoutRect.h"
9 9
10 namespace blink { 10 namespace blink {
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 154
155 const auto& transformMatrix = 155 const auto& transformMatrix =
156 localToAncestorMatrix(localTransformNode, ancestorTransformNode); 156 localToAncestorMatrix(localTransformNode, ancestorTransformNode);
157 DCHECK(transformMatrix.isInvertible()); 157 DCHECK(transformMatrix.isInvertible());
158 158
159 // TODO(chrishtr): Cache the inverse? 159 // TODO(chrishtr): Cache the inverse?
160 return transformMatrix.inverse().mapRect(rect); 160 return transformMatrix.inverse().mapRect(rect);
161 } 161 }
162 162
163 PrecomputedDataForAncestor& GeometryMapper::getPrecomputedDataForAncestor( 163 PrecomputedDataForAncestor& GeometryMapper::getPrecomputedDataForAncestor(
164 const TransformPaintPropertyNode* ancestorTransformNode) { 164 const TransformPaintPropertyNode* transform) {
165 auto addResult = m_data.insert(ancestorTransformNode, nullptr); 165 auto addResult = m_data.insert(transform, nullptr);
166 if (addResult.isNewEntry) 166 if (addResult.isNewEntry)
167 addResult.storedValue->value = PrecomputedDataForAncestor::create(); 167 addResult.storedValue->value = PrecomputedDataForAncestor::create();
168 return *addResult.storedValue->value; 168 return *addResult.storedValue->value;
169 } 169 }
170 170
171 TransformCache& GeometryMapper::getTransformCache(
172 const TransformPaintPropertyNode* node) {
173 return getPrecomputedDataForAncestor(node).toAncestorTransforms;
174 }
175
176 ClipCache& GeometryMapper::getClipCache(
177 const TransformPaintPropertyNode* transform,
178 const ClipPaintPropertyNode* clip) {
179 PrecomputedDataForAncestor& precomputedData =
180 getPrecomputedDataForAncestor(transform);
181
182 auto addResult = precomputedData.precomputedClips.insert(clip, nullptr);
183 if (addResult.isNewEntry)
184 addResult.storedValue->value = WTF::makeUnique<ClipCache>();
185 return *addResult.storedValue->value;
186 }
187
171 FloatRect GeometryMapper::localToAncestorClipRect( 188 FloatRect GeometryMapper::localToAncestorClipRect(
172 const PropertyTreeState& localState, 189 const PropertyTreeState& localState,
173 const PropertyTreeState& ancestorState) { 190 const PropertyTreeState& ancestorState) {
174 bool success = false; 191 bool success = false;
175 FloatRect result = 192 FloatRect result =
176 localToAncestorClipRectInternal(localState, ancestorState, success); 193 localToAncestorClipRectInternal(localState, ancestorState, success);
177 DCHECK(success); 194 DCHECK(success);
178 return result; 195 return result;
179 } 196 }
180 197
181 FloatRect GeometryMapper::localToAncestorClipRectInternal( 198 FloatRect GeometryMapper::localToAncestorClipRectInternal(
182 const PropertyTreeState& localState, 199 const PropertyTreeState& localState,
183 const PropertyTreeState& ancestorState, 200 const PropertyTreeState& ancestorState,
184 bool& success) { 201 bool& success) {
185 FloatRect clip(LayoutRect::infiniteIntRect()); 202 FloatRect clip(LayoutRect::infiniteIntRect());
186 if (localState.clip() == ancestorState.clip()) { 203 if (localState.clip() == ancestorState.clip()) {
187 success = true; 204 success = true;
188 return clip; 205 return clip;
189 } 206 }
190 207
191 PrecomputedDataForAncestor& precomputedData = 208 ClipCache& clipCache =
192 getPrecomputedDataForAncestor(ancestorState.transform()); 209 getClipCache(ancestorState.transform(), ancestorState.clip());
193 const ClipPaintPropertyNode* clipNode = localState.clip(); 210 const ClipPaintPropertyNode* clipNode = localState.clip();
194 Vector<const ClipPaintPropertyNode*> intermediateNodes; 211 Vector<const ClipPaintPropertyNode*> intermediateNodes;
195 212
196 // Iterate over the path from localState.clip to ancestorState.clip. Stop if 213 // Iterate over the path from localState.clip to ancestorState.clip. Stop if
197 // we've found a memoized (precomputed) clip for any particular node. 214 // we've found a memoized (precomputed) clip for any particular node.
198 while (clipNode && clipNode != ancestorState.clip()) { 215 while (clipNode && clipNode != ancestorState.clip()) {
199 auto it = precomputedData.toAncestorClipRects.find(clipNode); 216 auto it = clipCache.find(clipNode);
200 if (it != precomputedData.toAncestorClipRects.end()) { 217 if (it != clipCache.end()) {
201 clip = it->value; 218 clip = it->value;
202 break; 219 break;
203 } 220 }
204 intermediateNodes.push_back(clipNode); 221 intermediateNodes.push_back(clipNode);
205 clipNode = clipNode->parent(); 222 clipNode = clipNode->parent();
206 } 223 }
207 if (!clipNode) { 224 if (!clipNode) {
208 success = false; 225 success = false;
209 return clip; 226 return clip;
210 } 227 }
211 228
212 // Iterate down from the top intermediate node found in the previous loop, 229 // Iterate down from the top intermediate node found in the previous loop,
213 // computing and memoizing clip rects as we go. 230 // computing and memoizing clip rects as we go.
214 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); 231 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend();
215 ++it) { 232 ++it) {
216 success = false; 233 success = false;
217 const TransformationMatrix& transformMatrix = localToAncestorMatrixInternal( 234 const TransformationMatrix& transformMatrix = localToAncestorMatrixInternal(
218 (*it)->localTransformSpace(), ancestorState.transform(), success); 235 (*it)->localTransformSpace(), ancestorState.transform(), success);
219 if (!success) 236 if (!success)
220 return clip; 237 return clip;
221 FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rect()); 238 FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rect());
222 clip.intersect(mappedRect); 239 clip.intersect(mappedRect);
223 precomputedData.toAncestorClipRects.set(*it, clip); 240 clipCache.set(*it, clip);
224 } 241 }
225 242
226 success = true; 243 success = true;
227 return precomputedData.toAncestorClipRects.find(localState.clip())->value; 244 return clipCache.find(localState.clip())->value;
228 } 245 }
229 246
230 const TransformationMatrix& GeometryMapper::localToAncestorMatrix( 247 const TransformationMatrix& GeometryMapper::localToAncestorMatrix(
231 const TransformPaintPropertyNode* localTransformNode, 248 const TransformPaintPropertyNode* localTransformNode,
232 const TransformPaintPropertyNode* ancestorTransformNode) { 249 const TransformPaintPropertyNode* ancestorTransformNode) {
233 bool success = false; 250 bool success = false;
234 const auto& result = localToAncestorMatrixInternal( 251 const auto& result = localToAncestorMatrixInternal(
235 localTransformNode, ancestorTransformNode, success); 252 localTransformNode, ancestorTransformNode, success);
236 DCHECK(success); 253 DCHECK(success);
237 return result; 254 return result;
238 } 255 }
239 256
240 const TransformationMatrix& GeometryMapper::localToAncestorMatrixInternal( 257 const TransformationMatrix& GeometryMapper::localToAncestorMatrixInternal(
241 const TransformPaintPropertyNode* localTransformNode, 258 const TransformPaintPropertyNode* localTransformNode,
242 const TransformPaintPropertyNode* ancestorTransformNode, 259 const TransformPaintPropertyNode* ancestorTransformNode,
243 bool& success) { 260 bool& success) {
244 if (localTransformNode == ancestorTransformNode) { 261 if (localTransformNode == ancestorTransformNode) {
245 success = true; 262 success = true;
246 return m_identity; 263 return m_identity;
247 } 264 }
248 265
249 PrecomputedDataForAncestor& precomputedData = 266 TransformCache& transformCache = getTransformCache(ancestorTransformNode);
250 getPrecomputedDataForAncestor(ancestorTransformNode);
251 267
252 const TransformPaintPropertyNode* transformNode = localTransformNode; 268 const TransformPaintPropertyNode* transformNode = localTransformNode;
253 Vector<const TransformPaintPropertyNode*> intermediateNodes; 269 Vector<const TransformPaintPropertyNode*> intermediateNodes;
254 TransformationMatrix transformMatrix; 270 TransformationMatrix transformMatrix;
255 271
256 // Iterate over the path from localTransformNode to ancestorState.transform. 272 // Iterate over the path from localTransformNode to ancestorState.transform.
257 // Stop if we've found a memoized (precomputed) transform for any particular 273 // Stop if we've found a memoized (precomputed) transform for any particular
258 // node. 274 // node.
259 while (transformNode && transformNode != ancestorTransformNode) { 275 while (transformNode && transformNode != ancestorTransformNode) {
260 auto it = precomputedData.toAncestorTransforms.find(transformNode); 276 auto it = transformCache.find(transformNode);
261 if (it != precomputedData.toAncestorTransforms.end()) { 277 if (it != transformCache.end()) {
262 transformMatrix = it->value; 278 transformMatrix = it->value;
263 break; 279 break;
264 } 280 }
265 intermediateNodes.push_back(transformNode); 281 intermediateNodes.push_back(transformNode);
266 transformNode = transformNode->parent(); 282 transformNode = transformNode->parent();
267 } 283 }
268 if (!transformNode) { 284 if (!transformNode) {
269 success = false; 285 success = false;
270 return m_identity; 286 return m_identity;
271 } 287 }
272 288
273 // Iterate down from the top intermediate node found in the previous loop, 289 // Iterate down from the top intermediate node found in the previous loop,
274 // computing and memoizing transforms as we go. 290 // computing and memoizing transforms as we go.
275 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); 291 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend();
276 it++) { 292 it++) {
277 TransformationMatrix localTransformMatrix = (*it)->matrix(); 293 TransformationMatrix localTransformMatrix = (*it)->matrix();
278 localTransformMatrix.applyTransformOrigin((*it)->origin()); 294 localTransformMatrix.applyTransformOrigin((*it)->origin());
279 transformMatrix = transformMatrix * localTransformMatrix; 295 transformMatrix = transformMatrix * localTransformMatrix;
280 precomputedData.toAncestorTransforms.set(*it, transformMatrix); 296 transformCache.set(*it, transformMatrix);
281 } 297 }
282 success = true; 298 success = true;
283 return precomputedData.toAncestorTransforms.find(localTransformNode)->value; 299 return transformCache.find(localTransformNode)->value;
284 } 300 }
285 301
286 void GeometryMapper::clearCache() { 302 void GeometryMapper::clearCache() {
287 m_data.clear(); 303 m_data.clear();
288 } 304 }
289 305
290 namespace { 306 namespace {
291 307
292 template <typename NodeType> 308 template <typename NodeType>
293 unsigned nodeDepth(const NodeType* node) { 309 unsigned nodeDepth(const NodeType* node) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 const TransformPaintPropertyNode*, 354 const TransformPaintPropertyNode*,
339 const TransformPaintPropertyNode*); 355 const TransformPaintPropertyNode*);
340 template const ClipPaintPropertyNode* GeometryMapper::lowestCommonAncestor( 356 template const ClipPaintPropertyNode* GeometryMapper::lowestCommonAncestor(
341 const ClipPaintPropertyNode*, 357 const ClipPaintPropertyNode*,
342 const ClipPaintPropertyNode*); 358 const ClipPaintPropertyNode*);
343 template const ScrollPaintPropertyNode* GeometryMapper::lowestCommonAncestor( 359 template const ScrollPaintPropertyNode* GeometryMapper::lowestCommonAncestor(
344 const ScrollPaintPropertyNode*, 360 const ScrollPaintPropertyNode*,
345 const ScrollPaintPropertyNode*); 361 const ScrollPaintPropertyNode*);
346 362
347 } // namespace blink 363 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698