@@ -23,19 +23,26 @@ use pixels::{self, PixelFormat};
23
23
use std:: borrow:: Cow ;
24
24
use std:: cell:: { Cell , RefCell } ;
25
25
use std:: collections:: hash_map:: Entry ;
26
+ use std:: iter;
26
27
use std:: mem;
27
28
use std:: rc:: Rc ;
28
29
use std:: sync:: { Arc , Mutex } ;
29
30
use std:: thread;
30
31
use surfman:: { self , Adapter , Context , ContextAttributeFlags , ContextAttributes , Device } ;
31
32
use surfman:: GLVersion ;
33
+ use surfman:: Surface ;
32
34
use webrender_traits:: { WebrenderExternalImageRegistry , WebrenderImageHandlerType } ;
33
35
34
36
struct GLContextData {
35
37
ctx : Context ,
36
38
gl : Rc < dyn Gl > ,
37
39
state : GLState ,
38
40
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 > ,
39
46
}
40
47
41
48
pub struct GLState {
@@ -374,7 +381,9 @@ impl WebGLThread {
374
381
gl. bind_framebuffer ( gl:: FRAMEBUFFER , framebuffer) ;
375
382
376
383
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 } ) ;
378
387
379
388
self . cached_context_info . insert (
380
389
id,
@@ -398,9 +407,13 @@ impl WebGLThread {
398
407
& mut self . bound_context_id ) . expect ( "Missing WebGL context!" ) ;
399
408
400
409
// Throw out all buffers.
410
+ let swap_id = SwapChainId :: Context ( context_id) ;
401
411
let context_descriptor = self . device . context_descriptor ( & data. ctx ) ;
402
412
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
+ } ;
404
417
self . device . destroy_surface ( & mut data. ctx , old_surface) . unwrap ( ) ;
405
418
406
419
// Update WR image if needed. Resize image updates are only required for SharedTexture mode.
@@ -449,15 +462,21 @@ impl WebGLThread {
449
462
} ;
450
463
451
464
// 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
+ }
459
475
}
460
476
}
477
+ for ( _, surface) in data. unattached {
478
+ self . device . destroy_surface ( & mut data. ctx , surface) . unwrap ( ) ;
479
+ }
461
480
462
481
// Destroy the context
463
482
self . device . destroy_context ( & mut data. ctx ) . unwrap ( ) ;
@@ -551,8 +570,11 @@ impl WebGLThread {
551
570
println ! ( "... new back buffer will become {:?}" , new_back_buffer. id( ) ) ;
552
571
553
572
// 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
+ } ;
556
578
println ! ( "... front buffer is now {:?}" , new_front_buffer. id( ) ) ;
557
579
558
580
// Hand the new front buffer to the compositor.
0 commit comments