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

Add experimental plumbing for hardware accelerated rendering operations with the software renderer #7685

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8fd6921
WIP: Add plumbing for acceleration pixel blending operations on targe…
tronical Feb 6, 2025
580cc3a
WIP: Start wrapping TargetPIxelBuffer in C++
tronical Feb 6, 2025
612cdf9
Add draw_texture/process_texture and use accelerated fill_rectangle f…
scristall-bennu Feb 11, 2025
40b7820
Add span_y to draw_texture to fix partial texture draws
scristall-bennu Feb 12, 2025
4d2e980
Change TargetPixelBuffer's draw_texture function to take a data struc…
tronical Feb 20, 2025
a33605a
Expose screen rotation in the TargetPixelBuffer's draw_texture as int…
tronical Feb 20, 2025
8d17ad8
Fix the build with the experimental feature turned off
tronical Feb 20, 2025
bd3c11f
Some C++ docs for TargetPixelBuffer
tronical Feb 20, 2025
d2edf05
Improve API for C++ TargetPixelBuffer::draw_texture's blending color
tronical Feb 20, 2025
1694349
Missing docs fix
tronical Feb 20, 2025
64764df
More docs
tronical Feb 20, 2025
e4b143e
[autofix.ci] apply automated fixes
autofix-ci[bot] Feb 20, 2025
b72c507
Fix invalid reinterpret_cast in render to target pixel buffer method …
tronical Feb 20, 2025
06db589
Fix docs about fixed point format for source texture offsets
tronical Feb 20, 2025
dc214ab
Fix build for C++ generated code for embedded textures
tronical Feb 20, 2025
43bccd9
Simplify accelerated texture and rectangle fills
tronical Feb 21, 2025
1e6e1cf
Separate the target pixel buffer trait and related types into a separ…
tronical Feb 21, 2025
2a33efd
Fix window background fill
tronical Feb 21, 2025
59b6747
Simplify background color passing
tronical Feb 21, 2025
dce2900
Prospective fix for background fill
tronical Feb 21, 2025
3e22d7d
Revert "Simplify accelerated texture and rectangle fills"
tronical Feb 21, 2025
eee61ab
Rename TargetPixelBuffer::Pixel to ::TargetPixel
tronical Feb 21, 2025
44d5690
Simplify RenderToBuffer declaration
tronical Feb 21, 2025
d832e76
Simplify foreach_ranges by re-using foreach_region
tronical Feb 21, 2025
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
2 changes: 1 addition & 1 deletion api/cpp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ system-testing = ["i-slint-backend-selector/system-testing"]

std = ["i-slint-core/default", "i-slint-core/image-default-formats", "i-slint-backend-selector"]
freestanding = ["i-slint-core/libm", "i-slint-core/unsafe-single-threaded"]
experimental = []
experimental = ["i-slint-core/experimental"]

default = ["std", "backend-winit", "renderer-femtovg", "backend-qt"]

Expand Down
2 changes: 1 addition & 1 deletion api/cpp/cbindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,7 @@ fn gen_platform(
.with_after_include(
r"
namespace slint::platform { struct Rgb565Pixel; }
namespace slint::cbindgen_private { struct WindowProperties; using slint::platform::Rgb565Pixel; }
namespace slint::cbindgen_private { struct WindowProperties; using slint::platform::Rgb565Pixel; using slint::cbindgen_private::types::TexturePixelFormat; }
",
)
.generate()
Expand Down
159 changes: 159 additions & 0 deletions api/cpp/include/slint-platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,57 @@ struct Rgb565Pixel
friend bool operator==(const Rgb565Pixel &lhs, const Rgb565Pixel &rhs) = default;
};

# ifdef SLINT_FEATURE_EXPERIMENTAL

using cbindgen_private::types::TexturePixelFormat;

/// This structure describes the properties of a texture for blending with
/// TargetPixelBuffer::draw_texture().
struct Texture
{
/// A reference to the pixel bytes of the texture. These bytes are in the format specified by
/// `pixel_format`.
std::span<const uint8_t> bytes;
/// The pixel format of the texture.
TexturePixelFormat pixel_format;
uint16_t pixel_stride;
uint16_t width;
uint16_t height;
uint16_t delta_x;
uint16_t delta_y;
uint16_t source_offset_x;
uint16_t source_offset_y;
};

/// Abstract base class for a target pixel buffer where certain drawing operations can be delegated.
/// Use this to implement support for hardware accelerators such as DMA2D, PPA, or PXP on
/// Microcontrollers.
template<typename PixelType>
struct TargetPixelBuffer
{
virtual ~TargetPixelBuffer() { }

/// Returns a span of pixels for the specified line number.
virtual std::span<PixelType> line_slice(std::size_t line_number) = 0;
/// Returns the number of lines in the buffer. This is the height of the buffer in pixels.
virtual std::size_t num_lines() = 0;

/// Fill a rectangle at the specified pixel coordinates with the given color. Return true
/// if the operation succeeded; false otherwise;
virtual bool fill_rectangle(int16_t x, int16_t y, int16_t width, int16_t height,
const RgbaColor<uint8_t> &premultiplied_color) = 0;

/// Draw a portion of provided texture to the specified pixel coordinates. This may
/// be called multiple times for a given texture, for example when clipping. Typically
/// y is identicaly with span_y, but when clipping, span_y refers to the y coordinate of
/// the texture if it's unclipped. Each pixel of the texture is to be blended with the given
/// colorize color as well as the alpha value.
virtual bool draw_texture(int16_t x, int16_t y, int16_t width, int16_t height, int16_t span_y,
const Texture &texture, const RgbaColor<uint8_t> &colorize,
uint8_t alpha, int screen_rotation_degrees) = 0;
};
# endif

