From 0c4574cc36c36acea9aeb315676e8eeeebdb1266 Mon Sep 17 00:00:00 2001 From: Pavel Sountsov Date: Tue, 10 Jun 2025 21:54:50 -0700 Subject: [PATCH 1/4] Bind vertex/index buffers. --- allegro_primitives-sys/src/lib.rs | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/allegro_primitives-sys/src/lib.rs b/allegro_primitives-sys/src/lib.rs index c41570f30..3309bae02 100644 --- a/allegro_primitives-sys/src/lib.rs +++ b/allegro_primitives-sys/src/lib.rs @@ -62,6 +62,11 @@ pub mod allegro_primitives pub const ALLEGRO_LINE_CAP_TRIANGLE: c_uint = 3; pub const ALLEGRO_LINE_CAP_CLOSED: c_uint = 4; + pub const ALLEGRO_PRIM_BUFFER_STREAM: c_uint = 0x01; + pub const ALLEGRO_PRIM_BUFFER_STATIC: c_uint = 0x02; + pub const ALLEGRO_PRIM_BUFFER_DYNAMIC: c_uint = 0x04; + pub const ALLEGRO_PRIM_BUFFER_READWRITE: c_uint = 0x08; + #[repr(C)] #[derive(Copy, Clone)] pub struct ALLEGRO_VERTEX_ELEMENT @@ -87,6 +92,9 @@ pub mod allegro_primitives pub color: ALLEGRO_COLOR, } + opaque!(ALLEGRO_VERTEX_BUFFER); + opaque!(ALLEGRO_INDEX_BUFFER); + extern "C" { pub fn al_get_allegro_primitives_version() -> u32; pub fn al_init_primitives_addon() -> c_bool; @@ -228,5 +236,34 @@ pub mod allegro_primitives pub fn al_draw_filled_polygon_with_holes( vertices: *const c_float, vertex_counts: *const c_int, color: ALLEGRO_COLOR, ); + + pub fn al_create_vertex_buffer( + decl: *mut ALLEGRO_VERTEX_DECL, initial_data: *const c_void, num_vertices: c_int, + flags: c_int, + ) -> *mut ALLEGRO_VERTEX_BUFFER; + + pub fn al_destroy_vertex_buffer(buffer: *mut ALLEGRO_VERTEX_BUFFER); + + pub fn al_lock_vertex_buffer( + buffer: *mut ALLEGRO_VERTEX_BUFFER, offset: c_int, length: c_int, flags: c_int, + ) -> *mut c_void; + + pub fn al_unlock_vertex_buffer(buffer: *mut ALLEGRO_VERTEX_BUFFER); + + pub fn al_get_vertex_buffer_size(buffer: *mut ALLEGRO_VERTEX_BUFFER) -> c_int; + + pub fn al_create_index_buffer( + index_size: c_int, initial_data: *const c_void, num_indices: c_int, flags: c_int, + ) -> *mut ALLEGRO_INDEX_BUFFER; + + pub fn al_destroy_index_buffer(buffer: *mut ALLEGRO_INDEX_BUFFER); + + pub fn al_lock_index_buffer( + buffer: *mut ALLEGRO_INDEX_BUFFER, offset: c_int, length: c_int, flags: c_int, + ) -> *mut c_void; + + pub fn al_unlock_index_buffer(buffer: *mut ALLEGRO_INDEX_BUFFER); + + pub fn al_get_index_buffer_size(buffer: *mut ALLEGRO_INDEX_BUFFER) -> c_int; } } From bd00b2e3dbbe7809c96dfcce3197b965edec6589 Mon Sep 17 00:00:00 2001 From: Pavel Sountsov Date: Fri, 13 Jun 2025 02:14:40 -0700 Subject: [PATCH 2/4] Wrap vertex/index buffers. --- allegro/src/display.rs | 15 ++ allegro_primitives-sys/src/lib.rs | 9 + allegro_primitives/Cargo.toml | 5 + allegro_primitives/src/lib.rs | 416 ++++++++++++++++++++++++++++-- examples/Cargo.toml | 5 + examples/vertex_buffer.rs | 90 +++++++ 6 files changed, 518 insertions(+), 22 deletions(-) create mode 100644 examples/vertex_buffer.rs diff --git a/allegro/src/display.rs b/allegro/src/display.rs index 27310442c..d85b8527c 100644 --- a/allegro/src/display.rs +++ b/allegro/src/display.rs @@ -112,6 +112,7 @@ pub struct Display backbuffer: Bitmap, #[cfg(any(allegro_5_2_0, allegro_5_1_0))] shaders: Vec>, + tokens: Vec>, } impl Display @@ -139,6 +140,7 @@ impl Display Display { allegro_display: d, backbuffer: backbuffer, + tokens: vec![], } } @@ -149,6 +151,7 @@ impl Display allegro_display: d, backbuffer: backbuffer, shaders: vec![], + tokens: vec![], } } @@ -346,6 +349,11 @@ impl Display Err(()) } } + + pub fn add_dependency_token(&mut self, token: Arc) + { + self.tokens.push(token); + } } unsafe impl Send for Display {} @@ -355,6 +363,13 @@ impl Drop for Display { fn drop(&mut self) { + for token in &self.tokens + { + if Arc::strong_count(&token) != 1 + { + panic!("Have an outstanding dependency token! Token name: {}", token); + } + } if self.has_outstanding_shaders() { panic!("Display has outstanding shaders!"); diff --git a/allegro_primitives-sys/src/lib.rs b/allegro_primitives-sys/src/lib.rs index 3309bae02..e059ceb18 100644 --- a/allegro_primitives-sys/src/lib.rs +++ b/allegro_primitives-sys/src/lib.rs @@ -108,6 +108,15 @@ pub mod allegro_primitives vtxs: *const c_void, decl: *const ALLEGRO_VERTEX_DECL, texture: *mut ALLEGRO_BITMAP, indices: *const c_int, num_vtx: c_int, _type: c_int, ) -> c_int; + pub fn al_draw_vertex_buffer( + vertex_buffer: *mut ALLEGRO_VERTEX_BUFFER, texture: *mut ALLEGRO_BITMAP, start: c_int, + end: c_int, type_: c_int, + ) -> c_int; + + pub fn al_draw_indexed_buffer( + vertex_buffer: *mut ALLEGRO_VERTEX_BUFFER, texture: *mut ALLEGRO_BITMAP, + index_buffer: *mut ALLEGRO_INDEX_BUFFER, start: c_int, end: c_int, type_: c_int, + ) -> c_int; pub fn al_create_vertex_decl( elements: *const ALLEGRO_VERTEX_ELEMENT, stride: c_int, diff --git a/allegro_primitives/Cargo.toml b/allegro_primitives/Cargo.toml index 2b0e8ce48..4840d34dc 100644 --- a/allegro_primitives/Cargo.toml +++ b/allegro_primitives/Cargo.toml @@ -40,3 +40,8 @@ version = "=0.0.48" #auto path = "../allegro_primitives-sys" version = "=0.0.48" #auto + +[dependencies.allegro_util] + +path = "../allegro_util" +version = "=0.0.48" #auto diff --git a/allegro_primitives/src/lib.rs b/allegro_primitives/src/lib.rs index 2f5dfe88d..30cdcb607 100644 --- a/allegro_primitives/src/lib.rs +++ b/allegro_primitives/src/lib.rs @@ -9,14 +9,20 @@ extern crate allegro; extern crate allegro_primitives_sys; extern crate allegro_sys; +#[macro_use] +extern crate allegro_util; extern crate libc; -use allegro::{BitmapLike, Color, Core}; +use allegro::{BitmapLike, Color, Core, Display}; use allegro_primitives_sys::*; use allegro_sys::*; +use allegro_util::Flag; use libc::*; +use std::marker::PhantomData; +use std::mem::MaybeUninit; use std::ptr; +use std::sync::Arc; #[repr(u32)] #[derive(Copy, Clone)] @@ -95,16 +101,16 @@ impl PrimitivesAddon unsafe { al_get_allegro_primitives_version() as i32 } } - pub fn draw_prim( - &self, vtxs: &T, texture: Option<&B>, start: u32, end: u32, type_: PrimType, + pub fn draw_prim( + &self, vtxs: &[T], texture: Option<&B>, start: u32, end: u32, type_: PrimType, ) -> u32 { check_valid_target_bitmap(); let tex = texture.map_or(ptr::null_mut(), |bmp| bmp.get_allegro_bitmap()); unsafe { al_draw_prim( - vtxs.get_ptr() as *const _, - T::VertexType::get_decl(self).get_allegro_decl(), + vtxs.as_ptr() as *const _, + T::get_decl(self).get_allegro_decl(), tex, start as c_int, end as c_int, @@ -113,8 +119,8 @@ impl PrimitivesAddon } } - pub fn draw_indexed_prim( - &self, vtxs: &T, texture: Option<&B>, indices: &[i32], start: u32, end: u32, + pub fn draw_indexed_prim( + &self, vtxs: &[T], texture: Option<&B>, indices: &[i32], start: u32, end: u32, type_: PrimType, ) -> u32 { @@ -122,8 +128,8 @@ impl PrimitivesAddon let tex = texture.map_or(ptr::null_mut(), |bmp| bmp.get_allegro_bitmap()); unsafe { al_draw_indexed_prim( - vtxs.get_ptr() as *const _, - T::VertexType::get_decl(self).get_allegro_decl(), + vtxs.as_ptr() as *const _, + T::get_decl(self).get_allegro_decl(), tex, indices[start as usize..].as_ptr(), (end - start) as c_int, @@ -132,6 +138,43 @@ impl PrimitivesAddon } } + pub fn draw_vertex_buffer( + &self, vertex_buffer: &VertexBuffer, texture: Option<&B>, start: u32, end: u32, + type_: PrimType, + ) -> u32 + { + check_valid_target_bitmap(); + let tex = texture.map_or(ptr::null_mut(), |bmp| bmp.get_allegro_bitmap()); + unsafe { + al_draw_vertex_buffer( + vertex_buffer.get_allegro_buffer(), + tex, + start as c_int, + end as c_int, + type_ as c_int, + ) as u32 + } + } + + pub fn draw_indexed_buffer( + &self, vertex_buffer: &VertexBuffer, texture: Option<&B>, index_buffer: &IndexBuffer, + start: u32, end: u32, type_: PrimType, + ) -> u32 + { + check_valid_target_bitmap(); + let tex = texture.map_or(ptr::null_mut(), |bmp| bmp.get_allegro_bitmap()); + unsafe { + al_draw_indexed_buffer( + vertex_buffer.get_allegro_buffer(), + tex, + index_buffer.get_allegro_buffer(), + start as c_int, + end as c_int, + type_ as c_int, + ) as u32 + } + } + pub fn draw_line(&self, x1: f32, y1: f32, x2: f32, y2: f32, color: Color, thickness: f32) { check_valid_target_bitmap(); @@ -711,15 +754,6 @@ impl Drop for VertexDecl } } -pub trait VertexSource -{ - type VertexType: VertexType; - fn get_ptr(&self) -> *const u8 - { - ptr::null() - } -} - pub unsafe trait VertexType { fn get_decl(prim: &PrimitivesAddon) -> VertexDecl; @@ -733,12 +767,350 @@ unsafe impl VertexType for Vertex } } -impl VertexSource for [T] +flag_type! { + BufferFlags + { + BUFFER_STREAM = ALLEGRO_PRIM_BUFFER_STREAM, + BUFFER_STATIC = ALLEGRO_PRIM_BUFFER_STATIC, + BUFFER_DYNAMIC = ALLEGRO_PRIM_BUFFER_DYNAMIC, + BUFFER_READWRITE = ALLEGRO_PRIM_BUFFER_READWRITE + } +} + +pub struct VertexBufferLock<'l, T: VertexType, D> +{ + buffer: &'l mut VertexBuffer, + data: *mut [D], +} + +impl<'l, T: VertexType, D> VertexBufferLock<'l, T, D> +{ + pub fn as_mut(&mut self) -> &mut [D] + { + unsafe { self.data.as_mut().unwrap() } + } +} + +impl<'l, T: VertexType + Copy> VertexBufferLock<'l, T, MaybeUninit> +{ + pub fn copy_from_slice(&mut self, src: &[T]) + { + for (d, s) in &mut self.as_mut().iter_mut().zip(src.iter()) + { + d.write(*s); + } + } +} + +impl<'l, T: VertexType, D> Drop for VertexBufferLock<'l, T, D> +{ + fn drop(&mut self) + { + unsafe { + al_unlock_vertex_buffer(self.buffer.vertex_buffer); + } + } +} + +pub struct VertexBuffer +{ + vertex_buffer: *mut ALLEGRO_VERTEX_BUFFER, + #[allow(dead_code)] + vertex_decl: VertexDecl, // Needs to be alive while the buffer is alive. + vertex_type: PhantomData, + #[allow(dead_code)] + token: Arc, +} + +impl VertexBuffer +{ + pub fn new( + display: &mut Display, prim: &PrimitivesAddon, init_data: Option<&[T]>, size: u32, flags: BufferFlags, + ) -> Result + { + let token = Arc::new("VertexBuffer".to_string()); + display.add_dependency_token(token.clone()); + let vertex_decl = T::get_decl(prim); + if let Some(init_data) = init_data + { + if init_data.len() as u32 != size + { + return Err(()); + } + } + let vertex_buffer = unsafe { + al_create_vertex_buffer( + vertex_decl.get_allegro_decl() as *mut _, + init_data.map_or(ptr::null_mut(), |v| v.as_ptr() as *const _), + size as c_int, + flags.get() as c_int, + ) + }; + + if vertex_buffer.is_null() + { + Err(()) + } + else + { + Ok(VertexBuffer { + vertex_buffer: vertex_buffer, + vertex_decl: vertex_decl, + vertex_type: PhantomData, + token: token, + }) + } + } + + /// Locks the buffer for reading and optionally writing. + pub fn lock(&mut self, start: u32, len: u32, write: bool) + -> Result, ()> + { + let data = unsafe { + al_lock_vertex_buffer( + self.vertex_buffer, + start as c_int, + len as c_int, + if write + { + ALLEGRO_LOCK_READWRITE as c_int + } + else + { + ALLEGRO_LOCK_READONLY as c_int + }, + ) + }; + if data.is_null() + { + Err(()) + } + else + { + unsafe { + Ok(VertexBufferLock { + buffer: self, + data: std::slice::from_raw_parts_mut(data as *mut T, len as usize), + }) + } + } + } + + /// Locks the buffer for only writing. + /// + /// This is unsafe because the contents of the lock are undefined. + pub fn lock_write_only( + &mut self, start: u32, len: u32, + ) -> Result>, ()> + { + let data = unsafe { + al_lock_vertex_buffer( + self.vertex_buffer, + start as c_int, + len as c_int, + ALLEGRO_LOCK_WRITEONLY as c_int, + ) + }; + if data.is_null() + { + Err(()) + } + else + { + unsafe { + Ok(VertexBufferLock { + buffer: self, + data: std::slice::from_raw_parts_mut(data as *mut MaybeUninit, len as usize), + }) + } + } + } + + pub fn len(&mut self) -> u32 + { + unsafe { al_get_vertex_buffer_size(self.vertex_buffer) as u32 } + } + + pub fn get_allegro_buffer(&self) -> *mut ALLEGRO_VERTEX_BUFFER + { + self.vertex_buffer + } +} + +impl Drop for VertexBuffer +{ + fn drop(&mut self) + { + unsafe { + al_destroy_vertex_buffer(self.vertex_buffer); + } + } +} + +pub unsafe trait IndexType {} + +unsafe impl IndexType for u16 {} +unsafe impl IndexType for u32 {} + +pub struct IndexBufferLock<'l, T: IndexType, D> +{ + buffer: &'l mut IndexBuffer, + data: *mut [D], +} + +impl<'l, T: IndexType, D> IndexBufferLock<'l, T, D> +{ + pub fn as_mut(&mut self) -> &mut [D] + { + unsafe { self.data.as_mut().unwrap() } + } +} + +impl<'l, T: IndexType + Copy> IndexBufferLock<'l, T, MaybeUninit> +{ + pub fn copy_from_slice(&mut self, src: &[T]) + { + for (d, s) in &mut self.as_mut().iter_mut().zip(src.iter()) + { + d.write(*s); + } + } +} + +impl<'l, T: IndexType, D> Drop for IndexBufferLock<'l, T, D> +{ + fn drop(&mut self) + { + unsafe { + al_unlock_index_buffer(self.buffer.index_buffer); + } + } +} + +pub struct IndexBuffer +{ + index_buffer: *mut ALLEGRO_INDEX_BUFFER, + index_type: PhantomData, + #[allow(dead_code)] + token: Arc, +} + +impl IndexBuffer { - type VertexType = T; + pub fn new( + display: &mut Display, _: &PrimitivesAddon, init_data: Option<&[T]>, size: u32, flags: BufferFlags, + ) -> Result + { + let token = Arc::new("IndexBuffer".to_string()); + display.add_dependency_token(token.clone()); + if let Some(init_data) = init_data + { + if init_data.len() as u32 != size + { + return Err(()); + } + } + let index_buffer = unsafe { + al_create_index_buffer( + size_of::() as c_int, + init_data.map_or(ptr::null_mut(), |v| v.as_ptr() as *const _), + size as c_int, + flags.get() as c_int, + ) + }; + + if index_buffer.is_null() + { + Err(()) + } + else + { + Ok(IndexBuffer { + index_buffer: index_buffer, + index_type: PhantomData, + token: token, + }) + } + } + + /// Locks the buffer for reading and optionally writing. + pub fn lock(&mut self, start: u32, len: u32, write: bool) -> Result, ()> + { + let data = unsafe { + al_lock_index_buffer( + self.index_buffer, + start as c_int, + len as c_int, + if write + { + ALLEGRO_LOCK_READWRITE as c_int + } + else + { + ALLEGRO_LOCK_READONLY as c_int + }, + ) + }; + if data.is_null() + { + Err(()) + } + else + { + unsafe { + Ok(IndexBufferLock { + buffer: self, + data: std::slice::from_raw_parts_mut(data as *mut T, len as usize), + }) + } + } + } + + /// Locks the buffer for only writing. + pub fn lock_write_only( + &mut self, start: u32, len: u32, + ) -> Result>, ()> + { + let data = unsafe { + al_lock_index_buffer( + self.index_buffer, + start as c_int, + len as c_int, + ALLEGRO_LOCK_WRITEONLY as c_int, + ) + }; + if data.is_null() + { + Err(()) + } + else + { + unsafe { + Ok(IndexBufferLock { + buffer: self, + data: std::slice::from_raw_parts_mut(data as *mut MaybeUninit, len as usize), + }) + } + } + } - fn get_ptr(&self) -> *const u8 + pub fn len(&mut self) -> u32 { - self.as_ptr() as *const _ + unsafe { al_get_index_buffer_size(self.index_buffer) as u32 } + } + + pub fn get_allegro_buffer(&self) -> *mut ALLEGRO_INDEX_BUFFER + { + self.index_buffer + } +} + +impl Drop for IndexBuffer +{ + fn drop(&mut self) + { + unsafe { + al_destroy_index_buffer(self.index_buffer); + } } } diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 1978cff9d..4b8f227e9 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -49,6 +49,11 @@ path = "synth_example.rs" name = "user_events" path = "user_events.rs" +[[bin]] + +name = "vertex_buffer" +path = "vertex_buffer.rs" + [dependencies] getopts = "=0.2.21" diff --git a/examples/vertex_buffer.rs b/examples/vertex_buffer.rs new file mode 100644 index 000000000..ea7573251 --- /dev/null +++ b/examples/vertex_buffer.rs @@ -0,0 +1,90 @@ +// This file is released into Public Domain. +extern crate allegro; +extern crate allegro_primitives; +extern crate getopts; + +use allegro::*; +use allegro_primitives::*; +use getopts::*; +use std::env; + +#[cfg(any(allegro_5_2_0, allegro_5_1_0))] +allegro_main! { + let args = env::args().collect::>(); + + let mut opts = Options::new(); + opts.optflag("i", "init-only", "only initialize Allegro, don't do anything else"); + let matches = opts.parse(&args[1..]).unwrap(); + + let init_only = matches.opt_present("i"); + + let core = Core::init().unwrap(); + let prim = PrimitivesAddon::init(&core).unwrap(); + + if init_only + { + return; + } + + let mut disp = Display::new(&core, 800, 600).unwrap(); + disp.set_window_title("Vertex Buffer example"); + + let timer = Timer::new(&core, 1.0 / 60.0).unwrap(); + + let q = EventQueue::new(&core).unwrap(); + q.register_event_source(disp.get_event_source()); + q.register_event_source(timer.get_event_source()); + + let black = Color::from_rgb_f(0.0, 0.0, 0.0); + + let mut vertex_buffer = VertexBuffer::::new(&mut disp, &prim, None, 4, BUFFER_STREAM).unwrap(); + let mut index_buffer = IndexBuffer::::new(&mut disp, &prim, None, 6, BUFFER_STREAM).unwrap(); + + { + let mut lock = vertex_buffer.lock_write_only(0, 4).unwrap(); + lock.copy_from_slice(&[ + Vertex { x: 0.0, y: 0.0, z: 0.0, color: Color::from_rgb_f(1., 0., 0.), u: 0., v: 0., }, + Vertex { x: 500.0, y: 0.0, z: 0.0, color: Color::from_rgb_f(1., 1., 0.), u: 0., v: 0., }, + Vertex { x: 500.0, y: 500.0, z: 0.0, color: Color::from_rgb_f(0., 1., 1.), u: 0., v: 0., }, + Vertex { x: 0.0, y: 500.0, z: 0.0, color: Color::from_rgb_f(0., 0., 1.), u: 0., v: 0., }, + ]); + } + { + let mut lock = index_buffer.lock_write_only(0, 6).unwrap(); + lock.copy_from_slice(&[0, 1, 2, 0, 2, 3]); + } + + let mut redraw = true; + timer.start(); + 'exit: loop + { + if redraw && q.is_empty() + { + core.clear_to_color(black); + + prim.draw_indexed_buffer(&vertex_buffer, Option::<&Bitmap>::None, &index_buffer, 0, 6, PrimType::TriangleList); + + core.flip_display(); + redraw = false; + } + + match q.wait_for_event() + { + DisplayClose{..} => + { + break 'exit; + }, + TimerTick{..} => + { + redraw = true; + }, + _ => () + } + } +} + +#[cfg(not(any(allegro_5_2_0, allegro_5_1_0)))] +fn main() +{ + panic!("This example needs at least Allegro 5.1"); +} From b95a0fb23446cf48a6b2222296915812de97b7e1 Mon Sep 17 00:00:00 2001 From: Pavel Sountsov Date: Fri, 13 Jun 2025 02:29:46 -0700 Subject: [PATCH 3/4] Switch shaders to use the token system. --- allegro/src/display.rs | 55 +----------------------------------------- allegro/src/shader.rs | 31 +++++++++++++++++++++--- examples/shaders.rs | 10 ++++---- 3 files changed, 34 insertions(+), 62 deletions(-) diff --git a/allegro/src/display.rs b/allegro/src/display.rs index d85b8527c..eec44ef43 100644 --- a/allegro/src/display.rs +++ b/allegro/src/display.rs @@ -12,10 +12,9 @@ use events::EventSource; use ffi::*; use libc::*; #[cfg(any(allegro_5_2_0, allegro_5_1_0))] -use shader::{Shader, ShaderPlatform}; use std::ffi::CString; use std::mem; -use std::sync::{Arc, Weak}; +use std::sync::Arc; flag_type! { DisplayFlags @@ -111,7 +110,6 @@ pub struct Display allegro_display: *mut ALLEGRO_DISPLAY, backbuffer: Bitmap, #[cfg(any(allegro_5_2_0, allegro_5_1_0))] - shaders: Vec>, tokens: Vec>, } @@ -150,7 +148,6 @@ impl Display Display { allegro_display: d, backbuffer: backbuffer, - shaders: vec![], tokens: vec![], } } @@ -282,52 +279,6 @@ impl Display self.allegro_display } - /// Create a new shader associated with this display. - /// - /// Note that display destruction will panic if a strong reference is held - /// to a shader at that time. - #[cfg(any(allegro_5_2_0, allegro_5_1_0))] - pub fn create_shader(&mut self, platform: ShaderPlatform) -> Result, ()> - { - let shader; - unsafe { - let old_target = al_get_target_bitmap(); - al_set_target_bitmap(self.get_backbuffer().get_allegro_bitmap()); - shader = al_create_shader(platform as ALLEGRO_SHADER_PLATFORM); - al_set_target_bitmap(old_target); - }; - if !shader.is_null() - { - let shader = unsafe { Arc::new(Shader::wrap(shader)) }; - let ret = Arc::downgrade(&shader); - self.shaders.push(shader); - Ok(ret) - } - else - { - Err(()) - } - } - - #[cfg(any(allegro_5_2_0, allegro_5_1_0))] - fn has_outstanding_shaders(&self) -> bool - { - for shader in &self.shaders - { - if Arc::strong_count(&shader) != 1 - { - return true; - } - } - false - } - - #[cfg(not(any(allegro_5_2_0, allegro_5_1_0)))] - fn has_outstanding_shaders(&self) -> bool - { - false - } - pub fn show_cursor(&self, show: bool) -> Result<(), ()> { let ret = unsafe { @@ -370,10 +321,6 @@ impl Drop for Display panic!("Have an outstanding dependency token! Token name: {}", token); } } - if self.has_outstanding_shaders() - { - panic!("Display has outstanding shaders!"); - } unsafe { check_display_targeted_elsewhere(self.allegro_display, "destroy"); al_destroy_display(self.allegro_display); diff --git a/allegro/src/shader.rs b/allegro/src/shader.rs index 3c78f15d6..c3a2dba27 100644 --- a/allegro/src/shader.rs +++ b/allegro/src/shader.rs @@ -2,11 +2,14 @@ // // All rights reserved. Distributed under ZLib. For full terms see the file LICENSE. +use bitmap_like::BitmapLike; +use display::Display; use ffi::*; use libc::*; use std::ffi::{CStr, CString}; use std::ptr; +use std::sync::Arc; /// Shader platform. #[repr(u32)] @@ -47,14 +50,36 @@ pub enum ShaderType pub struct Shader { allegro_shader: *mut ALLEGRO_SHADER, + #[allow(dead_code)] + token: Arc, } impl Shader { - pub unsafe fn wrap(shader: *mut ALLEGRO_SHADER) -> Shader + /// Create a new shader associated with this display. + /// + /// Note that display destruction will panic if a shader remains alive at that time. + pub fn new(display: &mut Display, platform: ShaderPlatform) -> Result { - Shader { - allegro_shader: shader, + let shader; + unsafe { + let old_target = al_get_target_bitmap(); + al_set_target_bitmap(display.get_backbuffer().get_allegro_bitmap()); + shader = al_create_shader(platform as ALLEGRO_SHADER_PLATFORM); + al_set_target_bitmap(old_target); + }; + if !shader.is_null() + { + let token = Arc::new("Shader".to_string()); + display.add_dependency_token(token.clone()); + Ok(Shader { + allegro_shader: shader, + token: token, + }) + } + else + { + Err(()) } } diff --git a/examples/shaders.rs b/examples/shaders.rs index d148d246b..4317800e3 100644 --- a/examples/shaders.rs +++ b/examples/shaders.rs @@ -40,9 +40,9 @@ allegro_main! { let bmp = Bitmap::load(&core, "data/mysha.pcx").unwrap(); let black = Color::from_rgb_f(0.0, 0.0, 0.0); - let shader = disp.create_shader(ShaderPlatform::GLSL).unwrap(); + let shader = Shader::new(&mut disp, ShaderPlatform::GLSL).unwrap(); - shader.upgrade().unwrap().attach_shader_source(ShaderType::Vertex, Some( + shader.attach_shader_source(ShaderType::Vertex, Some( " attribute vec4 al_pos; attribute vec4 al_color; @@ -57,7 +57,7 @@ allegro_main! { gl_Position = al_projview_matrix * al_pos; } ")).unwrap(); - shader.upgrade().unwrap().attach_shader_source(ShaderType::Pixel, Some( + shader.attach_shader_source(ShaderType::Pixel, Some( " #ifdef GL_ES precision mediump float; @@ -75,7 +75,7 @@ allegro_main! { gl_FragColor = tmp; } ")).unwrap(); - shader.upgrade().unwrap().build().unwrap(); + shader.build().unwrap(); let tint = vec![[1.0f32, 0.0, 0.0]]; let mut redraw = true; @@ -86,7 +86,7 @@ allegro_main! { { core.set_target_bitmap(Some(&buffer)); core.clear_to_color(black); - core.use_shader(Some(&*shader.upgrade().unwrap())).unwrap(); + core.use_shader(Some(&shader)).unwrap(); core.set_shader_uniform("tint", &tint[..]).unwrap(); core.draw_bitmap(&bmp, 0.0, 0.0, Flag::zero()); From 14d4e53a9ad33fd036693f08d26e1e807e225e3c Mon Sep 17 00:00:00 2001 From: SiegeLord Date: Fri, 13 Jun 2025 02:32:58 -0700 Subject: [PATCH 4/4] Formatting --- allegro/src/display.rs | 5 ++++- allegro_primitives/src/lib.rs | 8 +++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/allegro/src/display.rs b/allegro/src/display.rs index eec44ef43..77bcb2e5c 100644 --- a/allegro/src/display.rs +++ b/allegro/src/display.rs @@ -318,7 +318,10 @@ impl Drop for Display { if Arc::strong_count(&token) != 1 { - panic!("Have an outstanding dependency token! Token name: {}", token); + panic!( + "Have an outstanding dependency token! Token name: {}", + token + ); } } unsafe { diff --git a/allegro_primitives/src/lib.rs b/allegro_primitives/src/lib.rs index 30cdcb607..03b523156 100644 --- a/allegro_primitives/src/lib.rs +++ b/allegro_primitives/src/lib.rs @@ -816,7 +816,7 @@ pub struct VertexBuffer { vertex_buffer: *mut ALLEGRO_VERTEX_BUFFER, #[allow(dead_code)] - vertex_decl: VertexDecl, // Needs to be alive while the buffer is alive. + vertex_decl: VertexDecl, // Needs to be alive while the buffer is alive. vertex_type: PhantomData, #[allow(dead_code)] token: Arc, @@ -825,7 +825,8 @@ pub struct VertexBuffer impl VertexBuffer { pub fn new( - display: &mut Display, prim: &PrimitivesAddon, init_data: Option<&[T]>, size: u32, flags: BufferFlags, + display: &mut Display, prim: &PrimitivesAddon, init_data: Option<&[T]>, size: u32, + flags: BufferFlags, ) -> Result { let token = Arc::new("VertexBuffer".to_string()); @@ -998,7 +999,8 @@ pub struct IndexBuffer impl IndexBuffer { pub fn new( - display: &mut Display, _: &PrimitivesAddon, init_data: Option<&[T]>, size: u32, flags: BufferFlags, + display: &mut Display, _: &PrimitivesAddon, init_data: Option<&[T]>, size: u32, + flags: BufferFlags, ) -> Result { let token = Arc::new("IndexBuffer".to_string());