diff --git a/gsk/vulkan/gskvulkanrender.c b/gsk/vulkan/gskvulkanrender.c index 12b84cb8c5..1957e75e48 100644 --- a/gsk/vulkan/gskvulkanrender.c +++ b/gsk/vulkan/gskvulkanrender.c @@ -58,7 +58,7 @@ struct _GskVulkanRender GskVulkanImage *target; - VkSampler samplers[2]; + VkSampler samplers[3]; GList *render_passes; GSList *cleanup_images; @@ -272,6 +272,21 @@ gsk_vulkan_render_new (GskRenderer *renderer, NULL, &self->samplers[GSK_VULKAN_SAMPLER_REPEAT]); + GSK_VK_CHECK (vkCreateSampler, device, + &(VkSamplerCreateInfo) { + .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + .magFilter = VK_FILTER_NEAREST, + .minFilter = VK_FILTER_NEAREST, + .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT, + .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, + .unnormalizedCoordinates = VK_FALSE, + .maxAnisotropy = 1.0, + }, + NULL, + &self->samplers[GSK_VULKAN_SAMPLER_NEAREST]); + self->uploader = gsk_vulkan_uploader_new (self->vulkan, self->command_pool); diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c index 1dc2e6286b..6dd7fb0d7e 100644 --- a/gsk/vulkan/gskvulkanrenderpass.c +++ b/gsk/vulkan/gskvulkanrenderpass.c @@ -43,6 +43,7 @@ typedef enum { GSK_VULKAN_OP_FALLBACK_CLIP, GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP, GSK_VULKAN_OP_TEXTURE, + GSK_VULKAN_OP_TEXTURE_SCALE, GSK_VULKAN_OP_COLOR, GSK_VULKAN_OP_LINEAR_GRADIENT, GSK_VULKAN_OP_OPACITY, @@ -496,6 +497,34 @@ gsk_vulkan_render_pass_add_texture_node (GskVulkanRenderPass *self, return TRUE; } +static inline gboolean +gsk_vulkan_render_pass_add_texture_scale_node (GskVulkanRenderPass *self, + GskVulkanRender *render, + const GskVulkanParseState *state, + GskRenderNode *node) +{ + GskVulkanPipelineType pipeline_type; + GskVulkanOp op = { + .render.type = GSK_VULKAN_OP_TEXTURE_SCALE, + .render.node = node, + .render.offset = state->offset, + }; + + if (gsk_vulkan_clip_contains_rect (&state->clip, &state->offset, &node->bounds)) + pipeline_type = GSK_VULKAN_PIPELINE_TEXTURE; + else if (state->clip.type == GSK_VULKAN_CLIP_RECT) + pipeline_type = GSK_VULKAN_PIPELINE_TEXTURE_CLIP; + else if (state->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR) + pipeline_type = GSK_VULKAN_PIPELINE_TEXTURE_CLIP_ROUNDED; + else + FALLBACK ("Texture nodes can't deal with clip type %u", state->clip.type); + + op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type); + g_array_append_val (self->render_ops, op); + + return TRUE; +} + static inline gboolean gsk_vulkan_render_pass_add_inset_shadow_node (GskVulkanRenderPass *self, GskVulkanRender *render, @@ -1162,7 +1191,7 @@ static const GskVulkanRenderPassNodeFunc nodes_vtable[N_RENDER_NODES] = { [GSK_BLUR_NODE] = gsk_vulkan_render_pass_add_blur_node, [GSK_DEBUG_NODE] = gsk_vulkan_render_pass_add_debug_node, [GSK_GL_SHADER_NODE] = NULL, - [GSK_TEXTURE_SCALE_NODE] = NULL, + [GSK_TEXTURE_SCALE_NODE] = gsk_vulkan_render_pass_add_texture_scale_node, [GSK_MASK_NODE] = NULL, }; @@ -1544,6 +1573,16 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self, } break; + case GSK_VULKAN_OP_TEXTURE_SCALE: + { + op->render.source = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)), + gsk_texture_scale_node_get_texture (op->render.node), + uploader); + op->render.source_rect = GRAPHENE_RECT_INIT(0, 0, 1, 1); + gsk_vulkan_render_add_cleanup_image (render, op->render.source); + } + break; + case GSK_VULKAN_OP_OPACITY: { GskRenderNode *child = gsk_opacity_node_get_child (op->render.node); @@ -1761,6 +1800,7 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self) case GSK_VULKAN_OP_FALLBACK_CLIP: case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP: case GSK_VULKAN_OP_TEXTURE: + case GSK_VULKAN_OP_TEXTURE_SCALE: case GSK_VULKAN_OP_REPEAT: case GSK_VULKAN_OP_COLOR: case GSK_VULKAN_OP_LINEAR_GRADIENT: @@ -1816,6 +1856,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self, case GSK_VULKAN_OP_FALLBACK_CLIP: case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP: case GSK_VULKAN_OP_TEXTURE: + case GSK_VULKAN_OP_TEXTURE_SCALE: gsk_vulkan_texture_pipeline_collect_vertex_data (GSK_VULKAN_TEXTURE_PIPELINE (op->render.pipeline), data + op->render.vertex_offset, op->render.image_descriptor, @@ -2071,6 +2112,25 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self, } break; + case GSK_VULKAN_OP_TEXTURE_SCALE: + if (op->render.source) + { + op->render.image_descriptor[0] = gsk_vulkan_render_get_image_descriptor (render, op->render.source); + switch (gsk_texture_scale_node_get_filter (op->render.node)) + { + default: + g_assert_not_reached (); + case GSK_SCALING_FILTER_LINEAR: + case GSK_SCALING_FILTER_TRILINEAR: + op->render.image_descriptor[1] = gsk_vulkan_render_get_sampler_descriptor (render, GSK_VULKAN_SAMPLER_DEFAULT); + break; + case GSK_SCALING_FILTER_NEAREST: + op->render.image_descriptor[1] = gsk_vulkan_render_get_sampler_descriptor (render, GSK_VULKAN_SAMPLER_NEAREST); + break; + } + } + break; + case GSK_VULKAN_OP_REPEAT: if (op->render.source) { @@ -2144,6 +2204,7 @@ gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass *self, case GSK_VULKAN_OP_FALLBACK_CLIP: case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP: case GSK_VULKAN_OP_TEXTURE: + case GSK_VULKAN_OP_TEXTURE_SCALE: case GSK_VULKAN_OP_REPEAT: if (!op->render.source) continue; diff --git a/gsk/vulkan/gskvulkanrenderprivate.h b/gsk/vulkan/gskvulkanrenderprivate.h index 51a9f00f87..70771a078a 100644 --- a/gsk/vulkan/gskvulkanrenderprivate.h +++ b/gsk/vulkan/gskvulkanrenderprivate.h @@ -53,7 +53,8 @@ typedef enum { typedef enum { GSK_VULKAN_SAMPLER_DEFAULT, - GSK_VULKAN_SAMPLER_REPEAT + GSK_VULKAN_SAMPLER_REPEAT, + GSK_VULKAN_SAMPLER_NEAREST } GskVulkanRenderSampler; GskVulkanRender * gsk_vulkan_render_new (GskRenderer *renderer,