Доки
BIN
wayland/docs/uml/diagram-activity-animation.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
51
wayland/docs/uml/diagram-activity-animation.puml
Normal 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
|
||||
BIN
wayland/docs/uml/diagram-activity-render.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
76
wayland/docs/uml/diagram-activity-render.puml
Normal 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
|
||||
BIN
wayland/docs/uml/diagram-class.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
127
wayland/docs/uml/diagram-class.puml
Normal 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
|
||||
BIN
wayland/docs/uml/diagram-component.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
74
wayland/docs/uml/diagram-component.puml
Normal 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
|
||||
BIN
wayland/docs/uml/diagram-sequence-init.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
78
wayland/docs/uml/diagram-sequence-init.puml
Normal 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
|
||||
BIN
wayland/docs/uml/diagram-sequence-keyboard.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
61
wayland/docs/uml/diagram-sequence-keyboard.puml
Normal 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
|
||||
BIN
wayland/docs/uml/diagram-state-figure.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
62
wayland/docs/uml/diagram-state-figure.puml
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||