This commit is contained in:
2025-11-18 01:22:01 +03:00
parent d04c04f028
commit 51a0a6a2eb
16 changed files with 535 additions and 5 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -0,0 +1,51 @@
@startuml
title Цикл анимации фигуры (aux_thread)
start
:aux_thread запущен;
while (окно не закрыто?) is (да)
:Залочить figure_mutex;
:figure_animation_step(draw_info);
partition "figure_animation_step (ASM)" {
:Обработка коллизий;
note right
figure_handle_collision():
- Расчёт точек фигуры на окружности
- Проверка выхода за границы
- Инверсия velocity при коллизии
- Обновление angular_velocity
end note
:Обновить позицию;
note right
position += (velocity * speed) / height
end note
:Обновить угол поворота;
note right
angle += angular_velocity * speed
end note
:Применить трение к вращению;
note right
angular_velocity *= 0.95
end note
}
:Разлочить figure_mutex;
:usleep(33 ms);
note right: ~30 FPS обновление физики
endwhile (нет)
:Завершение потока;
stop
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@@ -0,0 +1,76 @@
@startuml
title Цикл отрисовки окна (window_thread)
start
:window_thread запущен;
:Создать event queue;
:window_init();
:Запустить aux_thread для анимации;
while (окно не закрыто?) is (да)
:wl_display_dispatch_queue();
note right: Ожидание событий Wayland
if (событие произошло?) then (да)
if (xdg_surface_configure?) then (да)
:xdg_surface_ack_configure();
if (буфер не создан?) then (да)
:resize_canvas();
endif
:draw();
endif
if (xdg_toplevel_configure?) then (да)
if (размер изменился?) then (да)
:resize_new(w, h);
note right
- Освободить старый буфер
- Создать новый буфер
- Обновить размеры draw_info
end note
endif
endif
if (xdg_toplevel_close?) then (да)
:Установить need_close = 1;
endif
if (frame_callback?) then (да)
:Уничтожить старый callback;
:Создать новый callback;
partition "draw()" {
:Залочить figure_mutex;
:Очистить фон (черный);
:figure_draw();
note right
- Получить текущую фигуру
- Нарисовать границу и заливку
- Цвет зависит от типа фигуры
end note
:Разлочить figure_mutex;
:wl_surface_attach(buffer);
:wl_surface_damage_buffer();
:wl_surface_commit();
}
endif
endif
endwhile (нет)
:window_destroy();
:Уничтожить event queue;
:signal_thread_exit();
stop
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

View File

@@ -0,0 +1,127 @@
@startuml
title Структура классов проекта Wayland
class wayland_runtime {
+ init_wayland() : int32_t
+ run_window() : int32_t
+ wait_for_windows() : void
+ destroy_wayland() : void
+ get_window_by_surface(surf) : wayland_window*
--
- g_display : wl_display*
- g_slots[MAX_WINDOW_THREADS] : window_thread_slot
- g_thread_lock : pthread_mutex_t
- g_active_threads : atomic_int
- g_shutdown : atomic_bool
}
class window_thread_slot {
+ thread : pthread_t
+ aux_thread : pthread_t
+ active : int
+ queue : wl_event_queue*
+ window : wayland_window
}
class wayland_window {
+ id : int
+ wl_surface : wl_surface*
+ xdg_surface : xdg_surface*
+ xdg_toplevel : xdg_toplevel*
+ buffer : wl_buffer*
+ frame_callback : wl_callback*
+ queue : wl_event_queue*
+ need_close : int
+ draw_info : window_draw_info
--
+ window_init(display, queue) : int
+ window_destroy() : void
+ window_should_close() : int
}
class window_draw_info {
+ width : uint32_t
+ height : uint32_t
+ data : void*
+ figure : figure_animation_info
+ figure_mutex : pthread_mutex_t
}
class figure_animation_info {
+ type : figure_type
+ position : vec2
+ velocity : vec2
+ angle : float
+ angular_velocity : float
+ speed : float
+ radius : float
}
enum figure_type {
FIGURE_CIRCLE = 0
FIGURE_TRIANGLE = 1
FIGURE_SQUARE = 2
}
class registry {
+ registry_global_bind(display) : int
+ registry_global_unbind() : void
+ registry_get_compositor() : wl_compositor*
+ registry_get_shm() : wl_shm*
+ registry_get_xdg_wm_base() : xdg_wm_base*
--
- global_compositor : wl_compositor*
- global_shm : wl_shm*
- global_wm_base : xdg_wm_base*
- global_registry : wl_registry*
- global_thread : pthread_t
- global_thread_running : atomic_int
}
class input {
+ input_register_seat(seat) : void
+ input_cleanup() : void
--
- seat : wl_seat*
- keyboard : wl_keyboard*
- xkb_ctx : xkb_context*
- xkb_keymap : xkb_keymap*
- xkb_state : xkb_state*
- focused_window : wayland_window*
}
class input_handle {
+ keyboard_key_handle(kc, ks, state, window) : void
}
class figure_animate <<ASM>> {
+ figure_animation_step(draw_info) : void
+ place_points_on_circle(...) : void
--
- figure_handle_collision(draw_info) : void
- check_collision_mask(...) : uint64_t
- sincos_f32_rbp(angle) : (sin, cos)
}
class figure_draw {
+ figure_draw(draw_info, thickness, border_color, fill_color) : void
}
wayland_runtime "1" *-- "0..128" window_thread_slot
window_thread_slot "1" *-- "1" wayland_window
wayland_window "1" *-- "1" window_draw_info
window_draw_info "1" *-- "1" figure_animation_info
figure_animation_info --> figure_type
wayland_runtime ..> registry : uses
wayland_runtime ..> input : uses
wayland_window ..> registry : uses
wayland_window ..> figure_draw : uses
input ..> input_handle : uses
input --> wayland_window : focuses
window_thread_slot ..> figure_animate : uses (aux_thread)
figure_draw ..> figure_animate : uses
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@@ -0,0 +1,74 @@
@startuml
title Компоненты проекта Wayland
package "Wayland Application" {
[wayland-runtime] as Runtime
[registry] as Registry
[input] as Input
[input-handle] as InputHandle
[window] as Window
package "Rendering & Animation" {
[figure-draw] as FigureDraw
[figure-animate (ASM)] as FigureAnimate
}
Runtime --> Registry : использует глобальные объекты
Runtime --> Input : инициализирует
Runtime --> Window : создаёт и управляет
Input --> InputHandle : делегирует обработку
InputHandle --> Runtime : вызывает run_window()
InputHandle --> Window : изменяет параметры фигуры
Window --> Registry : получает compositor, shm, wm_base
Window --> FigureDraw : отрисовка фигуры
Window --> FigureAnimate : aux_thread для анимации
FigureDraw --> FigureAnimate : использует place_points_on_circle
}
package "System Libraries" {
[wayland-client] as WaylandLib
[xdg-shell-protocol] as XDGShell
[xkbcommon] as XKB
}
Registry --> WaylandLib
Registry --> XDGShell
Window --> WaylandLib
Window --> XDGShell
Input --> WaylandLib
Input --> XKB
cloud "Wayland Compositor" as Compositor
Runtime --> Compositor : wl_display_connect()
Registry --> Compositor : получение глобальных объектов
Window --> Compositor : создание окон и буферов
Input --> Compositor : получение событий клавиатуры
note right of Runtime
Центральный компонент:
- Управление жизненным циклом
- Многопоточность (окна + анимация)
- Синхронизация через mutex
end note
note right of FigureAnimate
Реализация на NASM:
- Физика движения
- Обработка коллизий
- Математика (sin/cos)
- SSE инструкции
end note
note right of Window
Каждое окно в отдельном потоке:
- window_thread: отрисовка
- aux_thread: анимация
- Event queue для изоляции событий
end note
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

@@ -0,0 +1,78 @@
@startuml
title Последовательность инициализации Wayland приложения
actor Main
participant "wayland-runtime" as Runtime
participant "registry" as Registry
participant "input" as Input
participant "window" as Window
Main -> Runtime: init_wayland()
activate Runtime
Runtime -> Runtime: wl_display_connect()
note right: Подключение к Wayland серверу
Runtime -> Registry: registry_global_bind(display)
activate Registry
Registry -> Registry: wl_display_get_registry()
Registry -> Registry: wl_registry_add_listener()
Registry -> Registry: wl_display_roundtrip()
note right: Получение глобальных объектов:\n- wl_compositor\n- wl_shm\n- xdg_wm_base\n- wl_seat
Registry -> Input: input_register_seat(seat)
activate Input
Input -> Input: wl_seat_add_listener()
Input -> Input: wl_seat_get_keyboard()
Input -> Input: xkb_context_new()
note right: Инициализация обработки клавиатуры
deactivate Input
Registry -> Registry: pthread_create(global_thread)
note right: Запуск потока обработки\nглобальных событий
deactivate Registry
Runtime -> Runtime: Инициализация слотов окон
Runtime -> Runtime: atomic_store(g_shutdown, 0)
deactivate Runtime
Main -> Runtime: run_window()
activate Runtime
Runtime -> Runtime: Найти свободный слот
Runtime -> Runtime: pthread_create(window_thread)
note right: Создание потока окна
Runtime --> Main: slot_index
== Поток окна ==
Runtime -> Runtime: wl_display_create_queue()
Runtime -> Window: window_init(display, queue)
activate Window
Window -> Registry: registry_get_compositor()
Window -> Registry: registry_get_shm()
Window -> Registry: registry_get_xdg_wm_base()
Window -> Window: wl_compositor_create_surface()
Window -> Window: xdg_wm_base_get_xdg_surface()
Window -> Window: xdg_surface_get_toplevel()
Window -> Window: Инициализация listeners
Window -> Window: Инициализация figure_animation_info
note right: Параметры анимации:\n- position, velocity\n- angle, angular_velocity\n- speed, radius
deactivate Window
Runtime -> Runtime: pthread_create(aux_thread)
note right: Вспомогательный поток\nдля анимации
Runtime -> Runtime: wl_display_dispatch_queue()
note right: Цикл обработки событий окна
deactivate Runtime
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -0,0 +1,61 @@
@startuml
title Обработка клавиатурного ввода
actor User
participant "Wayland Server" as Server
participant "input" as Input
participant "input-handle" as Handler
participant "wayland-runtime" as Runtime
participant "window" as Window
User -> Server: Нажатие клавиши
Server -> Input: keyboard_key(key, state)
activate Input
Input -> Input: xkb_state_key_get_one_sym()
note right: Преобразование keycode в keysym
Input -> Handler: keyboard_key_handle(kc, ks, state, window)
activate Handler
alt Клавиша Enter
Handler -> Runtime: run_window()
note right: Создание нового окна
else Клавиша '1'
Handler -> Window: figure.type = CIRCLE
else Клавиша '2'
Handler -> Window: figure.type = TRIANGLE
else Клавиша '3'
Handler -> Window: figure.type = SQUARE
else Клавиша '-'
Handler -> Handler: pthread_mutex_lock()
Handler -> Window: figure.speed -= 0.5
Handler -> Handler: Ограничить [1, 30]
Handler -> Handler: pthread_mutex_unlock()
else Клавиша '+' или '='
Handler -> Handler: pthread_mutex_lock()
Handler -> Window: figure.speed += 0.5
Handler -> Handler: Ограничить [1, 30]
Handler -> Handler: pthread_mutex_unlock()
else Клавиша Up
Handler -> Handler: pthread_mutex_lock()
Handler -> Window: figure.radius += 2.0
Handler -> Handler: Ограничить [1, max]
Handler -> Handler: pthread_mutex_unlock()
else Клавиша Down
Handler -> Handler: pthread_mutex_lock()
Handler -> Window: figure.radius -= 2.0
Handler -> Handler: Ограничить [1, max]
Handler -> Handler: pthread_mutex_unlock()
end
deactivate Handler
deactivate Input
note over Window
Изменения параметров фигуры
влияют на следующий frame
анимации и отрисовки
end note
@enduml

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

@@ -0,0 +1,62 @@
@startuml
title Диаграмма состояний фигуры
[*] --> Circle : init (по умолчанию)
Circle : Красный цвет (0xFFFF0000)
Circle : radius точек = 16
Triangle : Зелёный цвет (0xFF00FF00)
Triangle : radius точек = 3
Square : Синий цвет (0xFF0000FF)
Square : radius точек = 4
Circle --> Triangle : Клавиша '2'
Circle --> Square : Клавиша '3'
Triangle --> Circle : Клавиша '1'
Triangle --> Square : Клавиша '3'
Square --> Circle : Клавиша '1'
Square --> Triangle : Клавиша '2'
Circle : velocity движет позицию
Circle : angular_velocity вращает
Triangle : velocity движет позицию
Triangle : angular_velocity вращает
Square : velocity движет позицию
Square : angular_velocity вращает
note right of Circle
Общие свойства для всех состояний:
- position (x, y)
- velocity (vx, vy)
- angle (угол поворота)
- angular_velocity (скорость вращения)
- speed (множитель скорости: 1-30)
- radius (радиус в пикселях)
Управление:
- '+'/'-': изменение speed
- Up/Down: изменение radius
- Enter: создать новое окно
end note
state "Коллизия с границей" as Collision {
[*] --> CheckCollision
CheckCollision --> InvertVelocity : точка вышла за границу
InvertVelocity --> UpdateAngularVel : инверсия компоненты velocity
UpdateAngularVel --> CheckCollision : обновление angular_velocity
CheckCollision : проверка всех точек фигуры
InvertVelocity : vel = -vel (по оси коллизии)
UpdateAngularVel : зависит от направления движения
}
Circle --> Collision : каждый frame
Triangle --> Collision : каждый frame
Square --> Collision : каждый frame
Collision --> Circle
Collision --> Triangle
Collision --> Square
@enduml

View File

@@ -18,7 +18,7 @@ ANG_COLLIDE_COEF: dd 0.55
ANG_BOOST_FACTOR: dd 0.02
ANG_MAX: dd 0.04
ANG_SWITCH_FACTOR: dd 0.1
ANG_MAX_DELTA: dd 0.5
ANG_MAX_DELTA: dd 0.1
ANG_FRICTION: dd 0.95
section .text
@@ -380,6 +380,7 @@ figure_handle_collision:
; Обработка коллизий: инвертировать velocity только если движемся к границе
; Обработка velocity
; Проверка left (bit 0): инвертировать velocity.x только если vel.x < 0
test r14, 0x1
jz .check_right

View File

@@ -34,7 +34,7 @@ void keyboard_key_handle(xkb_keycode_t kc, xkb_keysym_t ks, enum keyboard_key_st
case '-':
/* decrease animation speed (multiplicative delta, clamped) */
pthread_mutex_lock(&window->draw_info.figure_mutex);
window->draw_info.figure.speed -= 0.5f;
window->draw_info.figure.speed -= 1;
if (window->draw_info.figure.speed < 1)
window->draw_info.figure.speed = 1;
printf("keyboard: speed decreased to %.2f\n", window->draw_info.figure.speed);
@@ -44,9 +44,9 @@ void keyboard_key_handle(xkb_keycode_t kc, xkb_keysym_t ks, enum keyboard_key_st
case '=': /* some layouts may emit '=' for unshifted, handle + via keysym */
/* increase animation speed (multiplicative delta, clamped) */
pthread_mutex_lock(&window->draw_info.figure_mutex);
window->draw_info.figure.speed += 0.5f;
if (window->draw_info.figure.speed > 30.0f)
window->draw_info.figure.speed = 30.0f;
window->draw_info.figure.speed += 1;
if (window->draw_info.figure.speed > 50.0f)
window->draw_info.figure.speed = 50.0f;
printf("keyboard: speed increased to %.2f\n", window->draw_info.figure.speed);
pthread_mutex_unlock(&window->draw_info.figure_mutex);
break;