Bug 1591837 - Support specification of FBO id in native compositor interface. r=mstange
authorGlenn Watson <git@intuitionlibrary.com>
Mon, 28 Oct 2019 20:38:57 +0000
changeset 499502 4697bcd0537b211a8e5849743a77e9ec7e1a7679
parent 499501 ff061f8b961218d20e3c0a17bd7d4c880021c442
child 499503 7e056a6f4792bac214531647fdfaac1443b2c4e2
push id114161
push userncsoregi@mozilla.com
push dateTue, 29 Oct 2019 21:34:24 +0000
treeherdermozilla-inbound@25bf8e097e60 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1591837
milestone72.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1591837 - Support specification of FBO id in native compositor interface. r=mstange Platform differences between DirectComposition and CoreAnimation mean that WR needs to bind the FBO ID that the underlying platform returns as part of the surface binding operation. Differential Revision: https://phabricator.services.mozilla.com/D50760
gfx/webrender_bindings/RenderCompositor.cpp
gfx/webrender_bindings/RenderCompositor.h
gfx/webrender_bindings/src/bindings.rs
gfx/wr/example-compositor/compositor/src/main.rs
gfx/wr/webrender/src/composite.rs
gfx/wr/webrender/src/device/gl.rs
gfx/wr/webrender/src/lib.rs
gfx/wr/webrender/src/renderer.rs
--- a/gfx/webrender_bindings/RenderCompositor.cpp
+++ b/gfx/webrender_bindings/RenderCompositor.cpp
@@ -31,19 +31,19 @@ void wr_compositor_add_surface(void* aCo
 }
 
 void wr_compositor_begin_frame(void* aCompositor) {
   RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor);
   compositor->CompositorBeginFrame();
 }
 
 void wr_compositor_bind(void* aCompositor, wr::NativeSurfaceId aId,
-                        wr::DeviceIntPoint* aOffset) {
+                        wr::DeviceIntPoint* aOffset, uint32_t* aFboId) {
   RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor);
-  compositor->Bind(aId, aOffset);
+  compositor->Bind(aId, aOffset, aFboId);
 }
 
 void wr_compositor_create_surface(void* aCompositor, wr::NativeSurfaceId aId,
                                   wr::DeviceIntSize aSize) {
   RenderCompositor* compositor = static_cast<RenderCompositor*>(aCompositor);
   compositor->CreateSurface(aId, aSize);
 }
 
--- a/gfx/webrender_bindings/RenderCompositor.h
+++ b/gfx/webrender_bindings/RenderCompositor.h
@@ -63,17 +63,18 @@ class RenderCompositor {
 
   virtual bool IsContextLost();
 
   virtual bool ShouldUseNativeCompositor() { return false; }
 
   // Interface for wr::Compositor
   virtual void CompositorBeginFrame() {}
   virtual void CompositorEndFrame() {}
-  virtual void Bind(wr::NativeSurfaceId aId, wr::DeviceIntPoint* aOffset) {}
+  virtual void Bind(wr::NativeSurfaceId aId, wr::DeviceIntPoint* aOffset,
+                    uint32_t* aFboId) {}
   virtual void Unbind() {}
   virtual void CreateSurface(wr::NativeSurfaceId aId, wr::DeviceIntSize aSize) {
   }
   virtual void DestroySurface(NativeSurfaceId aId) {}
   virtual void AddSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aPosition,
                           wr::DeviceIntRect aClipRect) {}
 
   void wr_compositor_unbind(void* aCompositor) {}
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -20,17 +20,17 @@ use std::os::raw::{c_int};
 use std::time::Duration;
 use gleam::gl;
 
 use webrender::{
     api::*, api::units::*, ApiRecordingReceiver, AsyncPropertySampler, AsyncScreenshotHandle,
     BinaryRecorder, Compositor, DebugFlags, Device, ExternalImage, ExternalImageHandler, ExternalImageSource,
     NativeSurfaceId, PipelineInfo, ProfilerHooks, RecordedFrameHandle, Renderer, RendererOptions, RendererStats,
     SceneBuilderHooks, ShaderPrecacheFlags, Shaders, ThreadListener, UploadMethod, VertexUsageHint,
-    WrShaders, set_profiler_hooks, CompositorConfig
+    WrShaders, set_profiler_hooks, CompositorConfig, NativeSurfaceInfo
 };
 use thread_profiler::register_thread_with_profiler;
 use moz2d_renderer::Moz2dBlobImageHandler;
 use program_cache::{WrProgramCache, remove_disk_cache};
 use rayon;
 use num_cpus;
 use euclid::SideOffsets2D;
 use nsstring::nsAString;
