diff options
Diffstat (limited to 'gfx/wr/direct-composition/src/main_windows.rs')
-rw-r--r-- | gfx/wr/direct-composition/src/main_windows.rs | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/gfx/wr/direct-composition/src/main_windows.rs b/gfx/wr/direct-composition/src/main_windows.rs new file mode 100644 index 0000000000..bf06480f2a --- /dev/null +++ b/gfx/wr/direct-composition/src/main_windows.rs @@ -0,0 +1,212 @@ +/* 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 http://mozilla.org/MPL/2.0/. */ + +extern crate direct_composition; +extern crate euclid; +extern crate gleam; +extern crate webrender; +extern crate winit; + +use euclid::size2; +use direct_composition::DirectComposition; +use std::sync::mpsc; +use webrender::api; +use webrender::render_api::*; +use winit::os::windows::{WindowExt, WindowBuilderExt}; +use winit::dpi::LogicalSize; + +fn main() { + let mut events_loop = winit::EventsLoop::new(); + + let (tx, rx) = mpsc::channel(); + let notifier = Box::new(Notifier { events_proxy: events_loop.create_proxy(), tx }); + + let window = winit::WindowBuilder::new() + .with_title("WebRender + ANGLE + DirectComposition") + .with_dimensions(LogicalSize::new(1024., 768.)) + .with_decorations(true) + .with_transparency(true) + .with_no_redirection_bitmap(true) + .build(&events_loop) + .unwrap(); + + let composition = direct_composition_from_window(&window); + let factor = window.get_hidpi_factor() as f32; + + let mut clicks: usize = 0; + let mut offset_y = 100.; + let mut rects = [ + Rectangle::new(&composition, ¬ifier, factor, size2(300, 200), 0., 0.2, 0.4, 1.), + Rectangle::new(&composition, ¬ifier, factor, size2(400, 300), 0., 0.5, 0., 0.5), + ]; + rects[0].render(factor, &rx); + rects[1].render(factor, &rx); + + rects[0].visual.set_offset_x(100.); + rects[0].visual.set_offset_y(50.); + + rects[1].visual.set_offset_x(200.); + rects[1].visual.set_offset_y(offset_y); + + composition.commit(); + + events_loop.run_forever(|event| { + if let winit::Event::WindowEvent { event, .. } = event { + match event { + winit::WindowEvent::CloseRequested => { + return winit::ControlFlow::Break + } + winit::WindowEvent::MouseWheel { delta, .. } => { + let dy = match delta { + winit::MouseScrollDelta::LineDelta(_, dy) => dy, + winit::MouseScrollDelta::PixelDelta(pos) => pos.y as f32, + }; + offset_y = (offset_y - 10. * dy).max(0.).min(468.); + + rects[1].visual.set_offset_y(offset_y); + composition.commit(); + } + winit::WindowEvent::MouseInput { + button: winit::MouseButton::Left, + state: winit::ElementState::Pressed, + .. + } => { + clicks += 1; + let rect = &mut rects[clicks % 2]; + rect.color.g += 0.1; + rect.color.g %= 1.; + rect.render(factor, &rx) + } + _ => {} + } + } + winit::ControlFlow::Continue + }); +} + +fn direct_composition_from_window(window: &winit::Window) -> DirectComposition { + unsafe { + DirectComposition::new(window.get_hwnd() as _) + } +} + +struct Rectangle { + visual: direct_composition::AngleVisual, + renderer: Option<webrender::Renderer>, + api: RenderApi, + document_id: api::DocumentId, + size: api::units::DeviceIntSize, + color: api::ColorF, +} + +impl Rectangle { + fn new(composition: &DirectComposition, notifier: &Box<Notifier>, + device_pixel_ratio: f32, size: api::units::DeviceIntSize, r: f32, g: f32, b: f32, a: f32) + -> Self { + let visual = composition.create_angle_visual(size.width as u32, size.height as u32); + visual.make_current(); + + let (renderer, sender) = webrender::Renderer::new( + composition.gleam.clone(), + notifier.clone(), + webrender::RendererOptions { + clear_color: Some(api::ColorF::new(0., 0., 0., 0.)), + device_pixel_ratio, + ..webrender::RendererOptions::default() + }, + None, + ).unwrap(); + let api = sender.create_api(); + + Rectangle { + visual, + renderer: Some(renderer), + document_id: api.add_document(size), + api, + size, + color: api::ColorF { r, g, b, a }, + } + } + + fn render(&mut self, device_pixel_ratio: f32, rx: &mpsc::Receiver<()>) { + self.visual.make_current(); + + let pipeline_id = api::PipelineId(0, 0); + let layout_size = self.size.to_f32() / euclid::Scale::new(device_pixel_ratio); + let mut builder = api::DisplayListBuilder::new(pipeline_id); + + let rect = euclid::Rect::new(euclid::Point2D::zero(), layout_size); + + let region = api::ComplexClipRegion::new( + rect, + api::BorderRadius::uniform(20.), + api::ClipMode::Clip + ); + let clip_id = builder.define_clip_rounded_rect( + &api::SpaceAndClipInfo::root_scroll(pipeline_id), + region, + ); + + builder.push_rect( + &api::CommonItemProperties::new( + rect, + api::SpaceAndClipInfo { + spatial_id: api::SpatialId::root_scroll_node(pipeline_id), + clip_id, + }, + ), + rect, + self.color, + ); + + let mut transaction = Transaction::new(); + transaction.set_display_list( + api::Epoch(0), + None, + layout_size, + builder.finalize(), + true, + ); + transaction.set_root_pipeline(pipeline_id); + transaction.generate_frame(0); + self.api.send_transaction(self.document_id, transaction); + rx.recv().unwrap(); + let renderer = self.renderer.as_mut().unwrap(); + renderer.update(); + renderer.render(self.size, 0).unwrap(); + let _ = renderer.flush_pipeline_info(); + self.visual.present(); + } +} + +impl Drop for Rectangle { + fn drop(&mut self) { + self.renderer.take().unwrap().deinit() + } +} + +#[derive(Clone)] +struct Notifier { + events_proxy: winit::EventsLoopProxy, + tx: mpsc::Sender<()>, +} + +impl api::RenderNotifier for Notifier { + fn clone(&self) -> Box<dyn api::RenderNotifier> { + Box::new(Clone::clone(self)) + } + + fn wake_up(&self, _composite_needed: bool) { + self.tx.send(()).unwrap(); + let _ = self.events_proxy.wakeup(); + } + + fn new_frame_ready(&self, + _: api::DocumentId, + _: bool, + composite_needed: bool, + _: Option<u64>) { + self.wake_up(composite_needed); + } +} |