diff options
Diffstat (limited to '')
| -rw-r--r-- | wgpu/src/image/atlas.rs | 205 | ||||
| -rw-r--r-- | wgpu/src/image/atlas/allocation.rs | 6 | ||||
| -rw-r--r-- | wgpu/src/image/atlas/allocator.rs | 4 | ||||
| -rw-r--r-- | wgpu/src/image/atlas/entry.rs | 10 | 
4 files changed, 118 insertions, 107 deletions
diff --git a/wgpu/src/image/atlas.rs b/wgpu/src/image/atlas.rs index 953dd4e2..eafe2f96 100644 --- a/wgpu/src/image/atlas.rs +++ b/wgpu/src/image/atlas.rs @@ -4,8 +4,6 @@ mod allocation;  mod allocator;  mod layer; -use std::num::NonZeroU32; -  pub use allocation::Allocation;  pub use entry::Entry;  pub use layer::Layer; @@ -14,6 +12,11 @@ use allocator::Allocator;  pub const SIZE: u32 = 2048; +use iced_graphics::image; +use iced_graphics::Size; + +use std::num::NonZeroU32; +  #[derive(Debug)]  pub struct Atlas {      texture: wgpu::Texture, @@ -35,7 +38,7 @@ impl Atlas {              mip_level_count: 1,              sample_count: 1,              dimension: wgpu::TextureDimension::D2, -            format: wgpu::TextureFormat::Bgra8UnormSrgb, +            format: wgpu::TextureFormat::Rgba8UnormSrgb,              usage: wgpu::TextureUsages::COPY_DST                  | wgpu::TextureUsages::COPY_SRC                  | wgpu::TextureUsages::TEXTURE_BINDING, @@ -61,99 +64,6 @@ impl Atlas {          self.layers.len()      } -    pub fn upload( -        &mut self, -        width: u32, -        height: u32, -        data: &[u8], -        device: &wgpu::Device, -        encoder: &mut wgpu::CommandEncoder, -    ) -> Option<Entry> { -        use wgpu::util::DeviceExt; - -        let entry = { -            let current_size = self.layers.len(); -            let entry = self.allocate(width, height)?; - -            // We grow the internal texture after allocating if necessary -            let new_layers = self.layers.len() - current_size; -            self.grow(new_layers, device, encoder); - -            entry -        }; - -        log::info!("Allocated atlas entry: {:?}", entry); - -        // It is a webgpu requirement that: -        //   BufferCopyView.layout.bytes_per_row % wgpu::COPY_BYTES_PER_ROW_ALIGNMENT == 0 -        // So we calculate padded_width by rounding width up to the next -        // multiple of wgpu::COPY_BYTES_PER_ROW_ALIGNMENT. -        let align = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT; -        let padding = (align - (4 * width) % align) % align; -        let padded_width = (4 * width + padding) as usize; -        let padded_data_size = padded_width * height as usize; - -        let mut padded_data = vec![0; padded_data_size]; - -        for row in 0..height as usize { -            let offset = row * padded_width; - -            padded_data[offset..offset + 4 * width as usize].copy_from_slice( -                &data[row * 4 * width as usize..(row + 1) * 4 * width as usize], -            ) -        } - -        let buffer = -            device.create_buffer_init(&wgpu::util::BufferInitDescriptor { -                label: Some("iced_wgpu::image staging buffer"), -                contents: &padded_data, -                usage: wgpu::BufferUsages::COPY_SRC, -            }); - -        match &entry { -            Entry::Contiguous(allocation) => { -                self.upload_allocation( -                    &buffer, width, height, padding, 0, allocation, encoder, -                ); -            } -            Entry::Fragmented { fragments, .. } => { -                for fragment in fragments { -                    let (x, y) = fragment.position; -                    let offset = (y * padded_width as u32 + 4 * x) as usize; - -                    self.upload_allocation( -                        &buffer, -                        width, -                        height, -                        padding, -                        offset, -                        &fragment.allocation, -                        encoder, -                    ); -                } -            } -        } - -        log::info!("Current atlas: {:?}", self); - -        Some(entry) -    } - -    pub fn remove(&mut self, entry: &Entry) { -        log::info!("Removing atlas entry: {:?}", entry); - -        match entry { -            Entry::Contiguous(allocation) => { -                self.deallocate(allocation); -            } -            Entry::Fragmented { fragments, .. } => { -                for fragment in fragments { -                    self.deallocate(&fragment.allocation); -                } -            } -        } -    } -      fn allocate(&mut self, width: u32, height: u32) -> Option<Entry> {          // Allocate one layer if texture fits perfectly          if width == SIZE && height == SIZE { @@ -204,7 +114,7 @@ impl Atlas {              }              return Some(Entry::Fragmented { -                size: (width, height), +                size: Size::new(width, height),                  fragments,              });          } @@ -284,7 +194,7 @@ impl Atlas {          encoder: &mut wgpu::CommandEncoder,      ) {          let (x, y) = allocation.position(); -        let (width, height) = allocation.size(); +        let Size { width, height } = allocation.size();          let layer = allocation.layer();          let extent = wgpu::Extent3d { @@ -336,7 +246,7 @@ impl Atlas {              mip_level_count: 1,              sample_count: 1,              dimension: wgpu::TextureDimension::D2, -            format: wgpu::TextureFormat::Bgra8UnormSrgb, +            format: wgpu::TextureFormat::Rgba8UnormSrgb,              usage: wgpu::TextureUsages::COPY_DST                  | wgpu::TextureUsages::COPY_SRC                  | wgpu::TextureUsages::TEXTURE_BINDING, @@ -388,3 +298,100 @@ impl Atlas {              });      }  } + +impl image::Storage for Atlas { +    type Entry = Entry; +    type State<'a> = (&'a wgpu::Device, &'a mut wgpu::CommandEncoder); + +    fn upload( +        &mut self, +        width: u32, +        height: u32, +        data: &[u8], +        (device, encoder): &mut Self::State<'_>, +    ) -> Option<Self::Entry> { +        use wgpu::util::DeviceExt; + +        let entry = { +            let current_size = self.layers.len(); +            let entry = self.allocate(width, height)?; + +            // We grow the internal texture after allocating if necessary +            let new_layers = self.layers.len() - current_size; +            self.grow(new_layers, device, encoder); + +            entry +        }; + +        log::info!("Allocated atlas entry: {:?}", entry); + +        // It is a webgpu requirement that: +        //   BufferCopyView.layout.bytes_per_row % wgpu::COPY_BYTES_PER_ROW_ALIGNMENT == 0 +        // So we calculate padded_width by rounding width up to the next +        // multiple of wgpu::COPY_BYTES_PER_ROW_ALIGNMENT. +        let align = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT; +        let padding = (align - (4 * width) % align) % align; +        let padded_width = (4 * width + padding) as usize; +        let padded_data_size = padded_width * height as usize; + +        let mut padded_data = vec![0; padded_data_size]; + +        for row in 0..height as usize { +            let offset = row * padded_width; + +            padded_data[offset..offset + 4 * width as usize].copy_from_slice( +                &data[row * 4 * width as usize..(row + 1) * 4 * width as usize], +            ) +        } + +        let buffer = +            device.create_buffer_init(&wgpu::util::BufferInitDescriptor { +                label: Some("iced_wgpu::image staging buffer"), +                contents: &padded_data, +                usage: wgpu::BufferUsages::COPY_SRC, +            }); + +        match &entry { +            Entry::Contiguous(allocation) => { +                self.upload_allocation( +                    &buffer, width, height, padding, 0, allocation, encoder, +                ); +            } +            Entry::Fragmented { fragments, .. } => { +                for fragment in fragments { +                    let (x, y) = fragment.position; +                    let offset = (y * padded_width as u32 + 4 * x) as usize; + +                    self.upload_allocation( +                        &buffer, +                        width, +                        height, +                        padding, +                        offset, +                        &fragment.allocation, +                        encoder, +                    ); +                } +            } +        } + +        log::info!("Current atlas: {:?}", self); + +        Some(entry) +    } + +    fn remove(&mut self, entry: &Entry, _: &mut Self::State<'_>) { +        log::info!("Removing atlas entry: {:?}", entry); + +        match entry { +            Entry::Contiguous(allocation) => { +                self.deallocate(allocation); +            } +            Entry::Fragmented { fragments, .. } => { +                for fragment in fragments { +                    self.deallocate(&fragment.allocation); +                } +            } +        } +    } +} diff --git a/wgpu/src/image/atlas/allocation.rs b/wgpu/src/image/atlas/allocation.rs index 59b7239f..43aba875 100644 --- a/wgpu/src/image/atlas/allocation.rs +++ b/wgpu/src/image/atlas/allocation.rs @@ -1,5 +1,7 @@  use crate::image::atlas::{self, allocator}; +use iced_graphics::Size; +  #[derive(Debug)]  pub enum Allocation {      Partial { @@ -19,10 +21,10 @@ impl Allocation {          }      } -    pub fn size(&self) -> (u32, u32) { +    pub fn size(&self) -> Size<u32> {          match self {              Allocation::Partial { region, .. } => region.size(), -            Allocation::Full { .. } => (atlas::SIZE, atlas::SIZE), +            Allocation::Full { .. } => Size::new(atlas::SIZE, atlas::SIZE),          }      } diff --git a/wgpu/src/image/atlas/allocator.rs b/wgpu/src/image/atlas/allocator.rs index 7a4ff5b1..03effdcb 100644 --- a/wgpu/src/image/atlas/allocator.rs +++ b/wgpu/src/image/atlas/allocator.rs @@ -46,10 +46,10 @@ impl Region {          (rectangle.min.x as u32, rectangle.min.y as u32)      } -    pub fn size(&self) -> (u32, u32) { +    pub fn size(&self) -> iced_graphics::Size<u32> {          let size = self.allocation.rectangle.size(); -        (size.width as u32, size.height as u32) +        iced_graphics::Size::new(size.width as u32, size.height as u32)      }  } diff --git a/wgpu/src/image/atlas/entry.rs b/wgpu/src/image/atlas/entry.rs index 9b3f16df..69c05a50 100644 --- a/wgpu/src/image/atlas/entry.rs +++ b/wgpu/src/image/atlas/entry.rs @@ -1,17 +1,19 @@  use crate::image::atlas; +use iced_graphics::image; +use iced_graphics::Size; +  #[derive(Debug)]  pub enum Entry {      Contiguous(atlas::Allocation),      Fragmented { -        size: (u32, u32), +        size: Size<u32>,          fragments: Vec<Fragment>,      },  } -impl Entry { -    #[cfg(feature = "image_rs")] -    pub fn size(&self) -> (u32, u32) { +impl image::storage::Entry for Entry { +    fn size(&self) -> Size<u32> {          match self {              Entry::Contiguous(allocation) => allocation.size(),              Entry::Fragmented { size, .. } => *size,  | 
