rendering element rewrite

This commit is contained in:
Jorijn van der Graaf 2025-12-28 00:05:03 +01:00
commit 3d40256bde
22 changed files with 799 additions and 795 deletions

View file

@ -23,7 +23,6 @@ module;
#include <stdlib.h>
#include <unistd.h>
#include <linux/input-event-codes.h>
#include <xkbcommon/xkbcommon.h>
#include "../lib/xdg-shell-client-protocol.h"
#include "../lib/wayland-xdg-decoration-unstable-v1-client-protocol.h"
#include <string.h>
@ -155,7 +154,7 @@ inline void blend_pixel_optimized(Pixel_BU8_GU8_RU8_AU8& dst, const Pixel_BU8_GU
}
void WindowWayland::RenderElement(Transform* transform) {
RenderingElement* element = dynamic_cast<RenderingElement*>(transform);
RenderingElementBase* element = dynamic_cast<RenderingElementBase*>(transform);
if(element) {
#ifdef CRAFTER_TIMING
auto start = std::chrono::high_resolution_clock::now();
@ -171,7 +170,7 @@ void WindowWayland::RenderElement(Transform* transform) {
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();
const Pixel_BU8_GU8_RU8_AU8* src_buffer = element->buffer.data();
std::int_fast32_t src_width = element->scaled.width;
std::int_fast32_t src_height = element->scaled.height;
@ -226,7 +225,7 @@ void WindowWayland::RenderElement(Transform* transform) {
#endif
}
std::sort(transform->children.begin(), transform->children.end(), [](Transform* a, Transform* b){ return a->z < b->z; });
std::sort(transform->children.begin(), transform->children.end(), [](Transform* a, Transform* b){ return a->anchor.z < b->anchor.z; });
for(Transform* child : transform->children) {
this->RenderElement(child);
}
@ -234,87 +233,107 @@ void WindowWayland::RenderElement(Transform* transform) {
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; });
std::sort(elements.begin(), elements.end(), [](Transform* a, Transform* b){ return a->anchor.z < b->anchor.z; });
std::vector<ClipRect> newClip;
//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};
// 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);
// std::memset(framebuffer, 0, width*height*4);
// 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;
// }
// }
// }
// // Color palette
// static const std::vector<Pixel_BU8_GU8_RU8_AU8> colors = {
// {255, 0, 0, 255}, // red
// { 0, 255, 0, 255}, // green
// { 0, 0, 255, 255}, // blue
// {255, 255, 0, 255}, // yellow
// {255, 0, 255, 255}, // magenta
// { 0, 255, 255, 255}, // cyan
// };
// std::size_t rectIndex = 0;
// for (const ClipRect& rect : dirtyRects) {
// const Pixel_BU8_GU8_RU8_AU8& color = colors[rectIndex % colors.size()];
// std::cout << std::format(
// "ClipRect {}: [{}, {}, {}, {}] Color = RGBA({}, {}, {}, {})",
// rectIndex,
// rect.left, rect.top, rect.right, rect.bottom,
// color.r, color.g, color.b, color.a
// ) << 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] = color;
// }
// }
// ++rectIndex;
// }
if (!dirtyRects.empty()) {
for (ClipRect rect : dirtyRects) {
@ -335,11 +354,17 @@ void WindowWayland::Render() {
dirtyRects.clear();
}
dirtyRects.clear();
wl_surface_damage(surface, 0, 0, width, height);
wl_surface_attach(surface, buffer, 0, 0);
wl_surface_commit(surface);
wl_surface_commit(surface);
wl_surface_damage(surface, 0, 0, 10000, 100000);
}
void WindowWayland::QueueRender() {
std::cout << cb << std::endl;
if(cb == nullptr) {
cb = wl_surface_frame(surface);
wl_callback_add_listener(cb, &wl_callback_listener, this);
}
}
void WindowWayland::StartUpdate() {
@ -396,6 +421,7 @@ void WindowWayland::wl_surface_frame_done(void* data, struct wl_callback *cb, ui
{
auto start = std::chrono::high_resolution_clock::now();
wl_callback_destroy(cb);
cb = nullptr;
WindowWayland* window = reinterpret_cast<WindowWayland*>(data);
#ifdef CRAFTER_TIMING
window->vblank = duration_cast<std::chrono::milliseconds>(start - window->frameEnd);
@ -413,18 +439,18 @@ void WindowWayland::wl_surface_frame_done(void* data, struct wl_callback *cb, ui
window->totalUpdate += entry.second;
}
#endif
#ifdef CRAFTER_TIMING
auto renderStart = std::chrono::high_resolution_clock::now();
window->renderTimings.clear();
#endif
window->Render();
#ifdef CRAFTER_TIMING
auto renderEnd = std::chrono::high_resolution_clock::now();
window->totalRender = renderEnd - renderStart;
#endif
}
#ifdef CRAFTER_TIMING
auto renderStart = std::chrono::high_resolution_clock::now();
window->renderTimings.clear();
#endif
window->Render();
#ifdef CRAFTER_TIMING
auto renderEnd = std::chrono::high_resolution_clock::now();
window->totalRender = renderEnd - renderStart;
#endif
#ifdef CRAFTER_TIMING
window->frameEnd = std::chrono::high_resolution_clock::now();
@ -557,6 +583,132 @@ void WindowWayland::keyboard_leave(void *data, wl_keyboard *keyboard, uint32_t s
}
CrafterKeys keysym_to_crafter_key(xkb_keysym_t sym)
{
switch (sym)
{
// Alphabet
case XKB_KEY_a: return CrafterKeys::A;
case XKB_KEY_b: return CrafterKeys::B;
case XKB_KEY_c: return CrafterKeys::C;
case XKB_KEY_d: return CrafterKeys::D;
case XKB_KEY_e: return CrafterKeys::E;
case XKB_KEY_f: return CrafterKeys::F;
case XKB_KEY_g: return CrafterKeys::G;
case XKB_KEY_h: return CrafterKeys::H;
case XKB_KEY_i: return CrafterKeys::I;
case XKB_KEY_j: return CrafterKeys::J;
case XKB_KEY_k: return CrafterKeys::K;
case XKB_KEY_l: return CrafterKeys::L;
case XKB_KEY_m: return CrafterKeys::M;
case XKB_KEY_n: return CrafterKeys::N;
case XKB_KEY_o: return CrafterKeys::O;
case XKB_KEY_p: return CrafterKeys::P;
case XKB_KEY_q: return CrafterKeys::Q;
case XKB_KEY_r: return CrafterKeys::R;
case XKB_KEY_s: return CrafterKeys::S;
case XKB_KEY_t: return CrafterKeys::T;
case XKB_KEY_u: return CrafterKeys::U;
case XKB_KEY_v: return CrafterKeys::V;
case XKB_KEY_w: return CrafterKeys::W;
case XKB_KEY_x: return CrafterKeys::X;
case XKB_KEY_y: return CrafterKeys::Y;
case XKB_KEY_z: return CrafterKeys::Z;
// Numbers
case XKB_KEY_0: return CrafterKeys::_0;
case XKB_KEY_1: return CrafterKeys::_1;
case XKB_KEY_2: return CrafterKeys::_2;
case XKB_KEY_3: return CrafterKeys::_3;
case XKB_KEY_4: return CrafterKeys::_4;
case XKB_KEY_5: return CrafterKeys::_5;
case XKB_KEY_6: return CrafterKeys::_6;
case XKB_KEY_7: return CrafterKeys::_7;
case XKB_KEY_8: return CrafterKeys::_8;
case XKB_KEY_9: return CrafterKeys::_9;
// Function keys
case XKB_KEY_F1: return CrafterKeys::F1;
case XKB_KEY_F2: return CrafterKeys::F2;
case XKB_KEY_F3: return CrafterKeys::F3;
case XKB_KEY_F4: return CrafterKeys::F4;
case XKB_KEY_F5: return CrafterKeys::F5;
case XKB_KEY_F6: return CrafterKeys::F6;
case XKB_KEY_F7: return CrafterKeys::F7;
case XKB_KEY_F8: return CrafterKeys::F8;
case XKB_KEY_F9: return CrafterKeys::F9;
case XKB_KEY_F10: return CrafterKeys::F10;
case XKB_KEY_F11: return CrafterKeys::F11;
case XKB_KEY_F12: return CrafterKeys::F12;
// Control keys
case XKB_KEY_Escape: return CrafterKeys::Escape;
case XKB_KEY_Tab: return CrafterKeys::Tab;
case XKB_KEY_Return: return CrafterKeys::Enter;
case XKB_KEY_space: return CrafterKeys::Space;
case XKB_KEY_BackSpace: return CrafterKeys::Backspace;
case XKB_KEY_Delete: return CrafterKeys::Delete;
case XKB_KEY_Insert: return CrafterKeys::Insert;
case XKB_KEY_Home: return CrafterKeys::Home;
case XKB_KEY_End: return CrafterKeys::End;
case XKB_KEY_Page_Up: return CrafterKeys::PageUp;
case XKB_KEY_Page_Down: return CrafterKeys::PageDown;
case XKB_KEY_Caps_Lock: return CrafterKeys::CapsLock;
case XKB_KEY_Num_Lock: return CrafterKeys::NumLock;
case XKB_KEY_Scroll_Lock:return CrafterKeys::ScrollLock;
// Modifiers
case XKB_KEY_Shift_L: return CrafterKeys::LeftShift;
case XKB_KEY_Shift_R: return CrafterKeys::RightShift;
case XKB_KEY_Control_L: return CrafterKeys::LeftCtrl;
case XKB_KEY_Control_R: return CrafterKeys::RightCtrl;
case XKB_KEY_Alt_L: return CrafterKeys::LeftAlt;
case XKB_KEY_Alt_R: return CrafterKeys::RightAlt;
case XKB_KEY_Super_L: return CrafterKeys::LeftSuper;
case XKB_KEY_Super_R: return CrafterKeys::RightSuper;
// Arrows
case XKB_KEY_Up: return CrafterKeys::Up;
case XKB_KEY_Down: return CrafterKeys::Down;
case XKB_KEY_Left: return CrafterKeys::Left;
case XKB_KEY_Right: return CrafterKeys::Right;
// Keypad
case XKB_KEY_KP_0: return CrafterKeys::keypad_0;
case XKB_KEY_KP_1: return CrafterKeys::keypad_1;
case XKB_KEY_KP_2: return CrafterKeys::keypad_2;
case XKB_KEY_KP_3: return CrafterKeys::keypad_3;
case XKB_KEY_KP_4: return CrafterKeys::keypad_4;
case XKB_KEY_KP_5: return CrafterKeys::keypad_5;
case XKB_KEY_KP_6: return CrafterKeys::keypad_6;
case XKB_KEY_KP_7: return CrafterKeys::keypad_7;
case XKB_KEY_KP_8: return CrafterKeys::keypad_8;
case XKB_KEY_KP_9: return CrafterKeys::keypad_9;
case XKB_KEY_KP_Enter: return CrafterKeys::keypad_enter;
case XKB_KEY_KP_Add: return CrafterKeys::keypad_plus;
case XKB_KEY_KP_Subtract: return CrafterKeys::keypad_minus;
case XKB_KEY_KP_Multiply: return CrafterKeys::keypad_multiply;
case XKB_KEY_KP_Divide: return CrafterKeys::keypad_divide;
case XKB_KEY_KP_Decimal: return CrafterKeys::keypad_decimal;
// Punctuation
case XKB_KEY_grave: return CrafterKeys::grave;
case XKB_KEY_minus: return CrafterKeys::minus;
case XKB_KEY_equal: return CrafterKeys::equal;
case XKB_KEY_bracketleft: return CrafterKeys::bracket_left;
case XKB_KEY_bracketright:return CrafterKeys::bracket_right;
case XKB_KEY_backslash: return CrafterKeys::backslash;
case XKB_KEY_semicolon: return CrafterKeys::semicolon;
case XKB_KEY_apostrophe: return CrafterKeys::quote;
case XKB_KEY_comma: return CrafterKeys::comma;
case XKB_KEY_period: return CrafterKeys::period;
case XKB_KEY_slash: return CrafterKeys::slash;
default:
return CrafterKeys::CrafterKeysMax;
}
}
void WindowWayland::keyboard_key(void *data, wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
WindowWayland* window = reinterpret_cast<WindowWayland*>(data);
@ -566,33 +718,22 @@ void WindowWayland::keyboard_key(void *data, wl_keyboard *keyboard, uint32_t ser
xkb_keycode_t keycode = key + 8;
xkb_keysym_t keysym = xkb_state_key_get_one_sym(window->xkb_state, keycode);
CrafterKeys crafterKey = keysym_to_crafter_key(keysym);
char utf8[8] = {0};
int len = xkb_keysym_to_utf8(keysym, utf8, sizeof(utf8));
if (len != 0) {
char keypress = utf8[0];
if(state == WL_KEYBOARD_KEY_STATE_PRESSED) {
if(window->heldkeys[keypress]) {
window->onKeyHold[keypress].Invoke();
window->onAnyKeyHold.Invoke(keypress);
} else{
window->heldkeys[keypress] = true;
window->onKeyDown[keypress].Invoke();
window->onAnyKeyDown.Invoke(keypress);
}
} else{
window->heldkeys[keypress] = false;
window->onKeyUp[keypress].Invoke();
window->onAnyKeyUp.Invoke(keypress);
}
} else {
// // fallback for keys like Return, Escape, etc.
// char name[64];
// if (xkb_keysym_get_name(keysym, name, sizeof(name)) > 0) {
// printf("Key %s pressed (non-printable or multi-char)\n", name);
// }
}
if(state == WL_KEYBOARD_KEY_STATE_PRESSED) {
if(window->heldkeys[static_cast<std::uint8_t>(crafterKey)]) {
window->onKeyHold[static_cast<std::uint8_t>(crafterKey)].Invoke();
window->onAnyKeyHold.Invoke(crafterKey);
} else{
window->heldkeys[static_cast<std::uint8_t>(crafterKey)] = true;
window->onKeyDown[static_cast<std::uint8_t>(crafterKey)].Invoke();
window->onAnyKeyDown.Invoke(crafterKey);
}
} else{
window->heldkeys[static_cast<std::uint8_t>(crafterKey)] = false;
window->onKeyUp[static_cast<std::uint8_t>(crafterKey)].Invoke();
window->onAnyKeyUp.Invoke(crafterKey);
}
}
void WindowWayland::keyboard_modifiers(void *data, wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) {