From bd8fc3f7d436721ef6d6a518a3b9d65d4abe4390 Mon Sep 17 00:00:00 2001 From: Jason Francis Date: Fri, 23 Aug 2019 17:35:59 -0400 Subject: [PATCH] Correctly render flipped/rotated screens --- src/main.c | 28 ++++++++++++++++++++++++++++ src/render.c | 43 +++++++++++++++++++++++++++++++------------ src/wdisplays.h | 14 +++++++++++--- 3 files changed, 70 insertions(+), 15 deletions(-) diff --git a/src/main.c b/src/main.c index 5ea320d..6d86b33 100644 --- a/src/main.c +++ b/src/main.c @@ -347,6 +347,21 @@ static inline void color_to_float_array(GtkStyleContext *ctx, out[3] = color.alpha; } +static unsigned form_get_rotation(GtkWidget *form) { + GtkBuilder *builder = GTK_BUILDER(g_object_get_data(G_OBJECT(form), "builder")); + unsigned rot; + for (rot = 0; rot < NUM_ROTATIONS; rot++) { + GtkWidget *rotate = GTK_WIDGET(gtk_builder_get_object(builder, + ROTATE_IDS[rot])); + gboolean selected; + g_object_get(rotate, "active", &selected, NULL); + if (selected) { + return rot; + } + } + return -1; +} + static void queue_canvas_draw(struct wd_state *state) { GtkStyleContext *style_ctx = gtk_widget_get_style_context(state->canvas); color_to_float_array(style_ctx, @@ -379,6 +394,13 @@ static void queue_canvas_draw(struct wd_state *state) { wl_list_insert(&state->render.heads, &head->render->link); } struct wd_render_head_data *render = head->render; + render->queued.rotation = form_get_rotation(GTK_WIDGET(form_iter->data)); + if (render->queued.rotation & 1) { + int tmp = w; + w = h; + h = tmp; + } + render->queued.x_invert = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "flipped"))); render->x1 = floor(x * state->zoom - state->render.scroll_x - state->render.x_origin); render->y1 = floor(y * state->zoom - state->render.scroll_y - state->render.y_origin); render->x2 = floor(render->x1 + w * state->zoom / scale); @@ -839,6 +861,10 @@ static void canvas_render(GtkGLArea *area, GdkGLContext *context, gpointer data) render->y_invert = frame->y_invert; render->swap_rgb = frame->swap_rgb; } + if (render->preview) { + render->active.rotation = render->queued.rotation; + render->active.x_invert = render->queued.x_invert; + } } else if (render->preview || render->pixels == NULL || size_changed(render)) { render->tex_width = render->x2 - render->x1; @@ -852,6 +878,8 @@ static void canvas_render(GtkGLArea *area, GdkGLContext *context, gpointer data) render->pixels = cairo_image_surface_get_data(head->surface); render->tex_stride = cairo_image_surface_get_stride(head->surface); render->updated_at = tick; + render->active.rotation = 0; + render->active.x_invert = false; render->y_invert = false; render->swap_rgb = false; } diff --git a/src/render.c b/src/render.c index 19fc368..1531db9 100644 --- a/src/render.c +++ b/src/render.c @@ -253,20 +253,39 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info, int i = 0; wl_list_for_each_reverse(head, &info->heads, link) { float *tri_ptr = res->tris + i * BT_UV_QUAD_SIZE; - float x1 = head->x1; - float y1 = head->y1; - float x2 = head->x2; - float y2 = head->y2; + float x1 = head->active.x_invert ? head->x2 : head->x1; + float y1 = head->y_invert ? head->y2 : head->y1; + float x2 = head->active.x_invert ? head->x1 : head->x2; + float y2 = head->y_invert ? head->y1 : head->y2; - float t1 = head->y_invert ? 1.f : 0.f; - float t2 = head->y_invert ? 0.f : 1.f; + float sa = 0.f; + float sb = 1.f; + float sc = sb; + float sd = sa; + float ta = 0.f; + float tb = ta; + float tc = 1.f; + float td = tc; + for (int i = 0; i < head->active.rotation; i++) { + float tmp = sd; + sd = sc; + sc = sb; + sb = sa; + sa = tmp; - PUSH_POINT_UV(tri_ptr, x1, y1, 0.f, t1) - PUSH_POINT_UV(tri_ptr, x2, y1, 1.f, t1) - PUSH_POINT_UV(tri_ptr, x1, y2, 0.f, t2) - PUSH_POINT_UV(tri_ptr, x1, y2, 0.f, t2) - PUSH_POINT_UV(tri_ptr, x2, y1, 1.f, t1) - PUSH_POINT_UV(tri_ptr, x2, y2, 1.f, t2) + tmp = td; + td = tc; + tc = tb; + tb = ta; + ta = tmp; + } + + PUSH_POINT_UV(tri_ptr, x1, y1, sa, ta) + PUSH_POINT_UV(tri_ptr, x2, y1, sb, tb) + PUSH_POINT_UV(tri_ptr, x1, y2, sd, td) + PUSH_POINT_UV(tri_ptr, x1, y2, sd, td) + PUSH_POINT_UV(tri_ptr, x2, y1, sb, tb) + PUSH_POINT_UV(tri_ptr, x2, y2, sc, tc) tris += 6; i++; diff --git a/src/wdisplays.h b/src/wdisplays.h index fa6a346..cc6e58d 100644 --- a/src/wdisplays.h +++ b/src/wdisplays.h @@ -148,25 +148,33 @@ struct wd_head { struct wd_gl_data; +struct wd_render_head_flags { + uint8_t rotation; + bool x_invert; +}; + struct wd_render_head_data { struct wl_list link; + uint64_t updated_at; + uint64_t transition_begin; float x1; float y1; float x2; float y2; + struct wd_render_head_flags queued; + struct wd_render_head_flags active; + uint8_t *pixels; unsigned tex_stride; unsigned tex_width; unsigned tex_height; + bool preview; bool y_invert; bool swap_rgb; - uint64_t updated_at; - bool hovered; - uint64_t transition_begin; }; struct wd_render_data {