diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-08-15 16:00:10 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-15 16:00:10 -0500 |
commit | 90f55ea4580e2a15f7d70d0491444f18b972d450 (patch) | |
tree | c85f3cb5d55babab03d56dac8b0d10d588b0a0f9 /components/canvas/gl_context.rs | |
parent | 2e60b27a2186a8cba4b952960155dfcf3f47d7db (diff) | |
parent | 703962fe61d673536eb982b45795ae13748f0f6a (diff) | |
download | servo-90f55ea4580e2a15f7d70d0491444f18b972d450.tar.gz servo-90f55ea4580e2a15f7d70d0491444f18b972d450.zip |
Auto merge of #17891 - MortimerGoro:webgl_move, r=glennw,emilio
Improved WebGL architecture
<!-- Please describe your changes on the following line: -->
Info about the big picture and the goals of the WebGL refactor in this thread: https://groups.google.com/forum/#!topic/mozilla.dev.servo/0WMGz60kKzQ
I tried to reduce this PR as much as possible as requested in the thread. I'll do separate PRs for other features (e.g.: Batch messages or use shared memory to improve frame times) or fixes.
Some tips to ease the review process:
- Most changes in DOM objects follow the same pattern (remove CanvasMsg wrapper and use the new sender method).
- WebGLCommands are the same ones as before (moved from webrender_api). So those lines are already reviewed.
- See WebGL traits in [components/canvas_traits/webgl.rs](https://github.com/servo/servo/pull/17891/files#diff-8701045d01505418701d0631d4d45562)
- See WebGLThread and WR External Image bridge in [components/canvas/webgl_thread.rs](https://github.com/servo/servo/pull/17891/files#diff-281554879f39a2a041f7a69d442a5d2e)
- The implementation submitted in this PR creates a single `WebGLThread` for all ScriptThread/Pipelines. See that in [components/canvas/webgl_mode/inprocess.rs](https://github.com/servo/servo/pull/17891/files#diff-250070c6c5a38c7f9fa0f5b3c101f68b)
The conformance tests will help to guarantee that we don't miss anything.
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [x] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17891)
<!-- Reviewable:end -->
Diffstat (limited to 'components/canvas/gl_context.rs')
-rw-r--r-- | components/canvas/gl_context.rs | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/components/canvas/gl_context.rs b/components/canvas/gl_context.rs new file mode 100644 index 00000000000..69a26c0e03c --- /dev/null +++ b/components/canvas/gl_context.rs @@ -0,0 +1,203 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use canvas_traits::webgl::WebGLCommand; +use compositing::compositor_thread::{CompositorProxy, self}; +use euclid::Size2D; +use gleam::gl; +use offscreen_gl_context::{ColorAttachmentType, GLContext, GLContextAttributes, GLContextDispatcher, GLLimits}; +use offscreen_gl_context::{NativeGLContext, NativeGLContextHandle, NativeGLContextMethods}; +use offscreen_gl_context::{OSMesaContext, OSMesaContextHandle}; +use std::sync::{Arc, Mutex}; +use super::webgl_thread::WebGLImpl; + +/// The GLContextFactory is used to create shared GL contexts with the main thread GL context. +/// Currently, shared textures are used to render WebGL textures into the WR compositor. +/// In order to create a shared context, the GLContextFactory stores the handle of the main GL context. +pub enum GLContextFactory { + Native(NativeGLContextHandle, Option<MainThreadDispatcher>), + OSMesa(OSMesaContextHandle), +} + +impl GLContextFactory { + /// Creates a new GLContextFactory that uses the currently bound GL context to create shared contexts. + pub fn current_native_handle(proxy: &CompositorProxy) -> Option<GLContextFactory> { + NativeGLContext::current_handle().map(|handle| { + if cfg!(target_os = "windows") { + // Used to dispatch functions from the GLContext thread to the main thread's event loop. + // Required to allow WGL GLContext sharing in Windows. + GLContextFactory::Native(handle, Some(MainThreadDispatcher::new(proxy.clone_compositor_proxy()))) + } else { + GLContextFactory::Native(handle, None) + } + }) + } + + /// Creates a new GLContextFactory that uses the currently bound OSMesa context to create shared contexts. + pub fn current_osmesa_handle() -> Option<GLContextFactory> { + OSMesaContext::current_handle().map(GLContextFactory::OSMesa) + } + + /// Creates a new shared GLContext with the main GLContext + pub fn new_shared_context(&self, + size: Size2D<i32>, + attributes: GLContextAttributes) -> Result<GLContextWrapper, &'static str> { + match *self { + GLContextFactory::Native(ref handle, ref dispatcher) => { + let dispatcher = dispatcher.as_ref().map(|d| Box::new(d.clone()) as Box<_>); + let ctx = GLContext::<NativeGLContext>::new_shared_with_dispatcher(size, + attributes, + ColorAttachmentType::Texture, + gl::GlType::default(), + Some(handle), + dispatcher); + ctx.map(GLContextWrapper::Native) + } + GLContextFactory::OSMesa(ref handle) => { + let ctx = GLContext::<OSMesaContext>::new_shared_with_dispatcher(size.to_untyped(), + attributes, + ColorAttachmentType::Texture, + gl::GlType::default(), + Some(handle), + None); + ctx.map(GLContextWrapper::OSMesa) + } + } + } + + /// Creates a new non-shared GLContext + pub fn new_context(&self, + size: Size2D<i32>, + attributes: GLContextAttributes) -> Result<GLContextWrapper, &'static str> { + match *self { + GLContextFactory::Native(..) => { + let ctx = GLContext::<NativeGLContext>::new_shared_with_dispatcher(size, + attributes, + ColorAttachmentType::Texture, + gl::GlType::default(), + None, + None); + ctx.map(GLContextWrapper::Native) + } + GLContextFactory::OSMesa(_) => { + let ctx = GLContext::<OSMesaContext>::new_shared_with_dispatcher(size.to_untyped(), + attributes, + ColorAttachmentType::Texture, + gl::GlType::default(), + None, + None); + ctx.map(GLContextWrapper::OSMesa) + } + } + } +} + + +/// GLContextWrapper used to abstract NativeGLContext and OSMesaContext types +pub enum GLContextWrapper { + Native(GLContext<NativeGLContext>), + OSMesa(GLContext<OSMesaContext>), +} + +impl GLContextWrapper { + pub fn make_current(&self) { + match *self { + GLContextWrapper::Native(ref ctx) => { + ctx.make_current().unwrap(); + } + GLContextWrapper::OSMesa(ref ctx) => { + ctx.make_current().unwrap(); + } + } + } + + pub fn unbind(&self) { + match *self { + GLContextWrapper::Native(ref ctx) => { + ctx.unbind().unwrap(); + } + GLContextWrapper::OSMesa(ref ctx) => { + ctx.unbind().unwrap(); + } + } + } + + pub fn apply_command(&self, cmd: WebGLCommand) { + match *self { + GLContextWrapper::Native(ref ctx) => { + WebGLImpl::apply(ctx, cmd); + } + GLContextWrapper::OSMesa(ref ctx) => { + WebGLImpl::apply(ctx, cmd); + } + } + } + + pub fn gl(&self) -> &gl::Gl { + match *self { + GLContextWrapper::Native(ref ctx) => { + ctx.gl() + } + GLContextWrapper::OSMesa(ref ctx) => { + ctx.gl() + } + } + } + + pub fn get_info(&self) -> (Size2D<i32>, u32, GLLimits) { + match *self { + GLContextWrapper::Native(ref ctx) => { + let (real_size, texture_id) = { + let draw_buffer = ctx.borrow_draw_buffer().unwrap(); + (draw_buffer.size(), draw_buffer.get_bound_texture_id().unwrap()) + }; + + let limits = ctx.borrow_limits().clone(); + + (real_size, texture_id, limits) + } + GLContextWrapper::OSMesa(ref ctx) => { + let (real_size, texture_id) = { + let draw_buffer = ctx.borrow_draw_buffer().unwrap(); + (draw_buffer.size(), draw_buffer.get_bound_texture_id().unwrap()) + }; + + let limits = ctx.borrow_limits().clone(); + + (real_size, texture_id, limits) + } + } + } + + pub fn resize(&mut self, size: Size2D<i32>) -> Result<(), &'static str> { + match *self { + GLContextWrapper::Native(ref mut ctx) => { + ctx.resize(size) + } + GLContextWrapper::OSMesa(ref mut ctx) => { + ctx.resize(size) + } + } + } +} + +/// Implements GLContextDispatcher to dispatch functions from GLContext threads to the main thread's event loop. +/// It's used in Windows to allow WGL GLContext sharing. +#[derive(Clone)] +pub struct MainThreadDispatcher { + compositor_proxy: Arc<Mutex<CompositorProxy>> +} + +impl MainThreadDispatcher { + fn new(proxy: CompositorProxy) -> Self { + Self { + compositor_proxy: Arc::new(Mutex::new(proxy)), + } + } +} +impl GLContextDispatcher for MainThreadDispatcher { + fn dispatch(&self, f: Box<Fn() + Send>) { + self.compositor_proxy.lock().unwrap().send(compositor_thread::Msg::Dispatch(f)); + } +} |