Add draw_texture/process_texture and use accelerated fill_rectangle for background draw

This commit is contained in:
Sam Cristall 2025-02-11 16:08:57 -07:00 committed by Simon Hausmann
parent fbee7f9566
commit 3855cf6b9c
3 changed files with 214 additions and 28 deletions

View file

@ -549,6 +549,11 @@ struct TargetPixelBuffer
virtual bool fill_rectangle(int16_t x, int16_t y, int16_t width, int16_t height, virtual bool fill_rectangle(int16_t x, int16_t y, int16_t width, int16_t height,
const RgbaColor<uint8_t> &premultiplied_color) = 0; const RgbaColor<uint8_t> &premultiplied_color) = 0;
virtual bool draw_texture(int16_t x, int16_t y, int16_t width, int16_t height,
const uint8_t *src, uint16_t src_stride, int16_t src_width,
int16_t src_height, uint8_t src_pixel_format, uint16_t src_dx,
uint16_t src_dy, uint16_t src_off_x, uint16_t src_off_y,
uint32_t colorize, uint8_t alpha, uint8_t rotation) = 0;
}; };
# endif # endif
@ -719,6 +724,18 @@ public:
return buffer->fill_rectangle( return buffer->fill_rectangle(
x, y, width, height, x, y, width, height,
Color::from_argb_uint8(alpha, red, green, blue)); Color::from_argb_uint8(alpha, red, green, blue));
},
.draw_texture =
[](void *self, int16_t x, int16_t y, int16_t width, int16_t handle,
const uint8_t *src, uint16_t src_stride, int16_t src_width,
int16_t src_height, uint8_t src_pixel_format, uint16_t src_dx,
uint16_t src_dy, uint16_t src_off_x, uint16_t src_off_y, uint32_t colorize,
uint8_t alpha, uint8_t rotation) {
auto *buffer = reinterpret_cast<TargetPixelBuffer<Rgb8Pixel> *>(self);
return buffer->draw_texture(x, y, width, handle, src, src_stride, src_width,
src_height, src_pixel_format, src_dx, src_dy,
src_off_x, src_off_y, colorize, alpha,
rotation);
} }
}; };
auto r = auto r =
@ -749,6 +766,18 @@ public:
return buffer->fill_rectangle( return buffer->fill_rectangle(
x, y, width, height, x, y, width, height,
Color::from_argb_uint8(alpha, red, green, blue)); Color::from_argb_uint8(alpha, red, green, blue));
},
.draw_texture =
[](void *self, int16_t x, int16_t y, int16_t width, int16_t handle,
const uint8_t *src, uint16_t src_stride, int16_t src_width,
int16_t src_height, uint8_t src_pixel_format, uint16_t src_dx,
uint16_t src_dy, uint16_t src_off_x, uint16_t src_off_y, uint32_t colorize,
uint8_t alpha, uint8_t rotation) {
auto *buffer = reinterpret_cast<TargetPixelBuffer<Rgb565Pixel> *>(self);
return buffer->draw_texture(x, y, width, handle, src, src_stride, src_width,
src_height, src_pixel_format, src_dx, src_dy,
src_off_x, src_off_y, colorize, alpha,
rotation);
} }
}; };
auto r = cbindgen_private::slint_software_renderer_render_accel_rgb565(inner, auto r = cbindgen_private::slint_software_renderer_render_accel_rgb565(inner,

View file

@ -384,6 +384,25 @@ mod software_renderer {
u8, u8,
u8, u8,
) -> bool, ) -> bool,
draw_texture: unsafe extern "C" fn(
CppTargetPixelBufferUserData,
i16,
i16,
i16,
i16,
*const u8,
u16,
i16,
i16,
u8,
u16,
u16,
u16,
u16,
u32,
u8,
u8,
) -> bool,
} }
impl TargetPixelBuffer for CppRgb8TargetPixelBuffer { impl TargetPixelBuffer for CppRgb8TargetPixelBuffer {
@ -424,6 +443,48 @@ mod software_renderer {
) )
} }
} }
fn draw_texture(
&mut self,
x: i16,
y: i16,
width: i16,
height: i16,
src: *const u8,
src_stride: u16,
src_width: i16,
src_height: i16,
src_pixel_format: u8,
dx: u16,
dy: u16,
off_x: u16,
off_y: u16,
colorize: u32,
alpha: u8,
rotation: u8,
) -> bool {
unsafe {
(self.draw_texture)(
self.user_data,
x,
y,
width,
height,
src,
src_stride,
src_width,
src_height,
src_pixel_format,
dx,
dy,
off_x,
off_y,
colorize,
alpha,
rotation,
)
}
}
} }
#[repr(C)] #[repr(C)]
@ -447,6 +508,25 @@ mod software_renderer {
u8, u8,
u8, u8,
) -> bool, ) -> bool,
draw_texture: unsafe extern "C" fn(
CppTargetPixelBufferUserData,
i16,
i16,
i16,
i16,
*const u8,
u16,
i16,
i16,
u8,
u16,
u16,
u16,
u16,
u32,
u8,
u8,
) -> bool,
} }
impl TargetPixelBuffer for CppRgb565TargetPixelBuffer { impl TargetPixelBuffer for CppRgb565TargetPixelBuffer {
@ -487,6 +567,48 @@ mod software_renderer {
) )
} }
} }
fn draw_texture(
&mut self,
x: i16,
y: i16,
width: i16,
height: i16,
src: *const u8,
src_stride: u16,
src_width: i16,
src_height: i16,
src_pixel_format: u8,
dx: u16,
dy: u16,
off_x: u16,
off_y: u16,
colorize: u32,
alpha: u8,
rotation: u8,
) -> bool {
unsafe {
(self.draw_texture)(
self.user_data,
x,
y,
width,
height,
src,
src_stride,
src_width,
src_height,
src_pixel_format,
dx,
dy,
off_x,
off_y,
colorize,
alpha,
rotation,
)
}
}
} }
#[no_mangle] #[no_mangle]

