Closed
Bug 1123019
Opened 10 years ago
Closed 10 years ago
Long dotted / dashed borders paint extremely slowly on Mac, even if only a screenful of them is visible
Categories
(Core :: Graphics, defect)
Tracking
()
RESOLVED
FIXED
mozilla39
People
(Reporter: mstange, Assigned: mstange)
References
Details
(Keywords: regression, Whiteboard: gfx-noted)
Attachments
(4 files, 5 obsolete files)
334 bytes,
text/html
|
Details | |
10.48 KB,
patch
|
jrmuizel
:
review+
|
Details | Diff | Splinter Review |
7.86 KB,
patch
|
Details | Diff | Splinter Review | |
2.97 KB,
patch
|
jrmuizel
:
review+
|
Details | Diff | Splinter Review |
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:38.0) Gecko/20100101 Firefox/38.0
I noticed this on a long reddit thread. It looks like CoreGraphics iterates over all line segments of the border and is very bad at ignoring those outside the visible bounds.
I think this is a regression. At least I don't remember it being this bad before. Tiling will have made this worse, but it might also be a regression in CG from 10.9 to 10.10.
Almost all the time is spent in this stack:
> nsCSSBorderRenderer::DrawDashedSide(mozilla::Side)
> mozilla::gfx::DrawTargetTiled::StrokeLine
> mozilla::gfx::DrawTargetCG::StrokeLine
> ripc_DrawPathCGContextDrawPath
> CGPathApplyRIPRenderPath
> CG::Path::Sequence::apply
> CG::Path::Subpath::apply
> CG::Chunk::apply
> path_iterator_add_line_to_point
Assignee | ||
Updated•10 years ago
|
Keywords: regressionwindow-wanted
Assignee | ||
Comment 1•10 years ago
|
||
Builds before tiling are fast, builds after tiling are slow, blaming bug 982338.
Blocks: osx-tiling
Assignee | ||
Comment 2•10 years ago
|
||
Updated•10 years ago
|
Whiteboard: gfx-noted
Comment 3•10 years ago
|
||
DrawTargetTiled attempts to avoid sending draw calls to tiles that won't be affected, but it doesn't yet do this for StrokeLine (or StrokeRect).
Implementing that should be easy and would fix the regression.
Comment 4•10 years ago
|
||
Markus, is this something you can take? Based on the time honoured "you find it, you fix it" approach :)
Assignee | ||
Comment 5•10 years ago
|
||
Sure.
(In reply to Matt Woodrow (:mattwoodrow) from comment #3)
> DrawTargetTiled attempts to avoid sending draw calls to tiles that won't be
> affected, but it doesn't yet do this for StrokeLine (or StrokeRect).
>
> Implementing that should be easy and would fix the regression.
It feels like the slowdown factor here is higher than the number of tiles, though. But I'll try that anyway.
Assignee: nobody → mstange
Status: NEW → ASSIGNED
Assignee | ||
Comment 6•10 years ago
|
||
This didn't make it any faster.
Attachment #8563147 -
Flags: review?(jmuizelaar)
Assignee | ||
Comment 7•10 years ago
|
||
This made all the difference. But it's a good chunk of code, probably way over-engineered, and needs lots of comments. Before I sit down and add those comments, do you think this is something we should do or do you have a different idea?
Attachment #8563151 -
Flags: review?(jmuizelaar)
Comment 8•10 years ago
|
||
(In reply to Markus Stange [:mstange] from comment #7)
> Created attachment 8563151 [details] [diff] [review]
> part 2: shorten lines
>
> This made all the difference. But it's a good chunk of code, probably way
> over-engineered, and needs lots of comments. Before I sit down and add those
> comments, do you think this is something we should do or do you have a
> different idea?
Can you summarize what it does?
Assignee | ||
Comment 9•10 years ago
|
||
It wraps a PathBuilder, and replaces LineTo calls with MoveTo, LineTo, MoveTo calls when a encountering a line that isn't completely inside the clip rect, so that only the visible part of the line (+ a little error margin) gets drawn, all the time ensuring that the dash pattern looks the same as if the line were drawn unshortened.
Assignee | ||
Comment 10•10 years ago
|
||
This helps because the perf problem is that CG spends ages iterating over dashes that are outside the clip.
Assignee | ||
Comment 11•10 years ago
|
||
Fixes <cmath> build failure and also implements the culling for StrokeLine.
Attachment #8563147 -
Attachment is obsolete: true
Attachment #8563147 -
Flags: review?(jmuizelaar)
Attachment #8566843 -
Flags: review?(jmuizelaar)
Assignee | ||
Comment 12•10 years ago
|
||
Attachment #8566844 -
Flags: review?(jmuizelaar)
Assignee | ||
Comment 13•10 years ago
|
||
The previous approach wasn't working because you can't close a path that has been chopped up, and you need it to work for the top left corner of stroked rectangles.
Attachment #8563151 -
Attachment is obsolete: true
Attachment #8563151 -
Flags: review?(jmuizelaar)
Attachment #8566845 -
Flags: review?(jmuizelaar)
Assignee | ||
Comment 14•10 years ago
|
||
Assignee | ||
Comment 15•10 years ago
|
||
I hope I've really fixed the build failure this time.
https://treeherder.mozilla.org/#/jobs?repo=try&revision=9eae58a04314
Attachment #8566843 -
Attachment is obsolete: true
Attachment #8566843 -
Flags: review?(jmuizelaar)
Attachment #8567196 -
Flags: review?(jmuizelaar)
Comment 16•10 years ago
|
||
Comment on attachment 8566844 [details] [diff] [review]
part 2: factor out stroking in DrawTargetCG
Review of attachment 8566844 [details] [diff] [review]:
-----------------------------------------------------------------
Lets not. This adds some overhead that we're not particularly in need of.
Attachment #8566844 -
Flags: review?(jmuizelaar) → review-
Comment 17•10 years ago
|
||
Comment on attachment 8566845 [details] [diff] [review]
part 3: shrink clipped stroked rectangles and lines in DrawTargetCG
Review of attachment 8566845 [details] [diff] [review]:
-----------------------------------------------------------------
::: gfx/2d/DrawTargetCG.cpp
@@ +998,5 @@
> + for (size_t i = 0; i < aStrokeOptions.mDashLength; i++) {
> + length += aStrokeOptions.mDashPattern[i];
> + }
> + if (aStrokeOptions.mDashLength == 1) {
> + // 1-element dash arrays are interpreted as a symmetric 2-element dash array.
The should be all odd dash arrays. i.e.
if (aStrokeOptions.mDashLength & 1)
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray
@@ +1053,5 @@
> +}
> +
> +// Liang-Barsky
> +// Sets aStart and aEnd to floats between 0 and the line length, or returns
> +// false if the line is completely outside the rect.
You should add a note as to why you chose Liang-Barsky over other options.
Does this include the improvements suggested here?
"Some Improvements to a Parametric Line Clipping Algorithm"
Attachment #8566845 -
Flags: review?(jmuizelaar) → review+
Updated•10 years ago
|
Attachment #8567196 -
Flags: review?(jmuizelaar) → review+
Assignee | ||
Updated•10 years ago
|
Attachment #8566844 -
Attachment is obsolete: true
Assignee | ||
Comment 18•10 years ago
|
||
(In reply to Jeff Muizelaar [:jrmuizel] from comment #17)
> Comment on attachment 8566845 [details] [diff] [review]
> part 3: shrink clipped stroked rectangles and lines in DrawTargetCG
>
> Review of attachment 8566845 [details] [diff] [review]:
> -----------------------------------------------------------------
>
> ::: gfx/2d/DrawTargetCG.cpp
> @@ +998,5 @@
> > + for (size_t i = 0; i < aStrokeOptions.mDashLength; i++) {
> > + length += aStrokeOptions.mDashPattern[i];
> > + }
> > + if (aStrokeOptions.mDashLength == 1) {
> > + // 1-element dash arrays are interpreted as a symmetric 2-element dash array.
>
> The should be all odd dash arrays. i.e.
> if (aStrokeOptions.mDashLength & 1)
>
> https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray
Thanks, that makes a lot more sense.
>
> @@ +1053,5 @@
> > +}
> > +
> > +// Liang-Barsky
> > +// Sets aStart and aEnd to floats between 0 and the line length, or returns
> > +// false if the line is completely outside the rect.
>
> You should add a note as to why you chose Liang-Barsky over other options.
Added a comment:
// This algorithm was chosen for its code brevity, with the hope that its
// performance is good enough.
> Does this include the improvements suggested here?
> "Some Improvements to a Parametric Line Clipping Algorithm"
Doesn't look like it. I actually think the original code I was looking at had the improvement, and I removed it because I wanted to have extra ifs tainting the std::min/max lines.
I have this check at the very end:
if (t0 > t1) {
return false;
}
The improvement suggested in that document is basically "move that check into the loop, so you can skip checking the remaining edges", if I understood correctly.
I have a hard time believing that at most three additional float divisions per line are going to hurt much.
Attachment #8566845 -
Attachment is obsolete: true
Comment 19•10 years ago
|
||
(In reply to Markus Stange [:mstange] from comment #18)
>
> > Does this include the improvements suggested here?
> > "Some Improvements to a Parametric Line Clipping Algorithm"
>
> Doesn't look like it. I actually think the original code I was looking at
> had the improvement, and I removed it because I wanted to have extra ifs
> tainting the std::min/max lines.
> I have this check at the very end:
> if (t0 > t1) {
> return false;
> }
> The improvement suggested in that document is basically "move that check
> into the loop, so you can skip checking the remaining edges", if I
> understood correctly.
> I have a hard time believing that at most three additional float divisions
> per line are going to hurt much.
Might as well add something about this to the comment too.
Assignee | ||
Comment 20•10 years ago
|
||
Actually, let me just move that if up into the loop body. That way, the number of lines of code stays the same, we get the behavior we want, and we don't need the comment.
Assignee | ||
Comment 21•10 years ago
|
||
Comment 22•10 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/4558317a4a9c
https://hg.mozilla.org/mozilla-central/rev/d472aa32cecf
Status: ASSIGNED → RESOLVED
Closed: 10 years ago
status-firefox39:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla39
Assignee | ||
Comment 23•10 years ago
|
||
Well that was just stupid.
Attachment #8574048 -
Flags: review?(jmuizelaar)
Updated•10 years ago
|
Attachment #8574048 -
Flags: review?(jmuizelaar) → review+
Assignee | ||
Comment 24•10 years ago
|
||
Comment 25•10 years ago
|
||
Comment 26•10 years ago
|
||
Release Note Request (optional, but appreciated)
[Why is this notable]: Fixes a regression from Firefox 35.
[Suggested wording]: Performance of displaying dashed lines on OS X is improved.
[Links (documentation, blog post, etc)]:
relnote-firefox:
--- → ?
Updated•10 years ago
|
You need to log in
before you can comment on or make changes to this bug.
Description
•