Skip to content

Commit f94c77c

Browse files
authored
Merge pull request servo#16 from asajeffrey/surfman-swap-chain-id
Add a swap chain id
2 parents a45f6d0 + 156e3d8 commit f94c77c

File tree

5 files changed

+71
-59
lines changed

5 files changed

+71
-59
lines changed

components/canvas/webgl_mode/inprocess.rs

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use crate::webgl_thread::{WebGLThread, WebGLThreadInit};
66
use canvas_traits::webgl::{WebGLContextId, WebGLMsg, WebGLSender, WebGLThreads};
77
use canvas_traits::webgl::{WebVRRenderHandler, webgl_channel};
8+
use canvas_traits::webgl::SwapChainId;
89
use euclid::default::Size2D;
910
use fnv::FnvHashMap;
1011
use gleam::gl;
@@ -114,7 +115,7 @@ struct WebGLExternalImages {
114115
context: Rc<RefCell<Context>>,
115116
webrender_gl: Rc<dyn gl::Gl>,
116117
swap_chains: SwapChains,
117-
locked_front_buffers: FnvHashMap<WebGLContextId, SurfaceTexture>,
118+
locked_front_buffers: FnvHashMap<SwapChainId, SurfaceTexture>,
118119
sendable: SendableWebGLExternalImages,
119120
}
120121

@@ -136,50 +137,36 @@ impl WebGLExternalImages {
136137
}
137138
}
138139

