отдельный поток для физики и изменение цвета
This commit is contained in:
9
wayland/include/figure-animate.h
Normal file
9
wayland/include/figure-animate.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef FIGURE_ANIMATE_H
|
||||||
|
#define FIGURE_ANIMATE_H
|
||||||
|
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
/* Провести один шаг анимации на окне */
|
||||||
|
void animation_step(struct window_draw_info* draw_info, float speed_multiplier);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef WAYLAND_WINDOW_H
|
#ifndef WAYLAND_WINDOW_H
|
||||||
#define WAYLAND_WINDOW_H
|
#define WAYLAND_WINDOW_H
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include "figure.h"
|
#include "figure.h"
|
||||||
|
|
||||||
@@ -8,8 +9,8 @@ struct window_draw_info {
|
|||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
int32_t width;
|
int32_t width;
|
||||||
int32_t height;
|
int32_t height;
|
||||||
uint8_t color;
|
|
||||||
struct figure_info figure;
|
struct figure_info figure;
|
||||||
|
pthread_mutex_t figure_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Данные одного Wayland-окна (одна поверхность) */
|
/* Данные одного Wayland-окна (одна поверхность) */
|
||||||
|
|||||||
@@ -21,6 +21,15 @@ void keyboard_key_handle(xkb_keycode_t kc, xkb_keysym_t ks, enum keyboard_key_st
|
|||||||
run_window();
|
run_window();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '1':
|
||||||
|
window->draw_info.figure.type = FIGURE_CIRCLE;
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
window->draw_info.figure.type = FIGURE_TRIANGLE;
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
window->draw_info.figure.type = FIGURE_SQUARE;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "registry.h"
|
#include "registry.h"
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
struct window_thread_slot
|
struct window_thread_slot
|
||||||
{
|
{
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
|
pthread_t aux_thread;
|
||||||
int active;
|
int active;
|
||||||
struct wl_event_queue *queue;
|
struct wl_event_queue *queue;
|
||||||
struct wayland_window window;
|
struct wayland_window window;
|
||||||
@@ -38,6 +40,21 @@ static void signal_thread_exit(struct window_thread_slot *slot)
|
|||||||
pthread_mutex_unlock(&g_thread_lock);
|
pthread_mutex_unlock(&g_thread_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *window_aux_loop(void *arg)
|
||||||
|
{
|
||||||
|
struct window_thread_slot *slot = arg;
|
||||||
|
struct window_draw_info *draw_info = &slot->window.draw_info;
|
||||||
|
while (!atomic_load(&g_shutdown) && !window_should_close(&slot->window))
|
||||||
|
{
|
||||||
|
/* На время обновления позиции фигуры локаем мутекс */
|
||||||
|
pthread_mutex_lock(&draw_info->figure_mutex);
|
||||||
|
usleep(10 * 1000);
|
||||||
|
pthread_mutex_unlock(&draw_info->figure_mutex);
|
||||||
|
usleep(100 * 1000);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void *window_thread_main(void *arg)
|
static void *window_thread_main(void *arg)
|
||||||
{
|
{
|
||||||
struct window_thread_slot *slot = arg;
|
struct window_thread_slot *slot = arg;
|
||||||
@@ -50,7 +67,6 @@ static void *window_thread_main(void *arg)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (window_init(g_display, slot->queue, &slot->window) < 0)
|
if (window_init(g_display, slot->queue, &slot->window) < 0)
|
||||||
{
|
{
|
||||||
wl_event_queue_destroy(slot->queue);
|
wl_event_queue_destroy(slot->queue);
|
||||||
@@ -59,6 +75,12 @@ static void *window_thread_main(void *arg)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Запуск вспомогательного потока, который пока просто крутится с паузой 100 ms.
|
||||||
|
* Поток завершится, как только окно будет помечено как закрыто. */
|
||||||
|
int aux_res = pthread_create(&slot->aux_thread, NULL, window_aux_loop, slot);
|
||||||
|
if (aux_res == 0)
|
||||||
|
pthread_detach(slot->aux_thread);
|
||||||
|
|
||||||
while (!atomic_load(&g_shutdown) && !window_should_close(&slot->window))
|
while (!atomic_load(&g_shutdown) && !window_should_close(&slot->window))
|
||||||
{
|
{
|
||||||
int dispatch = wl_display_dispatch_queue(g_display, slot->queue);
|
int dispatch = wl_display_dispatch_queue(g_display, slot->queue);
|
||||||
@@ -176,10 +198,10 @@ void destroy_wayland(void)
|
|||||||
atomic_store(&g_shutdown, 0);
|
atomic_store(&g_shutdown, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wayland_window* get_window_by_surface(struct wl_surface* surf)
|
struct wayland_window *get_window_by_surface(struct wl_surface *surf)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < MAX_WINDOW_THREADS; i++)
|
for (int i = 0; i < MAX_WINDOW_THREADS; i++)
|
||||||
if(g_slots[i].window.wl_surface == surf)
|
if (g_slots[i].window.wl_surface == surf)
|
||||||
return &g_slots[i].window;
|
return &g_slots[i].window;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ static void destroy_frame_callback(struct wayland_window *win)
|
|||||||
|
|
||||||
static void resize_canvas(struct wayland_window *win)
|
static void resize_canvas(struct wayland_window *win)
|
||||||
{
|
{
|
||||||
struct window_draw_info* draw_info = &win->draw_info;
|
struct window_draw_info *draw_info = &win->draw_info;
|
||||||
size_t stride = draw_info->width * 4;
|
size_t stride = draw_info->width * 4;
|
||||||
size_t size = stride * draw_info->height;
|
size_t size = stride * draw_info->height;
|
||||||
int32_t fd = alloc_shm(size);
|
int32_t fd = alloc_shm(size);
|
||||||
@@ -76,7 +76,7 @@ static void resize_new(struct wayland_window *win, int32_t w, int32_t h)
|
|||||||
{
|
{
|
||||||
if (!w || !h)
|
if (!w || !h)
|
||||||
return;
|
return;
|
||||||
struct window_draw_info* draw_info = &win->draw_info;
|
struct window_draw_info *draw_info = &win->draw_info;
|
||||||
|
|
||||||
if (draw_info->width != w || draw_info->height != h)
|
if (draw_info->width != w || draw_info->height != h)
|
||||||
{
|
{
|
||||||
@@ -93,7 +93,7 @@ static void resize_new(struct wayland_window *win, int32_t w, int32_t h)
|
|||||||
|
|
||||||
static void draw(struct wayland_window *win)
|
static void draw(struct wayland_window *win)
|
||||||
{
|
{
|
||||||
struct window_draw_info* draw_info = &win->draw_info;
|
struct window_draw_info *draw_info = &win->draw_info;
|
||||||
|
|
||||||
size_t stride = draw_info->width * 4;
|
size_t stride = draw_info->width * 4;
|
||||||
size_t size = stride * draw_info->height;
|
size_t size = stride * draw_info->height;
|
||||||
@@ -101,7 +101,35 @@ static void draw(struct wayland_window *win)
|
|||||||
if (!draw_info->data || !win->buffer)
|
if (!draw_info->data || !win->buffer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memset(draw_info->data, draw_info->color++, size);
|
// Залочиться, чтобы операции обновления позиции фигуры происходили атомарно
|
||||||
|
pthread_mutex_lock(&draw_info->figure_mutex);
|
||||||
|
struct figure_info figure = draw_info->figure;
|
||||||
|
pthread_mutex_unlock(&draw_info->figure_mutex);
|
||||||
|
|
||||||
|
uint32_t color;
|
||||||
|
switch (figure.type)
|
||||||
|
{
|
||||||
|
case FIGURE_CIRCLE:
|
||||||
|
color = 0xFFFFFFFF;
|
||||||
|
break;
|
||||||
|
case FIGURE_TRIANGLE:
|
||||||
|
color = 0xFFFF0000;
|
||||||
|
break;
|
||||||
|
case FIGURE_SQUARE:
|
||||||
|
color = 0xFF00FF00;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *bytes = (uint8_t *)draw_info->data;
|
||||||
|
for (int32_t y = 0; y < (int32_t)draw_info->height; ++y)
|
||||||
|
{
|
||||||
|
uint32_t *row = (uint32_t *)(bytes + y * stride);
|
||||||
|
for (int32_t x = 0; x < (int32_t)draw_info->width; ++x)
|
||||||
|
row[x] = color;
|
||||||
|
}
|
||||||
|
|
||||||
wl_surface_attach(win->wl_surface, win->buffer, 0, 0);
|
wl_surface_attach(win->wl_surface, win->buffer, 0, 0);
|
||||||
wl_surface_damage_buffer(win->wl_surface, 0, 0, draw_info->width, draw_info->height);
|
wl_surface_damage_buffer(win->wl_surface, 0, 0, draw_info->width, draw_info->height);
|
||||||
@@ -134,12 +162,17 @@ static void xdg_toplevel_cls(void *data, struct xdg_toplevel *xdg_top)
|
|||||||
|
|
||||||
static void xdg_toplevel_bounds(void *data, struct xdg_toplevel *xdg_top, int32_t w, int32_t h)
|
static void xdg_toplevel_bounds(void *data, struct xdg_toplevel *xdg_top, int32_t w, int32_t h)
|
||||||
{
|
{
|
||||||
(void)data; (void)xdg_top; (void)w; (void)h;
|
(void)data;
|
||||||
|
(void)xdg_top;
|
||||||
|
(void)w;
|
||||||
|
(void)h;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xdg_toplevel_wm_caps(void *data, struct xdg_toplevel *xdg_top, struct wl_array *caps)
|
static void xdg_toplevel_wm_caps(void *data, struct xdg_toplevel *xdg_top, struct wl_array *caps)
|
||||||
{
|
{
|
||||||
(void)data; (void)xdg_top; (void)caps;
|
(void)data;
|
||||||
|
(void)xdg_top;
|
||||||
|
(void)caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wl_callback_listener callback_listener;
|
static struct wl_callback_listener callback_listener;
|
||||||
@@ -162,19 +195,15 @@ static void frame_new(void *data, struct wl_callback *cb, uint32_t _)
|
|||||||
draw(win);
|
draw(win);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct wl_callback_listener callback_listener = {
|
static struct wl_callback_listener callback_listener = {
|
||||||
.done = frame_new
|
.done = frame_new};
|
||||||
};
|
|
||||||
static struct xdg_surface_listener surface_listener = {
|
static struct xdg_surface_listener surface_listener = {
|
||||||
.configure = xdg_surface_conf
|
.configure = xdg_surface_conf};
|
||||||
};
|
|
||||||
static struct xdg_toplevel_listener top_listener = {
|
static struct xdg_toplevel_listener top_listener = {
|
||||||
.configure = xdg_toplevel_conf,
|
.configure = xdg_toplevel_conf,
|
||||||
.close = xdg_toplevel_cls,
|
.close = xdg_toplevel_cls,
|
||||||
.configure_bounds = xdg_toplevel_bounds,
|
.configure_bounds = xdg_toplevel_bounds,
|
||||||
.wm_capabilities = xdg_toplevel_wm_caps
|
.wm_capabilities = xdg_toplevel_wm_caps};
|
||||||
};
|
|
||||||
|
|
||||||
int window_init(struct wl_display *display, struct wl_event_queue *queue, struct wayland_window *win)
|
int window_init(struct wl_display *display, struct wl_event_queue *queue, struct wayland_window *win)
|
||||||
{
|
{
|
||||||
@@ -202,12 +231,11 @@ int window_init(struct wl_display *display, struct wl_event_queue *queue, struct
|
|||||||
if (win->xdg_toplevel && queue)
|
if (win->xdg_toplevel && queue)
|
||||||
wl_proxy_set_queue((struct wl_proxy *)win->xdg_toplevel, queue);
|
wl_proxy_set_queue((struct wl_proxy *)win->xdg_toplevel, queue);
|
||||||
|
|
||||||
|
|
||||||
xdg_toplevel_add_listener(win->xdg_toplevel, &top_listener, win);
|
xdg_toplevel_add_listener(win->xdg_toplevel, &top_listener, win);
|
||||||
|
|
||||||
wl_surface_commit(win->wl_surface);
|
wl_surface_commit(win->wl_surface);
|
||||||
|
|
||||||
struct window_draw_info* draw_info = &win->draw_info;
|
struct window_draw_info *draw_info = &win->draw_info;
|
||||||
|
|
||||||
/* Инициализация состояния */
|
/* Инициализация состояния */
|
||||||
win->id = id++;
|
win->id = id++;
|
||||||
@@ -217,9 +245,15 @@ int window_init(struct wl_display *display, struct wl_event_queue *queue, struct
|
|||||||
win->buffer = NULL;
|
win->buffer = NULL;
|
||||||
win->frame_callback = NULL;
|
win->frame_callback = NULL;
|
||||||
win->need_close = 0;
|
win->need_close = 0;
|
||||||
draw_info->color = 0;
|
/* Мьютекс нужен для атомарного обращения к структуре фигуры */
|
||||||
|
if (pthread_mutex_init(&win->draw_info.figure_mutex, NULL) != 0)
|
||||||
|
{
|
||||||
|
/* if mutex init failed — cleanup and return error */
|
||||||
|
window_destroy(win);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
xdg_toplevel_set_app_id(win->xdg_toplevel, "my-wayland-window");
|
xdg_toplevel_set_app_id(win->xdg_toplevel, "my-wayland-window");
|
||||||
xdg_toplevel_set_title(win->xdg_toplevel, "Custom Title");
|
xdg_toplevel_set_title(win->xdg_toplevel, "Custom Title");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -243,4 +277,6 @@ void window_destroy(struct wayland_window *win)
|
|||||||
wl_surface_destroy(win->wl_surface);
|
wl_surface_destroy(win->wl_surface);
|
||||||
if (win->draw_info.data)
|
if (win->draw_info.data)
|
||||||
munmap(win->draw_info.data, win->draw_info.width * win->draw_info.height * 4);
|
munmap(win->draw_info.data, win->draw_info.width * win->draw_info.height * 4);
|
||||||
|
/* destroy mutex if initialized */
|
||||||
|
pthread_mutex_destroy(&win->draw_info.figure_mutex);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user