diff --git a/gsk/gpu/gskglframe.c b/gsk/gpu/gskglframe.c index 945c7b80e2..79c175a6e2 100644 --- a/gsk/gpu/gskglframe.c +++ b/gsk/gpu/gskglframe.c @@ -76,6 +76,8 @@ gsk_gl_frame_submit (GskGpuFrame *frame, { GskGLFrame *self = GSK_GL_FRAME (frame); + glEnable (GL_SCISSOR_TEST); + glEnable (GL_DEPTH_TEST); glDepthFunc (GL_LEQUAL); diff --git a/gsk/gpu/gskgpunodeprocessor.c b/gsk/gpu/gskgpunodeprocessor.c index f6fa3aed32..42a7017387 100644 --- a/gsk/gpu/gskgpunodeprocessor.c +++ b/gsk/gpu/gskgpunodeprocessor.c @@ -6,6 +6,7 @@ #include "gskgpuframeprivate.h" #include "gskgpuglobalsopprivate.h" #include "gskgpuimageprivate.h" +#include "gskgpuscissoropprivate.h" #include "gskgputextureopprivate.h" #include "gskgpuuploadopprivate.h" @@ -62,9 +63,10 @@ typedef struct _GskGpuNodeProcessor GskGpuNodeProcessor; typedef enum { - GSK_GPU_GLOBAL_MATRIX = (1 << 0), - GSK_GPU_GLOBAL_SCALE = (1 << 1), - GSK_GPU_GLOBAL_CLIP = (1 << 2) + GSK_GPU_GLOBAL_MATRIX = (1 << 0), + GSK_GPU_GLOBAL_SCALE = (1 << 1), + GSK_GPU_GLOBAL_CLIP = (1 << 2), + GSK_GPU_GLOBAL_SCISSOR = (1 << 3), } GskGpuGlobals; struct _GskGpuNodeProcessor @@ -108,7 +110,7 @@ gsk_gpu_node_processor_init (GskGpuNodeProcessor *self, gsk_gpu_image_get_height (target) / viewport->size.height); self->offset = GRAPHENE_POINT_INIT (-viewport->origin.x, -viewport->origin.y); - self->pending_globals = GSK_GPU_GLOBAL_MATRIX | GSK_GPU_GLOBAL_SCALE | GSK_GPU_GLOBAL_CLIP; + self->pending_globals = GSK_GPU_GLOBAL_MATRIX | GSK_GPU_GLOBAL_SCALE | GSK_GPU_GLOBAL_CLIP | GSK_GPU_GLOBAL_SCISSOR; } static void @@ -132,6 +134,14 @@ gsk_gpu_node_processor_emit_globals_op (GskGpuNodeProcessor *self) self->pending_globals &= ~(GSK_GPU_GLOBAL_MATRIX | GSK_GPU_GLOBAL_SCALE | GSK_GPU_GLOBAL_CLIP); } +static void +gsk_gpu_node_processor_emit_scissor_op (GskGpuNodeProcessor *self) +{ + gsk_gpu_scissor_op (self->frame, + &self->scissor); + self->pending_globals &= ~GSK_GPU_GLOBAL_SCISSOR; +} + void gsk_gpu_node_processor_process (GskGpuFrame *frame, GskGpuImage *target, @@ -373,7 +383,7 @@ static const struct NULL, }, [GSK_CONTAINER_NODE] = { - GSK_GPU_GLOBAL_MATRIX | GSK_GPU_GLOBAL_SCALE | GSK_GPU_GLOBAL_CLIP, + GSK_GPU_GLOBAL_MATRIX | GSK_GPU_GLOBAL_SCALE | GSK_GPU_GLOBAL_CLIP | GSK_GPU_GLOBAL_SCISSOR, gsk_gpu_node_processor_add_container_node, }, [GSK_CAIRO_NODE] = { @@ -421,7 +431,7 @@ static const struct NULL, }, [GSK_TRANSFORM_NODE] = { - GSK_GPU_GLOBAL_MATRIX | GSK_GPU_GLOBAL_SCALE | GSK_GPU_GLOBAL_CLIP, + GSK_GPU_GLOBAL_MATRIX | GSK_GPU_GLOBAL_SCALE | GSK_GPU_GLOBAL_CLIP | GSK_GPU_GLOBAL_SCISSOR, gsk_gpu_node_processor_add_transform_node, }, [GSK_OPACITY_NODE] = { @@ -519,6 +529,8 @@ gsk_gpu_node_processor_add_node (GskGpuNodeProcessor *self, required_globals = self->pending_globals & ~nodes_vtable[node_type].ignored_globals; if (required_globals & (GSK_GPU_GLOBAL_MATRIX | GSK_GPU_GLOBAL_SCALE | GSK_GPU_GLOBAL_CLIP)) gsk_gpu_node_processor_emit_globals_op (self); + if (required_globals & GSK_GPU_GLOBAL_SCISSOR) + gsk_gpu_node_processor_emit_scissor_op (self); g_assert ((self->pending_globals & ~nodes_vtable[node_type].ignored_globals) == 0); if (nodes_vtable[node_type].process_node) diff --git a/gsk/gpu/gskgpuscissorop.c b/gsk/gpu/gskgpuscissorop.c new file mode 100644 index 0000000000..1066bb877f --- /dev/null +++ b/gsk/gpu/gskgpuscissorop.c @@ -0,0 +1,88 @@ +#include "config.h" + +#include "gskgpuscissoropprivate.h" + +#include "gskgpuopprivate.h" +#include "gskgpuprintprivate.h" + +typedef struct _GskGpuScissorOp GskGpuScissorOp; + +struct _GskGpuScissorOp +{ + GskGpuOp op; + + cairo_rectangle_int_t rect; +}; + +static void +gsk_gpu_scissor_op_finish (GskGpuOp *op) +{ +} + +static void +gsk_gpu_scissor_op_print (GskGpuOp *op, + GskGpuFrame *frame, + GString *string, + guint indent) +{ + GskGpuScissorOp *self = (GskGpuScissorOp *) op; + + gsk_gpu_print_op (string, indent, "scissor"); + gsk_gpu_print_int_rect (string, &self->rect); + gsk_gpu_print_newline (string); +} + +#ifdef GDK_RENDERING_VULKAN +static GskGpuOp * +gsk_gpu_scissor_op_vk_command (GskGpuOp *op, + GskGpuFrame *frame, + VkRenderPass render_pass, + VkFormat format, + VkCommandBuffer command_buffer) +{ + GskGpuScissorOp *self = (GskGpuScissorOp *) op; + + vkCmdSetScissor (command_buffer, + 0, + 1, + &(VkRect2D) { + { self->rect.x, self->rect.y }, + { self->rect.width, self->rect.height }, + }); + + return op->next; +} +#endif + +static GskGpuOp * +gsk_gpu_scissor_op_gl_command (GskGpuOp *op, + GskGpuFrame *frame) +{ + GskGpuScissorOp *self = (GskGpuScissorOp *) op; + + glScissor (self->rect.x, self->rect.y, self->rect.width, self->rect.height); + + return op->next; +} + +static const GskGpuOpClass GSK_GPU_SCISSOR_OP_CLASS = { + GSK_GPU_OP_SIZE (GskGpuScissorOp), + GSK_GPU_STAGE_COMMAND, + gsk_gpu_scissor_op_finish, + gsk_gpu_scissor_op_print, +#ifdef GDK_RENDERING_VULKAN + gsk_gpu_scissor_op_vk_command, +#endif + gsk_gpu_scissor_op_gl_command +}; + +void +gsk_gpu_scissor_op (GskGpuFrame *frame, + const cairo_rectangle_int_t *rect) +{ + GskGpuScissorOp *self; + + self = (GskGpuScissorOp *) gsk_gpu_op_alloc (frame, &GSK_GPU_SCISSOR_OP_CLASS); + + self->rect = *rect; +} diff --git a/gsk/gpu/gskgpuscissoropprivate.h b/gsk/gpu/gskgpuscissoropprivate.h new file mode 100644 index 0000000000..60f25740b9 --- /dev/null +++ b/gsk/gpu/gskgpuscissoropprivate.h @@ -0,0 +1,12 @@ +#pragma once + +#include "gskgputypesprivate.h" + +G_BEGIN_DECLS + +void gsk_gpu_scissor_op (GskGpuFrame *frame, + const cairo_rectangle_int_t *rect); + + +G_END_DECLS + diff --git a/gsk/meson.build b/gsk/meson.build index 18f9f88787..049978473a 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -85,6 +85,7 @@ gsk_private_sources = files([ 'gpu/gskgpurenderer.c', 'gpu/gskgpurenderpassop.c', 'gpu/gskgpushaderop.c', + 'gpu/gskgpuscissorop.c', 'gpu/gskgputextureop.c', 'gpu/gskgpuuploadop.c', 'gpu/gsknglrenderer.c',