diff options
author | Ronan Pigott <rpigott@berkeley.edu> | 2019-11-13 11:23:36 -0700 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2019-11-29 18:13:37 +0100 |
commit | 6968fb3123e69f563cd01d472967a9e6ddca2ec1 (patch) | |
tree | 0e313d5e19da37762ab572e38c36ff33798f25fb /sway | |
parent | output: Ensure that frame_done is delayed on max_render_time (diff) | |
download | sway-6968fb3123e69f563cd01d472967a9e6ddca2ec1.tar.gz sway-6968fb3123e69f563cd01d472967a9e6ddca2ec1.tar.zst sway-6968fb3123e69f563cd01d472967a9e6ddca2ec1.zip |
add scale_filter output config option
Diffstat (limited to 'sway')
-rw-r--r-- | sway/commands/output.c | 1 | ||||
-rw-r--r-- | sway/commands/output/scale_filter.c | 34 | ||||
-rw-r--r-- | sway/config/output.c | 38 | ||||
-rw-r--r-- | sway/desktop/render.c | 26 | ||||
-rw-r--r-- | sway/ipc-json.c | 3 | ||||
-rw-r--r-- | sway/meson.build | 2 | ||||
-rw-r--r-- | sway/sway-output.5.scd | 8 | ||||
-rw-r--r-- | sway/tree/output.c | 1 |
8 files changed, 113 insertions, 0 deletions
diff --git a/sway/commands/output.c b/sway/commands/output.c index db2acb50..2790bd63 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c | |||
@@ -19,6 +19,7 @@ static struct cmd_handler output_handlers[] = { | |||
19 | { "res", output_cmd_mode }, | 19 | { "res", output_cmd_mode }, |
20 | { "resolution", output_cmd_mode }, | 20 | { "resolution", output_cmd_mode }, |
21 | { "scale", output_cmd_scale }, | 21 | { "scale", output_cmd_scale }, |
22 | { "scale_filter", output_cmd_scale_filter }, | ||
22 | { "subpixel", output_cmd_subpixel }, | 23 | { "subpixel", output_cmd_subpixel }, |
23 | { "toggle", output_cmd_toggle }, | 24 | { "toggle", output_cmd_toggle }, |
24 | { "transform", output_cmd_transform }, | 25 | { "transform", output_cmd_transform }, |
diff --git a/sway/commands/output/scale_filter.c b/sway/commands/output/scale_filter.c new file mode 100644 index 00000000..fa1e8e0d --- /dev/null +++ b/sway/commands/output/scale_filter.c | |||
@@ -0,0 +1,34 @@ | |||
1 | #include <string.h> | ||
2 | #include "log.h" | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/config.h" | ||
5 | #include "sway/output.h" | ||
6 | |||
7 | struct cmd_results *output_cmd_scale_filter(int argc, char **argv) { | ||
8 | if (!config->handler_context.output_config) { | ||
9 | return cmd_results_new(CMD_FAILURE, "Missing output config"); | ||
10 | } | ||
11 | |||
12 | if (!argc) { | ||
13 | return cmd_results_new(CMD_INVALID, "Missing scale_filter argument."); | ||
14 | } | ||
15 | |||
16 | |||
17 | enum scale_filter_mode scale_filter; | ||
18 | if (strcmp(*argv, "linear") == 0) { | ||
19 | scale_filter = SCALE_FILTER_LINEAR; | ||
20 | } else if (strcmp(*argv, "nearest") == 0) { | ||
21 | scale_filter = SCALE_FILTER_NEAREST; | ||
22 | } else if (strcmp(*argv, "smart") == 0) { | ||
23 | scale_filter = SCALE_FILTER_SMART; | ||
24 | } else { | ||
25 | return cmd_results_new(CMD_INVALID, "Invalid output scale_filter."); | ||
26 | } | ||
27 | |||
28 | struct output_config *oc = config->handler_context.output_config; | ||
29 | config->handler_context.leftovers.argc = argc - 1; | ||
30 | config->handler_context.leftovers.argv = argv + 1; | ||
31 | |||
32 | oc->scale_filter = scale_filter; | ||
33 | return NULL; | ||
34 | } | ||
diff --git a/sway/config/output.c b/sway/config/output.c index 1d5f81da..21a12b8f 100644 --- a/sway/config/output.c +++ b/sway/config/output.c | |||
@@ -29,6 +29,21 @@ void output_get_identifier(char *identifier, size_t len, | |||
29 | wlr_output->serial); | 29 | wlr_output->serial); |
30 | } | 30 | } |
31 | 31 | ||
32 | const char *sway_output_scale_filter_to_string(enum scale_filter_mode scale_filter) { | ||
33 | switch (scale_filter) { | ||
34 | case SCALE_FILTER_DEFAULT: | ||
35 | return "smart"; | ||
36 | case SCALE_FILTER_LINEAR: | ||
37 | return "linear"; | ||
38 | case SCALE_FILTER_NEAREST: | ||
39 | return "nearest"; | ||
40 | case SCALE_FILTER_SMART: | ||
41 | return "smart"; | ||
42 | } | ||
43 | sway_assert(false, "Unknown value for scale_filter."); | ||
44 | return NULL; | ||
45 | } | ||
46 | |||
32 | struct output_config *new_output_config(const char *name) { | 47 | struct output_config *new_output_config(const char *name) { |
33 | struct output_config *oc = calloc(1, sizeof(struct output_config)); | 48 | struct output_config *oc = calloc(1, sizeof(struct output_config)); |
34 | if (oc == NULL) { | 49 | if (oc == NULL) { |
@@ -45,6 +60,7 @@ struct output_config *new_output_config(const char *name) { | |||
45 | oc->custom_mode = -1; | 60 | oc->custom_mode = -1; |
46 | oc->x = oc->y = -1; | 61 | oc->x = oc->y = -1; |
47 | oc->scale = -1; | 62 | oc->scale = -1; |
63 | oc->scale_filter = SCALE_FILTER_DEFAULT; | ||
48 | oc->transform = -1; | 64 | oc->transform = -1; |
49 | oc->subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN; | 65 | oc->subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN; |
50 | oc->max_render_time = -1; | 66 | oc->max_render_time = -1; |
@@ -70,6 +86,9 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { | |||
70 | if (src->scale != -1) { | 86 | if (src->scale != -1) { |
71 | dst->scale = src->scale; | 87 | dst->scale = src->scale; |
72 | } | 88 | } |
89 | if (src->scale_filter != SCALE_FILTER_DEFAULT) { | ||
90 | dst->scale_filter = src->scale_filter; | ||
91 | } | ||
73 | if (src->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN) { | 92 | if (src->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN) { |
74 | dst->subpixel = src->subpixel; | 93 | dst->subpixel = src->subpixel; |
75 | } | 94 | } |
@@ -297,6 +316,24 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { | |||
297 | if (oc && oc->scale > 0) { | 316 | if (oc && oc->scale > 0) { |
298 | sway_log(SWAY_DEBUG, "Set %s scale to %f", oc->name, oc->scale); | 317 | sway_log(SWAY_DEBUG, "Set %s scale to %f", oc->name, oc->scale); |
299 | wlr_output_set_scale(wlr_output, oc->scale); | 318 | wlr_output_set_scale(wlr_output, oc->scale); |
319 | |||
320 | enum scale_filter_mode scale_filter_old = output->scale_filter; | ||
321 | switch (oc->scale_filter) { | ||
322 | case SCALE_FILTER_DEFAULT: | ||
323 | case SCALE_FILTER_SMART: | ||
324 | output->scale_filter = ceilf(wlr_output->scale) == wlr_output->scale ? | ||
325 | SCALE_FILTER_NEAREST : SCALE_FILTER_LINEAR; | ||
326 | break; | ||
327 | case SCALE_FILTER_LINEAR: | ||
328 | case SCALE_FILTER_NEAREST: | ||
329 | output->scale_filter = oc->scale_filter; | ||
330 | break; | ||
331 | } | ||
332 | if (scale_filter_old != output->scale_filter) { | ||
333 | sway_log(SWAY_DEBUG, "Set %s scale_filter to %s", oc->name, | ||
334 | sway_output_scale_filter_to_string(output->scale_filter)); | ||
335 | output_damage_whole(output); | ||
336 | } | ||
300 | } | 337 | } |
301 | 338 | ||
302 | if (oc && (oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN || config->reloading)) { | 339 | if (oc && (oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN || config->reloading)) { |
@@ -352,6 +389,7 @@ static void default_output_config(struct output_config *oc, | |||
352 | } | 389 | } |
353 | oc->x = oc->y = -1; | 390 | oc->x = oc->y = -1; |
354 | oc->scale = 1; | 391 | oc->scale = 1; |
392 | oc->scale_filter = SCALE_FILTER_DEFAULT; | ||
355 | struct sway_output *output = wlr_output->data; | 393 | struct sway_output *output = wlr_output->data; |
356 | oc->subpixel = output->detected_subpixel; | 394 | oc->subpixel = output->detected_subpixel; |
357 | oc->transform = WL_OUTPUT_TRANSFORM_NORMAL; | 395 | oc->transform = WL_OUTPUT_TRANSFORM_NORMAL; |
diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 960fe083..2e66abd4 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c | |||
@@ -1,9 +1,11 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | 1 | #define _POSIX_C_SOURCE 200809L |
2 | #include <assert.h> | 2 | #include <assert.h> |
3 | #include <GLES2/gl2.h> | ||
3 | #include <stdlib.h> | 4 | #include <stdlib.h> |
4 | #include <strings.h> | 5 | #include <strings.h> |
5 | #include <time.h> | 6 | #include <time.h> |
6 | #include <wayland-server-core.h> | 7 | #include <wayland-server-core.h> |
8 | #include <wlr/render/gles2.h> | ||
7 | #include <wlr/render/wlr_renderer.h> | 9 | #include <wlr/render/wlr_renderer.h> |
8 | #include <wlr/types/wlr_box.h> | 10 | #include <wlr/types/wlr_box.h> |
9 | #include <wlr/types/wlr_buffer.h> | 11 | #include <wlr/types/wlr_buffer.h> |
@@ -70,6 +72,28 @@ static void scissor_output(struct wlr_output *wlr_output, | |||
70 | wlr_renderer_scissor(renderer, &box); | 72 | wlr_renderer_scissor(renderer, &box); |
71 | } | 73 | } |
72 | 74 | ||
75 | static void set_scale_filter(struct wlr_output *wlr_output, | ||
76 | struct wlr_texture *texture, enum scale_filter_mode scale_filter) { | ||
77 | if (!wlr_texture_is_gles2(texture)) { | ||
78 | return; | ||
79 | } | ||
80 | |||
81 | struct wlr_gles2_texture_attribs attribs; | ||
82 | wlr_gles2_texture_get_attribs(texture, &attribs); | ||
83 | |||
84 | switch (scale_filter) { | ||
85 | case SCALE_FILTER_LINEAR: | ||
86 | glTexParameteri(attribs.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
87 | break; | ||
88 | case SCALE_FILTER_NEAREST: | ||
89 | glTexParameteri(attribs.target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||
90 | break; | ||
91 | case SCALE_FILTER_DEFAULT: | ||
92 | case SCALE_FILTER_SMART: | ||
93 | assert(false); // unreachable | ||
94 | } | ||
95 | } | ||
96 | |||
73 | static void render_texture(struct wlr_output *wlr_output, | 97 | static void render_texture(struct wlr_output *wlr_output, |
74 | pixman_region32_t *output_damage, struct wlr_texture *texture, | 98 | pixman_region32_t *output_damage, struct wlr_texture *texture, |
75 | const struct wlr_box *box, const float matrix[static 9], float alpha) { | 99 | const struct wlr_box *box, const float matrix[static 9], float alpha) { |
@@ -119,6 +143,7 @@ static void render_surface_iterator(struct sway_output *output, struct sway_view | |||
119 | wlr_matrix_project_box(matrix, &box, transform, rotation, | 143 | wlr_matrix_project_box(matrix, &box, transform, rotation, |
120 | wlr_output->transform_matrix); | 144 | wlr_output->transform_matrix); |
121 | 145 | ||
146 | set_scale_filter(wlr_output, texture, output->scale_filter); | ||
122 | render_texture(wlr_output, output_damage, texture, &box, matrix, alpha); | 147 | render_texture(wlr_output, output_damage, texture, &box, matrix, alpha); |
123 | 148 | ||
124 | wlr_presentation_surface_sampled_on_output(server.presentation, surface, | 149 | wlr_presentation_surface_sampled_on_output(server.presentation, surface, |
@@ -268,6 +293,7 @@ static void render_saved_view(struct sway_view *view, | |||
268 | wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0, | 293 | wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0, |
269 | wlr_output->transform_matrix); | 294 | wlr_output->transform_matrix); |
270 | 295 | ||
296 | set_scale_filter(wlr_output, view->saved_buffer->texture, output->scale_filter); | ||
271 | render_texture(wlr_output, damage, view->saved_buffer->texture, | 297 | render_texture(wlr_output, damage, view->saved_buffer->texture, |
272 | &box, matrix, alpha); | 298 | &box, matrix, alpha); |
273 | 299 | ||
diff --git a/sway/ipc-json.c b/sway/ipc-json.c index b880eb65..6cf8504a 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c | |||
@@ -177,6 +177,9 @@ static void ipc_json_describe_output(struct sway_output *output, | |||
177 | json_object_new_string(wlr_output->serial)); | 177 | json_object_new_string(wlr_output->serial)); |
178 | json_object_object_add(object, "scale", | 178 | json_object_object_add(object, "scale", |
179 | json_object_new_double(wlr_output->scale)); | 179 | json_object_new_double(wlr_output->scale)); |
180 | json_object_object_add(object, "scale_filter", | ||
181 | json_object_new_string( | ||
182 | sway_output_scale_filter_to_string(output->scale_filter))); | ||
180 | json_object_object_add(object, "transform", | 183 | json_object_object_add(object, "transform", |
181 | json_object_new_string( | 184 | json_object_new_string( |
182 | ipc_json_output_transform_description(wlr_output->transform))); | 185 | ipc_json_output_transform_description(wlr_output->transform))); |
diff --git a/sway/meson.build b/sway/meson.build index 5458d3dc..3e6e4da6 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -182,6 +182,7 @@ sway_sources = files( | |||
182 | 'commands/output/mode.c', | 182 | 'commands/output/mode.c', |
183 | 'commands/output/position.c', | 183 | 'commands/output/position.c', |
184 | 'commands/output/scale.c', | 184 | 'commands/output/scale.c', |
185 | 'commands/output/scale_filter.c', | ||
185 | 'commands/output/subpixel.c', | 186 | 'commands/output/subpixel.c', |
186 | 'commands/output/toggle.c', | 187 | 'commands/output/toggle.c', |
187 | 'commands/output/transform.c', | 188 | 'commands/output/transform.c', |
@@ -203,6 +204,7 @@ sway_deps = [ | |||
203 | math, | 204 | math, |
204 | pango, | 205 | pango, |
205 | pcre, | 206 | pcre, |
207 | glesv2, | ||
206 | pixman, | 208 | pixman, |
207 | server_protos, | 209 | server_protos, |
208 | wayland_server, | 210 | wayland_server, |
diff --git a/sway/sway-output.5.scd b/sway/sway-output.5.scd index 3824480f..2dfb2ac1 100644 --- a/sway/sway-output.5.scd +++ b/sway/sway-output.5.scd | |||
@@ -70,6 +70,14 @@ must be separated by one space. For example: | |||
70 | applications to taste. HiDPI isn't supported with Xwayland clients (windows | 70 | applications to taste. HiDPI isn't supported with Xwayland clients (windows |
71 | will blur). | 71 | will blur). |
72 | 72 | ||
73 | *output* <name> scale_filter linear|nearest|smart | ||
74 | Indicates how to scale application buffers that are rendered at a scale | ||
75 | lower than the output's configured scale, such as lo-dpi applications on | ||
76 | hi-dpi screens. Linear is smoother and blurrier, nearest (also known as | ||
77 | nearest neighbor) is sharper and blockier. Setting "smart" will apply | ||
78 | nearest scaling when the output has an integer scale factor, otherwise | ||
79 | linear. The default is "smart". | ||
80 | |||
73 | *output* <name> subpixel rgb|bgr|vrgb|vbgr|none | 81 | *output* <name> subpixel rgb|bgr|vrgb|vbgr|none |
74 | Manually sets the subpixel hinting for the specified output. This value is | 82 | Manually sets the subpixel hinting for the specified output. This value is |
75 | usually auto-detected, but some displays may misreport their subpixel | 83 | usually auto-detected, but some displays may misreport their subpixel |
diff --git a/sway/tree/output.c b/sway/tree/output.c index c4ec6eec..d2ede1f2 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -93,6 +93,7 @@ struct sway_output *output_create(struct wlr_output *wlr_output) { | |||
93 | output->wlr_output = wlr_output; | 93 | output->wlr_output = wlr_output; |
94 | wlr_output->data = output; | 94 | wlr_output->data = output; |
95 | output->detected_subpixel = wlr_output->subpixel; | 95 | output->detected_subpixel = wlr_output->subpixel; |
96 | output->scale_filter = SCALE_FILTER_NEAREST; | ||
96 | 97 | ||
97 | wl_signal_init(&output->events.destroy); | 98 | wl_signal_init(&output->events.destroy); |
98 | 99 | ||