/// Slint's software renderer.
///
/// To be used as a template parameter of the WindowAdapter.
Expand Down Expand Up @@ -680,6 +731,114 @@ class SoftwareRenderer : public AbstractRenderer
return PhysicalRegion { r };
}

# ifdef SLINT_FEATURE_EXPERIMENTAL
/// Renders into the given TargetPixelBuffer.
PhysicalRegion render(TargetPixelBuffer<Rgb8Pixel> *buffer) const
{
cbindgen_private::CppRgb8TargetPixelBuffer buffer_wrapper {
.user_data = buffer,
.line_slice =
[](void *self, uintptr_t line_number, Rgb8Pixel **slice_ptr,
uintptr_t *slice_len) {
auto *buffer = reinterpret_cast<TargetPixelBuffer<Rgb8Pixel> *>(self);
auto slice = buffer->line_slice(line_number);
*slice_ptr = slice.data();
*slice_len = slice.size();
},
.num_lines =
[](void *self) {
auto *buffer = reinterpret_cast<TargetPixelBuffer<Rgb8Pixel> *>(self);
return buffer->num_lines();
},
.fill_rectangle =
[](void *self, int16_t x, int16_t y, int16_t width, int16_t height, uint8_t red,
uint8_t green, uint8_t blue, uint8_t alpha) {
auto *buffer = reinterpret_cast<TargetPixelBuffer<Rgb8Pixel> *>(self);
return buffer->fill_rectangle(
x, y, width, height,
Color::from_argb_uint8(alpha, red, green, blue));
},
.draw_texture =
[](void *self, int16_t x, int16_t y, int16_t width, int16_t height,
int16_t span_y, const cbindgen_private::CppInternalTexture *internal_texture,
uint32_t colorize, uint8_t alpha, int32_t screen_rotation_degrees) {
auto *buffer = reinterpret_cast<TargetPixelBuffer<Rgb8Pixel> *>(self);
Texture texture {
.bytes = std::span<const uint8_t> { internal_texture->bytes,
internal_texture->bytes_len },
.pixel_format = internal_texture->pixel_format,
.pixel_stride = internal_texture->pixel_stride,
.width = internal_texture->width,
.height = internal_texture->height,
.delta_x = internal_texture->delta_x,
.delta_y = internal_texture->delta_y,
.source_offset_x = internal_texture->source_offset_x,
.source_offset_y = internal_texture->source_offset_y,
};
return buffer->draw_texture(x, y, width, height, span_y, texture,
Color::from_argb_encoded(colorize), alpha,
screen_rotation_degrees);
}
};
auto r =
cbindgen_private::slint_software_renderer_render_accel_rgb8(inner, &buffer_wrapper);
return PhysicalRegion { r };
}

/// Renders into the given TargetPixelBuffer.
PhysicalRegion render(TargetPixelBuffer<Rgb565Pixel> *buffer) const
{
cbindgen_private::CppRgb565TargetPixelBuffer buffer_wrapper {
.user_data = buffer,
.line_slice =
[](void *self, uintptr_t line_number, uint16_t **slice_ptr,
uintptr_t *slice_len) {
auto *buffer = reinterpret_cast<TargetPixelBuffer<Rgb565Pixel> *>(self);
auto slice = buffer->line_slice(line_number);
*slice_ptr = reinterpret_cast<uint16_t *>(slice.data());
*slice_len = slice.size();
},
.num_lines =
[](void *self) {
auto *buffer = reinterpret_cast<TargetPixelBuffer<Rgb565Pixel> *>(self);
return buffer->num_lines();
},
.fill_rectangle =
[](void *self, int16_t x, int16_t y, int16_t width, int16_t height, uint8_t red,
uint8_t green, uint8_t blue, uint8_t alpha) {
auto *buffer = reinterpret_cast<TargetPixelBuffer<Rgb565Pixel> *>(self);
return buffer->fill_rectangle(
x, y, width, height,
Color::from_argb_uint8(alpha, red, green, blue));
},
.draw_texture =
[](void *self, int16_t x, int16_t y, int16_t width, int16_t height,
int16_t span_y, const cbindgen_private::CppInternalTexture *internal_texture,
uint32_t colorize, uint8_t alpha, int32_t screen_rotation_degrees) {
auto *buffer = reinterpret_cast<TargetPixelBuffer<Rgb8Pixel> *>(self);
Texture texture {
.bytes = std::span<const uint8_t> { internal_texture->bytes,
internal_texture->bytes_len },
.pixel_format = internal_texture->pixel_format,
.pixel_stride = internal_texture->pixel_stride,
.width = internal_texture->width,
.height = internal_texture->height,
.delta_x = internal_texture->delta_x,
.delta_y = internal_texture->delta_y,
.source_offset_x = internal_texture->source_offset_x,
.source_offset_y = internal_texture->source_offset_y,
};
return buffer->draw_texture(x, y, width, height, span_y, texture,
Color::from_argb_encoded(colorize), alpha,
screen_rotation_degrees);
}
};
auto r = cbindgen_private::slint_software_renderer_render_accel_rgb565(inner,
&buffer_wrapper);
return PhysicalRegion { r };
}
# endif

/// Render the window scene into an RGB 565 encoded pixel buffer
///
/// The buffer must be at least as large as the associated slint::Window
Expand Down
Loading
Loading