Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use &mut and mutex lock to safely make Image implement Send #19

Merged
merged 5 commits into from
Dec 8, 2024
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
1 change: 1 addition & 0 deletions pixman/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ image = "0.24.7"
[features]
default = []
drm-fourcc = ["dep:drm-fourcc"]
sync = []
8 changes: 4 additions & 4 deletions pixman/examples/alpha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub fn main() {
]);

let mut alpha = [0x4f00004fu32; WIDTH * HEIGHT]; /* pale blue */
let alpha_img = Image::from_slice_mut(
let mut alpha_img = Image::from_slice_mut(
FormatCode::A8R8G8B8,
WIDTH,
HEIGHT,
Expand All @@ -32,7 +32,7 @@ pub fn main() {
.unwrap();

let mut dest = [0xffffff00u32; WIDTH * HEIGHT]; /* yellow */
let dest_img = Image::from_slice_mut(
let mut dest_img = Image::from_slice_mut(
FormatCode::A8R8G8B8,
WIDTH,
HEIGHT,
Expand All @@ -53,7 +53,7 @@ pub fn main() {
)
.unwrap();

let grad_img = LinearGradient::new(p1, p2, &stops).unwrap();
let mut grad_img = LinearGradient::new(p1, p2, &stops).unwrap();
grad_img.set_transform(transform).unwrap();
grad_img.set_repeat(Repeat::Pad);

Expand All @@ -79,7 +79,7 @@ pub fn main() {
((10 * WIDTH) as u16, HEIGHT as u16),
);

let out_img = Image::new(
let mut out_img = Image::new(
FormatCode::A8B8G8R8,
dest_img.width(),
dest_img.height(),
Expand Down
6 changes: 3 additions & 3 deletions pixman/examples/checkerboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ const HEIGHT: usize = 400;
const TILE_SIZE: usize = 25;

pub fn main() {
let checkerboard = Image::new(FormatCode::A8R8G8B8, WIDTH, HEIGHT, false).unwrap();
let destination = Image::new(FormatCode::A8R8G8B8, WIDTH, HEIGHT, false).unwrap();
let mut checkerboard = Image::new(FormatCode::A8R8G8B8, WIDTH, HEIGHT, false).unwrap();
let mut destination = Image::new(FormatCode::A8R8G8B8, WIDTH, HEIGHT, false).unwrap();

// let transform = Transform::new([
// [-1.96830, -1.82250, 512.12250],
Expand Down Expand Up @@ -57,7 +57,7 @@ pub fn main() {
(WIDTH as u16, HEIGHT as u16),
);

let out_img = Image::new(
let mut out_img = Image::new(
FormatCode::A8B8G8R8,
destination.width(),
destination.height(),
Expand Down
6 changes: 3 additions & 3 deletions pixman/examples/clip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub fn main() {
let r_outer = Fixed::from(100.0);

let mut src = [0xff0000ffu32; WIDTH * HEIGHT];
let src_img = Image::from_slice_mut(
let mut src_img = Image::from_slice_mut(
FormatCode::A8R8G8B8,
WIDTH,
HEIGHT,
Expand Down Expand Up @@ -50,7 +50,7 @@ pub fn main() {
src_img.set_repeat(Repeat::Normal);

let mut dst = [0xffff0000u32; WIDTH * HEIGHT];
let dst_img = Image::from_slice_mut(
let mut dst_img = Image::from_slice_mut(
FormatCode::A8R8G8B8,
WIDTH,
HEIGHT,
Expand All @@ -70,7 +70,7 @@ pub fn main() {
(WIDTH as u16, HEIGHT as u16),
);

let out_img = Image::new(
let mut out_img = Image::new(
FormatCode::A8B8G8R8,
dst_img.width(),
dst_img.height(),
Expand Down
10 changes: 5 additions & 5 deletions pixman/examples/conical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ const HEIGHT: usize = SIZE * NUM_ROWS;
const NUM_GRADIENTS: usize = 35;

pub fn main() {
let dest_img = Image::new(FormatCode::A8R8G8B8, WIDTH, HEIGHT, false).unwrap();
let mut dest_img = Image::new(FormatCode::A8R8G8B8, WIDTH, HEIGHT, false).unwrap();

draw_checkerboard(&dest_img, 25, 0xffaaaaaa, 0xff888888);
draw_checkerboard(&mut dest_img, 25, 0xffaaaaaa, 0xff888888);

let transform = Transform::identity()
.translate(0.5, 0.5, true)
Expand All @@ -26,7 +26,7 @@ pub fn main() {
let column = i % GRADIENTS_PER_ROW;
let row = i / GRADIENTS_PER_ROW;

let src_img = create_conical(i);
let mut src_img = create_conical(i);
src_img.set_repeat(Repeat::Normal);
src_img.set_transform(transform).unwrap();

Expand All @@ -41,7 +41,7 @@ pub fn main() {
);
}

let out_img = Image::new(
let mut out_img = Image::new(
FormatCode::A8B8G8R8,
dest_img.width(),
dest_img.height(),
Expand Down Expand Up @@ -89,7 +89,7 @@ fn create_conical(index: usize) -> ConicalGradient<'static> {
.unwrap()
}

fn draw_checkerboard(image: &Image<'_, '_>, check_size: usize, color1: u32, color2: u32) {
fn draw_checkerboard(image: &mut Image<'_, '_>, check_size: usize, color1: u32, color2: u32) {
let c1 = Solid::new(color1).unwrap();
let c2 = Solid::new(color2).unwrap();

Expand Down
6 changes: 3 additions & 3 deletions pixman/examples/gradient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub fn main() {
]);

let mut dest = [0xff00ff00u32; WIDTH * HEIGHT];
let dest_img = Image::from_slice_mut(
let mut dest_img = Image::from_slice_mut(
FormatCode::A8R8G8B8,
WIDTH,
HEIGHT,
Expand All @@ -31,7 +31,7 @@ pub fn main() {
)
.unwrap();

let src_img = LinearGradient::new(p1, p2, &stops).unwrap();
let mut src_img = LinearGradient::new(p1, p2, &stops).unwrap();

src_img.set_transform(transform).unwrap();
src_img.set_repeat(Repeat::None);
Expand All @@ -46,7 +46,7 @@ pub fn main() {
((10 * WIDTH) as u16, HEIGHT as u16),
);

let out_img = Image::new(
let mut out_img = Image::new(
FormatCode::A8B8G8R8,
dest_img.width(),
dest_img.height(),
Expand Down
6 changes: 3 additions & 3 deletions pixman/examples/solid_fill.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use pixman::{FormatCode, Image, Operation, Repeat, Solid};

pub fn main() {
let dst = Image::new(FormatCode::A8R8G8B8, 800, 600, true).unwrap();
let solid = Solid::new([0xffff, 0xffff, 0xffff, 0xffff]).unwrap();
let mut dst = Image::new(FormatCode::A8R8G8B8, 800, 600, true).unwrap();
let mut solid = Solid::new([0xffff, 0xffff, 0xffff, 0xffff]).unwrap();
solid.set_repeat(Repeat::Normal);
dst.composite(
Operation::Over,
Expand All @@ -14,7 +14,7 @@ pub fn main() {
(50, 50),
);

let out_img = Image::new(FormatCode::A8B8G8R8, dst.width(), dst.height(), false).unwrap();
let mut out_img = Image::new(FormatCode::A8B8G8R8, dst.width(), dst.height(), false).unwrap();
out_img.composite(
Operation::Src,
&dst,
Expand Down
6 changes: 3 additions & 3 deletions pixman/examples/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ pub fn main() {
),
);

let mask_img =
let mut mask_img =
Image::from_slice_mut(FormatCode::A8, WIDTH, HEIGHT, &mut mbits, WIDTH, false).unwrap();
let src_img = Solid::new(white).unwrap();
let dest_img =
let mut dest_img =
Image::from_slice_mut(FormatCode::A8R8G8B8, WIDTH, HEIGHT, bits, WIDTH * 4, false).unwrap();

mask_img.add_traps((0, 0), &[trap]);
Expand All @@ -42,7 +42,7 @@ pub fn main() {
(WIDTH as u16, HEIGHT as u16),
);

let out_img = Image::new(
let mut out_img = Image::new(
FormatCode::A8B8G8R8,
dest_img.width(),
dest_img.height(),
Expand Down
4 changes: 2 additions & 2 deletions pixman/examples/tri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub fn main() {
}

let src_img = Solid::new(color).unwrap();
let dest_img = Image::from_slice_mut(
let mut dest_img = Image::from_slice_mut(
FormatCode::A8R8G8B8,
WIDTH,
HEIGHT,
Expand All @@ -38,7 +38,7 @@ pub fn main() {
&tris,
);

let out_img = Image::new(
let mut out_img = Image::new(
FormatCode::A8B8G8R8,
dest_img.width(),
dest_img.height(),
Expand Down
53 changes: 39 additions & 14 deletions pixman/src/image/bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,32 @@ pub struct Image<'bits, 'alpha> {
_alpha: PhantomData<&'alpha ()>,
}

impl<'bits, 'alpha> std::ops::Deref for Image<'bits, 'alpha> {
// SAFETY: A reference to the image is only created by `set_alpha_map`.
// Which returns a type with a lifetime bound, so `&mut self` methods cannot
// be called while this additional reference is in use.
//
// Thus the only mutability allowed is reference counting, which is made
// thread-safe with the `REF_COUNT_LOCK` mutex, used when calling
// `pixman_image_unref`, or `pixman_image_set_alpha_map`.
#[cfg(feature = "sync")]
unsafe impl Send for Image<'_, '_> {}
#[cfg(feature = "sync")]
unsafe impl Sync for Image<'_, '_> {}

impl std::ops::Deref for Image<'_, '_> {
type Target = ImageRef;

fn deref(&self) -> &Self::Target {
&self.image
}
}

impl std::ops::DerefMut for Image<'_, '_> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.image
}
}

impl Image<'static, 'static> {
/// Create a new image with the specified format and size
pub fn new(
Expand Down Expand Up @@ -134,6 +152,8 @@ impl<'bits, 'a> Image<'bits, 'a> {
x: i16,
y: i16,
) -> Image<'bits, 'alpha> {
#[cfg(feature = "sync")]
let _lock = crate::REF_COUNT_LOCK.lock().unwrap();
unsafe {
ffi::pixman_image_set_alpha_map(self.as_ptr(), alpha_map.as_ptr(), x, y);
}
Expand All @@ -146,6 +166,8 @@ impl<'bits, 'a> Image<'bits, 'a> {

/// Clear a previously set alpha map
pub fn clear_alpha_map(self) -> Image<'bits, 'static> {
#[cfg(feature = "sync")]
let _lock = crate::REF_COUNT_LOCK.lock().unwrap();
unsafe {
ffi::pixman_image_set_alpha_map(self.as_ptr(), std::ptr::null_mut(), 0, 0);
}
Expand All @@ -157,7 +179,7 @@ impl<'bits, 'a> Image<'bits, 'a> {
}
}

impl<'bits, 'alpha> Image<'bits, 'alpha> {
impl Image<'_, '_> {
/// Get the width of the image
pub fn width(&self) -> usize {
unsafe { ffi::pixman_image_get_width(self.as_ptr()) as usize }
Expand Down Expand Up @@ -195,7 +217,7 @@ impl<'bits, 'alpha> Image<'bits, 'alpha> {

/// Fill this image with the specified boxes and color
pub fn fill_boxes(
&self,
&mut self,
op: Operation,
color: impl Into<Color>,
boxes: &[Box32],
Expand All @@ -219,7 +241,7 @@ impl<'bits, 'alpha> Image<'bits, 'alpha> {

/// Fill this image with the specified rectangles and color
pub fn fill_rectangles(
&self,
&mut self,
op: Operation,
color: impl Into<Color>,
rects: &[Rectangle16],
Expand All @@ -244,7 +266,7 @@ impl<'bits, 'alpha> Image<'bits, 'alpha> {
/// Composite the specified src image into this image
#[allow(clippy::too_many_arguments)]
pub fn composite(
&self,
&mut self,
operation: Operation,
src: &ImageRef,
mask: Option<&ImageRef>,
Expand Down Expand Up @@ -280,7 +302,7 @@ impl<'bits, 'alpha> Image<'bits, 'alpha> {
/// Composite the specified src image into this image
#[allow(clippy::too_many_arguments)]
pub fn composite32(
&self,
&mut self,
operation: Operation,
src: &ImageRef,
mask: Option<&ImageRef>,
Expand Down Expand Up @@ -314,7 +336,7 @@ impl<'bits, 'alpha> Image<'bits, 'alpha> {

/// Composite the specified triangles into this image
pub fn composite_triangles(
&self,
&mut self,
operation: Operation,
src: &ImageRef,
mask_format: FormatCode,
Expand All @@ -340,7 +362,7 @@ impl<'bits, 'alpha> Image<'bits, 'alpha> {

/// Composite the specified trapezoids into this image
pub fn composite_trapezoids(
&self,
&mut self,
operation: Operation,
src: &ImageRef,
mask_format: FormatCode,
Expand All @@ -365,7 +387,7 @@ impl<'bits, 'alpha> Image<'bits, 'alpha> {
}

/// Add the specified traps to this image
pub fn add_traps(&self, offset: (i16, i16), traps: &[Trap]) {
pub fn add_traps(&mut self, offset: (i16, i16), traps: &[Trap]) {
unsafe {
ffi::pixman_add_traps(
self.as_ptr(),
Expand All @@ -378,7 +400,7 @@ impl<'bits, 'alpha> Image<'bits, 'alpha> {
}

/// Add the specified trapezoids to this image
pub fn add_trapezoids(&self, offset: (i16, i32), traps: &[Trapezoid]) {
pub fn add_trapezoids(&mut self, offset: (i16, i32), traps: &[Trapezoid]) {
unsafe {
ffi::pixman_add_trapezoids(
self.as_ptr(),
Expand All @@ -391,7 +413,7 @@ impl<'bits, 'alpha> Image<'bits, 'alpha> {
}

/// Add the specified triangles to this image
pub fn add_triangles(&self, offset: (i32, i32), tris: &[Triangle]) {
pub fn add_triangles(&mut self, offset: (i32, i32), tris: &[Triangle]) {
unsafe {
ffi::pixman_add_triangles(
self.as_ptr(),
Expand Down Expand Up @@ -444,7 +466,7 @@ impl<'bits, 'alpha> Image<'bits, 'alpha> {
}

/// Rasterize the specified edges
pub fn rasterize_edges(&self, l: Edge, r: Edge, t: impl Into<Fixed>, b: impl Into<Fixed>) {
pub fn rasterize_edges(&mut self, l: Edge, r: Edge, t: impl Into<Fixed>, b: impl Into<Fixed>) {
unsafe {
ffi::pixman_rasterize_edges(
self.as_ptr(),
Expand All @@ -457,18 +479,21 @@ impl<'bits, 'alpha> Image<'bits, 'alpha> {
}

/// Rasterize the specified trapezoids
pub fn rasterize_trapezoid(&self, trap: Trapezoid, offset: (i32, i32)) {
pub fn rasterize_trapezoid(&mut self, trap: Trapezoid, offset: (i32, i32)) {
unsafe { ffi::pixman_rasterize_trapezoid(self.as_ptr(), trap.as_ptr(), offset.0, offset.1) }
}
}

impl<'bits, 'alpha> Image<'bits, 'alpha> {
impl Image<'_, '_> {
/// Initialize the image from a raw pointer
///
/// # Safety
///
/// The pointer is expected to be valid and have a ref-count of at least one.
/// Ownership of the pointer is transferred and unref will be called on drop.
///
/// Any other references to the `pixman_image_t` must not be mutated while this
/// `Image` exists, including changes to the reference count.
pub unsafe fn from_ptr(ptr: *mut ffi::pixman_image_t) -> Self {
Self {
image: unsafe { ImageRef::from_ptr(ptr) },
Expand Down
Loading
Loading