View file

@ -394,6 +394,31 @@ mod private_api {
) -> bool { ) -> bool {
false false
} }
/// Draw a texture into the buffer at the specified position with the given size and
/// colorized if needed. Returns true if the operation was successful; false if it could not be
/// implemented and instead the software renderer needs to draw the texture
fn draw_texture(
&mut self,
_x: i16,
_y: i16,
_width: i16,
_height: i16,
_src: *const u8,
_src_stride: u16,
_src_width: i16,
_src_height: i16,
_src_pixel_format: u8,
_src_dx: u16,
_src_dy: u16,
_src_off_x: u16,
_src_off_y: u16,
_colorize: u32,
_alpha: u8,
_rotation: u8,
) -> bool {
false
}
} }
} }
@ -617,27 +642,14 @@ impl SoftwareRenderer {
}; };
drop(i); drop(i);
let mut bg = TargetPixel::background(); let mut bg = PremultipliedRgbaColor::background();
// TODO: gradient background // TODO: gradient background
// TODO: Use TargetPixelBuffer::fill_rectangle PremultipliedRgbaColor::blend(&mut bg, background.color().into());
TargetPixel::blend(&mut bg, background.color().into());
let mut line = 0;
while let Some(next) = region_line_ranges(
&dirty_region,
line,
&mut renderer.actual_renderer.processor.dirty_range_cache,
) {
for l in line..next {
for r in &renderer.actual_renderer.processor.dirty_range_cache {
renderer.actual_renderer.processor.buffer.line_slice(l as usize)
[r.start as usize..r.end as usize]
.fill(bg);
}
}
line = next;
}
renderer.actual_renderer.processor.dirty_region = dirty_region.clone(); renderer.actual_renderer.processor.dirty_region = dirty_region.clone();
renderer.actual_renderer.processor.process_rectangle(
PhysicalRect::from_size(euclid::Size2D::new(size.width, size.height)),
bg,
);
for (component, origin) in components { for (component, origin) in components {
crate::item_rendering::render_component_items( crate::item_rendering::render_component_items(
@ -1241,15 +1253,38 @@ impl<T: TargetPixel, B: private_api::TargetPixelBuffer<Pixel = T>> RenderToBuffe
} }
fn process_texture_impl(&mut self, geometry: PhysicalRect, texture: SceneTexture<'_>) { fn process_texture_impl(&mut self, geometry: PhysicalRect, texture: SceneTexture<'_>) {
self.foreach_ranges(&geometry, |line, buffer, extra_left_clip, extra_right_clip| { self.foreach_region(&geometry, |buffer, rect, extra_left_clip, extra_right_clip| {
draw_functions::draw_texture_line( if !buffer.draw_texture(
&geometry, rect.origin.x,
PhysicalLength::new(line), rect.origin.y,
&texture, rect.size.width,
buffer, rect.size.height,
extra_left_clip, texture.data.as_ptr(),
extra_right_clip, texture.pixel_stride,
); texture.source_size().width,
texture.source_size().height,
texture.format as u8,
texture.extra.dx.0,
texture.extra.dy.0,
texture.extra.off_x.0,
texture.extra.off_y.0,
texture.extra.colorize.as_argb_encoded(),
texture.extra.alpha,
texture.extra.rotation as u8,
) {
let begin = rect.min_x();
let end = rect.max_x();
for l in rect.min_y()..rect.max_y() {
draw_functions::draw_texture_line(
&geometry,
PhysicalLength::new(l),
&texture,
&mut buffer.line_slice(l as usize)[begin as usize..end as usize],
extra_left_clip,
extra_right_clip,
);
}
}
}); });
} }
} }