aboutsummaryrefslogtreecommitdiffstats
path: root/components/webrender_surfman/lib.rs
diff options
context:
space:
mode:
authorAlan Jeffrey <ajeffrey@mozilla.com>2020-01-09 17:28:46 -0600
committerAlan Jeffrey <ajeffrey@mozilla.com>2020-04-17 23:44:53 -0500
commit8bb1732258c44e6850618a8f2fbb2927bc01b090 (patch)
treee4483e94fd5fbceb15fe9e35e3d5a085d3b2b814 /components/webrender_surfman/lib.rs
parent9dbc6554f087ca3675104fb1bac45b0c442a0158 (diff)
downloadservo-8bb1732258c44e6850618a8f2fbb2927bc01b090.tar.gz
servo-8bb1732258c44e6850618a8f2fbb2927bc01b090.zip
Update surfman to 0.2 and remove glutin
Diffstat (limited to 'components/webrender_surfman/lib.rs')
-rw-r--r--components/webrender_surfman/lib.rs213
1 files changed, 213 insertions, 0 deletions
diff --git a/components/webrender_surfman/lib.rs b/components/webrender_surfman/lib.rs
new file mode 100644
index 00000000000..193298808bc
--- /dev/null
+++ b/components/webrender_surfman/lib.rs
@@ -0,0 +1,213 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+#![deny(unsafe_code)]
+
+use euclid::default::Size2D;
+
+use std::cell::RefCell;
+use std::ffi::c_void;
+use std::rc::Rc;
+use surfman::Adapter;
+use surfman::Connection;
+use surfman::Context;
+use surfman::ContextAttributeFlags;
+use surfman::ContextAttributes;
+use surfman::Device;
+use surfman::Error;
+use surfman::GLApi;
+use surfman::GLVersion;
+use surfman::NativeContext;
+use surfman::NativeDevice;
+use surfman::NativeWidget;
+use surfman::Surface;
+use surfman::SurfaceAccess;
+use surfman::SurfaceInfo;
+use surfman::SurfaceTexture;
+use surfman::SurfaceType;
+use surfman_chains::SurfmanProvider;
+use surfman_chains::SwapChain;
+
+/// A bridge between webrender and surfman
+// TODO: move this into a different crate so that script doesn't depend on surfman
+#[derive(Clone)]
+pub struct WebrenderSurfman(Rc<WebrenderSurfmanData>);
+
+struct WebrenderSurfmanData {
+ device: RefCell<Device>,
+ context: RefCell<Context>,
+ // We either render to a swap buffer or to a native widget
+ swap_chain: Option<SwapChain<Device>>,
+}
+
+impl Drop for WebrenderSurfmanData {
+ fn drop(&mut self) {
+ let ref mut device = self.device.borrow_mut();
+ let ref mut context = self.context.borrow_mut();
+ if let Some(ref swap_chain) = self.swap_chain {
+ let _ = swap_chain.destroy(device, context);
+ }
+ let _ = device.destroy_context(context);
+ }
+}
+
+impl WebrenderSurfman {
+ pub fn create(
+ connection: &Connection,
+ adapter: &Adapter,
+ surface_type: SurfaceType<NativeWidget>,
+ ) -> Result<Self, Error> {
+ let mut device = connection.create_device(&adapter)?;
+ let flags = ContextAttributeFlags::ALPHA |
+ ContextAttributeFlags::DEPTH |
+ ContextAttributeFlags::STENCIL;
+ let version = match connection.gl_api() {
+ GLApi::GLES => GLVersion { major: 3, minor: 0 },
+ GLApi::GL => GLVersion { major: 3, minor: 2 },
+ };
+ let context_attributes = ContextAttributes { flags, version };
+ let context_descriptor = device.create_context_descriptor(&context_attributes)?;
+ let mut context = device.create_context(&context_descriptor)?;
+ let surface_access = SurfaceAccess::GPUOnly;
+ let headless = match surface_type {
+ SurfaceType::Widget { .. } => false,
+ SurfaceType::Generic { .. } => true,
+ };
+ let surface = device.create_surface(&context, surface_access, surface_type)?;
+ device
+ .bind_surface_to_context(&mut context, surface)
+ .map_err(|(err, mut surface)| {
+ let _ = device.destroy_surface(&mut context, &mut surface);
+ err
+ })?;
+ let swap_chain = if headless {
+ let surface_provider = Box::new(SurfmanProvider::new(surface_access));
+ Some(SwapChain::create_attached(
+ &mut device,
+ &mut context,
+ surface_provider,
+ )?)
+ } else {
+ None
+ };
+ let device = RefCell::new(device);
+ let context = RefCell::new(context);
+ let data = WebrenderSurfmanData {
+ device,
+ context,
+ swap_chain,
+ };
+ Ok(WebrenderSurfman(Rc::new(data)))
+ }
+
+ pub fn create_surface_texture(
+ &self,
+ surface: Surface,
+ ) -> Result<SurfaceTexture, (Error, Surface)> {
+ let ref device = self.0.device.borrow();
+ let ref mut context = self.0.context.borrow_mut();
+ device.create_surface_texture(context, surface)
+ }
+
+ pub fn destroy_surface_texture(
+ &self,
+ surface_texture: SurfaceTexture,
+ ) -> Result<Surface, (Error, SurfaceTexture)> {
+ let ref device = self.0.device.borrow();
+ let ref mut context = self.0.context.borrow_mut();
+ device.destroy_surface_texture(context, surface_texture)
+ }
+
+ pub fn make_gl_context_current(&self) -> Result<(), Error> {
+ let ref device = self.0.device.borrow();
+ let ref context = self.0.context.borrow();
+ device.make_context_current(context)
+ }
+
+ pub fn swap_chain(&self) -> Result<&SwapChain<Device>, Error> {
+ self.0.swap_chain.as_ref().ok_or(Error::WidgetAttached)
+ }
+
+ pub fn resize(&self, size: Size2D<i32>) -> Result<(), Error> {
+ let ref mut device = self.0.device.borrow_mut();
+ let ref mut context = self.0.context.borrow_mut();
+ if let Some(swap_chain) = self.0.swap_chain.as_ref() {
+ return swap_chain.resize(device, context, size);
+ }
+ let mut surface = device.unbind_surface_from_context(context)?.unwrap();
+ device.resize_surface(context, &mut surface, size)?;
+ device
+ .bind_surface_to_context(context, surface)
+ .map_err(|(err, mut surface)| {
+ let _ = device.destroy_surface(context, &mut surface);
+ err
+ })
+ }
+
+ pub fn present(&self) -> Result<(), Error> {
+ let ref mut device = self.0.device.borrow_mut();
+ let ref mut context = self.0.context.borrow_mut();
+ if let Some(ref swap_chain) = self.0.swap_chain {
+ return swap_chain.swap_buffers(device, context);
+ }
+ let mut surface = device.unbind_surface_from_context(context)?.unwrap();
+ device.present_surface(context, &mut surface)?;
+ device
+ .bind_surface_to_context(context, surface)
+ .map_err(|(err, mut surface)| {
+ let _ = device.destroy_surface(context, &mut surface);
+ err
+ })
+ }
+
+ pub fn connection(&self) -> Connection {
+ let ref device = self.0.device.borrow();
+ device.connection()
+ }
+
+ pub fn adapter(&self) -> Adapter {
+ let ref device = self.0.device.borrow();
+ device.adapter()
+ }
+
+ pub fn native_context(&self) -> NativeContext {
+ let ref device = self.0.device.borrow();
+ let ref context = self.0.context.borrow();
+ device.native_context(context)
+ }
+
+ pub fn native_device(&self) -> NativeDevice {
+ let ref device = self.0.device.borrow();
+ device.native_device()
+ }
+
+ pub fn context_attributes(&self) -> ContextAttributes {
+ let ref device = self.0.device.borrow();
+ let ref context = self.0.context.borrow();
+ let ref descriptor = device.context_descriptor(context);
+ device.context_descriptor_attributes(descriptor)
+ }
+
+ pub fn context_surface_info(&self) -> Result<Option<SurfaceInfo>, Error> {
+ let ref device = self.0.device.borrow();
+ let ref context = self.0.context.borrow();
+ device.context_surface_info(context)
+ }
+
+ pub fn surface_info(&self, surface: &Surface) -> SurfaceInfo {
+ let ref device = self.0.device.borrow();
+ device.surface_info(surface)
+ }
+
+ pub fn surface_texture_object(&self, surface: &SurfaceTexture) -> u32 {
+ let ref device = self.0.device.borrow();
+ device.surface_texture_object(surface)
+ }
+
+ pub fn get_proc_address(&self, name: &str) -> *const c_void {
+ let ref device = self.0.device.borrow();
+ let ref context = self.0.context.borrow();
+ device.get_proc_address(context, name)
+ }
+}