Use nearest filtering at integer output scales
abb6120846d1be8681541a1439d7c8073c7b7d06
1 parent
348a25f7
swm.c
+22 -0
| 4863 | 4863 | return true; |
|
| 4864 | 4864 | } |
|
| 4865 | 4865 | return false; |
|
| 4866 | 4866 | } |
|
| 4867 | 4867 | ||
| 4868 | + | /* Select the buffer filter for the output that is about to render. */ |
|
| 4869 | + | static void scene_buffer_set_scale_filter( |
|
| 4870 | + | struct wlr_scene_buffer *buffer, int sx, int sy, void *data |
|
| 4871 | + | ) { |
|
| 4872 | + | float scale = *(float *)data; |
|
| 4873 | + | bool downscaled = buffer->dst_width > 0 && buffer->dst_height > 0 && |
|
| 4874 | + | (buffer->dst_width < buffer->WLR_PRIVATE.buffer_width || |
|
| 4875 | + | buffer->dst_height < buffer->WLR_PRIVATE.buffer_height); |
|
| 4876 | + | ||
| 4877 | + | /* Filter changes apply to this render and must not damage other outputs. */ |
|
| 4878 | + | buffer->filter_mode = !downscaled && ceilf(scale) == scale |
|
| 4879 | + | ? WLR_SCALE_FILTER_NEAREST |
|
| 4880 | + | : WLR_SCALE_FILTER_BILINEAR; |
|
| 4881 | + | } |
|
| 4882 | + | ||
| 4868 | 4883 | /* Apply a display configuration requested by an external client. */ |
|
| 4869 | 4884 | void output_manager_apply(struct wl_listener *listener, void *data) { |
|
| 4870 | 4885 | struct wlr_output_configuration_v1 *config = data; |
|
| 4871 | 4886 | ||
| 4872 | 4887 | output_manager_apply_or_test(config, 0); |
| 4899 | 4914 | config_head->state.custom_mode.height <= 0)) |
|
| 4900 | 4915 | config_head->state.mode = wlr_output_preferred_mode(wlr_output); |
|
| 4901 | 4916 | wlr_output_head_v1_state_apply(&config_head->state, &output_state_pool[i].base); |
|
| 4902 | 4917 | i++; |
|
| 4903 | 4918 | ||
| 4919 | + | if (config_head->state.enabled) |
|
| 4920 | + | wlr_scene_node_for_each_buffer( |
|
| 4921 | + | &scene->tree.node, scene_buffer_set_scale_filter, &config_head->state.scale |
|
| 4922 | + | ); |
|
| 4904 | 4923 | if (config_head->state.enabled && |
|
| 4905 | 4924 | (!m || !m->scene_output || |
|
| 4906 | 4925 | !wlr_scene_output_build_state( |
|
| 4907 | 4926 | m->scene_output, &output_state_pool[i - 1].base, nullptr |
|
| 4908 | 4927 | ))) { |
| 5175 | 5194 | if (c->resize && !c->is_floating && |
|
| 5176 | 5195 | resize_blocks_frame(VISIBLEON(c, m), client_is_rendered_on_mon(c, m)) && |
|
| 5177 | 5196 | !client_is_stopped(c)) |
|
| 5178 | 5197 | goto skip; |
|
| 5179 | 5198 | } |
|
| 5199 | + | wlr_scene_output_for_each_buffer( |
|
| 5200 | + | m->scene_output, scene_buffer_set_scale_filter, &m->wlr_output->scale |
|
| 5201 | + | ); |
|
| 5180 | 5202 | wlr_scene_output_commit(m->scene_output, nullptr); |
|
| 5181 | 5203 | ||
| 5182 | 5204 | skip: |
|
| 5183 | 5205 | /* Tell applications that the frame has been drawn. */ |
|
| 5184 | 5206 | clock_gettime(CLOCK_MONOTONIC, &now); |