aboutsummaryrefslogtreecommitdiffstats
path: root/sway
diff options
context:
space:
mode:
authorLibravatar Ronan Pigott <rpigott@berkeley.edu>2019-11-13 11:23:36 -0700
committerLibravatar Simon Ser <contact@emersion.fr>2019-11-29 18:13:37 +0100
commit6968fb3123e69f563cd01d472967a9e6ddca2ec1 (patch)
tree0e313d5e19da37762ab572e38c36ff33798f25fb /sway
parentoutput: Ensure that frame_done is delayed on max_render_time (diff)
downloadsway-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.c1
-rw-r--r--sway/commands/output/scale_filter.c34
-rw-r--r--sway/config/output.c38
-rw-r--r--sway/desktop/render.c26
-rw-r--r--sway/ipc-json.c3
-rw-r--r--sway/meson.build2
-rw-r--r--sway/sway-output.5.scd8
-rw-r--r--sway/tree/output.c1
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
7struct 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
32const 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
32struct output_config *new_output_config(const char *name) { 47struct 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
75static 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
73static void render_texture(struct wlr_output *wlr_output, 97static 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