typedef struct _GskVulkanOpRender GskVulkanOpRender;
typedef struct _GskVulkanOpText GskVulkanOpText;
typedef struct _GskVulkanOpPushConstants GskVulkanOpPushConstants;
+typedef struct _GskVulkanOpScissor GskVulkanOpScissor;
typedef enum {
/* GskVulkanOpRender */
GSK_VULKAN_OP_COLOR_TEXT,
/* GskVulkanOpPushConstants */
GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS,
+ /* GskVulkanOpScissor */
+ GSK_VULKAN_OP_SCISSOR,
} GskVulkanOpType;
/* render ops with 0, 1 or 2 sources */
GskRoundedRect clip;
};
+struct _GskVulkanOpScissor
+{
+ GskVulkanOpType type;
+ GskRenderNode *node; /* node that's the source of this op */
+ cairo_rectangle_int_t rect;
+};
+
union _GskVulkanOp
{
GskVulkanOpType type;
GskVulkanOpRender render;
GskVulkanOpText text;
GskVulkanOpPushConstants constants;
+ GskVulkanOpScissor scissor;
};
struct _GskVulkanRenderPass
struct _GskVulkanParseState
{
- graphene_point_t offset;
- graphene_vec2_t scale;
- GskTransform *modelview;
- graphene_matrix_t projection;
- GskVulkanClip clip;
+ cairo_rectangle_int_t scissor;
+ graphene_point_t offset;
+ graphene_vec2_t scale;
+ GskTransform *modelview;
+ graphene_matrix_t projection;
+ GskVulkanClip clip;
};
#ifdef G_ENABLE_DEBUG
g_free (self);
}
+static void
+gsk_vulkan_render_pass_append_scissor (GskVulkanRenderPass *self,
+ GskRenderNode *node,
+ const GskVulkanParseState *state)
+{
+ GskVulkanOp op = {
+ .scissor.type = GSK_VULKAN_OP_SCISSOR,
+ .scissor.node = node,
+ .scissor.rect = state->scissor
+ };
+ g_array_append_val (self->render_ops, op);
+}
+
static void
gsk_vulkan_render_pass_append_push_constants (GskVulkanRenderPass *self,
GskRenderNode *node,
break;
}
+ new_state.scissor = state->scissor;
graphene_matrix_init_from_matrix (&new_state.projection, &state->projection);
gsk_vulkan_render_pass_append_push_constants (self, node, &new_state);
if (new_state.clip.type == GSK_VULKAN_CLIP_ALL_CLIPPED)
return TRUE;
+ new_state.scissor = state->scissor;
new_state.offset = state->offset;
graphene_vec2_init_from_vec2 (&new_state.scale, &state->scale);
new_state.modelview = state->modelview;
if (new_state.clip.type == GSK_VULKAN_CLIP_ALL_CLIPPED)
return TRUE;
+ new_state.scissor = state->scissor;
new_state.offset = state->offset;
graphene_vec2_init_from_vec2 (&new_state.scale, &state->scale);
new_state.modelview = state->modelview;
}
void
-gsk_vulkan_render_pass_add (GskVulkanRenderPass *self,
- GskVulkanRender *render,
- GskRenderNode *node)
+gsk_vulkan_render_pass_add (GskVulkanRenderPass *self,
+ GskVulkanRender *render,
+ GskRenderNode *node)
{
GskVulkanParseState state;
- cairo_rectangle_int_t rect;
graphene_rect_t clip;
+ float scale_x, scale_y;
- cairo_region_get_extents (self->clip, &rect);
- clip = GRAPHENE_RECT_INIT(rect.x + self->viewport.origin.x,
- rect.y + self->viewport.origin.y,
- rect.width, rect.height);
- if (graphene_rect_equal (&clip, &self->viewport))
- {
- graphene_rect_scale (&clip, 1 / graphene_vec2_get_x (&self->scale), 1 / graphene_vec2_get_y (&self->scale), &clip);
- gsk_vulkan_clip_init_empty (&state.clip, &self->viewport);
- }
- else
- {
- graphene_rect_scale (&clip, 1 / graphene_vec2_get_x (&self->scale), 1 / graphene_vec2_get_y (&self->scale), &clip);
- gsk_vulkan_clip_init_rect (&state.clip, &clip);
- }
+ scale_x = 1 / graphene_vec2_get_x (&self->scale);
+ scale_y = 1 / graphene_vec2_get_y (&self->scale);
+ cairo_region_get_extents (self->clip, &state.scissor);
+ clip = GRAPHENE_RECT_INIT(state.scissor.x, state.scissor.y,
+ state.scissor.width, state.scissor.height);
+ graphene_rect_scale (&clip, scale_x, scale_y, &clip);
+ gsk_vulkan_clip_init_empty (&state.clip, &clip);
state.modelview = NULL;
graphene_matrix_init_ortho (&state.projection,
- self->viewport.origin.x, self->viewport.origin.x + self->viewport.size.width,
- self->viewport.origin.y, self->viewport.origin.y + self->viewport.size.height,
+ 0, self->viewport.size.width,
+ 0, self->viewport.size.height,
2 * ORTHO_NEAR_PLANE - ORTHO_FAR_PLANE,
ORTHO_FAR_PLANE);
graphene_vec2_init_from_vec2 (&state.scale, &self->scale);
- state.offset = *graphene_point_zero ();
+ state.offset = GRAPHENE_POINT_INIT (-self->viewport.origin.x * scale_x,
+ -self->viewport.origin.y * scale_y);
+ gsk_vulkan_render_pass_append_scissor (self, node, &state);
gsk_vulkan_render_pass_append_push_constants (self, node, &state);
gsk_vulkan_render_pass_add_node (self, render, &state, node);
case GSK_VULKAN_OP_BORDER:
case GSK_VULKAN_OP_INSET_SHADOW:
case GSK_VULKAN_OP_OUTSET_SHADOW:
+ case GSK_VULKAN_OP_SCISSOR:
break;
}
}
g_assert_not_reached ();
case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS:
+ case GSK_VULKAN_OP_SCISSOR:
continue;
}
}
default:
g_assert_not_reached ();
case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS:
+ case GSK_VULKAN_OP_SCISSOR:
continue;
}
}
case GSK_VULKAN_OP_COLOR:
case GSK_VULKAN_OP_LINEAR_GRADIENT:
- case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS:
case GSK_VULKAN_OP_BORDER:
case GSK_VULKAN_OP_INSET_SHADOW:
case GSK_VULKAN_OP_OUTSET_SHADOW:
+ case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS:
+ case GSK_VULKAN_OP_SCISSOR:
break;
}
}
&op->constants.clip);
break;
+ case GSK_VULKAN_OP_SCISSOR:
+ vkCmdSetScissor (command_buffer,
+ 0,
+ 1,
+ &(VkRect2D) {
+ { op->scissor.rect.x, op->scissor.rect.y },
+ { op->scissor.rect.width, op->scissor.rect.height },
+ });
+ break;
+
case GSK_VULKAN_OP_CROSS_FADE:
if (!op->render.source || !op->render.source2)
continue;
cairo_region_get_extents (self->clip, &rect);
- vkCmdSetScissor (command_buffer,
- 0,
- 1,
- &(VkRect2D) {
- { rect.x, rect.y },
- { rect.width, rect.height }
- });
-
vkCmdBeginRenderPass (command_buffer,
&(VkRenderPassBeginInfo) {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,