Commit d23f353e authored by Guido Gunther's avatar Guido Gunther
Browse files

Merge branch 'primary-frac-scale' into 'main'

shell: Use fractional scale for phosh_shell_get_usable_area too

Closes #479

See merge request World/Phosh/phosh!883
parents 256730a8 8671cf7c
......@@ -162,34 +162,6 @@ phosh_monitor_manager_get_head_from_monitor (PhoshMonitorManager *self, PhoshMon
return NULL;
}
static gint32
phosh_monitor_manager_flip_transform (PhoshMonitorTransform transform)
{
/* Wayland rotation is opposite from DBus */
switch (transform) {
case PHOSH_MONITOR_TRANSFORM_90:
return WL_OUTPUT_TRANSFORM_270;
break;
case PHOSH_MONITOR_TRANSFORM_270:
return WL_OUTPUT_TRANSFORM_90;
break;
case PHOSH_MONITOR_TRANSFORM_FLIPPED_90:
return WL_OUTPUT_TRANSFORM_FLIPPED_270;
break;
case PHOSH_MONITOR_TRANSFORM_FLIPPED_270:
return WL_OUTPUT_TRANSFORM_FLIPPED_90;
break;
case PHOSH_MONITOR_TRANSFORM_NORMAL:
case PHOSH_MONITOR_TRANSFORM_180:
case PHOSH_MONITOR_TRANSFORM_FLIPPED:
case PHOSH_MONITOR_TRANSFORM_FLIPPED_180:
default:
/* Nothing to be done */
return transform;
}
}
/*
* DBus Interface
*/
......@@ -568,7 +540,7 @@ phosh_monitor_manager_handle_get_current_state (PhoshDBusDisplayConfig *skeleton
for (int k = 0; k < head->modes->len; k++) {
PhoshHeadMode *mode = g_ptr_array_index (head->modes, k);
g_autofree int *scales = NULL;
g_autofree float *scales = NULL;
if (!mode->name) {
g_warning ("Skipping unnamend mode %p", mode);
continue;
......@@ -576,7 +548,7 @@ phosh_monitor_manager_handle_get_current_state (PhoshDBusDisplayConfig *skeleton
g_variant_builder_init (&supported_scales_builder,
G_VARIANT_TYPE ("ad"));
scales = phosh_head_calculate_supported_mode_scales (head, mode, &n);
scales = phosh_head_calculate_supported_mode_scales (head, mode, &n, TRUE);
for (int l = 0; l < n; l++) {
g_variant_builder_add (&supported_scales_builder, "d",
(double)scales[l]);
......@@ -801,7 +773,7 @@ config_head_config_from_logical_monitor_variant (PhoshMonitorManager *self,
head->pending.scale = scale;
head->pending.x = x;
head->pending.y = y;
head->pending.transform = phosh_monitor_manager_flip_transform (transform);
head->pending.transform = transform;
head->pending.enabled = TRUE;
head->pending.seen = TRUE;
}
......
......@@ -38,8 +38,10 @@ static GParamSpec *props[PHOSH_HEAD_PROP_LAST_PROP];
#define MINIMUM_LOGICAL_AREA_LANDSCAPE (800 * 480)
#define MINIMUM_LOGICAL_AREA_PORTRAIT (360 * 720)
#define MINIMUM_SCALE_FACTOR 1
#define MAXIMUM_SCALE_FACTOR 4
#define MINIMUM_SCALE_FACTOR 1.0f
#define MAXIMUM_SCALE_FACTOR 4.0f
#define SCALE_FACTORS_PER_INTEGER 4
#define SCALE_FACTORS_STEPS (1.0 / (float) SCALE_FACTORS_PER_INTEGER)
G_DEFINE_TYPE (PhoshHead, phosh_head, G_TYPE_OBJECT);
......@@ -71,29 +73,24 @@ mode_name (PhoshHeadMode *mode)
static gboolean
is_logical_size_large_enough (int width, int height)
is_logical_size_large_enough (float width, float height)
{
if (width > height)
return width * height >= MINIMUM_LOGICAL_AREA_LANDSCAPE;
else
return width * height >= MINIMUM_LOGICAL_AREA_PORTRAIT;
int area = (width > height) ? MINIMUM_LOGICAL_AREA_LANDSCAPE : MINIMUM_LOGICAL_AREA_PORTRAIT;
return width * height >= area;
}
static gboolean
is_valid_scale (int width, int height, int scale)
is_valid_scale (float width, float height, float scale)
{
int scaled_h = height / scale;
int scaled_w = width / scale;
float scaled_h = height / scale;
float scaled_w = width / scale;
if (scale < MINIMUM_SCALE_FACTOR || scale > MAXIMUM_SCALE_FACTOR ||
!is_logical_size_large_enough (scaled_w, scaled_h))
if (scale < MINIMUM_SCALE_FACTOR || scale > MAXIMUM_SCALE_FACTOR)
return FALSE;
if (width % scale == 0 && height % scale == 0)
return TRUE;
return FALSE;
return is_logical_size_large_enough (floorf (scaled_w), floorf(scaled_h));
}
......@@ -586,28 +583,108 @@ phosh_head_find_mode_by_name (PhoshHead *self, const char *name)
}
int *
static float
get_closest_scale_factor_for_resolution (float width, float height, float scale, float threshold)
{
unsigned int i;
float scaled_h;
float scaled_w;
float best_scale;
int base_scaled_w;
gboolean found_one;
best_scale = 0;
if (!is_valid_scale (width, height, scale))
return 0.0;
if ((int)fmodf (width, scale) == 0 && (int)fmodf (height, scale) == 0)
return scale;
i = 0;
found_one = FALSE;
base_scaled_w = floorf (width / scale);
do {
for (int j = 0; j < 2; j++) {
float current_scale;
int offset = i * (j ? 1 : -1);
scaled_w = base_scaled_w + offset;
current_scale = width / scaled_w;
scaled_h = height / current_scale;
if (current_scale >= scale + threshold ||
current_scale <= scale - threshold ||
current_scale < MINIMUM_SCALE_FACTOR ||
current_scale > MAXIMUM_SCALE_FACTOR) {
return best_scale;
}
#pragma GCC diagnostic ignored "-Wfloat-equal"
if (floorf (scaled_h) == scaled_h) {
#pragma GCC diagnostic error "-Wfloat-equal"
found_one = TRUE;
if (fabsf (current_scale - scale) < fabsf (best_scale - scale))
best_scale = current_scale;
}
}
i++;
} while (!found_one);
return best_scale;
}
float *
phosh_head_calculate_supported_mode_scales (PhoshHead *head,
PhoshHeadMode *mode,
int *n_supported_scales)
int *n_supported_scales,
gboolean fractional)
{
unsigned int i;
GArray *supported_scales;
supported_scales = g_array_new (FALSE, FALSE, sizeof (int));
for (i = MINIMUM_SCALE_FACTOR; i <= MAXIMUM_SCALE_FACTOR; i++) {
if (is_valid_scale (mode->width, mode->height, i))
g_array_append_val (supported_scales, i);
supported_scales = g_array_new (FALSE, FALSE, sizeof (float));
if (fractional) {
for (int i = floorf (MINIMUM_SCALE_FACTOR); i <= ceilf (MAXIMUM_SCALE_FACTOR); i++) {
float max_bound;
#pragma GCC diagnostic ignored "-Wfloat-equal"
if (i == floorf (MINIMUM_SCALE_FACTOR) || i == ceilf (MAXIMUM_SCALE_FACTOR)) {
#pragma GCC diagnostic error "-Wfloat-equal"
max_bound = SCALE_FACTORS_STEPS;
} else {
max_bound = SCALE_FACTORS_STEPS / 2.0;
}
for (int j = 0; j < SCALE_FACTORS_PER_INTEGER; j++) {
float scale;
float scale_value = i + j * SCALE_FACTORS_STEPS;
scale = get_closest_scale_factor_for_resolution (mode->width, mode->height,
scale_value,
max_bound);
if (scale > 0.0)
g_array_append_val (supported_scales, scale);
}
}
} else {
for (float f = floorf (MINIMUM_SCALE_FACTOR); f <= ceilf (MAXIMUM_SCALE_FACTOR); f++) {
if (is_valid_scale (mode->width, mode->height, f)) {
g_array_append_val (supported_scales, f);
}
}
}
if (supported_scales->len == 0) {
int fallback_scale = 1;
float fallback_scale = 1.0;
g_array_append_val (supported_scales, fallback_scale);
}
*n_supported_scales = supported_scales->len;
return (int *) g_array_free (supported_scales, FALSE);
return (float *) g_array_free (supported_scales, FALSE);
}
/**
......
......@@ -71,9 +71,10 @@ gboolean phosh_head_get_enabled (PhoshHead *self);
PhoshHeadMode *phosh_head_get_preferred_mode (PhoshHead *self);
gboolean phosh_head_is_builtin (PhoshHead *self);
PhoshHeadMode *phosh_head_find_mode_by_name (PhoshHead *self, const char *name);
int * phosh_head_calculate_supported_mode_scales (PhoshHead *head,
float * phosh_head_calculate_supported_mode_scales (PhoshHead *head,
PhoshHeadMode *mode,
int *n);
int *n,
gboolean fractional);
void phosh_head_clear_pending (PhoshHead *self);
G_END_DECLS
......@@ -89,8 +89,8 @@ output_handle_scale (void *data,
{
PhoshMonitor *self = PHOSH_MONITOR (data);
/* nothing to do */
self->wl_output_done = FALSE;
self->scale = scale;
}
......@@ -404,7 +404,6 @@ phosh_monitor_class_init (PhoshMonitorClass *klass)
static void
phosh_monitor_init (PhoshMonitor *self)
{
self->scale = 1.0;
self->modes = g_array_new (FALSE, FALSE, sizeof(PhoshMonitorMode));
self->power_mode = PHOSH_MONITOR_POWER_SAVE_MODE_OFF;
}
......
......@@ -117,7 +117,7 @@ struct _PhoshMonitor {
int x, y, width, height;
int subpixel;
gint32 transform, scale;
gint32 transform;
struct {
gint32 x, y, width, height;
......
......@@ -258,6 +258,7 @@ add_activity (PhoshOverview *self, PhoshToplevel *toplevel)
PhoshOverviewPrivate *priv;
GtkWidget *activity;
const char *app_id, *title;
float scale;
g_return_if_fail (PHOSH_IS_OVERVIEW (self));
priv = phosh_overview_get_instance_private (self);
......@@ -267,9 +268,10 @@ add_activity (PhoshOverview *self, PhoshToplevel *toplevel)
g_debug ("Building activator for '%s' (%s)", app_id, title);
activity = phosh_activity_new (app_id, title);
scale = phosh_monitor_get_fractional_scale (monitor);
g_object_set (activity,
"win-width", monitor->width / monitor->scale, /* TODO: Get the real size somehow */
"win-height", monitor->height / monitor->scale,
"win-width", (int)(monitor->width / scale),
"win-height", (int)(monitor->height / scale),
"maximized", phosh_toplevel_is_maximized (toplevel),
NULL);
g_object_set_data (G_OBJECT (activity), "toplevel", toplevel);
......
......@@ -1171,7 +1171,7 @@ phosh_shell_get_usable_area (PhoshShell *self, int *x, int *y, int *width, int *
PhoshMonitor *monitor;
PhoshMonitorMode *mode;
int w, h;
int scale;
float scale;
g_return_if_fail (PHOSH_IS_SHELL (self));
......@@ -1180,11 +1180,11 @@ phosh_shell_get_usable_area (PhoshShell *self, int *x, int *y, int *width, int *
mode = phosh_monitor_get_current_mode (monitor);
g_return_if_fail (mode != NULL);
scale = monitor->scale ? monitor->scale : 1;
scale = MAX(1.0, phosh_monitor_get_fractional_scale (monitor));
g_debug ("Primary monitor %p scale is %d, transform is %d",
g_debug ("Primary monitor %p scale is %f, transform is %d",
monitor,
monitor->scale,
scale,
monitor->transform);
switch (phosh_monitor_get_transform(monitor)) {
......
......@@ -64,6 +64,7 @@ tests = [
'app-list-model',
'connectivity-info',
'favourite-model',
'head',
'media-player',
'mount-notification',
'notification',
......
/*
* Copyright (C) 2021 Purism SPC
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Author: Guido Günther <agx@sigxcpu.org>
*/
#include "monitor/head.h"
static void
test_phosh_head_scale_integer (void)
{
int num;
g_autofree float *scales;
PhoshHeadMode phone_mode = {
.width = 720,
.height = 1440,
};
PhoshHeadMode fourk_mode = {
.width = 3840,
.height = 2160,
};
scales = phosh_head_calculate_supported_mode_scales (NULL, &phone_mode, &num, FALSE);
g_assert_cmpint (num, ==, 2);
g_assert_cmpint (scales[0], ==, 1);
g_assert_cmpint (scales[1], ==, 2);
g_clear_pointer (&scales, g_free);
scales = phosh_head_calculate_supported_mode_scales (NULL, &fourk_mode, &num, FALSE);
g_assert_cmpint (num, ==, 4);
g_assert_cmpint (scales[0], ==, 1);
g_assert_cmpint (scales[1], ==, 2);
g_assert_cmpint (scales[2], ==, 3);
g_assert_cmpint (scales[3], ==, 4);
}
static void
test_phosh_head_scale_fractional (void)
{
int num;
g_autofree float *scales;
PhoshHeadMode mode = {
.width = 720,
.height = 1440,
};
PhoshHeadMode fourk_mode = {
.width = 3840,
.height = 2160,
};
scales = phosh_head_calculate_supported_mode_scales (NULL, &mode, &num, TRUE);
g_assert_cmpint (num, ==, 5);
#pragma GCC diagnostic ignored "-Wfloat-equal"
g_assert_cmpfloat (scales[0], ==, 1.0);
g_assert_cmpfloat (scales[1], ==, 1.25);
g_assert_cmpfloat (scales[2], ==, 1.5);
g_assert_cmpfloat (scales[3], >=, 1.75);
g_assert_cmpfloat (scales[3], <=, 1.76);
g_assert_cmpfloat (scales[4], ==, 2.0);
g_clear_pointer (&scales, g_free);
scales = phosh_head_calculate_supported_mode_scales (NULL, &fourk_mode, &num, TRUE);
g_assert_cmpint (num, ==, 13);
g_assert_cmpfloat (scales[0], ==, 1.0);
g_assert_cmpfloat (scales[1], ==, 1.25);
/* ... */
g_assert_cmpfloat (scales[11], ==, 3.75);
g_assert_cmpfloat (scales[12], ==, 4);
#pragma GCC diagnostic error "-Wfloat-equal"
}
int
main (int argc,
char *argv[])
{
g_test_init (&argc, &argv, NULL);
g_test_add_func("/phosh/head/scale/integer", test_phosh_head_scale_integer);
g_test_add_func("/phosh/head/scale/fractional", test_phosh_head_scale_fractional);
return g_test_run();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment