/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use std::os::raw::c_void; use std::ptr;
use mozangle::egl::ffi::types::EGLContext; use webrender::{CompositorInputConfig, CompositorSurfaceTransform, LayerCompositor}; use winit::raw_window_handle::{HasWindowHandle, RawWindowHandle};
usecrate::WindowWrapper;
use mozangle::egl::ffi::types::{EGLDisplay, EGLSurface, EGLint}; use mozangle::egl;
// A simplistic implementation of the `LayerCompositor` trait to allow wrench to // composite via DirectComposition. In this initial version, only a single // swap-chain is supported. Follow up patches will add layer and external // surface support.
// A basic layer - we only create one primary layer in the initial commit struct WrLayer { // Layer dimensions
width: i32,
height: i32, // EGL surface that gets bound for webrender to draw to
surface: EGLSurface, // Handle to the FFI layer
layer_id: LayerId,
}
// A basic `LayerCompositor` implementation for wrench pubstruct WrCompositor { // EGL display and content, provided by winit
context: EGLContext,
display: EGLDisplay, // FFI compositor handle
compositor: CompositorHandle, // The swapchain layers needed for current scene
layers: Vec<WrLayer>,
}
impl WrCompositor { pubfn new(window: &WindowWrapper) -> Self { // Retrieve the D3D11 device from winit - this was created when ANGLE was initialized let d3d11_device = window.get_d3d11_device();
// Get the win32 and EGL information needed from the window let (hwnd, display, context) = match window {
WindowWrapper::Angle { window, context: angle, .. } => { let hwnd = match window.window_handle().unwrap().as_raw() {
RawWindowHandle::Win32(h) => h.hwnd.get() as *const c_void,
_ => unreachable!(),
};
(hwnd, angle.get_display(), angle.get_context())
}
_ => unreachable!(),
};
// Construct the FFI part of the compositor impl let compositor = unsafe {
wrc_new(d3d11_device, hwnd)
};
impl Drop for WrCompositor { fn drop(&mutself) { unsafe {
wrc_delete(self.compositor);
}
}
}
impl LayerCompositor for WrCompositor { // Begin compositing a frame with the supplied input config // The main job of this method is to inspect the input config, create the output // config, and create any native OS resources that will be needed as layers get // composited. fn begin_frame(
&mutself,
input: &CompositorInputConfig,
) -> bool { unsafe { // Reset DC visual tree
wrc_begin_frame(self.compositor);
}
let prev_layer_count = self.layers.len(); let curr_layer_count = input.layers.len();
if prev_layer_count > curr_layer_count {
todo!();
} elseif curr_layer_count > prev_layer_count { // Construct new empty layers, they'll get resized below for _ in0 .. curr_layer_count-prev_layer_count { self.layers.push(WrLayer::empty());
}
}
for (input, layer) in input.layers.iter().zip(self.layers.iter_mut()) { let input_size = input.clip_rect.size();
// TODO(gwc): Handle External surfaces as swapchains separate from content
// See if we need to resize the swap-chain layer if input_size.width != layer.width ||
input_size.height != layer.height { // TODO: Handle resize of layer (not needed for initial commit, // but will need to support resizing wrench window)
assert_eq!(layer.layer_id, LayerId::INVALID);
// Construct a DC swap-chain
layer.width = input_size.width;
layer.height = input_size.height;
layer.layer_id = unsafe {
wrc_create_layer(self.compositor, layer.width, layer.height, input.is_opaque)
};
let pbuffer_attribs: [EGLint; 5] = [
egl::ffi::WIDTH as EGLint, layer.width,
egl::ffi::HEIGHT as EGLint, layer.height,
egl::ffi::NONE as EGLint,
];
let attribs: [EGLint; 18] = [
egl::ffi::SURFACE_TYPE as EGLint, egl::ffi::WINDOW_BIT as EGLint,
egl::ffi::RED_SIZE as EGLint, 8,
egl::ffi::GREEN_SIZE as EGLint, 8,
egl::ffi::BLUE_SIZE as EGLint, 8,
egl::ffi::ALPHA_SIZE as EGLint, 8,
egl::ffi::RENDERABLE_TYPE as EGLint, egl::ffi::OPENGL_ES2_BIT as EGLint, // TODO(gw): Can we disable z-buffer for compositing always?
egl::ffi::DEPTH_SIZE as EGLint, 24,
egl::ffi::STENCIL_SIZE as EGLint, 8,
egl::ffi::NONE as EGLint, egl::ffi::NONE as EGLint
];
// Get the D3D backbuffer texture for the swap-chain let back_buffer = unsafe {
wrc_get_layer_backbuffer(layer.layer_id)
};
// Create an EGL surface <-> binding to the D3D backbuffer texture letmut egl_config = ptr::null(); letmut cfg_count = 0;
let ok = unsafe {
egl::ffi::ChooseConfig(self.display, attribs.as_ptr(), &mut egl_config, 1, &mut cfg_count)
};
unsafe {
wrc_set_layer_position(
layer.layer_id,
input.offset.x as f32,
input.offset.y as f32,
);
}
}
true
}
// Bind a layer by index for compositing into fn bind_layer(&mutself, index: usize, _dirty_rects: &['color:red'>crate::DeviceIntRect]) { // Bind the DC surface to EGL so that WR can composite to the layer let layer = &self.layers[index];
let ok = unsafe {
egl::ffi::MakeCurrent( self.display,
layer.surface,
layer.surface, self.context,
)
};
assert!(ok != 0);
}
// Finish compositing a layer and present the swapchain fn present_layer(&mutself, index: usize, _dirty_rects: &[le='color:red'>crate::DeviceIntRect]) { let layer = &self.layers[index];
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.