optimization
This commit is contained in:
parent
9bb36c990d
commit
285e8c9182
4 changed files with 57 additions and 69 deletions
|
|
@ -98,30 +98,28 @@ void Window::LogTiming() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool Overlaps(const ScaleData& rect1, const ScaleData& rect2) {
|
|
||||||
return !(rect1.x + rect1.width <= rect2.x || rect2.x + rect2.width <= rect1.x || rect1.y + rect1.height <= rect2.y || rect2.y + rect2.height <= rect1.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
ScaleData MergeRects(const ScaleData& rect1, const ScaleData& rect2) {
|
void Window::AddDirtyRect(ScaleData scale) {
|
||||||
ScaleData merged;
|
ClipRect rect {
|
||||||
merged.x = std::min(rect1.x, rect2.x);
|
.left = std::max(scale.x, std::int_fast32_t(0)),
|
||||||
merged.y = std::min(rect1.y, rect2.y);
|
.right = std::min(scale.x + scale.width, width),
|
||||||
merged.width = std::max(rect1.x + rect1.width, rect2.x + rect2.width) - merged.x;
|
.top = std::max(scale.y, std::int_fast32_t(0)),
|
||||||
merged.height = std::max(rect1.y + rect1.height, rect2.y + rect2.height) - merged.y;
|
.bottom = std::min(scale.y + scale.height, height),
|
||||||
return merged;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
void Window::AddDirtyRect(ScaleData rect) {
|
if (rect.left >= rect.right || rect.top >= rect.bottom) {
|
||||||
bool merged = false;
|
return;
|
||||||
for (auto& existingRect : dirtyRects) {
|
}
|
||||||
if (Overlaps(existingRect, rect)) {
|
|
||||||
existingRect = MergeRects(existingRect, rect);
|
for (ClipRect& existingRect : dirtyRects) {
|
||||||
merged = true;
|
if (rect.left <= existingRect.right && rect.right >= existingRect.left && rect.top <= existingRect.bottom && rect.bottom >= existingRect.top) {
|
||||||
break;
|
existingRect.left = std::min(existingRect.left, rect.left);
|
||||||
|
existingRect.right = std::max(existingRect.right, rect.right);
|
||||||
|
existingRect.top = std::min(existingRect.top, rect.top);
|
||||||
|
existingRect.bottom = std::max(existingRect.bottom, rect.bottom);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!merged) {
|
|
||||||
dirtyRects.push_back(rect);
|
dirtyRects.push_back(rect);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -153,7 +153,6 @@ 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) {
|
void WindowWayland::RenderElement(Transform* transform) {
|
||||||
RenderingElement* element = dynamic_cast<RenderingElement*>(transform);
|
RenderingElement* element = dynamic_cast<RenderingElement*>(transform);
|
||||||
if(element) {
|
if(element) {
|
||||||
|
|
@ -161,54 +160,36 @@ void WindowWayland::RenderElement(Transform* transform) {
|
||||||
auto start = std::chrono::high_resolution_clock::now();
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Calculate clipping bounds
|
if(element->scaled.width < 1 || element->scaled.height < 1) {
|
||||||
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
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get source buffer data
|
for(ClipRect dirty : dirtyRects) {
|
||||||
const Pixel_BU8_GU8_RU8_AU8* src_buffer = element->bufferScaled.data();
|
dirty.left = std::max(element->scaled.x, dirty.left);
|
||||||
std::uint_fast32_t src_width = element->scaled.width;
|
dirty.top = std::max(element->scaled.y, dirty.top);
|
||||||
std::uint_fast32_t src_height = element->scaled.height;
|
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 is opaque, we can simply copy pixels without blending
|
|
||||||
if (element->opaque) {
|
if (element->opaque) {
|
||||||
// Render clipped region
|
for (std::int_fast32_t y = dirty.top; y < dirty.bottom; y++) {
|
||||||
for (std::int_fast32_t y = clip_top; y < clip_bottom; y++) {
|
|
||||||
std::int_fast32_t src_y = y - element->scaled.y;
|
std::int_fast32_t src_y = y - element->scaled.y;
|
||||||
|
|
||||||
for (std::int_fast32_t x = clip_left; x < clip_right; x++) {
|
for (std::int_fast32_t x = dirty.left; x < dirty.right; x++) {
|
||||||
std::int_fast32_t src_x = x - element->scaled.x;
|
std::int_fast32_t src_x = x - element->scaled.x;
|
||||||
|
|
||||||
// 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)
|
|
||||||
framebuffer[y * width + x] = src_buffer[src_y * src_width + src_x];
|
framebuffer[y * width + x] = src_buffer[src_y * src_width + src_x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Render clipped region with blending for non-opaque elements
|
for (std::int_fast32_t y = dirty.top; y < dirty.bottom; y++) {
|
||||||
for (std::int_fast32_t y = clip_top; y < clip_bottom; y++) {
|
|
||||||
std::int_fast32_t src_y = y - element->scaled.y;
|
std::int_fast32_t src_y = y - element->scaled.y;
|
||||||
|
|
||||||
for (std::int_fast32_t x = clip_left; x < clip_right; x++) {
|
for (std::int_fast32_t x = dirty.left; x < dirty.right; x++) {
|
||||||
std::int_fast32_t src_x = x - element->scaled.x;
|
std::int_fast32_t src_x = x - element->scaled.x;
|
||||||
|
|
||||||
// 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
|
|
||||||
blend_pixel_optimized(framebuffer[y * width + x], src_buffer[src_y * src_width + src_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; });
|
std::sort(elements.begin(), elements.end(), [](Transform* a, Transform* b){ return a->z < b->z; });
|
||||||
|
|
||||||
if (!dirtyRects.empty()) {
|
if (!dirtyRects.empty()) {
|
||||||
for (const ScaleData& rect : dirtyRects) {
|
for (ClipRect rect : dirtyRects) {
|
||||||
for (std::int_fast32_t y = rect.y; y < rect.y + rect.height && y < height; y++) {
|
for (std::int_fast32_t y = rect.top; y < rect.bottom; y++) {
|
||||||
for (std::int_fast32_t x = rect.x; x < rect.x + rect.width && x < width; x++) {
|
for (std::int_fast32_t x = rect.left; x < rect.right; x++) {
|
||||||
framebuffer[y * width + x] = {0, 0, 0, 0};
|
framebuffer[y * width + x] = {0, 0, 0, 0};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -244,12 +225,14 @@ void WindowWayland::Render() {
|
||||||
RenderElement(child);
|
RenderElement(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const ScaleData& rect : dirtyRects) {
|
for (ClipRect rect : dirtyRects) {
|
||||||
wl_surface_damage(surface, rect.x, rect.y, rect.width, rect.height);
|
wl_surface_damage(surface, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top);
|
||||||
}
|
}
|
||||||
dirtyRects.clear();
|
dirtyRects.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dirtyRects.clear();
|
||||||
|
wl_surface_damage(surface, 0, 0, width, height);
|
||||||
|
|
||||||
wl_surface_attach(surface, buffer, 0, 0);
|
wl_surface_attach(surface, buffer, 0, 0);
|
||||||
wl_surface_commit(surface);
|
wl_surface_commit(surface);
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,13 @@ namespace Crafter {
|
||||||
std::int_fast32_t height;
|
std::int_fast32_t height;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export struct ClipRect {
|
||||||
|
std::int_fast32_t left;
|
||||||
|
std::int_fast32_t right;
|
||||||
|
std::int_fast32_t top;
|
||||||
|
std::int_fast32_t bottom;
|
||||||
|
};
|
||||||
|
|
||||||
export struct __attribute__((packed)) Pixel_BU8_GU8_RU8_AU8 {
|
export struct __attribute__((packed)) Pixel_BU8_GU8_RU8_AU8 {
|
||||||
std::uint8_t b;
|
std::uint8_t b;
|
||||||
std::uint8_t g;
|
std::uint8_t g;
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ export namespace Crafter {
|
||||||
bool open = true;
|
bool open = true;
|
||||||
bool updating = false;
|
bool updating = false;
|
||||||
|
|
||||||
std::vector<ScaleData> dirtyRects;
|
std::vector<ClipRect> dirtyRects;
|
||||||
void AddDirtyRect(ScaleData rect);
|
void AddDirtyRect(ScaleData rect);
|
||||||
|
|
||||||
Window() = default;
|
Window() = default;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue