C++: support for RGB8 in the line by line rendering

Note: this adds a mendatory template parametter to the
(experimental) `render_by_line` function.
I tried to get the PixelType auto-detected from the callback but i
didn't manage
This commit is contained in:
Olivier Goffart 2025-02-19 09:11:10 +01:00 committed by GitHub
parent 48fbf887aa
commit 07803ccd6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 130 additions and 100 deletions

View file

@ -403,6 +403,70 @@ mod software_renderer {
renderer.render(buffer, pixel_stride)
}
#[cfg(feature = "experimental")]
struct LineByLineProcessor<TargetPixel> {
process_line_fn: extern "C" fn(
*mut core::ffi::c_void,
usize,
usize,
usize,
extern "C" fn(*const core::ffi::c_void, *mut TargetPixel, usize),
*const core::ffi::c_void,
),
user_data: *mut core::ffi::c_void,
}
#[cfg(feature = "experimental")]
impl<TargetPixel: i_slint_core::software_renderer::TargetPixel>
i_slint_core::software_renderer::LineBufferProvider for LineByLineProcessor<TargetPixel>
{
type TargetPixel = TargetPixel;
fn process_line(
&mut self,
line: usize,
range: core::ops::Range<usize>,
render_fn: impl FnOnce(&mut [TargetPixel]),
) {
self.cpp_process_line(line, range, render_fn);
}
}
#[cfg(feature = "experimental")]
impl<TargetPixel> LineByLineProcessor<TargetPixel> {
fn cpp_process_line<RenderFn: FnOnce(&mut [TargetPixel])>(
&mut self,
line: usize,
range: core::ops::Range<usize>,
render_fn: RenderFn,
) {
let mut render_fn = Some(render_fn);
let render_fn_ptr = &mut render_fn as *mut Option<RenderFn> as *const core::ffi::c_void;
extern "C" fn cpp_render_line_callback<
TargetPixel,
RenderFn: FnOnce(&mut [TargetPixel]),
>(
render_fn_ptr: *const core::ffi::c_void,
line_start: *mut TargetPixel,
len: usize,
) {
let line_slice = unsafe { core::slice::from_raw_parts_mut(line_start, len) };
let render_fn =
unsafe { (*(render_fn_ptr as *mut Option<RenderFn>)).take().unwrap() };
render_fn(line_slice);
}
(self.process_line_fn)(
self.user_data,
line,
range.start,
range.end,
cpp_render_line_callback::<TargetPixel, RenderFn>,
render_fn_ptr,
);
}
}
#[cfg(feature = "experimental")]
#[no_mangle]
pub unsafe extern "C" fn slint_software_renderer_render_by_line_rgb565(
@ -412,74 +476,32 @@ mod software_renderer {
usize,
usize,
usize,
extern "C" fn(*const core::ffi::c_void, *mut u16, usize),
extern "C" fn(*const core::ffi::c_void, *mut Rgb565Pixel, usize),
*const core::ffi::c_void,
),
user_data: *mut core::ffi::c_void,
) -> PhysicalRegion {
struct Rgb565Processor {
process_line_fn: extern "C" fn(
*mut core::ffi::c_void,
usize,
usize,
usize,
extern "C" fn(*const core::ffi::c_void, *mut u16, usize),
*const core::ffi::c_void,
),
user_data: *mut core::ffi::c_void,
}
impl i_slint_core::software_renderer::LineBufferProvider for Rgb565Processor {
type TargetPixel = Rgb565Pixel;
fn process_line(
&mut self,
line: usize,
range: core::ops::Range<usize>,
render_fn: impl FnOnce(&mut [Rgb565Pixel]),
) {
self.cpp_process_line(line, range, render_fn);
}
}
impl Rgb565Processor {
fn cpp_process_line<RenderFn: FnOnce(&mut [Rgb565Pixel])>(
&mut self,
line: usize,
range: core::ops::Range<usize>,
render_fn: RenderFn,
) {
let mut render_fn = Some(render_fn);
let render_fn_ptr =
&mut render_fn as *mut Option<RenderFn> as *const core::ffi::c_void;
extern "C" fn cpp_render_line_callback<RenderFn: FnOnce(&mut [Rgb565Pixel])>(
render_fn_ptr: *const core::ffi::c_void,
line_start: *mut u16,
len: usize,
) {
let line_slice = unsafe {
core::slice::from_raw_parts_mut(line_start as *mut Rgb565Pixel, len)
};
let render_fn =
unsafe { (*(render_fn_ptr as *mut Option<RenderFn>)).take().unwrap() };
render_fn(line_slice);
}
(self.process_line_fn)(
self.user_data,
line,
range.start,
range.end,
cpp_render_line_callback::<RenderFn>,
render_fn_ptr,
);
}
}
let renderer = &*(r as *const SoftwareRenderer);
let processor = LineByLineProcessor { process_line_fn, user_data };
renderer.render_by_line(processor)
}
let processor = Rgb565Processor { process_line_fn, user_data };
#[cfg(feature = "experimental")]
#[no_mangle]
pub unsafe extern "C" fn slint_software_renderer_render_by_line_rgb8(
r: SoftwareRendererOpaque,
process_line_fn: extern "C" fn(
*mut core::ffi::c_void,
usize,
usize,
usize,
extern "C" fn(*const core::ffi::c_void, *mut Rgb8Pixel, usize),
*const core::ffi::c_void,
),
user_data: *mut core::ffi::c_void,
) -> PhysicalRegion {
let renderer = &*(r as *const SoftwareRenderer);
let processor = LineByLineProcessor { process_line_fn, user_data };
renderer.render_by_line(processor)
}