.. and use them for color-matrix operations.
'vulkan/gskvulkanbuffer.c',
'vulkan/gskvulkanclip.c',
'vulkan/gskvulkancolorpipeline.c',
+ 'vulkan/gskvulkancolormatrixop.c',
'vulkan/gskvulkancolortextpipeline.c',
'vulkan/gskvulkancommandpool.c',
'vulkan/gskvulkancrossfadepipeline.c',
'vulkan/gskvulkanimage.c',
'vulkan/gskvulkanlineargradientpipeline.c',
'vulkan/gskvulkanmemory.c',
+ 'vulkan/gskvulkanoffscreenop.c',
'vulkan/gskvulkanop.c',
'vulkan/gskvulkanpipeline.c',
'vulkan/gskvulkanpushconstants.c',
--- /dev/null
+#include "config.h"
+
+#include "gskvulkancolormatrixopprivate.h"
+
+#include "gskvulkaneffectpipelineprivate.h"
+
+typedef struct _GskVulkanColorMatrixOp GskVulkanColorMatrixOp;
+
+struct _GskVulkanColorMatrixOp
+{
+ GskVulkanOp op;
+
+ GskVulkanImage *image;
+ graphene_matrix_t color_matrix;
+ graphene_vec4_t color_offset;
+ graphene_rect_t rect;
+ graphene_rect_t tex_rect;
+
+ guint32 image_descriptor;
+ guint32 sampler_descriptor;
+ GskVulkanPipeline *pipeline;
+ gsize vertex_offset;
+};
+
+static void
+gsk_vulkan_color_matrix_op_finish (GskVulkanOp *op)
+{
+ GskVulkanColorMatrixOp *self = (GskVulkanColorMatrixOp *) op;
+
+ g_object_unref (self->image);
+}
+
+static void
+gsk_vulkan_color_matrix_op_upload (GskVulkanOp *op,
+ GskVulkanRenderPass *pass,
+ GskVulkanRender *render,
+ GskVulkanUploader *uploader,
+ const graphene_rect_t *clip,
+ const graphene_vec2_t *scale)
+{
+}
+
+static inline gsize
+round_up (gsize number, gsize divisor)
+{
+ return (number + divisor - 1) / divisor * divisor;
+}
+
+static gsize
+gsk_vulkan_color_matrix_op_count_vertex_data (GskVulkanOp *op,
+ gsize n_bytes)
+{
+ GskVulkanColorMatrixOp *self = (GskVulkanColorMatrixOp *) op;
+ gsize vertex_stride;
+
+ vertex_stride = gsk_vulkan_pipeline_get_vertex_stride (self->pipeline);
+ n_bytes = round_up (n_bytes, vertex_stride);
+ self->vertex_offset = n_bytes;
+ n_bytes += vertex_stride;
+ return n_bytes;
+}
+
+static void
+gsk_vulkan_color_matrix_op_collect_vertex_data (GskVulkanOp *op,
+ GskVulkanRenderPass *pass,
+ GskVulkanRender *render,
+ guchar *data)
+{
+ GskVulkanColorMatrixOp *self = (GskVulkanColorMatrixOp *) op;
+
+ gsk_vulkan_effect_pipeline_collect_vertex_data (GSK_VULKAN_EFFECT_PIPELINE (self->pipeline),
+ data + self->vertex_offset,
+ (guint32[2]) {
+ self->image_descriptor,
+ self->sampler_descriptor,
+ },
+ graphene_point_zero (),
+ &self->rect,
+ &self->tex_rect,
+ &self->color_matrix,
+ &self->color_offset);
+}
+
+static void
+gsk_vulkan_color_matrix_op_reserve_descriptor_sets (GskVulkanOp *op,
+ GskVulkanRender *render)
+{
+ GskVulkanColorMatrixOp *self = (GskVulkanColorMatrixOp *) op;
+
+ self->image_descriptor = gsk_vulkan_render_get_image_descriptor (render, self->image);
+ self->sampler_descriptor = gsk_vulkan_render_get_sampler_descriptor (render, GSK_VULKAN_SAMPLER_DEFAULT);
+}
+
+static GskVulkanPipeline *
+gsk_vulkan_color_matrix_op_get_pipeline (GskVulkanOp *op)
+{
+ GskVulkanColorMatrixOp *self = (GskVulkanColorMatrixOp *) op;
+
+ return self->pipeline;
+}
+
+static void
+gsk_vulkan_color_matrix_op_command (GskVulkanOp *op,
+ GskVulkanRender *render,
+ VkPipelineLayout pipeline_layout,
+ VkCommandBuffer command_buffer)
+{
+ GskVulkanColorMatrixOp *self = (GskVulkanColorMatrixOp *) op;
+
+ gsk_vulkan_effect_pipeline_draw (GSK_VULKAN_EFFECT_PIPELINE (self->pipeline),
+ command_buffer,
+ self->vertex_offset / gsk_vulkan_pipeline_get_vertex_stride (self->pipeline),
+ 1);
+}
+
+static const GskVulkanOpClass GSK_VULKAN_COLOR_MATRIX_OP_CLASS = {
+ GSK_VULKAN_OP_SIZE (GskVulkanColorMatrixOp),
+ gsk_vulkan_color_matrix_op_finish,
+ gsk_vulkan_color_matrix_op_upload,
+ gsk_vulkan_color_matrix_op_count_vertex_data,
+ gsk_vulkan_color_matrix_op_collect_vertex_data,
+ gsk_vulkan_color_matrix_op_reserve_descriptor_sets,
+ gsk_vulkan_color_matrix_op_get_pipeline,
+ gsk_vulkan_color_matrix_op_command
+};
+
+gsize
+gsk_vulkan_color_matrix_op_size (void)
+{
+ return GSK_VULKAN_COLOR_MATRIX_OP_CLASS.size;
+}
+
+void
+gsk_vulkan_color_matrix_op_init (GskVulkanOp *op,
+ GskVulkanPipeline *pipeline,
+ GskVulkanImage *image,
+ const graphene_rect_t *rect,
+ const graphene_point_t *offset,
+ const graphene_rect_t *tex_rect,
+ const graphene_matrix_t *color_matrix,
+ const graphene_vec4_t *color_offset)
+{
+ GskVulkanColorMatrixOp *self = (GskVulkanColorMatrixOp *) op;
+
+ gsk_vulkan_op_init (op, &GSK_VULKAN_COLOR_MATRIX_OP_CLASS);
+
+ self->pipeline = pipeline;
+ self->image = g_object_ref (image);
+ graphene_rect_offset_r (rect, offset->x, offset->y, &self->rect);
+ gsk_vulkan_normalize_tex_coords (&self->tex_rect, rect, tex_rect);
+ self->color_matrix = *color_matrix;
+ self->color_offset = *color_offset;
+}
--- /dev/null
+#pragma once
+
+#include "gskvulkanopprivate.h"
+
+G_BEGIN_DECLS
+
+gsize gsk_vulkan_color_matrix_op_size (void) G_GNUC_CONST;
+
+void gsk_vulkan_color_matrix_op_init (GskVulkanOp *op,
+ GskVulkanPipeline *pipeline,
+ GskVulkanImage *image,
+ const graphene_rect_t *rect,
+ const graphene_point_t *offset,
+ const graphene_rect_t *tex_rect,
+ const graphene_matrix_t *color_matrix,
+ const graphene_vec4_t *color_offset);
+
+
+G_END_DECLS
+
--- /dev/null
+#include "config.h"
+
+#include "gskvulkanoffscreenopprivate.h"
+
+#include "gskrendernodeprivate.h"
+
+#include "gdk/gdkvulkancontextprivate.h"
+
+typedef struct _GskVulkanOffscreenOp GskVulkanOffscreenOp;
+
+struct _GskVulkanOffscreenOp
+{
+ GskVulkanOp op;
+
+ GskVulkanImage *image;
+ GskVulkanRenderPass *render_pass;
+};
+
+static void
+gsk_vulkan_offscreen_op_finish (GskVulkanOp *op)
+{
+ GskVulkanOffscreenOp *self = (GskVulkanOffscreenOp *) op;
+
+ g_object_unref (self->image);
+ gsk_vulkan_render_pass_free (self->render_pass);
+}
+
+static void
+gsk_vulkan_offscreen_op_upload (GskVulkanOp *op,
+ GskVulkanRenderPass *pass,
+ GskVulkanRender *render,
+ GskVulkanUploader *uploader,
+ const graphene_rect_t *clip,
+ const graphene_vec2_t *scale)
+{
+ GskVulkanOffscreenOp *self = (GskVulkanOffscreenOp *) op;
+
+ gsk_vulkan_render_pass_upload (self->render_pass, render, uploader);
+}
+
+static gsize
+gsk_vulkan_offscreen_op_count_vertex_data (GskVulkanOp *op,
+ gsize n_bytes)
+{
+ return n_bytes;
+}
+
+static void
+gsk_vulkan_offscreen_op_collect_vertex_data (GskVulkanOp *op,
+ GskVulkanRenderPass *pass,
+ GskVulkanRender *render,
+ guchar *data)
+{
+}
+
+static void
+gsk_vulkan_offscreen_op_reserve_descriptor_sets (GskVulkanOp *op,
+ GskVulkanRender *render)
+{
+ GskVulkanOffscreenOp *self = (GskVulkanOffscreenOp *) op;
+
+ gsk_vulkan_render_pass_reserve_descriptor_sets (self->render_pass, render);
+}
+
+static GskVulkanPipeline *
+gsk_vulkan_offscreen_op_get_pipeline (GskVulkanOp *op)
+{
+ return NULL;
+}
+
+static void
+gsk_vulkan_offscreen_op_command (GskVulkanOp *op,
+ GskVulkanRender *render,
+ VkPipelineLayout pipeline_layout,
+ VkCommandBuffer command_buffer)
+{
+ GskVulkanOffscreenOp *self = (GskVulkanOffscreenOp *) op;
+
+ gsk_vulkan_render_draw_pass (render, self->render_pass, VK_NULL_HANDLE);
+}
+
+static const GskVulkanOpClass GSK_VULKAN_OFFSCREEN_OP_CLASS = {
+ GSK_VULKAN_OP_SIZE (GskVulkanOffscreenOp),
+ gsk_vulkan_offscreen_op_finish,
+ gsk_vulkan_offscreen_op_upload,
+ gsk_vulkan_offscreen_op_count_vertex_data,
+ gsk_vulkan_offscreen_op_collect_vertex_data,
+ gsk_vulkan_offscreen_op_reserve_descriptor_sets,
+ gsk_vulkan_offscreen_op_get_pipeline,
+ gsk_vulkan_offscreen_op_command
+};
+
+gsize
+gsk_vulkan_offscreen_op_size (void)
+{
+ return GSK_VULKAN_OFFSCREEN_OP_CLASS.size;
+}
+
+GskVulkanImage *
+gsk_vulkan_offscreen_op_init (GskVulkanOp *op,
+ GdkVulkanContext *context,
+ GskVulkanRender *render,
+ const graphene_vec2_t *scale,
+ const graphene_rect_t *viewport,
+ VkSemaphore signal_semaphore,
+ GskRenderNode *node)
+{
+ GskVulkanOffscreenOp *self = (GskVulkanOffscreenOp *) op;
+ graphene_rect_t view;
+ cairo_region_t *clip;
+ float scale_x, scale_y;
+
+ scale_x = graphene_vec2_get_x (scale);
+ scale_y = graphene_vec2_get_y (scale);
+ view = GRAPHENE_RECT_INIT (scale_x * viewport->origin.x,
+ scale_y * viewport->origin.y,
+ ceil (scale_x * viewport->size.width),
+ ceil (scale_y * viewport->size.height));
+
+ gsk_vulkan_op_init (op, &GSK_VULKAN_OFFSCREEN_OP_CLASS);
+
+ self->image = gsk_vulkan_image_new_for_offscreen (context,
+ gdk_vulkan_context_get_offscreen_format (context,
+ gsk_render_node_get_preferred_depth (node)),
+ view.size.width, view.size.height);
+
+ clip = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
+ 0, 0,
+ gsk_vulkan_image_get_width (self->image),
+ gsk_vulkan_image_get_height (self->image)
+ });
+
+ self->render_pass = gsk_vulkan_render_pass_new (context,
+ self->image,
+ scale,
+ &view,
+ clip,
+ signal_semaphore);
+
+ cairo_region_destroy (clip);
+
+ gsk_vulkan_render_pass_add (self->render_pass, render, node);
+
+ return self->image;
+}
--- /dev/null
+#pragma once
+
+#include "gskvulkanopprivate.h"
+
+G_BEGIN_DECLS
+
+gsize gsk_vulkan_offscreen_op_size (void) G_GNUC_CONST;
+
+GskVulkanImage * gsk_vulkan_offscreen_op_init (GskVulkanOp *op,
+ GdkVulkanContext *context,
+ GskVulkanRender *render,
+ const graphene_vec2_t *scale,
+ const graphene_rect_t *viewport,
+ VkSemaphore signal_semaphore,
+ GskRenderNode *node);
+
+G_END_DECLS
+
#include "gskvulkanborderpipelineprivate.h"
#include "gskvulkanboxshadowpipelineprivate.h"
#include "gskvulkanclipprivate.h"
+#include "gskvulkancolormatrixopprivate.h"
#include "gskvulkancolorpipelineprivate.h"
#include "gskvulkancolortextpipelineprivate.h"
#include "gskvulkancrossfadepipelineprivate.h"
#include "gskvulkantextpipelineprivate.h"
#include "gskvulkantexturepipelineprivate.h"
#include "gskvulkanimageprivate.h"
+#include "gskvulkanoffscreenopprivate.h"
#include "gskvulkanpushconstantsprivate.h"
#include "gskvulkanscissoropprivate.h"
#include "gskvulkantextureopprivate.h"
GSK_VULKAN_OP_LINEAR_GRADIENT,
GSK_VULKAN_OP_OPACITY,
GSK_VULKAN_OP_BLUR,
- GSK_VULKAN_OP_COLOR_MATRIX,
GSK_VULKAN_OP_BORDER,
GSK_VULKAN_OP_INSET_SHADOW,
GSK_VULKAN_OP_OUTSET_SHADOW,
self->render_pass);
}
+static GskVulkanImage *
+gsk_vulkan_render_pass_get_node_as_image (GskVulkanRenderPass *self,
+ GskVulkanRender *render,
+ const GskVulkanParseState *state,
+ GskRenderNode *node,
+ graphene_rect_t *tex_bounds)
+{
+ VkSemaphore semaphore;
+ GskVulkanImage *result;
+
+ switch ((guint) gsk_render_node_get_node_type (node))
+ {
+ case GSK_TEXTURE_NODE:
+ {
+ GdkTexture *texture = gsk_texture_node_get_texture (node);
+ GskVulkanRenderer *renderer = GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render));
+ result = gsk_vulkan_renderer_get_texture_image (renderer, texture);
+ if (result == NULL)
+ {
+ result = gsk_vulkan_upload_op_init_texture (gsk_vulkan_render_pass_alloc_op (self, gsk_vulkan_upload_op_size ()),
+ self->vulkan,
+ texture);
+ gsk_vulkan_renderer_add_texture_image (renderer, texture, result);
+ }
+
+ *tex_bounds = node->bounds;
+ return result;
+ }
+
+ default:
+ {
+ graphene_rect_t clipped;
+
+ graphene_rect_offset_r (&state->clip.rect.bounds, - state->offset.x, - state->offset.y, &clipped);
+ graphene_rect_intersection (&clipped, &node->bounds, &clipped);
+
+ if (clipped.size.width == 0 || clipped.size.height == 0)
+ return NULL;
+
+ /* assuming the unclipped bounds should go to texture coordinates 0..1,
+ * calculate the coordinates for the clipped texture size
+ */
+ *tex_bounds = clipped;
+
+ vkCreateSemaphore (gdk_vulkan_context_get_device (self->vulkan),
+ &(VkSemaphoreCreateInfo) {
+ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+ NULL,
+ 0
+ },
+ NULL,
+ &semaphore);
+ g_array_append_val (self->wait_semaphores, semaphore);
+
+ result = gsk_vulkan_offscreen_op_init (gsk_vulkan_render_pass_alloc_op (self, gsk_vulkan_offscreen_op_size ()),
+ self->vulkan,
+ render,
+ &state->scale,
+ &clipped,
+ semaphore,
+ node);
+
+ return result;
+ }
+ }
+}
+
static void
gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
GskVulkanRender *render,
GskRenderNode *node)
{
GskVulkanPipelineType pipeline_type;
- GskVulkanOpRender op = {
- .type = GSK_VULKAN_OP_COLOR_MATRIX,
- .node = node,
- .offset = state->offset,
- };
+ GskVulkanImage *image;
+ graphene_rect_t tex_rect;
+
+ image = gsk_vulkan_render_pass_get_node_as_image (self,
+ render,
+ state,
+ gsk_color_matrix_node_get_child (node),
+ &tex_rect);
+ if (image == NULL)
+ return TRUE;
if (gsk_vulkan_clip_contains_rect (&state->clip, &state->offset, &node->bounds))
pipeline_type = GSK_VULKAN_PIPELINE_COLOR_MATRIX;
else
pipeline_type = GSK_VULKAN_PIPELINE_COLOR_MATRIX_CLIP_ROUNDED;
- op.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
- gsk_vulkan_render_pass_add_op (self, (GskVulkanOp *) &op);
+ gsk_vulkan_color_matrix_op_init (gsk_vulkan_render_pass_alloc_op (self, gsk_vulkan_color_matrix_op_size ()),
+ gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type),
+ image,
+ &node->bounds,
+ &state->offset,
+ &tex_rect,
+ gsk_color_matrix_node_get_color_matrix (node),
+ gsk_color_matrix_node_get_color_offset (node));
return TRUE;
}
}
break;
- case GSK_VULKAN_OP_COLOR_MATRIX:
- {
- GskRenderNode *child = gsk_color_matrix_node_get_child (op->render.node);
- graphene_rect_t tex_bounds;
-
- op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
- render,
- uploader,
- child,
- scale,
- clip,
- &op->render.offset,
- &tex_bounds);
- gsk_vulkan_normalize_tex_coords (&op->render.source_rect, &op->render.node->bounds, &tex_bounds);
- }
- break;
-
case GSK_VULKAN_OP_CROSS_FADE:
{
GskRenderNode *start = gsk_cross_fade_node_get_start_child (op->render.node);
case GSK_VULKAN_OP_COLOR:
case GSK_VULKAN_OP_LINEAR_GRADIENT:
case GSK_VULKAN_OP_OPACITY:
- case GSK_VULKAN_OP_COLOR_MATRIX:
case GSK_VULKAN_OP_BLUR:
case GSK_VULKAN_OP_BORDER:
case GSK_VULKAN_OP_INSET_SHADOW:
gsk_blur_node_get_radius (op->render.node));
break;
- case GSK_VULKAN_OP_COLOR_MATRIX:
- gsk_vulkan_effect_pipeline_collect_vertex_data (GSK_VULKAN_EFFECT_PIPELINE (op->render.pipeline),
- data + op->render.vertex_offset,
- op->render.image_descriptor,
- &op->render.offset,
- &op->render.node->bounds,
- &op->render.source_rect,
- gsk_color_matrix_node_get_color_matrix (op->render.node),
- gsk_color_matrix_node_get_color_offset (op->render.node));
- break;
-
case GSK_VULKAN_OP_BORDER:
gsk_vulkan_border_pipeline_collect_vertex_data (GSK_VULKAN_BORDER_PIPELINE (op->render.pipeline),
data + op->render.vertex_offset,
case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP:
case GSK_VULKAN_OP_OPACITY:
case GSK_VULKAN_OP_BLUR:
- case GSK_VULKAN_OP_COLOR_MATRIX:
if (op->render.source)
{
op->render.image_descriptor[0] = gsk_vulkan_render_get_image_descriptor (render, op->render.source);
case GSK_VULKAN_OP_COLOR:
case GSK_VULKAN_OP_LINEAR_GRADIENT:
case GSK_VULKAN_OP_OPACITY:
- case GSK_VULKAN_OP_COLOR_MATRIX:
case GSK_VULKAN_OP_BLUR:
case GSK_VULKAN_OP_BORDER:
case GSK_VULKAN_OP_INSET_SHADOW:
break;
case GSK_VULKAN_OP_OPACITY:
- case GSK_VULKAN_OP_COLOR_MATRIX:
if (!op->render.source)
break;
gsk_vulkan_effect_pipeline_draw (GSK_VULKAN_EFFECT_PIPELINE (op->render.pipeline),