@@ -1144,16 +1144,17 @@ extern "C" {
     fn wr_compositor_destroy_surface(
         compositor: *mut c_void,
         id: NativeSurfaceId,
     );
     fn wr_compositor_bind(
         compositor: *mut c_void,
         id: NativeSurfaceId,
         offset: &mut DeviceIntPoint,
+        fbo_id: &mut u32,
     );
     fn wr_compositor_unbind(compositor: *mut c_void);
     fn wr_compositor_begin_frame(compositor: *mut c_void);
     fn wr_compositor_add_surface(
         compositor: *mut c_void,
         id: NativeSurfaceId,
         position: DeviceIntPoint,
         clip_rect: DeviceIntRect,
@@ -1188,26 +1189,32 @@ impl Compositor for WrCompositor {
                 id,
             );
         }
     }
 
     fn bind(
         &mut self,
         id: NativeSurfaceId,
-    ) -> DeviceIntPoint {
-        let mut offset = DeviceIntPoint::zero();
+    ) -> NativeSurfaceInfo {
+        let mut surface_info = NativeSurfaceInfo {
+            origin: DeviceIntPoint::zero(),
+            fbo_id: 0,
+        };
+
         unsafe {
             wr_compositor_bind(
                 self.0,
                 id,
-                &mut offset,
+                &mut surface_info.origin,
+                &mut surface_info.fbo_id,
             );
         }
-        offset
+
+        surface_info
     }
 
     fn unbind(
         &mut self,
     ) {
         unsafe {
             wr_compositor_unbind(
                 self.0,
--- a/gfx/wr/example-compositor/compositor/src/main.rs
+++ b/gfx/wr/example-compositor/compositor/src/main.rs
@@ -50,23 +50,26 @@ impl webrender::Compositor for DirectCom
         id: webrender::NativeSurfaceId,
     ) {
         compositor::destroy_surface(self.window, id.0);
     }
 
     fn bind(
         &mut self,
         id: webrender::NativeSurfaceId,
-    ) -> DeviceIntPoint {
+    ) -> webrender::NativeSurfaceInfo {
         let (x, y) = compositor::bind_surface(
             self.window,
             id.0,
         );
 
-        DeviceIntPoint::new(x, y)
+        webrender::NativeSurfaceInfo {
+            origin: DeviceIntPoint::new(x, y),
+            fbo_id: 0,
+        }
     }
 
     fn unbind(&mut self) {
         compositor::unbind_surface(self.window);
     }
 
     fn begin_frame(&mut self) {
         compositor::begin_transaction(self.window);
--- a/gfx/wr/webrender/src/composite.rs
+++ b/gfx/wr/webrender/src/composite.rs
@@ -195,16 +195,37 @@ impl CompositeState {
 
 /// An arbitrary identifier for a native (OS compositor) surface
 #[repr(C)]
 #[derive(Debug, Copy, Clone)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct NativeSurfaceId(pub u64);
 
+/// Information about a bound surface that the native compositor
+/// returns to WR.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct NativeSurfaceInfo {
+    /// An offset into the surface that WR should draw. Some compositing
+    /// implementations (notably, DirectComposition) use texture atlases
+    /// when the surface sizes are small. In this case, an offset can
+    /// be returned into the larger texture where WR should draw. This
+    /// can be (0, 0) if texture atlases are not used.
+    pub origin: DeviceIntPoint,
+    /// The ID of the FBO that WR should bind to, in order to draw to
+    /// the bound surface. On Windows (ANGLE) this will always be 0,
+    /// since creating a p-buffer sets the default framebuffer to
+    /// be the DirectComposition surface. On Mac, this will be non-zero,
+    /// since it identifies the IOSurface that has been bound to draw to.
+    // TODO(gw): This may need to be a larger / different type for WR
+    //           backends that are not GL.
+    pub fbo_id: u32,
+}
+
 /// Defines an interface to a native (OS level) compositor. If supplied
 /// by the client application, then picture cache slices will be
 /// composited by the OS compositor, rather than drawn via WR batches.
 pub trait Compositor {
     /// Create a new OS compositor surface with the given properties.
     /// The surface is allocated but not placed in the visual tree.
     fn create_surface(
         &mut self,
@@ -220,17 +241,17 @@ pub trait Compositor {
 
     /// Bind this surface such that WR can issue OpenGL commands
     /// that will target the surface. Returns an (x, y) offset
     /// where WR should draw into the surface. This can be set
     /// to (0, 0) if the OS doesn't use texture atlases.
     fn bind(
         &mut self,
         id: NativeSurfaceId,
-    ) -> DeviceIntPoint;
+    ) -> NativeSurfaceInfo;
 
     /// Unbind the surface. This is called by WR when it has
     /// finished issuing OpenGL commands on the current surface.
     fn unbind(
         &mut self,
     );
 
     /// Begin the frame
--- a/gfx/wr/webrender/src/device/gl.rs
+++ b/gfx/wr/webrender/src/device/gl.rs
@@ -1077,16 +1077,17 @@ pub enum DrawTarget {
     /// Use an FBO attached to an external texture.
     External {
         fbo: FBOId,
         size: FramebufferIntSize,
     },
     /// An OS compositor surface
     NativeSurface {
         offset: DeviceIntPoint,
+        external_fbo_id: u32,
         dimensions: DeviceIntSize,
     },
 }
 
 impl DrawTarget {
     pub fn new_default(size: DeviceIntSize, surface_is_y_flipped: bool) -> Self {
         let total_size = FramebufferIntSize::from_untyped(size.to_untyped());
         DrawTarget::Default {
@@ -1727,44 +1728,42 @@ impl Device {
     }
 
     pub fn bind_draw_target(
         &mut self,
         target: DrawTarget,
     ) {
         let (fbo_id, rect, depth_available) = match target {
             DrawTarget::Default { rect, .. } => {
-                (Some(self.default_draw_fbo), rect, true)
+                (self.default_draw_fbo, rect, true)
             }
             DrawTarget::Texture { dimensions, fbo_id, with_depth, .. } => {
                 let rect = FramebufferIntRect::new(
                     FramebufferIntPoint::zero(),
                     FramebufferIntSize::from_untyped(dimensions.to_untyped()),
                 );
-                (Some(fbo_id), rect, with_depth)
+                (fbo_id, rect, with_depth)
             },
             DrawTarget::External { fbo, size } => {
-                (Some(fbo), size.into(), false)
+                (fbo, size.into(), false)
             }
-            DrawTarget::NativeSurface { offset, dimensions, .. } => {
+            DrawTarget::NativeSurface { external_fbo_id, offset, dimensions, .. } => {
                 (
-                    None,
+                    FBOId(external_fbo_id),
                     FramebufferIntRect::new(
                         FramebufferIntPoint::from_untyped(offset.to_untyped()),
                         FramebufferIntSize::from_untyped(dimensions.to_untyped()),
                     ),
                     true
                 )
             }
         };
 
         self.depth_available = depth_available;
-        if let Some(fbo_id) = fbo_id {
-            self.bind_draw_target_impl(fbo_id);
-        }
+        self.bind_draw_target_impl(fbo_id);
         self.gl.viewport(
             rect.origin.x,
             rect.origin.y,
             rect.size.width,
             rect.size.height,
         );
     }
 
--- a/gfx/wr/webrender/src/lib.rs
+++ b/gfx/wr/webrender/src/lib.rs
@@ -196,17 +196,17 @@ extern crate png;
 #[cfg(test)]
 extern crate rand;
 
 #[macro_use]
 pub extern crate api;
 extern crate webrender_build;
 
 #[doc(hidden)]
-pub use crate::composite::{CompositorConfig, Compositor, NativeSurfaceId};
+pub use crate::composite::{CompositorConfig, Compositor, NativeSurfaceId, NativeSurfaceInfo};
 pub use crate::device::{build_shader_strings, UploadMethod, VertexUsageHint, get_gl_target};
 pub use crate::device::{ProgramBinary, ProgramCache, ProgramCacheObserver, FormatDesc};
 pub use crate::device::Device;
 pub use crate::frame_builder::ChasePrimitive;
 pub use crate::prim_store::PrimitiveDebugId;
 pub use crate::profiler::{ProfilerHooks, set_profiler_hooks};
 pub use crate::renderer::{
     AsyncPropertySampler, CpuProfile, DebugFlags, OutputImageHandler, RendererKind, ExternalImage,
--- a/gfx/wr/webrender/src/renderer.rs
+++ b/gfx/wr/webrender/src/renderer.rs
@@ -5050,27 +5050,28 @@ impl Renderer {
 
                                     DrawTarget::from_texture(
                                         texture,
                                         layer as usize,
                                         true,
                                     )
                                 }
                                 ResolvedSurfaceTexture::NativeSurface { id, size, .. } => {
-                                    let offset = match self.compositor_config {
+                                    let surface_info = match self.compositor_config {
                                         CompositorConfig::Native { ref mut compositor, .. } => {
                                             compositor.bind(id)
                                         }
                                         CompositorConfig::Draw { .. } => {
                                             unreachable!();
                                         }
                                     };
 
                                     DrawTarget::NativeSurface {
-                                        offset,
+                                        offset: surface_info.origin,
+                                        external_fbo_id: surface_info.fbo_id,
                                         dimensions: size,
                                     }
                                 }
                             };
 
                             let projection = Transform3D::ortho(
                                 0.0,
                                 draw_target.dimensions().width as f32,