Preview rotation follows device

This commit is contained in:
Benjamin Schaaf 2021-05-04 00:06:55 +10:00
parent 46bfb39dfd
commit 64b75bcbe5
6 changed files with 142 additions and 15 deletions

View File

@ -5,10 +5,12 @@ precision mediump float;
attribute vec2 vert; attribute vec2 vert;
attribute vec2 tex_coord; attribute vec2 tex_coord;
uniform mat3 transform;
varying vec2 uv; varying vec2 uv;
void main() { void main() {
uv = tex_coord; uv = tex_coord;
gl_Position = vec4(vert, 0, 1); gl_Position = vec4(transform * vec3(vert, 1), 1);
} }

View File

@ -75,6 +75,8 @@ static int captures_remaining = 0;
static int preview_width; static int preview_width;
static int preview_height; static int preview_height;
static int device_rotation;
struct control_state { struct control_state {
bool gain_is_manual; bool gain_is_manual;
int gain; int gain;
@ -275,6 +277,7 @@ update_process_pipeline()
.burst_length = burst_length, .burst_length = burst_length,
.preview_width = preview_width, .preview_width = preview_width,
.preview_height = preview_height, .preview_height = preview_height,
.device_rotation = device_rotation,
.gain_is_manual = current_controls.gain_is_manual, .gain_is_manual = current_controls.gain_is_manual,
.gain = current_controls.gain, .gain = current_controls.gain,
.gain_max = info->gain_max, .gain_max = info->gain_max,
@ -521,11 +524,13 @@ update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
has_changed = has_changed || burst_length != state->burst_length || has_changed = has_changed || burst_length != state->burst_length ||
preview_width != state->preview_width || preview_width != state->preview_width ||
preview_height != state->preview_height; preview_height != state->preview_height ||
device_rotation != state->device_rotation;
burst_length = state->burst_length; burst_length = state->burst_length;
preview_width = state->preview_width; preview_width = state->preview_width;
preview_height = state->preview_height; preview_height = state->preview_height;
device_rotation = state->device_rotation;
if (camera) { if (camera) {
struct control_state previous_desired = desired_controls; struct control_state previous_desired = desired_controls;

View File

@ -10,6 +10,8 @@ struct mp_io_pipeline_state {
int preview_width; int preview_width;
int preview_height; int preview_height;
int device_rotation;
bool gain_is_manual; bool gain_is_manual;
int gain; int gain;

View File

@ -40,6 +40,8 @@ static MPCameraMode mode;
static int preview_width = -1; static int preview_width = -1;
static int preview_height = -1; static int preview_height = -1;
static int device_rotation = 0;
static bool gain_is_manual = false; static bool gain_is_manual = false;
static int gain; static int gain;
static int gain_max; static int gain_max;
@ -95,6 +97,7 @@ update_io_pipeline()
.burst_length = burst_length, .burst_length = burst_length,
.preview_width = preview_width, .preview_width = preview_width,
.preview_height = preview_height, .preview_height = preview_height,
.device_rotation = device_rotation,
.gain_is_manual = gain_is_manual, .gain_is_manual = gain_is_manual,
.gain = gain, .gain = gain,
.exposure_is_manual = exposure_is_manual, .exposure_is_manual = exposure_is_manual,
@ -215,6 +218,7 @@ mp_main_capture_completed(GdkTexture *thumb, const char *fname)
} }
static GLuint blit_program; static GLuint blit_program;
static GLuint blit_uniform_transform;
static GLuint blit_uniform_texture; static GLuint blit_uniform_texture;
static GLuint solid_program; static GLuint solid_program;
static GLuint solid_uniform_color; static GLuint solid_uniform_color;
@ -247,6 +251,7 @@ preview_realize(GtkGLArea *area)
glBindAttribLocation(blit_program, GL_UTIL_TEX_COORD_ATTRIBUTE, "tex_coord"); glBindAttribLocation(blit_program, GL_UTIL_TEX_COORD_ATTRIBUTE, "tex_coord");
check_gl(); check_gl();
blit_uniform_transform = glGetUniformLocation(blit_program, "transform");
blit_uniform_texture = glGetUniformLocation(blit_program, "texture"); blit_uniform_texture = glGetUniformLocation(blit_program, "texture");
GLuint solid_shaders[] = { GLuint solid_shaders[] = {
@ -266,17 +271,26 @@ preview_realize(GtkGLArea *area)
static void static void
position_preview(float *offset_x, float *offset_y, float *size_x, float *size_y) position_preview(float *offset_x, float *offset_y, float *size_x, float *size_y)
{ {
int scale = gtk_widget_get_scale_factor(preview); int buffer_width, buffer_height;
int preview_height = gtk_widget_get_allocated_height(preview) * scale; if (device_rotation == 0 || device_rotation == 180) {
int top_height = gtk_widget_get_allocated_height(preview_top_box) * scale; buffer_width = preview_buffer_width;
int bottom_height = gtk_widget_get_allocated_height(preview_bottom_box) * scale; buffer_height = preview_buffer_height;
} else {
buffer_width = preview_buffer_height;
buffer_height = preview_buffer_width;
}
int scale_factor = gtk_widget_get_scale_factor(preview);
int top_height = gtk_widget_get_allocated_height(preview_top_box) * scale_factor;
int bottom_height = gtk_widget_get_allocated_height(preview_bottom_box) * scale_factor;
int inner_height = preview_height - top_height - bottom_height; int inner_height = preview_height - top_height - bottom_height;
double ratio = preview_buffer_height / (double)preview_buffer_width; double scale = MIN(preview_width / (float) buffer_width, preview_height / (float) buffer_height);
*offset_x = 0; *size_x = scale * buffer_width;
*size_x = preview_width; *size_y = scale * buffer_height;
*size_y = preview_width * ratio;
*offset_x = (preview_width - *size_x) / 2.0;
if (*size_y > inner_height) { if (*size_y > inner_height) {
*offset_y = (preview_height - *size_y) / 2.0; *offset_y = (preview_height - *size_y) / 2.0;
@ -314,6 +328,19 @@ preview_draw(GtkGLArea *area, GdkGLContext *ctx, gpointer data)
if (current_preview_buffer) { if (current_preview_buffer) {
glUseProgram(blit_program); glUseProgram(blit_program);
GLfloat rotation_list[4] = { 0, -1, 0, 1 };
int rotation_index = device_rotation / 90;
GLfloat sin_rot = rotation_list[rotation_index];
GLfloat cos_rot = rotation_list[(4 + rotation_index - 1) % 4];
GLfloat matrix[9] = {
cos_rot, sin_rot, 0,
-sin_rot, cos_rot, 0,
0, 0, 1,
};
glUniformMatrix3fv(blit_uniform_transform, 1, GL_FALSE, matrix);
check_gl();
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mp_process_pipeline_buffer_get_texture_id(current_preview_buffer)); glBindTexture(GL_TEXTURE_2D, mp_process_pipeline_buffer_get_texture_id(current_preview_buffer));
glUniform1i(blit_uniform_texture, 0); glUniform1i(blit_uniform_texture, 0);
@ -719,6 +746,62 @@ create_simple_action(GtkApplication *app, const char *name, GCallback callback)
return action; return action;
} }
static void display_config_received(GDBusConnection *conn, GAsyncResult *res, gpointer user_data)
{
GError *error = NULL;
GVariant *result = g_dbus_connection_call_finish(conn, res, &error);
if (!result) {
printf("Failed to get display configuration: %s\n", error->message);
return;
}
GVariant *configs = g_variant_get_child_value(result, 1);
if (g_variant_n_children(configs) == 0) {
return;
}
GVariant *config = g_variant_get_child_value(configs, 0);
GVariant *rot_config = g_variant_get_child_value(config, 7);
uint32_t rotation_index = g_variant_get_uint32(rot_config);
assert(rotation_index < 4);
int new_rotation = rotation_index * 90;
if (new_rotation != device_rotation) {
device_rotation = new_rotation;
update_io_pipeline();
}
}
static void update_screen_rotation(GDBusConnection *conn)
{
g_dbus_connection_call(conn,
"org.gnome.Mutter.DisplayConfig",
"/org/gnome/Mutter/DisplayConfig",
"org.gnome.Mutter.DisplayConfig",
"GetResources",
NULL,
NULL,
G_DBUS_CALL_FLAGS_NO_AUTO_START,
-1,
NULL,
(GAsyncReadyCallback)display_config_received,
NULL);
}
static void on_screen_rotate(
GDBusConnection *conn,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
update_screen_rotation(conn);
}
static void static void
activate(GtkApplication *app, gpointer data) activate(GtkApplication *app, gpointer data)
{ {
@ -779,6 +862,21 @@ activate(GtkApplication *app, gpointer data)
const char *quit_accels[] = { "<Ctrl>q", "<Ctrl>w", NULL }; const char *quit_accels[] = { "<Ctrl>q", "<Ctrl>w", NULL };
gtk_application_set_accels_for_action(app, "app.quit", quit_accels); gtk_application_set_accels_for_action(app, "app.quit", quit_accels);
// Listen for phosh rotation
GDBusConnection *conn = g_application_get_dbus_connection(G_APPLICATION(app));
g_dbus_connection_signal_subscribe(
conn,
NULL,
"org.gnome.Mutter.DisplayConfig",
"MonitorsChanged",
"/org/gnome/Mutter/DisplayConfig",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
&on_screen_rotate,
NULL,
NULL);
update_screen_rotation(conn);
mp_io_pipeline_start(); mp_io_pipeline_start();
gtk_application_add_window(app, GTK_WINDOW(window)); gtk_application_add_window(app, GTK_WINDOW(window));

View File

@ -31,6 +31,7 @@ static volatile int frames_processed = 0;
static volatile int frames_received = 0; static volatile int frames_received = 0;
static const struct mp_camera_config *camera; static const struct mp_camera_config *camera;
static int camera_rotation;
static MPCameraMode mode; static MPCameraMode mode;
@ -40,6 +41,8 @@ static int captures_remaining = 0;
static int preview_width; static int preview_width;
static int preview_height; static int preview_height;
static int device_rotation;
static int output_buffer_width = -1; static int output_buffer_width = -1;
static int output_buffer_height = -1; static int output_buffer_height = -1;
@ -370,13 +373,13 @@ process_image_for_capture(const uint8_t *image, int count)
TIFFSetField(tif, TIFFTAG_MAKE, mp_get_device_make()); TIFFSetField(tif, TIFFTAG_MAKE, mp_get_device_make());
TIFFSetField(tif, TIFFTAG_MODEL, mp_get_device_model()); TIFFSetField(tif, TIFFTAG_MODEL, mp_get_device_model());
uint16_t orientation; uint16_t orientation;
if (camera->rotate == 0) { if (camera_rotation == 0) {
orientation = camera->mirrored ? ORIENTATION_TOPRIGHT : orientation = camera->mirrored ? ORIENTATION_TOPRIGHT :
ORIENTATION_TOPLEFT; ORIENTATION_TOPLEFT;
} else if (camera->rotate == 90) { } else if (camera_rotation == 90) {
orientation = camera->mirrored ? ORIENTATION_RIGHTBOT : orientation = camera->mirrored ? ORIENTATION_RIGHTBOT :
ORIENTATION_LEFTBOT; ORIENTATION_LEFTBOT;
} else if (camera->rotate == 180) { } else if (camera_rotation == 180) {
orientation = camera->mirrored ? ORIENTATION_BOTLEFT : orientation = camera->mirrored ? ORIENTATION_BOTLEFT :
ORIENTATION_BOTRIGHT; ORIENTATION_BOTRIGHT;
} else { } else {
@ -583,7 +586,7 @@ process_image(MPPipeline *pipeline, const MPBuffer *buffer)
memcpy(image, buffer->data, size); memcpy(image, buffer->data, size);
mp_io_pipeline_release_buffer(buffer->index); mp_io_pipeline_release_buffer(buffer->index);
MPZBarImage *zbar_image = mp_zbar_image_new(image, mode.pixel_format, mode.width, mode.height, camera->rotate, camera->mirrored); MPZBarImage *zbar_image = mp_zbar_image_new(image, mode.pixel_format, mode.width, mode.height, camera_rotation, camera->mirrored);
mp_zbar_pipeline_process_image(mp_zbar_image_ref(zbar_image)); mp_zbar_pipeline_process_image(mp_zbar_image_ref(zbar_image));
#ifdef PROFILE_PROCESS #ifdef PROFILE_PROCESS
@ -692,10 +695,21 @@ on_output_changed()
camera->blacklevel); camera->blacklevel);
} }
static int
mod(int a, int b)
{
int r = a % b;
return r < 0 ? r + b : r;
}
static void static void
update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state) update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state)
{ {
const bool output_changed = (!mp_camera_mode_is_equivalent(&mode, &state->mode) || preview_width != state->preview_width || preview_height != state->preview_height); const bool output_changed =
!mp_camera_mode_is_equivalent(&mode, &state->mode)
|| preview_width != state->preview_width
|| preview_height != state->preview_height
|| device_rotation != state->device_rotation;
camera = state->camera; camera = state->camera;
mode = state->mode; mode = state->mode;
@ -703,6 +717,8 @@ update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state
preview_width = state->preview_width; preview_width = state->preview_width;
preview_height = state->preview_height; preview_height = state->preview_height;
device_rotation = state->device_rotation;
burst_length = state->burst_length; burst_length = state->burst_length;
// gain_is_manual = state->gain_is_manual; // gain_is_manual = state->gain_is_manual;
@ -713,6 +729,8 @@ update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state
exposure = state->exposure; exposure = state->exposure;
if (output_changed) { if (output_changed) {
camera_rotation = mod(camera->rotate - device_rotation, 360);
on_output_changed(); on_output_changed();
} }

View File

@ -13,6 +13,8 @@ struct mp_process_pipeline_state {
int preview_width; int preview_width;
int preview_height; int preview_height;
int device_rotation;
bool gain_is_manual; bool gain_is_manual;
int gain; int gain;
int gain_max; int gain_max;