@@ -23,19 +23,26 @@ use pixels::{self, PixelFormat};
2323use std:: borrow:: Cow ;
2424use std:: cell:: { Cell , RefCell } ;
2525use std:: collections:: hash_map:: Entry ;
26+ use std:: iter;
2627use std:: mem;
2728use std:: rc:: Rc ;
2829use std:: sync:: { Arc , Mutex } ;
2930use std:: thread;
3031use surfman:: { self , Adapter , Context , ContextAttributeFlags , ContextAttributes , Device } ;
3132use surfman:: GLVersion ;
33+ use surfman:: Surface ;
3234use webrender_traits:: { WebrenderExternalImageRegistry , WebrenderImageHandlerType } ;
3335
3436struct 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
4148pub struct GLState {
@@ -364,7 +371,9 @@ impl WebGLThread {
364371 gl. bind_framebuffer ( gl:: FRAMEBUFFER , framebuffer) ;
365372
366373 let state = Default :: default ( ) ;
367- self . contexts . insert ( id, GLContextData { ctx, gl, state, attributes } ) ;
374+ let attached = SwapChainId :: Context ( id) ;
375+ let unattached = Default :: default ( ) ;
376+ self . contexts . insert ( id, GLContextData { ctx, gl, state, attributes, attached, unattached } ) ;
368377
369378 self . cached_context_info . insert (
370379 id,
@@ -388,9 +397,13 @@ impl WebGLThread {
388397 & mut self . bound_context_id ) . expect ( "Missing WebGL context!" ) ;
389398
390399 // Throw out all buffers.
400+ let swap_id = SwapChainId :: Context ( context_id) ;
391401 let context_descriptor = self . device . context_descriptor ( & data. ctx ) ;
392402 let new_surface = self . device . create_surface ( & data. ctx , & size. to_i32 ( ) ) . unwrap ( ) ;
393- let old_surface = self . device . replace_context_surface ( & mut data. ctx , new_surface) . unwrap ( ) ;
403+ let old_surface = match data. unattached . get_mut ( & swap_id) {
404+ Some ( surface) => mem:: replace ( surface, new_surface) ,
405+ None => self . device . replace_context_surface ( & mut data. ctx , new_surface) . unwrap ( ) ,
406+ } ;
394407 self . device . destroy_surface ( & mut data. ctx , old_surface) . unwrap ( ) ;
395408
396409 // Update WR image if needed. Resize image updates are only required for SharedTexture mode.
@@ -439,15 +452,21 @@ impl WebGLThread {
439452 } ;
440453
441454 // Destroy all the surfaces
442- let swap_id = SwapChainId :: Context ( context_id) ;
443- if let Some ( swap_chain) = self . swap_chains . lock ( ) . remove ( & swap_id) {
444- for surface in swap_chain. pending_surface {
445- self . device . destroy_surface ( & mut data. ctx , surface) . unwrap ( ) ;
446- }
447- for surface in swap_chain. presented_surfaces {
448- self . device . destroy_surface ( & mut data. ctx , surface) . unwrap ( ) ;
455+ let swap_ids = iter:: once ( data. attached )
456+ . chain ( data. unattached . keys ( ) . cloned ( ) ) ;
457+ for swap_id in swap_ids {
458+ if let Some ( swap_chain) = self . swap_chains . lock ( ) . remove ( & swap_id) {
459+ for surface in swap_chain. pending_surface {
460+ self . device . destroy_surface ( & mut data. ctx , surface) . unwrap ( ) ;
461+ }
462+ for surface in swap_chain. presented_surfaces {
463+ self . device . destroy_surface ( & mut data. ctx , surface) . unwrap ( ) ;
464+ }
449465 }
450466 }
467+ for ( _, surface) in data. unattached {
468+ self . device . destroy_surface ( & mut data. ctx , surface) . unwrap ( ) ;
469+ }
451470
452471 // Destroy the context
453472 self . device . destroy_context ( & mut data. ctx ) . unwrap ( ) ;
@@ -541,8 +560,11 @@ impl WebGLThread {
541560 println ! ( "... new back buffer will become {:?}" , new_back_buffer. id( ) ) ;
542561
543562 // Swap the buffers.
544- let new_front_buffer = self . device . replace_context_surface ( & mut data. ctx , new_back_buffer)
545- . expect ( "Where's the new front buffer?" ) ;
563+ let new_front_buffer = match data. unattached . get_mut ( & swap_id) {
564+ Some ( surface) => mem:: replace ( surface, new_back_buffer) ,
565+ None => self . device . replace_context_surface ( & mut data. ctx , new_back_buffer)
566+ . expect ( "Where's the new front buffer?" ) ,
567+ } ;
546568 println ! ( "... front buffer is now {:?}" , new_front_buffer. id( ) ) ;
547569
548570 // Hand the new front buffer to the compositor.
0 commit comments