139-
impl WebrenderExternalImageApi for WebGLExternalImages {
140-
fn lock(&mut self, id: u64) -> (u32, Size2D<i32>) {
141-
let id = WebGLContextId(id);
142-
140+
impl WebGLExternalImages {
141+
fn lock_swap_chain(&mut self, id: SwapChainId) -> Option<(u32, Size2D<i32>)> {
143142
let mut swap_chains = self.swap_chains.lock();
144-
let mut front_buffer = None;
145-
if let Some(ref mut swap_chain) = swap_chains.get_mut(&id) {
146-
front_buffer = swap_chain.pending_surface.take();
147-
if front_buffer.is_none() {
148-
println!("*** no surface ready, presenting last one");
149-
front_buffer = swap_chain.presented_surfaces.pop();
150-
}
151-
}
143+
let swap_chain = swap_chains.get_mut(&id)?;
144+
let front_buffer = swap_chain.pending_surface.take().or_else(|| {
145+
println!("*** no surface ready, presenting last one");
146+
swap_chain.presented_surfaces.pop()
147+
})?;
152148

153-
let (mut gl_texture, mut size) = (0, Size2D::new(0, 0));
154-
if let Some(front_buffer) = front_buffer {
155-
let mut context = self.context.borrow_mut();
156-
size = front_buffer.size();
157-
let front_buffer_texture = self.device
158-
.create_surface_texture(&mut *context, front_buffer)
159-
.unwrap();
160-
gl_texture = front_buffer_texture.gl_texture();
161-
self.locked_front_buffers.insert(id, front_buffer_texture);
162-
}
163-
164-
(gl_texture, size)
165-
}
149+
let mut context = self.context.borrow_mut();
150+
let size = front_buffer.size();
151+
let front_buffer_texture = self.device
152+
.create_surface_texture(&mut *context, front_buffer)
153+
.unwrap();
154+
let gl_texture = front_buffer_texture.gl_texture();
166155

167-
fn unlock(&mut self, id: u64) {
168-
self.sendable.unlock(id as usize);
156+
self.locked_front_buffers.insert(id, front_buffer_texture);
169157

170-
let id = WebGLContextId(id);
171-
let locked_front_buffer = match self.locked_front_buffers.remove(&id) {
172-
None => return,
173-
Some(locked_front_buffer) => locked_front_buffer,
174-
};
158+
Some((gl_texture, size))
159+
}
175160

161+
fn unlock_swap_chain(&mut self, id: SwapChainId) -> Option<()> {
162+
let locked_front_buffer = self.locked_front_buffers.remove(&id)?;
176163
let mut context = self.context.borrow_mut();
177164
let locked_front_buffer = self.device
178165
.destroy_surface_texture(&mut *context, locked_front_buffer)
179166
.unwrap();
180167

181168
self.swap_chains.push_presented_surface(id, locked_front_buffer);
182-
169+
Some(())
183170
/*
184171
let mut front_buffer_slot = self.swap_chains.get(id);
185172
let mut locked_front_buffer_slot = front_buffer_slot.lock();
@@ -194,9 +181,21 @@ impl WebrenderExternalImageApi for WebGLExternalImages {
194181
}
195182
}
196183

184+
impl WebrenderExternalImageApi for WebGLExternalImages {
185+
fn lock(&mut self, id: u64) -> (u32, Size2D<i32>) {
186+
let id = SwapChainId::Context(WebGLContextId(id));
187+
self.lock_swap_chain(id).unwrap_or_default()
188+
}
189+
190+
fn unlock(&mut self, id: u64) {
191+
let id = SwapChainId::Context(WebGLContextId(id));
192+
self.unlock_swap_chain(id);
193+
}
194+
}
195+
197196
#[derive(Clone)]
198197
pub struct SwapChains {
199-
table: Arc<Mutex<FnvHashMap<WebGLContextId, SwapChain>>>,
198+
table: Arc<Mutex<FnvHashMap<SwapChainId, SwapChain>>>,
200199
}
201200

202201
pub(crate) struct SwapChain {
@@ -211,9 +210,9 @@ impl SwapChains {
211210
}
212211
}
213212

214-
fn push_presented_surface(&self, context_id: WebGLContextId, surface: Surface) {
213+
fn push_presented_surface(&self, swap_id: SwapChainId, surface: Surface) {
215214
let mut table = self.lock();
216-
match table.entry(context_id) {
215+
match table.entry(swap_id) {
217216
Entry::Vacant(vacant_entry) => {
218217
vacant_entry.insert(SwapChain {
219218
pending_surface: None,
@@ -226,7 +225,7 @@ impl SwapChains {
226225
}
227226
}
228227

229-
pub(crate) fn lock(&self) -> MutexGuard<FnvHashMap<WebGLContextId, SwapChain>> {
228+
pub(crate) fn lock(&self) -> MutexGuard<FnvHashMap<SwapChainId, SwapChain>> {
230229
self.table.lock().unwrap()
231230
}
232231
}

components/canvas/webgl_mode/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44

55
mod inprocess;
66

7-
pub use self::inprocess::{SwapChains, WebGLComm};
7+
pub use self::inprocess::WebGLComm;
88
pub(crate) use self::inprocess::SwapChain;
9+
pub(crate) use self::inprocess::SwapChains;

components/canvas/webgl_thread.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use canvas_traits::webgl::{WebGLFramebufferId, WebGLMsg, WebGLMsgSender, WebGLPr
1414
use canvas_traits::webgl::{WebGLReceiver, WebGLRenderbufferId, WebGLSLVersion, WebGLSender};
1515
use canvas_traits::webgl::{WebGLShaderId, WebGLTextureId, WebGLVersion, WebGLVertexArrayId};
1616
use canvas_traits::webgl::{WebVRCommand, WebVRRenderHandler, YAxisTreatment};
17+
use canvas_traits::webgl::SwapChainId;
1718
use euclid::default::Size2D;
1819
use fnv::FnvHashMap;
1920
use gleam::gl::{self, Gl, GlFns, GlesFns};
@@ -85,7 +86,7 @@ pub(crate) struct WebGLThread {
8586
receiver: WebGLReceiver<WebGLMsg>,
8687
/// The receiver that should be used to send WebGL messages for processing.
8788
sender: WebGLSender<WebGLMsg>,
88-
/// The front buffer for each WebGL context ID.
89+
/// The front buffer for each swap chain ID.
8990
swap_chains: SwapChains,
9091
///
9192
api_type: gl::GlType,
@@ -258,8 +259,8 @@ impl WebGLThread {
258259
WebGLMsg::UpdateWebRenderImage(ctx_id, sender) => {
259260
self.handle_update_wr_image(ctx_id, sender);
260261
},
261-
WebGLMsg::SwapBuffers(ctx_id) => {
262-
self.handle_swap_buffers(ctx_id);
262+
WebGLMsg::SwapBuffers(swap_id) => {
263+
self.handle_swap_buffers(swap_id);
263264
},
264265
WebGLMsg::DOMToTextureCommand(command) => {
265266
self.handle_dom_to_texture(command);
@@ -401,12 +402,6 @@ impl WebGLThread {
401402
let new_surface = self.device.create_surface(&data.ctx, &size.to_i32()).unwrap();
402403
let old_surface = self.device.replace_context_surface(&mut data.ctx, new_surface).unwrap();
403404
self.device.destroy_surface(&mut data.ctx, old_surface).unwrap();
404-
let new_surface = self.device.create_surface(&data.ctx, &size.to_i32()).unwrap();
405-
let old_surface = self.device.replace_context_surface(&mut data.ctx, new_surface).unwrap();
406-
self.device.destroy_surface(&mut data.ctx, old_surface).unwrap();
407-
408-
let framebuffer = self.device.context_surface_framebuffer_object(&data.ctx).unwrap();
409-
data.gl.bind_framebuffer(gl::FRAMEBUFFER, framebuffer);
410405

411406
// Update WR image if needed. Resize image updates are only required for SharedTexture mode.
412407
// Readback mode already updates the image every frame to send the raw pixels.
@@ -454,7 +449,8 @@ impl WebGLThread {
454449
};
455450

456451
// Destroy all the surfaces
457-
if let Some(swap_chain) = self.swap_chains.lock().remove(&context_id) {
452+
let swap_id = SwapChainId::Context(context_id);
453+
if let Some(swap_chain) = self.swap_chains.lock().remove(&swap_id) {
458454
for surface in swap_chain.pending_surface {
459455
self.device.destroy_surface(&mut data.ctx, surface).unwrap();
460456
}
@@ -481,7 +477,7 @@ impl WebGLThread {
481477
sender: WebGLSender<webrender_api::ImageKey>,
482478
) {
483479
println!("handle_update_wr_image()");
484-
self.handle_swap_buffers(context_id);
480+
self.handle_swap_buffers(SwapChainId::Context(context_id));
485481

486482
let data = Self::make_current_if_needed_mut(
487483
&self.device,
@@ -516,8 +512,9 @@ impl WebGLThread {
516512
sender.send(image_key).unwrap();
517513
}
518514

519-
fn handle_swap_buffers(&mut self, context_id: WebGLContextId) {
515+
fn handle_swap_buffers(&mut self, swap_id: SwapChainId) {
520516
println!("handle_swap_buffers()");
517+
let context_id = swap_id.context_id();
521518
let data = Self::make_current_if_needed_mut(
522519
&self.device,
523520
context_id,
@@ -532,7 +529,7 @@ impl WebGLThread {
532529

533530
// Fetch a new back buffer.
534531
let mut new_back_buffer = None;
535-
if let Some(ref mut swap_chain) = swap_chains.get_mut(&context_id) {
532+
if let Some(ref mut swap_chain) = swap_chains.get_mut(&swap_id) {
536533
for presented_surface_index in 0..swap_chain.presented_surfaces.len() {
537534
if size == swap_chain.presented_surfaces[presented_surface_index].size() {
538535
new_back_buffer = Some(swap_chain.presented_surfaces
@@ -554,13 +551,12 @@ impl WebGLThread {
554551
println!("... new back buffer will become {:?}", new_back_buffer.id());
555552

556553
// Swap the buffers.
557-
let new_front_buffer = self.device
558-
.replace_context_surface(&mut data.ctx, new_back_buffer)
554+
let new_front_buffer = self.device.replace_context_surface(&mut data.ctx, new_back_buffer)
559555
.expect("Where's the new front buffer?");
560556
println!("... front buffer is now {:?}", new_front_buffer.id());
561557

562558
// Hand the new front buffer to the compositor.
563-
match swap_chains.entry(context_id) {
559+
match swap_chains.entry(swap_id) {
564560
Entry::Occupied(mut occupied_entry) => {
565561
let mut swap_chain = occupied_entry.get_mut();
566562
if let Some(old_front_buffer) = mem::replace(&mut swap_chain.pending_surface,

components/canvas_traits/webgl.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ pub enum WebGLMsg {
9696
/// Commands used for the DOMToTexture feature.
9797
DOMToTextureCommand(DOMToTextureCommand),
9898
/// Performs a buffer swap.
99-
SwapBuffers(WebGLContextId),
99+
SwapBuffers(SwapChainId),
100100
/// Frees all resources and closes the thread.
101101
Exit,
102102
}
@@ -198,7 +198,8 @@ impl WebGLMsgSender {
198198

199199
#[inline]
200200
pub fn send_swap_buffers(&self) -> WebGLSendResult {
201-
self.sender.send(WebGLMsg::SwapBuffers(self.ctx_id))
201+
let swap_id = SwapChainId::Context(self.ctx_id);
202+
self.sender.send(WebGLMsg::SwapBuffers(swap_id))
202203
}
203204

204205
pub fn send_dom_to_texture(&self, command: DOMToTextureCommand) -> WebGLSendResult {
@@ -527,6 +528,20 @@ define_resource_id!(WebGLVertexArrayId);
527528
)]
528529
pub struct WebGLContextId(pub u64);
529530

531+
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
532+
pub enum SwapChainId {
533+
Context(WebGLContextId),
534+
// TODO: support opaque framebuffers
535+
}
536+
537+
impl SwapChainId {
538+
pub fn context_id(&self) -> WebGLContextId {
539+
match *self {
540+
SwapChainId::Context(id) => id,
541+
}
542+
}
543+
}
544+
530545
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
531546
pub enum WebGLError {
532547
InvalidEnum,

components/constellation/constellation.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ use backtrace::Backtrace;
105105
use bluetooth_traits::BluetoothRequest;
106106
use canvas::canvas_paint_thread::CanvasPaintThread;
107107
use canvas_traits::canvas::{CanvasId, CanvasMsg};
108-
use canvas_traits::webgl::{WebGLContextId, WebGLMsg, WebGLThreads};
108+
use canvas_traits::webgl::{SwapChainId, WebGLContextId, WebGLMsg, WebGLThreads};
109109
use compositing::compositor_thread::CompositorProxy;
110110
use compositing::compositor_thread::Msg as ToCompositorMsg;
111111
use compositing::SendableFrameTree;
@@ -2130,7 +2130,8 @@ where
21302130
fn handle_swap_webgl_buffers_msg(&mut self, context_ids: Vec<WebGLContextId>) {
21312131
if let Some(ref webgl_threads) = self.webgl_threads {
21322132
for context_id in context_ids {
2133-
if webgl_threads.0.send(WebGLMsg::SwapBuffers(context_id)).is_err() {
2133+
let swap_id = SwapChainId::Context(context_id);
2134+
if webgl_threads.0.send(WebGLMsg::SwapBuffers(swap_id)).is_err() {
21342135
warn!("Failed to send WebGL buffer swap message!")
21352136
}
21362137
}

0 commit comments

Comments
 (0)