2022-09-07 20:14:14 +00:00
|
|
|
use crate::{
|
|
|
|
create_buffer_with_data, Descriptors, GradientStorage, GradientUniforms, RegistryData,
|
2022-09-07 20:27:57 +00:00
|
|
|
TextureTransforms, Vertex,
|
2022-09-07 20:14:14 +00:00
|
|
|
};
|
|
|
|
use fnv::FnvHashMap;
|
|
|
|
use ruffle_render::bitmap::BitmapHandle;
|
2022-09-07 20:27:57 +00:00
|
|
|
use ruffle_render::tessellator::{Bitmap, Draw as LyonDraw, DrawType as TessDrawType, Gradient};
|
2022-09-07 20:14:14 +00:00
|
|
|
use swf::CharacterId;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Mesh {
|
|
|
|
pub draws: Vec<Draw>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Draw {
|
|
|
|
pub draw_type: DrawType,
|
|
|
|
pub vertex_buffer: wgpu::Buffer,
|
|
|
|
pub index_buffer: wgpu::Buffer,
|
|
|
|
pub num_indices: u32,
|
|
|
|
pub num_mask_indices: u32,
|
|
|
|
}
|
|
|
|
|
2022-09-07 20:27:57 +00:00
|
|
|
impl Draw {
|
|
|
|
pub fn new(
|
|
|
|
descriptors: &Descriptors,
|
|
|
|
draw: LyonDraw,
|
|
|
|
shape_id: CharacterId,
|
|
|
|
draw_id: usize,
|
|
|
|
bitmap_registry: &FnvHashMap<BitmapHandle, RegistryData>,
|
|
|
|
) -> Self {
|
|
|
|
let vertices: Vec<_> = draw.vertices.into_iter().map(Vertex::from).collect();
|
|
|
|
let vertex_buffer = create_buffer_with_data(
|
|
|
|
&descriptors.device,
|
|
|
|
bytemuck::cast_slice(&vertices),
|
|
|
|
wgpu::BufferUsages::VERTEX,
|
|
|
|
create_debug_label!("Shape {} ({}) vbo", shape_id, draw.draw_type.name()),
|
|
|
|
);
|
|
|
|
|
|
|
|
let index_buffer = create_buffer_with_data(
|
|
|
|
&descriptors.device,
|
|
|
|
bytemuck::cast_slice(&draw.indices),
|
|
|
|
wgpu::BufferUsages::INDEX,
|
|
|
|
create_debug_label!("Shape {} ({}) ibo", shape_id, draw.draw_type.name()),
|
|
|
|
);
|
|
|
|
|
|
|
|
let index_count = draw.indices.len() as u32;
|
|
|
|
match draw.draw_type {
|
|
|
|
TessDrawType::Color => Draw {
|
|
|
|
draw_type: DrawType::color(),
|
|
|
|
vertex_buffer,
|
|
|
|
index_buffer,
|
|
|
|
num_indices: index_count,
|
|
|
|
num_mask_indices: draw.mask_index_count,
|
|
|
|
},
|
|
|
|
TessDrawType::Gradient(gradient) => Draw {
|
|
|
|
draw_type: DrawType::gradient(&descriptors, gradient, shape_id, draw_id),
|
|
|
|
vertex_buffer,
|
|
|
|
index_buffer,
|
|
|
|
num_indices: index_count,
|
|
|
|
num_mask_indices: draw.mask_index_count,
|
|
|
|
},
|
|
|
|
TessDrawType::Bitmap(bitmap) => Draw {
|
|
|
|
draw_type: DrawType::bitmap(
|
|
|
|
&descriptors,
|
|
|
|
&bitmap_registry,
|
|
|
|
bitmap,
|
|
|
|
shape_id,
|
|
|
|
draw_id,
|
|
|
|
),
|
|
|
|
vertex_buffer,
|
|
|
|
index_buffer,
|
|
|
|
num_indices: index_count,
|
|
|
|
num_mask_indices: draw.mask_index_count,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-07 20:14:14 +00:00
|
|
|
#[allow(dead_code)]
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum DrawType {
|
|
|
|
Color,
|
|
|
|
Gradient {
|
|
|
|
texture_transforms: wgpu::Buffer,
|
|
|
|
gradient: wgpu::Buffer,
|
|
|
|
bind_group: wgpu::BindGroup,
|
|
|
|
},
|
|
|
|
Bitmap {
|
|
|
|
texture_transforms: wgpu::Buffer,
|
2022-09-08 09:49:50 +00:00
|
|
|
binds: BitmapBinds,
|
2022-09-07 20:14:14 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DrawType {
|
|
|
|
pub fn color() -> Self {
|
|
|
|
DrawType::Color
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn gradient(
|
|
|
|
descriptors: &Descriptors,
|
|
|
|
gradient: Gradient,
|
|
|
|
shape_id: CharacterId,
|
|
|
|
draw_id: usize,
|
|
|
|
) -> Self {
|
2022-09-07 20:20:04 +00:00
|
|
|
let tex_transforms_ubo = create_texture_transforms(
|
2022-09-07 20:14:14 +00:00
|
|
|
&descriptors.device,
|
2022-09-07 20:20:04 +00:00
|
|
|
&gradient.matrix,
|
2022-09-07 20:14:14 +00:00
|
|
|
create_debug_label!(
|
|
|
|
"Shape {} draw {} textransforms ubo transfer buffer",
|
|
|
|
shape_id,
|
|
|
|
draw_id
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
|
|
|
let (gradient_ubo, buffer_size) =
|
|
|
|
if descriptors.limits.max_storage_buffers_per_shader_stage > 0 {
|
|
|
|
(
|
|
|
|
create_buffer_with_data(
|
|
|
|
&descriptors.device,
|
|
|
|
bytemuck::cast_slice(&[GradientStorage::from(gradient)]),
|
|
|
|
wgpu::BufferUsages::STORAGE,
|
|
|
|
create_debug_label!(
|
|
|
|
"Shape {} draw {} gradient ubo transfer buffer",
|
|
|
|
shape_id,
|
|
|
|
draw_id
|
|
|
|
),
|
|
|
|
),
|
|
|
|
wgpu::BufferSize::new(std::mem::size_of::<GradientStorage>() as u64),
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
(
|
|
|
|
create_buffer_with_data(
|
|
|
|
&descriptors.device,
|
|
|
|
bytemuck::cast_slice(&[GradientUniforms::from(gradient)]),
|
|
|
|
wgpu::BufferUsages::UNIFORM,
|
|
|
|
create_debug_label!(
|
|
|
|
"Shape {} draw {} gradient ubo transfer buffer",
|
|
|
|
shape_id,
|
|
|
|
draw_id
|
|
|
|
),
|
|
|
|
),
|
|
|
|
wgpu::BufferSize::new(std::mem::size_of::<GradientUniforms>() as u64),
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
let bind_group_label =
|
|
|
|
create_debug_label!("Shape {} (gradient) draw {} bindgroup", shape_id, draw_id);
|
|
|
|
let bind_group = descriptors
|
|
|
|
.device
|
|
|
|
.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
|
|
layout: &descriptors.bind_layouts.gradient,
|
|
|
|
entries: &[
|
|
|
|
wgpu::BindGroupEntry {
|
|
|
|
binding: 0,
|
|
|
|
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
|
|
|
|
buffer: &tex_transforms_ubo,
|
|
|
|
offset: 0,
|
|
|
|
size: wgpu::BufferSize::new(
|
|
|
|
std::mem::size_of::<TextureTransforms>() as u64
|
|
|
|
),
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
wgpu::BindGroupEntry {
|
|
|
|
binding: 1,
|
|
|
|
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
|
|
|
|
buffer: &gradient_ubo,
|
|
|
|
offset: 0,
|
|
|
|
size: buffer_size,
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
],
|
|
|
|
label: bind_group_label.as_deref(),
|
|
|
|
});
|
|
|
|
DrawType::Gradient {
|
|
|
|
texture_transforms: tex_transforms_ubo,
|
|
|
|
gradient: gradient_ubo,
|
|
|
|
bind_group,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn bitmap(
|
|
|
|
descriptors: &Descriptors,
|
|
|
|
bitmap_registry: &FnvHashMap<BitmapHandle, RegistryData>,
|
|
|
|
bitmap: Bitmap,
|
|
|
|
shape_id: CharacterId,
|
|
|
|
draw_id: usize,
|
|
|
|
) -> Self {
|
|
|
|
let entry = bitmap_registry.get(&bitmap.bitmap).unwrap();
|
|
|
|
let texture_view = entry
|
|
|
|
.texture_wrapper
|
|
|
|
.texture
|
|
|
|
.create_view(&Default::default());
|
2022-09-08 09:49:50 +00:00
|
|
|
let texture_transforms = create_texture_transforms(
|
2022-09-07 20:14:14 +00:00
|
|
|
&descriptors.device,
|
2022-09-07 20:20:04 +00:00
|
|
|
&bitmap.matrix,
|
2022-09-07 20:14:14 +00:00
|
|
|
create_debug_label!(
|
|
|
|
"Shape {} draw {} textransforms ubo transfer buffer",
|
|
|
|
shape_id,
|
|
|
|
draw_id
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
|
|
|
let bind_group_label =
|
|
|
|
create_debug_label!("Shape {} (bitmap) draw {} bindgroup", shape_id, draw_id);
|
2022-09-08 09:49:50 +00:00
|
|
|
let binds = BitmapBinds::new(
|
|
|
|
&descriptors.device,
|
|
|
|
&descriptors.bind_layouts.bitmap,
|
|
|
|
bitmap.is_smoothed,
|
|
|
|
bitmap.is_repeating,
|
|
|
|
&texture_transforms,
|
|
|
|
texture_view,
|
|
|
|
bind_group_label,
|
|
|
|
);
|
|
|
|
|
|
|
|
DrawType::Bitmap {
|
|
|
|
texture_transforms,
|
|
|
|
binds,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct BitmapBinds {
|
|
|
|
pub is_smoothed: bool,
|
|
|
|
pub is_repeating: bool,
|
|
|
|
pub bind_group: wgpu::BindGroup,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl BitmapBinds {
|
|
|
|
pub fn new(
|
|
|
|
device: &wgpu::Device,
|
|
|
|
layout: &wgpu::BindGroupLayout,
|
|
|
|
is_smoothed: bool,
|
|
|
|
is_repeating: bool,
|
|
|
|
texture_transforms: &wgpu::Buffer,
|
|
|
|
texture_view: wgpu::TextureView,
|
|
|
|
label: Option<String>,
|
|
|
|
) -> Self {
|
|
|
|
let bind_group =
|
|
|
|
device.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
|
|
layout: &layout,
|
2022-09-07 20:14:14 +00:00
|
|
|
entries: &[
|
|
|
|
wgpu::BindGroupEntry {
|
|
|
|
binding: 0,
|
|
|
|
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
|
2022-09-08 09:49:50 +00:00
|
|
|
buffer: &texture_transforms,
|
2022-09-07 20:14:14 +00:00
|
|
|
offset: 0,
|
|
|
|
size: wgpu::BufferSize::new(
|
|
|
|
std::mem::size_of::<TextureTransforms>() as u64
|
|
|
|
),
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
wgpu::BindGroupEntry {
|
|
|
|
binding: 1,
|
|
|
|
resource: wgpu::BindingResource::TextureView(&texture_view),
|
|
|
|
},
|
|
|
|
],
|
2022-09-08 09:49:50 +00:00
|
|
|
label: label.as_deref(),
|
2022-09-07 20:14:14 +00:00
|
|
|
});
|
2022-09-08 09:49:50 +00:00
|
|
|
Self {
|
|
|
|
is_smoothed,
|
|
|
|
is_repeating,
|
2022-09-07 20:14:14 +00:00
|
|
|
bind_group,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-09-07 20:20:04 +00:00
|
|
|
|
|
|
|
fn create_texture_transforms(
|
|
|
|
device: &wgpu::Device,
|
|
|
|
matrix: &[[f32; 3]; 3],
|
|
|
|
label: Option<String>,
|
|
|
|
) -> wgpu::Buffer {
|
|
|
|
let mut texture_transform = [[0.0; 4]; 4];
|
|
|
|
texture_transform[0][..3].copy_from_slice(&matrix[0]);
|
|
|
|
texture_transform[1][..3].copy_from_slice(&matrix[1]);
|
|
|
|
texture_transform[2][..3].copy_from_slice(&matrix[2]);
|
|
|
|
|
|
|
|
create_buffer_with_data(
|
|
|
|
&device,
|
|
|
|
bytemuck::cast_slice(&[texture_transform]),
|
|
|
|
wgpu::BufferUsages::UNIFORM,
|
|
|
|
label,
|
|
|
|
)
|
|
|
|
}
|