зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1615148 - Update wrench's winit and glutin dependencies. r=gw
To versions 0.26 and 0.28 respectively. The most significant change is that winit's event loop has been overhauled. poll_events() has been removed, and you are strongly encouranged to use run() instead, which takes full control of the events loop. There does exist a run_return(), however, though we are advised against using it. We have chosen to do so for now anyway to make porting easier. I have attempted to match the existing semantics as closely as possible, though there may be slight differences. This patch additionally updates the version of rust used to build wrench on CI. Due to missing support in the 0.28 crates.io version of glutin, android wrench builds no longer work following this change. This will be rectified by the next patch in this series. Differential Revision: https://phabricator.services.mozilla.com/D144417
This commit is contained in:
Родитель
14f8cafbc3
Коммит
0a0a0bb91d
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -21,13 +21,5 @@ opt-level = 2
|
||||||
[profile.release.package.glsl]
|
[profile.release.package.glsl]
|
||||||
opt-level = 2
|
opt-level = 2
|
||||||
|
|
||||||
# Running wrench on android built with master cargo-apk results in a crash
|
|
||||||
# due to a mismatched version of android_glue (a dependency of winit).
|
|
||||||
# Override it to use a suitable version of android_glue.
|
|
||||||
# See https://github.com/rust-windowing/android-rs-glue/issues/239.
|
|
||||||
# This can be removed once a new version of android_glue is published to crates.io.
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
android_glue = { git = "https://github.com/rust-windowing/android-rs-glue.git", rev = "e3ac6edea5814e1faca0c31ea8fac6877cb929ea" }
|
|
||||||
# this is a version that fixes some incompatibilites with newer rust/aarch64
|
|
||||||
winit = { version = "0.19", git = "https://github.com/jrmuizel/winit", branch="wr" }
|
|
||||||
fog = { path = "fog" }
|
fog = { path = "fog" }
|
||||||
|
|
|
@ -58,10 +58,10 @@ app_units = "0.7"
|
||||||
env_logger = "0.5"
|
env_logger = "0.5"
|
||||||
euclid = "0.22"
|
euclid = "0.22"
|
||||||
gleam = "0.13"
|
gleam = "0.13"
|
||||||
glutin = "0.21"
|
glutin = "0.28"
|
||||||
rayon = "1"
|
rayon = "1"
|
||||||
webrender = { path = "../webrender" }
|
webrender = { path = "../webrender" }
|
||||||
winit = "0.19"
|
winit = "0.26"
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
core-foundation = "0.7"
|
core-foundation = "0.7"
|
||||||
|
|
|
@ -54,25 +54,26 @@ impl Example for App {
|
||||||
|
|
||||||
fn on_event(
|
fn on_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
event: winit::WindowEvent,
|
event: winit::event::WindowEvent,
|
||||||
|
_window: &winit::window::Window,
|
||||||
_api: &mut RenderApi,
|
_api: &mut RenderApi,
|
||||||
_document_id: DocumentId
|
_document_id: DocumentId,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match event {
|
match event {
|
||||||
winit::WindowEvent::KeyboardInput {
|
winit::event::WindowEvent::KeyboardInput {
|
||||||
input: winit::KeyboardInput {
|
input: winit::event::KeyboardInput {
|
||||||
state: winit::ElementState::Pressed,
|
state: winit::event::ElementState::Pressed,
|
||||||
virtual_keycode: Some(key),
|
virtual_keycode: Some(key),
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
match key {
|
match key {
|
||||||
winit::VirtualKeyCode::Right => {
|
winit::event::VirtualKeyCode::Right => {
|
||||||
self.rect_count += 1;
|
self.rect_count += 1;
|
||||||
println!("rects = {}", self.rect_count);
|
println!("rects = {}", self.rect_count);
|
||||||
}
|
}
|
||||||
winit::VirtualKeyCode::Left => {
|
winit::event::VirtualKeyCode::Left => {
|
||||||
self.rect_count = cmp::max(self.rect_count, 1) - 1;
|
self.rect_count = cmp::max(self.rect_count, 1) - 1;
|
||||||
println!("rects = {}", self.rect_count);
|
println!("rects = {}", self.rect_count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,24 +141,30 @@ impl Example for App {
|
||||||
self.add_rounded_rect(bounds, ColorF::new(0.0, 0.0, 1.0, 0.5), builder, pipeline_id, key2, None);
|
self.add_rounded_rect(bounds, ColorF::new(0.0, 0.0, 1.0, 0.5), builder, pipeline_id, key2, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&mut self, win_event: winit::WindowEvent, api: &mut RenderApi, document_id: DocumentId) -> bool {
|
fn on_event(
|
||||||
|
&mut self,
|
||||||
|
win_event: winit::event::WindowEvent,
|
||||||
|
_window: &winit::window::Window,
|
||||||
|
api: &mut RenderApi,
|
||||||
|
document_id: DocumentId
|
||||||
|
) -> bool {
|
||||||
let mut rebuild_display_list = false;
|
let mut rebuild_display_list = false;
|
||||||
|
|
||||||
match win_event {
|
match win_event {
|
||||||
winit::WindowEvent::KeyboardInput {
|
winit::event::WindowEvent::KeyboardInput {
|
||||||
input: winit::KeyboardInput {
|
input: winit::event::KeyboardInput {
|
||||||
state: winit::ElementState::Pressed,
|
state: winit::event::ElementState::Pressed,
|
||||||
virtual_keycode: Some(key),
|
virtual_keycode: Some(key),
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let (delta_angle, delta_opacity) = match key {
|
let (delta_angle, delta_opacity) = match key {
|
||||||
winit::VirtualKeyCode::Down => (0.0, -0.1),
|
winit::event::VirtualKeyCode::Down => (0.0, -0.1),
|
||||||
winit::VirtualKeyCode::Up => (0.0, 0.1),
|
winit::event::VirtualKeyCode::Up => (0.0, 0.1),
|
||||||
winit::VirtualKeyCode::Right => (1.0, 0.0),
|
winit::event::VirtualKeyCode::Right => (1.0, 0.0),
|
||||||
winit::VirtualKeyCode::Left => (-1.0, 0.0),
|
winit::event::VirtualKeyCode::Left => (-1.0, 0.0),
|
||||||
winit::VirtualKeyCode::R => {
|
winit::event::VirtualKeyCode::R => {
|
||||||
rebuild_display_list = true;
|
rebuild_display_list = true;
|
||||||
(0.0, 0.0)
|
(0.0, 0.0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,18 @@ use std::env;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use webrender;
|
use webrender;
|
||||||
use winit;
|
use winit;
|
||||||
|
use winit::platform::run_return::EventLoopExtRunReturn;
|
||||||
use webrender::{DebugFlags, ShaderPrecacheFlags};
|
use webrender::{DebugFlags, ShaderPrecacheFlags};
|
||||||
use webrender::api::*;
|
use webrender::api::*;
|
||||||
use webrender::render_api::*;
|
use webrender::render_api::*;
|
||||||
use webrender::api::units::*;
|
use webrender::api::units::*;
|
||||||
|
|
||||||
struct Notifier {
|
struct Notifier {
|
||||||
events_proxy: winit::EventsLoopProxy,
|
events_proxy: winit::event_loop::EventLoopProxy<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Notifier {
|
impl Notifier {
|
||||||
fn new(events_proxy: winit::EventsLoopProxy) -> Notifier {
|
fn new(events_proxy: winit::event_loop::EventLoopProxy<()>) -> Notifier {
|
||||||
Notifier { events_proxy }
|
Notifier { events_proxy }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +33,7 @@ impl RenderNotifier for Notifier {
|
||||||
|
|
||||||
fn wake_up(&self, _composite_needed: bool) {
|
fn wake_up(&self, _composite_needed: bool) {
|
||||||
#[cfg(not(target_os = "android"))]
|
#[cfg(not(target_os = "android"))]
|
||||||
let _ = self.events_proxy.wakeup();
|
let _ = self.events_proxy.send_event(());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_frame_ready(&self,
|
fn new_frame_ready(&self,
|
||||||
|
@ -83,7 +84,8 @@ pub trait Example {
|
||||||
);
|
);
|
||||||
fn on_event(
|
fn on_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: winit::WindowEvent,
|
_: winit::event::WindowEvent,
|
||||||
|
_: &winit::window::Window,
|
||||||
_: &mut RenderApi,
|
_: &mut RenderApi,
|
||||||
_: DocumentId,
|
_: DocumentId,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
@ -123,11 +125,10 @@ pub fn main_wrapper<E: Example>(
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut events_loop = winit::EventsLoop::new();
|
let mut events_loop = winit::event_loop::EventLoop::new();
|
||||||
let window_builder = winit::WindowBuilder::new()
|
let window_builder = winit::window::WindowBuilder::new()
|
||||||
.with_title(E::TITLE)
|
.with_title(E::TITLE)
|
||||||
.with_multitouch()
|
.with_inner_size(winit::dpi::LogicalSize::new(E::WIDTH as f64, E::HEIGHT as f64));
|
||||||
.with_dimensions(winit::dpi::LogicalSize::new(E::WIDTH as f64, E::HEIGHT as f64));
|
|
||||||
let windowed_context = glutin::ContextBuilder::new()
|
let windowed_context = glutin::ContextBuilder::new()
|
||||||
.with_gl(glutin::GlRequest::GlThenGles {
|
.with_gl(glutin::GlRequest::GlThenGles {
|
||||||
opengl_version: (3, 2),
|
opengl_version: (3, 2),
|
||||||
|
@ -154,7 +155,7 @@ pub fn main_wrapper<E: Example>(
|
||||||
|
|
||||||
println!("OpenGL version {}", gl.get_string(gl::VERSION));
|
println!("OpenGL version {}", gl.get_string(gl::VERSION));
|
||||||
println!("Shader resource path: {:?}", res_path);
|
println!("Shader resource path: {:?}", res_path);
|
||||||
let device_pixel_ratio = windowed_context.window().get_hidpi_factor() as f32;
|
let device_pixel_ratio = windowed_context.window().scale_factor() as f32;
|
||||||
println!("Device pixel ratio: {}", device_pixel_ratio);
|
println!("Device pixel ratio: {}", device_pixel_ratio);
|
||||||
|
|
||||||
println!("Loading shaders...");
|
println!("Loading shaders...");
|
||||||
|
@ -171,9 +172,7 @@ pub fn main_wrapper<E: Example>(
|
||||||
let device_size = {
|
let device_size = {
|
||||||
let size = windowed_context
|
let size = windowed_context
|
||||||
.window()
|
.window()
|
||||||
.get_inner_size()
|
.inner_size();
|
||||||
.unwrap()
|
|
||||||
.to_physical(device_pixel_ratio as f64);
|
|
||||||
DeviceIntSize::new(size.width as i32, size.height as i32)
|
DeviceIntSize::new(size.width as i32, size.height as i32)
|
||||||
};
|
};
|
||||||
let notifier = Box::new(Notifier::new(events_loop.create_proxy()));
|
let notifier = Box::new(Notifier::new(events_loop.create_proxy()));
|
||||||
|
@ -218,48 +217,55 @@ pub fn main_wrapper<E: Example>(
|
||||||
api.send_transaction(document_id, txn);
|
api.send_transaction(document_id, txn);
|
||||||
|
|
||||||
println!("Entering event loop");
|
println!("Entering event loop");
|
||||||
events_loop.run_forever(|global_event| {
|
events_loop.run_return(|global_event, _elwt, control_flow| {
|
||||||
let mut txn = Transaction::new();
|
let mut txn = Transaction::new();
|
||||||
let mut custom_event = true;
|
let mut custom_event = true;
|
||||||
|
|
||||||
let old_flags = debug_flags;
|
let old_flags = debug_flags;
|
||||||
let win_event = match global_event {
|
let win_event = match global_event {
|
||||||
winit::Event::WindowEvent { event, .. } => event,
|
winit::event::Event::WindowEvent { event, .. } => event,
|
||||||
_ => return winit::ControlFlow::Continue,
|
_ => return,
|
||||||
};
|
};
|
||||||
match win_event {
|
match win_event {
|
||||||
winit::WindowEvent::CloseRequested => return winit::ControlFlow::Break,
|
winit::event::WindowEvent::CloseRequested => {
|
||||||
winit::WindowEvent::AxisMotion { .. } |
|
*control_flow = winit::event_loop::ControlFlow::Exit;
|
||||||
winit::WindowEvent::CursorMoved { .. } => {
|
return;
|
||||||
|
}
|
||||||
|
winit::event::WindowEvent::AxisMotion { .. } |
|
||||||
|
winit::event::WindowEvent::CursorMoved { .. } => {
|
||||||
custom_event = example.on_event(
|
custom_event = example.on_event(
|
||||||
win_event,
|
win_event,
|
||||||
&mut api,
|
windowed_context.window(),
|
||||||
document_id,
|
&mut api,
|
||||||
);
|
document_id,
|
||||||
|
);
|
||||||
// skip high-frequency events from triggering a frame draw.
|
// skip high-frequency events from triggering a frame draw.
|
||||||
if !custom_event {
|
if !custom_event {
|
||||||
return winit::ControlFlow::Continue;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
winit::WindowEvent::KeyboardInput {
|
winit::event::WindowEvent::KeyboardInput {
|
||||||
input: winit::KeyboardInput {
|
input: winit::event::KeyboardInput {
|
||||||
state: winit::ElementState::Pressed,
|
state: winit::event::ElementState::Pressed,
|
||||||
virtual_keycode: Some(key),
|
virtual_keycode: Some(key),
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
} => match key {
|
} => match key {
|
||||||
winit::VirtualKeyCode::Escape => return winit::ControlFlow::Break,
|
winit::event::VirtualKeyCode::Escape => {
|
||||||
winit::VirtualKeyCode::P => debug_flags.toggle(DebugFlags::PROFILER_DBG),
|
*control_flow = winit::event_loop::ControlFlow::Exit;
|
||||||
winit::VirtualKeyCode::O => debug_flags.toggle(DebugFlags::RENDER_TARGET_DBG),
|
return;
|
||||||
winit::VirtualKeyCode::I => debug_flags.toggle(DebugFlags::TEXTURE_CACHE_DBG),
|
}
|
||||||
winit::VirtualKeyCode::T => debug_flags.toggle(DebugFlags::PICTURE_CACHING_DBG),
|
winit::event::VirtualKeyCode::P => debug_flags.toggle(DebugFlags::PROFILER_DBG),
|
||||||
winit::VirtualKeyCode::Q => debug_flags.toggle(
|
winit::event::VirtualKeyCode::O => debug_flags.toggle(DebugFlags::RENDER_TARGET_DBG),
|
||||||
|
winit::event::VirtualKeyCode::I => debug_flags.toggle(DebugFlags::TEXTURE_CACHE_DBG),
|
||||||
|
winit::event::VirtualKeyCode::T => debug_flags.toggle(DebugFlags::PICTURE_CACHING_DBG),
|
||||||
|
winit::event::VirtualKeyCode::Q => debug_flags.toggle(
|
||||||
DebugFlags::GPU_TIME_QUERIES | DebugFlags::GPU_SAMPLE_QUERIES
|
DebugFlags::GPU_TIME_QUERIES | DebugFlags::GPU_SAMPLE_QUERIES
|
||||||
),
|
),
|
||||||
winit::VirtualKeyCode::G => debug_flags.toggle(DebugFlags::GPU_CACHE_DBG),
|
winit::event::VirtualKeyCode::G => debug_flags.toggle(DebugFlags::GPU_CACHE_DBG),
|
||||||
winit::VirtualKeyCode::M => api.notify_memory_pressure(),
|
winit::event::VirtualKeyCode::M => api.notify_memory_pressure(),
|
||||||
winit::VirtualKeyCode::C => {
|
winit::event::VirtualKeyCode::C => {
|
||||||
let path: PathBuf = "../captures/example".into();
|
let path: PathBuf = "../captures/example".into();
|
||||||
//TODO: switch between SCENE/FRAME capture types
|
//TODO: switch between SCENE/FRAME capture types
|
||||||
// based on "shift" modifier, when `glutin` is updated.
|
// based on "shift" modifier, when `glutin` is updated.
|
||||||
|
@ -269,6 +275,7 @@ pub fn main_wrapper<E: Example>(
|
||||||
_ => {
|
_ => {
|
||||||
custom_event = example.on_event(
|
custom_event = example.on_event(
|
||||||
win_event,
|
win_event,
|
||||||
|
windowed_context.window(),
|
||||||
&mut api,
|
&mut api,
|
||||||
document_id,
|
document_id,
|
||||||
)
|
)
|
||||||
|
@ -276,6 +283,7 @@ pub fn main_wrapper<E: Example>(
|
||||||
},
|
},
|
||||||
other => custom_event = example.on_event(
|
other => custom_event = example.on_event(
|
||||||
other,
|
other,
|
||||||
|
windowed_context.window(),
|
||||||
&mut api,
|
&mut api,
|
||||||
document_id,
|
document_id,
|
||||||
),
|
),
|
||||||
|
@ -313,7 +321,7 @@ pub fn main_wrapper<E: Example>(
|
||||||
example.draw_custom(&*gl);
|
example.draw_custom(&*gl);
|
||||||
windowed_context.swap_buffers().ok();
|
windowed_context.swap_buffers().ok();
|
||||||
|
|
||||||
winit::ControlFlow::Continue
|
*control_flow = winit::event_loop::ControlFlow::Wait;
|
||||||
});
|
});
|
||||||
|
|
||||||
renderer.deinit();
|
renderer.deinit();
|
||||||
|
|
|
@ -77,12 +77,18 @@ impl Example for App {
|
||||||
builder.pop_stacking_context();
|
builder.pop_stacking_context();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&mut self, event: winit::WindowEvent, api: &mut RenderApi, document_id: DocumentId) -> bool {
|
fn on_event(
|
||||||
|
&mut self,
|
||||||
|
event: winit::event::WindowEvent,
|
||||||
|
_window: &winit::window::Window,
|
||||||
|
api: &mut RenderApi,
|
||||||
|
document_id: DocumentId,
|
||||||
|
) -> bool {
|
||||||
match event {
|
match event {
|
||||||
winit::WindowEvent::KeyboardInput {
|
winit::event::WindowEvent::KeyboardInput {
|
||||||
input: winit::KeyboardInput {
|
input: winit::event::KeyboardInput {
|
||||||
state: winit::ElementState::Pressed,
|
state: winit::event::ElementState::Pressed,
|
||||||
virtual_keycode: Some(winit::VirtualKeyCode::Space),
|
virtual_keycode: Some(winit::event::VirtualKeyCode::Space),
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
|
|
|
@ -17,13 +17,14 @@ use webrender::api::units::*;
|
||||||
use webrender::render_api::*;
|
use webrender::render_api::*;
|
||||||
use webrender::DebugFlags;
|
use webrender::DebugFlags;
|
||||||
use winit::dpi::LogicalSize;
|
use winit::dpi::LogicalSize;
|
||||||
|
use winit::platform::run_return::EventLoopExtRunReturn;
|
||||||
|
|
||||||
struct Notifier {
|
struct Notifier {
|
||||||
events_proxy: winit::EventsLoopProxy,
|
events_proxy: winit::event_loop::EventLoopProxy<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Notifier {
|
impl Notifier {
|
||||||
fn new(events_proxy: winit::EventsLoopProxy) -> Notifier {
|
fn new(events_proxy: winit::event_loop::EventLoopProxy<()>) -> Notifier {
|
||||||
Notifier { events_proxy }
|
Notifier { events_proxy }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +38,7 @@ impl RenderNotifier for Notifier {
|
||||||
|
|
||||||
fn wake_up(&self, _composite_needed: bool) {
|
fn wake_up(&self, _composite_needed: bool) {
|
||||||
#[cfg(not(target_os = "android"))]
|
#[cfg(not(target_os = "android"))]
|
||||||
let _ = self.events_proxy.wakeup();
|
let _ = self.events_proxy.send_event(());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_frame_ready(&self,
|
fn new_frame_ready(&self,
|
||||||
|
@ -50,7 +51,7 @@ impl RenderNotifier for Notifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Window {
|
struct Window {
|
||||||
events_loop: winit::EventsLoop, //TODO: share events loop?
|
events_loop: winit::event_loop::EventLoop<()>, //TODO: share events loop?
|
||||||
context: Option<glutin::WindowedContext<NotCurrent>>,
|
context: Option<glutin::WindowedContext<NotCurrent>>,
|
||||||
renderer: webrender::Renderer,
|
renderer: webrender::Renderer,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
|
@ -63,11 +64,10 @@ struct Window {
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
fn new(name: &'static str, clear_color: ColorF) -> Self {
|
fn new(name: &'static str, clear_color: ColorF) -> Self {
|
||||||
let events_loop = winit::EventsLoop::new();
|
let events_loop = winit::event_loop::EventLoop::new();
|
||||||
let window_builder = winit::WindowBuilder::new()
|
let window_builder = winit::window::WindowBuilder::new()
|
||||||
.with_title(name)
|
.with_title(name)
|
||||||
.with_multitouch()
|
.with_inner_size(LogicalSize::new(800. as f64, 600. as f64));
|
||||||
.with_dimensions(LogicalSize::new(800., 600.));
|
|
||||||
let context = glutin::ContextBuilder::new()
|
let context = glutin::ContextBuilder::new()
|
||||||
.with_gl(glutin::GlRequest::GlThenGles {
|
.with_gl(glutin::GlRequest::GlThenGles {
|
||||||
opengl_version: (3, 2),
|
opengl_version: (3, 2),
|
||||||
|
@ -88,8 +88,6 @@ impl Window {
|
||||||
glutin::Api::WebGl => unimplemented!(),
|
glutin::Api::WebGl => unimplemented!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let device_pixel_ratio = context.window().get_hidpi_factor() as f32;
|
|
||||||
|
|
||||||
let opts = webrender::RendererOptions {
|
let opts = webrender::RendererOptions {
|
||||||
clear_color,
|
clear_color,
|
||||||
..webrender::RendererOptions::default()
|
..webrender::RendererOptions::default()
|
||||||
|
@ -98,9 +96,7 @@ impl Window {
|
||||||
let device_size = {
|
let device_size = {
|
||||||
let size = context
|
let size = context
|
||||||
.window()
|
.window()
|
||||||
.get_inner_size()
|
.inner_size();
|
||||||
.unwrap()
|
|
||||||
.to_physical(device_pixel_ratio as f64);
|
|
||||||
DeviceIntSize::new(size.width as i32, size.height as i32)
|
DeviceIntSize::new(size.width as i32, size.height as i32)
|
||||||
};
|
};
|
||||||
let notifier = Box::new(Notifier::new(events_loop.create_proxy()));
|
let notifier = Box::new(Notifier::new(events_loop.create_proxy()));
|
||||||
|
@ -140,45 +136,46 @@ impl Window {
|
||||||
let renderer = &mut self.renderer;
|
let renderer = &mut self.renderer;
|
||||||
let api = &mut self.api;
|
let api = &mut self.api;
|
||||||
|
|
||||||
self.events_loop.poll_events(|global_event| match global_event {
|
self.events_loop.run_return(|global_event, _elwt, control_flow| {
|
||||||
winit::Event::WindowEvent { event, .. } => match event {
|
*control_flow = winit::event_loop::ControlFlow::Exit;
|
||||||
winit::WindowEvent::CloseRequested |
|
match global_event {
|
||||||
winit::WindowEvent::KeyboardInput {
|
winit::event::Event::WindowEvent { event, .. } => match event {
|
||||||
input: winit::KeyboardInput {
|
winit::event::WindowEvent::CloseRequested |
|
||||||
virtual_keycode: Some(winit::VirtualKeyCode::Escape),
|
winit::event::WindowEvent::KeyboardInput {
|
||||||
|
input: winit::event::KeyboardInput {
|
||||||
|
virtual_keycode: Some(winit::event::VirtualKeyCode::Escape),
|
||||||
|
..
|
||||||
|
},
|
||||||
..
|
..
|
||||||
},
|
} => {
|
||||||
..
|
do_exit = true
|
||||||
} => {
|
}
|
||||||
do_exit = true
|
winit::event::WindowEvent::KeyboardInput {
|
||||||
}
|
input: winit::event::KeyboardInput {
|
||||||
winit::WindowEvent::KeyboardInput {
|
state: winit::event::ElementState::Pressed,
|
||||||
input: winit::KeyboardInput {
|
virtual_keycode: Some(winit::event::VirtualKeyCode::P),
|
||||||
state: winit::ElementState::Pressed,
|
..
|
||||||
virtual_keycode: Some(winit::VirtualKeyCode::P),
|
},
|
||||||
..
|
..
|
||||||
},
|
} => {
|
||||||
..
|
println!("set flags {}", my_name);
|
||||||
} => {
|
api.send_debug_cmd(DebugCommand::SetFlags(DebugFlags::PROFILER_DBG))
|
||||||
println!("set flags {}", my_name);
|
}
|
||||||
api.send_debug_cmd(DebugCommand::SetFlags(DebugFlags::PROFILER_DBG))
|
_ => {}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
});
|
});
|
||||||
if do_exit {
|
if do_exit {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
let context = unsafe { self.context.take().unwrap().make_current().unwrap() };
|
let context = unsafe { self.context.take().unwrap().make_current().unwrap() };
|
||||||
let device_pixel_ratio = context.window().get_hidpi_factor() as f32;
|
let device_pixel_ratio = context.window().scale_factor() as f32;
|
||||||
let device_size = {
|
let device_size = {
|
||||||
let size = context
|
let size = context
|
||||||
.window()
|
.window()
|
||||||
.get_inner_size()
|
.inner_size();
|
||||||
.unwrap()
|
|
||||||
.to_physical(device_pixel_ratio as f64);
|
|
||||||
DeviceIntSize::new(size.width as i32, size.height as i32)
|
DeviceIntSize::new(size.width as i32, size.height as i32)
|
||||||
};
|
};
|
||||||
let layout_size = device_size.to_f32() / euclid::Scale::new(device_pixel_ratio);
|
let layout_size = device_size.to_f32() / euclid::Scale::new(device_pixel_ratio);
|
||||||
|
|
|
@ -165,22 +165,28 @@ impl Example for App {
|
||||||
builder.pop_stacking_context();
|
builder.pop_stacking_context();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&mut self, event: winit::WindowEvent, api: &mut RenderApi, document_id: DocumentId) -> bool {
|
fn on_event(
|
||||||
|
&mut self,
|
||||||
|
event: winit::event::WindowEvent,
|
||||||
|
window: &winit::window::Window,
|
||||||
|
api: &mut RenderApi,
|
||||||
|
document_id: DocumentId,
|
||||||
|
) -> bool {
|
||||||
let mut txn = Transaction::new();
|
let mut txn = Transaction::new();
|
||||||
match event {
|
match event {
|
||||||
winit::WindowEvent::KeyboardInput {
|
winit::event::WindowEvent::KeyboardInput {
|
||||||
input: winit::KeyboardInput {
|
input: winit::event::KeyboardInput {
|
||||||
state: winit::ElementState::Pressed,
|
state: winit::event::ElementState::Pressed,
|
||||||
virtual_keycode: Some(key),
|
virtual_keycode: Some(key),
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let offset = match key {
|
let offset = match key {
|
||||||
winit::VirtualKeyCode::Down => Some(LayoutVector2D::new(0.0, -10.0)),
|
winit::event::VirtualKeyCode::Down => Some(LayoutVector2D::new(0.0, -10.0)),
|
||||||
winit::VirtualKeyCode::Up => Some(LayoutVector2D::new(0.0, 10.0)),
|
winit::event::VirtualKeyCode::Up => Some(LayoutVector2D::new(0.0, 10.0)),
|
||||||
winit::VirtualKeyCode::Right => Some(LayoutVector2D::new(-10.0, 0.0)),
|
winit::event::VirtualKeyCode::Right => Some(LayoutVector2D::new(-10.0, 0.0)),
|
||||||
winit::VirtualKeyCode::Left => Some(LayoutVector2D::new(10.0, 0.0)),
|
winit::event::VirtualKeyCode::Left => Some(LayoutVector2D::new(10.0, 0.0)),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -197,14 +203,15 @@ impl Example for App {
|
||||||
txn.generate_frame(0, RenderReasons::empty());
|
txn.generate_frame(0, RenderReasons::empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
winit::WindowEvent::CursorMoved { position: LogicalPosition { x, y }, .. } => {
|
winit::event::WindowEvent::CursorMoved { position, .. } => {
|
||||||
self.cursor_position = WorldPoint::new(x as f32, y as f32);
|
let pos: LogicalPosition<f32> = position.to_logical(window.scale_factor());
|
||||||
|
self.cursor_position = WorldPoint::new(pos.x, pos.y);
|
||||||
}
|
}
|
||||||
winit::WindowEvent::MouseWheel { delta, .. } => {
|
winit::event::WindowEvent::MouseWheel { delta, .. } => {
|
||||||
const LINE_HEIGHT: f32 = 38.0;
|
const LINE_HEIGHT: f32 = 38.0;
|
||||||
let (dx, dy) = match delta {
|
let (dx, dy) = match delta {
|
||||||
winit::MouseScrollDelta::LineDelta(dx, dy) => (dx, dy * LINE_HEIGHT),
|
winit::event::MouseScrollDelta::LineDelta(dx, dy) => (dx, dy * LINE_HEIGHT),
|
||||||
winit::MouseScrollDelta::PixelDelta(pos) => (pos.x as f32, pos.y as f32),
|
winit::event::MouseScrollDelta::PixelDelta(pos) => (pos.x as f32, pos.y as f32),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.scroll_offset += LayoutVector2D::new(dx, dy);
|
self.scroll_offset += LayoutVector2D::new(dx, dy);
|
||||||
|
@ -219,7 +226,7 @@ impl Example for App {
|
||||||
|
|
||||||
txn.generate_frame(0, RenderReasons::empty());
|
txn.generate_frame(0, RenderReasons::empty());
|
||||||
}
|
}
|
||||||
winit::WindowEvent::MouseInput { .. } => {
|
winit::event::WindowEvent::MouseInput { .. } => {
|
||||||
let results = api.hit_test(
|
let results = api.hit_test(
|
||||||
document_id,
|
document_id,
|
||||||
self.cursor_position,
|
self.cursor_position,
|
||||||
|
|
|
@ -192,14 +192,15 @@ impl Example for App {
|
||||||
|
|
||||||
fn on_event(
|
fn on_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
event: winit::WindowEvent,
|
event: winit::event::WindowEvent,
|
||||||
|
_window: &winit::window::Window,
|
||||||
api: &mut RenderApi,
|
api: &mut RenderApi,
|
||||||
document_id: DocumentId,
|
document_id: DocumentId,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match event {
|
match event {
|
||||||
winit::WindowEvent::KeyboardInput {
|
winit::event::WindowEvent::KeyboardInput {
|
||||||
input: winit::KeyboardInput {
|
input: winit::event::KeyboardInput {
|
||||||
state: winit::ElementState::Pressed,
|
state: winit::event::ElementState::Pressed,
|
||||||
virtual_keycode: Some(key),
|
virtual_keycode: Some(key),
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
|
@ -208,7 +209,7 @@ impl Example for App {
|
||||||
let mut txn = Transaction::new();
|
let mut txn = Transaction::new();
|
||||||
|
|
||||||
match key {
|
match key {
|
||||||
winit::VirtualKeyCode::S => {
|
winit::event::VirtualKeyCode::S => {
|
||||||
self.stress_keys.clear();
|
self.stress_keys.clear();
|
||||||
|
|
||||||
for _ in 0 .. 16 {
|
for _ in 0 .. 16 {
|
||||||
|
@ -235,10 +236,10 @@ impl Example for App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
winit::VirtualKeyCode::D => if let Some(image_key) = self.image_key.take() {
|
winit::event::VirtualKeyCode::D => if let Some(image_key) = self.image_key.take() {
|
||||||
txn.delete_image(image_key);
|
txn.delete_image(image_key);
|
||||||
},
|
},
|
||||||
winit::VirtualKeyCode::U => if let Some(image_key) = self.image_key {
|
winit::event::VirtualKeyCode::U => if let Some(image_key) = self.image_key {
|
||||||
let size = 128;
|
let size = 128;
|
||||||
self.image_generator.generate_image(size);
|
self.image_generator.generate_image(size);
|
||||||
|
|
||||||
|
@ -249,7 +250,7 @@ impl Example for App {
|
||||||
&DirtyRect::All,
|
&DirtyRect::All,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
winit::VirtualKeyCode::E => {
|
winit::event::VirtualKeyCode::E => {
|
||||||
if let Some(image_key) = self.image_key.take() {
|
if let Some(image_key) = self.image_key.take() {
|
||||||
txn.delete_image(image_key);
|
txn.delete_image(image_key);
|
||||||
}
|
}
|
||||||
|
@ -272,7 +273,7 @@ impl Example for App {
|
||||||
|
|
||||||
self.image_key = Some(image_key);
|
self.image_key = Some(image_key);
|
||||||
}
|
}
|
||||||
winit::VirtualKeyCode::R => {
|
winit::event::VirtualKeyCode::R => {
|
||||||
if let Some(image_key) = self.image_key.take() {
|
if let Some(image_key) = self.image_key.take() {
|
||||||
txn.delete_image(image_key);
|
txn.delete_image(image_key);
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,7 +189,8 @@ impl Example for App {
|
||||||
|
|
||||||
fn on_event(
|
fn on_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
_event: winit::WindowEvent,
|
_event: winit::event::WindowEvent,
|
||||||
|
_window: &winit::window::Window,
|
||||||
_api: &mut RenderApi,
|
_api: &mut RenderApi,
|
||||||
_document_id: DocumentId,
|
_document_id: DocumentId,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
|
|
@ -11,17 +11,15 @@ packages = [
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"core-graphics",
|
"core-graphics",
|
||||||
"gl_generator",
|
"gl_generator",
|
||||||
"gleam",
|
# glsl requires 5.1, and xcursor (required by winit) requires 7.1.
|
||||||
|
# when a version of glsl depending on 7.1 is published we can update.
|
||||||
|
"nom",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
# https://github.com/trimental/andrew/issues/5
|
# Can be fixed by updating clap dependency - see bug 1765326
|
||||||
"rusttype",
|
"strsim",
|
||||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1615148
|
|
||||||
"smallvec",
|
|
||||||
"yaml-rust",
|
"yaml-rust",
|
||||||
# These are tracked in bug 1587468, see there for pending work.
|
# Can be fixed by removing time dependency - see bug 1765324
|
||||||
"proc-macro2",
|
"wasi",
|
||||||
"quote",
|
|
||||||
"unicode-xid",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# Files that are ignored for all tidy and lint checks.
|
# Files that are ignored for all tidy and lint checks.
|
||||||
|
|
|
@ -10,7 +10,7 @@ edition = "2018"
|
||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
env_logger = { version = "0.5", optional = true }
|
env_logger = { version = "0.5", optional = true }
|
||||||
gleam = "0.13"
|
gleam = "0.13"
|
||||||
glutin = "0.21"
|
glutin = "0.28"
|
||||||
clap = { version = "2", features = ["yaml"] }
|
clap = { version = "2", features = ["yaml"] }
|
||||||
glsl = "4.0"
|
glsl = "4.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
@ -22,7 +22,7 @@ crossbeam = "0.2"
|
||||||
osmesa-sys = { version = "0.1.2", optional = true }
|
osmesa-sys = { version = "0.1.2", optional = true }
|
||||||
osmesa-src = { version = "0.2", git = "https://github.com/servo/osmesa-src", optional = true }
|
osmesa-src = { version = "0.2", git = "https://github.com/servo/osmesa-src", optional = true }
|
||||||
webrender = { path = "../webrender", features = ["capture", "replay", "png", "profiler", "no_static_freetype", "leak_checks"] }
|
webrender = { path = "../webrender", features = ["capture", "replay", "png", "profiler", "no_static_freetype", "leak_checks"] }
|
||||||
winit = "0.19"
|
winit = "0.26"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
semver = "0.9.0"
|
semver = "0.9.0"
|
||||||
swgl = { path = "../swgl", optional = true }
|
swgl = { path = "../swgl", optional = true }
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use glutin::{self, ContextBuilder, ContextCurrentState, CreationError};
|
use glutin::{self, ContextBuilder, ContextCurrentState, CreationError};
|
||||||
use winit::{EventsLoop, Window, WindowBuilder};
|
use winit::{event_loop::EventLoop, window::Window, window::WindowBuilder};
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
pub enum Context {}
|
pub enum Context {}
|
||||||
|
@ -16,7 +16,7 @@ impl Context {
|
||||||
pub fn with_window<T: ContextCurrentState>(
|
pub fn with_window<T: ContextCurrentState>(
|
||||||
_: WindowBuilder,
|
_: WindowBuilder,
|
||||||
_: ContextBuilder<'_, T>,
|
_: ContextBuilder<'_, T>,
|
||||||
_: &EventsLoop,
|
_: &EventLoop<()>,
|
||||||
) -> Result<(Window, Self), CreationError> {
|
) -> Result<(Window, Self), CreationError> {
|
||||||
Err(CreationError::PlatformSpecific(
|
Err(CreationError::PlatformSpecific(
|
||||||
"ANGLE rendering is only supported on Windows".into(),
|
"ANGLE rendering is only supported on Windows".into(),
|
||||||
|
@ -27,16 +27,16 @@ impl Context {
|
||||||
pub fn with_window<T: ContextCurrentState>(
|
pub fn with_window<T: ContextCurrentState>(
|
||||||
window_builder: WindowBuilder,
|
window_builder: WindowBuilder,
|
||||||
context_builder: ContextBuilder<'_, T>,
|
context_builder: ContextBuilder<'_, T>,
|
||||||
events_loop: &EventsLoop,
|
events_loop: &EventLoop<()>,
|
||||||
) -> Result<(Window, Self), CreationError> {
|
) -> Result<(Window, Self), CreationError> {
|
||||||
use winit::os::windows::WindowExt;
|
use winit::platform::windows::WindowExtWindows;
|
||||||
|
|
||||||
// FIXME: &context_builder.pf_reqs https://github.com/tomaka/glutin/pull/1002
|
// FIXME: &context_builder.pf_reqs https://github.com/tomaka/glutin/pull/1002
|
||||||
let pf_reqs = &glutin::PixelFormatRequirements::default();
|
let pf_reqs = &glutin::PixelFormatRequirements::default();
|
||||||
let gl_attr = &context_builder.gl_attr.map_sharing(|_| unimplemented!());
|
let gl_attr = &context_builder.gl_attr.map_sharing(|_| unimplemented!());
|
||||||
let window = window_builder.build(events_loop)?;
|
let window = window_builder.build(events_loop)?;
|
||||||
Self::new(pf_reqs, gl_attr)
|
Self::new(pf_reqs, gl_attr)
|
||||||
.and_then(|p| p.finish(window.get_hwnd() as _))
|
.and_then(|p| p.finish(window.hwnd() as _))
|
||||||
.map(|context| (window, context))
|
.map(|context| (window, context))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ use gleam::gl;
|
||||||
#[cfg(feature = "software")]
|
#[cfg(feature = "software")]
|
||||||
use gleam::gl::Gl;
|
use gleam::gl::Gl;
|
||||||
use crate::perf::PerfHarness;
|
use crate::perf::PerfHarness;
|
||||||
use crate::png::save_flipped;
|
|
||||||
use crate::rawtest::RawtestHarness;
|
use crate::rawtest::RawtestHarness;
|
||||||
use crate::reftest::{ReftestHarness, ReftestOptions};
|
use crate::reftest::{ReftestHarness, ReftestOptions};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
@ -51,7 +50,8 @@ use webrender::api::*;
|
||||||
use webrender::render_api::*;
|
use webrender::render_api::*;
|
||||||
use webrender::api::units::*;
|
use webrender::api::units::*;
|
||||||
use winit::dpi::{LogicalPosition, LogicalSize};
|
use winit::dpi::{LogicalPosition, LogicalSize};
|
||||||
use winit::VirtualKeyCode;
|
use winit::event::VirtualKeyCode;
|
||||||
|
use winit::platform::run_return::EventLoopExtRunReturn;
|
||||||
use crate::wrench::{CapturedSequence, Wrench, WrenchThing};
|
use crate::wrench::{CapturedSequence, Wrench, WrenchThing};
|
||||||
use crate::yaml_frame_reader::YamlFrameReader;
|
use crate::yaml_frame_reader::YamlFrameReader;
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ mod swgl {
|
||||||
|
|
||||||
pub enum WindowWrapper {
|
pub enum WindowWrapper {
|
||||||
WindowedContext(glutin::WindowedContext<glutin::PossiblyCurrent>, Rc<dyn gl::Gl>, Option<swgl::Context>),
|
WindowedContext(glutin::WindowedContext<glutin::PossiblyCurrent>, Rc<dyn gl::Gl>, Option<swgl::Context>),
|
||||||
Angle(winit::Window, angle::Context, Rc<dyn gl::Gl>, Option<swgl::Context>),
|
Angle(winit::window::Window, angle::Context, Rc<dyn gl::Gl>, Option<swgl::Context>),
|
||||||
Headless(HeadlessContext, Rc<dyn gl::Gl>, Option<swgl::Context>),
|
Headless(HeadlessContext, Rc<dyn gl::Gl>, Option<swgl::Context>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,11 +184,8 @@ impl WindowWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_inner_size(&self) -> DeviceIntSize {
|
fn get_inner_size(&self) -> DeviceIntSize {
|
||||||
fn inner_size(window: &winit::Window) -> DeviceIntSize {
|
fn inner_size(window: &winit::window::Window) -> DeviceIntSize {
|
||||||
let size = window
|
let size = window.inner_size();
|
||||||
.get_inner_size()
|
|
||||||
.unwrap()
|
|
||||||
.to_physical(window.get_hidpi_factor());
|
|
||||||
DeviceIntSize::new(size.width as i32, size.height as i32)
|
DeviceIntSize::new(size.width as i32, size.height as i32)
|
||||||
}
|
}
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -203,9 +200,9 @@ impl WindowWrapper {
|
||||||
fn hidpi_factor(&self) -> f32 {
|
fn hidpi_factor(&self) -> f32 {
|
||||||
match *self {
|
match *self {
|
||||||
WindowWrapper::WindowedContext(ref windowed_context, ..) => {
|
WindowWrapper::WindowedContext(ref windowed_context, ..) => {
|
||||||
windowed_context.window().get_hidpi_factor() as f32
|
windowed_context.window().scale_factor() as f32
|
||||||
}
|
}
|
||||||
WindowWrapper::Angle(ref window, ..) => window.get_hidpi_factor() as f32,
|
WindowWrapper::Angle(ref window, ..) => window.scale_factor() as f32,
|
||||||
WindowWrapper::Headless(..) => 1.0,
|
WindowWrapper::Headless(..) => 1.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -317,7 +314,7 @@ fn make_software_context() -> swgl::Context {
|
||||||
fn make_window(
|
fn make_window(
|
||||||
size: DeviceIntSize,
|
size: DeviceIntSize,
|
||||||
vsync: bool,
|
vsync: bool,
|
||||||
events_loop: &Option<winit::EventsLoop>,
|
events_loop: &Option<winit::event_loop::EventLoop<()>>,
|
||||||
angle: bool,
|
angle: bool,
|
||||||
gl_request: glutin::GlRequest,
|
gl_request: glutin::GlRequest,
|
||||||
software: bool,
|
software: bool,
|
||||||
|
@ -332,10 +329,10 @@ fn make_window(
|
||||||
let context_builder = glutin::ContextBuilder::new()
|
let context_builder = glutin::ContextBuilder::new()
|
||||||
.with_gl(gl_request)
|
.with_gl(gl_request)
|
||||||
.with_vsync(vsync);
|
.with_vsync(vsync);
|
||||||
let window_builder = winit::WindowBuilder::new()
|
|
||||||
|
let window_builder = winit::window::WindowBuilder::new()
|
||||||
.with_title("WRench")
|
.with_title("WRench")
|
||||||
.with_multitouch()
|
.with_inner_size(LogicalSize::new(size.width as f64, size.height as f64));
|
||||||
.with_dimensions(LogicalSize::new(size.width as f64, size.height as f64));
|
|
||||||
|
|
||||||
if angle {
|
if angle {
|
||||||
angle::Context::with_window(
|
angle::Context::with_window(
|
||||||
|
@ -602,7 +599,7 @@ fn main() {
|
||||||
let mut events_loop = if args.is_present("headless") {
|
let mut events_loop = if args.is_present("headless") {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(winit::EventsLoop::new())
|
Some(winit::event_loop::EventLoop::new())
|
||||||
};
|
};
|
||||||
|
|
||||||
let gl_request = match args.value_of("renderer") {
|
let gl_request = match args.value_of("renderer") {
|
||||||
|
@ -681,8 +678,7 @@ fn main() {
|
||||||
render(
|
render(
|
||||||
&mut wrench,
|
&mut wrench,
|
||||||
&mut window,
|
&mut window,
|
||||||
size,
|
events_loop.as_mut().expect("`wrench show` is not supported in headless mode"),
|
||||||
&mut events_loop,
|
|
||||||
subargs,
|
subargs,
|
||||||
no_block,
|
no_block,
|
||||||
no_batch,
|
no_batch,
|
||||||
|
@ -766,8 +762,7 @@ fn main() {
|
||||||
fn render<'a>(
|
fn render<'a>(
|
||||||
wrench: &mut Wrench,
|
wrench: &mut Wrench,
|
||||||
window: &mut WindowWrapper,
|
window: &mut WindowWrapper,
|
||||||
size: DeviceIntSize,
|
events_loop: &mut winit::event_loop::EventLoop<()>,
|
||||||
events_loop: &mut Option<winit::EventsLoop>,
|
|
||||||
subargs: &clap::ArgMatches<'a>,
|
subargs: &clap::ArgMatches<'a>,
|
||||||
no_block: bool,
|
no_block: bool,
|
||||||
no_batch: bool,
|
no_batch: bool,
|
||||||
|
@ -798,10 +793,6 @@ fn render<'a>(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut show_help = false;
|
|
||||||
let mut do_loop = false;
|
|
||||||
let mut cursor_position = WorldPoint::zero();
|
|
||||||
|
|
||||||
window.update(wrench);
|
window.update(wrench);
|
||||||
thing.do_frame(wrench);
|
thing.do_frame(wrench);
|
||||||
|
|
||||||
|
@ -818,197 +809,178 @@ fn render<'a>(
|
||||||
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut body = |wrench: &mut Wrench, events: Vec<winit::Event>| {
|
let mut show_help = false;
|
||||||
let mut do_frame = false;
|
let mut do_loop = false;
|
||||||
let mut do_render = !events.is_empty();
|
let mut cursor_position = WorldPoint::zero();
|
||||||
|
let mut do_render = false;
|
||||||
|
let mut do_frame = false;
|
||||||
|
|
||||||
for event in events {
|
events_loop.run_return(|event, _elwt, control_flow| {
|
||||||
match event {
|
// By default after each iteration of the event loop we block the thread until the next
|
||||||
winit::Event::Awakened => {}
|
// events arrive. --no-block can be used to run the event loop as quickly as possible.
|
||||||
winit::Event::WindowEvent { event, .. } => match event {
|
// On Android, we are generally profiling when running wrench, and don't want to block
|
||||||
winit::WindowEvent::CloseRequested => {
|
// on UI events.
|
||||||
return winit::ControlFlow::Break;
|
if !no_block && cfg!(not(target_os = "android")) {
|
||||||
}
|
*control_flow = winit::event_loop::ControlFlow::Wait;
|
||||||
winit::WindowEvent::Refresh |
|
} else {
|
||||||
winit::WindowEvent::Focused(..) => {}
|
*control_flow = winit::event_loop::ControlFlow::Poll;
|
||||||
winit::WindowEvent::CursorMoved { position: LogicalPosition { x, y }, .. } => {
|
}
|
||||||
cursor_position = WorldPoint::new(x as f32, y as f32);
|
|
||||||
wrench.renderer.set_cursor_position(
|
match event {
|
||||||
DeviceIntPoint::new(
|
winit::event::Event::UserEvent(_) => {
|
||||||
cursor_position.x.round() as i32,
|
do_render = true;
|
||||||
cursor_position.y.round() as i32,
|
}
|
||||||
),
|
winit::event::Event::WindowEvent { event, .. } => match event {
|
||||||
);
|
winit::event::WindowEvent::CloseRequested => {
|
||||||
}
|
*control_flow = winit::event_loop::ControlFlow::Exit;
|
||||||
winit::WindowEvent::KeyboardInput {
|
}
|
||||||
input: winit::KeyboardInput {
|
winit::event::WindowEvent::Focused(..) => do_render = true,
|
||||||
state: winit::ElementState::Pressed,
|
winit::event::WindowEvent::CursorMoved { position, .. } => {
|
||||||
virtual_keycode: Some(vk),
|
let pos: LogicalPosition<f32> = position.to_logical(window.hidpi_factor() as f64);
|
||||||
..
|
cursor_position = WorldPoint::new(pos.x, pos.y);
|
||||||
},
|
wrench.renderer.set_cursor_position(
|
||||||
|
DeviceIntPoint::new(
|
||||||
|
cursor_position.x.round() as i32,
|
||||||
|
cursor_position.y.round() as i32,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
do_render = true;
|
||||||
|
}
|
||||||
|
winit::event::WindowEvent::KeyboardInput {
|
||||||
|
input: winit::event::KeyboardInput {
|
||||||
|
state: winit::event::ElementState::Pressed,
|
||||||
|
virtual_keycode: Some(vk),
|
||||||
..
|
..
|
||||||
} => match vk {
|
},
|
||||||
VirtualKeyCode::Escape => {
|
..
|
||||||
return winit::ControlFlow::Break;
|
} => match vk {
|
||||||
}
|
VirtualKeyCode::Escape => {
|
||||||
VirtualKeyCode::B => {
|
*control_flow = winit::event_loop::ControlFlow::Exit;
|
||||||
debug_flags.toggle(DebugFlags::INVALIDATION_DBG);
|
|
||||||
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
|
||||||
}
|
|
||||||
VirtualKeyCode::P => {
|
|
||||||
debug_flags.toggle(DebugFlags::PROFILER_DBG);
|
|
||||||
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
|
||||||
}
|
|
||||||
VirtualKeyCode::O => {
|
|
||||||
debug_flags.toggle(DebugFlags::RENDER_TARGET_DBG);
|
|
||||||
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
|
||||||
}
|
|
||||||
VirtualKeyCode::I => {
|
|
||||||
debug_flags.toggle(DebugFlags::TEXTURE_CACHE_DBG);
|
|
||||||
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
|
||||||
}
|
|
||||||
VirtualKeyCode::D => {
|
|
||||||
debug_flags.toggle(DebugFlags::PICTURE_CACHING_DBG);
|
|
||||||
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
|
||||||
}
|
|
||||||
VirtualKeyCode::Q => {
|
|
||||||
debug_flags.toggle(DebugFlags::GPU_TIME_QUERIES | DebugFlags::GPU_SAMPLE_QUERIES);
|
|
||||||
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
|
||||||
}
|
|
||||||
VirtualKeyCode::V => {
|
|
||||||
debug_flags.toggle(DebugFlags::SHOW_OVERDRAW);
|
|
||||||
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
|
||||||
}
|
|
||||||
VirtualKeyCode::G => {
|
|
||||||
debug_flags.toggle(DebugFlags::GPU_CACHE_DBG);
|
|
||||||
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
|
||||||
|
|
||||||
// force scene rebuild to see the full set of used GPU cache entries
|
|
||||||
let mut txn = Transaction::new();
|
|
||||||
txn.set_root_pipeline(wrench.root_pipeline_id);
|
|
||||||
wrench.api.send_transaction(wrench.document_id, txn);
|
|
||||||
|
|
||||||
do_render = false;
|
|
||||||
do_frame = true;
|
|
||||||
}
|
|
||||||
VirtualKeyCode::M => {
|
|
||||||
wrench.api.notify_memory_pressure();
|
|
||||||
}
|
|
||||||
VirtualKeyCode::L => {
|
|
||||||
do_loop = !do_loop;
|
|
||||||
}
|
|
||||||
VirtualKeyCode::Left => {
|
|
||||||
thing.prev_frame();
|
|
||||||
do_render = false;
|
|
||||||
do_frame = true;
|
|
||||||
}
|
|
||||||
VirtualKeyCode::Right => {
|
|
||||||
thing.next_frame();
|
|
||||||
do_render = false;
|
|
||||||
do_frame = true;
|
|
||||||
}
|
|
||||||
VirtualKeyCode::H => {
|
|
||||||
show_help = !show_help;
|
|
||||||
}
|
|
||||||
VirtualKeyCode::C => {
|
|
||||||
let path = PathBuf::from("../captures/wrench");
|
|
||||||
wrench.api.save_capture(path, CaptureBits::all());
|
|
||||||
do_render = false;
|
|
||||||
}
|
|
||||||
VirtualKeyCode::X => {
|
|
||||||
let results = wrench.api.hit_test(
|
|
||||||
wrench.document_id,
|
|
||||||
cursor_position,
|
|
||||||
);
|
|
||||||
|
|
||||||
println!("Hit test results:");
|
|
||||||
for item in &results.items {
|
|
||||||
println!(" • {:?}", item);
|
|
||||||
}
|
|
||||||
println!();
|
|
||||||
do_render = false;
|
|
||||||
}
|
|
||||||
VirtualKeyCode::Z => {
|
|
||||||
debug_flags.toggle(DebugFlags::ZOOM_DBG);
|
|
||||||
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
|
||||||
}
|
|
||||||
VirtualKeyCode::Y => {
|
|
||||||
println!("Clearing all caches...");
|
|
||||||
wrench.api.send_debug_cmd(DebugCommand::ClearCaches(ClearCache::all()));
|
|
||||||
do_frame = true;
|
|
||||||
}
|
|
||||||
_other_virtual_keycode => { do_render = false; }
|
|
||||||
}
|
}
|
||||||
_other_window_event => { do_render = false; }
|
VirtualKeyCode::B => {
|
||||||
},
|
debug_flags.toggle(DebugFlags::INVALIDATION_DBG);
|
||||||
_other_event => { do_render = false; }
|
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
||||||
|
do_render = true;
|
||||||
|
}
|
||||||
|
VirtualKeyCode::P => {
|
||||||
|
debug_flags.toggle(DebugFlags::PROFILER_DBG);
|
||||||
|
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
||||||
|
do_render = true;
|
||||||
|
}
|
||||||
|
VirtualKeyCode::O => {
|
||||||
|
debug_flags.toggle(DebugFlags::RENDER_TARGET_DBG);
|
||||||
|
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
||||||
|
do_render = true;
|
||||||
|
}
|
||||||
|
VirtualKeyCode::I => {
|
||||||
|
debug_flags.toggle(DebugFlags::TEXTURE_CACHE_DBG);
|
||||||
|
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
||||||
|
do_render = true;
|
||||||
|
}
|
||||||
|
VirtualKeyCode::D => {
|
||||||
|
debug_flags.toggle(DebugFlags::PICTURE_CACHING_DBG);
|
||||||
|
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
||||||
|
do_render = true;
|
||||||
|
}
|
||||||
|
VirtualKeyCode::Q => {
|
||||||
|
debug_flags.toggle(DebugFlags::GPU_TIME_QUERIES | DebugFlags::GPU_SAMPLE_QUERIES);
|
||||||
|
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
||||||
|
do_render = true;
|
||||||
|
}
|
||||||
|
VirtualKeyCode::V => {
|
||||||
|
debug_flags.toggle(DebugFlags::SHOW_OVERDRAW);
|
||||||
|
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
||||||
|
do_render = true;
|
||||||
|
}
|
||||||
|
VirtualKeyCode::G => {
|
||||||
|
debug_flags.toggle(DebugFlags::GPU_CACHE_DBG);
|
||||||
|
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
||||||
|
|
||||||
|
// force scene rebuild to see the full set of used GPU cache entries
|
||||||
|
let mut txn = Transaction::new();
|
||||||
|
txn.set_root_pipeline(wrench.root_pipeline_id);
|
||||||
|
wrench.api.send_transaction(wrench.document_id, txn);
|
||||||
|
|
||||||
|
do_frame = true;
|
||||||
|
}
|
||||||
|
VirtualKeyCode::M => {
|
||||||
|
wrench.api.notify_memory_pressure();
|
||||||
|
do_render = true;
|
||||||
|
}
|
||||||
|
VirtualKeyCode::L => {
|
||||||
|
do_loop = !do_loop;
|
||||||
|
do_render = true;
|
||||||
|
}
|
||||||
|
VirtualKeyCode::Left => {
|
||||||
|
thing.prev_frame();
|
||||||
|
do_frame = true;
|
||||||
|
}
|
||||||
|
VirtualKeyCode::Right => {
|
||||||
|
thing.next_frame();
|
||||||
|
do_frame = true;
|
||||||
|
}
|
||||||
|
VirtualKeyCode::H => {
|
||||||
|
show_help = !show_help;
|
||||||
|
do_render = true;
|
||||||
|
}
|
||||||
|
VirtualKeyCode::C => {
|
||||||
|
let path = PathBuf::from("../captures/wrench");
|
||||||
|
wrench.api.save_capture(path, CaptureBits::all());
|
||||||
|
}
|
||||||
|
VirtualKeyCode::X => {
|
||||||
|
let results = wrench.api.hit_test(
|
||||||
|
wrench.document_id,
|
||||||
|
cursor_position,
|
||||||
|
);
|
||||||
|
|
||||||
|
println!("Hit test results:");
|
||||||
|
for item in &results.items {
|
||||||
|
println!(" • {:?}", item);
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
VirtualKeyCode::Z => {
|
||||||
|
debug_flags.toggle(DebugFlags::ZOOM_DBG);
|
||||||
|
wrench.api.send_debug_cmd(DebugCommand::SetFlags(debug_flags));
|
||||||
|
do_render = true;
|
||||||
|
}
|
||||||
|
VirtualKeyCode::Y => {
|
||||||
|
println!("Clearing all caches...");
|
||||||
|
wrench.api.send_debug_cmd(DebugCommand::ClearCaches(ClearCache::all()));
|
||||||
|
do_frame = true;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
winit::event::Event::MainEventsCleared => {
|
||||||
|
window.update(wrench);
|
||||||
|
|
||||||
|
if do_frame {
|
||||||
|
do_frame = false;
|
||||||
|
let frame_num = thing.do_frame(wrench);
|
||||||
|
unsafe {
|
||||||
|
CURRENT_FRAME_NUMBER = frame_num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if do_render {
|
||||||
|
do_render = false;
|
||||||
|
|
||||||
|
if show_help {
|
||||||
|
wrench.show_onscreen_help();
|
||||||
|
}
|
||||||
|
|
||||||
|
wrench.render();
|
||||||
|
window.upload_software_to_native();
|
||||||
|
window.swap_buffers();
|
||||||
|
|
||||||
|
if do_loop {
|
||||||
|
thing.next_frame();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
window.update(wrench);
|
|
||||||
|
|
||||||
if do_frame {
|
|
||||||
let frame_num = thing.do_frame(wrench);
|
|
||||||
unsafe {
|
|
||||||
CURRENT_FRAME_NUMBER = frame_num;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if do_render {
|
|
||||||
if show_help {
|
|
||||||
wrench.show_onscreen_help();
|
|
||||||
}
|
|
||||||
|
|
||||||
wrench.render();
|
|
||||||
window.upload_software_to_native();
|
|
||||||
window.swap_buffers();
|
|
||||||
|
|
||||||
if do_loop {
|
|
||||||
thing.next_frame();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
winit::ControlFlow::Continue
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(events_loop) = events_loop.as_mut() {
|
|
||||||
// We want to ensure that we:
|
|
||||||
//
|
|
||||||
// (a) Block the thread when no events are present (for CPU/battery purposes)
|
|
||||||
// (b) Don't lag the input events by having the event queue back up.
|
|
||||||
loop {
|
|
||||||
let mut pending_events = Vec::new();
|
|
||||||
|
|
||||||
// Block the thread until at least one event arrives
|
|
||||||
// On Android, we are generally profiling when running
|
|
||||||
// wrench, and don't want to block on UI events.
|
|
||||||
if !no_block && cfg!(not(target_os = "android")) {
|
|
||||||
events_loop.run_forever(|event| {
|
|
||||||
pending_events.push(event);
|
|
||||||
winit::ControlFlow::Break
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect any other pending events that are also available
|
|
||||||
events_loop.poll_events(|event| {
|
|
||||||
pending_events.push(event);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ensure there is at least one event present so that the
|
|
||||||
// frame gets rendered.
|
|
||||||
if pending_events.is_empty() {
|
|
||||||
pending_events.push(winit::Event::Awakened);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process all of those pending events in the next vsync period
|
|
||||||
if body(wrench, pending_events) == winit::ControlFlow::Break {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while body(wrench, vec![winit::Event::Awakened]) == winit::ControlFlow::Continue {}
|
|
||||||
let fb_rect = FramebufferIntSize::new(size.width, size.height).into();
|
|
||||||
let pixels = wrench.renderer.read_pixels_rgba8(fb_rect);
|
|
||||||
save_flipped("screenshot.png", pixels, size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crossbeam::sync::chase_lev;
|
||||||
use dwrote;
|
use dwrote;
|
||||||
#[cfg(all(unix, not(target_os = "android")))]
|
#[cfg(all(unix, not(target_os = "android")))]
|
||||||
use font_loader::system_fonts;
|
use font_loader::system_fonts;
|
||||||
use winit::EventsLoopProxy;
|
use winit::event_loop::EventLoopProxy;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
@ -36,7 +36,7 @@ pub enum FontDescriptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NotifierData {
|
struct NotifierData {
|
||||||
events_loop_proxy: Option<EventsLoopProxy>,
|
events_loop_proxy: Option<EventLoopProxy<()>>,
|
||||||
frames_notified: u32,
|
frames_notified: u32,
|
||||||
timing_receiver: chase_lev::Stealer<time::SteadyTime>,
|
timing_receiver: chase_lev::Stealer<time::SteadyTime>,
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
|
@ -44,7 +44,7 @@ struct NotifierData {
|
||||||
|
|
||||||
impl NotifierData {
|
impl NotifierData {
|
||||||
fn new(
|
fn new(
|
||||||
events_loop_proxy: Option<EventsLoopProxy>,
|
events_loop_proxy: Option<EventLoopProxy<()>>,
|
||||||
timing_receiver: chase_lev::Stealer<time::SteadyTime>,
|
timing_receiver: chase_lev::Stealer<time::SteadyTime>,
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -84,7 +84,7 @@ impl Notifier {
|
||||||
|
|
||||||
if let Some(ref _elp) = data.events_loop_proxy {
|
if let Some(ref _elp) = data.events_loop_proxy {
|
||||||
#[cfg(not(target_os = "android"))]
|
#[cfg(not(target_os = "android"))]
|
||||||
let _ = _elp.wakeup();
|
let _ = _elp.send_event(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,7 +217,7 @@ impl Wrench {
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
window: &mut WindowWrapper,
|
window: &mut WindowWrapper,
|
||||||
proxy: Option<EventsLoopProxy>,
|
proxy: Option<EventLoopProxy<()>>,
|
||||||
shader_override_path: Option<PathBuf>,
|
shader_override_path: Option<PathBuf>,
|
||||||
use_optimized_shaders: bool,
|
use_optimized_shaders: bool,
|
||||||
size: DeviceIntSize,
|
size: DeviceIntSize,
|
||||||
|
@ -268,7 +268,7 @@ impl Wrench {
|
||||||
// put an Awakened event into the queue to kick off the first frame
|
// put an Awakened event into the queue to kick off the first frame
|
||||||
if let Some(ref _elp) = proxy {
|
if let Some(ref _elp) = proxy {
|
||||||
#[cfg(not(target_os = "android"))]
|
#[cfg(not(target_os = "android"))]
|
||||||
let _ = _elp.wakeup();
|
let _ = _elp.send_event(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let (timing_sender, timing_receiver) = chase_lev::deque();
|
let (timing_sender, timing_receiver) = chase_lev::deque();
|
||||||
|
|
|
@ -175,15 +175,9 @@ wrench-deps:
|
||||||
- 'gfx/wr/Cargo.lock'
|
- 'gfx/wr/Cargo.lock'
|
||||||
- 'gfx/wr/ci-scripts/install-meson.sh'
|
- 'gfx/wr/ci-scripts/install-meson.sh'
|
||||||
toolchain-artifact: public/build/wrench-deps.tar.zst
|
toolchain-artifact: public/build/wrench-deps.tar.zst
|
||||||
dependencies:
|
|
||||||
linux64-rust-1.47: toolchain-linux64-rust-1.47
|
|
||||||
fetches:
|
fetches:
|
||||||
fetch:
|
fetch:
|
||||||
- android-rs-glue
|
- android-rs-glue
|
||||||
linux64-rust-1.47:
|
|
||||||
- artifact: rustc.tar.zst
|
|
||||||
extract: true
|
|
||||||
dest: rustc-1.47
|
|
||||||
toolchain:
|
toolchain:
|
||||||
- linux64-rust # whatever m-c is built with
|
- linux64-rust # whatever m-c is built with
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче