Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion canvas/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ repository = "https://github.com/image-rs/canvas"
categories = ["multimedia::images"]

[dependencies]
image-texel = { path = "../texel", version = "0.3.0" }
image-texel = { path = "../texel", version = "0.4.0" }
bytemuck = "1.1"

[dev-dependencies]
Expand Down
4 changes: 2 additions & 2 deletions texel/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "image-texel"
version = "0.3.1"
version = "0.4.0"
edition = "2021"
rust-version = "1.77"
rust-version = "1.84"

description = "A texel type and allocated buffers suitable for image data."
authors = ["Aurelia Molzer <[email protected]>"]
Expand Down
11 changes: 11 additions & 0 deletions texel/Changes.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# v0.4.0

- Add `AtomicImage`, `CellImage` and several supporting types and interfaces.
These replicate large parts of the `Image` and `ImageMut` types but allow for
operations on a shared buffer, wrapping `Arc` and `Rc` respectively.
- Added `PlaneOf` trait, a relationship between a layout, and index, and a
subcomponent of the layout. All image reference types implement a form of
`into_planes` that splits them apart by those components.
- Added a `Relocate` trait for layouts that can be move to another location
in a buffer.

## v0.3.1

- Fix compilation on non-explicit targets, where the maximum alignment will
Expand Down
21 changes: 21 additions & 0 deletions texel/src/buf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,11 @@ impl AtomicBuffer {
}
}

/// Query if two buffers share the same memory region.
pub fn ptr_eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.inner, &other.inner)
}

/// Retrieve the byte capacity of the allocated storage.
pub fn capacity(&self) -> usize {
core::mem::size_of_val(&*self.inner)
Expand Down Expand Up @@ -1014,6 +1019,14 @@ impl cmp::PartialEq<[u8]> for cell_buf {

impl cmp::Eq for cell_buf {}

impl cmp::PartialEq for CellBuffer {
fn eq(&self, other: &Self) -> bool {
**self == **other
}
}

impl cmp::Eq for CellBuffer {}

impl TexelMappingBuffer for &'_ cell_buf {
/// Internally mapping function when the mapping can be done forwards.
fn map_forward<P, Q>(
Expand Down Expand Up @@ -1197,6 +1210,14 @@ impl cmp::PartialEq<[u8]> for atomic_buf {

impl cmp::Eq for atomic_buf {}

impl cmp::PartialEq for AtomicBuffer {
fn eq(&self, other: &Self) -> bool {
**self == **other
}
}

impl cmp::Eq for AtomicBuffer {}

impl TexelMappingBuffer for &'_ atomic_buf {
/// Internally mapping function when the mapping can be done forwards.
fn map_forward<P, Q>(
Expand Down
36 changes: 35 additions & 1 deletion texel/src/image/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,20 @@ use crate::{Texel, TexelBuffer};

/// A container of allocated bytes, parameterized over the layout.
///
/// This is a synchronized, shared equivalent to [`Image`][`crate::image::Image`]. That is the
/// buffer of bytes of this container is shared between clones of this value and potentially
/// between threads. In particular the same buffer may be owned and viewed with different layouts
/// and modified concurrently. The guarantee, however, is merely that concurrent modification is
/// free of undefined data races. There is no locking, implied synchronization, or ordering
/// guarantees between edits except when you can modify disjoint parts of the buffer.
///
/// ## Differences to owned Image
///
/// Comparing values of this type is possible, but requires calling the method [`Self::compare`] to
/// create a comparator. This is because comparing is inherently racing against modifications made
/// on other threads. While the implementation prevents any unsound *data races* there is no
/// specific meaning to any of its outcomes unless the caller ensure synchronization in some other
/// manner.
#[derive(Clone)]
pub struct AtomicImage<Layout = Bytes> {
inner: RawImage<AtomicBuffer, Layout>,
Expand All @@ -18,7 +31,8 @@ pub struct AtomicImage<Layout = Bytes> {
/// A partial view of an atomic image.
///
/// Note that this requires its underlying buffer to be highly aligned! For that reason it is not
/// possible to take a reference at an arbitrary number of bytes.
/// possible to take a reference at an arbitrary number of bytes. Values of this type are created
/// by calling [`AtomicImage::as_ref`] or [`AtomicImage::checked_to_ref`].
#[derive(Clone, PartialEq, Eq)]
pub struct AtomicImageRef<'buf, Layout = &'buf Bytes> {
inner: RawImage<&'buf atomic_buf, Layout>,
Expand Down Expand Up @@ -156,6 +170,26 @@ impl<L> AtomicImage<L> {
self.inner.fits(layout)
}

/// Check if two images refer to the same buffer.
pub fn ptr_eq(&self, other: &Self) -> bool {
AtomicBuffer::ptr_eq(self.inner.get(), other.inner.get())
}

/// Create a comparator to another image.
///
/// Note that comparing is inherently racing against modifications made on other threads. While
/// the implementation prevents any unsound *data races* there is no specific meaning to any of
/// its outcomes unless the caller ensure synchronization in some other manner.
///
/// You can also compare the allocation with [`Self::ptr_eq`] or ignore the layout and compare
/// buffer contents with [`Self::as_capacity_atomic_buf`].
pub fn compare(&self) -> impl core::cmp::Eq + core::cmp::PartialEq + '_
where
L: core::cmp::Eq,
{
(self.inner.layout(), self.inner.get())
}

/// Get a reference to the aligned unstructured bytes of the image.
///
/// Note that this may return more bytes than required for the specific layout for various
Expand Down
17 changes: 11 additions & 6 deletions texel/src/image/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ use core::cell::Cell;

/// A container of allocated bytes, parameterized over the layout.
///
/// ## Differences to owned Image
///
/// The implementations for [`PartialEq`] and [`Eq`] are not provided. In many containers and
/// contexts these two traits are required to rule out absence of interior mutability.
#[derive(Clone)]
/// This is a unsynchronized, shared equivalent to [`Image`][`crate::image::Image`]. That is the
/// buffer of bytes of this container is shared between clones of this value but can not be sent
/// between threads. In particular the same buffer may be owned and viewed with different layouts.
#[derive(Clone, PartialEq, Eq)]
pub struct CellImage<Layout = Bytes> {
inner: RawImage<CellBuffer, Layout>,
}

/// A partial view of an atomic image.
///
/// Note that this requires its underlying buffer to be highly aligned! For that reason it is not
/// possible to take a reference at an arbitrary number of bytes.
/// possible to take a reference at an arbitrary number of bytes. Values of this type are created
/// by calling [`CellImage::as_ref`] or [`CellImage::checked_to_ref`].
#[derive(Clone, PartialEq, Eq)]
pub struct CellImageRef<'buf, Layout = &'buf Bytes> {
inner: RawImage<&'buf cell_buf, Layout>,
Expand Down Expand Up @@ -160,6 +160,11 @@ impl<L> CellImage<L> {
self.inner.fits(layout)
}

/// Check if two images refer to the same buffer.
pub fn ptr_eq(&self, other: &Self) -> bool {
CellBuffer::ptr_eq(self.inner.get(), other.inner.get())
}

/// Get a reference to the aligned unstructured bytes of the image.
///
/// Note that this may return more bytes than required for the specific layout for various
Expand Down
5 changes: 5 additions & 0 deletions texel/src/image/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,11 @@ impl<B, L> RawImage<B, L> {
texel.cast_buf(self.as_buf())
}

/// Get mutable reference to the buffer.
pub(crate) fn get(&self) -> &B {
&self.buffer
}

/// Get a mutable reference to the buffer. It is inadvisible to modify the buffer in a way that
/// it can no longer hold the layout.
pub(crate) fn get_mut(&mut self) -> &mut B {
Expand Down
Loading