optimization

This commit is contained in:
Jorijn van der Graaf 2025-11-26 20:15:25 +01:00
commit 285e8c9182
4 changed files with 57 additions and 69 deletions

View file

@ -153,62 +153,43 @@ inline void blend_pixel_optimized(Pixel_BU8_GU8_RU8_AU8& dst, const Pixel_BU8_GU
}
}
// Optimized rendering with bounds checking and early exit
void WindowWayland::RenderElement(Transform* transform) {
RenderingElement* element = dynamic_cast<RenderingElement*>(transform);
if(element) {
#ifdef CRAFTER_TIMING
auto start = std::chrono::high_resolution_clock::now();
#endif
// Calculate clipping bounds
std::int_fast32_t clip_left = std::max(element->scaled.x, std::int_fast32_t(0));
std::int_fast32_t clip_top = std::max(element->scaled.y, std::int_fast32_t(0));
std::int_fast32_t clip_right = std::min(element->scaled.x + element->scaled.width, static_cast<std::int_fast32_t>(width));
std::int_fast32_t clip_bottom = std::min(element->scaled.y + element->scaled.height, static_cast<std::int_fast32_t>(height));
// Early exit if completely outside screen
if (clip_left >= clip_right || clip_top >= clip_bottom) {
#ifdef CRAFTER_TIMING
auto end = std::chrono::high_resolution_clock::now();
renderTimings.push_back({element, element->scaled.width, element->scaled.height, end-start});
#endif
if(element->scaled.width < 1 || element->scaled.height < 1) {
return;
}
// Get source buffer data
const Pixel_BU8_GU8_RU8_AU8* src_buffer = element->bufferScaled.data();
std::uint_fast32_t src_width = element->scaled.width;
std::uint_fast32_t src_height = element->scaled.height;
// If element is opaque, we can simply copy pixels without blending
if (element->opaque) {
// Render clipped region
for (std::int_fast32_t y = clip_top; y < clip_bottom; y++) {
std::int_fast32_t src_y = y - element->scaled.y;
for (std::int_fast32_t x = clip_left; x < clip_right; x++) {
std::int_fast32_t src_x = x - element->scaled.x;
for(ClipRect dirty : dirtyRects) {
dirty.left = std::max(element->scaled.x, dirty.left);
dirty.top = std::max(element->scaled.y, dirty.top);
dirty.right = std::min(element->scaled.x+element->scaled.width, dirty.right);
dirty.bottom = std::min(element->scaled.y+element->scaled.height, dirty.bottom);
const Pixel_BU8_GU8_RU8_AU8* src_buffer = element->bufferScaled.data();
std::int_fast32_t src_width = element->scaled.width;
std::int_fast32_t src_height = element->scaled.height;
if (element->opaque) {
for (std::int_fast32_t y = dirty.top; y < dirty.bottom; y++) {
std::int_fast32_t src_y = y - element->scaled.y;
// Bounds check for source buffer
if (src_x >= 0 && src_x < static_cast<std::int_fast32_t>(src_width) && src_y >= 0 && src_y < static_cast<std::int_fast32_t>(src_height)) {
// Direct copy for opaque elements (skip blending)
for (std::int_fast32_t x = dirty.left; x < dirty.right; x++) {
std::int_fast32_t src_x = x - element->scaled.x;
framebuffer[y * width + x] = src_buffer[src_y * src_width + src_x];
}
}
}
} else {
// Render clipped region with blending for non-opaque elements
for (std::int_fast32_t y = clip_top; y < clip_bottom; y++) {
std::int_fast32_t src_y = y - element->scaled.y;
for (std::int_fast32_t x = clip_left; x < clip_right; x++) {
std::int_fast32_t src_x = x - element->scaled.x;
} else {
for (std::int_fast32_t y = dirty.top; y < dirty.bottom; y++) {
std::int_fast32_t src_y = y - element->scaled.y;
// Bounds check for source buffer
if (src_x >= 0 && src_x < static_cast<std::int_fast32_t>(src_width) && src_y >= 0 && src_y < static_cast<std::int_fast32_t>(src_height)) {
// Blend pixels
for (std::int_fast32_t x = dirty.left; x < dirty.right; x++) {
std::int_fast32_t src_x = x - element->scaled.x;
blend_pixel_optimized(framebuffer[y * width + x], src_buffer[src_y * src_width + src_x]);
}
}
@ -232,9 +213,9 @@ void WindowWayland::Render() {
std::sort(elements.begin(), elements.end(), [](Transform* a, Transform* b){ return a->z < b->z; });
if (!dirtyRects.empty()) {
for (const ScaleData& rect : dirtyRects) {
for (std::int_fast32_t y = rect.y; y < rect.y + rect.height && y < height; y++) {
for (std::int_fast32_t x = rect.x; x < rect.x + rect.width && x < width; x++) {
for (ClipRect rect : dirtyRects) {
for (std::int_fast32_t y = rect.top; y < rect.bottom; y++) {
for (std::int_fast32_t x = rect.left; x < rect.right; x++) {
framebuffer[y * width + x] = {0, 0, 0, 0};
}
}
@ -244,12 +225,14 @@ void WindowWayland::Render() {
RenderElement(child);
}
for (const ScaleData& rect : dirtyRects) {
wl_surface_damage(surface, rect.x, rect.y, rect.width, rect.height);
for (ClipRect rect : dirtyRects) {
wl_surface_damage(surface, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top);
}
dirtyRects.clear();
}
dirtyRects.clear();
wl_surface_damage(surface, 0, 0, width, height);
wl_surface_attach(surface, buffer, 0, 0);
wl_surface_commit(surface);