Changeset 62238 in webkit
- Timestamp:
- Jul 1, 2010 1:33:13 AM (14 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r62235 r62238 1 2010-07-01 Nikolas Zimmermann <nzimmermann@rim.com> 2 3 Reviewed by Eric Seidel & Dirk Schulze. 4 5 Performance regression for setting content of <text> in SVG 6 https://bugs.webkit.org/show_bug.cgi?id=36564 7 8 Dramatically reducing the number of repaintRectInLocalCoordinates() calls needed while painting. 9 Do not pass the repaintRect to prepareToRenderSVGContent, only calculate it if opacity < 1 or -webkit-svg-shadow is set. 10 Most noticeable is that RenderSVGRoot had to visit all children, before actually painting, just to calculate the repaint rect. 11 And as RenderSVGRoot never carries shadow or opacity it was completly useless. 12 13 RenderSVGContainer also called repaintRectInLocalCoordinates, but the result is only needed when painting outlines, which is a rare case. 14 These modifications fix the performance regression and the number of repaintRectInLocalCoordinate calls for the complex example in 15 the bug report with 500 runs shrinks from 1.7 million calls to less than 105.000. 16 17 50 runs without the patch: ~ 520.8ms 18 50 runs with the patch : ~ 501.8ms 19 20 The test calls setTimeout(0) 50 times, that already accounts for the 500ms. So setting the content of a <text> 21 element withs clippers applied, is very cheap now. 22 23 Also remove the need to pass in a filter argument to prepareToRenderSVGContent/finishRenderSVGContent, it can easily be grabbed 24 of the cache - just like all other resources are handled, simplifying the code. 25 26 * rendering/RenderPath.cpp: 27 (WebCore::RenderPath::paint): 28 * rendering/RenderSVGContainer.cpp: 29 (WebCore::RenderSVGContainer::paint): 30 (WebCore::RenderSVGContainer::repaintRectInLocalCoordinates): 31 * rendering/RenderSVGImage.cpp: 32 (WebCore::RenderSVGImage::paint): 33 * rendering/RenderSVGRoot.cpp: 34 (WebCore::RenderSVGRoot::paint): 35 * rendering/SVGInlineFlowBox.cpp: 36 (WebCore::SVGInlineFlowBox::paint): 37 * rendering/SVGRenderSupport.cpp: 38 (WebCore::SVGRenderSupport::prepareToRenderSVGContent): 39 (WebCore::SVGRenderSupport::finishRenderSVGContent): 40 * rendering/SVGRenderSupport.h: 41 * rendering/SVGRootInlineBox.cpp: 42 (WebCore::SVGRootInlineBox::paint): 43 1 44 2010-07-01 Eric Seidel <eric@webkit.org> 2 45 -
trunk/WebCore/rendering/RenderPath.cpp
r62118 r62238 35 35 #include "PointerEventsHitRules.h" 36 36 #include "RenderSVGContainer.h" 37 #include "RenderSVGResourceFilter.h"38 37 #include "RenderSVGResourceMarker.h" 39 38 #include "StrokeStyleApplier.h" … … 174 173 childPaintInfo.context->save(); 175 174 childPaintInfo.applyTransform(m_localTransform); 176 RenderSVGResourceFilter* filter = 0;177 175 178 176 if (childPaintInfo.phase == PaintPhaseForeground) { 179 177 PaintInfo savedInfo(childPaintInfo); 180 178 181 if (SVGRenderSupport::prepareToRenderSVGContent(this, childPaintInfo , boundingBox, filter)) {179 if (SVGRenderSupport::prepareToRenderSVGContent(this, childPaintInfo)) { 182 180 const SVGRenderStyle* svgStyle = style()->svgStyle(); 183 181 if (svgStyle->shapeRendering() == SR_CRISPEDGES) … … 190 188 } 191 189 192 SVGRenderSupport::finishRenderSVGContent(this, childPaintInfo, filter,savedInfo.context);190 SVGRenderSupport::finishRenderSVGContent(this, childPaintInfo, savedInfo.context); 193 191 } 194 192 -
trunk/WebCore/rendering/RenderSVGContainer.cpp
r62118 r62238 88 88 89 89 PaintInfo childPaintInfo(paintInfo); 90 91 90 childPaintInfo.context->save(); 92 91 … … 96 95 childPaintInfo.applyTransform(localToParentTransform()); 97 96 98 RenderSVGResourceFilter* filter = 0;99 FloatRect boundingBox = repaintRectInLocalCoordinates();100 101 97 bool continueRendering = true; 102 98 if (childPaintInfo.phase == PaintPhaseForeground) 103 continueRendering = SVGRenderSupport::prepareToRenderSVGContent(this, childPaintInfo , boundingBox, filter);99 continueRendering = SVGRenderSupport::prepareToRenderSVGContent(this, childPaintInfo); 104 100 105 101 if (continueRendering) { … … 110 106 111 107 if (paintInfo.phase == PaintPhaseForeground) 112 SVGRenderSupport::finishRenderSVGContent(this, childPaintInfo, filter,paintInfo.context);108 SVGRenderSupport::finishRenderSVGContent(this, childPaintInfo, paintInfo.context); 113 109 114 110 childPaintInfo.context->restore(); … … 119 115 // FIXME: This means our focus ring won't share our rotation like it should. 120 116 // We should instead disable our clip during PaintPhaseOutline 121 IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates()));122 if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE)117 if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE) { 118 IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates())); 123 119 paintOutline(paintInfo.context, paintRectInParent.x(), paintRectInParent.y(), paintRectInParent.width(), paintRectInParent.height()); 120 } 124 121 } 125 122 … … 142 139 } 143 140 144 // RenderSVGContainer is used for <g> elements which do not themselves have a145 // width or height, so we union all of our child rects as our repaint rect.146 141 FloatRect RenderSVGContainer::repaintRectInLocalCoordinates() const 147 142 { 148 143 FloatRect repaintRect = strokeBoundingBox(); 149 144 SVGRenderSupport::intersectRepaintRectWithResources(this, repaintRect); 150 151 145 return repaintRect; 152 146 } -
trunk/WebCore/rendering/RenderSVGImage.cpp
r62118 r62238 84 84 85 85 if (paintInfo.phase == PaintPhaseForeground) { 86 RenderSVGResourceFilter* filter = 0;87 88 86 PaintInfo savedInfo(paintInfo); 89 87 90 if (SVGRenderSupport::prepareToRenderSVGContent(this, paintInfo , m_localBounds, filter)) {88 if (SVGRenderSupport::prepareToRenderSVGContent(this, paintInfo)) { 91 89 FloatRect destRect = m_localBounds; 92 90 FloatRect srcRect(0, 0, image()->width(), image()->height()); … … 98 96 paintInfo.context->drawImage(image(), DeviceColorSpace, destRect, srcRect); 99 97 } 100 SVGRenderSupport::finishRenderSVGContent(this, paintInfo, filter,savedInfo.context);98 SVGRenderSupport::finishRenderSVGContent(this, paintInfo, savedInfo.context); 101 99 } 102 100 -
trunk/WebCore/rendering/RenderSVGRoot.cpp
r62142 r62238 172 172 childPaintInfo.applyTransform(localToRepaintContainerTransform(parentOriginInContainer)); 173 173 174 RenderSVGResourceFilter* filter = 0;175 FloatRect boundingBox = repaintRectInLocalCoordinates();176 177 174 bool continueRendering = true; 178 175 if (childPaintInfo.phase == PaintPhaseForeground) 179 continueRendering = SVGRenderSupport::prepareToRenderSVGContent(this, childPaintInfo , boundingBox, filter);176 continueRendering = SVGRenderSupport::prepareToRenderSVGContent(this, childPaintInfo); 180 177 181 178 if (continueRendering) … … 183 180 184 181 if (childPaintInfo.phase == PaintPhaseForeground) 185 SVGRenderSupport::finishRenderSVGContent(this, childPaintInfo, filter,paintInfo.context);182 SVGRenderSupport::finishRenderSVGContent(this, childPaintInfo, paintInfo.context); 186 183 187 184 childPaintInfo.context->restore(); -
trunk/WebCore/rendering/SVGInlineFlowBox.cpp
r62118 r62238 42 42 childPaintInfo.context->save(); 43 43 44 RenderSVGResourceFilter* filter = 0; 45 FloatRect repaintRect = boxRenderer->repaintRectInLocalCoordinates(); 46 47 if (SVGRenderSupport::prepareToRenderSVGContent(boxRenderer, childPaintInfo, repaintRect, filter)) { 44 if (SVGRenderSupport::prepareToRenderSVGContent(boxRenderer, childPaintInfo)) { 48 45 for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) 49 46 child->paint(childPaintInfo, 0, 0); 50 47 } 51 48 52 SVGRenderSupport::finishRenderSVGContent(boxRenderer, childPaintInfo, filter,paintInfo.context);49 SVGRenderSupport::finishRenderSVGContent(boxRenderer, childPaintInfo, paintInfo.context); 53 50 childPaintInfo.context->restore(); 54 51 } -
trunk/WebCore/rendering/SVGRenderSupport.cpp
r62118 r62238 75 75 } 76 76 77 bool SVGRenderSupport::prepareToRenderSVGContent(RenderObject* object, PaintInfo& paintInfo , const FloatRect& repaintRect, RenderSVGResourceFilter*& filter)77 bool SVGRenderSupport::prepareToRenderSVGContent(RenderObject* object, PaintInfo& paintInfo) 78 78 { 79 79 #if !ENABLE(FILTERS) … … 92 92 ASSERT(svgStyle); 93 93 94 FloatRect repaintRect; 95 94 96 // Setup transparency layers before setting up SVG resources! 95 float opacity = style->opacity(); 96 if (opacity < 1.0f) { 97 float opacity = style->opacity(); 98 if (opacity < 1) { 99 repaintRect = object->repaintRectInLocalCoordinates(); 97 100 paintInfo.context->clip(repaintRect); 98 101 paintInfo.context->beginTransparencyLayer(opacity); … … 100 103 101 104 if (const ShadowData* shadow = svgStyle->shadow()) { 105 // Eventually compute repaint rect, if not done so far. 106 if (opacity >= 1) 107 repaintRect = object->repaintRectInLocalCoordinates(); 108 102 109 paintInfo.context->clip(repaintRect); 103 110 paintInfo.context->setShadow(IntSize(shadow->x(), shadow->y()), shadow->blur(), shadow->color(), style->colorSpace()); 104 paintInfo.context->beginTransparencyLayer(1 .0f);111 paintInfo.context->beginTransparencyLayer(1); 105 112 } 106 113 … … 113 120 return false; 114 121 } else 115 svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement);122 document->accessSVGExtensions()->addPendingResource(maskerId, styledElement); 116 123 } 117 124 … … 121 128 clipper->applyResource(object, style, paintInfo.context, ApplyToDefaultMode); 122 129 else 123 svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement);130 document->accessSVGExtensions()->addPendingResource(clipperId, styledElement); 124 131 } 125 132 … … 127 134 if (svgStyle->hasFilter()) { 128 135 AtomicString filterId(svgStyle->filterResource()); 129 filter = getRenderSVGResourceById<RenderSVGResourceFilter>(document, filterId); 130 if (filter) { 136 if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(document, filterId)) { 131 137 if (!filter->applyResource(object, style, paintInfo.context, ApplyToDefaultMode)) 132 138 return false; 133 139 } else 134 svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement);140 document->accessSVGExtensions()->addPendingResource(filterId, styledElement); 135 141 } 136 142 #endif … … 139 145 } 140 146 141 void SVGRenderSupport::finishRenderSVGContent(RenderObject* object, PaintInfo& paintInfo, RenderSVGResourceFilter*& filter,GraphicsContext* savedContext)147 void SVGRenderSupport::finishRenderSVGContent(RenderObject* object, PaintInfo& paintInfo, GraphicsContext* savedContext) 142 148 { 143 149 #if !ENABLE(FILTERS) … … 151 157 ASSERT(style); 152 158 159 const SVGRenderStyle* svgStyle = style->svgStyle(); 160 ASSERT(svgStyle); 161 153 162 #if ENABLE(FILTERS) 154 if (filter) { 155 filter->postApplyResource(object, paintInfo.context, ApplyToDefaultMode); 156 paintInfo.context = savedContext; 163 if (svgStyle->hasFilter()) { 164 AtomicString filterId(svgStyle->filterResource()); 165 if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(object->document(), filterId)) { 166 filter->postApplyResource(object, paintInfo.context, ApplyToDefaultMode); 167 paintInfo.context = savedContext; 168 } 157 169 } 158 170 #endif 159 171 160 172 float opacity = style->opacity(); 161 if (opacity < 1 .0f)173 if (opacity < 1) 162 174 paintInfo.context->endTransparencyLayer(); 163 175 164 176 // This needs to be done separately from opacity, because if both properties are set, 165 177 // then the transparency layers are nested. 166 if (s tyle->svgStyle()->shadow())178 if (svgStyle->shadow()) 167 179 paintInfo.context->endTransparencyLayer(); 168 180 } -
trunk/WebCore/rendering/SVGRenderSupport.h
r62118 r62238 38 38 class RenderObject; 39 39 class RenderStyle; 40 class RenderSVGResourceFilter;41 40 class TransformState; 42 41 … … 45 44 public: 46 45 // Used by all SVG renderers who apply clip/filter/etc. resources to the renderer content 47 static bool prepareToRenderSVGContent(RenderObject*, PaintInfo& , const FloatRect& boundingBox, RenderSVGResourceFilter*&);48 static void finishRenderSVGContent(RenderObject*, PaintInfo&, RenderSVGResourceFilter*&,GraphicsContext* savedContext);46 static bool prepareToRenderSVGContent(RenderObject*, PaintInfo&); 47 static void finishRenderSVGContent(RenderObject*, PaintInfo&, GraphicsContext* savedContext); 49 48 50 49 // Shares child layouting code between RenderSVGRoot/RenderSVG(Hidden)Container -
trunk/WebCore/rendering/SVGRootInlineBox.cpp
r62118 r62238 28 28 #include "GraphicsContext.h" 29 29 #include "RenderBlock.h" 30 #include "RenderSVGResourceFilter.h"31 30 #include "SVGInlineFlowBox.h" 32 31 #include "SVGInlineTextBox.h" … … 51 50 childPaintInfo.context->save(); 52 51 53 FloatRect repaintRect = boxRenderer->repaintRectInLocalCoordinates(); 54 55 RenderSVGResourceFilter* filter = 0; 56 if (SVGRenderSupport::prepareToRenderSVGContent(boxRenderer, childPaintInfo, repaintRect, filter)) { 52 if (SVGRenderSupport::prepareToRenderSVGContent(boxRenderer, childPaintInfo)) { 57 53 for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) 58 54 child->paint(childPaintInfo, 0, 0); 59 55 } 60 56 61 SVGRenderSupport::finishRenderSVGContent(boxRenderer, childPaintInfo, filter,paintInfo.context);57 SVGRenderSupport::finishRenderSVGContent(boxRenderer, childPaintInfo, paintInfo.context); 62 58 childPaintInfo.context->restore(); 63 59 }
Note: See TracChangeset
for help on using the changeset viewer.