Use nearest filtering at integer output scales

abb6120846d1be8681541a1439d7c8073c7b7d06
Alexis Sellier committed ago 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);