-
-
Notifications
You must be signed in to change notification settings - Fork 480
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable off-main-thread rendering on macOS #931
Conversation
In servo/webrender#1640 we discussed how Firefox (and probably also other browsers) have a compositor thread, which is not the main thread, that does all their OpenGL calls. In glutin this kind of architecture doesn't seem to be possible right now since it's not possible to split the `GlWindow` into the window and the context, and the `Context` doesn't implement `Send` on macOS. The following two changes allow such architectures: - Implement `Send` for `Context` on macOS. The Apple docs suggest that this is correct. - Add a `split` method to `GlWindow` that allows obtaining an owned `Window` and `Context`.
I don't like this change as it is, because destroying the |
Interesting, that makes sense. I'll see if I can think of some way to use the borrow checker to fix that, if possible. |
Okay here's a sketch of my new idea, I'm not sure when or if I'll get around to fully implementing it though: trait RenderThread {
type Message;
type State;
// these are both called only on the render thread
/// sets up state that needs the context, and probably sets context as active for this thread
fn init(ctx: &Context) -> State;
/// called by render thread event loop on getting an mpsc message
fn got_message(ctx: &Context, state: &mut State, msg: Message);
}
struct ConcurrentGlWindow<R: RenderThread> { ... }
enum RenderThreadMsg<T> {
// handled by the thread's loop, drops the context and shuts down the thread
Close,
// calls got_message with the contained message
Inner(T),
}
impl<R: RenderThread> ConcurrentGlWindow<R> {
// this is the main loop of the render thread, called from a thread::spawn somewhere
pub render_thread_loop(render_thread: R, ctx: Context, rcv: mpsc::Receiver<RenderThreadMsg<R::Message>>) {
// 1. do context initialization that has to be done on the render thread, if any
ctx.do_setup_stuff();
let mut state = render_thread.init(&ctx);
for msg in rcv.into_iter() {
match msg {
RenderThreadMsg::Close => break,
RenderThreadMsg::Inner(m) => render_thread.got_message(&ctx, &mut state, m),
}
}
}
// enable the main thread to send messages to render, like new frame data
pub fn sender(&self) -> &mpsc::Sender<RenderThreadMsg<R::Message>> { ... }
// on platforms that don't support off-main-thread rendering, this manually ticks the render thread event loop on the main thread. When there is a separate thread, it does nothing.
pub fn tick(&self) { ... }
pub fn window(&self) -> &Window { ... }
}
impl Deref for ConcurrentGlWindow { type Target = Window; ... }
impl Drop for ConcurrentGlWindow {
fn drop(&mut self) {
self.sender.send(RenderThreadMsg::Close);
self.thread_join_handle.join();
}
} Thoughts? |
Theoretically, the correct and easiest fix would be to implement |
@tomaka implementing On macOS, each thread has its own OpenGL context, and you are only supposed to do calls on that context from one thread at a time. You can do it from multiple threads, but only if you synchronize them. If Also the |
That's the reason why the methods on the |
In servo/webrender#1640 we discussed how Firefox
(and probably also other browsers) have a compositor thread, which is not the
main thread, that does all their OpenGL calls. In glutin this kind of
architecture doesn't seem to be possible right now since it's not possible to
split the
GlWindow
into the window and the context, and theContext
doesn't implement
Send
on macOS.The following two changes allow such architectures:
Send
forContext
on macOS. The Apple docs suggest that this is correct.split
method toGlWindow
that allows obtaining an ownedWindow
andContext
.cc @mitchmindtree @mstange @glennw