Display grid lines when moving a display
This commit is contained in:
parent
e0f382af84
commit
d9b868077a
90
src/main.c
90
src/main.c
@ -154,7 +154,7 @@ static gboolean send_apply(gpointer data) {
|
|||||||
GdkDisplay *display = gdk_window_get_display(window);
|
GdkDisplay *display = gdk_window_get_display(window);
|
||||||
struct wl_display *wl_display = gdk_wayland_display_get_wl_display(display);
|
struct wl_display *wl_display = gdk_wayland_display_get_wl_display(display);
|
||||||
wd_apply_state(state, outputs, wl_display);
|
wd_apply_state(state, outputs, wl_display);
|
||||||
state->apply_pending = false;
|
state->apply_pending = FALSE;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ static void apply_state(struct wd_state *state) {
|
|||||||
|
|
||||||
/* queue this once per iteration in order to prevent duplicate updates */
|
/* queue this once per iteration in order to prevent duplicate updates */
|
||||||
if (!state->apply_pending) {
|
if (!state->apply_pending) {
|
||||||
state->apply_pending = true;
|
state->apply_pending = TRUE;
|
||||||
g_idle_add(send_apply, state);
|
g_idle_add(send_apply, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,11 +257,12 @@ static void cache_scroll(struct wd_state *state) {
|
|||||||
static gboolean redraw_canvas(GtkWidget *widget, GdkFrameClock *frame_clock, gpointer data);
|
static gboolean redraw_canvas(GtkWidget *widget, GdkFrameClock *frame_clock, gpointer data);
|
||||||
|
|
||||||
static void update_tick_callback(struct wd_state *state) {
|
static void update_tick_callback(struct wd_state *state) {
|
||||||
bool any_animate = false;
|
bool any_animate = FALSE;
|
||||||
struct wd_render_head_data *render;
|
struct wd_render_head_data *render;
|
||||||
wl_list_for_each(render, &state->render.heads, link) {
|
wl_list_for_each(render, &state->render.heads, link) {
|
||||||
if (state->render.updated_at < render->transition_begin + HOVER_USECS) {
|
if (state->render.updated_at < render->hover_begin + HOVER_USECS
|
||||||
any_animate = true;
|
|| state->render.updated_at < render->click_begin + HOVER_USECS) {
|
||||||
|
any_animate = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,12 +280,12 @@ static void update_tick_callback(struct wd_state *state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void update_cursor(struct wd_state *state) {
|
static void update_cursor(struct wd_state *state) {
|
||||||
bool any_hovered = false;
|
bool any_hovered = FALSE;
|
||||||
struct wd_head *head;
|
struct wd_head *head;
|
||||||
wl_list_for_each(head, &state->heads, link) {
|
wl_list_for_each(head, &state->heads, link) {
|
||||||
struct wd_render_head_data *render = head->render;
|
struct wd_render_head_data *render = head->render;
|
||||||
if (render != NULL && render->hovered) {
|
if (render != NULL && render->hovered) {
|
||||||
any_hovered = true;
|
any_hovered = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -300,6 +301,15 @@ static void update_cursor(struct wd_state *state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void flip_anim(uint64_t *timer, uint64_t tick) {
|
||||||
|
uint64_t animate_end = *timer + HOVER_USECS;
|
||||||
|
if (tick < animate_end) {
|
||||||
|
*timer = tick - (animate_end - tick);
|
||||||
|
} else {
|
||||||
|
*timer = tick;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void update_hovered(struct wd_state *state) {
|
static void update_hovered(struct wd_state *state) {
|
||||||
GdkDisplay *display = gdk_display_get_default();
|
GdkDisplay *display = gdk_display_get_default();
|
||||||
GdkWindow *window = gtk_widget_get_window(state->canvas);
|
GdkWindow *window = gtk_widget_get_window(state->canvas);
|
||||||
@ -309,17 +319,17 @@ static void update_hovered(struct wd_state *state) {
|
|||||||
GdkFrameClock *clock = gtk_widget_get_frame_clock(state->canvas);
|
GdkFrameClock *clock = gtk_widget_get_frame_clock(state->canvas);
|
||||||
uint64_t tick = gdk_frame_clock_get_frame_time(clock);
|
uint64_t tick = gdk_frame_clock_get_frame_time(clock);
|
||||||
g_autoptr(GList) seats = gdk_display_list_seats(display);
|
g_autoptr(GList) seats = gdk_display_list_seats(display);
|
||||||
bool any_hovered = false;
|
bool any_hovered = FALSE;
|
||||||
struct wd_render_head_data *render;
|
struct wd_render_head_data *render;
|
||||||
wl_list_for_each(render, &state->render.heads, link) {
|
wl_list_for_each(render, &state->render.heads, link) {
|
||||||
bool init_hovered = render->hovered;
|
bool init_hovered = render->hovered;
|
||||||
render->hovered = false;
|
render->hovered = FALSE;
|
||||||
if (any_hovered) {
|
if (any_hovered) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (state->clicked == render) {
|
if (state->clicked == render) {
|
||||||
render->hovered = true;
|
render->hovered = TRUE;
|
||||||
any_hovered = true;
|
any_hovered = TRUE;
|
||||||
} else if (state->clicked == NULL) {
|
} else if (state->clicked == NULL) {
|
||||||
for (GList *iter = seats; iter != NULL; iter = iter->next) {
|
for (GList *iter = seats; iter != NULL; iter = iter->next) {
|
||||||
double mouse_x;
|
double mouse_x;
|
||||||
@ -329,14 +339,14 @@ static void update_hovered(struct wd_state *state) {
|
|||||||
gdk_window_get_device_position_double(window, pointer, &mouse_x, &mouse_y, NULL);
|
gdk_window_get_device_position_double(window, pointer, &mouse_x, &mouse_y, NULL);
|
||||||
if (mouse_x >= render->x1 && mouse_x < render->x2 &&
|
if (mouse_x >= render->x1 && mouse_x < render->x2 &&
|
||||||
mouse_y >= render->y1 && mouse_y < render->y2) {
|
mouse_y >= render->y1 && mouse_y < render->y2) {
|
||||||
render->hovered = true;
|
render->hovered = TRUE;
|
||||||
any_hovered = true;
|
any_hovered = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (init_hovered != render->hovered) {
|
if (init_hovered != render->hovered) {
|
||||||
render->transition_begin = tick;
|
flip_anim(&render->hover_begin, tick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update_cursor(state);
|
update_cursor(state);
|
||||||
@ -812,11 +822,6 @@ static cairo_surface_t *draw_head(PangoContext *pango,
|
|||||||
cairo_set_source_color(cr, info->border_color);
|
cairo_set_source_color(cr, info->border_color);
|
||||||
cairo_fill(cr);
|
cairo_fill(cr);
|
||||||
|
|
||||||
cairo_set_line_width(cr, 1.);
|
|
||||||
cairo_rectangle(cr, 0, 0, width, height);
|
|
||||||
cairo_set_source_color(cr, info->fg_color);
|
|
||||||
cairo_stroke(cr);
|
|
||||||
|
|
||||||
PangoLayout *layout = pango_layout_new(pango);
|
PangoLayout *layout = pango_layout_new(pango);
|
||||||
pango_layout_set_text(layout, name, -1);
|
pango_layout_set_text(layout, name, -1);
|
||||||
int text_width = pango_units_from_double(width - TEXT_MARGIN * 2);
|
int text_width = pango_units_from_double(width - TEXT_MARGIN * 2);
|
||||||
@ -862,7 +867,7 @@ static void canvas_render(GtkGLArea *area, GdkGLContext *context, gpointer data)
|
|||||||
render->tex_width = frame->width;
|
render->tex_width = frame->width;
|
||||||
render->tex_height = frame->height;
|
render->tex_height = frame->height;
|
||||||
render->pixels = frame->pixels;
|
render->pixels = frame->pixels;
|
||||||
render->preview = true;
|
render->preview = TRUE;
|
||||||
render->updated_at = tick;
|
render->updated_at = tick;
|
||||||
render->y_invert = frame->y_invert;
|
render->y_invert = frame->y_invert;
|
||||||
render->swap_rgb = frame->swap_rgb;
|
render->swap_rgb = frame->swap_rgb;
|
||||||
@ -875,7 +880,7 @@ static void canvas_render(GtkGLArea *area, GdkGLContext *context, gpointer data)
|
|||||||
|| render->pixels == NULL || size_changed(render)) {
|
|| render->pixels == NULL || size_changed(render)) {
|
||||||
render->tex_width = render->x2 - render->x1;
|
render->tex_width = render->x2 - render->x1;
|
||||||
render->tex_height = render->y2 - render->y1;
|
render->tex_height = render->y2 - render->y1;
|
||||||
render->preview = false;
|
render->preview = FALSE;
|
||||||
if (head->surface != NULL) {
|
if (head->surface != NULL) {
|
||||||
cairo_surface_destroy(head->surface);
|
cairo_surface_destroy(head->surface);
|
||||||
}
|
}
|
||||||
@ -885,9 +890,9 @@ static void canvas_render(GtkGLArea *area, GdkGLContext *context, gpointer data)
|
|||||||
render->tex_stride = cairo_image_surface_get_stride(head->surface);
|
render->tex_stride = cairo_image_surface_get_stride(head->surface);
|
||||||
render->updated_at = tick;
|
render->updated_at = tick;
|
||||||
render->active.rotation = 0;
|
render->active.rotation = 0;
|
||||||
render->active.x_invert = false;
|
render->active.x_invert = FALSE;
|
||||||
render->y_invert = false;
|
render->y_invert = FALSE;
|
||||||
render->swap_rgb = false;
|
render->swap_rgb = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -911,6 +916,23 @@ static void canvas_unrealize(GtkWidget *widget, gpointer data) {
|
|||||||
state->gl_data = NULL;
|
state->gl_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_clicked_head(struct wd_state *state,
|
||||||
|
struct wd_render_head_data *clicked) {
|
||||||
|
GdkFrameClock *clock = gtk_widget_get_frame_clock(state->canvas);
|
||||||
|
uint64_t tick = gdk_frame_clock_get_frame_time(clock);
|
||||||
|
if (clicked != state->clicked) {
|
||||||
|
if (state->clicked != NULL) {
|
||||||
|
state->clicked->clicked = FALSE;
|
||||||
|
flip_anim(&state->clicked->click_begin, tick);
|
||||||
|
}
|
||||||
|
if (clicked != NULL) {
|
||||||
|
clicked->clicked = TRUE;
|
||||||
|
flip_anim(&clicked->click_begin, tick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state->clicked = clicked;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean canvas_click(GtkWidget *widget, GdkEvent *event,
|
static gboolean canvas_click(GtkWidget *widget, GdkEvent *event,
|
||||||
gpointer data) {
|
gpointer data) {
|
||||||
struct wd_state *state = data;
|
struct wd_state *state = data;
|
||||||
@ -923,7 +945,7 @@ static gboolean canvas_click(GtkWidget *widget, GdkEvent *event,
|
|||||||
double mouse_y = event->button.y;
|
double mouse_y = event->button.y;
|
||||||
if (mouse_x >= render->x1 && mouse_x < render->x2 &&
|
if (mouse_x >= render->x1 && mouse_x < render->x2 &&
|
||||||
mouse_y >= render->y1 && mouse_y < render->y2) {
|
mouse_y >= render->y1 && mouse_y < render->y2) {
|
||||||
state->clicked = render;
|
set_clicked_head(state, render);
|
||||||
state->click_offset.x = event->button.x - render->x1;
|
state->click_offset.x = event->button.x - render->x1;
|
||||||
state->click_offset.y = event->button.y - render->y1;
|
state->click_offset.y = event->button.y - render->y1;
|
||||||
break;
|
break;
|
||||||
@ -936,7 +958,7 @@ static gboolean canvas_click(GtkWidget *widget, GdkEvent *event,
|
|||||||
struct wd_render_head_data *render;
|
struct wd_render_head_data *render;
|
||||||
wl_list_for_each(render, &state->render.heads, link) {
|
wl_list_for_each(render, &state->render.heads, link) {
|
||||||
render->updated_at = 0;
|
render->updated_at = 0;
|
||||||
render->preview = true;
|
render->preview = TRUE;
|
||||||
}
|
}
|
||||||
gtk_gl_area_queue_render(GTK_GL_AREA(state->canvas));
|
gtk_gl_area_queue_render(GTK_GL_AREA(state->canvas));
|
||||||
g_autoptr(GList) forms = gtk_container_get_children(GTK_CONTAINER(state->stack));
|
g_autoptr(GList) forms = gtk_container_get_children(GTK_CONTAINER(state->stack));
|
||||||
@ -949,7 +971,7 @@ static gboolean canvas_click(GtkWidget *widget, GdkEvent *event,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (event->button.button == 2) {
|
} else if (event->button.button == 2) {
|
||||||
state->panning = true;
|
state->panning = TRUE;
|
||||||
state->pan_last.x = event->button.x;
|
state->pan_last.x = event->button.x;
|
||||||
state->pan_last.y = event->button.y;
|
state->pan_last.y = event->button.y;
|
||||||
}
|
}
|
||||||
@ -961,10 +983,10 @@ static gboolean canvas_release(GtkWidget *widget, GdkEvent *event,
|
|||||||
gpointer data) {
|
gpointer data) {
|
||||||
struct wd_state *state = data;
|
struct wd_state *state = data;
|
||||||
if (event->button.button == 1) {
|
if (event->button.button == 1) {
|
||||||
state->clicked = NULL;
|
set_clicked_head(state, NULL);
|
||||||
}
|
}
|
||||||
if (event->button.button == 2) {
|
if (event->button.button == 2) {
|
||||||
state->panning = false;
|
state->panning = FALSE;
|
||||||
}
|
}
|
||||||
update_cursor(state);
|
update_cursor(state);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -1084,10 +1106,10 @@ static gboolean canvas_enter(GtkWidget *widget, GdkEvent *event,
|
|||||||
gpointer data) {
|
gpointer data) {
|
||||||
struct wd_state *state = data;
|
struct wd_state *state = data;
|
||||||
if (!(event->crossing.state & GDK_BUTTON1_MASK)) {
|
if (!(event->crossing.state & GDK_BUTTON1_MASK)) {
|
||||||
state->clicked = NULL;
|
set_clicked_head(state, NULL);
|
||||||
}
|
}
|
||||||
if (!(event->crossing.state & GDK_BUTTON2_MASK)) {
|
if (!(event->crossing.state & GDK_BUTTON2_MASK)) {
|
||||||
state->panning = false;
|
state->panning = FALSE;
|
||||||
}
|
}
|
||||||
update_cursor(state);
|
update_cursor(state);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -1098,7 +1120,7 @@ static gboolean canvas_leave(GtkWidget *widget, GdkEvent *event,
|
|||||||
struct wd_state *state = data;
|
struct wd_state *state = data;
|
||||||
struct wd_render_head_data *render;
|
struct wd_render_head_data *render;
|
||||||
wl_list_for_each(render, &state->render.heads, link) {
|
wl_list_for_each(render, &state->render.heads, link) {
|
||||||
render->hovered = false;
|
render->hovered = FALSE;
|
||||||
}
|
}
|
||||||
update_tick_callback(state);
|
update_tick_callback(state);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -1321,12 +1343,12 @@ static void activate(GtkApplication* app, gpointer user_data) {
|
|||||||
wd_fatal_error(1, "Compositor doesn't support xdg-output-unstable-v1");
|
wd_fatal_error(1, "Compositor doesn't support xdg-output-unstable-v1");
|
||||||
}
|
}
|
||||||
if (state->copy_manager == NULL) {
|
if (state->copy_manager == NULL) {
|
||||||
state->capture = false;
|
state->capture = FALSE;
|
||||||
g_simple_action_set_state(capture_action, g_variant_new_boolean(state->capture));
|
g_simple_action_set_state(capture_action, g_variant_new_boolean(state->capture));
|
||||||
g_simple_action_set_enabled(capture_action, FALSE);
|
g_simple_action_set_enabled(capture_action, FALSE);
|
||||||
}
|
}
|
||||||
if (state->layer_shell == NULL) {
|
if (state->layer_shell == NULL) {
|
||||||
state->show_overlay = false;
|
state->show_overlay = FALSE;
|
||||||
g_simple_action_set_state(overlay_action, g_variant_new_boolean(state->show_overlay));
|
g_simple_action_set_state(overlay_action, g_variant_new_boolean(state->show_overlay));
|
||||||
g_simple_action_set_enabled(overlay_action, FALSE);
|
g_simple_action_set_enabled(overlay_action, FALSE);
|
||||||
}
|
}
|
||||||
|
240
src/render.c
240
src/render.c
@ -37,6 +37,18 @@
|
|||||||
#define BT_COLOR_QUAD_SIZE (6 * BT_COLOR_VERT_SIZE)
|
#define BT_COLOR_QUAD_SIZE (6 * BT_COLOR_VERT_SIZE)
|
||||||
#define BT_COLOR_MAX (BT_COLOR_QUAD_SIZE * HEADS_MAX)
|
#define BT_COLOR_MAX (BT_COLOR_QUAD_SIZE * HEADS_MAX)
|
||||||
|
|
||||||
|
#define BT_LINE_VERT_SIZE (2 + 4)
|
||||||
|
#define BT_LINE_QUAD_SIZE (8 * BT_LINE_VERT_SIZE)
|
||||||
|
#define BT_LINE_EXT_SIZE (24 * BT_LINE_VERT_SIZE)
|
||||||
|
#define BT_LINE_MAX (BT_LINE_EXT_SIZE * (HEADS_MAX + 1))
|
||||||
|
|
||||||
|
enum gl_buffers {
|
||||||
|
TEXTURE_BUFFER,
|
||||||
|
COLOR_BUFFER,
|
||||||
|
LINE_BUFFER,
|
||||||
|
NUM_BUFFERS
|
||||||
|
};
|
||||||
|
|
||||||
struct wd_gl_data {
|
struct wd_gl_data {
|
||||||
GLuint color_program;
|
GLuint color_program;
|
||||||
GLuint color_vertex_shader;
|
GLuint color_vertex_shader;
|
||||||
@ -54,12 +66,12 @@ struct wd_gl_data {
|
|||||||
GLuint texture_texture_uniform;
|
GLuint texture_texture_uniform;
|
||||||
GLuint texture_color_transform_uniform;
|
GLuint texture_color_transform_uniform;
|
||||||
|
|
||||||
GLuint buffers[2];
|
GLuint buffers[NUM_BUFFERS];
|
||||||
|
|
||||||
unsigned texture_count;
|
unsigned texture_count;
|
||||||
GLuint textures[HEADS_MAX];
|
GLuint textures[HEADS_MAX];
|
||||||
|
|
||||||
float tris[BT_COLOR_MAX];
|
float verts[BT_LINE_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *color_vertex_shader_src = "\
|
static const char *color_vertex_shader_src = "\
|
||||||
@ -186,15 +198,19 @@ struct wd_gl_data *wd_gl_setup(void) {
|
|||||||
res->texture_color_transform_uniform = glGetUniformLocation(
|
res->texture_color_transform_uniform = glGetUniformLocation(
|
||||||
res->texture_program, "color_transform");
|
res->texture_program, "color_transform");
|
||||||
|
|
||||||
glGenBuffers(2, res->buffers);
|
glGenBuffers(NUM_BUFFERS, res->buffers);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[0]);
|
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[TEXTURE_BUFFER]);
|
||||||
glBufferData(GL_ARRAY_BUFFER, BT_UV_MAX * sizeof(float),
|
glBufferData(GL_ARRAY_BUFFER, BT_UV_MAX * sizeof(float),
|
||||||
NULL, GL_DYNAMIC_DRAW);
|
NULL, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[1]);
|
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[COLOR_BUFFER]);
|
||||||
glBufferData(GL_ARRAY_BUFFER, BT_COLOR_MAX * sizeof(float),
|
glBufferData(GL_ARRAY_BUFFER, BT_COLOR_MAX * sizeof(float),
|
||||||
NULL, GL_DYNAMIC_DRAW);
|
NULL, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[LINE_BUFFER]);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, BT_LINE_MAX * sizeof(float),
|
||||||
|
NULL, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,27 +226,50 @@ static const GLfloat TRANSFORM_BGR[16] = {
|
|||||||
1, 0, 0, 0,
|
1, 0, 0, 0,
|
||||||
0, 0, 0, 1};
|
0, 0, 0, 1};
|
||||||
|
|
||||||
#define PUSH_POINT(_start, _a, _b) \
|
#define PUSH_POINT_COLOR(_start, _a, _b, _color, _alpha) \
|
||||||
*((_start)++) = (_a);\
|
*((_start)++) = (_a);\
|
||||||
*((_start)++) = (_b);
|
*((_start)++) = (_b);\
|
||||||
|
*((_start)++) = ((_color)[0]);\
|
||||||
|
*((_start)++) = ((_color)[1]);\
|
||||||
|
*((_start)++) = ((_color)[2]);\
|
||||||
|
*((_start)++) = (_alpha);
|
||||||
|
|
||||||
#define PUSH_COLOR(_start, _a, _b, _c, _d) \
|
#define PUSH_POINT_UV(_start, _a, _b, _c, _d) \
|
||||||
*((_start)++) = (_a);\
|
*((_start)++) = (_a);\
|
||||||
*((_start)++) = (_b);\
|
*((_start)++) = (_b);\
|
||||||
*((_start)++) = (_c);\
|
*((_start)++) = (_c);\
|
||||||
*((_start)++) = (_d);
|
*((_start)++) = (_d);
|
||||||
|
|
||||||
#define PUSH_POINT_UV(_start, _a, _b, _c, _d) \
|
static inline float lerp(float x, float y, float a) {
|
||||||
PUSH_COLOR(_start, _a, _b, _c, _d)
|
return x * (1.f - a) + y * a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void lerp_color(float out[3], float x[3], float y[3], float a) {
|
||||||
|
out[0] = lerp(x[0], y[0], a);
|
||||||
|
out[1] = lerp(x[1], y[1], a);
|
||||||
|
out[2] = lerp(x[2], y[2], a);
|
||||||
|
out[3] = lerp(x[3], y[3], a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float ease(float d) {
|
||||||
|
d *= 2.f;
|
||||||
|
if (d <= 1.f) {
|
||||||
|
d = d * d;
|
||||||
|
} else {
|
||||||
|
d -= 1.f;
|
||||||
|
d = d * (2.f - d) + 1.f;
|
||||||
|
}
|
||||||
|
d /= 2.f;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
||||||
uint64_t tick) {
|
uint64_t tick) {
|
||||||
unsigned int tris = 0;
|
unsigned int tri_verts = 0;
|
||||||
|
|
||||||
unsigned int head_count = wl_list_length(&info->heads);
|
unsigned int head_count = wl_list_length(&info->heads);
|
||||||
if (head_count >= HEADS_MAX) {
|
if (head_count >= HEADS_MAX)
|
||||||
head_count = HEADS_MAX;
|
head_count = HEADS_MAX;
|
||||||
}
|
|
||||||
|
|
||||||
if (head_count > res->texture_count) {
|
if (head_count > res->texture_count) {
|
||||||
glGenTextures(head_count - res->texture_count,
|
glGenTextures(head_count - res->texture_count,
|
||||||
@ -250,7 +289,7 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
|||||||
struct wd_render_head_data *head;
|
struct wd_render_head_data *head;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
wl_list_for_each_reverse(head, &info->heads, link) {
|
wl_list_for_each_reverse(head, &info->heads, link) {
|
||||||
float *tri_ptr = res->tris + i * BT_UV_QUAD_SIZE;
|
float *tri_ptr = res->verts + i * BT_UV_QUAD_SIZE;
|
||||||
float x1 = head->active.x_invert ? head->x2 : head->x1;
|
float x1 = head->active.x_invert ? head->x2 : head->x1;
|
||||||
float y1 = head->y_invert ? head->y2 : head->y1;
|
float y1 = head->y_invert ? head->y2 : head->y1;
|
||||||
float x2 = head->active.x_invert ? head->x1 : head->x2;
|
float x2 = head->active.x_invert ? head->x1 : head->x2;
|
||||||
@ -285,11 +324,10 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
|||||||
PUSH_POINT_UV(tri_ptr, x2, y1, sb, tb)
|
PUSH_POINT_UV(tri_ptr, x2, y1, sb, tb)
|
||||||
PUSH_POINT_UV(tri_ptr, x2, y2, sc, tc)
|
PUSH_POINT_UV(tri_ptr, x2, y2, sc, tc)
|
||||||
|
|
||||||
tris += 6;
|
tri_verts += 6;
|
||||||
i++;
|
i++;
|
||||||
if (i >= HEADS_MAX) {
|
if (i >= HEADS_MAX)
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glClearColor(info->bg_color[0], info->bg_color[1], info->bg_color[2], 1.f);
|
glClearColor(info->bg_color[0], info->bg_color[1], info->bg_color[2], 1.f);
|
||||||
@ -297,11 +335,11 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
|||||||
|
|
||||||
float screen_size[2] = { info->viewport_width, info->viewport_height };
|
float screen_size[2] = { info->viewport_width, info->viewport_height };
|
||||||
|
|
||||||
if (tris > 0) {
|
if (tri_verts > 0) {
|
||||||
glUseProgram(res->texture_program);
|
glUseProgram(res->texture_program);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[0]);
|
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[TEXTURE_BUFFER]);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0,
|
glBufferSubData(GL_ARRAY_BUFFER, 0,
|
||||||
tris * BT_UV_VERT_SIZE * sizeof(float), res->tris);
|
tri_verts * BT_UV_VERT_SIZE * sizeof(float), res->verts);
|
||||||
glEnableVertexAttribArray(res->texture_position_attribute);
|
glEnableVertexAttribArray(res->texture_position_attribute);
|
||||||
glEnableVertexAttribArray(res->texture_uv_attribute);
|
glEnableVertexAttribArray(res->texture_uv_attribute);
|
||||||
glVertexAttribPointer(res->texture_position_attribute,
|
glVertexAttribPointer(res->texture_position_attribute,
|
||||||
@ -328,19 +366,23 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
|||||||
head->swap_rgb ? TRANSFORM_RGB : TRANSFORM_BGR);
|
head->swap_rgb ? TRANSFORM_RGB : TRANSFORM_BGR);
|
||||||
glDrawArrays(GL_TRIANGLES, i * 6, 6);
|
glDrawArrays(GL_TRIANGLES, i * 6, 6);
|
||||||
i++;
|
i++;
|
||||||
if (i >= HEADS_MAX) {
|
if (i >= HEADS_MAX)
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tris = 0;
|
tri_verts = 0;
|
||||||
|
|
||||||
int j = 0;
|
int j = 0;
|
||||||
i = 0;
|
i = 0;
|
||||||
|
bool any_clicked = false;
|
||||||
|
uint64_t click_begin = 0;
|
||||||
wl_list_for_each_reverse(head, &info->heads, link) {
|
wl_list_for_each_reverse(head, &info->heads, link) {
|
||||||
if (head->hovered || tick < head->transition_begin + HOVER_USECS) {
|
any_clicked = head->clicked || any_clicked;
|
||||||
float *tri_ptr = res->tris + j++ * BT_COLOR_QUAD_SIZE;
|
if (head->click_begin > click_begin)
|
||||||
|
click_begin = head->click_begin;
|
||||||
|
if (head->hovered || tick < head->hover_begin + HOVER_USECS) {
|
||||||
|
float *tri_ptr = res->verts + j++ * BT_COLOR_QUAD_SIZE;
|
||||||
float x1 = head->x1;
|
float x1 = head->x1;
|
||||||
float y1 = head->y1;
|
float y1 = head->y1;
|
||||||
float x2 = head->x2;
|
float x2 = head->x2;
|
||||||
@ -348,48 +390,32 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
|||||||
|
|
||||||
float *color = info->selection_color;
|
float *color = info->selection_color;
|
||||||
float d = fminf(
|
float d = fminf(
|
||||||
(tick - head->transition_begin) / (double) HOVER_USECS, 1.f);
|
(tick - head->hover_begin) / (double) HOVER_USECS, 1.f);
|
||||||
if (!head->hovered) {
|
if (!head->hovered)
|
||||||
d = 1.f - d;
|
d = 1.f - d;
|
||||||
}
|
float alpha = color[3] * ease(d) * .5f;
|
||||||
d *= 2.f;
|
|
||||||
if (d <= 1.f) {
|
|
||||||
d = d * d;
|
|
||||||
} else {
|
|
||||||
d -= 1.f;
|
|
||||||
d = d * (2.f - d) + 1.f;
|
|
||||||
}
|
|
||||||
d /= 2.f;
|
|
||||||
float alpha = color[3] * d * .5f;
|
|
||||||
|
|
||||||
PUSH_POINT(tri_ptr, x1, y1)
|
PUSH_POINT_COLOR(tri_ptr, x1, y1, color, alpha)
|
||||||
PUSH_COLOR(tri_ptr, color[0], color[1], color[2], alpha)
|
PUSH_POINT_COLOR(tri_ptr, x2, y1, color, alpha)
|
||||||
PUSH_POINT(tri_ptr, x2, y1)
|
PUSH_POINT_COLOR(tri_ptr, x1, y2, color, alpha)
|
||||||
PUSH_COLOR(tri_ptr, color[0], color[1], color[2], alpha)
|
PUSH_POINT_COLOR(tri_ptr, x1, y2, color, alpha)
|
||||||
PUSH_POINT(tri_ptr, x1, y2)
|
PUSH_POINT_COLOR(tri_ptr, x2, y1, color, alpha)
|
||||||
PUSH_COLOR(tri_ptr, color[0], color[1], color[2], alpha)
|
PUSH_POINT_COLOR(tri_ptr, x2, y2, color, alpha)
|
||||||
PUSH_POINT(tri_ptr, x1, y2)
|
|
||||||
PUSH_COLOR(tri_ptr, color[0], color[1], color[2], alpha)
|
|
||||||
PUSH_POINT(tri_ptr, x2, y1)
|
|
||||||
PUSH_COLOR(tri_ptr, color[0], color[1], color[2], alpha)
|
|
||||||
PUSH_POINT(tri_ptr, x2, y2)
|
|
||||||
PUSH_COLOR(tri_ptr, color[0], color[1], color[2], alpha)
|
|
||||||
|
|
||||||
tris += 6;
|
tri_verts += 6;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
if (i >= HEADS_MAX) {
|
if (i >= HEADS_MAX)
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tris > 0) {
|
if (tri_verts > 0) {
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glUseProgram(res->color_program);
|
glUseProgram(res->color_program);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[1]);
|
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[COLOR_BUFFER]);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0,
|
glBufferSubData(GL_ARRAY_BUFFER, 0,
|
||||||
tris * BT_COLOR_VERT_SIZE * sizeof(float), res->tris);
|
tri_verts * BT_COLOR_VERT_SIZE * sizeof(float), res->verts);
|
||||||
glEnableVertexAttribArray(res->color_position_attribute);
|
glEnableVertexAttribArray(res->color_position_attribute);
|
||||||
glEnableVertexAttribArray(res->color_color_attribute);
|
glEnableVertexAttribArray(res->color_color_attribute);
|
||||||
glVertexAttribPointer(res->color_position_attribute, 2, GL_FLOAT, GL_FALSE,
|
glVertexAttribPointer(res->color_position_attribute, 2, GL_FLOAT, GL_FALSE,
|
||||||
@ -397,13 +423,113 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
|||||||
glVertexAttribPointer(res->color_color_attribute, 4, GL_FLOAT, GL_FALSE,
|
glVertexAttribPointer(res->color_color_attribute, 4, GL_FLOAT, GL_FALSE,
|
||||||
BT_COLOR_VERT_SIZE * sizeof(float), (void *) (2 * sizeof(float)));
|
BT_COLOR_VERT_SIZE * sizeof(float), (void *) (2 * sizeof(float)));
|
||||||
glUniform2fv(res->color_screen_size_uniform, 1, screen_size);
|
glUniform2fv(res->color_screen_size_uniform, 1, screen_size);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, tris);
|
glDrawArrays(GL_TRIANGLES, 0, tri_verts);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int line_verts = 0;
|
||||||
|
i = 0;
|
||||||
|
float *line_ptr = res->verts;
|
||||||
|
if (any_clicked || (click_begin && tick < click_begin + HOVER_USECS)) {
|
||||||
|
const float ox = -info->scroll_x - info->x_origin;
|
||||||
|
const float oy = -info->scroll_y - info->y_origin;
|
||||||
|
const float sx = screen_size[0];
|
||||||
|
const float sy = screen_size[1];
|
||||||
|
|
||||||
|
float color[4];
|
||||||
|
lerp_color(color, info->selection_color, info->fg_color, .5f);
|
||||||
|
float d = fminf(
|
||||||
|
(tick - click_begin) / (double) HOVER_USECS, 1.f);
|
||||||
|
if (!any_clicked)
|
||||||
|
d = 1.f - d;
|
||||||
|
float alpha = color[3] * ease(d) * .5f;
|
||||||
|
|
||||||
|
PUSH_POINT_COLOR(line_ptr, ox, oy, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, sx, oy, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, ox, oy, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, ox, sy, color, alpha)
|
||||||
|
|
||||||
|
line_verts += 4;
|
||||||
|
}
|
||||||
|
wl_list_for_each(head, &info->heads, link) {
|
||||||
|
float x1 = head->x1;
|
||||||
|
float y1 = head->y1;
|
||||||
|
float x2 = head->x2;
|
||||||
|
float y2 = head->y2;
|
||||||
|
|
||||||
|
float *color = info->fg_color;
|
||||||
|
float alpha = color[3] * (head->clicked ? .5f : .25f);
|
||||||
|
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x1, y1, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x2, y1, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x2, y1, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x2, y2, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x2, y2, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x1, y2, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x1, y2, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x1, y1, color, alpha)
|
||||||
|
|
||||||
|
line_verts += 8;
|
||||||
|
|
||||||
|
if (any_clicked || (click_begin && tick < click_begin + HOVER_USECS)) {
|
||||||
|
float d = fminf(
|
||||||
|
(tick - click_begin) / (double) HOVER_USECS, 1.f);
|
||||||
|
if (!any_clicked)
|
||||||
|
d = 1.f - d;
|
||||||
|
alpha = color[3] * ease(d) * (head->clicked ? .15f : .075f);
|
||||||
|
|
||||||
|
const float sx = screen_size[0];
|
||||||
|
const float sy = screen_size[1];
|
||||||
|
|
||||||
|
PUSH_POINT_COLOR(line_ptr, 0, y1, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x1, y1, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x1, 0, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x1, y1, color, alpha)
|
||||||
|
|
||||||
|
PUSH_POINT_COLOR(line_ptr, sx, y1, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x2, y1, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x2, 0, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x2, y1, color, alpha)
|
||||||
|
|
||||||
|
PUSH_POINT_COLOR(line_ptr, sx, y2, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x2, y2, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x2, sy, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x2, y2, color, alpha)
|
||||||
|
|
||||||
|
PUSH_POINT_COLOR(line_ptr, 0, y2, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x1, y2, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x1, sy, color, alpha)
|
||||||
|
PUSH_POINT_COLOR(line_ptr, x1, y2, color, alpha)
|
||||||
|
|
||||||
|
line_verts += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
if (i >= HEADS_MAX)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line_verts > 0) {
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glUseProgram(res->color_program);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[LINE_BUFFER]);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0,
|
||||||
|
line_verts * BT_LINE_VERT_SIZE * sizeof(float), res->verts);
|
||||||
|
glEnableVertexAttribArray(res->color_position_attribute);
|
||||||
|
glEnableVertexAttribArray(res->color_color_attribute);
|
||||||
|
glVertexAttribPointer(res->color_position_attribute, 2, GL_FLOAT, GL_FALSE,
|
||||||
|
BT_LINE_VERT_SIZE * sizeof(float), (void *) (0 * sizeof(float)));
|
||||||
|
glVertexAttribPointer(res->color_color_attribute, 4, GL_FLOAT, GL_FALSE,
|
||||||
|
BT_LINE_VERT_SIZE * sizeof(float), (void *) (2 * sizeof(float)));
|
||||||
|
glUniform2fv(res->color_screen_size_uniform, 1, screen_size);
|
||||||
|
glDrawArrays(GL_LINES, 0, line_verts);
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wd_gl_cleanup(struct wd_gl_data *res) {
|
void wd_gl_cleanup(struct wd_gl_data *res) {
|
||||||
glDeleteBuffers(2, res->buffers);
|
glDeleteBuffers(NUM_BUFFERS, res->buffers);
|
||||||
glDeleteShader(res->texture_fragment_shader);
|
glDeleteShader(res->texture_fragment_shader);
|
||||||
glDeleteShader(res->texture_vertex_shader);
|
glDeleteShader(res->texture_vertex_shader);
|
||||||
glDeleteProgram(res->texture_program);
|
glDeleteProgram(res->texture_program);
|
||||||
|
@ -156,7 +156,8 @@ struct wd_render_head_flags {
|
|||||||
struct wd_render_head_data {
|
struct wd_render_head_data {
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
uint64_t updated_at;
|
uint64_t updated_at;
|
||||||
uint64_t transition_begin;
|
uint64_t hover_begin;
|
||||||
|
uint64_t click_begin;
|
||||||
|
|
||||||
float x1;
|
float x1;
|
||||||
float y1;
|
float y1;
|
||||||
@ -175,6 +176,7 @@ struct wd_render_head_data {
|
|||||||
bool y_invert;
|
bool y_invert;
|
||||||
bool swap_rgb;
|
bool swap_rgb;
|
||||||
bool hovered;
|
bool hovered;
|
||||||
|
bool clicked;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wd_render_data {
|
struct wd_render_data {
|
||||||
|
Loading…
Reference in New Issue
Block a user