Closed Bug 676250 Opened 13 years ago Closed 11 years ago

Make OpenGL painting bypass the Cocoa setNeedsDisplay/drawRect machinery

Categories

(Core :: Widget: Cocoa, defect)

All
macOS
defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla22

People

(Reporter: mstange, Assigned: mstange)

References

Details

Attachments

(1 file, 4 obsolete files)

Attached patch wip (obsolete) — Splinter Review
With OpenGL painting, we're doing some unnecessary work during invalidation: We store the invalid region on the NSWindow using -[NSView setNeedsDisplayInRect:]. That's not necessary since we'll be recompositing the whole window anyway, and Gecko knows which regions it needs to repaint inside the retained layers because each layer stores its own dirty region.

One case where avoiding the unnecessary region unioning is bug 554004 comment 2. 

Another reason why we don't really want to use setNeedsDisplay  for GL painting is given in bug 676248.

Instead of using setNeedsDisplayInRect and waiting for an invocation of drawRect, we can just use the Objective C equivalent of posting an nsRunnable for drawing. The wip patch should be mostly complete, except it doesn't post NS_WILL_PAINT events yet.
Attached patch v1 (obsolete) — Splinter Review
This seems to work well. It's needed for bug 675410.
Assignee: nobody → mstange
Attachment #550377 - Attachment is obsolete: true
Status: NEW → ASSIGNED
Attachment #675318 - Flags: review?(joshmoz)
(In reply to Markus Stange from comment #0)
> except it
> doesn't post NS_WILL_PAINT events yet.

I'm pretty sure that NS_WILL_PAINT events aren't necessary because all Gecko-originating invalidations come from the refresh driver anyway which has already flushed everything.
Comment on attachment 675318 [details] [diff] [review]
v1

Review of attachment 675318 [details] [diff] [review]:
-----------------------------------------------------------------

Benoit Girard would be a better reviewer.
Attachment #675318 - Flags: review?(joshmoz) → review?(bgirard)
Comment on attachment 675318 [details] [diff] [review]
v1

Review of attachment 675318 [details] [diff] [review]:
-----------------------------------------------------------------

This looks good to me. I'm sure you've checked this but just to be safe: Make sure it is well tested for window resize (with and without personas see bug 797431), and losing/regaining window focus (bug 770056).

::: widget/cocoa/nsChildView.mm
@@ +2186,5 @@
> +    return;
> +
> +  if ([self isUsingOpenGL]) {
> +    // When using OpenGL we don't want to go through the usual Cocoa painting
> +    // machinery for performance reasons. We just use a timer instead.

s/timer/refresh driver.

Instead of 'performance reasons' we should elaborate. If I understand it correctly it prevents us from repainting the window surface. We should note that here.
Attachment #675318 - Flags: review?(bgirard) → review+
This patch is a few months old and has bit-rotted. I'll see if I can bring it up to date.
Attached patch v1.1 (obsolete) — Splinter Review
De-bitrotted.
Attachment #675318 - Attachment is obsolete: true
Attached patch Patch v1.2 (r+'d by BenWa) (obsolete) — Splinter Review
Addressed Benoit's review comments.
Attachment #720124 - Attachment is obsolete: true
Actually, sorry, I should have answered the comments because I don't think they're valid.

(In reply to Benoit Girard (:BenWa) from comment #4)
> ::: widget/cocoa/nsChildView.mm
> @@ +2186,5 @@
> > +    return;
> > +
> > +  if ([self isUsingOpenGL]) {
> > +    // When using OpenGL we don't want to go through the usual Cocoa painting
> > +    // machinery for performance reasons. We just use a timer instead.
> 
> s/timer/refresh driver.

The timer I'm referring to here is the [self performSelector:@selector(drawUsingOpenGLCallback) withObject:nil afterDelay:0] Cocoa timer. The refresh driver would be used either way. So I think we should keep "timer".

> Instead of 'performance reasons' we should elaborate. If I understand it
> correctly it prevents us from repainting the window surface. We should note
> that here.

Well, the real reason is more complicated than that and wouldn't fit in a comment. Specifically, it prevents us from accessing the normal window buffer surface unnecessarily, so we waste less time synchronizing the two surfaces. (These synchronizations show up in a profiler as CGSDeviceLock / _CGSLockWindow / _CGSSynchronizeWindowBackingStore.)
It also means that Cocoa doesn't have any potentially expensive invalid rect management for us.
I was originally going to land this patch with Benoit's changes, but I'll hold off until the above is resolved.
Ohh I see now. You're right refresh driver isn't the right word. Timer isn't quite the right word either, we're just en-queue an event to run refresh outside of setNeedsDisplayInRect. The explanation you give is great and I don't see why doesn't fit in a comment. Perhaps something along those lines:

Draw the frame outside of setNeedsDisplayInRect to prevent us from needing to access the normal window buffer surface unnecessarily, so we waste less time synchronizing the two surfaces. (These synchronizations show up in a profiler as CGSDeviceLock / _CGSLockWindow / _CGSSynchronizeWindowBackingStore.)
It also means that Cocoa doesn't have any potentially expensive invalid rect management for us.

The comment is big but the code on it's own isn't clear without it.
Good, let's use that comment. How about "delayed perform" instead of "timer"? I'm having a hard time coming up with a good word. But we should be consistent and replace "timer" in this comment, too:

+    // We usually don't get here for Gecko-initiated repaints. Those call
+    // drawUsingOpenGL from a timer and don't go through drawRect.
Alright, I used Benoit's comment, and replaced the "timer" comment in the other block with this:

// We usually don't get here for Gecko-initiated repaints. Instead, those  
// eventually call drawUsingOpenGL, and don't go through drawRect.         
// Paints that come through here are triggered by something that Cocoa     
// controls, for example by window resizing or window focus changes.       

If that comment is incorrect / needs updating, let me know.

I've pushed to inbound as https://hg.mozilla.org/integration/mozilla-inbound/rev/c95439870e05
Attachment #720858 - Attachment is obsolete: true
https://hg.mozilla.org/mozilla-central/rev/c95439870e05
Status: ASSIGNED → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla22
I approve of the comment. Thanks!
Depends on: 849157
No longer depends on: 849157
Depends on: 849157
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: