@@ -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 {
@@ -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