draw rect optimization
This commit is contained in:
parent
6df6355ba7
commit
615d90c36f
3 changed files with 113 additions and 30 deletions
|
|
@ -111,10 +111,27 @@ void Window::AddDirtyRect(ScaleData scale) {
|
|||
return;
|
||||
}
|
||||
|
||||
//merging logic should work so that no pixel is drawn twice, and that no pixel not marked dirty is drawn.
|
||||
//so lets say there is already an existing horizontal bar and the new rect is a vertical bar making a cross shape, the center of the cross will currently be drawn twice
|
||||
//so we need to turn it into 3 rects, the top part of the vertical bar, the horizontal bar, and the bottom part of the vertical bar
|
||||
//in this way no pixel is drawn twice and no area not marked dirty is included
|
||||
for(ClipRect existing : dirtyRects) {
|
||||
//fully enclosed
|
||||
if(rect.left >= existing.left && rect.right <= existing.right && rect.top >= existing.top && rect.bottom <= existing.bottom) {
|
||||
return;
|
||||
}
|
||||
|
||||
//horizontal line
|
||||
if(rect.top == existing.top && rect.bottom == existing.bottom) {
|
||||
existing.left = std::min(rect.left, existing.left);
|
||||
existing.right = std::max(rect.right, existing.right);
|
||||
return;
|
||||
}
|
||||
|
||||
//vertical line
|
||||
if(rect.left == existing.left && rect.right == existing.right) {
|
||||
existing.top = std::min(rect.top, existing.top);
|
||||
existing.bottom = std::max(rect.bottom, existing.bottom);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//no overlap
|
||||
dirtyRects.push_back(rect);
|
||||
}
|
||||
|
|
@ -212,37 +212,104 @@ void WindowWayland::Render() {
|
|||
elements.erase(std::remove(elements.begin(), elements.end(), static_cast<Transform*>(nullptr)), elements.end());
|
||||
std::sort(elements.begin(), elements.end(), [](Transform* a, Transform* b){ return a->z < b->z; });
|
||||
|
||||
for(uint_fast32_t i = 0; i < width*height; i++) {
|
||||
framebuffer[i] = {0, 0, 0, 255};
|
||||
std::vector<ClipRect> newClip;
|
||||
|
||||
for (std::uint_fast32_t i = 0; i < dirtyRects.size(); i++) {
|
||||
ClipRect rect = dirtyRects[i];
|
||||
for (std::uint_fast32_t i2 = i + 1; i2 < dirtyRects.size(); i2++) {
|
||||
ClipRect existing = dirtyRects[i2];
|
||||
if(rect.bottom >= existing.top && rect.top <= existing.top) {
|
||||
newClip.push_back({
|
||||
.left = rect.left,
|
||||
.right = rect.right,
|
||||
.top = rect.top,
|
||||
.bottom = existing.top,
|
||||
});
|
||||
//-| shape
|
||||
if(rect.right > existing.right) {
|
||||
newClip.push_back({
|
||||
.left = existing.right,
|
||||
.right = rect.right,
|
||||
.top = existing.top,
|
||||
.bottom = existing.bottom,
|
||||
});
|
||||
}
|
||||
//|- shape
|
||||
if(rect.left < existing.left) {
|
||||
newClip.push_back({
|
||||
.left = rect.left,
|
||||
.right = existing.left,
|
||||
.top = existing.top,
|
||||
.bottom = existing.bottom,
|
||||
});
|
||||
}
|
||||
//-| or |- shape where rect extends further down
|
||||
if(rect.bottom > existing.bottom) {
|
||||
newClip.push_back({
|
||||
.left = rect.left,
|
||||
.right = rect.right,
|
||||
.top = existing.bottom,
|
||||
.bottom = rect.bottom,
|
||||
});
|
||||
}
|
||||
goto inner;
|
||||
}
|
||||
if (rect.left <= existing.right && rect.right >= existing.left) {
|
||||
newClip.push_back({
|
||||
.left = rect.left,
|
||||
.right = existing.left,
|
||||
.top = rect.top,
|
||||
.bottom = rect.bottom,
|
||||
});
|
||||
if (rect.right > existing.right) {
|
||||
newClip.push_back({
|
||||
.left = existing.right,
|
||||
.right = rect.right,
|
||||
.top = rect.top,
|
||||
.bottom = rect.bottom,
|
||||
});
|
||||
}
|
||||
goto inner;
|
||||
}
|
||||
}
|
||||
newClip.push_back(rect);
|
||||
inner:;
|
||||
}
|
||||
|
||||
dirtyRects = std::move(newClip);
|
||||
|
||||
// for(uint_fast32_t i = 0; i < width*height; i++) {
|
||||
// framebuffer[i] = {0, 0, 0, 255};
|
||||
// }
|
||||
|
||||
// std::cout << dirtyRects.size() << std::endl;
|
||||
// for (ClipRect rect : dirtyRects) {
|
||||
// //std::cout << std::format("{}, {}, {}, {}", rect.left, rect.top, rect.right, rect.bottom) << std::endl;
|
||||
// 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].r += 30;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!dirtyRects.empty()) {
|
||||
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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(Transform* child : elements) {
|
||||
RenderElement(child);
|
||||
}
|
||||
|
||||
for (ClipRect rect : dirtyRects) {
|
||||
//std::cout << std::format("{}, {}, {}, {}", rect.left, rect.top, rect.right, rect.bottom) << std::endl;
|
||||
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].r += 30;
|
||||
wl_surface_damage(surface, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top);
|
||||
}
|
||||
dirtyRects.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// if (!dirtyRects.empty()) {
|
||||
// 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};
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// for(Transform* child : elements) {
|
||||
// RenderElement(child);
|
||||
// }
|
||||
|
||||
// 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);
|
||||
|
|
|
|||
|
|
@ -56,9 +56,7 @@ export namespace Crafter {
|
|||
Event<FrameTime> onUpdate;
|
||||
bool open = true;
|
||||
bool updating = false;
|
||||
|
||||
std::vector<ClipRect> dirtyRects;
|
||||
void AddDirtyRect(ScaleData rect);
|
||||
|
||||
Window() = default;
|
||||
Window(std::int_fast32_t width, std::int_fast32_t height);
|
||||
|
|
@ -66,6 +64,7 @@ export namespace Crafter {
|
|||
Window(Window&&) = delete;
|
||||
virtual ~Window() = default;
|
||||
Window& operator=(const Window&) = delete;
|
||||
void AddDirtyRect(ScaleData rect);
|
||||
virtual void StartSync() = 0;
|
||||
virtual void StartUpdate() = 0;
|
||||
virtual void StopUpdate() = 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue