@@ -10,6 +10,12 @@ use crate::color::Color;
1010mod color;
1111mod error;
1212
13+ unsafe fn cstr_to_str < ' a > ( ptr : * const std:: ffi:: c_char ) -> Result < & ' a str , ProcessingError > {
14+ unsafe { std:: ffi:: CStr :: from_ptr ( ptr) }
15+ . to_str ( )
16+ . map_err ( |_| ProcessingError :: InvalidArgument ( "non-UTF8 C string" . to_string ( ) ) )
17+ }
18+
1319/// Initialize libProcessing.
1420///
1521/// SAFETY:
@@ -1776,12 +1782,12 @@ pub unsafe extern "C" fn processing_material_set_float(
17761782 value : f32 ,
17771783) {
17781784 error:: clear_error ( ) ;
1779- let name = unsafe { std:: ffi:: CStr :: from_ptr ( name) } . to_str ( ) . unwrap ( ) ;
17801785 error:: check ( || {
1786+ let name = unsafe { cstr_to_str ( name) } ?;
17811787 material_set (
17821788 Entity :: from_bits ( mat_id) ,
17831789 name,
1784- material :: MaterialValue :: Float ( value) ,
1790+ shader_value :: ShaderValue :: Float ( value) ,
17851791 )
17861792 } ) ;
17871793}
@@ -1800,12 +1806,12 @@ pub unsafe extern "C" fn processing_material_set_float4(
18001806 a : f32 ,
18011807) {
18021808 error:: clear_error ( ) ;
1803- let name = unsafe { std:: ffi:: CStr :: from_ptr ( name) } . to_str ( ) . unwrap ( ) ;
18041809 error:: check ( || {
1810+ let name = unsafe { cstr_to_str ( name) } ?;
18051811 material_set (
18061812 Entity :: from_bits ( mat_id) ,
18071813 name,
1808- material :: MaterialValue :: Float4 ( [ r, g, b, a] ) ,
1814+ shader_value :: ShaderValue :: Float4 ( [ r, g, b, a] ) ,
18091815 )
18101816 } ) ;
18111817}
@@ -1824,6 +1830,176 @@ pub extern "C" fn processing_material(window_id: u64, mat_id: u64) {
18241830 error:: check ( || graphics_record_command ( window_entity, DrawCommand :: Material ( mat_entity) ) ) ;
18251831}
18261832
1833+ // Shader
1834+
1835+ /// Create a shader from WGSL source.
1836+ ///
1837+ /// # Safety
1838+ /// - `source` must be non-null
1839+ #[ unsafe( no_mangle) ]
1840+ pub unsafe extern "C" fn processing_shader_create ( source : * const std:: ffi:: c_char ) -> u64 {
1841+ error:: clear_error ( ) ;
1842+ error:: check ( || {
1843+ let source = unsafe { cstr_to_str ( source) } ?;
1844+ shader_create ( source)
1845+ } )
1846+ . map ( |e| e. to_bits ( ) )
1847+ . unwrap_or ( 0 )
1848+ }
1849+
1850+ /// Load a shader from a file path.
1851+ ///
1852+ /// # Safety
1853+ /// - `path` must be non-null
1854+ #[ unsafe( no_mangle) ]
1855+ pub unsafe extern "C" fn processing_shader_load ( path : * const std:: ffi:: c_char ) -> u64 {
1856+ error:: clear_error ( ) ;
1857+ error:: check ( || {
1858+ let path = unsafe { cstr_to_str ( path) } ?;
1859+ shader_load ( path)
1860+ } )
1861+ . map ( |e| e. to_bits ( ) )
1862+ . unwrap_or ( 0 )
1863+ }
1864+
1865+ #[ unsafe( no_mangle) ]
1866+ pub extern "C" fn processing_shader_destroy ( shader_id : u64 ) {
1867+ error:: clear_error ( ) ;
1868+ error:: check ( || shader_destroy ( Entity :: from_bits ( shader_id) ) ) ;
1869+ }
1870+
1871+ // Buffer
1872+
1873+ #[ unsafe( no_mangle) ]
1874+ pub extern "C" fn processing_buffer_create ( size : u64 ) -> u64 {
1875+ error:: clear_error ( ) ;
1876+ error:: check ( || buffer_create ( size) )
1877+ . map ( |e| e. to_bits ( ) )
1878+ . unwrap_or ( 0 )
1879+ }
1880+
1881+ /// Create a buffer initialized with data.
1882+ ///
1883+ /// # Safety
1884+ /// - `data` must point to `len` valid bytes
1885+ #[ unsafe( no_mangle) ]
1886+ pub unsafe extern "C" fn processing_buffer_create_with_data ( data : * const u8 , len : u64 ) -> u64 {
1887+ error:: clear_error ( ) ;
1888+ let bytes = unsafe { std:: slice:: from_raw_parts ( data, len as usize ) } . to_vec ( ) ;
1889+ error:: check ( || buffer_create_with_data ( bytes) )
1890+ . map ( |e| e. to_bits ( ) )
1891+ . unwrap_or ( 0 )
1892+ }
1893+
1894+ /// Write data to a buffer.
1895+ ///
1896+ /// # Safety
1897+ /// - `data` must point to `len` valid bytes
1898+ #[ unsafe( no_mangle) ]
1899+ pub unsafe extern "C" fn processing_buffer_write ( buf_id : u64 , data : * const u8 , len : u64 ) {
1900+ error:: clear_error ( ) ;
1901+ let bytes = unsafe { std:: slice:: from_raw_parts ( data, len as usize ) } . to_vec ( ) ;
1902+ error:: check ( || buffer_write ( Entity :: from_bits ( buf_id) , bytes) ) ;
1903+ }
1904+
1905+ /// Returns the byte length of a buffer, or 0 if the buffer does not exist
1906+ /// (in which case the error is set).
1907+ #[ unsafe( no_mangle) ]
1908+ pub extern "C" fn processing_buffer_size ( buf_id : u64 ) -> u64 {
1909+ error:: clear_error ( ) ;
1910+ error:: check ( || buffer_size ( Entity :: from_bits ( buf_id) ) ) . unwrap_or ( 0 )
1911+ }
1912+
1913+ /// Read buffer contents into a caller-provided buffer.
1914+ ///
1915+ /// Returns the buffer's byte length. If the returned size is `<= out_len`, the
1916+ /// data has been written to `out`; otherwise `out` is left untouched and the
1917+ /// caller should reallocate and retry. Returns 0 if the buffer does not exist
1918+ /// or the GPU readback failed (in which case the error is set).
1919+ ///
1920+ /// # Safety
1921+ /// - `out` must be valid for writes of `out_len` bytes (may be null if
1922+ /// `out_len == 0`, in which case this acts as a size query).
1923+ #[ unsafe( no_mangle) ]
1924+ pub unsafe extern "C" fn processing_buffer_read ( buf_id : u64 , out : * mut u8 , out_len : u64 ) -> u64 {
1925+ error:: clear_error ( ) ;
1926+ let Some ( data) = error:: check ( || buffer_read ( Entity :: from_bits ( buf_id) ) ) else {
1927+ return 0 ;
1928+ } ;
1929+ let needed = data. len ( ) as u64 ;
1930+ if needed <= out_len {
1931+ unsafe { std:: ptr:: copy_nonoverlapping ( data. as_ptr ( ) , out, data. len ( ) ) } ;
1932+ }
1933+ needed
1934+ }
1935+
1936+ #[ unsafe( no_mangle) ]
1937+ pub extern "C" fn processing_buffer_destroy ( buf_id : u64 ) {
1938+ error:: clear_error ( ) ;
1939+ error:: check ( || buffer_destroy ( Entity :: from_bits ( buf_id) ) ) ;
1940+ }
1941+
1942+ // Compute
1943+
1944+ #[ unsafe( no_mangle) ]
1945+ pub extern "C" fn processing_compute_create ( shader_id : u64 ) -> u64 {
1946+ error:: clear_error ( ) ;
1947+ error:: check ( || compute_create ( Entity :: from_bits ( shader_id) ) )
1948+ . map ( |e| e. to_bits ( ) )
1949+ . unwrap_or ( 0 )
1950+ }
1951+
1952+ /// Set a float property on a compute shader.
1953+ ///
1954+ /// # Safety
1955+ /// - `name` must be non-null
1956+ #[ unsafe( no_mangle) ]
1957+ pub unsafe extern "C" fn processing_compute_set_float (
1958+ compute_id : u64 ,
1959+ name : * const std:: ffi:: c_char ,
1960+ value : f32 ,
1961+ ) {
1962+ error:: clear_error ( ) ;
1963+ error:: check ( || {
1964+ let name = unsafe { cstr_to_str ( name) } ?;
1965+ compute_set (
1966+ Entity :: from_bits ( compute_id) ,
1967+ name,
1968+ shader_value:: ShaderValue :: Float ( value) ,
1969+ )
1970+ } ) ;
1971+ }
1972+
1973+ /// Set a buffer property on a compute shader.
1974+ #[ unsafe( no_mangle) ]
1975+ pub unsafe extern "C" fn processing_compute_set_buffer (
1976+ compute_id : u64 ,
1977+ name : * const std:: ffi:: c_char ,
1978+ buf_id : u64 ,
1979+ ) {
1980+ error:: clear_error ( ) ;
1981+ error:: check ( || {
1982+ let name = unsafe { cstr_to_str ( name) } ?;
1983+ compute_set (
1984+ Entity :: from_bits ( compute_id) ,
1985+ name,
1986+ shader_value:: ShaderValue :: Buffer ( Entity :: from_bits ( buf_id) ) ,
1987+ )
1988+ } ) ;
1989+ }
1990+
1991+ #[ unsafe( no_mangle) ]
1992+ pub extern "C" fn processing_compute_dispatch ( compute_id : u64 , x : u32 , y : u32 , z : u32 ) {
1993+ error:: clear_error ( ) ;
1994+ error:: check ( || compute_dispatch ( Entity :: from_bits ( compute_id) , x, y, z) ) ;
1995+ }
1996+
1997+ #[ unsafe( no_mangle) ]
1998+ pub extern "C" fn processing_compute_destroy ( compute_id : u64 ) {
1999+ error:: clear_error ( ) ;
2000+ error:: check ( || compute_destroy ( Entity :: from_bits ( compute_id) ) ) ;
2001+ }
2002+
18272003// Mouse buttons
18282004pub const PROCESSING_MOUSE_LEFT : u8 = 0 ;
18292005pub const PROCESSING_MOUSE_MIDDLE : u8 = 1 ;
0 commit comments