[OS X] [OpenGL] Drawing in the title bar

RESOLVED FIXED in mozilla2.0b7

Status

()

defect
RESOLVED FIXED
9 years ago
9 years ago

People

(Reporter: mstange, Assigned: mstange)

Tracking

Trunk
mozilla2.0b7
All
macOS
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(blocking2.0 betaN+)

Details

Attachments

(1 attachment, 2 obsolete attachments)

The title bar drawing functionality I added in bug 513158 doesn't work with the OpenGL layers backend.

Drawing in the title bar is required for an acceptable Personas appearance and for tabs-in-titlebar, should we decide to do it.

In the non-accelerated world, title bar drawing takes place inside a pattern callback function:
http://hg.mozilla.org/mozilla-central/annotate/6ccd956d1df9/widget/src/cocoa/nsCocoaWindow.mm#l2415
We get a CGContextRef for the pattern and call [ChildView drawRect:inContext:] with that context, and all drawing draws into the context. When we're finished, the window frame's internal drawing functions apply rounded-corner clipping and a highlight effect to what's been rendered and then draws the window title text and the window control buttons on top of everything.

In the OpenGL world, [ChildView drawRect:inContext:] couldn't care less about the CGContextRef it gets, so nothing gets rendered in the title bar.

I'm not sure how to fix this. I see two options:

Option one is to use the BasicLayerManager for title bar drawing, even if the rest of the window uses OpenGL drawing. That's probably very bad for performance.

