render: Add wgpu-rs based renderer, used by desktop
This commit is contained in:
parent
834756c167
commit
f0445d94b8
File diff suppressed because it is too large
Load Diff
|
@ -8,7 +8,7 @@ members = [
|
|||
"scanner",
|
||||
|
||||
"render/canvas",
|
||||
"render/glium",
|
||||
"render/wgpu",
|
||||
"render/common_tess",
|
||||
]
|
||||
|
||||
|
|
|
@ -8,9 +8,7 @@ default-run = "ruffle_desktop"
|
|||
[dependencies]
|
||||
cpal = "0.11.0"
|
||||
ruffle_core = { path = "../core" }
|
||||
ruffle_render_glium = { path = "../render/glium" }
|
||||
glium = "0.27.0"
|
||||
glutin = "0.24"
|
||||
ruffle_render_wgpu = { path = "../render/wgpu" }
|
||||
env_logger = "0.7.1"
|
||||
generational-arena = "0.2.7"
|
||||
image = "0.23.4"
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
use crate::custom_event::RuffleEvent;
|
||||
use crate::task::Task;
|
||||
use generational_arena::{Arena, Index};
|
||||
use glutin::event_loop::EventLoopProxy;
|
||||
use ruffle_core::backend::navigator::{Error, OwnedFuture};
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::sync::{Arc, Mutex, Weak};
|
||||
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
|
||||
use winit::event_loop::EventLoopProxy;
|
||||
|
||||
/// Exeuctor context passed to event sources.
|
||||
///
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
use glium::Display;
|
||||
use ruffle_core::backend::input::{InputBackend, MouseCursor};
|
||||
use ruffle_core::events::{KeyCode, PlayerEvent};
|
||||
use std::collections::HashSet;
|
||||
use std::rc::Rc;
|
||||
use winit::event::{ElementState, VirtualKeyCode, WindowEvent};
|
||||
use winit::window::Window;
|
||||
|
||||
pub struct WinitInputBackend {
|
||||
keys_down: HashSet<VirtualKeyCode>,
|
||||
display: Display,
|
||||
window: Rc<Window>,
|
||||
cursor_visible: bool,
|
||||
last_key: KeyCode,
|
||||
}
|
||||
|
||||
impl WinitInputBackend {
|
||||
pub fn new(display: Display) -> Self {
|
||||
pub fn new(window: Rc<Window>) -> Self {
|
||||
Self {
|
||||
keys_down: HashSet::new(),
|
||||
cursor_visible: true,
|
||||
last_key: KeyCode::Unknown,
|
||||
display,
|
||||
window,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,12 +177,12 @@ impl InputBackend for WinitInputBackend {
|
|||
}
|
||||
|
||||
fn hide_mouse(&mut self) {
|
||||
self.display.gl_window().window().set_cursor_visible(false);
|
||||
self.window.set_cursor_visible(false);
|
||||
self.cursor_visible = false;
|
||||
}
|
||||
|
||||
fn show_mouse(&mut self) {
|
||||
self.display.gl_window().window().set_cursor_visible(true);
|
||||
self.window.set_cursor_visible(true);
|
||||
self.cursor_visible = true;
|
||||
}
|
||||
|
||||
|
@ -193,7 +194,7 @@ impl InputBackend for WinitInputBackend {
|
|||
MouseCursor::IBeam => CursorIcon::Text,
|
||||
MouseCursor::Grab => CursorIcon::Grab,
|
||||
};
|
||||
self.display.gl_window().window().set_cursor_icon(icon);
|
||||
self.window.set_cursor_icon(icon);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,22 +9,21 @@ mod task;
|
|||
|
||||
use crate::custom_event::RuffleEvent;
|
||||
use crate::executor::GlutinAsyncExecutor;
|
||||
use glutin::{
|
||||
dpi::{LogicalSize, PhysicalPosition},
|
||||
event::{ElementState, MouseButton, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
window::WindowBuilder,
|
||||
ContextBuilder,
|
||||
};
|
||||
use ruffle_core::{
|
||||
backend::audio::{AudioBackend, NullAudioBackend},
|
||||
Player,
|
||||
};
|
||||
use ruffle_render_glium::GliumRenderBackend;
|
||||
use ruffle_render_wgpu::WGPURenderBackend;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Instant;
|
||||
use structopt::StructOpt;
|
||||
|
||||
use std::rc::Rc;
|
||||
use winit::dpi::{LogicalSize, PhysicalPosition};
|
||||
use winit::event::{ElementState, MouseButton, WindowEvent};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
use winit::window::WindowBuilder;
|
||||
|
||||
#[derive(StructOpt, Debug)]
|
||||
#[structopt(name = "basic")]
|
||||
struct Opt {
|
||||
|
@ -49,16 +48,15 @@ fn run_player(input_path: PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
|||
let swf_data = std::fs::read(&input_path)?;
|
||||
|
||||
let event_loop: EventLoop<RuffleEvent> = EventLoop::with_user_event();
|
||||
let window_builder = WindowBuilder::new().with_title(format!(
|
||||
let window = Rc::new(
|
||||
WindowBuilder::new()
|
||||
.with_title(format!(
|
||||
"Ruffle - {}",
|
||||
input_path.file_name().unwrap_or_default().to_string_lossy()
|
||||
));
|
||||
let windowed_context = ContextBuilder::new()
|
||||
.with_vsync(true)
|
||||
.with_multisampling(4)
|
||||
.with_srgb(true)
|
||||
.with_stencil_buffer(8)
|
||||
.build_windowed(window_builder, &event_loop)?;
|
||||
))
|
||||
.build(&event_loop)?,
|
||||
);
|
||||
|
||||
let audio: Box<dyn AudioBackend> = match audio::CpalAudioBackend::new() {
|
||||
Ok(audio) => Box::new(audio),
|
||||
Err(e) => {
|
||||
|
@ -66,7 +64,7 @@ fn run_player(input_path: PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
|||
Box::new(NullAudioBackend::new())
|
||||
}
|
||||
};
|
||||
let renderer = Box::new(GliumRenderBackend::new(windowed_context)?);
|
||||
let renderer = Box::new(WGPURenderBackend::new(window.clone())?);
|
||||
let (executor, chan) = GlutinAsyncExecutor::new(event_loop.create_proxy());
|
||||
let navigator = Box::new(navigator::ExternalNavigatorBackend::with_base_path(
|
||||
input_path
|
||||
|
@ -75,8 +73,7 @@ fn run_player(input_path: PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
|||
chan,
|
||||
event_loop.create_proxy(),
|
||||
)); //TODO: actually implement this backend type
|
||||
let display = renderer.display().clone();
|
||||
let input = Box::new(input::WinitInputBackend::new(display.clone()));
|
||||
let input = Box::new(input::WinitInputBackend::new(window.clone()));
|
||||
let player = Player::new(renderer, audio, navigator, input, swf_data)?;
|
||||
|
||||
let logical_size: LogicalSize<u32> = {
|
||||
|
@ -85,13 +82,15 @@ fn run_player(input_path: PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
|||
|
||||
(player_lock.movie_width(), player_lock.movie_height()).into()
|
||||
};
|
||||
let scale_factor = display.gl_window().window().scale_factor();
|
||||
let scale_factor = window.scale_factor();
|
||||
|
||||
// Set initial size to movie dimensions.
|
||||
display.gl_window().window().set_inner_size(logical_size);
|
||||
display
|
||||
.gl_window()
|
||||
.resize(logical_size.to_physical(scale_factor));
|
||||
window.set_inner_size(logical_size);
|
||||
let size = logical_size.to_physical(scale_factor);
|
||||
player
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_viewport_dimensions(size.width, size.height);
|
||||
|
||||
let mut mouse_pos = PhysicalPosition::new(0.0, 0.0);
|
||||
let mut time = Instant::now();
|
||||
|
@ -100,8 +99,8 @@ fn run_player(input_path: PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
|||
event_loop.run(move |event, _window_target, control_flow| {
|
||||
*control_flow = ControlFlow::Wait;
|
||||
match event {
|
||||
glutin::event::Event::LoopDestroyed => return,
|
||||
glutin::event::Event::WindowEvent { event, .. } => match event {
|
||||
winit::event::Event::LoopDestroyed => return,
|
||||
winit::event::Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::Resized(size) => {
|
||||
let mut player_lock = player.lock().unwrap();
|
||||
player_lock.set_viewport_dimensions(size.width, size.height);
|
||||
|
@ -155,7 +154,7 @@ fn run_player(input_path: PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
|||
}
|
||||
_ => (),
|
||||
},
|
||||
glutin::event::Event::UserEvent(RuffleEvent::TaskPoll) => executor
|
||||
winit::event::Event::UserEvent(RuffleEvent::TaskPoll) => executor
|
||||
.lock()
|
||||
.expect("active executor reference")
|
||||
.poll_all(),
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
//! Navigator backend for web
|
||||
|
||||
use crate::custom_event::RuffleEvent;
|
||||
use glutin::event_loop::EventLoopProxy;
|
||||
use ruffle_core::backend::navigator::{
|
||||
Error, NavigationMethod, NavigatorBackend, OwnedFuture, RequestOptions,
|
||||
};
|
||||
|
@ -11,6 +10,7 @@ use std::path::{Path, PathBuf};
|
|||
use std::sync::mpsc::Sender;
|
||||
use std::time::{Duration, Instant};
|
||||
use url::Url;
|
||||
use winit::event_loop::EventLoopProxy;
|
||||
|
||||
/// Implementation of `NavigatorBackend` for non-web environments that can call
|
||||
/// out to a web browser.
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
[package]
|
||||
name = "ruffle_render_glium"
|
||||
version = "0.1.0"
|
||||
authors = ["Mike Welsh <mwelsh@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
glium = "0.27.0"
|
||||
glutin = "0.24"
|
||||
image = "0.23.4"
|
||||
jpeg-decoder = "0.1.18"
|
||||
log = "0.4"
|
||||
ruffle_core = { path = "../../core" }
|
||||
ruffle_render_common_tess = { path = "../common_tess" }
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,17 @@
|
|||
[package]
|
||||
name = "ruffle_render_wgpu"
|
||||
version = "0.1.0"
|
||||
authors = ["Nathan Adams <dinnerbone@dinnerbone.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wgpu = "0.5"
|
||||
wgpu-native = "0.5"
|
||||
image = "0.23.4"
|
||||
jpeg-decoder = "0.1.18"
|
||||
log = "0.4"
|
||||
lyon = "0.15.6"
|
||||
ruffle_core = { path = "../../core" }
|
||||
futures = "0.3.4"
|
||||
bytemuck = "1.2.0"
|
||||
winit = "0.22"
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/sh
|
||||
glslangValidator -V ./shaders/color.frag -o ./shaders/color.frag.spv
|
||||
glslangValidator -V ./shaders/color.vert -o ./shaders/color.vert.spv
|
||||
glslangValidator -V ./shaders/bitmap.frag -o ./shaders/bitmap.frag.spv
|
||||
glslangValidator -V ./shaders/gradient.frag -o ./shaders/gradient.frag.spv
|
||||
glslangValidator -V ./shaders/texture.vert -o ./shaders/texture.vert.spv
|
|
@ -0,0 +1,26 @@
|
|||
#version 450
|
||||
|
||||
layout(set = 0, binding = 2) uniform Colors {
|
||||
vec4 mult_color;
|
||||
vec4 add_color;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 3) uniform texture2D t_color;
|
||||
layout(set = 0, binding = 4) uniform sampler s_color;
|
||||
|
||||
layout(location=0) in vec2 frag_uv;
|
||||
|
||||
layout(location=0) out vec4 out_color;
|
||||
|
||||
void main() {
|
||||
|
||||
vec4 color = texture(sampler2D(t_color, s_color), frag_uv);
|
||||
// Unmultiply alpha before apply color transform.
|
||||
if( color.a > 0 ) {
|
||||
color.rgb /= color.a;
|
||||
color = mult_color * color + add_color;
|
||||
color.rgb *= color.a;
|
||||
}
|
||||
|
||||
out_color = color;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,9 @@
|
|||
#version 450
|
||||
|
||||
layout(location=0) in vec4 frag_color;
|
||||
|
||||
layout(location=0) out vec4 out_color;
|
||||
|
||||
void main() {
|
||||
out_color = frag_color;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,22 @@
|
|||
#version 450
|
||||
|
||||
layout(set = 0, binding = 0) uniform Transforms {
|
||||
mat4 view_matrix;
|
||||
mat4 world_matrix;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 1) uniform Colors {
|
||||
vec4 mult_color;
|
||||
vec4 add_color;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec2 position;
|
||||
layout(location = 1) in vec4 color;
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
void main() {
|
||||
frag_color = color * mult_color + add_color;
|
||||
gl_Position = view_matrix * world_matrix * vec4(position, 0.0, 1.0);
|
||||
gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,75 @@
|
|||
#version 450
|
||||
|
||||
layout(set = 0, binding = 2) uniform Colors {
|
||||
vec4 mult_color;
|
||||
vec4 add_color;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 3) uniform Gradient {
|
||||
int u_gradient_type;
|
||||
uint u_num_colors;
|
||||
int u_repeat_mode;
|
||||
float u_focal_point;
|
||||
vec4 u_ratios[16];
|
||||
vec4 u_colors[16];
|
||||
};
|
||||
|
||||
layout(location=0) in vec2 frag_uv;
|
||||
|
||||
layout(location=0) out vec4 out_color;
|
||||
|
||||
void main() {
|
||||
vec4 color;
|
||||
int last = int(int(u_num_colors) - 1);
|
||||
float t;
|
||||
if( u_gradient_type == 0 )
|
||||
{
|
||||
t = frag_uv.x;
|
||||
}
|
||||
else if( u_gradient_type == 1 )
|
||||
{
|
||||
t = length(frag_uv * 2.0 - 1.0);
|
||||
}
|
||||
else if( u_gradient_type == 2 )
|
||||
{
|
||||
vec2 uv = frag_uv * 2.0 - 1.0;
|
||||
vec2 d = vec2(u_focal_point, 0.0) - uv;
|
||||
float l = length(d);
|
||||
d /= l;
|
||||
t = l / (sqrt(1.0 - u_focal_point*u_focal_point*d.y*d.y) + u_focal_point*d.x);
|
||||
}
|
||||
if( u_repeat_mode == 0 )
|
||||
{
|
||||
// Clamp
|
||||
t = clamp(t, 0.0, 1.0);
|
||||
}
|
||||
else if( u_repeat_mode == 1 )
|
||||
{
|
||||
// Repeat
|
||||
t = fract(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mirror
|
||||
if( t < 0.0 )
|
||||
{
|
||||
t = -t;
|
||||
}
|
||||
if( (int(t)&1) == 0 ) {
|
||||
t = fract(t);
|
||||
} else {
|
||||
t = 1.0 - fract(t);
|
||||
}
|
||||
}
|
||||
int i = 0;
|
||||
int j = 1;
|
||||
t = clamp(t, u_ratios[0].x, u_ratios[last].x);
|
||||
while( t > u_ratios[j].x )
|
||||
{
|
||||
i = j;
|
||||
j++;
|
||||
}
|
||||
float a = (t - u_ratios[i].x) / (u_ratios[j].x - u_ratios[i].x);
|
||||
color = mix(u_colors[i], u_colors[j], a);
|
||||
out_color = mult_color * color + add_color;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,21 @@
|
|||
#version 450
|
||||
|
||||
layout(set = 0, binding = 0) uniform Transforms {
|
||||
mat4 view_matrix;
|
||||
mat4 world_matrix;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 1) uniform Texture {
|
||||
mat4 u_matrix;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec2 position;
|
||||
layout(location = 1) in vec4 color;
|
||||
|
||||
layout(location = 0) out vec2 frag_uv;
|
||||
|
||||
void main() {
|
||||
frag_uv = vec2(mat3(u_matrix) * vec3(position, 1.0));
|
||||
gl_Position = view_matrix * world_matrix * vec4(position, 0.0, 1.0);
|
||||
gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0;
|
||||
}
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue