diff --git a/include/render/vulkan.h b/include/render/vulkan.h index f901f5f1..c4766e73 100644 --- a/include/render/vulkan.h +++ b/include/render/vulkan.h @@ -125,6 +125,7 @@ void vulkan_format_props_finish(struct wlr_vk_format_props *props); struct wlr_vk_pipeline_layout_key { const struct wlr_vk_format *ycbcr_format; + enum wlr_scale_filter_mode filter_mode; }; struct wlr_vk_pipeline_layout { diff --git a/include/wlr/render/wlr_renderer.h b/include/wlr/render/wlr_renderer.h index a150930c..a7d0241e 100644 --- a/include/wlr/render/wlr_renderer.h +++ b/include/wlr/render/wlr_renderer.h @@ -196,6 +196,16 @@ enum wlr_render_blend_mode { WLR_RENDER_BLEND_MODE_NONE, }; +/** + * Filter modes. + */ +enum wlr_scale_filter_mode { + /* bilinear texture filtering (default) */ + WLR_SCALE_FILTER_BILINEAR, + /* nearest texture filtering */ + WLR_SCALE_FILTER_NEAREST, +}; + struct wlr_render_texture_options { /* Source texture */ struct wlr_texture *texture; @@ -209,6 +219,8 @@ struct wlr_render_texture_options { const pixman_region32_t *clip; /* Transform applied to the source texture */ enum wl_output_transform transform; + /* Filtering */ + enum wlr_scale_filter_mode filter_mode; }; /** diff --git a/render/gles2/pass.c b/render/gles2/pass.c index 89ca873e..b1d21616 100644 --- a/render/gles2/pass.c +++ b/render/gles2/pass.c @@ -170,7 +170,18 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, glActiveTexture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex); - glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + switch (options->filter_mode) { + case WLR_SCALE_FILTER_BILINEAR: + glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + break; + case WLR_SCALE_FILTER_NEAREST: + glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + break; + } + glUniform1i(shader->tex, 0); glUniform1f(shader->alpha, alpha); set_proj_matrix(shader->proj, pass->projection_matrix, &dst_box); diff --git a/render/pixman/pass.c b/render/pixman/pass.c index 3f0927ee..0528d540 100644 --- a/render/pixman/pass.c +++ b/render/pixman/pass.c @@ -120,6 +120,15 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, height = src_box.height; } + switch (options->filter_mode) { + case WLR_SCALE_FILTER_BILINEAR: + pixman_image_set_filter(texture->image, PIXMAN_FILTER_BILINEAR, NULL, 0); + break; + case WLR_SCALE_FILTER_NEAREST: + pixman_image_set_filter(texture->image, PIXMAN_FILTER_NEAREST, NULL, 0); + break; + } + pixman_image_set_clip_region32(buffer->image, (pixman_region32_t *)options->clip); pixman_image_composite32(PIXMAN_OP_OVER, texture->image, mask, buffer->image, src_box.x, src_box.y, 0, 0, dest_x, dest_y, diff --git a/render/vulkan/pass.c b/render/vulkan/pass.c index acc2a5ae..7ac5cf95 100644 --- a/render/vulkan/pass.c +++ b/render/vulkan/pass.c @@ -547,6 +547,7 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, .source = WLR_VK_SHADER_SOURCE_TEXTURE, .layout = { .ycbcr_format = texture->format->is_ycbcr ? texture->format : NULL, + .filter_mode = options->filter_mode, }, .texture_transform = texture->transform, }); diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index 205f40ad..374d6384 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -2073,6 +2073,10 @@ static bool pipeline_layout_key_equals( assert(!a->ycbcr_format || a->ycbcr_format->is_ycbcr); assert(!b->ycbcr_format || b->ycbcr_format->is_ycbcr); + if (a->filter_mode != b->filter_mode) { + return false; + } + if (a->ycbcr_format != b->ycbcr_format) { return false; } @@ -2384,12 +2388,21 @@ struct wlr_vk_pipeline_layout *get_or_create_pipeline_layout( pipeline_layout->key = *key; VkResult res; + VkFilter filter; + switch (key->filter_mode) { + case WLR_SCALE_FILTER_BILINEAR: + filter = VK_FILTER_LINEAR; + break; + case WLR_SCALE_FILTER_NEAREST: + filter = VK_FILTER_NEAREST; + break; + } VkSamplerYcbcrConversionInfo conversion_info; VkSamplerCreateInfo sampler_create_info = { .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, - .magFilter = VK_FILTER_LINEAR, - .minFilter = VK_FILTER_LINEAR, + .magFilter = filter, + .minFilter = filter, .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST, .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,