Option two is to draw the whole window frame ourselves, including rounded corners, highlight effects and title bar buttons. It's possible but requires some work. For example, we have to change the window's XUL structure to include the window control buttons and the window title. (And I'm not sure how to get the rounded corner clipping, since border-radius is ignored on root elements because their background is pulled up into the canvas frame...)
This would affect add-on compatibility, so it would need to be done soon.

Any ideas?
(In reply to comment #0)
> Option two is to draw the whole window frame ourselves, including rounded
> corners, highlight effects and title bar buttons. It's possible but requires
> some work. For example, we have to change the window's XUL structure to include
> the window control buttons and the window title. (And I'm not sure how to get
> the rounded corner clipping, since border-radius is ignored on root elements
> because their background is pulled up into the canvas frame...)
> This would affect add-on compatibility, so it would need to be done soon.

Couldn't we just not draw the titlebar with XUL, have code in nsChildView.mm that draws the complete titlebar automatically?
(In reply to comment #1)
> have code in nsChildView.mm
> that draws the complete titlebar automatically?

I didn't have an idea how to do this but your suggestion in bug 595180 comment 3 about having the layer manager create buffers that nsChildView.mm can use sounds good.

Do you also have an idea about how to achieve rounded corners?
Blocks: ogl-osx-beta
blocking2.0: --- → ?
Duplicate of this bug: 594862
It would suck to release beta 6 with this, but it won't be the end of the world.
blocking2.0: ? → betaN+
The rounded corners are the top-left and top-right? How does that work? The whole window is actually RGBA, and after we've painted Cocoa erases some of the pixels?
(In reply to comment #5)
> The rounded corners are the top-left and top-right?

Yes.

> How does that work? The whole window is actually RGBA

Yes, apparently, but in a non-obvious way. For example, isOpaque still returns YES. Maybe they've just special-cased the corners and kept most opaqueness optimizations.
If you use a Persona with the GL backend, you'll see that most of the title bar turns black, except for 4x4 squares in the top left and right corners. So they only seem to clear the corners and keep the rest opaque.

> and after we've painted Cocoa erases some of the pixels?

I think it first clears the corner squares, then sets a rounded clip path and then lets us paint.
Posted patch make unified windows work (obsolete) — Splinter Review
This makes the unified toolbar work, but the persona still doesn't draw - we draw black instead.
(In reply to comment #0)
> Option one is to use the BasicLayerManager for title bar drawing, even if the
> rest of the window uses OpenGL drawing. That's probably very bad for
> performance.

Option one seems like the easier approach, and I don't really see why it would be bad for performance.
(In reply to comment #7)
> Created attachment 476157 [details] [diff] [review]
> make unified windows work

I have a different patch for that in bug 595933.(In reply to comment #8)

> (In reply to comment #0)
> > Option one is to use the BasicLayerManager for title bar drawing, even if the
> > rest of the window uses OpenGL drawing. That's probably very bad for
> > performance.
> 
> Option one seems like the easier approach, and I don't really see why it would
> be bad for performance.

Yeah, now that I think about it again I don't see why it would so bad. I'll try it out.
Depends on: 599241
No longer depends on: 599241
Depends on: 599241
The UnderlaySurface sample from Apple shows that it is possible for us to have NSView type things over top of opengl content.

The idea behind the sample is to use NSOpenGLCPSurfaceOrder to put the OpenGL surface below the window contents instead of defaulting to above.

It may be possible for us to have the OpenGL surface be the size of the entire window and then have the title bar exist overtop.
(In reply to comment #10)
> The UnderlaySurface sample from Apple

I've read about that sample but I couldn't find it. Did you find it?

I've played with NSOpenGLCPSurfaceOrder and it degraded performance pretty heavily. I don't know how the sample does it, but in order for the OpenGL stuff to be visible under my NSViews, I had to make them all transparent; even the window itself needed to be transparent. This comes with a high performance cost since it will cause transparent views to be cleared before every drawRect. The time spent in _CGSSynchronizeWindowBackingStore also increased a lot.
This patch (+ backing out bug 599241) makes nsChildView::GetLayerManager return a BasicLayerManager during titlebar drawing. However, our layer drawing system isn't prepared for dealing with changing layer managers; I get tons of assertions like:
###!!! ASSERTION: mFramesWithLayers out of sync: '!props.Get(DisplayItemDataProperty())', file /Users/markus/code/mozilla/layout/base/FrameLayerBuilder.cpp, line 566
(In reply to comment #11)
> (In reply to comment #10)
> > The UnderlaySurface sample from Apple
> 
> I've read about that sample but I couldn't find it. Did you find it?

I found it on my machine in "/Developer/Examples/OpenGL/Cocoa/UnderlaySurface"
 
> I've played with NSOpenGLCPSurfaceOrder and it degraded performance pretty
> heavily. I don't know how the sample does it, but in order for the OpenGL stuff
> to be visible under my NSViews, I had to make them all transparent; even the
> window itself needed to be transparent. This comes with a high performance cost
> since it will cause transparent views to be cleared before every drawRect. The
> time spent in _CGSSynchronizeWindowBackingStore also increased a lot.

Interesting...
(In reply to comment #13)
> (In reply to comment #11)
> > (In reply to comment #10)
> > > The UnderlaySurface sample from Apple
> > 
> > I've read about that sample but I couldn't find it. Did you find it?
> 
> I found it on my machine in "/Developer/Examples/OpenGL/Cocoa/UnderlaySurface"

Strange. That's on my other machine, but not on this one.

The example doesn't make the window transparent, but it clears the background at the beginning of drawRect:, which has the same effect.
No longer blocks: ogl-osx-beta
Assignee: nobody → mstange
Markus, you can probably get around those assertion issues by having nsDisplayList::PaintForFrame somehow not call WillBeginRetainedLayerTransaction when painting to the titlebar. E.g. we could add a flag to the layer manager itself or an extra output value to GetLayerManager which returns whether or not the layer manager should be treated as the "true" retaining layer manager.
Posted patch v1Splinter Review
Attachment #476157 - Attachment is obsolete: true
Attachment #479527 - Attachment is obsolete: true
Attachment #482021 - Flags: review?(roc)
Status: NEW → ASSIGNED
Comment on attachment 482021 [details] [diff] [review]
v1

+     * The layer manager may change during the lifetime of the widget, but
+     * aAllowRetaining will only ever return true for one layer manager per
+     * widget.

That's actually not true. We need to change the layer manager sometimes (e.g. when the Windows D3D driver reboots), and layout should be able to deal with that; the fact it currently doesn't deal very well is a bug. (But we don't want to rely on that here, since constantly switching retained layer managers would kill performance.) So please take this comment out.

+  nsBaseWidget::AutoUseBasicLayerManager _(mGeckoChild);
+  [self drawRect:aRect inContext:aContext];

Cute, but can we call the temporary setupLayerManager or something else meaningful?
Attachment #482021 - Flags: review?(roc) → review+
http://hg.mozilla.org/mozilla-central/rev/94a24110bbf0
Status: ASSIGNED → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla2.0b8
Target Milestone: mozilla2.0b8 → mozilla2.0b7
You need to log in before you can comment on or make changes to this bug.