Skip to content

Commit 8de8aa3

Browse files
authored
Merge pull request servo#17 from asajeffrey/surfman-unattached-swap-chains
Allow webGL swap chains to exist without being attached to their context
2 parents f94c77c + 359cadb commit 8de8aa3

File tree

1 file changed

+33
-11
lines changed

1 file changed

+33
-11
lines changed

components/canvas/webgl_thread.rs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,26 @@ use pixels::{self, PixelFormat};
2323
use std::borrow::Cow;
2424
use std::cell::{Cell, RefCell};
2525
use std::collections::hash_map::Entry;
26+
use std::iter;
2627
use std::mem;
2728
use std::rc::Rc;
2829
use std::sync::{Arc, Mutex};
2930
use std::thread;
3031
use surfman::{self, Adapter, Context, ContextAttributeFlags, ContextAttributes, Device};
3132
use surfman::GLVersion;
33+
use surfman::Surface;
3234
use webrender_traits::{WebrenderExternalImageRegistry, WebrenderImageHandlerType};
3335

3436
struct GLContextData {
3537
ctx: Context,
3638
gl: Rc<dyn Gl>,
3739
state: GLState,
3840
attributes: GLContextAttributes,
41+
// Each WebGL context has a collection of swap chains, one of which is attached
42+
// (that is, its surface is the current surface of the context).
43+
attached: SwapChainId,
44+
// The other swap chains are unattached, and their surfaces are not the current surface of the context.
45+
unattached: FnvHashMap<SwapChainId, Surface>,
3946
}
4047

4148
pub struct GLState {
@@ -374,7 +381,9 @@ impl WebGLThread {
374381
gl.bind_framebuffer(gl::FRAMEBUFFER, framebuffer);
375382

376383
let state = Default::default();
377-
self.contexts.insert(id, GLContextData { ctx, gl, state, attributes });
384+
let attached = SwapChainId::Context(id);
385+
let unattached = Default::default();
386+
self.contexts.insert(id, GLContextData { ctx, gl, state, attributes, attached, unattached });
378387

379388
self.cached_context_info.insert(
380389
id,
@@ -398,9 +407,13 @@ impl WebGLThread {
398407
&mut self.bound_context_id).expect("Missing WebGL context!");
399408

400409
// Throw out all buffers.
410+
let swap_id = SwapChainId::Context(context_id);
401411
let context_descriptor = self.device.context_descriptor(&data.ctx);
402412
let new_surface = self.device.create_surface(&data.ctx, &size.to_i32()).unwrap();
403-
let old_surface = self.device.replace_context_surface(&mut data.ctx, new_surface).unwrap();
413+
let old_surface = match data.unattached.get_mut(&swap_id) {
414+
Some(surface) => mem::replace(surface, new_surface),
415+
None => self.device.replace_context_surface(&mut data.ctx, new_surface).unwrap(),
416+
};
404417
self.device.destroy_surface(&mut data.ctx, old_surface).unwrap();
405418

406419
// Update WR image if needed. Resize image updates are only required for SharedTexture mode.
@@ -449,15 +462,21 @@ impl WebGLThread {
449462
};
450463

451464
// Destroy all the surfaces
452-
let swap_id = SwapChainId::Context(context_id);
453-
if let Some(swap_chain) = self.swap_chains.lock().remove(&swap_id) {
454-
for surface in swap_chain.pending_surface {
455-
self.device.destroy_surface(&mut data.ctx, surface).unwrap();
456-
}
457-
for surface in swap_chain.presented_surfaces {
458-
self.device.destroy_surface(&mut data.ctx, surface).unwrap();
465+
let swap_ids = iter::once(data.attached)
466+
.chain(data.unattached.keys().cloned());
467+
for swap_id in swap_ids {
468+
if let Some(swap_chain) = self.swap_chains.lock().remove(&swap_id) {
469+
for surface in swap_chain.pending_surface {
470+
self.device.destroy_surface(&mut data.ctx, surface).unwrap();
471+
}
472+
for surface in swap_chain.presented_surfaces {
473+
self.device.destroy_surface(&mut data.ctx, surface).unwrap();
474+
}
459475
}
460476
}
477+
for (_, surface) in data.unattached {
478+
self.device.destroy_surface(&mut data.ctx, surface).unwrap();
479+
}
461480

462481
// Destroy the context
463482
self.device.destroy_context(&mut data.ctx).unwrap();
@@ -551,8 +570,11 @@ impl WebGLThread {
551570
println!("... new back buffer will become {:?}", new_back_buffer.id());
552571

553572
// Swap the buffers.
554-
let new_front_buffer = self.device.replace_context_surface(&mut data.ctx, new_back_buffer)
555-
.expect("Where's the new front buffer?");
573+
let new_front_buffer = match data.unattached.get_mut(&swap_id) {
574+
Some(surface) => mem::replace(surface, new_back_buffer),
575+
None => self.device.replace_context_surface(&mut data.ctx, new_back_buffer)
576+
.expect("Where's the new front buffer?"),
577+
};
556578
println!("... front buffer is now {:?}", new_front_buffer.id());
557579

558580
// Hand the new front buffer to the compositor.

0 commit comments

Comments
 (0)