|
|
DescriptionAllow user-specified clip region for SkiaBitLocker
This allows us to allocate a smaller region when painting native
controls on Mac.
BUG=247716
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=291226
Patch Set 1 #Patch Set 2 : Clean up comments #Patch Set 3 : Temp #Patch Set 4 : Fixed #Patch Set 5 : Minimize diffs #Patch Set 6 : Fix variable names #Patch Set 7 : Add dummy context #Patch Set 8 : Incorporate review feedback #Messages
Total messages: 24 (0 generated)
I'll be converting the WebKit callers to this as I determine which have accurate bounds computations.
Is it equivalent to have the callers just set a cliprect before installing the locker? i.e. canvas->save(); canvas->clipRect(dirtyRect); SkiaBitLocker locker(canvas); .... canvas->restore();
On 2014/08/20 00:42:41, reed1 wrote: > Is it equivalent to have the callers just set a cliprect before installing the > locker? > > i.e. > > canvas->save(); > canvas->clipRect(dirtyRect); > SkiaBitLocker locker(canvas); > .... > canvas->restore(); I wanted to avoid the extra work done in SkiaBitLocker::computeDirtyRect -- would it be better to just have that has a flag passed to SkiaBitLocker & do the explicit clip at the call site?
Ah, I didn't notice that you skip the searching code if there is a rect. I think that's fine, and it may be fine to keep the API as you've written it. I was partly asking just to see if it was logically equivalent, since the locker already limits its buffer to the bounds of the current clip.
I wonder if it would be simpler (a smaller change) if you just apply the dirtyRect as a clip in the constructor. That way you wouldn't need to track it as a separate value (and it would be correctly transformed by any matrix in the canvas). SkiaBitLocker(SkCanvas* canvas, const SkRect* bounds) { if (bounds) { canvas->save(); canvas->clipRect(*bounds); fNeedToComputeTightBounds = false; } else { fNeedToComputeTightBounds = true; } }
On 2014/08/20 01:14:36, reed1 wrote: > I wonder if it would be simpler (a smaller change) if you just apply the > dirtyRect as a clip in the constructor. That way you wouldn't need to track it > as a separate value (and it would be correctly transformed by any matrix in the > canvas). > > SkiaBitLocker(SkCanvas* canvas, const SkRect* bounds) { > if (bounds) { > canvas->save(); > canvas->clipRect(*bounds); > fNeedToComputeTightBounds = false; > } else { > fNeedToComputeTightBounds = true; > } > } I gave that a try, but it looks like clipRect replaces rather than intersects the existing clip rect (which results in lots of error spew to stdout) -- I think that this one is probably the way to go.
On 2014/08/20 02:24:49, ccameron1 wrote: > On 2014/08/20 01:14:36, reed1 wrote: > > I wonder if it would be simpler (a smaller change) if you just apply the > > dirtyRect as a clip in the constructor. That way you wouldn't need to track it > > as a separate value (and it would be correctly transformed by any matrix in > the > > canvas). > > > > SkiaBitLocker(SkCanvas* canvas, const SkRect* bounds) { > > if (bounds) { > > canvas->save(); > > canvas->clipRect(*bounds); > > fNeedToComputeTightBounds = false; > > } else { > > fNeedToComputeTightBounds = true; > > } > > } > > I gave that a try, but it looks like clipRect replaces rather than intersects > the existing clip rect (which results in lots of error spew to stdout) -- I > think that this one is probably the way to go. clipRect with just one argument (the rect) definitely intersects, so I'm not sure what happened in your test.
On 2014/08/20 13:26:12, reed1 wrote: > On 2014/08/20 02:24:49, ccameron1 wrote: > > On 2014/08/20 01:14:36, reed1 wrote: > > > I wonder if it would be simpler (a smaller change) if you just apply the > > > dirtyRect as a clip in the constructor. That way you wouldn't need to track > it > > > as a separate value (and it would be correctly transformed by any matrix in > > the > > > canvas). > > > > > > SkiaBitLocker(SkCanvas* canvas, const SkRect* bounds) { > > > if (bounds) { > > > canvas->save(); > > > canvas->clipRect(*bounds); > > > fNeedToComputeTightBounds = false; > > > } else { > > > fNeedToComputeTightBounds = true; > > > } > > > } > > > > I gave that a try, but it looks like clipRect replaces rather than intersects > > the existing clip rect (which results in lots of error spew to stdout) -- I > > think that this one is probably the way to go. > > clipRect with just one argument (the rect) definitely intersects, so I'm not > sure what happened in your test. Remember, anything passed to clipRect is automatically transformed by the canvas' CTM into device coordinates. Make sure the rect you pass is in the same coordinates as any drawing primitives.
Ah, got it -- updated. It turns out that if the clip rect ends up being empty, then we end up getting errors to the effect of: Aug 20 12:50:41 ccameron-macbookpro.roam.corp.google.com Chromium Helper[1163] <Error>: CGContextGetCTM: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update. This is a result of returning NULL from SkiaBitLocker::cgContext(). Now that my math is fixed, that doesn't happen, but maybe I should update SkiaBitLocker to always return a cgContext -- it appears that its callers assume that will not return NULL. Want me to do that in this patch, or a separate one?
I like the api and the impl. lgtm Regarding the NULL return -- I kind of look at it as a feature, since it means the caller can know not to spend anytime drawing into that CGContext. Thus my first thought would be to fix the callers. However, if you decide to always return one, that will also work.
Thanks! That sounds good -- I have some concern that some callers will have a hard time proving to themselves that they won't draw anything (when Skia is able to know better, and not create a context). It should be easy to see if we hit this when I put in the Blink-side changes.
The CQ bit was checked by [email protected]
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/[email protected]/462423006/100001
The CQ bit was unchecked by [email protected]
I ran this through some tests with the Blink-side, and indeed there are places where it's tricky to make sure that the clip region is non-empty, and some go ahead and draw into regions that don't intersect the clip region. I added the "bitmap-backed context can be a dummy context" support, to make these just no-ops instead of errors.
On 2014/08/20 22:50:43, ccameron1 wrote: > I ran this through some tests with the Blink-side, and indeed there are places > where it's tricky to make sure that the clip region is non-empty, and some go > ahead and draw into regions that don't intersect the clip region. > > I added the "bitmap-backed context can be a dummy context" support, to make > these just no-ops instead of errors. Hmmm, not sure we are communicating perfectly yet :) after any clip-call on canvas, you can say: if (canvas->isClipEmpty()) { // no need to draw *anything*, since we will not draw any pixels } I am assuming this might be useful info to tell the client of the locker, so they can not execute any of their drawing calls. Is that what you thought I was saying?
On 2014/08/20 23:04:09, reed1 wrote: > On 2014/08/20 22:50:43, ccameron1 wrote: > > I ran this through some tests with the Blink-side, and indeed there are places > > where it's tricky to make sure that the clip region is non-empty, and some go > > ahead and draw into regions that don't intersect the clip region. > > > > I added the "bitmap-backed context can be a dummy context" support, to make > > these just no-ops instead of errors. > > Hmmm, not sure we are communicating perfectly yet :) > > after any clip-call on canvas, you can say: > > if (canvas->isClipEmpty()) { > // no need to draw *anything*, since we will not draw any pixels > } > > I am assuming this might be useful info to tell the client of the locker, so > they can not execute any of their drawing calls. Is that what you thought I was > saying? I think what you're suggesting -- skipping the draw calls when we're drawing to an empty clip region -- is the right way to do things. It's probably worth mentioning that I'm very afraid to change the callsites of this -- the bulk of the users of this are the things that create a LocalCurrentGrahpicsContext in third_party/WebKit/Source/core/rendering/RenderThemeChromiumMac.mm and third_party/WebKit/Source/platform/mac/ThemeMac.mm, which are doing their draw calls through overly-stateful Cocoa APIs. I'd prefer to check in a very minimal change (just the clip rects) to the Blink side, and leave the accompanying logic unchanged, to minimize the risk of regressions.
On 2014/08/20 23:35:49, ccameron1 wrote: > On 2014/08/20 23:04:09, reed1 wrote: > > On 2014/08/20 22:50:43, ccameron1 wrote: > > > I ran this through some tests with the Blink-side, and indeed there are > places > > > where it's tricky to make sure that the clip region is non-empty, and some > go > > > ahead and draw into regions that don't intersect the clip region. > > > > > > I added the "bitmap-backed context can be a dummy context" support, to make > > > these just no-ops instead of errors. > > > > Hmmm, not sure we are communicating perfectly yet :) > > > > after any clip-call on canvas, you can say: > > > > if (canvas->isClipEmpty()) { > > // no need to draw *anything*, since we will not draw any pixels > > } > > > > I am assuming this might be useful info to tell the client of the locker, so > > they can not execute any of their drawing calls. Is that what you thought I > was > > saying? > > I think what you're suggesting -- skipping the draw calls when we're drawing to > an empty clip region -- is the right way to do things. > > It's probably worth mentioning that I'm very afraid to change the callsites of > this -- the bulk of the users of this are the things that create a > LocalCurrentGrahpicsContext in > third_party/WebKit/Source/core/rendering/RenderThemeChromiumMac.mm and > third_party/WebKit/Source/platform/mac/ThemeMac.mm, which are doing their draw > calls through overly-stateful Cocoa APIs. > > I'd prefer to check in a very minimal change (just the clip rects) to the Blink > side, and leave the accompanying logic unchanged, to minimize the risk of > regressions. Gotcha. In that case, lets at least leave some getter() on the locker that can report if its clip is now empty, so we can (later) chip-away at callers who might take advantage of this knowledge.
Good idea -- updated the patch.
lgtm
Thanks!
The CQ bit was checked by [email protected]
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/[email protected]/462423006/130001
Message was sent while issue was closed.
Committed patchset #8 (130001) as 291226 |